diff --git a/api/.nvmrc b/api/.nvmrc index 72773deb8..23670da19 100644 --- a/api/.nvmrc +++ b/api/.nvmrc @@ -1 +1 @@ -11.4.0 +18.20.4 \ No newline at end of file diff --git a/api/Dockerfile.development b/api/Dockerfile.development index 0b160524c..b02301952 100644 --- a/api/Dockerfile.development +++ b/api/Dockerfile.development @@ -1,12 +1,10 @@ -FROM node:11.4.0 +FROM node:18-bullseye -# force update sources.list (sketchy, but good for now until we update container) -RUN echo "deb http://archive.ubuntu.com/ubuntu xenial main universe" > /etc/apt/sources.list \ - && echo "deb http://archive.ubuntu.com/ubuntu xenial-updates main universe" >> /etc/apt/sources.list \ - && echo "deb http://security.ubuntu.com/ubuntu xenial-security main universe" >> /etc/apt/sources.list - -# TODO: fix apt-get update (upgrade node image, lol) -RUN apt-get update -y && apt-get install --allow-unauthenticated -y gdal-bin +# Update the package list and install gdal-bin and its dependencies +RUN apt-get update -y && \ + apt-get install -y --no-install-recommends \ + gdal-bin \ + && apt-get clean && rm -rf /var/lib/apt/lists/* WORKDIR /app COPY package.json . diff --git a/api/Dockerfile.jobs b/api/Dockerfile.jobs index 5aef9219b..c178de932 100644 --- a/api/Dockerfile.jobs +++ b/api/Dockerfile.jobs @@ -1,4 +1,4 @@ -FROM node:11.4.0 as build-stage +FROM node:18-bullseye as build-stage WORKDIR /app COPY package.json . @@ -7,7 +7,7 @@ RUN npm install COPY . /app RUN /app/node_modules/.bin/tsc --build /app/tsconfig.json -FROM keymetrics/pm2:12-alpine +FROM keymetrics/pm2:18-alpine LABEL maintainer "Dan Melton " WORKDIR /app diff --git a/api/Dockerfile.production b/api/Dockerfile.production index 6146c38af..439f30b76 100644 --- a/api/Dockerfile.production +++ b/api/Dockerfile.production @@ -1,4 +1,4 @@ -FROM node:11.4.0 as build-stage +FROM node:18-bullseye as build-stage WORKDIR /app COPY package.json . @@ -7,7 +7,7 @@ RUN npm install COPY . /app RUN /app/node_modules/.bin/tsc --build /app/tsconfig.json -FROM keymetrics/pm2:12-alpine +FROM keymetrics/pm2:18-alpine LABEL maintainer "Dan Melton " WORKDIR /app diff --git a/api/Dockerfile.qa b/api/Dockerfile.qa index f133a5fa0..b0c012f88 100644 --- a/api/Dockerfile.qa +++ b/api/Dockerfile.qa @@ -1,4 +1,4 @@ -FROM node:11.4.0 +FROM node:18-bullseye LABEL maintainer "Dan Melton " RUN apt-get update -y && apt-get install -y gdal-bin diff --git a/api/app.ts b/api/app.ts index bc2bc301f..59854edef 100644 --- a/api/app.ts +++ b/api/app.ts @@ -4,8 +4,8 @@ import * as cors from 'cors'; import * as fileUpload from 'express-fileupload'; import { setupRoutes } from './routes'; import db from './models/db'; -import bugsnag from '@bugsnag/js'; -import bugsnagExpress from '@bugsnag/plugin-express'; +import Bugsnag from '@bugsnag/js'; +import BugsnagPluginExpress from '@bugsnag/plugin-express'; /*** corsOptions set to return all Access-Control-Allow-Origin headers with requesting domain @@ -14,10 +14,10 @@ import bugsnagExpress from '@bugsnag/plugin-express'; https://expressjs.com/en/resources/middleware/cors.html#configuring-cors-w-dynamic-origin ***/ const corsOptions = { - origin: function (origin, callback) { - callback(null, true); - }, - credentials: true + origin: function (origin, callback) { + callback(null, true); + }, + credentials: true, }; (async () => { @@ -25,25 +25,27 @@ const corsOptions = { const app: express.Express = express(); if (process.env.NODE_ENV === 'production') { - const bugsnagClient = bugsnag({ + const bugsnagClient = Bugsnag.start({ apiKey: process.env.BUG_SNAG_API_KEY, - releaseStage: process.env.APP_ENV + releaseStage: process.env.APP_ENV, + plugins: [BugsnagPluginExpress], }); - bugsnagClient.use(bugsnagExpress); const middleware = bugsnagClient.getPlugin('express'); app.use(middleware.requestHandler); app.use(middleware.errorHandler); } app.use(logger('dev')); - app.use(fileUpload({ - createParentPath: true, - limits: { - fileSize: 10 * 1024 * 1024 * 1024 // 10MB max file(s) size - }, - useTempFiles : true, - tempFileDir : '/app/uploads', - debug: false // flip to true for local testing - })); + app.use( + fileUpload({ + createParentPath: true, + limits: { + fileSize: 10 * 1024 * 1024 * 1024, // 10MB max file(s) size + }, + useTempFiles: true, + tempFileDir: '/app/uploads', + debug: false, // flip to true for local testing + }) + ); app.use(cors(corsOptions)); app.options('*', cors(corsOptions)); diff --git a/api/controller/activities.ts b/api/controller/activities.ts index 0b44a898e..c2f370fbe 100644 --- a/api/controller/activities.ts +++ b/api/controller/activities.ts @@ -1,9 +1,6 @@ import { Response } from 'express'; import { checkCurrentUser, IRequest } from '../routes/helpers'; -import { - getActivityAttachmentAsync, - getAllActivityRecordsAsync, -} from '../services/activityService'; +import { getActivityAttachmentAsync, getAllActivityRecordsAsync } from '../services/activityService'; import { bugsnagClient } from '../services/bugsnagService'; import { IsNumber } from 'class-validator'; import { checkDto } from './helpers'; @@ -13,14 +10,17 @@ export async function getActivities(request: IRequest, response: Response, next: checkCurrentUser(request); request.body.currentUserId = request.currentUser.id; - const hostName = (request.hostname || '').includes('openelectionsportland') ? 'openelectionsportland.org' : 'smalldonorelections.org'; + const hostName = (request.hostname || '').includes('openelectionsportland') + ? 'openelectionsportland.org' + : 'smalldonorelections.org'; const records = await getAllActivityRecordsAsync(request.body, hostName); + console.log({ records }); response.status(200).json(records); } catch (err) { if (process.env.NODE_ENV === 'production' && err.message !== 'No token set') { bugsnagClient.notify(err); } - return response.status(422).json({message: err.message}); + return response.status(422).json({ message: err.message }); } } @@ -37,10 +37,12 @@ export async function getActivityAttachment(request: IRequest, response: Respons checkCurrentUser(request); const getActivityFileDto = Object.assign(new GetActivityAttachmentDto(), { activityId: parseInt(request.params.id), - currentUserId: request.currentUser.id + currentUserId: request.currentUser.id, }); await checkDto(getActivityFileDto); - const hostName = (request.hostname || '').includes('openelectionsportland') ? 'openelectionsportland.org' : 'smalldonorelections.org'; + const hostName = (request.hostname || '').includes('openelectionsportland') + ? 'openelectionsportland.org' + : 'smalldonorelections.org'; const data = await getActivityAttachmentAsync(getActivityFileDto); response.set('Content-Type', data.contentType); if (data.fileName) { @@ -49,6 +51,6 @@ export async function getActivityAttachment(request: IRequest, response: Respons response.setHeader('Content-Transfer-Encoding', 'binary'); return response.status(200).send(data.buffer); } catch (err) { - return response.status(422).json({message: err.message}); + return response.status(422).json({ message: err.message }); } } diff --git a/api/controller/expenditures.ts b/api/controller/expenditures.ts index abea3c2c6..871900641 100644 --- a/api/controller/expenditures.ts +++ b/api/controller/expenditures.ts @@ -6,7 +6,9 @@ import { IGetExpenditureAttrs, getExpendituresAsync, IUpdateExpenditureAttrs, - updateExpenditureAsync, createExpenditureCommentAsync, getExpenditureByIdAsync + updateExpenditureAsync, + createExpenditureCommentAsync, + getExpenditureByIdAsync, } from '../services/expenditureService'; import { checkCurrentUser, IRequest } from '../routes/helpers'; import { checkDto } from './helpers'; @@ -15,7 +17,7 @@ import { ExpenditureType, ExpenditureSubType, PayeeType, - PurposeType + PurposeType, } from '../models/entity/Expenditure'; import { PaymentMethod } from '../models/entity/Expenditure'; import { bugsnagClient } from '../services/bugsnagService'; @@ -109,7 +111,7 @@ export async function addExpenditure(request: IRequest, response: Response, next checkCurrentUser(request); const addExpenditureDto = Object.assign(new AddExpenditureDto(), { ...request.body, - currentUserId: request.currentUser.id + currentUserId: request.currentUser.id, }); await checkDto(addExpenditureDto); const expenditure = await addExpenditureAsync(addExpenditureDto); @@ -118,7 +120,7 @@ export async function addExpenditure(request: IRequest, response: Response, next if (process.env.NODE_ENV === 'production' && err.message !== 'No token set') { bugsnagClient.notify(err); } - return response.status(422).json({message: err.message}); + return response.status(422).json({ message: err.message }); } } @@ -163,7 +165,7 @@ export async function getExpenditures(request: IRequest, response: Response, nex checkCurrentUser(request); const getExpendituresDto = Object.assign(new GetExpendituresDto(), { ...request.body, - currentUserId: request.currentUser.id + currentUserId: request.currentUser.id, }); await checkDto(getExpendituresDto); @@ -181,7 +183,7 @@ export async function getExpenditures(request: IRequest, response: Response, nex if (process.env.NODE_ENV === 'production' && err.message !== 'No token set') { bugsnagClient.notify(err); } - return response.status(422).json({message: err.message}); + return response.status(422).json({ message: err.message }); } } @@ -270,7 +272,7 @@ export async function updateExpenditure(request: IRequest, response: Response, n checkCurrentUser(request); const updateExpenditureDto = Object.assign(new UpdateExpenditureDto(), { ...request.body, - currentUserId: request.currentUser.id + currentUserId: request.currentUser.id, }); await checkDto(updateExpenditureDto); const expenditure = await updateExpenditureAsync(updateExpenditureDto); @@ -280,12 +282,11 @@ export async function updateExpenditure(request: IRequest, response: Response, n if (process.env.NODE_ENV === 'production' && err.message !== 'No token set') { bugsnagClient.notify(err); } - return response.status(422).json({message: err.message}); + return response.status(422).json({ message: err.message }); } } export class ExpenditureCommentDto { - currentUserId: number; @IsNumber() @@ -296,7 +297,6 @@ export class ExpenditureCommentDto { @IsOptional() attachmentPath: UploadedFile; - } export async function createExpenditureComment(request: IRequest, response: Response, next: Function) { @@ -305,7 +305,7 @@ export async function createExpenditureComment(request: IRequest, response: Resp const attrs: any = { expenditureId: parseInt(request.params.id), currentUserId: request.currentUser.id, - comment: request.body.comment + comment: request.body.comment, }; let file; if (request.files && request.files.attachment) { @@ -323,13 +323,11 @@ export async function createExpenditureComment(request: IRequest, response: Resp if (process.env.NODE_ENV === 'production' && err.message !== 'No token set') { bugsnagClient.notify(err); } - return response.status(422).json({message: err.message}); + return response.status(422).json({ message: err.message }); } } - export class GetExpenditureByIdDto { - @IsNumber() expenditureId: number; @@ -342,7 +340,7 @@ export async function getExpenditureById(request: IRequest, response: Response, checkCurrentUser(request); const getExpenditureByIdDto = Object.assign(new GetExpenditureByIdDto(), { expenditureId: parseInt(request.params.id), - currentUserId: request.currentUser.id + currentUserId: request.currentUser.id, }); await checkDto(getExpenditureByIdDto); const expenditure = await getExpenditureByIdAsync(getExpenditureByIdDto); diff --git a/api/controller/helpers.ts b/api/controller/helpers.ts index 290f2e172..be76aba53 100644 --- a/api/controller/helpers.ts +++ b/api/controller/helpers.ts @@ -1,7 +1,7 @@ import { validate } from 'class-validator'; import { FileArray } from 'express-fileupload'; import { createReadStream } from 'fs'; -import * as parse from 'csv-parse/lib'; +import { parse } from 'csv-parse'; import { IAddContributionAttrs } from '../services/contributionService'; import { convertToTimeZone } from 'date-fns-timezone'; import { @@ -14,7 +14,6 @@ import { } from '../models/entity/Contribution'; export async function checkDto(dto): Promise { - console.log('from checkDto'); const validationErrors = await validate(dto, { validationError: { target: false } }); if (validationErrors.length) { throw new Error( @@ -28,7 +27,6 @@ export async function checkDto(dto): Promise { } export async function checkDtoWithEnums(dto): Promise { - console.log('from checkDtoWithEnums'); const validationErrors = await validate(dto, { validationError: { target: false } }); if (validationErrors.length) { throw new Error( @@ -203,11 +201,9 @@ export async function parseBulkCsvData(body: IBulkUploadBody, file: FileArray): .pipe(parse({ delimiter: ',', columns: true })) .on('data', (row: IBulkUploadCSV) => { if (runColumnCheck) { - console.log('header row start'); const rowTitleErrors = []; Object.keys(row || {}).forEach((rowItem) => { if (!acceptableColumnTitles.includes(rowItem)) { - console.log(`${rowItem} should not be here.`); rowTitleErrors.push(rowItem); } }); @@ -218,7 +214,6 @@ export async function parseBulkCsvData(body: IBulkUploadBody, file: FileArray): } reject(new Error(`${rowErrorString}. Columns should be: ${acceptableColumnTitles.join(', ')}`)); } - console.log('header row end'); runColumnCheck = false; } const newRow: Partial = {}; diff --git a/api/jest.config.js b/api/jest.config.js new file mode 100644 index 000000000..35a91b834 --- /dev/null +++ b/api/jest.config.js @@ -0,0 +1,15 @@ +module.exports = { + preset: 'ts-jest', + testEnvironment: 'node', + testMatch: ['**/test/**/*.spec.ts'], + moduleFileExtensions: ['ts', 'js'], + transform: { + '^.+\\.ts$': [ + 'ts-jest', + { + tsconfig: 'tsconfig.json', + }, + ], + }, + maxWorkers: 1, +}; diff --git a/api/jobs/helpers/db.ts b/api/jobs/helpers/db.ts index 2f0cfb13e..067f736c5 100644 --- a/api/jobs/helpers/db.ts +++ b/api/jobs/helpers/db.ts @@ -1,25 +1,29 @@ import 'reflect-metadata'; -import { createConnection, Connection, getConnection } from 'typeorm'; +import { DataSource } from 'typeorm'; +import ORMConfig from '../../models/ormconfig'; -export default async (): Promise => { - try { - const connection: Connection = await createConnection({ - type: 'postgres', - host: process.env.DB_HOST, - port: parseInt(process.env.DB_PORT), - username: process.env.DB_USERNAME, - password: process.env.DB_PASSWORD, - database: process.env.DB_NAME, - entities: [ - '/app/build/models/entity/*.js' - ], - synchronize: false, - logging: false - }); +export default async (): Promise => { + if (!global.oaeJobConnection || !global.oaeJobConnection.isConnected) { + try { + // const connection: Connection = await createConnection(ORMConfig); + const jobOrmConfig = { + ...ORMConfig, + entities: ['/app/build/models/entity/*.js'], + synchronize: false, + migrations: undefined, + }; - return connection; - } catch (e) { - return getConnection('default'); - } + const connection: DataSource = new DataSource(jobOrmConfig); + global.oaeConnection = await connection.initialize(); + // This is safe to do in prod and dev because it tracks what migrations have ran already in the db. + if (process.env.NODE_ENV === 'production') { + // If migrations are needed, use this code: + // await connection.runMigrations(); + } + } catch (error) { + console.log('Using existing default db connection.'); + } + } + return global.oaeJobConnection; }; diff --git a/api/jobs/processors/cronNightlyEmailProcessor.ts b/api/jobs/processors/cronNightlyEmailProcessor.ts index 88c34c804..f65396125 100644 --- a/api/jobs/processors/cronNightlyEmailProcessor.ts +++ b/api/jobs/processors/cronNightlyEmailProcessor.ts @@ -1,11 +1,10 @@ import db from '../../models/db'; -import { getConnection } from 'typeorm'; import { Campaign } from '../../models/entity/Campaign'; import { sendNightlyEmailQueue } from '../queues'; export default async (job: { data: any }): Promise => { - await db(); - const campaignRepository = getConnection('default').getRepository('Campaign'); + const dataSource = await db(); + const campaignRepository = dataSource.getRepository('Campaign'); const campaigns = (await campaignRepository.find()) as Campaign[]; const promises = []; campaigns.forEach((campaign: Campaign): void => { diff --git a/api/jobs/queues/requeueAllDs.ts b/api/jobs/queues/requeueAllDs.ts index b4c224329..769095f35 100644 --- a/api/jobs/queues/requeueAllDs.ts +++ b/api/jobs/queues/requeueAllDs.ts @@ -1,15 +1,14 @@ import db from '../../models/db'; -import { getConnection } from 'typeorm'; import { Contribution } from '../../models/entity/Contribution'; import { dataScienceResultQueue } from './index'; export async function requeueDataScienceJobs() { - await db(); - const rep = getConnection().getRepository('Contribution'); + const dataSource = await db(); + const rep = dataSource.getRepository('Contribution'); const contr = await rep.find(); const promises = []; - contr.forEach( (contr: Contribution) => { - dataScienceResultQueue.add({id: contr.id}); + contr.forEach((contr: Contribution) => { + dataScienceResultQueue.add({ id: contr.id }); console.log(`Queued Datascience job for Contribution ${contr.id}`); }); await Promise.all(promises); diff --git a/api/models/db.ts b/api/models/db.ts index bb42711e3..630f26f92 100644 --- a/api/models/db.ts +++ b/api/models/db.ts @@ -1,18 +1,23 @@ import 'reflect-metadata'; -import { createConnection, Connection, getConnectionManager } from 'typeorm'; +import { DataSource } from 'typeorm'; import ORMConfig from './ormconfig'; -export default async (): Promise => { - try { - const connection: Connection = await createConnection(ORMConfig); - // This is safe to do in prod and dev because it tracks what migrations have ran already in the db. - if (process.env.NODE_ENV === 'production') { - // If migrations are needed, use this code: - // await connection.runMigrations(); + +export default async function db(): Promise { + if (!global.oaeConnection || !global.oaeConnection.isConnected) { + try { + // const connection: Connection = await createConnection(ORMConfig); + + const connection: DataSource = new DataSource(ORMConfig); + global.oaeConnection = await connection.initialize(); + + // This is safe to do in prod and dev because it tracks what migrations have ran already in the db. + if (process.env.NODE_ENV === 'production') { + // If migrations are needed, use this code: + // await connection.runMigrations(); + } + } catch (error) { + console.log('Using existing default db connection.'); } - return connection; - } catch (error) { - console.log('Using existing default db connection.'); - const existingConnection = getConnectionManager().get('default'); - return existingConnection; } -}; + return global.oaeConnection; +} diff --git a/api/models/entity/Activity.ts b/api/models/entity/Activity.ts index 3c03c5eb2..919f4e88a 100644 --- a/api/models/entity/Activity.ts +++ b/api/models/entity/Activity.ts @@ -6,15 +6,15 @@ import { BeforeInsert, BeforeUpdate, CreateDateColumn, - getConnection, - Between + Between, } from 'typeorm'; -import {Government} from './Government'; -import {Campaign} from './Campaign'; -import {User} from './User'; -import {IsDefined, validate, ValidationError} from 'class-validator'; -import {Contribution} from './Contribution'; -import {Expenditure} from './Expenditure'; +import { Government } from './Government'; +import { Campaign } from './Campaign'; +import { User } from './User'; +import { IsDefined, validate, ValidationError } from 'class-validator'; +import { Contribution } from './Contribution'; +import { Expenditure } from './Expenditure'; +import db from '../db'; export enum ActivityTypeEnum { USER = 'user', @@ -44,14 +44,14 @@ export class Activity { @Column({ type: 'enum', - enum: ActivityTypeEnum + enum: ActivityTypeEnum, }) @IsDefined() activityType: ActivityTypeEnum; @Column({ nullable: true, - default: false + default: false, }) notify: boolean; @@ -60,19 +60,19 @@ export class Activity { }) attachmentPath: string; - @ManyToOne(type => Government, government => government.activities, {eager: true}) + @ManyToOne((type) => Government, (government) => government.activities, { eager: true }) government: Government; - @ManyToOne(type => Campaign, campaign => campaign.activities, {eager: true}) + @ManyToOne((type) => Campaign, (campaign) => campaign.activities, { eager: true }) campaign: Campaign; - @ManyToOne(type => User, user => user.activities, {eager: true}) + @ManyToOne((type) => User, (user) => user.activities, { eager: true }) user: User; - @ManyToOne(type => Contribution, contribution => contribution.activities, {eager: true}) + @ManyToOne((type) => Contribution, (contribution) => contribution.activities, { eager: true }) contribution: Contribution; - @ManyToOne(type => Expenditure, expenditure => expenditure.activities, {eager: true}) + @ManyToOne((type) => Expenditure, (expenditure) => expenditure.activities, { eager: true }) expenditure: Expenditure; public errors: ValidationError[]; @@ -105,14 +105,14 @@ export class Activity { if (!u) { const error = new ValidationError(); error.property = 'userId'; - error.constraints = {isDefined: 'userId should not be null or undefined'}; + error.constraints = { isDefined: 'userId should not be null or undefined' }; this.errors.push(error); } } } export interface IActivityResults { - data: IActivityResult[] + data: IActivityResult[]; perPage: number; page: number; total: number; @@ -128,25 +128,32 @@ export interface IActivityResult { attachmentPath?: string; } -export async function getActivityByGovernmentAsync(governmentId, perPage, page: number, hostName: string): Promise { - const activityRepository = getConnection('default').getRepository('Activity'); +export async function getActivityByGovernmentAsync( + governmentId, + perPage, + page: number, + hostName: string +): Promise { + const dataSource = await db(); + const activityRepository = dataSource.getRepository('Activity'); const total = await activityRepository .createQueryBuilder('activity') .select( 'activity.id, "activity"."userId", activity.notes, "activity"."campaignId", "activity"."activityId", "activity"."activityType", "activity"."createdAt", "activity"."attachmentPath"' ) - .andWhere('"activity"."governmentId" = :governmentId', {governmentId: governmentId}) + .andWhere('"activity"."governmentId" = :governmentId', { governmentId: governmentId }) .getCount(); let data = (await activityRepository .createQueryBuilder('activity') .select( 'activity.id, "activity"."userId", activity.notes, "activity"."campaignId", "activity"."activityId", "activity"."activityType", "activity"."createdAt"' ) - .andWhere('"activity"."governmentId" = :governmentId', {governmentId: governmentId}) + .andWhere('"activity"."governmentId" = :governmentId', { governmentId: governmentId }) .orderBy('"activity"."createdAt"', 'DESC') .limit(perPage) .offset(perPage * page) - .getRawMany() as IActivityResult[]); + .getRawMany()) as IActivityResult[]; + data = data.map((item: IActivityResult) => { if (item.attachmentPath) { if (process.env.APP_ENV === 'staging') { @@ -163,25 +170,31 @@ export async function getActivityByGovernmentAsync(governmentId, perPage, page: data, total, perPage, - page + page, }; } -export async function getActivityByCampaignAsync(campaignId, perPage, page: number, hostName: string): Promise { - const activityRepository = getConnection('default').getRepository('Activity'); +export async function getActivityByCampaignAsync( + campaignId, + perPage, + page: number, + hostName: string +): Promise { + const dataSource = await db(); + const activityRepository = dataSource.getRepository('Activity'); const total = await activityRepository .createQueryBuilder('activity') .select( 'activity.id, "activity"."userId", activity.notes, "activity"."campaignId", "activity"."activityId", "activity"."activityType", "activity"."createdAt", "activity"."attachmentPath"' ) - .andWhere('"activity"."campaignId" = :campaignId', {campaignId}) + .andWhere('"activity"."campaignId" = :campaignId', { campaignId }) .getCount(); let data = (await activityRepository .createQueryBuilder('activity') .select( 'activity.id, "activity"."userId", activity.notes, "activity"."campaignId", "activity"."activityId", "activity"."activityType", "activity"."createdAt", "activity"."attachmentPath"' ) - .andWhere('"activity"."campaignId" = :campaignId', {campaignId}) + .andWhere('"activity"."campaignId" = :campaignId', { campaignId }) .orderBy('"activity"."createdAt"', 'DESC') .limit(perPage) .offset(perPage * page) @@ -202,72 +215,94 @@ export async function getActivityByCampaignAsync(campaignId, perPage, page: numb data, total, perPage, - page + page, }; } - export interface IShortActivityResult { notes: string; activityId: number; activityType: ActivityTypeEnum; } -export async function getActivityByCampaignByTimeAsync(campaignId: number, from, to: Date): Promise { - const activityRepository = getConnection('default').getRepository('Activity'); - return (await activityRepository - .find({ - select: ['notes', 'activityId', 'activityType', 'createdAt'], - where: { - campaign: { - id: campaignId - }, - createdAt: Between(from, to), - notify: true, +export async function getActivityByCampaignByTimeAsync( + campaignId: number, + from, + to: Date +): Promise { + const dataSource = await db(); + const activityRepository = dataSource.getRepository('Activity'); + return (await activityRepository.find({ + select: ['notes', 'activityId', 'activityType', 'createdAt'], + where: { + campaign: { + id: campaignId, }, - order: { - createdAt: 'DESC' - } - })) as IShortActivityResult[]; + createdAt: Between(from, to), + notify: true, + }, + order: { + createdAt: 'DESC', + }, + })) as IShortActivityResult[]; } export async function getActivityByUserAsync(userId, perPage, page: number): Promise { - const activityRepository = getConnection('default').getRepository('Activity'); - const total = await activityRepository.createQueryBuilder('activity') - .select('activity.id, "activity"."userId", activity.notes, "activity"."campaignId", "activity"."activityId", "activity"."activityType", "activity"."createdAt", "activity"."attachmentPath"') - .andWhere('"activity"."userId" = :userId', {userId}) + const dataSource = await db(); + const activityRepository = dataSource.getRepository('Activity'); + const total = await activityRepository + .createQueryBuilder('activity') + .select( + 'activity.id, "activity"."userId", activity.notes, "activity"."campaignId", "activity"."activityId", "activity"."activityType", "activity"."createdAt", "activity"."attachmentPath"' + ) + .andWhere('"activity"."userId" = :userId', { userId }) .getCount(); - const data = await activityRepository.createQueryBuilder('activity') - .select('activity.id, "activity"."userId", activity.notes, "activity"."campaignId", "activity"."activityId", "activity"."activityType", "activity"."createdAt", "activity"."attachmentPath"') - .andWhere('"activity"."userId" = :userId', {userId}) + const data = (await activityRepository + .createQueryBuilder('activity') + .select( + 'activity.id, "activity"."userId", activity.notes, "activity"."campaignId", "activity"."activityId", "activity"."activityType", "activity"."createdAt", "activity"."attachmentPath"' + ) + .andWhere('"activity"."userId" = :userId', { userId }) .orderBy('"activity"."createdAt"', 'DESC') .limit(perPage) .offset(perPage * page) - .getRawMany() as IActivityResult[]; + .getRawMany()) as IActivityResult[]; return { data, total, perPage, - page + page, }; } -export async function getActivityByContributionAsync(contributionId, perPage, page: number, hostName: string): Promise { - const activityRepository = getConnection('default').getRepository('Activity'); - const total = await activityRepository.createQueryBuilder('activity') - .select('activity.id, "activity"."userId", activity.notes, "activity"."campaignId", "activity"."activityId", "activity"."activityType", "activity"."createdAt", "activity"."attachmentPath"') - .andWhere('"activity"."activityId" = :contributionId', {contributionId}) +export async function getActivityByContributionAsync( + contributionId, + perPage, + page: number, + hostName: string +): Promise { + const dataSource = await db(); + const activityRepository = dataSource.getRepository('Activity'); + const total = await activityRepository + .createQueryBuilder('activity') + .select( + 'activity.id, "activity"."userId", activity.notes, "activity"."campaignId", "activity"."activityId", "activity"."activityType", "activity"."createdAt", "activity"."attachmentPath"' + ) + .andWhere('"activity"."activityId" = :contributionId', { contributionId }) .andWhere('("activity"."activityType" = :activityType1 OR "activity"."activityType" = :activityType2)', { activityType1: ActivityTypeEnum.CONTRIBUTION, - activityType2: ActivityTypeEnum.COMMENT_CONTR + activityType2: ActivityTypeEnum.COMMENT_CONTR, }) .getCount(); - let data = (await activityRepository.createQueryBuilder('activity') - .select('activity.id, "activity"."userId", activity.notes, "activity"."campaignId", "activity"."activityId", "activity"."activityType", "activity"."createdAt", "activity"."attachmentPath"') - .andWhere('"activity"."activityId" = :contributionId', {contributionId}) + let data = (await activityRepository + .createQueryBuilder('activity') + .select( + 'activity.id, "activity"."userId", activity.notes, "activity"."campaignId", "activity"."activityId", "activity"."activityType", "activity"."createdAt", "activity"."attachmentPath"' + ) + .andWhere('"activity"."activityId" = :contributionId', { contributionId }) .andWhere('("activity"."activityType" = :activityType1 OR "activity"."activityType" = :activityType2)', { activityType1: ActivityTypeEnum.CONTRIBUTION, - activityType2: ActivityTypeEnum.COMMENT_CONTR + activityType2: ActivityTypeEnum.COMMENT_CONTR, }) .orderBy('"activity"."createdAt"', 'DESC') .limit(perPage) @@ -289,29 +324,41 @@ export async function getActivityByContributionAsync(contributionId, perPage, pa data, total, perPage, - page + page, }; } -export async function getActivityByExpenditureAsync(expenditureId, perPage, page: number, hostName: string): Promise { - const activityRepository = getConnection('default').getRepository('Activity'); - let data = await activityRepository.createQueryBuilder('activity') - .select('activity.id, "activity"."userId", activity.notes, "activity"."campaignId", "activity"."activityId", "activity"."activityType", "activity"."createdAt", "activity"."attachmentPath"') - .andWhere('"activity"."activityId" = :expenditureId', {expenditureId}) +export async function getActivityByExpenditureAsync( + expenditureId, + perPage, + page: number, + hostName: string +): Promise { + const dataSource = await db(); + const activityRepository = dataSource.getRepository('Activity'); + let data = (await activityRepository + .createQueryBuilder('activity') + .select( + 'activity.id, "activity"."userId", activity.notes, "activity"."campaignId", "activity"."activityId", "activity"."activityType", "activity"."createdAt", "activity"."attachmentPath"' + ) + .andWhere('"activity"."activityId" = :expenditureId', { expenditureId }) .andWhere('("activity"."activityType" = :activityType1 OR "activity"."activityType" = :activityType2)', { activityType1: ActivityTypeEnum.EXPENDITURE, - activityType2: ActivityTypeEnum.COMMENT_EXP + activityType2: ActivityTypeEnum.COMMENT_EXP, }) .orderBy('"activity"."createdAt"', 'DESC') .limit(perPage) .offset(perPage * page) - .getRawMany() as IActivityResult[]; - const total = await activityRepository.createQueryBuilder('activity') - .select('activity.id, "activity"."userId", activity.notes, "activity"."campaignId", "activity"."activityId", "activity"."activityType", "activity"."createdAt", "activity"."attachmentPath"') - .andWhere('"activity"."activityId" = :expenditureId', {expenditureId}) + .getRawMany()) as IActivityResult[]; + const total = await activityRepository + .createQueryBuilder('activity') + .select( + 'activity.id, "activity"."userId", activity.notes, "activity"."campaignId", "activity"."activityId", "activity"."activityType", "activity"."createdAt", "activity"."attachmentPath"' + ) + .andWhere('"activity"."activityId" = :expenditureId', { expenditureId }) .andWhere('("activity"."activityType" = :activityType1 OR "activity"."activityType" = :activityType2)', { activityType1: ActivityTypeEnum.EXPENDITURE, - activityType2: ActivityTypeEnum.COMMENT_EXP + activityType2: ActivityTypeEnum.COMMENT_EXP, }) .getCount(); data = data.map((item: IActivityResult) => { @@ -330,6 +377,6 @@ export async function getActivityByExpenditureAsync(expenditureId, perPage, page data, total, perPage, - page + page, }; } diff --git a/api/models/entity/Campaign.ts b/api/models/entity/Campaign.ts index cad8fb024..0acbcd989 100644 --- a/api/models/entity/Campaign.ts +++ b/api/models/entity/Campaign.ts @@ -1,19 +1,11 @@ -import { - Entity, - PrimaryGeneratedColumn, - Column, - ManyToOne, - OneToMany, - BeforeInsert, - BeforeUpdate, - getConnection -} from 'typeorm'; +import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, OneToMany, BeforeInsert, BeforeUpdate } from 'typeorm'; import { Government } from './Government'; import { Permission } from './Permission'; import { IsDefined, validate, ValidationError } from 'class-validator'; import { Activity } from './Activity'; import { Contribution } from './Contribution'; import { Expenditure } from './Expenditure'; +import db from '../db'; // Note, if you change any column type on the model, it will do a drop column operation, which means data loss in production. @Entity() @@ -29,21 +21,21 @@ export class Campaign { @IsDefined() officeSought: string; - @ManyToOne(type => Government, government => government.campaigns, { - eager: true + @ManyToOne((type) => Government, (government) => government.campaigns, { + eager: true, }) government: Government; - @OneToMany(type => Activity, activity => activity.user) + @OneToMany((type) => Activity, (activity) => activity.user) activities: Activity[]; - @OneToMany(type => Permission, permission => permission.campaign) + @OneToMany((type) => Permission, (permission) => permission.campaign) permissions: Permission[]; - @OneToMany(type => Contribution, contribution => contribution.government) + @OneToMany((type) => Contribution, (contribution) => contribution.government) contributions: Contribution[]; - @OneToMany(type => Expenditure, expenditure => expenditure.government) + @OneToMany((type) => Expenditure, (expenditure) => expenditure.government) expenditures: Expenditure[]; public errors: ValidationError[]; @@ -83,7 +75,7 @@ export class Campaign { id: this.id, name: this.name, governmentId: this.government.id, - officeSought: this.officeSought + officeSought: this.officeSought, }; } } @@ -94,7 +86,8 @@ export interface ICampaignSummary { } export async function getCampaignSummariesByGovernmentIdAsync(governmentId: number): Promise { - const campaignRepository = getConnection('default').getRepository('Campaign'); + const dataSource = await db(); + const campaignRepository = dataSource.getRepository('Campaign'); const campaigns = (await campaignRepository .createQueryBuilder('campaign') .andWhere('"campaign"."governmentId" = :governmentId', { governmentId }) diff --git a/api/models/entity/Contribution.ts b/api/models/entity/Contribution.ts index 93f04385c..d4b35dab7 100644 --- a/api/models/entity/Contribution.ts +++ b/api/models/entity/Contribution.ts @@ -8,7 +8,6 @@ import { OneToMany, CreateDateColumn, UpdateDateColumn, - getConnection, Between, In, LessThanOrEqual, @@ -22,10 +21,10 @@ import { IGetContributionGeoJsonOptions, IGetContributionOptions } from '../../s import { removeUndefined } from './helpers'; import { MatchAddressType } from '../../services/dataScienceService'; import { Parser } from 'json2csv'; -import * as dateFormat from 'dateformat'; -import OrestarContributionConverter from '../../models/converters/orestarContributionConverter'; +import * as dateFormat from 'date-and-time'; import { convertContributionsToXML } from '../converters'; import { addDataScienceJob } from '../../jobs/helpers/addJobs'; +import db from '../db'; export enum ContributionType { CONTRIBUTION = 'contribution', @@ -489,7 +488,7 @@ export class Contribution { } } -export const contributionSummaryFields = [ +export const contributionSummaryFields: (keyof Contribution)[] = [ 'id', 'amount', 'createdAt', @@ -533,7 +532,7 @@ export const contributionSummaryFields = [ ]; export type IContributionSummary = Pick; -export const contributionGovSummaryFields = [ +export const contributionGovSummaryFields: (keyof Contribution)[] = [ 'id', 'amount', 'createdAt', @@ -625,7 +624,8 @@ export async function getContributionsByGovernmentIdAsync( options?: IGetContributionOptions ): Promise { try { - const contributionRepository = getConnection('default').getRepository('Contribution'); + const dataSource = await db(); + const contributionRepository = dataSource.getRepository('Contribution'); const { page, perPage, campaignId, status, from, to, matchId, sort, format } = options; const isGovQuery = !options.campaignId; const where = { @@ -707,7 +707,8 @@ export async function getContributionsGeoJsonAsync( ): Promise { console.log('GET THEM CONTRIBUTIONS GEO', options); try { - const contributionRepository = getConnection('default').getRepository('Contribution'); + const dataSource = await db(); + const contributionRepository = dataSource.getRepository('Contribution'); let from; let to; if (options) { @@ -797,7 +798,7 @@ export async function getContributionsGeoJsonAsync( campaignName: contribution.campaign.name, officeSought: contribution.campaign.officeSought, batchId: contributorsMap.get(userKey), - isMiscCashContributionUnder100 + isMiscCashContributionUnder100, }, geometry: { type: 'Point', @@ -837,7 +838,7 @@ export function convertToCsv(contributions: any): string { contributions.data.map((item: any): any => { item.campaignId = item.campaign.id; item.campaignName = item.campaign.name; - item.date = dateFormat(item.date, 'yyyy/mm/dd'); + item.date = dateFormat.format(item.date, 'yyyy/mm/dd'); delete item.campaign; delete item.government; return item; @@ -865,7 +866,8 @@ export async function getContributionsSummaryByStatusAsync( attrs: SummaryAttrs ): Promise { try { - const contributionQuery = getConnection('default') + const dataSource = await db(); + const contributionQuery = dataSource .getRepository('Contribution') .createQueryBuilder('contributions') .select('SUM(contributions.amount)', 'amount') diff --git a/api/models/entity/Expenditure.ts b/api/models/entity/Expenditure.ts index 10e4bb6b1..80ed74e40 100644 --- a/api/models/entity/Expenditure.ts +++ b/api/models/entity/Expenditure.ts @@ -8,10 +8,9 @@ import { OneToMany, CreateDateColumn, UpdateDateColumn, - getConnection, Between, LessThanOrEqual, - MoreThanOrEqual + MoreThanOrEqual, } from 'typeorm'; import { IsDefined, validate, ValidationError } from 'class-validator'; import { Government } from './Government'; @@ -19,13 +18,14 @@ import { Campaign } from './Campaign'; import { Activity } from './Activity'; import { IGetExpenditureAttrs } from '../../services/expenditureService'; import { Parser } from 'json2csv'; -import * as dateFormat from 'dateformat'; +import * as dateFormat from 'date-and-time'; import { convertExpendituresToXML } from '../converters'; +import db from '../db'; export enum ExpenditureType { EXPENDITURE = 'expenditure', OTHER = 'other', - OTHER_DISBURSEMENT = 'other_disbursement' + OTHER_DISBURSEMENT = 'other_disbursement', } export enum ExpenditureSubType { @@ -35,7 +35,7 @@ export enum ExpenditureSubType { ACCOUNTS_PAYABLE_RESCINDED = 'accounts_payable_rescinded', CASH_BALANCE_ADJUSTMENT = 'cash_balance_adjustment', MISCELLANEOUS_OTHER_DISBURSEMENT = 'miscellaneous_other_disbursement', - REFUND_OF_CONTRIBUTION = 'refund_of_expenditure' + REFUND_OF_CONTRIBUTION = 'refund_of_expenditure', } export enum PayeeType { @@ -46,7 +46,7 @@ export enum PayeeType { POLITICAL_COMMITTEE = 'political_committee', POLITICAL_PARTY = 'political_party', UNREGISTERED = 'unregistered', - OTHER = 'other' + OTHER = 'other', } export enum PaymentMethod { @@ -56,7 +56,7 @@ export enum PaymentMethod { CREDIT_CARD_ONLINE = 'credit_card_online', CREDIT_CARD_PAPER = 'credit_card_paper', ETF = 'electronic_funds_transfer', - DEBIT = 'debit' + DEBIT = 'debit', } export enum ExpenditureStatus { @@ -64,7 +64,7 @@ export enum ExpenditureStatus { DRAFT = 'draft', SUBMITTED = 'submitted', OUT_OF_COMPLIANCE = 'out_of_compliance', - IN_COMPLIANCE = 'in_compliance' + IN_COMPLIANCE = 'in_compliance', } export enum PurposeType { @@ -76,14 +76,14 @@ export enum PurposeType { GENERAL_OPERATING = 'general_operating_expenses', PRIMTING = 'printing', MANAGEMENT = 'management', - NEWSPAPER = 'print_advertising', + NEWSPAPER = 'print_advertising', OTHER_AD = 'other_advertising', PETITION = 'petition_circulators', POSTAGE = 'postage', PREP_AD = 'preparation_of_advertising', POLLING = 'surveys_and_polls', TRAVEL = 'travel_expenses', - UTILITIES = 'utilities' + UTILITIES = 'utilities', } // Note, if you change any column type on the model, it will do a drop column operation, which means data loss in production. @@ -107,14 +107,14 @@ export class Expenditure { @Column({ type: 'enum', enum: ExpenditureType, - default: ExpenditureType.EXPENDITURE + default: ExpenditureType.EXPENDITURE, }) @IsDefined() type: ExpenditureType; @Column({ type: 'enum', - enum: ExpenditureSubType + enum: ExpenditureSubType, }) @IsDefined() subType: ExpenditureSubType; @@ -122,13 +122,13 @@ export class Expenditure { @Column({ type: 'enum', enum: PaymentMethod, - nullable: true + nullable: true, }) paymentMethod?: PaymentMethod; @Column({ type: 'enum', - enum: PayeeType + enum: PayeeType, }) @IsDefined() payeeType: PayeeType; @@ -136,7 +136,7 @@ export class Expenditure { @Column({ type: 'enum', enum: PurposeType, - nullable: true + nullable: true, }) purpose?: PurposeType; @@ -179,8 +179,8 @@ export class Expenditure { }, from: (value: string) => { return parseFloat(value); - } - } + }, + }, }) @IsDefined() amount: number; @@ -188,18 +188,18 @@ export class Expenditure { @Column({ type: 'enum', enum: ExpenditureStatus, - default: ExpenditureStatus.DRAFT + default: ExpenditureStatus.DRAFT, }) @IsDefined() status: ExpenditureStatus; - @ManyToOne(type => Government, government => government.expenditures) + @ManyToOne((type) => Government, (government) => government.expenditures) government: Government; - @ManyToOne(type => Campaign, campaign => campaign.expenditures) + @ManyToOne((type) => Campaign, (campaign) => campaign.expenditures) campaign: Campaign; - @OneToMany(type => Activity, activity => activity.expenditure) + @OneToMany((type) => Activity, (activity) => activity.expenditure) activities: Activity[]; public errors: ValidationError[] = []; @@ -254,14 +254,14 @@ export class Expenditure { ![ ExpenditureSubType.ACCOUNTS_PAYABLE, ExpenditureSubType.CASH_EXPENDITURE, - ExpenditureSubType.PERSONAL_EXPENDITURE + ExpenditureSubType.PERSONAL_EXPENDITURE, ].includes(this.subType) ) { const error = new ValidationError(); error.property = 'subType'; error.constraints = { notAllowed: - 'Type "expenditure" must have a subType of "accounts_payable, cash_expenditure or personal_expenditure"' + 'Type "expenditure" must have a subType of "accounts_payable, cash_expenditure or personal_expenditure"', }; this.errors.push(error); } @@ -274,7 +274,7 @@ export class Expenditure { const error = new ValidationError(); error.property = 'subType'; error.constraints = { - notAllowed: 'Type "other" must have a subType of "accounts_payable or cash_balance_adjustment"' + notAllowed: 'Type "other" must have a subType of "accounts_payable or cash_balance_adjustment"', }; this.errors.push(error); } @@ -282,14 +282,14 @@ export class Expenditure { if ( ![ ExpenditureSubType.MISCELLANEOUS_OTHER_DISBURSEMENT, - ExpenditureSubType.REFUND_OF_CONTRIBUTION + ExpenditureSubType.REFUND_OF_CONTRIBUTION, ].includes(this.subType) ) { const error = new ValidationError(); error.property = 'subType'; error.constraints = { notAllowed: - 'Type "other_disbursement" must have a subType of "miscellaneous_other_disbursement or refund_of_expenditure"' + 'Type "other_disbursement" must have a subType of "miscellaneous_other_disbursement or refund_of_expenditure"', }; this.errors.push(error); } @@ -307,18 +307,18 @@ export class Expenditure { toJSON() { const json: any = {}; - expenditureSummaryFields.forEach(( (key: string): void => { + expenditureSummaryFields.forEach((key: string): void => { json[key] = this[key]; - })); + }); json.campaign = { name: this.campaign.name, - id: this.campaign.id + id: this.campaign.id, }; return json as IExpenditureSummary; } } -export const expenditureSummaryFields = [ +export const expenditureSummaryFields: (keyof Expenditure)[] = [ 'id', 'amount', 'createdAt', @@ -339,9 +339,9 @@ export const expenditureSummaryFields = [ 'dateOriginalTransaction', 'vendorForOriginalPurchase', 'status', - 'date' + 'date', ]; -export type IExpenditureSummary = Pick; +export type IExpenditureSummary = Pick; export type IExpenditureSummaryResults = { data: IExpenditureSummary[]; @@ -357,35 +357,35 @@ export async function getExpendituresByGovernmentIdAsync( options?: IGetExpenditureAttrs ): Promise { try { - const expenditureRepository = getConnection('default').getRepository('Expenditure'); + const dataSource = await db(); + const expenditureRepository = dataSource.getRepository('Expenditure'); const { page, perPage, campaignId, status, from, to, sort, format } = options; - const where = { - government: { - id: governmentId - }, - campaign: campaignId - ? { - id: campaignId - } - : undefined, - status, - date: - from && to ? Between(from, to) : from ? MoreThanOrEqual(from) : to ? LessThanOrEqual(to) : undefined - }; + // Ensure page is a positive integer + const validPage = page < 1 ? 1 : page; + const where: any = { + government: { + id: governmentId, + }, + // Only include campaign if campaignId is defined + ...(campaignId && { campaign: { id: campaignId } }), + // Only include status if status is defined + ...(status && { status }), + // Only include date range if from or to is defined + ...(from && to + ? { date: Between(from, to) } + : from + ? { date: MoreThanOrEqual(from) } + : to + ? { date: LessThanOrEqual(to) } + : {}), + }; const query: any = { select: expenditureSummaryFields, relations: ['campaign', 'government'], where, - join: { - alias: 'contribution', - leftJoinAndSelect: { - government: 'contribution.government', - campaign: 'contribution.campaign' - } - }, - skip: format === 'csv' ? undefined : page, - take: format === 'csv' ? undefined : perPage, - order: { 'updatedAt': 'DESC'} + skip: format === 'csv' ? undefined : (validPage - 1) * perPage, + take: format === 'csv' ? undefined : perPage, + order: { updatedAt: 'DESC' }, }; if (sort) { @@ -402,38 +402,41 @@ export async function getExpendituresByGovernmentIdAsync( } query.order = { [sortField]: sort.direction }; - } - const expenditures = (await expenditureRepository.find(removeUndefined(query)) as IExpenditureSummary[]).map((item: any): any => { + const expenditures = await expenditureRepository.find(removeUndefined(query)); + const formattedExpenditures = expenditures.map((item: any): any => { const json = item.toJSON(); json.campaign = { id: item.campaign.id, - name: item.campaign.name}; + name: item.campaign.name, + }; json.government = { id: item.government.id, - name: item.government.name}; + name: item.government.name, + }; return json; }); + const total = await expenditureRepository.count(removeUndefined(query)); return { - data: expenditures, + data: formattedExpenditures, total, perPage, - page + page, }; } catch (err) { - console.log(err); + console.log('Error:', err); // Log the error throw new Error('Error executing get expenditures query'); } } export function convertToCsv(expenditures: IExpenditureSummaryResults): string { const json2csvParser = new Parser(); - expenditures.data.map( (item: any ): any => { + expenditures.data.map((item: any): any => { item.campaignId = item.campaign.id; item.campaignName = item.campaign.name; - item.date = dateFormat(item.date, 'yyyy/mm/dd'); + item.date = dateFormat.format(item.date, 'yyyy/mm/dd'); delete item.campaign; delete item.government; return item; @@ -445,8 +448,8 @@ export function convertToXml(expenditures: IExpenditureSummaryResults, filerId: return convertExpendituresToXML(expenditures, filerId); } -const removeUndefined = obj => { - Object.keys(obj).forEach(key => { +const removeUndefined = (obj) => { + Object.keys(obj).forEach((key) => { if (obj[key] && typeof obj[key] === 'object') removeUndefined(obj[key]); else if (obj[key] === undefined) delete obj[key]; }); @@ -459,28 +462,28 @@ export interface ExpenditureSummaryByStatus { amount: number; } - export interface SummaryAttrs { campaignId?: number; governmentId?: number; } -export async function getExpenditureSummaryByStatusAsync( - attrs: SummaryAttrs -): Promise { +export async function getExpenditureSummaryByStatusAsync(attrs: SummaryAttrs): Promise { try { - const expenditureQuery = getConnection('default') + const dataSource = await db(); + const expenditureQuery = dataSource .getRepository('Expenditure') .createQueryBuilder('expenditures') .select('SUM(expenditures.amount)', 'amount') .addSelect('COUNT(expenditures.*)', 'total') .addSelect('expenditures.status', 'status') - .where('expenditures.status != :status', {status: ExpenditureStatus.ARCHIVED}) + .where('expenditures.status != :status', { status: ExpenditureStatus.ARCHIVED }) .groupBy('expenditures.status'); if (attrs.campaignId) { - expenditureQuery.andWhere('expenditures."campaignId" = :campaignId', {campaignId: attrs.campaignId}); + expenditureQuery.andWhere('expenditures."campaignId" = :campaignId', { campaignId: attrs.campaignId }); } else if (attrs.governmentId) { - expenditureQuery.andWhere('expenditures."governmentId" = :governmentId', {governmentId: attrs.governmentId}); + expenditureQuery.andWhere('expenditures."governmentId" = :governmentId', { + governmentId: attrs.governmentId, + }); } const results: any = await expenditureQuery.getRawMany(); @@ -489,11 +492,10 @@ export async function getExpenditureSummaryByStatusAsync( summary.push({ status: item.status, total: parseInt(item.total), - amount: parseInt(item.amount) + amount: parseInt(item.amount), }); }); return summary; - } catch (err) { throw new Error('Error executing get expenditures summary status query'); } diff --git a/api/models/entity/ExternalContribution.ts b/api/models/entity/ExternalContribution.ts index 817a886b7..8f88ab299 100644 --- a/api/models/entity/ExternalContribution.ts +++ b/api/models/entity/ExternalContribution.ts @@ -1,301 +1,314 @@ import { - Entity, - Column, - CreateDateColumn, - UpdateDateColumn, - PrimaryColumn, - getConnection, - Between, - MoreThanOrEqual, - LessThanOrEqual, + Entity, + Column, + CreateDateColumn, + UpdateDateColumn, + PrimaryColumn, + Between, + MoreThanOrEqual, + LessThanOrEqual, } from 'typeorm'; import { IsDefined, validate, ValidationError } from 'class-validator'; import { ContributionType, ContributorType, IContributionsGeoJson } from './Contribution'; import { IGetContributionGeoJsonOptions } from '../../services/contributionService'; import { removeUndefined } from './helpers'; +import db from '../db'; export enum ExternalContributionSubType { - CASH = 'cash', - INKIND_CONTRIBUTION = 'inkind_contribution', - INKIND_PAID_SUPERVISION = 'inkind_paid_supervision', - INKIND_FORGIVEN_ACCOUNT = 'inkind_forgiven_account', - INKIND_FORGIVEN_PERSONAL = 'inkind_forgiven_personal', - ITEM_SOLD_FAIR_MARKET = 'item_sold_fair_market', - ITEM_RETURNED_CHECK = 'item_returned_check', - ITEM_MISC = 'item_misc', - ITEM_REFUND = 'item_refund', - OTHER = 'other', + CASH = 'cash', + INKIND_CONTRIBUTION = 'inkind_contribution', + INKIND_PAID_SUPERVISION = 'inkind_paid_supervision', + INKIND_FORGIVEN_ACCOUNT = 'inkind_forgiven_account', + INKIND_FORGIVEN_PERSONAL = 'inkind_forgiven_personal', + ITEM_SOLD_FAIR_MARKET = 'item_sold_fair_market', + ITEM_RETURNED_CHECK = 'item_returned_check', + ITEM_MISC = 'item_misc', + ITEM_REFUND = 'item_refund', + OTHER = 'other', } // Note, if you change any column type on the model, it will do a drop column operation, which means data loss in production. @Entity('external_contributions') export class ExternalContribution { - // New: from Orestar - @PrimaryColumn() - @IsDefined() - orestarOriginalId: string; - - // New: from Orestar - @Column() - @IsDefined() - orestarTransactionId: string; - - @Column() - @CreateDateColumn() - createdAt: Date; - - @Column() - @UpdateDateColumn() - updatedAt: Date; - - @Column({ - type: 'enum', - enum: ContributionType, - default: ContributionType.CONTRIBUTION, - }) - @IsDefined() - type: ContributionType; - - @Column({ - type: 'enum', - enum: ExternalContributionSubType, - }) - @IsDefined() - subType: ExternalContributionSubType; - - @Column({ - type: 'enum', - enum: ContributorType, - }) - @IsDefined() - contributorType: ContributorType; - - @Column({ nullable: true }) - name?: string; - - @IsDefined() - @Column() - address1: string; - - @Column({ nullable: true }) - address2?: string; - - @IsDefined() - @Column() - city: string; - - @IsDefined() - @Column() - state: string; - - @IsDefined() - @Column() - zip: string; - - @Column() - country: string; - - @Column({ nullable: true }) - notes?: string; - - @Column({ - type: 'decimal', - transformer: { - to: (value: number): number => value, - from: (value: string): number => parseFloat(value), - }, - }) - amount: number; - - @Column({ nullable: true }) - occupation?: string; - - @Column({ nullable: true }) - employerName?: string; - - @Column({ nullable: true }) - employerCity?: string; - - @Column({ nullable: true }) - employerState?: string; - - @Column() - @IsDefined() - date: Date; - - @Column({ - type: 'geometry', - nullable: true, - spatialFeatureType: 'Point', - srid: 4326, - }) - addressPoint?: { - type: 'Point'; - coordinates: [number, number]; - }; // geoJson coordinates for address - - public errors: ValidationError[] = []; - - async isValidAsync(): Promise { - await this.validateAsync(); - return this.errors.length === 0; - } - - async validateAsync(): Promise { - const errors = await validate(this); - this.errors = errors; - this.validateType(); - this.validateName(); - this.validateContributorAddress(); - return this.errors; - } - - validateType(): void { - if (this.type === ContributionType.CONTRIBUTION) { - if ( - ![ - ExternalContributionSubType.CASH, - ExternalContributionSubType.INKIND_CONTRIBUTION, - ExternalContributionSubType.INKIND_PAID_SUPERVISION, - ExternalContributionSubType.INKIND_FORGIVEN_ACCOUNT, - ExternalContributionSubType.INKIND_FORGIVEN_PERSONAL, - ].includes(this.subType) - ) { - const error = new ValidationError(); - error.property = 'subType'; - error.constraints = { - notAllowed: 'Type "contribution" must have a valid subType of "cash or an inkind value"', - }; - this.errors.push(error); - } - } else if ( - [ - ExternalContributionSubType.CASH, - ExternalContributionSubType.INKIND_CONTRIBUTION, - ExternalContributionSubType.INKIND_PAID_SUPERVISION, - ExternalContributionSubType.INKIND_FORGIVEN_ACCOUNT, - ExternalContributionSubType.INKIND_FORGIVEN_PERSONAL, - ].includes(this.subType) - ) { - const error = new ValidationError(); - error.property = 'subType'; - error.constraints = { notAllowed: 'Type "other" cannot have a subType of "cash or inkind value"' }; - this.errors.push(error); + // New: from Orestar + @PrimaryColumn() + @IsDefined() + orestarOriginalId: string; + + // New: from Orestar + @Column() + @IsDefined() + orestarTransactionId: string; + + @Column() + @CreateDateColumn() + createdAt: Date; + + @Column() + @UpdateDateColumn() + updatedAt: Date; + + @Column({ + type: 'enum', + enum: ContributionType, + default: ContributionType.CONTRIBUTION, + }) + @IsDefined() + type: ContributionType; + + @Column({ + type: 'enum', + enum: ExternalContributionSubType, + }) + @IsDefined() + subType: ExternalContributionSubType; + + @Column({ + type: 'enum', + enum: ContributorType, + }) + @IsDefined() + contributorType: ContributorType; + + @Column({ nullable: true }) + name?: string; + + @IsDefined() + @Column() + address1: string; + + @Column({ nullable: true }) + address2?: string; + + @IsDefined() + @Column() + city: string; + + @IsDefined() + @Column() + state: string; + + @IsDefined() + @Column() + zip: string; + + @Column() + country: string; + + @Column({ nullable: true }) + notes?: string; + + @Column({ + type: 'decimal', + transformer: { + to: (value: number): number => value, + from: (value: string): number => parseFloat(value), + }, + }) + amount: number; + + @Column({ nullable: true }) + occupation?: string; + + @Column({ nullable: true }) + employerName?: string; + + @Column({ nullable: true }) + employerCity?: string; + + @Column({ nullable: true }) + employerState?: string; + + @Column() + @IsDefined() + date: Date; + + @Column({ + type: 'geometry', + nullable: true, + spatialFeatureType: 'Point', + srid: 4326, + }) + addressPoint?: { + type: 'Point'; + coordinates: [number, number]; + }; // geoJson coordinates for address + + public errors: ValidationError[] = []; + + async isValidAsync(): Promise { + await this.validateAsync(); + return this.errors.length === 0; } - } - - validateName(): void { - if (!this.name || this.name.trim() === '') { - const error = new ValidationError(); - error.property = 'name'; - error.constraints = { isDefined: 'name should not be null or undefined' }; - this.errors.push(error); + + async validateAsync(): Promise { + const errors = await validate(this); + this.errors = errors; + this.validateType(); + this.validateName(); + this.validateContributorAddress(); + return this.errors; } - } - validateContributorAddress(): boolean { - if (this.contributorType === ContributorType.INDIVIDUAL || this.contributorType === ContributorType.FAMILY) { - return !!(this.address1 && this.city && this.zip && this.state); + validateType(): void { + if (this.type === ContributionType.CONTRIBUTION) { + if ( + ![ + ExternalContributionSubType.CASH, + ExternalContributionSubType.INKIND_CONTRIBUTION, + ExternalContributionSubType.INKIND_PAID_SUPERVISION, + ExternalContributionSubType.INKIND_FORGIVEN_ACCOUNT, + ExternalContributionSubType.INKIND_FORGIVEN_PERSONAL, + ].includes(this.subType) + ) { + const error = new ValidationError(); + error.property = 'subType'; + error.constraints = { + notAllowed: 'Type "contribution" must have a valid subType of "cash or an inkind value"', + }; + this.errors.push(error); + } + } else if ( + [ + ExternalContributionSubType.CASH, + ExternalContributionSubType.INKIND_CONTRIBUTION, + ExternalContributionSubType.INKIND_PAID_SUPERVISION, + ExternalContributionSubType.INKIND_FORGIVEN_ACCOUNT, + ExternalContributionSubType.INKIND_FORGIVEN_PERSONAL, + ].includes(this.subType) + ) { + const error = new ValidationError(); + error.property = 'subType'; + error.constraints = { notAllowed: 'Type "other" cannot have a subType of "cash or inkind value"' }; + this.errors.push(error); + } + } + + validateName(): void { + if (!this.name || this.name.trim() === '') { + const error = new ValidationError(); + error.property = 'name'; + error.constraints = { isDefined: 'name should not be null or undefined' }; + this.errors.push(error); + } + } + + validateContributorAddress(): boolean { + if (this.contributorType === ContributorType.INDIVIDUAL || this.contributorType === ContributorType.FAMILY) { + return !!(this.address1 && this.city && this.zip && this.state); + } + return true; } - return true; - } } -export const contributionSummaryFields = [ - 'orestarOriginalId', - 'orestarTransactionId', - 'country', - 'amount', - 'type', - 'subType', - 'contributorType', - 'name', - 'address1', - 'address2', - 'city', - 'state', - 'zip', - 'occupation', - 'employerName', - 'employerCity', - 'employerState', - 'notes', - 'date', - 'addressPoint', +export const contributionSummaryFields: (keyof ExternalContribution)[] = [ + 'orestarOriginalId', + 'orestarTransactionId', + 'country', + 'amount', + 'type', + 'subType', + 'contributorType', + 'name', + 'address1', + 'address2', + 'city', + 'state', + 'zip', + 'occupation', + 'employerName', + 'employerCity', + 'employerState', + 'notes', + 'date', + 'addressPoint', ]; -export type IContributionSummary = Pick; +export type IContributionSummary = Pick; export async function getExternalContributionsGeoJsonAsync( - options?: IGetContributionGeoJsonOptions + options?: IGetContributionGeoJsonOptions ): Promise { - try { - const externalContributionRepository = getConnection('default').getRepository('external_contributions'); - let from; - let to; - if (options) { - from = options.from; - to = options.to; - } - - const where = { - date: from && to ? Between(from, to) : from ? MoreThanOrEqual(from) : to ? LessThanOrEqual(to) : undefined - }; - const query: any = { - select: ['date', 'type', 'amount', 'city', 'state', 'zip', 'name', 'addressPoint', 'contributorType', 'subType'], - where, - order: { - date: 'DESC' - } - }; - - // create a map of contributors - const contributorsMap = new Map(); - - const contributions = (await externalContributionRepository.find(removeUndefined(query)) as any).map((contribution: ExternalContribution, index: number): any => { - const userKey = contribution.name || 'unknown'; - const batchId = `batch-${index}`; - if (!contributorsMap.has(userKey)) { - contributorsMap.set(userKey, batchId); - } - let isMiscCashContributionUnder100 = undefined; - if (userKey && userKey.includes('Miscellaneous Cash Contributions $100')) { - isMiscCashContributionUnder100 = true; - } - const json = { - type: 'Feature', - properties: { - type: contribution.type, - city: contribution.city, - state: contribution.state, - zip: contribution.zip, - amount: contribution.amount, - contributorType: contribution.contributorType, - contributionType: contribution.type, - contributionSubType: contribution.subType, - date: contribution.date.toISOString(), - campaignId: -1, - campaignName: 'Ted Wheeler', - officeSought: 'Mayor', - batchId: contributorsMap.get(userKey), - isMiscCashContributionUnder100, - }, - geometry: { - type: 'Point', - // @ts-ignore - coordinates: contribution.addressPoint ? contribution.addressPoint.coordinates : undefined + try { + const dataSource = await db(); + const externalContributionRepository = dataSource.getRepository('external_contributions'); + let from; + let to; + if (options) { + from = options.from; + to = options.to; } - }; - return json; - }); - - return { - type: 'FeatureCollection', - features: contributions, - }; + const where = { + date: from && to ? Between(from, to) : from ? MoreThanOrEqual(from) : to ? LessThanOrEqual(to) : undefined, + }; + const query: any = { + select: [ + 'date', + 'type', + 'amount', + 'city', + 'state', + 'zip', + 'name', + 'addressPoint', + 'contributorType', + 'subType', + ], + where, + order: { + date: 'DESC', + }, + }; - } catch (err) { - console.log(err); - throw new Error('Error executing get contributions geojson query'); - } -} \ No newline at end of file + // create a map of contributors + const contributorsMap = new Map(); + + const contributions = ((await externalContributionRepository.find(removeUndefined(query))) as any).map( + (contribution: ExternalContribution, index: number): any => { + const userKey = contribution.name || 'unknown'; + const batchId = `batch-${index}`; + if (!contributorsMap.has(userKey)) { + contributorsMap.set(userKey, batchId); + } + let isMiscCashContributionUnder100 = undefined; + if (userKey && userKey.includes('Miscellaneous Cash Contributions $100')) { + isMiscCashContributionUnder100 = true; + } + const json = { + type: 'Feature', + properties: { + type: contribution.type, + city: contribution.city, + state: contribution.state, + zip: contribution.zip, + amount: contribution.amount, + contributorType: contribution.contributorType, + contributionType: contribution.type, + contributionSubType: contribution.subType, + date: contribution.date.toISOString(), + campaignId: -1, + campaignName: 'Ted Wheeler', + officeSought: 'Mayor', + batchId: contributorsMap.get(userKey), + isMiscCashContributionUnder100, + }, + geometry: { + type: 'Point', + // @ts-ignore + coordinates: contribution.addressPoint ? contribution.addressPoint.coordinates : undefined, + }, + }; + + return json; + } + ); + + return { + type: 'FeatureCollection', + features: contributions, + }; + } catch (err) { + console.log(err); + throw new Error('Error executing get contributions geojson query'); + } +} diff --git a/api/models/entity/Permission.ts b/api/models/entity/Permission.ts index e7f8b9a46..2130ccc4e 100644 --- a/api/models/entity/Permission.ts +++ b/api/models/entity/Permission.ts @@ -1,9 +1,9 @@ -import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, BeforeInsert, BeforeUpdate, getConnection } from 'typeorm'; +import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, BeforeInsert, BeforeUpdate } from 'typeorm'; import { Government, IGovernmentSummary } from './Government'; import { Campaign, ICampaignSummary } from './Campaign'; -import { IUserSummary, User, UserStatus } from './User'; +import { IUserSummary, User } from './User'; import { IsDefined, validate, ValidationError } from 'class-validator'; -import { PermissionType } from 'aws-sdk/clients/workmail'; +import db from '../db'; export enum UserRole { GOVERNMENT_ADMIN = 'government_admin', @@ -15,31 +15,29 @@ export enum UserRole { // Note, if you change any column type on the model, it will do a drop column operation, which means data loss in production. @Entity() export class Permission { - @PrimaryGeneratedColumn() id: number; @Column({ type: 'enum', enum: UserRole, - default: UserRole.CAMPAIGN_STAFF + default: UserRole.CAMPAIGN_STAFF, }) @IsDefined() role: UserRole; - - @ManyToOne(type => Government, government => government.permissions, { - eager: true + @ManyToOne((type) => Government, (government) => government.permissions, { + eager: true, }) government: Government; - @ManyToOne(type => Campaign, campaign => campaign.permissions, { - eager: true + @ManyToOne((type) => Campaign, (campaign) => campaign.permissions, { + eager: true, }) campaign: Campaign; - @ManyToOne(type => User, user => user.permissions, { - eager: true + @ManyToOne((type) => User, (user) => user.permissions, { + eager: true, }) user: User; @@ -73,7 +71,7 @@ export class Permission { if (!u) { const error = new ValidationError(); error.property = 'userId'; - error.constraints = {isDefined: 'userId should not be null or undefined'}; + error.constraints = { isDefined: 'userId should not be null or undefined' }; this.errors.push(error); } } @@ -83,7 +81,7 @@ export class Permission { if (!g) { const error = new ValidationError(); error.property = 'governmentId'; - error.constraints = {isDefined: 'governmentId should not be null or undefined'}; + error.constraints = { isDefined: 'governmentId should not be null or undefined' }; this.errors.push(error); } } @@ -93,12 +91,12 @@ export class Permission { if (!c && this.role !== UserRole.GOVERNMENT_ADMIN) { const error = new ValidationError(); error.property = 'campaignId'; - error.constraints = {isDefined: 'campaignId should not be null or undefined'}; + error.constraints = { isDefined: 'campaignId should not be null or undefined' }; this.errors.push(error); } else if (c && this.role === UserRole.GOVERNMENT_ADMIN) { const error = new ValidationError(); error.property = 'campaignId'; - error.constraints = {notAllowed: 'campaignId cannot be set with GovernmentAdmin as a UserRole'}; + error.constraints = { notAllowed: 'campaignId cannot be set with GovernmentAdmin as a UserRole' }; this.errors.push(error); } } @@ -108,8 +106,8 @@ export class Permission { id: this.id, user: this.user.id, role: this.role, - campaign: {id: this.campaign.id, name: this.campaign.name}, - government: {id: this.government.id, name: this.government.name}, + campaign: { id: this.campaign.id, name: this.campaign.name }, + government: { id: this.government.id, name: this.government.name }, }; } } @@ -131,14 +129,16 @@ export interface IUserPermission { } export async function getPermissionsByCampaignIdAsync(campaignId: number): Promise { - const permissionRepository = getConnection('default').getRepository('Permission'); - const permissions = await permissionRepository.createQueryBuilder('permission') - .andWhere('"permission"."campaignId" = :campaignId', {campaignId}) // notice "" quotes around camelCase id items - .innerJoinAndSelect('permission.user', 'user', ) + const dataSource = await db(); + const permissionRepository = dataSource.getRepository('Permission'); + const permissions = (await permissionRepository + .createQueryBuilder('permission') + .andWhere('"permission"."campaignId" = :campaignId', { campaignId }) // notice "" quotes around camelCase id items + .innerJoinAndSelect('permission.user', 'user') .innerJoinAndSelect('permission.campaign', 'campaign') .innerJoinAndSelect('permission.government', 'government') - .getMany() as IUserPermissionResult[]; - return permissions.map(permission => { + .getMany()) as IUserPermissionResult[]; + return permissions.map((permission) => { return { id: permission.id, role: permission.role, @@ -156,16 +156,18 @@ export async function getPermissionsByCampaignIdAsync(campaignId: number): Promi } export async function getPermissionsByGovernmentIdAsync(governmentId: number): Promise { - const permissionRepository = getConnection('default').getRepository('Permission'); - const permissions = await permissionRepository.createQueryBuilder('permission') - .andWhere('"permission"."governmentId" = :governmentId', {governmentId}) + const dataSource = await db(); + const permissionRepository = dataSource.getRepository('Permission'); + const permissions = (await permissionRepository + .createQueryBuilder('permission') + .andWhere('"permission"."governmentId" = :governmentId', { governmentId }) .innerJoinAndSelect('permission.user', 'user') .innerJoinAndSelect('permission.government', 'government') .leftJoinAndSelect('permission.campaign', 'campaign') .addOrderBy('"permission"."campaignId"', 'ASC') - .getMany() as IUserPermissionResult[]; + .getMany()) as IUserPermissionResult[]; - return permissions.map(permission => { + return permissions.map((permission) => { const userPermission: IUserPermission = { id: permission.id, role: permission.role, @@ -173,13 +175,13 @@ export async function getPermissionsByGovernmentIdAsync(governmentId: number): P government: { id: permission.government.id, name: permission.government.name, - } + }, }; if (permission.campaign) { userPermission.campaign = { id: permission.campaign.id, - name: permission.campaign.name + name: permission.campaign.name, }; } return userPermission; diff --git a/api/models/ormconfig.ts b/api/models/ormconfig.ts index 5543ea8cd..d1463c78f 100644 --- a/api/models/ormconfig.ts +++ b/api/models/ormconfig.ts @@ -1,23 +1,15 @@ -import { ConnectionOptions } from 'typeorm'; +import { DataSourceOptions } from 'typeorm'; -const ORMConfig: ConnectionOptions = { - type: 'postgres', - host: process.env.DB_HOST, - port: parseInt(process.env.DB_PORT), - username: process.env.DB_USERNAME, - password: process.env.DB_PASSWORD, - database: process.env.DB_NAME, - entities: [ - __dirname + '/entity/*{.ts,.js}', - ], - migrations: [ - __dirname + '/migrations/*{.ts,.js}', - ], - synchronize: process.env.NODE_ENV === 'production' ? false : true, - logging: false, - cli: { - entitiesDir: 'models/entity', - migrationsDir: 'models/migrations', - }, +const ORMConfig: DataSourceOptions = { + type: 'postgres', + host: process.env.DB_HOST, + port: parseInt(process.env.DB_PORT), + username: process.env.DB_USERNAME, + password: process.env.DB_PASSWORD, + database: process.env.DB_NAME, + entities: [__dirname + '/entity/*{.ts,.js}'], + migrations: [__dirname + '/migrations/*{.ts,.js}'], + synchronize: process.env.NODE_ENV === 'production' ? false : true, + logging: false, }; -export default ORMConfig; \ No newline at end of file +export default ORMConfig; diff --git a/api/models/seeds/seeds.ts b/api/models/seeds/seeds.ts index f34052687..b5030cf1c 100644 --- a/api/models/seeds/seeds.ts +++ b/api/models/seeds/seeds.ts @@ -1,4 +1,3 @@ -import { getConnection } from 'typeorm'; import { createUserAsync } from '../../services/userService'; import { newCampaignAsync, newExpenditureAsync, newGovernmentAsync, truncateAll } from '../../test/factories'; import { addPermissionAsync } from '../../services/permissionService'; @@ -6,12 +5,13 @@ import { UserRole } from '../entity/Permission'; import { User, UserStatus } from '../../models/entity/User'; import { Address } from '../../models/entity/Address'; import * as fs from 'fs'; -import * as parse from 'csv-parse/lib/sync'; +import { parse } from 'csv-parse/sync'; import { addContributionAsync } from '../../services/contributionService'; import { ContributionSubType, ContributionType, ContributorType, PaymentMethod, OaeType } from '../entity/Contribution'; -import * as faker from 'faker'; import { Government } from '../entity/Government'; import { Campaign } from '../entity/Campaign'; +import db from '../db'; +import { faker } from '@faker-js/faker'; function chunk(array, size) { const chunked_arr = []; @@ -36,19 +36,15 @@ export async function seedAddresses() { const parsed = parse(data, { columns: true, - skip_empty_lines: true + skip_empty_lines: true, }); const chunks = chunk(parsed, 1000); let i = 0; const promises = []; + const dataSource = await db(); chunks.forEach((addressArray: any): void => { - const query = getConnection() - .createQueryBuilder() - .insert() - .into(Address) - .values(addressArray) - .execute(); + const query = dataSource.createQueryBuilder().insert().into(Address).values(addressArray).execute(); promises.push(query); i++; }); @@ -61,7 +57,7 @@ export function addGISBoundaries() { ); } -export interface Address { +export interface AddressI { firstName: string; middleName: string; lastName: string; @@ -85,32 +81,34 @@ export async function addContributions(user: User, government: Government, campa // firstName,middleName,lastName,county,address1,address2,city,state,zip,zipPlusFour const promises = []; - const parsed: Address[] = parse(data, { + const parsed: AddressI[] = parse(data, { columns: true, - skip_empty_lines: true - }); - - parsed.forEach((address: Address) => { - promises.push(addContributionAsync({ - firstName: address.firstName, - lastName: address.lastName, - address1: address.address1, - address2: address.address2, - city: address.city, - state: address.state, - zip: address.zip, - contributorType: ContributorType.INDIVIDUAL, - type: ContributionType.CONTRIBUTION, - subType: ContributionSubType.CASH, - amount: faker.finance.amount(1, 500, 2), - date: faker.date.past(1), - governmentId: government.id, - campaignId: campaign.id, - currentUserId: user.id, - paymentMethod: PaymentMethod.CREDIT_CARD_ONLINE, - oaeType: OaeType.ALLOWABLE, - occupation: 'Other' - })); + skip_empty_lines: true, + }); + + parsed.forEach((address: AddressI) => { + promises.push( + addContributionAsync({ + firstName: address.firstName, + lastName: address.lastName, + address1: address.address1, + address2: address.address2, + city: address.city, + state: address.state, + zip: address.zip, + contributorType: ContributorType.INDIVIDUAL, + type: ContributionType.CONTRIBUTION, + subType: ContributionSubType.CASH, + amount: parseInt(faker.finance.amount({ min: 1, max: 500, dec: 2 })), + date: faker.date.past().getTime(), // this is sus + governmentId: government.id, + campaignId: campaign.id, + currentUserId: user.id, + paymentMethod: PaymentMethod.CREDIT_CARD_ONLINE, + oaeType: OaeType.ALLOWABLE, + occupation: 'Other', + }) + ); }); return Promise.all(promises); @@ -132,7 +130,7 @@ export default async (onlyData?: boolean) => { email: 'govadmin@openelectionsportland.org', password: 'password', firstName: 'Government', - lastName: 'Admin' + lastName: 'Admin', }); console.log('Adding a campaign admin'); @@ -140,7 +138,7 @@ export default async (onlyData?: boolean) => { email: 'campaignadmin@openelectionsportland.org', password: 'password', firstName: 'Campaign', - lastName: 'Admin' + lastName: 'Admin', }); console.log('Adding a campaign staff'); @@ -148,7 +146,7 @@ export default async (onlyData?: boolean) => { email: 'campaignstaff@openelectionsportland.org', password: 'password', firstName: 'Campaign', - lastName: 'Staff' + lastName: 'Staff', }); console.log('Adding a campaign staff'); @@ -156,7 +154,7 @@ export default async (onlyData?: boolean) => { email: 'campaignstaff+1@openelectionsportland.org', invitationCode: 'inviteme', firstName: 'Campaign', - lastName: 'Staff' + lastName: 'Staff', }); console.log('Adding a campaign staff'); @@ -164,7 +162,7 @@ export default async (onlyData?: boolean) => { email: 'campaignstaff+removeme@openelectionsportland.org', password: 'password', firstName: 'Campaign', - lastName: 'Staff' + lastName: 'Staff', }); console.log('Adding a campaign staff'); @@ -172,10 +170,11 @@ export default async (onlyData?: boolean) => { email: 'campaignstaff+removeme2@openelectionsportland.org', password: 'password', firstName: 'Campaign', - lastName: 'Staff' + lastName: 'Staff', }); - const userRepository = getConnection('default').getRepository('User'); + const dataSource = await db(); + const userRepository = dataSource.getRepository('User'); let campaignStaffReset = new User(); campaignStaffReset.email = 'campaignstaff+2@openelectionsportland.org'; campaignStaffReset.firstName = 'Campaign'; @@ -197,43 +196,43 @@ export default async (onlyData?: boolean) => { await addPermissionAsync({ userId: govAdmin.id, role: UserRole.GOVERNMENT_ADMIN, - governmentId: government.id + governmentId: government.id, }); await addPermissionAsync({ userId: campaignAdmin.id, role: UserRole.CAMPAIGN_ADMIN, - campaignId: campaign.id + campaignId: campaign.id, }); await addPermissionAsync({ userId: campaignStaff.id, role: UserRole.CAMPAIGN_STAFF, - campaignId: campaign.id + campaignId: campaign.id, }); await addPermissionAsync({ userId: campaignStaffInvited.id, role: UserRole.CAMPAIGN_STAFF, - campaignId: campaign.id + campaignId: campaign.id, }); await addPermissionAsync({ userId: campaignStaffReset.id, role: UserRole.CAMPAIGN_STAFF, - campaignId: campaign.id + campaignId: campaign.id, }); await addPermissionAsync({ userId: campaignStaffRemoved.id, role: UserRole.CAMPAIGN_STAFF, - campaignId: campaign.id + campaignId: campaign.id, }); await addPermissionAsync({ userId: campaignStaffRemoved2.id, role: UserRole.CAMPAIGN_STAFF, - campaignId: campaign.id + campaignId: campaign.id, }); await seedAddresses(); diff --git a/api/package-lock.json b/api/package-lock.json index 58cde3ed7..a249525dd 100644 --- a/api/package-lock.json +++ b/api/package-lock.json @@ -1,6415 +1,10972 @@ { - "name": "app", - "version": "0.1.0", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@bugsnag/browser": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@bugsnag/browser/-/browser-6.4.1.tgz", - "integrity": "sha512-dpNrD0ghigSh21mbR7GlfFrLJdtbpgmCWnNSHhSR1AOqsdl82ZGitsb6tPwmTTLatCFrFiptLkGjKBhkGLI3DA==" - }, - "@bugsnag/js": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@bugsnag/js/-/js-6.4.1.tgz", - "integrity": "sha512-1JME0OOkVup35YHJ8MHDOwN6lK+7ftwSld0oWkehLMRLjteWhoSg57XqMYsbSFK0IAbOrWdlTiL6ceU/lNeu6A==", - "requires": { - "@bugsnag/browser": "^6.4.1", - "@bugsnag/node": "^6.4.1" - } - }, - "@bugsnag/node": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@bugsnag/node/-/node-6.4.1.tgz", - "integrity": "sha512-ncVPJtg16hp4kMsDwbqGRRCX3wUwjyPfoiCx73qLDmuuthFYBKq7qLZCHjWSQ5/6rm/8ahF6TFa4JEnaZXb3qQ==", - "requires": { - "byline": "^5.0.0", - "error-stack-parser": "^2.0.2", - "iserror": "^0.0.2", - "pump": "^3.0.0", - "stack-generator": "^2.0.3" - } - }, - "@bugsnag/plugin-express": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@bugsnag/plugin-express/-/plugin-express-6.4.1.tgz", - "integrity": "sha512-7ppJNTYBqEjqIn/psZ2NUZ9a3gwi+xlllzuQDSs0N5WFR3ju3gPrjd7DLkARa1oXj+p/kISke+XY1nnex1wsIg==", - "requires": { - "iserror": "^0.0.2" - } - }, - "@sinonjs/commons": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.0.tgz", - "integrity": "sha512-wEj54PfsZ5jGSwMX68G8ZXFawcSglQSXqCftWX3ec8MDUzQdHgcKvw97awHbY0efQEL5iKUOAmmVtoYgmrSG4Q==", - "dev": true, - "requires": { - "type-detect": "4.0.8" - } - }, - "@sinonjs/formatio": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.2.2.tgz", - "integrity": "sha512-B8SEsgd8gArBLMD6zpRw3juQ2FVSsmdd7qlevyDqzS9WTCtvF55/gAL+h6gue8ZvPYcdiPdvueM/qm//9XzyTQ==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1", - "@sinonjs/samsam": "^3.1.0" - } - }, - "@sinonjs/samsam": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.3.tgz", - "integrity": "sha512-bKCMKZvWIjYD0BLGnNrxVuw4dkWCYsLqFOUWw8VgKF/+5Y+mE7LfHWPIYoDXowH+3a9LsWDMo0uAP8YDosPvHQ==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.3.0", - "array-from": "^2.1.1", - "lodash": "^4.17.15" - } - }, - "@sinonjs/text-encoding": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", - "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", - "dev": true - }, - "@sqltools/formatter": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@sqltools/formatter/-/formatter-1.2.3.tgz", - "integrity": "sha512-O3uyB/JbkAEMZaP3YqyHH7TMnex7tWyCbCI4EfJdOCoN6HIhqdJBWTM6aCCiWQ/5f5wxjgU735QAIpJbjDvmzg==" - }, - "@types/bcrypt": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-3.0.0.tgz", - "integrity": "sha512-nohgNyv+1ViVcubKBh0+XiNJ3dO8nYu///9aJ4cgSqv70gBL+94SNy/iC2NLzKPT2Zt/QavrOkBVbZRLZmw6NQ==" - }, - "@types/bcryptjs": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/@types/bcryptjs/-/bcryptjs-2.4.2.tgz", - "integrity": "sha512-LiMQ6EOPob/4yUL66SZzu6Yh77cbzJFYll+ZfaPiPPFswtIlA/Fs1MzdKYA7JApHU49zQTbJGX3PDmCpIdDBRQ==" - }, - "@types/body-parser": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.17.0.tgz", - "integrity": "sha1-n1ydm9BLtUvjLV65/A2Ml05s9Yw=", - "requires": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "@types/bull": { - "version": "3.10.2", - "resolved": "https://registry.npmjs.org/@types/bull/-/bull-3.10.2.tgz", - "integrity": "sha512-h4tSMobjXRRcyQiEou/evWsxXZOVfYr4ee1dnsdK/XRdhECQm9m2+fxm6I3oH2R9rWTlu4xj9cQuwd74szSKLA==", - "dev": true, - "requires": { - "@types/ioredis": "*" - } - }, - "@types/connect": { - "version": "3.4.32", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.32.tgz", - "integrity": "sha512-4r8qa0quOvh7lGD0pre62CAb1oni1OO6ecJLGCezTmhQ8Fz50Arx9RUszryR8KlgK6avuSXvviL6yWyViQABOg==", - "requires": { - "@types/node": "*" - } - }, - "@types/express": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.16.1.tgz", - "integrity": "sha512-V0clmJow23WeyblmACoxbHBu2JKlE5TiIme6Lem14FnPW9gsttyHtk6wq7njcdIWH1njAaFgR8gW09lgY98gQg==", - "requires": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "*", - "@types/serve-static": "*" - } - }, - "@types/express-fileupload": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@types/express-fileupload/-/express-fileupload-1.1.0.tgz", - "integrity": "sha512-l7ElHOlTt3Dis1My3LvEwP4tDw/cYiM1sor5nQY8aRm8HPVwalG48lf7ym9k2/z/PwRGADABGgIhv0a6y7XzoA==", - "requires": { - "@types/express": "*" - } - }, - "@types/express-serve-static-core": { - "version": "4.16.3", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.16.3.tgz", - "integrity": "sha512-HFgBmRDTvdnrRFXqBr2NM2NUCu6fIpzJsUTlRVENF8lxvstof7cl9Fxfwq5S0kJbO/FsPVcjlxpOM3ZxIkn7Rw==", - "requires": { - "@types/node": "*", - "@types/range-parser": "*" - } - }, - "@types/express-session": { - "version": "1.15.12", - "resolved": "https://registry.npmjs.org/@types/express-session/-/express-session-1.15.12.tgz", - "integrity": "sha512-DHZXzWy6Nu5Ng0syXUiVFRpZ6/1DOXoTCWa6RG3itGrub2ioBYvgtDbkT6VHHNo3iOdHRROyWANsMBJVaflblQ==", - "requires": { - "@types/express": "*", - "@types/node": "*" - } - }, - "@types/ioredis": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/@types/ioredis/-/ioredis-4.0.13.tgz", - "integrity": "sha512-3GKQUu5DPIlERomUfhxeLZHbwY3KOANSuCu7iEcFEuCh7pzO5gnLjU4BoBJvy+uQ3TkduU8DLzJIB2iS4d4IAw==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=" - }, - "@types/mime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.1.tgz", - "integrity": "sha512-FwI9gX75FgVBJ7ywgnq/P7tw+/o1GUbtP0KzbtusLigAOgIgNISRK0ZPl4qertvXSIE8YbsVJueQ90cDt9YYyw==" - }, - "@types/mocha": { - "version": "5.2.6", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.6.tgz", - "integrity": "sha512-1axi39YdtBI7z957vdqXI4Ac25e7YihYQtJa+Clnxg1zTJEaIRbndt71O3sP4GAMgiAm0pY26/b9BrY4MR/PMw==", - "dev": true - }, - "@types/node": { - "version": "8.10.45", - "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.45.tgz", - "integrity": "sha512-tGVTbA+i3qfXsLbq9rEq/hezaHY55QxQLeXQL2ejNgFAxxrgu8eMmYIOsRcl7hN1uTLVsKOOYacV/rcJM3sfgQ==" - }, - "@types/range-parser": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz", - "integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==" - }, - "@types/serve-static": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.2.tgz", - "integrity": "sha1-9axNemQgqZpqRa9HGfTc2M2Qekg=", - "requires": { - "@types/express-serve-static-core": "*", - "@types/mime": "*" - } - }, - "@types/zen-observable": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/@types/zen-observable/-/zen-observable-0.8.3.tgz", - "integrity": "sha512-fbF6oTd4sGGy0xjHPKAt+eS2CrxJ3+6gQ3FGcBoIJR2TLAyCkCyI8JqZNy+FeON0AhVgNJoUumVoZQjBFUqHkw==" - }, - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true - }, - "accepts": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.6.tgz", - "integrity": "sha512-QsaoUD2dpVpjENy8JFpQnXP9vyzoZPmAoKrE3S6HtSB7qzSebkJNnmdY4p004FQUSSiHXPueENpoeuUW/7a8Ig==", - "requires": { - "mime-types": "~2.1.24", - "negotiator": "0.6.1" - } - }, - "ajv": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", - "integrity": "sha1-kNDVRDnaWHzX6EO/twRfUL0ivfE=", - "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ansi-align": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz", - "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=", - "dev": true, - "requires": { - "string-width": "^2.0.0" - } - }, - "ansi-colors": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", - "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", - "dev": true - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "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==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" - }, - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, - "app-root-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-3.0.0.tgz", - "integrity": "sha512-qMcx+Gy2UZynHjOHOIXPNvpf+9cjvk3cWrBBK7zg4gH9+clobJRb9NGzcT7mQTcV/6Gm/1WelUtqxVXnNlrwcw==" - }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true - }, - "are-we-there-yet": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", - "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", - "dev": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true - }, - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" - }, - "array-from": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz", - "integrity": "sha1-z+nYwmYoudxa7MYqn12PHzUsEZU=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" - }, - "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" - }, - "assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==" - }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true - }, - "async-each": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", - "dev": true - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true - }, - "aws-sdk": { - "version": "2.1135.0", - "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1135.0.tgz", - "integrity": "sha512-bl9n4QgrEh52hmQ+Jo76BgJXM/p+PwfVZvImEQHFeel/33H/PDLcTJquEw5bzxM1HRNI24iH+FNPwyWLMrttTw==", - "requires": { - "buffer": "4.9.2", - "events": "1.1.1", - "ieee754": "1.1.13", - "jmespath": "0.16.0", - "querystring": "0.2.0", - "sax": "1.2.1", - "url": "0.10.3", - "uuid": "3.3.2", - "xml2js": "0.4.19" - } - }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" - }, - "aws4": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", - "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" - }, - "babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" - }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" - }, - "basic-auth": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", - "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", - "requires": { - "safe-buffer": "5.1.2" - } - }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "requires": { - "tweetnacl": "^0.14.3" - } - }, - "bcryptjs": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", - "integrity": "sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms=" - }, - "binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", - "dev": true - }, - "bindings": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.3.1.tgz", - "integrity": "sha512-i47mqjF9UbjxJhxGf+pZ6kSxrnI3wBLlnGI2ArWJ4r0VrvDS7ZYXkprq/pLaBWYq4GM0r4zdHY+NNRqEMU7uew==", - "dev": true - }, - "body-parser": { - "version": "1.18.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", - "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", - "requires": { - "bytes": "3.0.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "~1.6.3", - "iconv-lite": "0.4.23", - "on-finished": "~2.3.0", - "qs": "6.5.2", - "raw-body": "2.3.3", - "type-is": "~1.6.16" - } - }, - "boxen": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz", - "integrity": "sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==", - "dev": true, - "requires": { - "ansi-align": "^2.0.0", - "camelcase": "^4.0.0", - "chalk": "^2.0.1", - "cli-boxes": "^1.0.0", - "string-width": "^2.0.0", - "term-size": "^1.2.0", - "widest-line": "^2.0.0" - } - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "buffer": { - "version": "4.9.2", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", - "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" - } - }, - "buffer-equal-constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" - }, - "buffer-writer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", - "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==" - }, - "builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", - "dev": true - }, - "bull": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/bull/-/bull-3.15.0.tgz", - "integrity": "sha512-5+HoYZXy5tYIpWdod7Xa0nahRkN2uItfmoCqgWEokabDjD4igvfB9CHf3uPWBnXngQ8EiTlglim5IGdz4MzdvA==", - "requires": { - "cron-parser": "^2.13.0", - "debuglog": "^1.0.0", - "get-port": "^5.1.1", - "ioredis": "^4.14.1", - "lodash": "^4.17.15", - "p-timeout": "^3.2.0", - "promise.prototype.finally": "^3.1.2", - "semver": "^6.3.0", - "util.promisify": "^1.0.1", - "uuid": "^3.4.0" - }, - "dependencies": { - "cluster-key-slot": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.0.tgz", - "integrity": "sha512-2Nii8p3RwAPiFwsnZvukotvow2rIHM+yQ6ZcBXGHdniadkYGZYiGmkHJIbZPIV9nfv7m/U1IPMVVcAhoWFeklw==" - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "requires": { - "ms": "^2.1.1" - } - }, - "ioredis": { - "version": "4.17.3", - "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-4.17.3.tgz", - "integrity": "sha512-iRvq4BOYzNFkDnSyhx7cmJNOi1x/HWYe+A4VXHBu4qpwJaGT1Mp+D2bVGJntH9K/Z/GeOM/Nprb8gB3bmitz1Q==", - "requires": { - "cluster-key-slot": "^1.1.0", - "debug": "^4.1.1", - "denque": "^1.1.0", - "lodash.defaults": "^4.2.0", - "lodash.flatten": "^4.4.0", - "redis-commands": "1.5.0", - "redis-errors": "^1.2.0", - "redis-parser": "^3.0.0", - "standard-as-callback": "^2.0.1" - } - }, - "redis-commands": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.5.0.tgz", - "integrity": "sha512-6KxamqpZ468MeQC3bkWmCB1fp56XL64D4Kf0zJSwDZbVLLm7KFkoIcHrgRvQ+sk8dnhySs7+yBg94yIkAK7aJg==" - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" - } - } - }, - "busboy": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.3.1.tgz", - "integrity": "sha512-y7tTxhGKXcyBxRKAni+awqx8uqaJKrSFSNFSeRG5CsWNdmy2BIK+6VGWEW7TZnIO/533mtMEA4rOevQV815YJw==", - "requires": { - "dicer": "0.3.0" - } - }, - "byline": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/byline/-/byline-5.0.0.tgz", - "integrity": "sha1-dBxSFkaOrcRXsDQQEYrXfejB3bE=" - }, - "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" - }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - } - }, - "call-me-maybe": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", - "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=" - }, - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true - }, - "capture-stack-trace": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz", - "integrity": "sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw==", - "dev": true - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" - }, - "chai": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", - "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", - "requires": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^3.0.1", - "get-func-name": "^2.0.0", - "pathval": "^1.1.0", - "type-detect": "^4.0.5" - } - }, - "chai-as-promised": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz", - "integrity": "sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==", - "dev": true, - "requires": { - "check-error": "^1.0.2" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "check-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=" - }, - "chokidar": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.5.tgz", - "integrity": "sha512-i0TprVWp+Kj4WRPtInjexJ8Q+BqTE909VpH8xVhXrJkoc5QC8VO9TryGOqTr+2hljzc1sC62t22h5tZePodM/A==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "fsevents": "^1.2.7", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - }, - "dependencies": { - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - } - } - }, - "chownr": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.3.tgz", - "integrity": "sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw==", - "dev": true, - "optional": true - }, - "ci-info": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", - "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==", - "dev": true - }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "class-validator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.9.1.tgz", - "integrity": "sha512-3wApflrd3ywVZyx4jaasGoFt8pmo4aGLPPAEKCKCsTRWVGPilahD88q3jQjRQwja50rl9a7rsP5LAxJYwGK8/Q==", - "requires": { - "google-libphonenumber": "^3.1.6", - "validator": "10.4.0" - } - }, - "cli-boxes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz", - "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=", - "dev": true - }, - "cli-highlight": { - "version": "2.1.11", - "resolved": "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.11.tgz", - "integrity": "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==", - "requires": { - "chalk": "^4.0.0", - "highlight.js": "^10.7.1", - "mz": "^2.4.0", - "parse5": "^5.1.1", - "parse5-htmlparser2-tree-adapter": "^6.0.0", - "yargs": "^16.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "requires": { - "has-flag": "^4.0.0" - } - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" - }, - "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - } - }, - "yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==" - } - } - }, - "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "requires": { - "ansi-regex": "^5.0.1" - } - } - } - }, - "cluster-key-slot": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.0.12.tgz", - "integrity": "sha1-1d7/KlIHF7yYMTl5tocwmy02jik=" - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true - }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - } - }, - "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==", - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - }, - "combined-stream": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", - "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "commander": { - "version": "2.20.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", - "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==" - }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "configstore": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.2.tgz", - "integrity": "sha512-vtv5HtGjcYUgFrXc6Kx747B83MRRVS5R1VTEQoXvuP+kMI+if6uywV0nDGoiydJRy4yk7h9od5Og0kxx4zUXmw==", - "dev": true, - "requires": { - "dot-prop": "^4.1.0", - "graceful-fs": "^4.1.2", - "make-dir": "^1.0.0", - "unique-string": "^1.0.0", - "write-file-atomic": "^2.0.0", - "xdg-basedir": "^3.0.0" - } - }, - "console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true - }, - "content-disposition": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", - "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" - }, - "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" - }, - "cookie": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", - "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" - }, - "cookie-parser": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.4.tgz", - "integrity": "sha512-lo13tqF3JEtFO7FyA49CqbhaFkskRJ0u/UAiINgrIXeRCY41c88/zxtrECl8AKH3B0hj9q10+h3Kt8I7KlW4tw==", - "requires": { - "cookie": "0.3.1", - "cookie-signature": "1.0.6" - } - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" - }, - "cookiejar": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", - "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==", - "dev": true - }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "requires": { - "object-assign": "^4", - "vary": "^1" - } - }, - "crc": { - "version": "3.4.4", - "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.4.tgz", - "integrity": "sha1-naHpgOO9RPxck79as9ozeNheRms=" - }, - "create-error-class": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", - "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", - "dev": true, - "requires": { - "capture-stack-trace": "^1.0.0" - } - }, - "cron-parser": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-2.15.0.tgz", - "integrity": "sha512-rMFkrQw8+oG5OuwjiXesup4KeIlEG/IU82YtG4xyAHbO5jhKmYaHPp/ZNhq9+7TjSJ65E3zV3kQPUbmXSff2/g==", - "requires": { - "is-nan": "^1.3.0", - "moment-timezone": "^0.5.31" - } - }, - "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true, - "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "crypto-random-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", - "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=", - "dev": true - }, - "csv": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/csv/-/csv-5.1.1.tgz", - "integrity": "sha512-gezB9D+enrh2tLj+vsAD8JyYRMIJdSMpec/Pgbb+7YRj6Q6/D12HLSwjhx+CrirRT4dESjZYXWX1JfqlV4RlTA==", - "requires": { - "csv-generate": "^3.2.0", - "csv-parse": "^4.3.0", - "csv-stringify": "^5.1.2", - "stream-transform": "^1.0.8" - } - }, - "csv-generate": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/csv-generate/-/csv-generate-3.2.3.tgz", - "integrity": "sha512-IcR3K0Nx+nJAkcU2eAglVR7DuHnxcuhUM2w2cR+aHOW7bZp2S5LyN2HF3zTkp6BV/DjR6ykoKznUm+AjnWcOKg==" - }, - "csv-parse": { - "version": "4.4.6", - "resolved": "https://registry.npmjs.org/csv-parse/-/csv-parse-4.4.6.tgz", - "integrity": "sha512-VisC5TBBhOF+70zjrF9FOiqI2LZOhXK/vAWlOrqyqz3lLa+P8jzJ7L/sg90MHmkSY/brAXWwrmGSZR0tM5yi4g==" - }, - "csv-stringify": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/csv-stringify/-/csv-stringify-5.3.0.tgz", - "integrity": "sha512-VMYPbE8zWz475smwqb9VbX9cj0y4J0PBl59UdcqzLkzXHZZ8dh4Rmbb0ZywsWEtUml4A96Hn7Q5MW9ppVghYzg==", - "requires": { - "lodash.get": "~4.4.2" - } - }, - "d": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", - "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", - "dev": true, - "requires": { - "es5-ext": "^0.10.9" - } - }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "requires": { - "assert-plus": "^1.0.0" - } - }, - "date-fns": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz", - "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==" - }, - "date-fns-timezone": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/date-fns-timezone/-/date-fns-timezone-0.1.4.tgz", - "integrity": "sha512-npnZn1eIeHV8A3Hqw86mn6CjH+qMe0TSCs4anpD4Rouf+mE9eIJuaHviIpNmGL9GiDmcUoiaKdkX5ihf+yZQZA==", - "requires": { - "date-fns": "^1.29.0", - "timezone-support": "^1.5.5" - } - }, - "dateformat": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", - "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==" - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } - } - }, - "debuglog": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/debuglog/-/debuglog-1.0.1.tgz", - "integrity": "sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI=" - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true - }, - "deep-eql": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", - "requires": { - "type-detect": "^4.0.0" - } - }, - "deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true - }, - "deepmerge": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz", - "integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==" - }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "requires": { - "object-keys": "^1.0.12" - } - }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" - }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", - "dev": true - }, - "denque": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz", - "integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ==" - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" - }, - "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" - }, - "detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", - "dev": true - }, - "dicer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.3.0.tgz", - "integrity": "sha512-MdceRRWqltEG2dZqO769g27N/3PXfcKl04VhYnBlo2YhH7zPi88VebsjTKclaOyiuMaGU72hTfw3VkUitGcVCA==", - "requires": { - "streamsearch": "0.1.2" - } - }, - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==" - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "requires": { - "esutils": "^2.0.2" - } - }, - "dot-prop": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.1.tgz", - "integrity": "sha512-l0p4+mIuJIua0mhxGoh4a+iNL9bmeK5DvnSVQa6T0OhrVmaEa1XScX5Etc673FePCJOArq/4Pa2cLGODUWTPOQ==", - "dev": true, - "requires": { - "is-obj": "^1.0.0" - } - }, - "dotenv": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", - "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==" - }, - "duplexer3": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", - "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", - "dev": true - }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" - }, - "end-of-stream": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", - "integrity": "sha1-7SljTRm6ukY7bOa4CjchPqtx7EM=", - "requires": { - "once": "^1.4.0" - } - }, - "error-stack-parser": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.0.4.tgz", - "integrity": "sha512-fZ0KkoxSjLFmhW5lHbUT3tLwy3nX1qEzMYo8koY1vrsAco53CMT1djnBSeC/wUjTEZRhZl9iRw7PaMaxfJ4wzQ==", - "requires": { - "stackframe": "^1.1.0" - } - }, - "es-abstract": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", - "integrity": "sha1-rIYUX91QmdjdSVWMy6Lq+biOJOk=", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.0", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "is-callable": "^1.1.4", - "is-regex": "^1.0.4", - "object-keys": "^1.0.12" - } - }, - "es-to-primitive": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", - "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "es5-ext": { - "version": "0.10.50", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.50.tgz", - "integrity": "sha1-bQ4joKvbJwGOWsT9CbQSvFUXp3g=", - "dev": true, - "requires": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.1", - "next-tick": "^1.0.0" - } - }, - "es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "es6-map": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", - "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14", - "es6-iterator": "~2.0.1", - "es6-set": "~0.1.5", - "es6-symbol": "~3.1.1", - "event-emitter": "~0.3.5" - } - }, - "es6-set": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", - "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14", - "es6-iterator": "~2.0.1", - "es6-symbol": "3.1.1", - "event-emitter": "~0.3.5" - } - }, - "es6-symbol": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", - "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14" - } - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" - }, - "esutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" - }, - "event-emitter": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14" - } - }, - "events": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", - "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=" - }, - "execa": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", - "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", - "dev": true, - "requires": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "express": { - "version": "4.16.4", - "resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz", - "integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==", - "requires": { - "accepts": "~1.3.5", - "array-flatten": "1.1.1", - "body-parser": "1.18.3", - "content-disposition": "0.5.2", - "content-type": "~1.0.4", - "cookie": "0.3.1", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.1.1", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.2", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.4", - "qs": "6.5.2", - "range-parser": "~1.2.0", - "safe-buffer": "5.1.2", - "send": "0.16.2", - "serve-static": "1.13.2", - "setprototypeof": "1.1.0", - "statuses": "~1.4.0", - "type-is": "~1.6.16", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - } - }, - "express-fileupload": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/express-fileupload/-/express-fileupload-1.3.1.tgz", - "integrity": "sha512-LD1yabD3exmWIFujKGDnT1rmxSomaqQSlUvzIsrA1ZgwCJ6ci7lg2YHFGM3Q6DfK+Yk0gAVU7GWLE7qDMwZLkw==", - "requires": { - "busboy": "^0.3.1" - } - }, - "express-session": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.15.6.tgz", - "integrity": "sha512-r0nrHTCYtAMrFwZ0kBzZEXa1vtPVrw0dKvGSrKP4dahwBQ1BJpF2/y1Pp4sCD/0kvxV4zZeclyvfmw0B4RMJQA==", - "requires": { - "cookie": "0.3.1", - "cookie-signature": "1.0.6", - "crc": "3.4.4", - "debug": "2.6.9", - "depd": "~1.1.1", - "on-headers": "~1.0.1", - "parseurl": "~1.3.2", - "uid-safe": "~2.1.5", - "utils-merge": "1.0.1" - } - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" - }, - "faker": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/faker/-/faker-4.1.0.tgz", - "integrity": "sha1-HkW7vsxndLPBlfrSg1EJxtdIzD8=", - "dev": true - }, - "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" - }, - "fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" - }, - "fengari": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/fengari/-/fengari-0.1.4.tgz", - "integrity": "sha512-6ujqUuiIYmcgkGz8MGAdERU57EIluGGPSUgGPTsco657EHa+srq0S3/YUl/r9kx1+D+d4rGfYObd+m8K22gB1g==", - "dev": true, - "requires": { - "readline-sync": "^1.4.9", - "sprintf-js": "^1.1.1", - "tmp": "^0.0.33" - }, - "dependencies": { - "sprintf-js": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", - "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", - "dev": true - } - } - }, - "fengari-interop": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/fengari-interop/-/fengari-interop-0.1.2.tgz", - "integrity": "sha512-8iTvaByZVoi+lQJhHH9vC+c/Yaok9CwOqNQZN6JrVpjmWwW4dDkeblBXhnHC+BoI6eF4Cy5NKW3z6ICEjvgywQ==", - "dev": true - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "finalhandler": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", - "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.2", - "statuses": "~1.4.0", - "unpipe": "~1.0.0" - } - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "flash": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/flash/-/flash-1.1.0.tgz", - "integrity": "sha1-irKyntO2ilz7Gom/mOf2nX8aAgo=" - }, - "flat": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", - "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", - "dev": true, - "requires": { - "is-buffer": "~2.0.3" - }, - "dependencies": { - "is-buffer": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", - "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==", - "dev": true - } - } - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" - }, - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "formidable": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.1.tgz", - "integrity": "sha512-Fs9VRguL0gqGHkXS5GQiMCr1VhZBxz0JnJs4JmMp/2jL18Fmbzvv7vOFRU+U8TBkHEE/CX1qDXzJplVULgsLeg==", - "dev": true - }, - "forwarded": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" - }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "requires": { - "map-cache": "^0.2.2" - } - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" - }, - "fs-minipass": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", - "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", - "dev": true, - "requires": { - "minipass": "^2.6.0" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "fsevents": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.8.tgz", - "integrity": "sha512-tPvHgPGB7m40CZ68xqFGkKuzN+RnpGmSV+hgeKxhRpbxdqKXUFJGC3yonBOLzQBcJyGpdZFDfCsdOC2KFsXzeA==", - "dev": true, - "optional": true, - "requires": { - "nan": "^2.12.1", - "node-pre-gyp": "^0.12.0" - }, - "dependencies": { - "abbrev": { - "version": "1.1.1", - "resolved": false, - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": false, - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "aproba": { - "version": "1.2.0", - "resolved": false, - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.5", - "resolved": false, - "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", - "dev": true, - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "balanced-match": { - "version": "1.0.0", - "resolved": false, - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": false, - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "code-point-at": { - "version": "1.1.0", - "resolved": false, - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": false, - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "console-control-strings": { - "version": "1.1.0", - "resolved": false, - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true - }, - "core-util-is": { - "version": "1.0.2", - "resolved": false, - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true, - "optional": true - }, - "debug": { - "version": "4.1.1", - "resolved": false, - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "optional": true, - "requires": { - "ms": "^2.1.1" - } - }, - "deep-extend": { - "version": "0.6.0", - "resolved": false, - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true, - "optional": true - }, - "delegates": { - "version": "1.0.0", - "resolved": false, - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", - "dev": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.3", - "resolved": false, - "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", - "dev": true, - "optional": true - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": false, - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true, - "optional": true - }, - "gauge": { - "version": "2.7.4", - "resolved": false, - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "dev": true, - "optional": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "glob": { - "version": "7.1.3", - "resolved": false, - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "dev": true, - "optional": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-unicode": { - "version": "2.0.1", - "resolved": false, - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", - "dev": true, - "optional": true - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": false, - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ignore-walk": { - "version": "3.0.1", - "resolved": false, - "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", - "dev": true, - "optional": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "inflight": { - "version": "1.0.6", - "resolved": false, - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "optional": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": false, - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, - "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": false, - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": false, - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true, - "optional": true - }, - "minimatch": { - "version": "3.0.4", - "resolved": false, - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "ms": { - "version": "2.1.1", - "resolved": false, - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true, - "optional": true - }, - "needle": { - "version": "2.3.0", - "resolved": false, - "integrity": "sha512-QBZu7aAFR0522EyaXZM0FZ9GLpq6lvQ3uq8gteiDUp7wKdy0lSd2hPlgFwVuW1CBkfEs9PfDQsQzZghLs/psdg==", - "dev": true, - "optional": true, - "requires": { - "debug": "^4.1.0", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - } - }, - "node-pre-gyp": { - "version": "0.12.0", - "resolved": false, - "integrity": "sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A==", - "dev": true, - "optional": true, - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.1", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4" - } - }, - "nopt": { - "version": "4.0.1", - "resolved": false, - "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", - "dev": true, - "optional": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "npm-bundled": { - "version": "1.0.6", - "resolved": false, - "integrity": "sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g==", - "dev": true, - "optional": true - }, - "npm-packlist": { - "version": "1.4.1", - "resolved": false, - "integrity": "sha512-+TcdO7HJJ8peiiYhvPxsEDhF3PJFGUGRcFsGve3vxvxdcpO2Z4Z7rkosRM0kWj6LfbK/P0gu3dzk5RU1ffvFcw==", - "dev": true, - "optional": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" - } - }, - "npmlog": { - "version": "4.1.2", - "resolved": false, - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "dev": true, - "optional": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": false, - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": false, - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "resolved": false, - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "os-homedir": { - "version": "1.0.2", - "resolved": false, - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": false, - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true, - "optional": true - }, - "osenv": { - "version": "0.1.5", - "resolved": false, - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "dev": true, - "optional": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": false, - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "2.0.0", - "resolved": false, - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", - "dev": true, - "optional": true - }, - "rc": { - "version": "1.2.8", - "resolved": false, - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, - "optional": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true, - "optional": true - } - } - }, - "readable-stream": { - "version": "2.3.6", - "resolved": false, - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "optional": true, - "requires": { - "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" - } - }, - "rimraf": { - "version": "2.6.3", - "resolved": false, - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "optional": true, - "requires": { - "glob": "^7.1.3" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": false, - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": false, - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true, - "optional": true - }, - "sax": { - "version": "1.2.4", - "resolved": false, - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", - "dev": true, - "optional": true - }, - "semver": { - "version": "5.7.0", - "resolved": false, - "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", - "dev": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "resolved": false, - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "resolved": false, - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", - "dev": true, - "optional": true - }, - "string-width": { - "version": "1.0.2", - "resolved": false, - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": false, - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": false, - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": false, - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true, - "optional": true - }, - "tar": { - "version": "4.4.13", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", - "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", - "dev": true, - "optional": true, - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.8.6", - "minizlib": "^1.2.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.3" - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": false, - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true, - "optional": true - }, - "wide-align": { - "version": "1.1.3", - "resolved": false, - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, - "optional": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": false, - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - } - } - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "dev": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - }, - "dependencies": { - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - } - } - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" - }, - "get-func-name": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=" - }, - "get-port": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz", - "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==" - }, - "get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true - }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true - }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "requires": { - "assert-plus": "^1.0.0" - } - }, - "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha1-OWCDLT8VdBCDQtr9OmezMsCWnfE=", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - } - }, - "global-dirs": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", - "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", - "dev": true, - "requires": { - "ini": "^1.3.4" - } - }, - "google-libphonenumber": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/google-libphonenumber/-/google-libphonenumber-3.2.2.tgz", - "integrity": "sha1-PZ17pyfpmlCBLyGw7TE3I7dsXFQ=" - }, - "got": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz", - "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=", - "dev": true, - "requires": { - "create-error-class": "^3.0.0", - "duplexer3": "^0.1.4", - "get-stream": "^3.0.0", - "is-redirect": "^1.0.0", - "is-retry-allowed": "^1.0.0", - "is-stream": "^1.0.0", - "lowercase-keys": "^1.0.0", - "safe-buffer": "^5.0.1", - "timed-out": "^4.0.0", - "unzip-response": "^2.0.1", - "url-parse-lax": "^1.0.0" - } - }, - "graceful-fs": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", - "integrity": "sha1-/7cD4QZuig7qpMi4C6klPu77+wA=", - "dev": true - }, - "growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true - }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" - }, - "har-validator": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", - "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", - "requires": { - "ajv": "^6.5.5", - "har-schema": "^2.0.0" - } - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "has-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", - "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=" - }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", - "dev": true - }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, - "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "dependencies": { - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true - }, - "highlight.js": { - "version": "10.7.3", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", - "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==" - }, - "homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "requires": { - "parse-passwd": "^1.0.0" - } - }, - "http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - } - }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, - "iconv-lite": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", - "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ieee754": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" - }, - "ignore-by-default": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", - "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=", - "dev": true - }, - "ignore-walk": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.4.tgz", - "integrity": "sha512-PY6Ii8o1jMRA1z4F2hRkH/xN59ox43DavKvD3oDpfurRlOJyAHpifIwpbdv1n4jt4ov0jSpw3kQ4GhJnpBL6WQ==", - "dev": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "import-lazy": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", - "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", - "dev": true - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, - "ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "ioredis": { - "version": "4.9.3", - "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-4.9.3.tgz", - "integrity": "sha512-17BjBQ4cdUY8hxIvcpvxohH8uZ93/I2pi2CsdgbgXV1oYFiLOLpQASNmtZUsysxTwiF2Dcld7YgqJymNQsAdwA==", - "requires": { - "cluster-key-slot": "^1.0.6", - "debug": "^3.1.0", - "denque": "^1.1.0", - "lodash.defaults": "^4.2.0", - "lodash.flatten": "^4.4.0", - "redis-commands": "1.4.0", - "redis-errors": "^1.2.0", - "redis-parser": "^3.0.0", - "standard-as-callback": "^2.0.1" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha1-6D0X3hbYp++3cX7b5fsQE17uYps=", - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "ioredis-mock": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/ioredis-mock/-/ioredis-mock-4.9.0.tgz", - "integrity": "sha512-J2GmJg01175o8TleL0OhoXPYTXffN2g1lmVc+0M22f6XPwnsQpQzLeGpcVJlwn1awYgqaCxIRpFq8snUvaQ33Q==", - "dev": true, - "requires": { - "array-from": "^2.1.1", - "es6-map": "^0.1.5", - "es6-set": "^0.1.5", - "fengari": "^0.1.4", - "fengari-interop": "^0.1.2", - "lodash": "^4.17.4", - "minimatch": "^3.0.4", - "object-assign": "^4.1.1", - "standard-as-callback": "^2.0.0" - } - }, - "ipaddr.js": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", - "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==" - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "requires": { - "binary-extensions": "^1.0.0" - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-callable": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", - "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", - "dev": true - }, - "is-ci": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz", - "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==", - "dev": true, - "requires": { - "ci-info": "^1.5.0" - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-date-object": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", - "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=" - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - }, - "is-installed-globally": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz", - "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=", - "dev": true, - "requires": { - "global-dirs": "^0.1.0", - "is-path-inside": "^1.0.0" - } - }, - "is-nan": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.0.tgz", - "integrity": "sha512-z7bbREymOqt2CCaZVly8aC4ML3Xhfi0ekuOnjO2L8vKdl+CttdVoGZQhd4adMFAsxQ5VeRVwORs4tU8RH+HFtQ==", - "requires": { - "define-properties": "^1.1.3" - } - }, - "is-npm": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz", - "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ=", - "dev": true - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", - "dev": true - }, - "is-path-inside": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", - "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", - "dev": true, - "requires": { - "path-is-inside": "^1.0.1" - } - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "is-redirect": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", - "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=", - "dev": true - }, - "is-regex": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", - "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", - "dev": true, - "requires": { - "has": "^1.0.1" - } - }, - "is-retry-allowed": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", - "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=", - "dev": true - }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true - }, - "is-symbol": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", - "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", - "requires": { - "has-symbols": "^1.0.0" - } - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "iserror": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/iserror/-/iserror-0.0.2.tgz", - "integrity": "sha1-vVNFH+L2aLnyQCwZZnh6qix8C/U=" - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" - }, - "jmespath": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz", - "integrity": "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==" - }, - "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", - "dev": true - }, - "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" - }, - "json-schema-ref-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/json-schema-ref-parser/-/json-schema-ref-parser-7.1.0.tgz", - "integrity": "sha512-eP9+39HimQUpmqEUHRpV+oh8hiVMRU2tD6H+8uDc0raCQxX6jARN4nSJe5OpAtPt7eObuIUIsW7AwvGBzCHavQ==", - "requires": { - "call-me-maybe": "^1.0.1", - "js-yaml": "^3.13.1", - "ono": "^5.0.1" - } - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" - }, - "json2csv": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/json2csv/-/json2csv-4.5.3.tgz", - "integrity": "sha512-tg5sm25TOwgMsPUixPFmmuOUFtVCj4p57XipoE8gi/ejNftce/0d8LBgWnCkjF4HsLDsFzszdbIEV6mnK0WfNg==", - "requires": { - "commander": "^2.15.1", - "jsonparse": "^1.3.1", - "lodash.get": "^4.4.2" - } - }, - "json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "requires": { - "minimist": "^1.2.0" - } - }, - "jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=" - }, - "jsonwebtoken": { - "version": "8.5.1", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", - "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", - "requires": { - "jws": "^3.2.2", - "lodash.includes": "^4.3.0", - "lodash.isboolean": "^3.0.3", - "lodash.isinteger": "^4.0.4", - "lodash.isnumber": "^3.0.3", - "lodash.isplainobject": "^4.0.6", - "lodash.isstring": "^4.0.1", - "lodash.once": "^4.0.0", - "ms": "^2.1.1", - "semver": "^5.6.0" - } - }, - "jsprim": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", - "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - }, - "dependencies": { - "json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" - } - } - }, - "just-extend": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.1.0.tgz", - "integrity": "sha512-ApcjaOdVTJ7y4r08xI5wIqpvwS48Q0PBG4DJROcEkH1f8MdAiNFyFxz3xoL0LWAVwjrwPYZdVHHxhRHcx/uGLA==", - "dev": true - }, - "jwa": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", - "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", - "requires": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", - "requires": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - }, - "latest-version": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz", - "integrity": "sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=", - "dev": true, - "requires": { - "package-json": "^4.0.0" - } - }, - "libxmljs": { - "version": "0.19.7", - "resolved": "https://registry.npmjs.org/libxmljs/-/libxmljs-0.19.7.tgz", - "integrity": "sha512-lFJyG9T1mVwTzNTw6ZkvIt0O+NsIR+FTE+RcC2QDFGU8YMnQrnyEOGrj6HWSe1AdwQK7s37BOp4NL+pcAqfK2g==", - "dev": true, - "requires": { - "bindings": "~1.3.0", - "nan": "~2.14.0", - "node-pre-gyp": "~0.11.0" - }, - "dependencies": { - "nan": { - "version": "2.14.2", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", - "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==", - "dev": true - } - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "lodash.defaults": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=" - }, - "lodash.flatten": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=" - }, - "lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" - }, - "lodash.includes": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", - "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=" - }, - "lodash.isboolean": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", - "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" - }, - "lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" - }, - "lodash.isinteger": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", - "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=" - }, - "lodash.isnumber": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", - "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=" - }, - "lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" - }, - "lodash.isstring": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" - }, - "lodash.once": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" - }, - "log-symbols": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", - "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", - "dev": true, - "requires": { - "chalk": "^2.0.1" - } - }, - "lolex": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-4.2.0.tgz", - "integrity": "sha512-gKO5uExCXvSm6zbF562EvM+rd1kQDnB9AZBbiQVzf1ZmdDpxUSvpnAaVOP83N/31mRK8Ml8/VE8DMvsAZQ+7wg==", - "dev": true - }, - "lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", - "dev": true - }, - "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - }, - "dependencies": { - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - } - } - }, - "make-dir": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", - "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", - "dev": true, - "requires": { - "pify": "^3.0.0" - } - }, - "make-error": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz", - "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==" - }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "requires": { - "object-visit": "^1.0.0" - } - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" - }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, - "mime": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", - "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" - }, - "mime-db": { - "version": "1.40.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", - "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==" - }, - "mime-types": { - "version": "2.1.24", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", - "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", - "requires": { - "mime-db": "1.40.0" - } - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" - }, - "minipass": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", - "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", - "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", - "dev": true, - "requires": { - "minipass": "^2.9.0" - } - }, - "mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "dev": true, - "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "requires": { - "minimist": "^1.2.5" - } - }, - "mocha": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.3.tgz", - "integrity": "sha512-0R/3FvjIGH3eEuG17ccFPk117XL2rWxatr81a57D+r/x2uTYZRbdZ4oVidEUMh2W2TJDa7MdAb12Lm2/qrKajg==", - "dev": true, - "requires": { - "ansi-colors": "3.2.3", - "browser-stdout": "1.3.1", - "debug": "3.2.6", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "find-up": "3.0.0", - "glob": "7.1.3", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "3.13.1", - "log-symbols": "2.2.0", - "minimatch": "3.0.4", - "mkdirp": "0.5.4", - "ms": "2.1.1", - "node-environment-flags": "1.0.5", - "object.assign": "4.1.0", - "strip-json-comments": "2.0.1", - "supports-color": "6.0.0", - "which": "1.3.1", - "wide-align": "1.1.3", - "yargs": "13.3.2", - "yargs-parser": "13.1.2", - "yargs-unparser": "1.6.0" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "mkdirp": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.4.tgz", - "integrity": "sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "supports-color": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", - "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "moment": { - "version": "2.29.3", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.3.tgz", - "integrity": "sha512-c6YRvhEo//6T2Jz/vVtYzqBzwvPT95JBQ+smCytzf7c50oMZRsR/a4w88aD34I+/QVSfnoAnSBFPJHItlOMJVw==" - }, - "moment-timezone": { - "version": "0.5.31", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.31.tgz", - "integrity": "sha512-+GgHNg8xRhMXfEbv81iDtrVeTcWt0kWmTEY1XQK14dICTXnWJnT0dxdlPspwqF3keKMVPXwayEsk1DI0AA/jdA==", - "requires": { - "moment": ">= 2.9.0" - } - }, - "morgan": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.9.1.tgz", - "integrity": "sha512-HQStPIV4y3afTiCYVxirakhlCfGkI161c76kKFca7Fk1JusM//Qeo1ej2XaMniiNeaZklMVrh3vTtIzpzwbpmA==", - "requires": { - "basic-auth": "~2.0.0", - "debug": "2.6.9", - "depd": "~1.1.2", - "on-finished": "~2.3.0", - "on-headers": "~1.0.1" - } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" - }, - "mz": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "requires": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, - "nan": { - "version": "2.13.2", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.13.2.tgz", - "integrity": "sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw==", - "dev": true, - "optional": true - }, - "nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - } - }, - "needle": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/needle/-/needle-2.9.1.tgz", - "integrity": "sha512-6R9fqJ5Zcmf+uYaFgdIHmLwNldn5HbK8L5ybn7Uz+ylX/rnOsSp1AHcvQSrCaFN+qNM1wpymHqD7mVasEOlHGQ==", - "dev": true, - "requires": { - "debug": "^3.2.6", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", - "dev": true - } - } - }, - "negotiator": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", - "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" - }, - "next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", - "dev": true - }, - "nise": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/nise/-/nise-1.5.3.tgz", - "integrity": "sha512-Ymbac/94xeIrMf59REBPOv0thr+CJVFMhrlAkW/gjCIE58BGQdCj0x7KRCb3yz+Ga2Rz3E9XXSvUyyxqqhjQAQ==", - "dev": true, - "requires": { - "@sinonjs/formatio": "^3.2.1", - "@sinonjs/text-encoding": "^0.7.1", - "just-extend": "^4.0.2", - "lolex": "^5.0.1", - "path-to-regexp": "^1.7.0" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "lolex": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-5.1.2.tgz", - "integrity": "sha512-h4hmjAvHTmd+25JSwrtTIuwbKdwg5NzZVRMLn9saij4SZaepCrTCxPr35H/3bjwfMJtN+t3CX8672UIkglz28A==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.7.0" - } - }, - "path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", - "dev": true, - "requires": { - "isarray": "0.0.1" - } - } - } - }, - "node-environment-flags": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz", - "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==", - "dev": true, - "requires": { - "object.getownpropertydescriptors": "^2.0.3", - "semver": "^5.7.0" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "requires": { - "whatwg-url": "^5.0.0" - } - }, - "node-pre-gyp": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.11.0.tgz", - "integrity": "sha512-TwWAOZb0j7e9eGaf9esRx3ZcLaE5tQ2lvYy1pb5IAaG1a2e2Kv5Lms1Y4hpj+ciXJRofIxxlt5haeQ/2ANeE0Q==", - "dev": true, - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.1", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4" - }, - "dependencies": { - "nopt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", - "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", - "dev": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - } - } - }, - "nodemon": { - "version": "1.18.10", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-1.18.10.tgz", - "integrity": "sha512-we51yBb1TfEvZamFchRgcfLbVYgg0xlGbyXmOtbBzDwxwgewYS/YbZ5tnlnsH51+AoSTTsT3A2E/FloUbtH8cQ==", - "dev": true, - "requires": { - "chokidar": "^2.1.0", - "debug": "^3.1.0", - "ignore-by-default": "^1.0.1", - "minimatch": "^3.0.4", - "pstree.remy": "^1.1.6", - "semver": "^5.5.0", - "supports-color": "^5.2.0", - "touch": "^3.1.0", - "undefsafe": "^2.0.2", - "update-notifier": "^2.5.0" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha1-6D0X3hbYp++3cX7b5fsQE17uYps=", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "nopt": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", - "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", - "dev": true, - "requires": { - "abbrev": "1" - } - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, - "npm-bundled": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.2.tgz", - "integrity": "sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ==", - "dev": true, - "requires": { - "npm-normalize-package-bin": "^1.0.1" - } - }, - "npm-normalize-package-bin": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", - "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==", - "dev": true - }, - "npm-packlist": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz", - "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==", - "dev": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1", - "npm-normalize-package-bin": "^1.0.1" - } - }, - "npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true, - "requires": { - "path-key": "^2.0.0" - } - }, - "npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "dev": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, - "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "object-inspect": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", - "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==" - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" - }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "requires": { - "isobject": "^3.0.0" - } - }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - } - }, - "object.getownpropertydescriptors": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", - "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.5.1" - } - }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "requires": { - "ee-first": "1.1.1" - } - }, - "on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "requires": { - "wrappy": "1" - } - }, - "ono": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ono/-/ono-5.0.1.tgz", - "integrity": "sha512-4/4BPGHX8OuDDNx1SrOqTOI7zajPjvBvrG1jDG3hDq4qBpoKlzG2d83Vdz26hvv0FFWYsLdHf+1Vu/k2d8Ww9w==" - }, - "openapi-schemas": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/openapi-schemas/-/openapi-schemas-1.0.0.tgz", - "integrity": "sha512-KYy5vRmutd8ieqZQKWDAFEa7xiLXLkdWZljwLgxJV/5ydJqRIE9hMG5n9jTYtP5+fuZ3NhIYk2wIa+BCDoQpwg==" - }, - "openapi-types": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-1.3.5.tgz", - "integrity": "sha512-11oi4zYorsgvg5yBarZplAqbpev5HkuVNPlZaPTknPDzAynq+lnJdXAmruGWP0s+dNYZS7bjM+xrTpJw7184Fg==" - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true - }, - "osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "dev": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" - }, - "p-limit": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", - "integrity": "sha1-QXyZQeYCepq8ulCS3SkE4lW1+8I=", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-timeout": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", - "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", - "requires": { - "p-finally": "^1.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "package-json": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-4.0.1.tgz", - "integrity": "sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=", - "dev": true, - "requires": { - "got": "^6.7.1", - "registry-auth-token": "^3.0.1", - "registry-url": "^3.0.3", - "semver": "^5.1.0" - } - }, - "packet-reader": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", - "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" - }, - "parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=" - }, - "parse5": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", - "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==" - }, - "parse5-htmlparser2-tree-adapter": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", - "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", - "requires": { - "parse5": "^6.0.1" - }, - "dependencies": { - "parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" - } - } - }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" - }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true - }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" - }, - "path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true - }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" - }, - "pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==" - }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, - "pg": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/pg/-/pg-7.9.0.tgz", - "integrity": "sha512-GkzteBFpsIoIBCSuomqik3IGvhqAtTr32jclR24RmUg170Jrn6ypwR97YalFHrsE1iaW8T0aAH13dmij8QUQ0g==", - "requires": { - "buffer-writer": "2.0.0", - "packet-reader": "1.0.0", - "pg-connection-string": "0.1.3", - "pg-pool": "^2.0.4", - "pg-types": "~2.0.0", - "pgpass": "1.x", - "semver": "4.3.2" - }, - "dependencies": { - "semver": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.2.tgz", - "integrity": "sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c=" - } - } - }, - "pg-connection-string": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-0.1.3.tgz", - "integrity": "sha1-2hhHsglA5C7hSSvq9l1J2RskXfc=" - }, - "pg-hstore": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/pg-hstore/-/pg-hstore-2.3.2.tgz", - "integrity": "sha1-9+8FPnubiSrphq8vfL6GQy388k8=", - "requires": { - "underscore": "^1.7.0" - } - }, - "pg-int8": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", - "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==" - }, - "pg-pool": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-2.0.6.tgz", - "integrity": "sha1-e1YaSC/rCg5Zm1i1E3/S2zrYERw=" - }, - "pg-types": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.0.1.tgz", - "integrity": "sha1-uFhaN/Kpx7OGdH5EV0eZVJ5fSTM=", - "requires": { - "pg-int8": "1.0.1", - "postgres-array": "~2.0.0", - "postgres-bytea": "~1.0.0", - "postgres-date": "~1.0.4", - "postgres-interval": "^1.1.0" - } - }, - "pgpass": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.2.tgz", - "integrity": "sha1-Knu0G2BltnkH6R2hsHwYR8h3swY=", - "requires": { - "split": "^1.0.0" - } - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true - }, - "postgres-array": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", - "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==" - }, - "postgres-bytea": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", - "integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU=" - }, - "postgres-date": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.4.tgz", - "integrity": "sha512-bESRvKVuTrjoBluEcpv2346+6kgB7UlnqWZsnbnCccTNq/pqfj1j6oBaN5+b/NrDXepYUT/HKadqv3iS9lJuVA==" - }, - "postgres-interval": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", - "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", - "requires": { - "xtend": "^4.0.0" - } - }, - "prepend-http": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", - "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", - "dev": true - }, - "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", - "dev": true - }, - "promise.prototype.finally": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/promise.prototype.finally/-/promise.prototype.finally-3.1.2.tgz", - "integrity": "sha512-A2HuJWl2opDH0EafgdjwEw7HysI8ff/n4lW4QEVBCUXFk9QeGecBWv0Deph0UmLe3tTNYegz8MOjsVuE6SMoJA==", - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.0", - "function-bind": "^1.1.1" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.6", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", - "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.0", - "is-regex": "^1.1.0", - "object-inspect": "^1.7.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" - }, - "is-callable": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz", - "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==" - }, - "is-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.0.tgz", - "integrity": "sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw==", - "requires": { - "has-symbols": "^1.0.1" - } - } - } - }, - "proxy-addr": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", - "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==", - "requires": { - "forwarded": "~0.1.2", - "ipaddr.js": "1.9.0" - } - }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true - }, - "psl": { - "version": "1.1.31", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", - "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==" - }, - "pstree.remy": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.6.tgz", - "integrity": "sha512-NdF35+QsqD7EgNEI5mkI/X+UwaxVEbQaz9f4IooEmMUv6ZPmlTQYGjBPJGgrlzNdjSvIy4MWMg6Q6vCgBO2K+w==", - "dev": true - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" - }, - "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" - }, - "querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" - }, - "random-bytes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", - "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=" - }, - "range-parser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", - "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" - }, - "raw-body": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", - "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", - "requires": { - "bytes": "3.0.0", - "http-errors": "1.6.3", - "iconv-lite": "0.4.23", - "unpipe": "1.0.0" - } - }, - "rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - } - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - } - }, - "readline-sync": { - "version": "1.4.9", - "resolved": "https://registry.npmjs.org/readline-sync/-/readline-sync-1.4.9.tgz", - "integrity": "sha1-PtqOZfI80qF+YTAbHwADOWr17No=", - "dev": true - }, - "redis-commands": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.4.0.tgz", - "integrity": "sha512-cu8EF+MtkwI4DLIT0x9P8qNTLFhQD4jLfxLR0cCNkeGzs87FN6879JOJwNQR/1zD7aSYNbU0hgsV9zGY71Itvw==" - }, - "redis-errors": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", - "integrity": "sha1-62LSrbFeTq9GEMBK/hUpOEJQq60=" - }, - "redis-parser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", - "integrity": "sha1-tm2CjNyv5rS4pCin3vTGvKwxyLQ=", - "requires": { - "redis-errors": "^1.0.0" - } - }, - "reflect-metadata": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", - "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" - }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - } - }, - "registry-auth-token": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.4.0.tgz", - "integrity": "sha512-4LM6Fw8eBQdwMYcES4yTnn2TqIasbXuwDx3um+QRs7S55aMKCBKBxvPXl2RiUjHwuJLTyYfxSpmfSAjQpcuP+A==", - "dev": true, - "requires": { - "rc": "^1.1.6", - "safe-buffer": "^5.0.1" - } - }, - "registry-url": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", - "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", - "dev": true, - "requires": { - "rc": "^1.0.1" - } - }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true - }, - "repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", - "dev": true - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true - }, - "request": { - "version": "2.88.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", - "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.0", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.4.3", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "resolve": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.1.tgz", - "integrity": "sha512-KuIe4mf++td/eFb6wkaPbMDnP6kObCaEtIDuHOUED6MNUo4K670KZUHuuvYPZDxNF0WVLw49n06M2m2dXphEzA==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true - }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true - }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "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==" - }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "requires": { - "ret": "~0.1.10" - } - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "sax": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", - "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=" - }, - "semver": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", - "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==" - }, - "semver-diff": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz", - "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=", - "dev": true, - "requires": { - "semver": "^5.0.3" - } - }, - "send": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", - "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", - "requires": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "~1.6.2", - "mime": "1.4.1", - "ms": "2.0.0", - "on-finished": "~2.3.0", - "range-parser": "~1.2.0", - "statuses": "~1.4.0" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } - } - }, - "serve-static": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", - "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.2", - "send": "0.16.2" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" - }, - "sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true - }, - "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", - "dev": true - }, - "sinon": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-7.5.0.tgz", - "integrity": "sha512-AoD0oJWerp0/rY9czP/D6hDTTUYGpObhZjMpd7Cl/A6+j0xBE+ayL/ldfggkBXUs0IkvIiM1ljM8+WkOc5k78Q==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.4.0", - "@sinonjs/formatio": "^3.2.1", - "@sinonjs/samsam": "^3.3.3", - "diff": "^3.5.0", - "lolex": "^4.2.0", - "nise": "^1.5.2", - "supports-color": "^5.5.0" - } - }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "requires": { - "kind-of": "^3.2.0" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" - }, - "source-map-resolve": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", - "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", - "dev": true, - "requires": { - "atob": "^2.1.1", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, - "source-map-support": { - "version": "0.4.18", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", - "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", - "requires": { - "source-map": "^0.5.6" - } - }, - "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "dev": true - }, - "split": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", - "requires": { - "through": "2" - } - }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.0" - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" - }, - "sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, - "stack-generator": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/stack-generator/-/stack-generator-2.0.4.tgz", - "integrity": "sha512-ha1gosTNcgxwzo9uKTQ8zZ49aUp5FIUW58YHFxCqaAHtE0XqBg0chGFYA1MfmW//x1KWq3F4G7Ug7bJh4RiRtg==", - "requires": { - "stackframe": "^1.1.0" - } - }, - "stackframe": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.1.0.tgz", - "integrity": "sha512-Vx6W1Yvy+AM1R/ckVwcHQHV147pTPBKWCRLrXMuPrFVfvBUc3os7PR1QLIWCMhPpRg5eX9ojzbQIMLGBwyLjqg==" - }, - "standard-as-callback": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.0.1.tgz", - "integrity": "sha512-NQOxSeB8gOI5WjSaxjBgog2QFw55FV8TkS6Y07BiB3VJ8xNTvUYm0wl0s8ObgQ5NhdpnNfigMIKjgPESzgr4tg==" - }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, - "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "statuses": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", - "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" - }, - "stream-transform": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/stream-transform/-/stream-transform-1.0.8.tgz", - "integrity": "sha512-1q+dL790Ps0NV33rISMq9OLtfDA9KMJZdo1PHZXE85orrWsM4FAh8CVyAOTHO0rhyeM138KNPngBPrx33bFsxw==" - }, - "streamsearch": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", - "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=" - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, - "string.prototype.trimend": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", - "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.6", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", - "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.0", - "is-regex": "^1.1.0", - "object-inspect": "^1.7.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" - }, - "is-callable": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz", - "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==" - }, - "is-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.0.tgz", - "integrity": "sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw==", - "requires": { - "has-symbols": "^1.0.1" - } - } - } - }, - "string.prototype.trimstart": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", - "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.6", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", - "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.0", - "is-regex": "^1.1.0", - "object-inspect": "^1.7.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" - }, - "is-callable": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz", - "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==" - }, - "is-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.0.tgz", - "integrity": "sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw==", - "requires": { - "has-symbols": "^1.0.1" - } - } - } - }, - "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==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" - }, - "strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", - "dev": true - }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" - }, - "superagent": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz", - "integrity": "sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==", - "dev": true, - "requires": { - "component-emitter": "^1.2.0", - "cookiejar": "^2.1.0", - "debug": "^3.1.0", - "extend": "^3.0.0", - "form-data": "^2.3.1", - "formidable": "^1.2.0", - "methods": "^1.1.1", - "mime": "^1.4.1", - "qs": "^6.5.1", - "readable-stream": "^2.3.5" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "supertest": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/supertest/-/supertest-4.0.2.tgz", - "integrity": "sha512-1BAbvrOZsGA3YTCWqbmh14L0YEq0EGICX/nBnfkfVJn7SrxQV1I3pMYjSzG9y/7ZU2V9dWqyqk2POwxlb09duQ==", - "dev": true, - "requires": { - "methods": "^1.1.2", - "superagent": "^3.8.3" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - }, - "swagger-jsdoc": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/swagger-jsdoc/-/swagger-jsdoc-3.3.0.tgz", - "integrity": "sha512-O9I93uFM2/6QUPfRDW5I/dEcU54nwzjVpI0druO/EOXrGf3OKtj8wMdobGr45+ayD5uY58WrQ4hDhRa0238d0w==", - "requires": { - "commander": "2.20.0", - "doctrine": "3.0.0", - "glob": "7.1.4", - "js-yaml": "3.13.1", - "swagger-parser": "8.0.0" - }, - "dependencies": { - "glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } - } - }, - "swagger-methods": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/swagger-methods/-/swagger-methods-2.0.0.tgz", - "integrity": "sha512-afMNP6XtF7w4XB2pFuF07JNrHGaKoppwC0O3Zrkv0PWGbMT3KyFYpk4lzdcax7RYV1JgMZeatX8ndYjL2y+0tQ==" - }, - "swagger-parser": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/swagger-parser/-/swagger-parser-8.0.0.tgz", - "integrity": "sha512-zk6ig8J2B4OqCnBSIqO67/Ui96NTjuoX10YGa4YVlIlQzLpHUZbLFZaO+zSubQoqAiJxmpvlbUplEcFIsPCESA==", - "requires": { - "call-me-maybe": "^1.0.1", - "json-schema-ref-parser": "^7.1.0", - "ono": "^5.0.1", - "openapi-schemas": "^1.0.0", - "openapi-types": "^1.3.5", - "swagger-methods": "^2.0.0", - "z-schema": "^4.1.0" - } - }, - "swagger-ui-dist": { - "version": "4.11.1", - "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-4.11.1.tgz", - "integrity": "sha512-pf3kfSTYdF9mYFY2VnfJ51wnXlSVhEGdtymhpHzfbFw2jTbiEWgBoVz5EB9aW2EaJvUGTM1YHAXYZX7Jk4RdAQ==" - }, - "swagger-ui-express": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-4.4.0.tgz", - "integrity": "sha512-1CzRkHG386VQMVZK406jcpgnW2a9A5A/NiAjKhsFTQqUBWRF+uGbXTU/mA7WSV3mTzyOQDvjBdWP/c2qd5lqKw==", - "requires": { - "swagger-ui-dist": ">=4.11.0" - } - }, - "tar": { - "version": "4.4.19", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz", - "integrity": "sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==", - "dev": true, - "requires": { - "chownr": "^1.1.4", - "fs-minipass": "^1.2.7", - "minipass": "^2.9.0", - "minizlib": "^1.3.3", - "mkdirp": "^0.5.5", - "safe-buffer": "^5.2.1", - "yallist": "^3.1.1" - }, - "dependencies": { - "chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "dev": true - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - } - } - }, - "term-size": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz", - "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=", - "dev": true, - "requires": { - "execa": "^0.7.0" - } - }, - "thenify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", - "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "requires": { - "any-promise": "^1.0.0" - } - }, - "thenify-all": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=", - "requires": { - "thenify": ">= 3.1.0 < 4" - } - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" - }, - "timed-out": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", - "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=", - "dev": true - }, - "timezone-support": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/timezone-support/-/timezone-support-1.8.1.tgz", - "integrity": "sha512-+pKzxoUe4PZXaQcswceJlA+69oRyyu1uivnYKdpsC7eGzZiuvTLbU4WYPqTKslEsoSvjN8k/u/6qNfGikBB/wA==", - "requires": { - "commander": "2.19.0" - }, - "dependencies": { - "commander": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", - "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==" - } - } - }, - "tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, - "requires": { - "os-tmpdir": "~1.0.2" - } - }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - }, - "touch": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", - "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", - "dev": true, - "requires": { - "nopt": "~1.0.10" - } - }, - "tough-cookie": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", - "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", - "requires": { - "psl": "^1.1.24", - "punycode": "^1.4.1" - }, - "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" - } - } - }, - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" - }, - "ts-node": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-3.3.0.tgz", - "integrity": "sha1-wTxqMCTjC+EYDdUwOPwgkonUv2k=", - "requires": { - "arrify": "^1.0.0", - "chalk": "^2.0.0", - "diff": "^3.1.0", - "make-error": "^1.1.1", - "minimist": "^1.2.0", - "mkdirp": "^0.5.1", - "source-map-support": "^0.4.0", - "tsconfig": "^6.0.0", - "v8flags": "^3.0.0", - "yn": "^2.0.0" - } - }, - "tsconfig": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-6.0.0.tgz", - "integrity": "sha1-aw6DdgA9evGGT434+J3QBZ/80DI=", - "requires": { - "strip-bom": "^3.0.0", - "strip-json-comments": "^2.0.0" - } - }, - "tsconfig-paths": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.8.0.tgz", - "integrity": "sha512-zZEYFo4sjORK8W58ENkRn9s+HmQFkkwydDG7My5s/fnfr2YYCaiyXe/HBUcIgU8epEKOXwiahOO+KZYjiXlWyQ==", - "requires": { - "@types/json5": "^0.0.29", - "deepmerge": "^2.0.1", - "json5": "^1.0.1", - "minimist": "^1.2.0", - "strip-bom": "^3.0.0" - } - }, - "tslib": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", - "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", - "dev": true - }, - "tslint": { - "version": "5.14.0", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.14.0.tgz", - "integrity": "sha512-IUla/ieHVnB8Le7LdQFRGlVJid2T/gaJe5VkjzRVSRR6pA2ODYrnfR1hmxi+5+au9l50jBwpbBL34txgv4NnTQ==", - "dev": true, - "requires": { - "babel-code-frame": "^6.22.0", - "builtin-modules": "^1.1.1", - "chalk": "^2.3.0", - "commander": "^2.12.1", - "diff": "^3.2.0", - "glob": "^7.1.1", - "js-yaml": "^3.7.0", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.1", - "resolve": "^1.3.2", - "semver": "^5.3.0", - "tslib": "^1.8.0", - "tsutils": "^2.29.0" - } - }, - "tsutils": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", - "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - } - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" - }, - "type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" - }, - "type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - } - }, - "typeorm": { - "version": "0.2.45", - "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.2.45.tgz", - "integrity": "sha512-c0rCO8VMJ3ER7JQ73xfk0zDnVv0WDjpsP6Q1m6CVKul7DB9iVdWLRjPzc8v2eaeBuomsbZ2+gTaYr8k1gm3bYA==", - "requires": { - "@sqltools/formatter": "^1.2.2", - "app-root-path": "^3.0.0", - "buffer": "^6.0.3", - "chalk": "^4.1.0", - "cli-highlight": "^2.1.11", - "debug": "^4.3.1", - "dotenv": "^8.2.0", - "glob": "^7.1.6", - "js-yaml": "^4.0.0", - "mkdirp": "^1.0.4", - "reflect-metadata": "^0.1.13", - "sha.js": "^2.4.11", - "tslib": "^2.1.0", - "uuid": "^8.3.2", - "xml2js": "^0.4.23", - "yargs": "^17.0.1", - "zen-observable-ts": "^1.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "requires": { - "color-convert": "^2.0.1" - } - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - }, - "buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" - } - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "requires": { - "argparse": "^2.0.1" - } - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "requires": { - "has-flag": "^4.0.0" - } - }, - "tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" - }, - "xml2js": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", - "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", - "requires": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" - } - }, - "xmlbuilder": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", - "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==" - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" - }, - "yargs": { - "version": "17.5.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.0.tgz", - "integrity": "sha512-3sLxVhbAB5OC8qvVRebCLWuouhwh/rswsiDYx3WGxajUk/l4G20SKfrKKFeNIHboUFt2JFgv2yfn+5cgOr/t5A==", - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" - } - }, - "yargs-parser": { - "version": "21.0.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz", - "integrity": "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==" - } - } - }, - "typeorm-fixtures": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/typeorm-fixtures/-/typeorm-fixtures-0.8.5.tgz", - "integrity": "sha512-V90PY6nw1+CpoEsR6uqXmN0CtmbQAPgaX5+sA629IryodUQIXBjSGabAul4jBvuVkdJZXWf12QuXGl6ti429Xg==", - "dev": true - }, - "typescript": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.5.3.tgz", - "integrity": "sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g==" - }, - "uid-safe": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", - "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", - "requires": { - "random-bytes": "~1.0.0" - } - }, - "undefsafe": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", - "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", - "dev": true - }, - "underscore": { - "version": "1.13.3", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.3.tgz", - "integrity": "sha512-QvjkYpiD+dJJraRA8+dGAU4i7aBbb2s0S3jA45TFOvg2VgqvdCDd/3N6CqA8gluk1W91GLoXg5enMUx560QzuA==" - }, - "union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - } - }, - "unique-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", - "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", - "dev": true, - "requires": { - "crypto-random-string": "^1.0.0" - } - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" - }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true - } - } - }, - "unzip-response": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz", - "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=", - "dev": true - }, - "upath": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.2.tgz", - "integrity": "sha1-PbZYYA7a7sy+bbXmhNZ+6MKs0Gg=", - "dev": true - }, - "update-notifier": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-2.5.0.tgz", - "integrity": "sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw==", - "dev": true, - "requires": { - "boxen": "^1.2.1", - "chalk": "^2.0.1", - "configstore": "^3.0.0", - "import-lazy": "^2.1.0", - "is-ci": "^1.0.10", - "is-installed-globally": "^0.1.0", - "is-npm": "^1.0.0", - "latest-version": "^3.0.0", - "semver-diff": "^2.0.0", - "xdg-basedir": "^3.0.0" - } - }, - "uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", - "requires": { - "punycode": "^2.1.0" - } - }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true - }, - "url": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", - "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", - "requires": { - "punycode": "1.3.2", - "querystring": "0.2.0" - }, - "dependencies": { - "punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" - } - } - }, - "url-parse-lax": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", - "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", - "dev": true, - "requires": { - "prepend-http": "^1.0.1" - } - }, - "use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "util.promisify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", - "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.2", - "has-symbols": "^1.0.1", - "object.getownpropertydescriptors": "^2.1.0" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.6", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", - "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.0", - "is-regex": "^1.1.0", - "object-inspect": "^1.7.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" - }, - "is-callable": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz", - "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==" - }, - "is-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.0.tgz", - "integrity": "sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw==", - "requires": { - "has-symbols": "^1.0.1" - } - }, - "object.getownpropertydescriptors": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", - "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" - } - } - } - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" - }, - "uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" - }, - "v8flags": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.2.tgz", - "integrity": "sha512-MtivA7GF24yMPte9Rp/BWGCYQNaUj86zeYxV/x2RRJMKagImbbv3u8iJC57lNhWLPcGLJmHcHmFWkNsplbbLWw==", - "requires": { - "homedir-polyfill": "^1.0.1" - } - }, - "validator": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-10.4.0.tgz", - "integrity": "sha512-Q/wBy3LB1uOyssgNlXSRmaf22NxjvDNZM2MtIQ4jaEOAB61xsh1TQxsq1CgzUMBV1lDrVMogIh8GjG1DYW0zLg==" - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" - }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" - }, - "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, - "widest-line": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", - "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==", - "dev": true, - "requires": { - "string-width": "^2.1.1" - } - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "requires": { - "color-convert": "^2.0.1" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "requires": { - "ansi-regex": "^5.0.1" - } - } - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "write-file-atomic": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.2.tgz", - "integrity": "sha512-s0b6vB3xIVRLWywa6X9TOMA7k9zio0TMOsl9ZnDkliA/cfJlpHXAscj0gbHVJiTdIuAYpIyqS5GW91fqm6gG5g==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" - } - }, - "xdg-basedir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", - "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=", - "dev": true - }, - "xml2js": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", - "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", - "requires": { - "sax": ">=0.6.0", - "xmlbuilder": "~9.0.1" - } - }, - "xmlbuilder": { - "version": "9.0.7", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", - "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=" - }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" - }, - "y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "dev": true - }, - "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, - "yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dev": true, - "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - } - } - } - }, - "yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - }, - "dependencies": { - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - } - } - }, - "yargs-unparser": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", - "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", - "dev": true, - "requires": { - "flat": "^4.1.0", - "lodash": "^4.17.15", - "yargs": "^13.3.0" - } - }, - "yn": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", - "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=" - }, - "z-schema": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-4.2.4.tgz", - "integrity": "sha512-YvBeW5RGNeNzKOUJs3rTL4+9rpcvHXt5I051FJbOcitV8bl40pEfcG0Q+dWSwS0/BIYrMZ/9HHoqLllMkFhD0w==", - "requires": { - "commander": "^2.7.1", - "lodash.get": "^4.4.2", - "lodash.isequal": "^4.5.0", - "validator": "^13.6.0" - }, - "dependencies": { - "validator": { - "version": "13.7.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz", - "integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==" + "name": "app", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "app", + "version": "0.1.0", + "dependencies": { + "@bugsnag/js": "^8.0.0", + "@bugsnag/plugin-express": "^8.0.0", + "@types/bcrypt": "^5.0.2", + "@types/bcryptjs": "^2.4.6", + "@types/express": "^4.17.21", + "@types/express-fileupload": "^1.5.1", + "@types/express-session": "^1.18.0", + "aws-sdk": "^2.1691.0", + "bcryptjs": "^2.4.3", + "bull": "^4.16.2", + "chai": "^5.1.1", + "class-validator": "^0.14.1", + "cookie-parser": "~1.4.6", + "cors": "^2.8.5", + "csv": "^6.3.10", + "csv-parse": "^5.5.6", + "date-and-time": "^3.6.0", + "date-fns-timezone": "^0.1.4", + "debug": "~4.3.7", + "express": "~4.19.2", + "express-fileupload": "^1.5.1", + "express-session": "^1.18.0", + "flash": "^1.1.0", + "http-errors": "~2.0.0", + "ioredis": "^5.4.1", + "json2csv": "^5.0.7", + "jsonwebtoken": "^9.0.2", + "morgan": "~1.10.0", + "node-fetch": "^2.7.0", + "pg": "^8.12.0", + "pg-hstore": "^2.3.4", + "reflect-metadata": "^0.2.2", + "request": "^2.88.2", + "swagger-jsdoc": "^6.2.8", + "swagger-ui-express": "^5.0.1", + "ts-node": "10.9.2", + "tsconfig-paths": "4.2.0", + "typeorm": "^0.3.20", + "typescript": "5.5.4" + }, + "devDependencies": { + "@faker-js/faker": "^9.0.3", + "@types/dateformat": "^5.0.2", + "@types/jest": "^29.5.14", + "@types/mocha": "^10.0.7", + "@types/node": "^22.5.4", + "chai-as-promised": "^8.0.0", + "faker": "^6.6.6", + "ioredis-mock": "^8.9.0", + "jest": "^29.7.0", + "libxmljs": "1.0.8", + "mocha": "^10.7.3", + "nodemon": "^3.1.4", + "sinon": "^18.0.0", + "supertest": "^7.0.0", + "ts-jest": "^29.2.5", + "tslint": "^6.1.3", + "xml2js": "^0.6.2" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@ampproject/remapping/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@apidevtools/json-schema-ref-parser": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.1.2.tgz", + "integrity": "sha512-r1w81DpR+KyRWd3f+rk6TNqMgedmAxZP5v5KWlXQWlgMUUtyEJch0DKEci1SorPMiSeM8XPl7MZ3miJ60JIpQg==", + "dependencies": { + "@jsdevtools/ono": "^7.1.3", + "@types/json-schema": "^7.0.6", + "call-me-maybe": "^1.0.1", + "js-yaml": "^4.1.0" + } + }, + "node_modules/@apidevtools/json-schema-ref-parser/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/@apidevtools/json-schema-ref-parser/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@apidevtools/openapi-schemas": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@apidevtools/openapi-schemas/-/openapi-schemas-2.1.0.tgz", + "integrity": "sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/@apidevtools/swagger-methods": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz", + "integrity": "sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==" + }, + "node_modules/@apidevtools/swagger-parser": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/@apidevtools/swagger-parser/-/swagger-parser-10.0.3.tgz", + "integrity": "sha512-sNiLY51vZOmSPFZA5TF35KZ2HbgYklQnTSDnkghamzLb3EkNtcQnrBQEj5AOCxHpTtXpqMCRM1CrmV2rG6nw4g==", + "dependencies": { + "@apidevtools/json-schema-ref-parser": "^9.0.6", + "@apidevtools/openapi-schemas": "^2.0.4", + "@apidevtools/swagger-methods": "^3.0.2", + "@jsdevtools/ono": "^7.1.3", + "call-me-maybe": "^1.0.1", + "z-schema": "^5.0.1" + }, + "peerDependencies": { + "openapi-types": ">=7" + } + }, + "node_modules/@babel/code-frame": { + "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/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.5.tgz", + "integrity": "sha512-XvcZi1KWf88RVbF9wn8MN6tYFloU5qX8KjuF3E1PVBmJ9eypXfs4GRiJwLuTZL0iSnJUKn1BFPa5BPZZJyFzPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "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.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", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.5.tgz", + "integrity": "sha512-2caSP6fN9I7HOe6nqhtft7V4g7/V/gfDsC3Ag4W7kEzzvRGKqiv0pu0HogPiZ3KaVSoNDhUws6IJjDjpfmYIXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.26.5", + "@babel/types": "^7.26.5", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/generator/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.26.5.tgz", + "integrity": "sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.26.5", + "@babel/helper-validator-option": "^7.25.9", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/@babel/helper-module-imports": { + "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.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "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.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", + "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "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": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "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": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "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": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "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/template": "^7.25.9", + "@babel/types": "^7.26.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.5.tgz", + "integrity": "sha512-SRJ4jYmXRqV1/Xc+TIVG84WjHBXKlxO9sHQnA2Pf12QQEAp1LOh6kDzNHXcUnbH1QI0FDoPPVOt+vyUDucxpaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.26.5" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "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.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "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.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "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.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "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.9", + "@babel/parser": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.5.tgz", + "integrity": "sha512-rkOSPOw+AXbgtwUga3U4u8RpoK9FEFWBNAlTpcnkLFjL5CT+oyHNuUUC/xx6XefEJ16r38r8Bc/lfp6rYuHeJQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.5", + "@babel/parser": "^7.26.5", + "@babel/template": "^7.25.9", + "@babel/types": "^7.26.5", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.5.tgz", + "integrity": "sha512-L6mZmwFDK6Cjh1nRCLXpa6no13ZIioJDz7mdkzHv399pThrTa/k0nUlNaenOeh2kWu/iaOQYElEpKPUswUa9Vg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@bugsnag/browser": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@bugsnag/browser/-/browser-8.0.0.tgz", + "integrity": "sha512-v+Ff9rHuzB7Fb/RBxlqA1Bhn+SulZWIvbI+I0fIsJQ7mdOgnVuAK16HwiSzXSmrfntEB2M4NAyfUAQRcWjAKTA==", + "dependencies": { + "@bugsnag/core": "^8.0.0" + } + }, + "node_modules/@bugsnag/core": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@bugsnag/core/-/core-8.0.0.tgz", + "integrity": "sha512-AcDMjd4RZ+G8M/n6TFzL5P/1due+aNvTIu+26mu9TW2Tt4d/86lKVFQSy0H2Ju1HIaBdqtUUNCTXOIeNXJVkHQ==", + "dependencies": { + "@bugsnag/cuid": "^3.0.0", + "@bugsnag/safe-json-stringify": "^6.0.0", + "error-stack-parser": "^2.0.3", + "iserror": "0.0.2", + "stack-generator": "^2.0.3" + } + }, + "node_modules/@bugsnag/cuid": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@bugsnag/cuid/-/cuid-3.1.1.tgz", + "integrity": "sha512-d2z4b0rEo3chI07FNN1Xds8v25CNeekecU6FC/2Fs9MxY2EipkZTThVcV2YinMn8dvRUlViKOyC50evoUxg8tw==" + }, + "node_modules/@bugsnag/js": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@bugsnag/js/-/js-8.0.0.tgz", + "integrity": "sha512-xlSA48AJtnj+SsS824k1Gzo/gJTnn5xTBbWE7NhbsHEBBGVX3U7vOVBF75mZZEi89XwTiRwjQ91fASw4Rv5Ebg==", + "dependencies": { + "@bugsnag/browser": "^8.0.0", + "@bugsnag/node": "^8.0.0" + } + }, + "node_modules/@bugsnag/node": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@bugsnag/node/-/node-8.0.0.tgz", + "integrity": "sha512-boI969qvzuNgS61M0hTbLFKzWPo+OC8AFr4j3hGxGTOiqQD5QuFwSQ40Jcet+y1BHjMRjj3QD4U+722nOqaXyQ==", + "dependencies": { + "@bugsnag/core": "^8.0.0", + "byline": "^5.0.0", + "error-stack-parser": "^2.0.2", + "iserror": "^0.0.2", + "pump": "^3.0.0", + "stack-generator": "^2.0.3" + } + }, + "node_modules/@bugsnag/plugin-express": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@bugsnag/plugin-express/-/plugin-express-8.0.0.tgz", + "integrity": "sha512-Xzc4yy7ybV9Wx/mZMCOcl+f/wAV1eFqwx/RPLnA2bga6Z1CcFc9Gr6LS13tExC5R8VQKnDw44YSB2GGlCUiMHA==", + "peerDependencies": { + "@bugsnag/core": "^8.0.0-alpha.1" + } + }, + "node_modules/@bugsnag/safe-json-stringify": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@bugsnag/safe-json-stringify/-/safe-json-stringify-6.0.0.tgz", + "integrity": "sha512-htzFO1Zc57S8kgdRK9mLcPVTW1BY2ijfH7Dk2CeZmspTWKdKqSo1iwmqrq2WtRjFlo8aRZYgLX0wFrDXF/9DLA==" + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@faker-js/faker": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-9.0.3.tgz", + "integrity": "sha512-lWrrK4QNlFSU+13PL9jMbMKLJYXDFu3tQfayBsMXX7KL/GiQeqfB1CzHkqD5UHBUtPAuPo6XwGbMFNdVMZObRA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/fakerjs" + } + ], + "license": "MIT", + "engines": { + "node": ">=18.0.0", + "npm": ">=9.0.0" + } + }, + "node_modules/@ioredis/as-callback": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@ioredis/as-callback/-/as-callback-3.0.0.tgz", + "integrity": "sha512-Kqv1rZ3WbgOrS+hgzJ5xG5WQuhvzzSTRYvNeyPMLOAM78MHSnuKI20JeJGbpuAt//LCuP0vsexZcorqW7kWhJg==", + "dev": true + }, + "node_modules/@ioredis/commands": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz", + "integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==" + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/console/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/console/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/console/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/console/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jest/console/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/core/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/core/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/core/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/core/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jest/core/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/core/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers/node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/reporters/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jest/reporters/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/reporters/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/reporters/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/reporters/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jest/reporters/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/reporters/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jest/transform/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/transform/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/transform/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/transform/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jest/transform/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/transform/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/types/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/types/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/types/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jest/types/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/types/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@jsdevtools/ono": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", + "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==" + }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/semver": { + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.0.tgz", + "integrity": "sha512-DrfFnPzblFmNrIZzg5RzHegbiRWg7KMR7btwi2yjHwx06zsUbO5g613sVwEV7FTwmzJu+Io0lJe2GJ3LxqpvBQ==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.3.tgz", + "integrity": "sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.3.tgz", + "integrity": "sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.3.tgz", + "integrity": "sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.3.tgz", + "integrity": "sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.3.tgz", + "integrity": "sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-win32-x64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.3.tgz", + "integrity": "sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "11.3.1", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-11.3.1.tgz", + "integrity": "sha512-EVJO7nW5M/F5Tur0Rf2z/QoMo+1Ia963RiMtapiQrEWvY0iBUvADo8Beegwjpnle5BHkyHuoxSTW3jF43H1XRA==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^3.0.1" + } + }, + "node_modules/@sinonjs/samsam": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.0.tgz", + "integrity": "sha512-Bp8KUVlLp8ibJZrnvq2foVhP0IVX2CIprMJPK0vqGqgrDa0OHVKeZyBykqskkrdxV6yKBPmGasO8LVjAKR3Gew==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^2.0.0", + "lodash.get": "^4.4.2", + "type-detect": "^4.0.8" + } + }, + "node_modules/@sinonjs/samsam/node_modules/@sinonjs/commons": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", + "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/text-encoding": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.3.tgz", + "integrity": "sha512-DE427ROAphMQzU4ENbliGYrBSYPXF+TtLg9S8vzeA+OF4ZKzoDdzfL8sxuMUGS/lgRhM6j1URSk9ghf7Xo1tyA==", + "dev": true + }, + "node_modules/@sqltools/formatter": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@sqltools/formatter/-/formatter-1.2.5.tgz", + "integrity": "sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw==" + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==" + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", + "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/bcrypt": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-5.0.2.tgz", + "integrity": "sha512-6atioO8Y75fNcbmj0G7UjI9lXN2pQ/IGJ2FWT4a/btd0Lk9lQalHLKhkgKVZ3r+spnmWUKfbMi1GEe9wyHQfNQ==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/bcryptjs": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/@types/bcryptjs/-/bcryptjs-2.4.6.tgz", + "integrity": "sha512-9xlo6R2qDs5uixm0bcIqCeMCE6HiQsIyel9KQySStiyqNl2tnj2mP3DX1Nf56MD6KMenNNlBBsy3LJ7gUEQPXQ==" + }, + "node_modules/@types/body-parser": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.17.0.tgz", + "integrity": "sha1-n1ydm9BLtUvjLV65/A2Ml05s9Yw=", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/busboy": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@types/busboy/-/busboy-1.5.4.tgz", + "integrity": "sha512-kG7WrUuAKK0NoyxfQHsVE6j1m01s6kMma64E+OZenQABMQyTJop1DumUWcLwAQ2JzpefU7PDYoRDKl8uZosFjw==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.32", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.32.tgz", + "integrity": "sha512-4r8qa0quOvh7lGD0pre62CAb1oni1OO6ecJLGCezTmhQ8Fz50Arx9RUszryR8KlgK6avuSXvviL6yWyViQABOg==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/dateformat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@types/dateformat/-/dateformat-5.0.2.tgz", + "integrity": "sha512-M95hNBMa/hnwErH+a+VOD/sYgTmo15OTYTM2Hr52/e0OdOuY+Crag+kd3/ioZrhg0WGbl9Sm3hR7UU+MH6rfOw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/express": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-fileupload": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@types/express-fileupload/-/express-fileupload-1.5.1.tgz", + "integrity": "sha512-DllImBVI1lCyjl2klky/TEwk60mbNebgXv1669h66g9TfptWSrEFq5a/raHSutaFzjSm1tmn9ypdNfu4jPSixQ==", + "dependencies": { + "@types/busboy": "*", + "@types/express": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.19.5", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.5.tgz", + "integrity": "sha512-y6W03tvrACO72aijJ5uF02FRq5cgDR9lUxddQ8vyF+GvmjJQqbzDcJngEjURc+ZsG31VI3hODNZJ2URj86pzmg==", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/express-session": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/@types/express-session/-/express-session-1.18.0.tgz", + "integrity": "sha512-27JdDRgor6PoYlURY+Y5kCakqp5ulC0kmf7y+QwaY+hv9jEFuQOThgkjyA53RP3jmKuBsH5GR6qEfFmvb8mwOA==", + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/ioredis-mock": { + "version": "8.2.5", + "resolved": "https://registry.npmjs.org/@types/ioredis-mock/-/ioredis-mock-8.2.5.tgz", + "integrity": "sha512-cZyuwC9LGtg7s5G9/w6rpy3IOZ6F/hFR0pQlWYZESMo1xQUYbDpa6haqB4grTePjsGzcB/YLBFCjqRunK5wieg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/node": "*", + "ioredis": ">=5" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "29.5.14", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.14.tgz", + "integrity": "sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" + }, + "node_modules/@types/mime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.1.tgz", + "integrity": "sha512-FwI9gX75FgVBJ7ywgnq/P7tw+/o1GUbtP0KzbtusLigAOgIgNISRK0ZPl4qertvXSIE8YbsVJueQ90cDt9YYyw==" + }, + "node_modules/@types/mocha": { + "version": "10.0.7", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.7.tgz", + "integrity": "sha512-GN8yJ1mNTcFcah/wKEFIJckJx9iJLoMSzWcfRRuxz/Jk+U6KQNnml+etbtxFK8lPjzOw3zp4Ha/kjSst9fsHYw==", + "dev": true + }, + "node_modules/@types/node": { + "version": "22.5.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.4.tgz", + "integrity": "sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==", + "dependencies": { + "undici-types": "~6.19.2" + } + }, + "node_modules/@types/qs": { + "version": "6.9.15", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", + "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==" + }, + "node_modules/@types/range-parser": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz", + "integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==" + }, + "node_modules/@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/send/node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==" + }, + "node_modules/@types/serve-static": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.2.tgz", + "integrity": "sha1-9axNemQgqZpqRa9HGfTc2M2Qekg=", + "dependencies": { + "@types/express-serve-static-core": "*", + "@types/mime": "*" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/validator": { + "version": "13.12.1", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.12.1.tgz", + "integrity": "sha512-w0URwf7BQb0rD/EuiG12KP0bailHKHP5YVviJG9zw3ykAokL0TuxU2TUqMB7EwZ59bDHYdeTIvjI5m0S7qHfOA==" + }, + "node_modules/@types/yargs": { + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.3.tgz", + "integrity": "sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "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, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/app-root-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-3.1.0.tgz", + "integrity": "sha512-biN3PwB2gUtjaYy/isrU3aNWI5w+fAfvHkSvCKeQGxhmYpwKFUxudR3Yya+KqVRHBmEDYh+/lTozYCFbmzX4nA==", + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "deprecated": "This package is no longer supported.", + "dev": true, + "license": "ISC", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "dev": true + }, + "node_modules/asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "dev": true, + "license": "MIT" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "node_modules/available-typed-arrays": { + "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==", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/aws-sdk": { + "version": "2.1691.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1691.0.tgz", + "integrity": "sha512-/F2YC+DlsY3UBM2Bdnh5RLHOPNibS/+IcjUuhP8XuctyrN+MlL+fWDAiela32LTDk7hMy4rx8MTgvbJ+0blO5g==", + "hasInstallScript": true, + "dependencies": { + "buffer": "4.9.2", + "events": "1.1.1", + "ieee754": "1.1.13", + "jmespath": "0.16.0", + "querystring": "0.2.0", + "sax": "1.2.1", + "url": "0.10.3", + "util": "^0.12.4", + "uuid": "8.0.0", + "xml2js": "0.6.2" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/aws-sdk/node_modules/uuid": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz", + "integrity": "sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" + }, + "node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-jest/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/babel-jest/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/babel-jest/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/babel-jest/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/babel-jest/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-jest/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz", + "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dev": true, + "license": "MIT", + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/bcryptjs": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "integrity": "sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms=" + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bindings": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.3.1.tgz", + "integrity": "sha512-i47mqjF9UbjxJhxGf+pZ6kSxrnI3wBLlnGI2ArWJ4r0VrvDS7ZYXkprq/pLaBWYq4GM0r4zdHY+NNRqEMU7uew==", + "dev": true, + "license": "MIT" + }, + "node_modules/body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/body-parser/node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "node_modules/browserslist": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", + "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "caniuse-lite": "^1.0.30001688", + "electron-to-chromium": "^1.5.73", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.1" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-json-stable-stringify": "2.x" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/bull": { + "version": "4.16.2", + "resolved": "https://registry.npmjs.org/bull/-/bull-4.16.2.tgz", + "integrity": "sha512-VCy33UdPGiIoZHDTrslGXKXWxcIUHNH5Z82pihr8HicbIfAH4SHug1HxlwKEbibVv85hq8rJ9tKAW/cuxv2T0A==", + "dependencies": { + "cron-parser": "^4.2.1", + "get-port": "^5.1.1", + "ioredis": "^5.3.2", + "lodash": "^4.17.21", + "msgpackr": "^1.10.1", + "semver": "^7.5.2", + "uuid": "^8.3.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/bull/node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/bull/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/bull/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/byline": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/byline/-/byline-5.0.0.tgz", + "integrity": "sha512-s6webAy+R4SR8XVuJWt2V2rGvhnrhxN+9S15GNuTK3wKPOXFF6RNc+8ug2XhH+2s4f+uudG4kUVYmYOQWL2g0Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-me-maybe": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", + "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==" + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001692", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001692.tgz", + "integrity": "sha512-A95VKan0kdtrsnMubMKxEKUKImOPSuCpYgxSQBo036P5YYgVIcOYJEgt/txJWqObiRQeISNCfef9nvlQ0vbV7A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "node_modules/chai": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.1.tgz", + "integrity": "sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA==", + "dependencies": { + "assertion-error": "^2.0.1", + "check-error": "^2.1.1", + "deep-eql": "^5.0.1", + "loupe": "^3.1.0", + "pathval": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/chai-as-promised": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-8.0.0.tgz", + "integrity": "sha512-sMsGXTrS3FunP/wbqh/KxM8Kj/aLPXQGkNtvE5wPfSToq8wkkvBpTZo1LIiEVmC4BwkKpag+l5h/20lBMk6nUg==", + "dev": true, + "dependencies": { + "check-error": "^2.0.0" + }, + "peerDependencies": { + "chai": ">= 2.1.2 < 6" + } + }, + "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, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/check-error": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", + "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", + "engines": { + "node": ">= 16" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz", + "integrity": "sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==", + "dev": true, + "license": "MIT" + }, + "node_modules/class-validator": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.1.tgz", + "integrity": "sha512-2VEG9JICxIqTpoK1eMzZqaV+u/EiwEJkMGzTrZf6sU/fwsnOITVgYJ8yojSy6CaXtO9V0Cc6ZQZ8h8m4UBuLwQ==", + "dependencies": { + "@types/validator": "^13.11.8", + "libphonenumber-js": "^1.10.53", + "validator": "^13.9.0" + } + }, + "node_modules/cli-highlight": { + "version": "2.1.11", + "resolved": "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.11.tgz", + "integrity": "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==", + "dependencies": { + "chalk": "^4.0.0", + "highlight.js": "^10.7.1", + "mz": "^2.4.0", + "parse5": "^5.1.1", + "parse5-htmlparser2-tree-adapter": "^6.0.0", + "yargs": "^16.0.0" + }, + "bin": { + "highlight": "bin/highlight" + }, + "engines": { + "node": ">=8.0.0", + "npm": ">=5.0.0" + } + }, + "node_modules/cli-highlight/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/cli-highlight/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/cli-highlight/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/cli-highlight/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/cli-highlight/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-highlight/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/cluster-key-slot": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", + "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", + "dev": true, + "license": "MIT" + }, + "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, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true, + "license": "ISC", + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", + "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", + "dev": true + }, + "node_modules/component-emitter": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz", + "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-disposition/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-parser": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz", + "integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==", + "license": "MIT", + "dependencies": { + "cookie": "0.7.2", + "cookie-signature": "1.0.6" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "node_modules/cookiejar": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", + "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", + "dev": true + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-jest/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/create-jest/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/create-jest/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/create-jest/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/create-jest/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/create-jest/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" + }, + "node_modules/cron-parser": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-4.9.0.tgz", + "integrity": "sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==", + "dependencies": { + "luxon": "^3.2.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/csv": { + "version": "6.3.10", + "resolved": "https://registry.npmjs.org/csv/-/csv-6.3.10.tgz", + "integrity": "sha512-5NYZG4AN2ZUthmNxIudgBEdMPUnbQHu9V4QTzBPqQzUP3KQsFiJo+8HQ0+oVxj1PomIT1/f67VI1QH/hsrZLKA==", + "dependencies": { + "csv-generate": "^4.4.1", + "csv-parse": "^5.5.6", + "csv-stringify": "^6.5.1", + "stream-transform": "^3.3.2" + }, + "engines": { + "node": ">= 0.1.90" + } + }, + "node_modules/csv-generate": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/csv-generate/-/csv-generate-4.4.1.tgz", + "integrity": "sha512-O/einO0v4zPmXaOV+sYqGa02VkST4GP5GLpWBNHEouIU7pF3kpGf3D0kCCvX82ydIY4EKkOK+R8b1BYsRXravg==" + }, + "node_modules/csv-parse": { + "version": "5.5.6", + "resolved": "https://registry.npmjs.org/csv-parse/-/csv-parse-5.5.6.tgz", + "integrity": "sha512-uNpm30m/AGSkLxxy7d9yRXpJQFrZzVWLFBkS+6ngPcZkw/5k3L/jjFuj7tVnEpRn+QgmiXr21nDlhCiUK4ij2A==" + }, + "node_modules/csv-stringify": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/csv-stringify/-/csv-stringify-6.5.1.tgz", + "integrity": "sha512-+9lpZfwpLntpTIEpFbwQyWuW/hmI/eHuJZD1XzeZpfZTqkf1fyvBbBLXTJJMsBuuS11uTShMqPwzx4A6ffXgRQ==" + }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/date-and-time": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/date-and-time/-/date-and-time-3.6.0.tgz", + "integrity": "sha512-V99gLaMqNQxPCObBumb31Bfy3OByXnpqUM0yHPi/aBQE61g42A2rGk6Z2CDnpLrWsOFLQwOgl4Vgshw6D44ebw==", + "license": "MIT" + }, + "node_modules/date-fns": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz", + "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==" + }, + "node_modules/date-fns-timezone": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-fns-timezone/-/date-fns-timezone-0.1.4.tgz", + "integrity": "sha512-npnZn1eIeHV8A3Hqw86mn6CjH+qMe0TSCs4anpD4Rouf+mE9eIJuaHviIpNmGL9GiDmcUoiaKdkX5ihf+yZQZA==", + "dependencies": { + "date-fns": "^1.29.0", + "timezone-support": "^1.5.5" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/dayjs": { + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", + "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==" + }, + "node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/dedent": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", + "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deep-eql": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", + "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", + "engines": { + "node": ">=6" + } + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "devOptional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/dezalgo": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", + "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", + "dev": true, + "dependencies": { + "asap": "^2.0.0", + "wrappy": "1" + } + }, + "node_modules/diff": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.83", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.83.tgz", + "integrity": "sha512-LcUDPqSt+V0QmI47XLzZrz5OqILSMGsPFkDYus22rIbgorSvBYEFqq854ltTmUdHkY92FSdAAvsh4jWEULMdfQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/error-stack-parser": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz", + "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==", + "dependencies": { + "stackframe": "^1.3.4" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "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": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/express": { + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.2", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.6.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express-fileupload": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/express-fileupload/-/express-fileupload-1.5.1.tgz", + "integrity": "sha512-LsYG1ALXEB7vlmjuSw8ABeOctMp8a31aUC5ZF55zuz7O2jLFnmJYrCv10py357ky48aEoBQ/9bVXgFynjvaPmA==", + "dependencies": { + "busboy": "^1.6.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/express-session": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.18.1.tgz", + "integrity": "sha512-a5mtTqEaZvBCL9A9aqkrtfz+3SMDhOVUnjafjo+s7A9Txkq+SVX2DLvSp1Zrv4uCXa3lMSK3viWnh9Gg07PBUA==", + "license": "MIT", + "dependencies": { + "cookie": "0.7.2", + "cookie-signature": "1.0.7", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-headers": "~1.0.2", + "parseurl": "~1.3.3", + "safe-buffer": "5.2.1", + "uid-safe": "~2.1.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/express-session/node_modules/cookie-signature": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==" + }, + "node_modules/express-session/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express-session/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/express-session/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/express/node_modules/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/express/node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/express/node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/express/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "engines": [ + "node >=0.6.0" + ] + }, + "node_modules/faker": { + "version": "6.6.6", + "resolved": "https://registry.npmjs.org/faker/-/faker-6.6.6.tgz", + "integrity": "sha512-9tCqYEDHI5RYFQigXFwF1hnCwcWCOJl/hmll0lr5D2Ljjb0o4wphb69wikeJDz5qCEzXCoPvG6ss5SDP6IfOdg==", + "dev": true + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "license": "MIT" + }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "dev": true + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/fengari": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/fengari/-/fengari-0.1.4.tgz", + "integrity": "sha512-6ujqUuiIYmcgkGz8MGAdERU57EIluGGPSUgGPTsco657EHa+srq0S3/YUl/r9kx1+D+d4rGfYObd+m8K22gB1g==", + "dev": true, + "dependencies": { + "readline-sync": "^1.4.9", + "sprintf-js": "^1.1.1", + "tmp": "^0.0.33" + } + }, + "node_modules/fengari-interop": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/fengari-interop/-/fengari-interop-0.1.3.tgz", + "integrity": "sha512-EtZ+oTu3kEwVJnoymFPBVLIbQcCoy9uWCVnMA6h3M/RqHkUBsLYp29+RRHf9rKr6GwjubWREU1O7RretFIXjHw==", + "dev": true, + "peerDependencies": { + "fengari": "^0.1.0" + } + }, + "node_modules/fengari/node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "dev": true + }, + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/finalhandler/node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flash": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/flash/-/flash-1.1.0.tgz", + "integrity": "sha1-irKyntO2ilz7Gom/mOf2nX8aAgo=" + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "engines": { + "node": "*" + } + }, + "node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "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==", + "dev": true, + "dependencies": { + "dezalgo": "^1.0.4", + "hexoid": "^1.0.0", + "once": "^1.4.0" + }, + "funding": { + "url": "https://ko-fi.com/tunnckoCore/commissions" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "deprecated": "This package is no longer supported.", + "dev": true, + "license": "ISC", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-func-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", + "engines": { + "node": "*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-port": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz", + "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "engines": { + "node": ">=4" + } + }, + "node_modules/har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "deprecated": "this library is no longer supported", + "dependencies": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "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, + "engines": { + "node": ">=8" + } + }, + "node_modules/highlight.js": { + "version": "10.7.3", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", + "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", + "engines": { + "node": "*" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true, + "license": "MIT" + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=", + "dev": true + }, + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ioredis": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.4.1.tgz", + "integrity": "sha512-2YZsvl7jopIa1gaePkeMtd9rAcSjOOjPtpcLlOeusyO+XH2SK5ZcT+UCrElPP+WVIInh2TzeI4XW9ENaSLVVHA==", + "dependencies": { + "@ioredis/commands": "^1.1.1", + "cluster-key-slot": "^1.1.0", + "debug": "^4.3.4", + "denque": "^2.1.0", + "lodash.defaults": "^4.2.0", + "lodash.isarguments": "^3.1.0", + "redis-errors": "^1.2.0", + "redis-parser": "^3.0.0", + "standard-as-callback": "^2.1.0" + }, + "engines": { + "node": ">=12.22.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ioredis" + } + }, + "node_modules/ioredis-mock": { + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/ioredis-mock/-/ioredis-mock-8.9.0.tgz", + "integrity": "sha512-yIglcCkI1lvhwJVoMsR51fotZVsPsSk07ecTCgRTRlicG0Vq3lke6aAaHklyjmRNRsdYAgswqC2A0bPtQK4LSw==", + "dev": true, + "dependencies": { + "@ioredis/as-callback": "^3.0.0", + "@ioredis/commands": "^1.2.0", + "fengari": "^0.1.4", + "fengari-interop": "^0.1.3", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12.22" + }, + "peerDependencies": { + "@types/ioredis-mock": "^8", + "ioredis": "^5" + } + }, + "node_modules/ioredis-mock/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "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==", + "engines": { + "node": ">= 0.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==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-typed-array": { + "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==", + "dependencies": { + "which-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/iserror": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/iserror/-/iserror-0.0.2.tgz", + "integrity": "sha512-oKGGrFVaWwETimP3SiWwjDeY27ovZoyZPHtxblC4hCq9fXxed/jasx+ATWFFjCVSRZng8VTMsN1nDnGo6zMBSw==" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report/node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/istanbul-lib-report/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jake": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz", + "integrity": "sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.4", + "minimatch": "^3.1.2" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jake/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jake/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jake/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jake/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/jake/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jake/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-circus/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-circus/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-circus/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/jest-circus/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-circus/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-cli/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-cli/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-cli/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/jest-cli/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-cli/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/jest-cli/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-cli/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-cli/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/jest-cli/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-config/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-config/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-config/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-config/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/jest-config/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-config/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-diff/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-diff/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-diff/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-diff/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/jest-diff/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-diff/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-each/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-each/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-each/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/jest-each/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-each/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-matcher-utils/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-matcher-utils/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-matcher-utils/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/jest-matcher-utils/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-matcher-utils/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-message-util/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-message-util/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-message-util/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-message-util/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/jest-message-util/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-message-util/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-resolve/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-resolve/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-resolve/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/jest-resolve/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-resolve/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-runner/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-runner/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-runner/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/jest-runner/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runner/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-runtime/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-runtime/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-runtime/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/jest-runtime/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runtime/node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runtime/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-snapshot/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-snapshot/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/jest-snapshot/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-snapshot/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jest-snapshot/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-util/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-util/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-util/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-util/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/jest-util/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-util/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-validate/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-validate/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-validate/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/jest-validate/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-validate/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-watcher/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-watcher/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-watcher/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-watcher/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/jest-watcher/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-watcher/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/jmespath": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz", + "integrity": "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "node_modules/json2csv": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/json2csv/-/json2csv-5.0.7.tgz", + "integrity": "sha512-YRZbUnyaJZLZUJSRi2G/MqahCyRv9n/ds+4oIetjDF3jWQA7AG7iSeKTiZiCNqtMZM7HDyt0e/W6lEnoGEmMGA==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "dependencies": { + "commander": "^6.1.0", + "jsonparse": "^1.3.1", + "lodash.get": "^4.4.2" + }, + "bin": { + "json2csv": "bin/json2csv.js" + }, + "engines": { + "node": ">= 10", + "npm": ">= 6.13.0" + } + }, + "node_modules/json2csv/node_modules/commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "engines": [ + "node >= 0.2.0" + ] + }, + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jsonwebtoken/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jsprim": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", + "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/jsprim/node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" + }, + "node_modules/just-extend": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-6.2.0.tgz", + "integrity": "sha512-cYofQu2Xpom82S6qD778jBDpwvvy39s1l/hrYij2u9AMdQcGRpaBu6kY4mVhuno5kJVi1DAz4aiphA2WI1/OAw==", + "dev": true + }, + "node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/libphonenumber-js": { + "version": "1.11.7", + "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.11.7.tgz", + "integrity": "sha512-x2xON4/Qg2bRIS11KIN9yCNYUjhtiEjNyptjX0mX+pyKHecxuJVLIpfX1lq9ZD6CrC/rB+y4GBi18c6CEcUR+A==" + }, + "node_modules/libxmljs": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/libxmljs/-/libxmljs-1.0.8.tgz", + "integrity": "sha512-gp7UwxHMjrfWaj4xyeoA7ZtT0HnU5xtA6KKwE+an1xDI+7cjVsNwwIDppy2g13B7ywxCyDWWk70sMAXOufeTlQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.9", + "bindings": "~1.3.0", + "nan": "^2.17.0" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=" + }, + "node_modules/lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=" + }, + "node_modules/lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" + }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.mergewith": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz", + "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-symbols/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/log-symbols/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/log-symbols/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/log-symbols/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/loupe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.1.tgz", + "integrity": "sha512-edNu/8D5MKVfGVFRhFf8aAxiTM6Wumfz5XsaatSxlD3w4R1d/WEKUTydCdPGbl9K7QG/Ca3GnDV2sIKIpXRQcw==", + "dependencies": { + "get-func-name": "^2.0.1" + } + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" + }, + "node_modules/luxon": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.5.0.tgz", + "integrity": "sha512-rh+Zjr6DNfUYR3bPwJEnuwDdqMbxZW7LOQfUN4B54+Cl+0o5zaU9RJ6bcidfDtC1cWCZXQ+nvX8bf6bAji37QQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "license": "ISC" + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + }, + "node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/mocha": { + "version": "10.7.3", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.7.3.tgz", + "integrity": "sha512-uQWxAu44wwiACGqjbPYmjo7Lg8sFrS3dQe7PP2FQI+woptP4vZXSMcfMyFL/e1yFEeEpV4RtyTpZROOKmxis+A==", + "dev": true, + "dependencies": { + "ansi-colors": "^4.1.3", + "browser-stdout": "^1.3.1", + "chokidar": "^3.5.3", + "debug": "^4.3.5", + "diff": "^5.2.0", + "escape-string-regexp": "^4.0.0", + "find-up": "^5.0.0", + "glob": "^8.1.0", + "he": "^1.2.0", + "js-yaml": "^4.1.0", + "log-symbols": "^4.1.0", + "minimatch": "^5.1.6", + "ms": "^2.1.3", + "serialize-javascript": "^6.0.2", + "strip-json-comments": "^3.1.1", + "supports-color": "^8.1.1", + "workerpool": "^6.5.1", + "yargs": "^16.2.0", + "yargs-parser": "^20.2.9", + "yargs-unparser": "^2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha.js" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/mocha/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/mocha/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/mocha/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/mocha/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/mocha/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/mocha/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mocha/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/morgan": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", + "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", + "dependencies": { + "basic-auth": "~2.0.1", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-finished": "~2.3.0", + "on-headers": "~1.0.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/morgan/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/morgan/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/msgpackr": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.11.0.tgz", + "integrity": "sha512-I8qXuuALqJe5laEBYoFykChhSXLikZmUhccjGsPuSJ/7uPip2TJ7lwdIQwWSAi0jGZDXv4WOP8Qg65QZRuXxXw==", + "optionalDependencies": { + "msgpackr-extract": "^3.0.2" + } + }, + "node_modules/msgpackr-extract": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-3.0.3.tgz", + "integrity": "sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA==", + "hasInstallScript": true, + "optional": true, + "dependencies": { + "node-gyp-build-optional-packages": "5.2.2" + }, + "bin": { + "download-msgpackr-prebuilds": "bin/download-prebuilds.js" + }, + "optionalDependencies": { + "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.3", + "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.3" + } + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nan": { + "version": "2.22.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.22.0.tgz", + "integrity": "sha512-nbajikzWTMwsW+eSsNm3QwlOs7het9gGJU5dDZzRTQGk03vyBOauxgI4VakDzE0PtsGTmXPsXTbbjVhRwR5mpw==", + "dev": true, + "license": "MIT" + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/nise": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/nise/-/nise-6.0.0.tgz", + "integrity": "sha512-K8ePqo9BFvN31HXwEtTNGzgrPpmvgciDsFz8aztFjt4LqKO/JeFD8tBOeuDiCMXrIl/m1YvfH8auSpxfaD09wg==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^3.0.0", + "@sinonjs/fake-timers": "^11.2.2", + "@sinonjs/text-encoding": "^0.7.2", + "just-extend": "^6.2.0", + "path-to-regexp": "^6.2.1" + } + }, + "node_modules/nise/node_modules/path-to-regexp": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", + "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-gyp-build-optional-packages": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.2.2.tgz", + "integrity": "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==", + "optional": true, + "dependencies": { + "detect-libc": "^2.0.1" + }, + "bin": { + "node-gyp-build-optional-packages": "bin.js", + "node-gyp-build-optional-packages-optional": "optional.js", + "node-gyp-build-optional-packages-test": "build-test.js" + } + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "dev": true, + "license": "MIT" + }, + "node_modules/nodemon": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.4.tgz", + "integrity": "sha512-wjPBbFhtpJwmIeY2yP7QF+UKzPfltVGtfce1g/bB15/8vCGZj8uxD62b/b9M9/WVgme0NZudpownKN+c0plXlQ==", + "dev": true, + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^4", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", + "semver": "^7.5.3", + "simple-update-notifier": "^2.0.0", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nodemon/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", + "dev": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "deprecated": "This package is no longer supported.", + "dev": true, + "license": "ISC", + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, + "node_modules/oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "engines": { + "node": "*" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/openapi-types": { + "version": "12.1.3", + "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz", + "integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==", + "license": "MIT", + "peer": true + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", + "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==" + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse5": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", + "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==" + }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", + "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", + "dependencies": { + "parse5": "^6.0.1" + } + }, + "node_modules/parse5-htmlparser2-tree-adapter/node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", + "license": "MIT" + }, + "node_modules/pathval": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", + "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", + "engines": { + "node": ">= 14.16" + } + }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "node_modules/pg": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.12.0.tgz", + "integrity": "sha512-A+LHUSnwnxrnL/tZ+OLfqR1SxLN3c/pgDztZ47Rpbsd4jUytsTtwQo/TLPRzPJMp/1pbhYVhH9cuSZLAajNfjQ==", + "dependencies": { + "pg-connection-string": "^2.6.4", + "pg-pool": "^3.6.2", + "pg-protocol": "^1.6.1", + "pg-types": "^2.1.0", + "pgpass": "1.x" + }, + "engines": { + "node": ">= 8.0.0" + }, + "optionalDependencies": { + "pg-cloudflare": "^1.1.1" + }, + "peerDependencies": { + "pg-native": ">=3.0.1" + }, + "peerDependenciesMeta": { + "pg-native": { + "optional": true + } + } + }, + "node_modules/pg-cloudflare": { + "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==", + "optional": true + }, + "node_modules/pg-connection-string": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.4.tgz", + "integrity": "sha512-v+Z7W/0EO707aNMaAEfiGnGL9sxxumwLl2fJvCQtMn9Fxsg+lPpPkdcyBSv/KFgpGdYkMfn+EI1Or2EHjpgLCA==" + }, + "node_modules/pg-hstore": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/pg-hstore/-/pg-hstore-2.3.4.tgz", + "integrity": "sha512-N3SGs/Rf+xA1M2/n0JBiXFDVMzdekwLZLAO0g7mpDY9ouX+fDI7jS6kTq3JujmYbtNSJ53TJ0q4G98KVZSM4EA==", + "dependencies": { + "underscore": "^1.13.1" + }, + "engines": { + "node": ">= 0.8.x" + } + }, + "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==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/pg-pool": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.2.tgz", + "integrity": "sha512-Htjbg8BlwXqSBQ9V8Vjtc+vzf/6fVUuak/3/XXKA9oxZprwW3IMDQTGHP+KDmVL7rtd+R1QjbnCFPuTHm3G4hg==", + "peerDependencies": { + "pg": ">=8.0" + } + }, + "node_modules/pg-protocol": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.1.tgz", + "integrity": "sha512-jPIlvgoD63hrEuihvIg+tJhoGjUsLPn6poJY9N5CnlPd91c2T18T/9zBtLxZSb1EhYxBRoZJtzScCaWlYLtktg==" + }, + "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==", + "dependencies": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pgpass": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.2.tgz", + "integrity": "sha1-Knu0G2BltnkH6R2hsHwYR8h3swY=", + "dependencies": { + "split": "^1.0.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==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/possible-typed-array-names": { + "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==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postgres-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/postgres-bytea": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-date": { + "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==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-interval": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "dependencies": { + "xtend": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" + }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" + }, + "node_modules/qs": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", + "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true, + "license": "MIT" + }, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/readline-sync": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/readline-sync/-/readline-sync-1.4.10.tgz", + "integrity": "sha512-gNva8/6UAe8QYepIQH/jQ2qn91Qj0B9sYjMBBs3QOB8F2CXcKgLxQaJRP76sWVRQt+QU+8fAkCbCvjjMFu7Ycw==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/redis-errors": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", + "integrity": "sha1-62LSrbFeTq9GEMBK/hUpOEJQq60=", + "engines": { + "node": ">=4" + } + }, + "node_modules/redis-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", + "integrity": "sha1-tm2CjNyv5rS4pCin3vTGvKwxyLQ=", + "dependencies": { + "redis-errors": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/reflect-metadata": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", + "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==" + }, + "node_modules/request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve.exports": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "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==" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/sax": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", + "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=" + }, + "node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/send/node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true, + "license": "ISC" + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/simple-update-notifier/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/sinon": { + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-18.0.0.tgz", + "integrity": "sha512-+dXDXzD1sBO6HlmZDd7mXZCR/y5ECiEiGCBSGuFD/kZ0bDTofPYc6JaeGmPSF+1j1MejGUWkORbYOLDyvqCWpA==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^3.0.1", + "@sinonjs/fake-timers": "^11.2.2", + "@sinonjs/samsam": "^8.0.0", + "diff": "^5.2.0", + "nise": "^6.0.0", + "supports-color": "^7" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/sinon" + } + }, + "node_modules/sinon/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/sinon/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true, + "license": "MIT" + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/split": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", + "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", + "dependencies": { + "through": "2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "node_modules/sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stack-generator": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/stack-generator/-/stack-generator-2.0.10.tgz", + "integrity": "sha512-mwnua/hkqM6pF4k8SnmZ2zfETsRUpWXREfA/goT8SLCV4iOFa4bzOX2nDipWAZFPTjLvQB82f5yaodMVhK0yJQ==", + "dependencies": { + "stackframe": "^1.3.4" + } + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/stackframe": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", + "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==" + }, + "node_modules/standard-as-callback": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", + "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==" + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/stream-transform": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/stream-transform/-/stream-transform-3.3.2.tgz", + "integrity": "sha512-v64PUnPy9Qw94NGuaEMo+9RHQe4jTBYf+NkTtqkCgeuiNo8NlL0LtLR7fkKWNVFtp3RhIm5Dlxkgm5uz7TDimQ==" + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string_decoder": { + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/superagent": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-9.0.2.tgz", + "integrity": "sha512-xuW7dzkUpcJq7QnhOsnNUgtYp3xRwpt2F7abdRYIpCsAt0hhUqia0EdxyXZQQpNmGtsCzYHryaKSV3q3GJnq7w==", + "dev": true, + "dependencies": { + "component-emitter": "^1.3.0", + "cookiejar": "^2.1.4", + "debug": "^4.3.4", + "fast-safe-stringify": "^2.1.1", + "form-data": "^4.0.0", + "formidable": "^3.5.1", + "methods": "^1.1.2", + "mime": "2.6.0", + "qs": "^6.11.0" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/superagent/node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/superagent/node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/superagent/node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "dev": true, + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/supertest": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-7.0.0.tgz", + "integrity": "sha512-qlsr7fIC0lSddmA3tzojvzubYxvlGtzumcdHgPwbFWMISQwL22MhM2Y3LNt+6w9Yyx7559VW5ab70dgphm8qQA==", + "dev": true, + "dependencies": { + "methods": "^1.1.2", + "superagent": "^9.0.1" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "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, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/swagger-jsdoc": { + "version": "6.2.8", + "resolved": "https://registry.npmjs.org/swagger-jsdoc/-/swagger-jsdoc-6.2.8.tgz", + "integrity": "sha512-VPvil1+JRpmJ55CgAtn8DIcpBs0bL5L3q5bVQvF4tAW/k/9JYSj7dCpaYCAv5rufe0vcCbBRQXGvzpkWjvLklQ==", + "dependencies": { + "commander": "6.2.0", + "doctrine": "3.0.0", + "glob": "7.1.6", + "lodash.mergewith": "^4.6.2", + "swagger-parser": "^10.0.3", + "yaml": "2.0.0-1" + }, + "bin": { + "swagger-jsdoc": "bin/swagger-jsdoc.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/swagger-jsdoc/node_modules/commander": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.0.tgz", + "integrity": "sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/swagger-jsdoc/node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/swagger-parser": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/swagger-parser/-/swagger-parser-10.0.3.tgz", + "integrity": "sha512-nF7oMeL4KypldrQhac8RyHerJeGPD1p2xDh900GPvc+Nk7nWP6jX2FcC7WmkinMoAmoO774+AFXcWsW8gMWEIg==", + "dependencies": { + "@apidevtools/swagger-parser": "10.0.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/swagger-ui-dist": { + "version": "5.17.14", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.17.14.tgz", + "integrity": "sha512-CVbSfaLpstV65OnSjbXfVd6Sta3q3F7Cj/yYuvHMp1P90LztOLs6PfUnKEVAeiIVQt9u2SaPwv0LiH/OyMjHRw==" + }, + "node_modules/swagger-ui-express": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-5.0.1.tgz", + "integrity": "sha512-SrNU3RiBGTLLmFU8GIJdOdanJTl4TOmT27tt3bWWHppqYmAZ6IDuEuBvMU6nZq0zLEe6b/1rACXCgLZqO6ZfrA==", + "dependencies": { + "swagger-ui-dist": ">=5.0.0" + }, + "engines": { + "node": ">= v0.10.32" + }, + "peerDependencies": { + "express": ">=4.0.0 || >=5.0.0-beta" + } + }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "dev": true, + "license": "ISC", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "license": "ISC", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "node_modules/timezone-support": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/timezone-support/-/timezone-support-1.8.1.tgz", + "integrity": "sha512-+pKzxoUe4PZXaQcswceJlA+69oRyyu1uivnYKdpsC7eGzZiuvTLbU4WYPqTKslEsoSvjN8k/u/6qNfGikBB/wA==", + "dependencies": { + "commander": "2.19.0" + }, + "bin": { + "create-timezone-data": "bin/create-timezone-data" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/timezone-support/node_modules/commander": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", + "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==" + }, + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "dev": true, + "dependencies": { + "nopt": "~1.0.10" + }, + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, + "node_modules/tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/ts-jest": { + "version": "29.2.5", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.2.5.tgz", + "integrity": "sha512-KD8zB2aAZrcKIdGk4OwpJggeLcH1FgrICqDSROWqlnJXGCXK4Mn6FcdK2B6670Xr73lHMG1kHw8R87A0ecZ+vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "bs-logger": "^0.2.6", + "ejs": "^3.1.10", + "fast-json-stable-stringify": "^2.1.0", + "jest-util": "^29.0.0", + "json5": "^2.2.3", + "lodash.memoize": "^4.1.2", + "make-error": "^1.3.6", + "semver": "^7.6.3", + "yargs-parser": "^21.1.1" + }, + "bin": { + "ts-jest": "cli.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/transform": "^29.0.0", + "@jest/types": "^29.0.0", + "babel-jest": "^29.0.0", + "jest": "^29.0.0", + "typescript": ">=4.3 <6" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@jest/transform": { + "optional": true + }, + "@jest/types": { + "optional": true + }, + "babel-jest": { + "optional": true + }, + "esbuild": { + "optional": true + } + } + }, + "node_modules/ts-jest/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ts-jest/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/ts-node/node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/tsconfig-paths": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", + "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", + "dependencies": { + "json5": "^2.2.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tslib": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", + "dev": true + }, + "node_modules/tslint": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-6.1.3.tgz", + "integrity": "sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg==", + "deprecated": "TSLint has been deprecated in favor of ESLint. Please see https://github.com/palantir/tslint/issues/4534 for more information.", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^4.0.1", + "glob": "^7.1.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.3", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.13.0", + "tsutils": "^2.29.0" + }, + "bin": { + "tslint": "bin/tslint" + }, + "engines": { + "node": ">=4.8.0" + }, + "peerDependencies": { + "typescript": ">=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev || >= 4.0.0-dev" + } + }, + "node_modules/tslint/node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/tslint/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/tsutils": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "peerDependencies": { + "typescript": ">=2.1.0 || >=2.1.0-dev || >=2.2.0-dev || >=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >= 3.0.0-dev || >= 3.1.0-dev" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typeorm": { + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.3.20.tgz", + "integrity": "sha512-sJ0T08dV5eoZroaq9uPKBoNcGslHBR4E4y+EBHs//SiGbblGe7IeduP/IH4ddCcj0qp3PHwDwGnuvqEAnKlq/Q==", + "dependencies": { + "@sqltools/formatter": "^1.2.5", + "app-root-path": "^3.1.0", + "buffer": "^6.0.3", + "chalk": "^4.1.2", + "cli-highlight": "^2.1.11", + "dayjs": "^1.11.9", + "debug": "^4.3.4", + "dotenv": "^16.0.3", + "glob": "^10.3.10", + "mkdirp": "^2.1.3", + "reflect-metadata": "^0.2.1", + "sha.js": "^2.4.11", + "tslib": "^2.5.0", + "uuid": "^9.0.0", + "yargs": "^17.6.2" + }, + "bin": { + "typeorm": "cli.js", + "typeorm-ts-node-commonjs": "cli-ts-node-commonjs.js", + "typeorm-ts-node-esm": "cli-ts-node-esm.js" + }, + "engines": { + "node": ">=16.13.0" + }, + "funding": { + "url": "https://opencollective.com/typeorm" + }, + "peerDependencies": { + "@google-cloud/spanner": "^5.18.0", + "@sap/hana-client": "^2.12.25", + "better-sqlite3": "^7.1.2 || ^8.0.0 || ^9.0.0", + "hdb-pool": "^0.1.6", + "ioredis": "^5.0.4", + "mongodb": "^5.8.0", + "mssql": "^9.1.1 || ^10.0.1", + "mysql2": "^2.2.5 || ^3.0.1", + "oracledb": "^6.3.0", + "pg": "^8.5.1", + "pg-native": "^3.0.0", + "pg-query-stream": "^4.0.0", + "redis": "^3.1.1 || ^4.0.0", + "sql.js": "^1.4.0", + "sqlite3": "^5.0.3", + "ts-node": "^10.7.0", + "typeorm-aurora-data-api-driver": "^2.0.0" + }, + "peerDependenciesMeta": { + "@google-cloud/spanner": { + "optional": true + }, + "@sap/hana-client": { + "optional": true + }, + "better-sqlite3": { + "optional": true + }, + "hdb-pool": { + "optional": true + }, + "ioredis": { + "optional": true + }, + "mongodb": { + "optional": true + }, + "mssql": { + "optional": true + }, + "mysql2": { + "optional": true + }, + "oracledb": { + "optional": true + }, + "pg": { + "optional": true + }, + "pg-native": { + "optional": true + }, + "pg-query-stream": { + "optional": true + }, + "redis": { + "optional": true + }, + "sql.js": { + "optional": true + }, + "sqlite3": { + "optional": true + }, + "ts-node": { + "optional": true + }, + "typeorm-aurora-data-api-driver": { + "optional": true + } + } + }, + "node_modules/typeorm/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/typeorm/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/typeorm/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/typeorm/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/typeorm/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/typeorm/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/typeorm/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/typeorm/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/typeorm/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/typeorm/node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/typeorm/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/typeorm/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/typeorm/node_modules/mkdirp": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-2.1.6.tgz", + "integrity": "sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A==", + "bin": { + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/typeorm/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/typeorm/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" + }, + "node_modules/typeorm/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/typeorm/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/typeorm/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/typescript": { + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", + "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "dependencies": { + "random-bytes": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true + }, + "node_modules/underscore": { + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.3.tgz", + "integrity": "sha512-QvjkYpiD+dJJraRA8+dGAU4i7aBbb2s0S3jA45TFOvg2VgqvdCDd/3N6CqA8gluk1W91GLoXg5enMUx560QzuA==" + }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/url": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", + "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", + "dependencies": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "node_modules/url/node_modules/punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==" + }, + "node_modules/v8-to-istanbul": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "dev": true, + "license": "ISC", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/v8-to-istanbul/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/validator": { + "version": "13.12.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.12.0.tgz", + "integrity": "sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-typed-array": { + "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==", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/workerpool": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", + "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", + "dev": true + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/xml2js": { + "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" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "node_modules/yaml": { + "version": "2.0.0-1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.0.0-1.tgz", + "integrity": "sha512-W7h5dEhywMKenDJh2iX/LABkbFnBxasD27oyXWDS/feDsxiw0dD5ncXdYXgkvAsXIY2MpW/ZKkr9IU30DBdMNQ==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/z-schema": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-5.0.5.tgz", + "integrity": "sha512-D7eujBWkLa3p2sIpJA0d1pr7es+a7m0vFAnZLlCEKq/Ij2k0MLi9Br2UPxoxdYystm5K1yeBGzub0FlYUEWj2Q==", + "dependencies": { + "lodash.get": "^4.4.2", + "lodash.isequal": "^4.5.0", + "validator": "^13.7.0" + }, + "bin": { + "z-schema": "bin/z-schema" + }, + "engines": { + "node": ">=8.0.0" + }, + "optionalDependencies": { + "commander": "^9.4.1" + } + }, + "node_modules/z-schema/node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "optional": true, + "engines": { + "node": "^12.20.0 || >=14" + } } - } - }, - "zen-observable": { - "version": "0.8.15", - "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.15.tgz", - "integrity": "sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==" - }, - "zen-observable-ts": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-1.1.0.tgz", - "integrity": "sha512-1h4zlLSqI2cRLPJUHJFL8bCWHhkpuXkF+dbGkRaWjgDIG26DmzyshUMrdV/rL3UnR+mhaX4fRq8LPouq0MYYIA==", - "requires": { - "@types/zen-observable": "0.8.3", - "zen-observable": "0.8.15" - } } - } } diff --git a/api/package.json b/api/package.json index 83041acc0..e3a435630 100644 --- a/api/package.json +++ b/api/package.json @@ -9,9 +9,9 @@ "testdev": "npm-run-all -p -r start test", "lint": "tslint */**.ts", "posttest": "npm run lint", - "test": "mocha --timeout 5000 --require ts-node/register test/setup.ts test/**/*.spec.ts", - "testone": "mocha --timeout 5000 --require ts-node/register test/setup.ts", - "test-watch": "mocha --watch --require ts-node/register --watch-extensions ts test/setup.ts test/**/*.spec.ts", + "test": "jest --config jest.config.js", + "testone": "jest --config jest.config.js --testPathPattern", + "test-watch": "jest --config jest.config.js --watch", "seed": "ts-node models/seeds/index.ts", "queue": "ts-node models/seeds/index.ts", "console": "ts-node", @@ -22,59 +22,63 @@ "typeorm:cli": "ts-node ./node_modules/typeorm/cli.js -f ./models/ormconfig.ts" }, "dependencies": { - "@bugsnag/js": "^6.4.0", - "@bugsnag/plugin-express": "^6.4.0", - "@types/bcrypt": "^3.0.0", - "@types/bcryptjs": "^2.4.2", - "@types/express": "^4.16.1", - "@types/express-fileupload": "^1.1.0", - "@types/express-session": "^1.15.12", - "aws-sdk": "^2.1135.0", + "@bugsnag/js": "^8.0.0", + "@bugsnag/plugin-express": "^8.0.0", + "@types/bcrypt": "^5.0.2", + "@types/bcryptjs": "^2.4.6", + "@types/express": "^4.17.21", + "@types/express-fileupload": "^1.5.1", + "@types/express-session": "^1.18.0", + "aws-sdk": "^2.1691.0", "bcryptjs": "^2.4.3", - "bull": "^3.15.0", - "chai": "^4.2.0", - "class-validator": "^0.9.1", - "cookie-parser": "~1.4.3", + "bull": "^4.16.2", + "chai": "^5.1.1", + "class-validator": "^0.14.1", + "cookie-parser": "~1.4.6", "cors": "^2.8.5", - "csv": "^5.1.1", - "csv-parse": "^4.4.6", + "csv": "^6.3.10", + "csv-parse": "^5.5.6", + "date-and-time": "^3.6.0", "date-fns-timezone": "^0.1.4", - "dateformat": "^3.0.3", - "debug": "~2.6.9", - "express": "~4.16.0", - "express-fileupload": "^1.3.1", - "express-session": "^1.15.6", + "debug": "~4.3.7", + "express": "~4.19.2", + "express-fileupload": "^1.5.1", + "express-session": "^1.18.0", "flash": "^1.1.0", - "http-errors": "~1.6.2", - "ioredis": "^4.9.0", - "json2csv": "^4.5.3", - "jsonwebtoken": "^8.5.1", - "morgan": "~1.9.0", - "node-fetch": "^2.6.7", - "pg": "^7.9.0", - "pg-hstore": "^2.3.2", - "reflect-metadata": "^0.1.13", - "request": "^2.88.0", - "swagger-jsdoc": "^3.3.0", - "swagger-ui-express": "^4.4.0", - "ts-node": "3.3.0", - "tsconfig-paths": "3.8.0", - "typeorm": "^0.2.45", - "typescript": "3.5.3" + "http-errors": "~2.0.0", + "ioredis": "^5.4.1", + "json2csv": "^5.0.7", + "jsonwebtoken": "^9.0.2", + "morgan": "~1.10.0", + "node-fetch": "^2.7.0", + "pg": "^8.12.0", + "pg-hstore": "^2.3.4", + "reflect-metadata": "^0.2.2", + "request": "^2.88.2", + "swagger-jsdoc": "^6.2.8", + "swagger-ui-express": "^5.0.1", + "ts-node": "10.9.2", + "tsconfig-paths": "4.2.0", + "typeorm": "^0.3.20", + "typescript": "5.5.4" }, "devDependencies": { - "@types/bull": "^3.10.2", - "@types/mocha": "^5.2.6", - "@types/node": "^8.0.29", - "chai-as-promised": "^7.1.1", - "faker": "^4.1.0", - "ioredis-mock": "^4.9.0", - "libxmljs": "^0.19.7", - "mocha": "^6.2.3", - "nodemon": "^1.18.10", - "sinon": "^7.5.0", - "supertest": "^4.0.2", - "tslint": "^5.14.0", - "typeorm-fixtures": "^0.8.5" + "@faker-js/faker": "^9.0.3", + "@types/dateformat": "^5.0.2", + "@types/jest": "^29.5.14", + "@types/mocha": "^10.0.7", + "@types/node": "^22.5.4", + "chai-as-promised": "^8.0.0", + "faker": "^6.6.6", + "ioredis-mock": "^8.9.0", + "jest": "^29.7.0", + "libxmljs": "1.0.8", + "mocha": "^10.7.3", + "nodemon": "^3.1.4", + "sinon": "^18.0.0", + "supertest": "^7.0.0", + "ts-jest": "^29.2.5", + "tslint": "^6.1.3", + "xml2js": "^0.6.2" } } diff --git a/api/services/activityService.ts b/api/services/activityService.ts index 9955cb7af..f181690b5 100644 --- a/api/services/activityService.ts +++ b/api/services/activityService.ts @@ -7,16 +7,13 @@ import { getActivityByExpenditureAsync, getActivityByGovernmentAsync, IActivityResults, - IShortActivityResult + IShortActivityResult, } from '../models/entity/Activity'; -import { getConnection } from 'typeorm'; import { Government } from '../models/entity/Government'; import { User } from '../models/entity/User'; import { Campaign } from '../models/entity/Campaign'; import { isCampaignAdminAsync, isCampaignStaffAsync, isGovernmentAdminAsync } from './permissionService'; -import { Contribution } from '../models/entity/Contribution'; -import { Expenditure } from '../models/entity/Expenditure'; -import * as fs from 'fs'; +import db from '../models/db'; export interface ICreateActivityServiceParams { currentUser: User; @@ -30,7 +27,8 @@ export interface ICreateActivityServiceParams { } export async function createActivityRecordAsync(params: ICreateActivityServiceParams): Promise { - const repository = getConnection('default').getRepository('Activity'); + const dataSource = await db(); + const repository = dataSource.getRepository('Activity'); let activity = new Activity(); activity.user = params.currentUser; activity.government = params.government; @@ -52,13 +50,15 @@ export interface IGetActivityRecords { governmentId?: number; // get all activities by government, requires government admin campaignId?: number; // get all activities by government, requires government admin, campaign admin or staff contributionId?: number; // get all activities by contribution, includes comments - expenditureId?: number; // get all activities by expenditures + expenditureId?: number; // get all activities by expenditures perPage?: number; page?: number; } -export async function getAllActivityRecordsAsync(params: IGetActivityRecords, hostName: string): Promise { - +export async function getAllActivityRecordsAsync( + params: IGetActivityRecords, + hostName: string +): Promise { const perPage = params.perPage || 100; const page = params.page || 0; @@ -70,45 +70,59 @@ export async function getAllActivityRecordsAsync(params: IGetActivityRecords, ho } if (params.campaignId) { - const campaignRepository = getConnection('default').getRepository('Campaign'); + const dataSource = await db(); + const campaignRepository = dataSource.getRepository('Campaign'); - const campaign = (await campaignRepository.findOneOrFail(params.campaignId, { - relations: ['government'] - })) as Campaign; + const campaign = await campaignRepository.findOneOrFail({ + where: { id: params.campaignId }, + relations: ['government'], + }); const hasGovAdminPermissions = await isGovernmentAdminAsync(params.currentUserId, campaign.government.id); - const hasCampaignAdminPermissions = hasGovAdminPermissions || await isCampaignAdminAsync(params.currentUserId, params.campaignId); - const hasCampaignStaffPermissions = hasCampaignAdminPermissions || await isCampaignStaffAsync(params.currentUserId, params.campaignId); + const hasCampaignAdminPermissions = + hasGovAdminPermissions || (await isCampaignAdminAsync(params.currentUserId, params.campaignId)); + const hasCampaignStaffPermissions = + hasCampaignAdminPermissions || (await isCampaignStaffAsync(params.currentUserId, params.campaignId)); + if (hasGovAdminPermissions || hasCampaignAdminPermissions || hasCampaignStaffPermissions) { return getActivityByCampaignAsync(params.campaignId, perPage, page, hostName); } } if (params.contributionId) { - const contributionRepository = getConnection('default').getRepository('Contribution'); + const dataSource = await db(); + const contributionRepository = dataSource.getRepository('Contribution'); - const contribution = (await contributionRepository.findOneOrFail(params.contributionId, { - relations: ['government', 'campaign'] - })) as Contribution; + const contribution = await contributionRepository.findOneOrFail({ + where: { id: params.contributionId }, + relations: ['government', 'campaign'], + }); const hasGovAdminPermissions = await isGovernmentAdminAsync(params.currentUserId, contribution.government.id); - const hasCampaignAdminPermissions = hasGovAdminPermissions || await isCampaignAdminAsync(params.currentUserId, contribution.campaign.id); - const hasCampaignStaffPermissions = hasCampaignAdminPermissions || await isCampaignStaffAsync(params.currentUserId, contribution.campaign.id); + const hasCampaignAdminPermissions = + hasGovAdminPermissions || (await isCampaignAdminAsync(params.currentUserId, contribution.campaign.id)); + const hasCampaignStaffPermissions = + hasCampaignAdminPermissions || (await isCampaignStaffAsync(params.currentUserId, contribution.campaign.id)); + if (hasGovAdminPermissions || hasCampaignAdminPermissions || hasCampaignStaffPermissions) { return getActivityByContributionAsync(params.contributionId, perPage, page, hostName); } } if (params.expenditureId) { - const expenditureRepository = getConnection('default').getRepository('Expenditure'); + const dataSource = await db(); + const expenditureRepository = dataSource.getRepository('Expenditure'); - const expenditure = (await expenditureRepository.findOneOrFail(params.expenditureId, { - relations: ['government', 'campaign'] - })) as Expenditure; + const expenditure = await expenditureRepository.findOneOrFail({ + where: { id: params.expenditureId }, + relations: ['government', 'campaign'], + }); const hasGovAdminPermissions = await isGovernmentAdminAsync(params.currentUserId, expenditure.government.id); - const hasCampaignAdminPermissions = hasGovAdminPermissions || await isCampaignAdminAsync(params.currentUserId, expenditure.campaign.id); - const hasCampaignStaffPermissions = hasCampaignAdminPermissions || await isCampaignStaffAsync(params.currentUserId, expenditure.campaign.id); + const hasCampaignAdminPermissions = + hasGovAdminPermissions || (await isCampaignAdminAsync(params.currentUserId, expenditure.campaign.id)); + const hasCampaignStaffPermissions = + hasCampaignAdminPermissions || (await isCampaignStaffAsync(params.currentUserId, expenditure.campaign.id)); if (hasGovAdminPermissions || hasCampaignAdminPermissions || hasCampaignStaffPermissions) { return getActivityByExpenditureAsync(params.expenditureId, perPage, page, hostName); @@ -119,7 +133,7 @@ export async function getAllActivityRecordsAsync(params: IGetActivityRecords, ho total: 0, perPage, page, - data: [] + data: [], }; } @@ -129,22 +143,27 @@ export interface IGetActivityRecordsForEmails { to: Date; } -export async function getActivityRecordsForEmailsAsync(params: IGetActivityRecordsForEmails): Promise { +export async function getActivityRecordsForEmailsAsync( + params: IGetActivityRecordsForEmails +): Promise { return await getActivityByCampaignByTimeAsync(params.campaignId, params.from, params.to); } - export interface IGetActivityAttachment { currentUserId: number; activityId: number; } -export async function getActivityAttachmentAsync(params: IGetActivityAttachment): Promise<{contentType: string, buffer: Buffer, fileName?: string}> { - const activityRepository = getConnection('default').getRepository('Activity'); +export async function getActivityAttachmentAsync( + params: IGetActivityAttachment +): Promise<{ contentType: string; buffer: Buffer; fileName?: string }> { + const dataSource = await db(); + const activityRepository = dataSource.getRepository('Activity'); - const activity = (await activityRepository.findOneOrFail(params.activityId, { - relations: ['campaign', 'government'] - })) as Activity; + const activity = await activityRepository.findOneOrFail({ + where: { id: params.activityId }, + relations: ['campaign', 'government'], + }); const isGovernmentAdmin = await isGovernmentAdminAsync(params.currentUserId, activity.government.id); let isCampaignAdmin = false; @@ -163,7 +182,9 @@ export async function getActivityAttachmentAsync(params: IGetActivityAttachment) } } -export async function getFileAttachmentAsync(filePath: string): Promise<{contentType: string, buffer: Buffer, fileName?: string}> { +export async function getFileAttachmentAsync( + filePath: string +): Promise<{ contentType: string; buffer: Buffer; fileName?: string }> { // if (process.env.APP_ENV === 'development' || process.env.NODE_ENV === 'test') { // return( // Promise.resolve({ @@ -176,30 +197,40 @@ export async function getFileAttachmentAsync(filePath: string): Promise<{content let key = new URL(filePath).pathname; key = key.substr(1); const AWS = require('aws-sdk'); - const s3 = new AWS.S3({apiVersion: '2006-03-01'}); - const data = await s3.getObject({Bucket: 'open-elections', Key: key}).promise(); + const s3 = new AWS.S3({ apiVersion: '2006-03-01' }); + const data = await s3.getObject({ Bucket: 'open-elections', Key: key }).promise(); const fileNameArray = key.split('/'); const fileName = fileNameArray[fileNameArray.length - 1]; - return {contentType: data.ContentType, buffer: data.Body, fileName}; + return { contentType: data.ContentType, buffer: data.Body, fileName }; } -export async function saveFileAttachmentAsync(id: number, type: 'expenditures' | 'contributions', fileName: string, filePath: string): Promise { +export async function saveFileAttachmentAsync( + id: number, + type: 'expenditures' | 'contributions', + fileName: string, + filePath: string +): Promise { // if (process.env.APP_ENV === 'development' || process.env.NODE_ENV === 'test') { // return Promise.resolve(filePath); // } let folder = 'production-uploads'; // if (process.env.APP_ENV === 'staging') { - folder = 'qa-uploads'; + folder = 'qa-uploads'; // } - if (!process.env.AWS_ACCESS_KEY_ID || !process.env.AWS_SECRET_ACCESS_KEY || !process.env.AWS_DEFAULT_REGION || !process.env.HOST_URL) { + if ( + !process.env.AWS_ACCESS_KEY_ID || + !process.env.AWS_SECRET_ACCESS_KEY || + !process.env.AWS_DEFAULT_REGION || + !process.env.HOST_URL + ) { throw new Error('The API needs AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY passed in as env variables'); } const AWS = require('aws-sdk'); - const s3 = new AWS.S3({apiVersion: '2006-03-01'}); - const uploadParams = {Bucket: 'open-elections', Key: '', Body: ''}; + const s3 = new AWS.S3({ apiVersion: '2006-03-01' }); + const uploadParams = { Bucket: 'open-elections', Key: '', Body: '' }; const fs = require('fs'); const fileStream = fs.createReadStream(filePath); diff --git a/api/services/bugsnagService.ts b/api/services/bugsnagService.ts index 1375a2cf5..b50895296 100644 --- a/api/services/bugsnagService.ts +++ b/api/services/bugsnagService.ts @@ -1,12 +1,11 @@ -import bugsnag from '@bugsnag/js'; +import Bugsnag from '@bugsnag/js'; export const bugsnagClient = (() => { if (process.env.NODE_ENV === 'production') { - return bugsnag({ + return Bugsnag.start({ apiKey: process.env.BUG_SNAG_API_KEY, - releaseStage: process.env.APP_ENV + releaseStage: process.env.APP_ENV, }); } return; })(); - diff --git a/api/services/campaignService.ts b/api/services/campaignService.ts index 4a421a512..014e4cf3d 100644 --- a/api/services/campaignService.ts +++ b/api/services/campaignService.ts @@ -1,22 +1,18 @@ -import { getConnection } from 'typeorm'; import { Campaign, getCampaignSummariesByGovernmentIdAsync, ICampaignSummary } from '../models/entity/Campaign'; import { Government } from '../models/entity/Government'; import { addUserToCampaignAsync, isCampaignAdminAsync, isCampaignStaffAsync, - isGovernmentAdminAsync + isGovernmentAdminAsync, } from './permissionService'; import { UserRole } from '../models/entity/Permission'; import { ExpenditureSummaryByStatus, getExpenditureSummaryByStatusAsync } from '../models/entity/Expenditure'; -import { - Contribution, - ContributionSummaryByStatus, - getContributionsSummaryByStatusAsync -} from '../models/entity/Contribution'; +import { ContributionSummaryByStatus, getContributionsSummaryByStatusAsync } from '../models/entity/Contribution'; import { User } from '../models/entity/User'; import { ActivityTypeEnum } from '../models/entity/Activity'; import { createActivityRecordAsync } from './activityService'; +import db from '../models/db'; export interface ICreateCampaign { name: string; @@ -37,17 +33,19 @@ export interface IUpdateCampaignName { export async function createCampaignAsync(campaignAttrs: ICreateCampaign): Promise { try { - + const dataSource = await db(); if (await isGovernmentAdminAsync(campaignAttrs.currentUserId, campaignAttrs.governmentId)) { - const campaignRepository = getConnection('default').getRepository('Campaign'); - const governmentRepository = getConnection('default').getRepository('Government'); + const campaignRepository = dataSource.getRepository('Campaign'); + const governmentRepository = dataSource.getRepository('Government'); const campaign = new Campaign(); campaign.name = campaignAttrs.name; campaign.officeSought = campaignAttrs.officeSought; - const government = (await governmentRepository.findOne(campaignAttrs.governmentId)) as Government; + const government = (await governmentRepository.findOne({ + where: { id: campaignAttrs.governmentId }, + })) as Government; campaign.government = government; if (await campaign.isValidAsync()) { - const savedCampaign = await campaignRepository.save(campaign) as Campaign; + const savedCampaign = (await campaignRepository.save(campaign)) as Campaign; if (campaignAttrs.email && campaignAttrs.firstName && campaignAttrs.lastName) { await addUserToCampaignAsync({ email: campaignAttrs.email, @@ -55,7 +53,7 @@ export async function createCampaignAsync(campaignAttrs: ICreateCampaign): Promi lastName: campaignAttrs.lastName, role: UserRole.CAMPAIGN_ADMIN, campaignId: savedCampaign.id, - currentUserId: campaignAttrs.currentUserId + currentUserId: campaignAttrs.currentUserId, }); } } else { @@ -72,25 +70,30 @@ export async function createCampaignAsync(campaignAttrs: ICreateCampaign): Promi export async function updateCampaignNameAsync(campaignAttrs: IUpdateCampaignName): Promise { try { + const dataSource = await db(); if (await isGovernmentAdminAsync(campaignAttrs.currentUserId, campaignAttrs.governmentId)) { - const campaignRepository = getConnection('default').getRepository('Campaign'); - const governmentRepository = getConnection('default').getRepository('Government'); - const campaign = (await campaignRepository.findOne(campaignAttrs.campaignId) as Campaign); + const campaignRepository = dataSource.getRepository('Campaign'); + const governmentRepository = dataSource.getRepository('Government'); + const campaign = (await campaignRepository.findOne({ + where: { id: campaignAttrs.campaignId }, + })) as Campaign; const oldName = campaign.name; campaign.name = campaignAttrs.newName; - const government = (await governmentRepository.findOne(campaignAttrs.governmentId)) as Government; + const government = (await governmentRepository.findOne({ + where: { id: campaignAttrs.governmentId }, + })) as Government; campaign.government = government; if (await campaign.isValidAsync()) { - await campaignRepository.save(campaign) as Campaign; - const repository = getConnection('default').getRepository('User'); - const user = await repository.findOneOrFail(campaignAttrs.currentUserId) as User; + (await campaignRepository.save(campaign)) as Campaign; + const repository = dataSource.getRepository('User'); + const user = (await repository.findOneOrFail({ where: { id: campaignAttrs.currentUserId } })) as User; await createActivityRecordAsync({ currentUser: user, notes: `${user.name()} changed Campaign name from "${oldName}" to "${campaignAttrs.newName}"`, government: await campaign.government, campaign: campaign, activityType: ActivityTypeEnum.CAMPAIGN, - activityId: user.id + activityId: user.id, }); } else { throw new Error('Campaign is not valid'); @@ -109,7 +112,7 @@ export interface IGetCampaigns { governmentId: number; } -export async function getCampaignsAsync({currentUserId, governmentId}: IGetCampaigns): Promise { +export async function getCampaignsAsync({ currentUserId, governmentId }: IGetCampaigns): Promise { try { if (await isGovernmentAdminAsync(currentUserId, governmentId)) { return getCampaignSummariesByGovernmentIdAsync(governmentId); @@ -134,37 +137,44 @@ export interface StatusSummary { export async function getStatusSummary(attrs: GetStatusSummaryAttrs): Promise { if (attrs.campaignId) { - const repository = getConnection('default').getRepository('Campaign'); - const campaign = (await repository.findOneOrFail(attrs.campaignId, { - relations: ['government'] + const dataSource = await db(); + const repository = dataSource.getRepository('Campaign'); + const campaign = (await repository.findOneOrFail({ + where: { id: attrs.campaignId }, + relations: ['government'], })) as Campaign; const hasGovPermissions = await isGovernmentAdminAsync(attrs.currentUserId, campaign.government.id); - const hasCampaignPermissions = await isCampaignAdminAsync(attrs.currentUserId, attrs.campaignId) || await isCampaignStaffAsync(attrs.currentUserId, attrs.campaignId); + const hasCampaignPermissions = + (await isCampaignAdminAsync(attrs.currentUserId, attrs.campaignId)) || + (await isCampaignStaffAsync(attrs.currentUserId, attrs.campaignId)); if (hasGovPermissions || hasCampaignPermissions) { const contributions = await getContributionsSummaryByStatusAsync({ - campaignId: attrs.campaignId + campaignId: attrs.campaignId, }); const expenditures = await getExpenditureSummaryByStatusAsync({ - campaignId: attrs.campaignId + campaignId: attrs.campaignId, }); return { expenditures, - contributions + contributions, }; } else { throw new Error('User does not have permissions for this campaign'); } } else if (attrs.governmentId) { const hasGovPermissions = await isGovernmentAdminAsync(attrs.currentUserId, attrs.governmentId); + if (!hasGovPermissions) { + throw new Error('User does not have permissions for this government'); + } const contributions = await getContributionsSummaryByStatusAsync({ - governmentId: attrs.governmentId + governmentId: attrs.governmentId, }); const expenditures = await getExpenditureSummaryByStatusAsync({ - governmentId: attrs.governmentId + governmentId: attrs.governmentId, }); return { expenditures, - contributions + contributions, }; } throw new Error('Either governmentId or campaignId must be present'); diff --git a/api/services/contributionService.ts b/api/services/contributionService.ts index ffbecd305..9a799c83d 100644 --- a/api/services/contributionService.ts +++ b/api/services/contributionService.ts @@ -1,4 +1,3 @@ -import { getConnection } from 'typeorm'; import { Contribution, contributionGovSummaryFields, @@ -27,11 +26,12 @@ import { isCampaignAdminAsync, isCampaignStaffAsync, isGovernmentAdminAsync } fr import { User } from '../models/entity/User'; import { Activity, ActivityTypeEnum } from '../models/entity/Activity'; import { createActivityRecordAsync, saveFileAttachmentAsync } from './activityService'; -import { MatchAddressType, MatchDonorInfoType, PersonMatchType, retrieveResultAsync } from './dataScienceService'; +import { PersonMatchType, retrieveResultAsync } from './dataScienceService'; import * as crypto from 'crypto'; import { geocodeAddressAsync } from './gisService'; import { addDataScienceJob, renderError } from '../jobs/helpers/addJobs'; import { UploadedFile } from 'express-fileupload'; +import db from '../models/db'; export interface IAddContributionAttrs { address1: string; @@ -73,19 +73,19 @@ export interface IAddContributionAttrs { export async function getContributionErrorsAsync(contributionAttrs: IAddContributionAttrs): Promise { try { + const dataSource = await db(); const hasCampaignPermissions = (await isCampaignAdminAsync(contributionAttrs.currentUserId, contributionAttrs.campaignId)) || (await isCampaignStaffAsync(contributionAttrs.currentUserId, contributionAttrs.campaignId)); if (hasCampaignPermissions) { - const defaultConn = getConnection('default'); - const governmentRepository = defaultConn.getRepository('Government'); - const campaignRepository = defaultConn.getRepository('Campaign'); + const governmentRepository = dataSource.getRepository('Government'); + const campaignRepository = dataSource.getRepository('Campaign'); const contribution = new Contribution(); const [campaign, government] = await Promise.all([ - campaignRepository.findOne(contributionAttrs.campaignId), - governmentRepository.findOne(contributionAttrs.governmentId), + campaignRepository.findOne({ where: { id: contributionAttrs.campaignId } }), + governmentRepository.findOne({ where: { id: contributionAttrs.governmentId } }), ]); contribution.campaign = campaign as Campaign; @@ -145,22 +145,22 @@ export async function getContributionErrorsAsync(contributionAttrs: IAddContribu export async function addContributionAsync(contributionAttrs: IAddContributionAttrs): Promise { try { + const dataSource = await db(); const hasCampaignPermissions = (await isCampaignAdminAsync(contributionAttrs.currentUserId, contributionAttrs.campaignId)) || (await isCampaignStaffAsync(contributionAttrs.currentUserId, contributionAttrs.campaignId)); if (hasCampaignPermissions) { - const defaultConn = getConnection('default'); - const contributionRepository = defaultConn.getRepository('Contribution'); - const governmentRepository = defaultConn.getRepository('Government'); - const campaignRepository = defaultConn.getRepository('Campaign'); - const userRepository = defaultConn.getRepository('User'); + const contributionRepository = dataSource.getRepository('Contribution'); + const governmentRepository = dataSource.getRepository('Government'); + const campaignRepository = dataSource.getRepository('Campaign'); + const userRepository = dataSource.getRepository('User'); const contribution = new Contribution(); const [campaign, government, user] = await Promise.all([ - campaignRepository.findOne(contributionAttrs.campaignId), - governmentRepository.findOne(contributionAttrs.governmentId), - userRepository.findOneOrFail(contributionAttrs.currentUserId) as unknown as User, + campaignRepository.findOne({ where: { id: contributionAttrs.campaignId } }), + governmentRepository.findOne({ where: { id: contributionAttrs.governmentId } }), + userRepository.findOneOrFail({ where: { id: contributionAttrs.currentUserId } }) as unknown as User, ]); contribution.campaign = campaign as Campaign; @@ -338,12 +338,17 @@ export interface IUpdateContributionAttrs { export async function updateContributionAsync(contributionAttrs: IUpdateContributionAttrs): Promise { try { - const defaultConn = getConnection('default'); - const contributionRepository = defaultConn.getRepository('Contribution'); - const userRepository = defaultConn.getRepository('User'); - let contribution = (await contributionRepository.findOneOrFail(contributionAttrs.id, { - relations: ['campaign', 'government'], - })) as Contribution; + const dataSource = await db(); + const contributionRepository = dataSource.getRepository('Contribution'); + const userRepository = dataSource.getRepository('User'); + let contribution = (await contributionRepository + .findOneOrFail({ + where: { id: contributionAttrs.id }, + relations: ['campaign', 'government'], + }) + .catch(() => { + throw new Error(`Could not find any entity of type "Contribution" matching: ${contributionAttrs.id}`); + })) as Contribution; const attrs = Object.assign({}, contributionAttrs); if (attrs.date) { attrs.date = new Date(attrs.date); @@ -390,7 +395,7 @@ export async function updateContributionAsync(contributionAttrs: IUpdateContribu if (hasCampaignPermissions) { const [_, user, changeNotes] = await Promise.all([ contributionRepository.update(contributionAttrs.id, attrs), - userRepository.findOneOrFail({ id: contributionAttrs.currentUserId }) as unknown as User, + userRepository.findOneOrFail({ where: { id: contributionAttrs.currentUserId } }) as unknown as User, Object.keys(attrs) .filter((key) => attrs[key] && attrs[key] !== '') .filter((key) => contribution[key] && contribution[key] !== '') @@ -407,7 +412,8 @@ export async function updateContributionAsync(contributionAttrs: IUpdateContribu activityId: contribution.id, notify: isGovAdmin, }); - contribution = (await contributionRepository.findOneOrFail(contributionAttrs.id, { + contribution = (await contributionRepository.findOneOrFail({ + where: { id: contributionAttrs.id }, relations: ['campaign', 'government'], })) as Contribution; return contribution; @@ -429,9 +435,11 @@ export async function getContributionByIdAsync( contributionAttrs: IGetContributionByIdAttrs ): Promise { try { + const dataSource = await db(); const { contributionId, currentUserId } = contributionAttrs; - const contributionRepository = getConnection('default').getRepository('Contribution'); - let contribution = (await contributionRepository.findOneOrFail(contributionId, { + const contributionRepository = dataSource.getRepository('Contribution'); + let contribution = (await contributionRepository.findOneOrFail({ + where: { id: contributionId }, relations: ['campaign', 'government'], })) as Contribution; const hasCampaignPermissions = @@ -460,14 +468,15 @@ export interface IArchiveContributionByIdOptions { export async function archiveContributionAsync(contrAttrs: IArchiveContributionByIdOptions) { try { - const defaultConn = getConnection('default'); - const contributionRepository = defaultConn.getRepository('Contribution'); - const userRepository = defaultConn.getRepository('User'); + const dataSource = await db(); + const contributionRepository = dataSource.getRepository('Contribution'); + const userRepository = dataSource.getRepository('User'); const [contribution, user] = await Promise.all([ - contributionRepository.findOneOrFail(contrAttrs.contributionId, { + contributionRepository.findOneOrFail({ + where: { id: contrAttrs.contributionId }, relations: ['campaign', 'government'], }) as unknown as Contribution, - userRepository.findOneOrFail(contrAttrs.currentUserId) as unknown as User, + userRepository.findOneOrFail({ where: { id: contrAttrs.currentUserId } }) as unknown as User, ]); const hasCampaignPermissions = (await isCampaignAdminAsync(contrAttrs.currentUserId, contribution.campaign.id)) || @@ -507,15 +516,21 @@ export interface IContributionCommentAttrs { export async function createContributionCommentAsync(attrs: IContributionCommentAttrs): Promise { try { - const defaultConn = getConnection('default'); - const contributionRepository = defaultConn.getRepository('Contribution'); - const userRepository = defaultConn.getRepository('User'); - const activityRepository = defaultConn.getRepository('Activity'); - const contribution = (await contributionRepository.findOneOrFail(attrs.contributionId, { - relations: ['campaign', 'government'], - })) as Contribution; + const dataSource = await db(); + const contributionRepository = dataSource.getRepository('Contribution'); + const userRepository = dataSource.getRepository('User'); + const activityRepository = dataSource.getRepository('Activity'); + const contribution = await contributionRepository + .findOneOrFail({ + where: { id: attrs.contributionId }, + relations: ['campaign', 'government'], + }) + .catch((error) => { + console.log(error.message); + throw new Error(`Could not find any entity of type "Contribution" matching: ${attrs.contributionId}`); + }); - const user = (await userRepository.findOneOrFail(attrs.currentUserId)) as User; + const user = (await userRepository.findOneOrFail({ where: { id: attrs.currentUserId } })) as User; const hasPermissions = (await isCampaignAdminAsync(user.id, contribution.campaign.id)) || @@ -551,10 +566,11 @@ export async function createContributionCommentAsync(attrs: IContributionComment export async function retrieveAndSaveMatchResultAsync(contributionId: number): Promise { try { - const defaultConn = getConnection('default'); - const contributionRepository = defaultConn.getRepository('Contribution'); + const dataSource = await db(); + const contributionRepository = dataSource.getRepository('Contribution'); - const contribution = (await contributionRepository.findOneOrFail(contributionId, { + const contribution = (await contributionRepository.findOneOrFail({ + where: { id: contributionId }, relations: ['campaign', 'government'], })) as Contribution; @@ -603,12 +619,17 @@ export interface UpdateMatchResultAttrs { export async function updateMatchResultAsync(attrs: UpdateMatchResultAttrs): Promise { try { - const defaultConn = getConnection('default'); - const contributionRepository = defaultConn.getRepository('Contribution'); - - const contribution = (await contributionRepository.findOneOrFail(attrs.contributionId, { - relations: ['government', 'campaign'], - })) as Contribution; + const dataSource = await db(); + const contributionRepository = dataSource.getRepository('Contribution'); + + const contribution = (await contributionRepository + .findOneOrFail({ + where: { id: attrs.contributionId }, + relations: ['government', 'campaign'], + }) + .catch(() => { + throw new Error(`Could not find any entity of type "Contribution" matching: ${attrs.contributionId}`); + })) as Contribution; if (contribution.matchStrength === MatchStrength.EXACT) { throw new Error('Contribution has an exact match, cannot update'); @@ -648,12 +669,17 @@ export interface MatchResults { export async function getMatchResultAsync(attrs: GetMatchResultAttrs): Promise { try { - const defaultConn = getConnection('default'); - const contributionRepository = defaultConn.getRepository('Contribution'); - - const contribution = (await contributionRepository.findOneOrFail(attrs.contributionId, { - relations: ['government'], - })) as Contribution; + const dataSource = await db(); + const contributionRepository = dataSource.getRepository('Contribution'); + + const contribution = (await contributionRepository + .findOneOrFail({ + where: { id: attrs.contributionId }, + relations: ['government'], + }) + .catch(() => { + throw new Error(`Could not find any entity of type "Contribution" matching: ${attrs.contributionId}`); + })) as Contribution; const hasPermissions = await isGovernmentAdminAsync(attrs.currentUserId, contribution.government.id); if (hasPermissions) { const matchResults: MatchResults = { @@ -677,10 +703,12 @@ export async function getMatchResultAsync(attrs: GetMatchResultAttrs): Promise { - const defaultConn = getConnection('default'); - const contributionRepository = defaultConn.getRepository('Contribution'); + const dataSource = await db(); + const contributionRepository = dataSource.getRepository('Contribution'); - const contribution = (await contributionRepository.findOneOrFail(contributionId)) as Contribution; + const contribution = (await contributionRepository.findOneOrFail({ + where: { id: contributionId }, + })) as Contribution; if (contribution.addressPoint && contribution.addressPoint.coordinates) { // TODO: may need to remove this once caught up return true; @@ -692,7 +720,7 @@ export async function getGISCoordinates(contributionId: number): Promise { try { + const dataSource = await db(); const hasCampaignPermissions = (await isCampaignAdminAsync(expenditureAttrs.currentUserId, expenditureAttrs.campaignId)) || (await isCampaignStaffAsync(expenditureAttrs.currentUserId, expenditureAttrs.campaignId)); if (hasCampaignPermissions) { - const defaultConn = getConnection('default'); - const expenditureRepository = defaultConn.getRepository('Expenditure'); - const governmentRepository = defaultConn.getRepository('Government'); - const campaignRepository = defaultConn.getRepository('Campaign'); - const userRepository = defaultConn.getRepository('User'); + const expenditureRepository = dataSource.getRepository('Expenditure'); + const governmentRepository = dataSource.getRepository('Government'); + const campaignRepository = dataSource.getRepository('Campaign'); + const userRepository = dataSource.getRepository('User'); const expenditure = new Expenditure(); const [campaign, government] = await Promise.all([ - campaignRepository.findOne(expenditureAttrs.campaignId), - governmentRepository.findOne(expenditureAttrs.governmentId) + campaignRepository.findOne({ where: { id: expenditureAttrs.campaignId } }), + governmentRepository.findOne({ where: { id: expenditureAttrs.governmentId } }), ]); expenditure.campaign = campaign as Campaign; @@ -91,7 +92,9 @@ export async function addExpenditureAsync(expenditureAttrs: IAddExpenditureAttrs if (await expenditure.isValidAsync()) { const saved = await expenditureRepository.save(expenditure); - const user = await userRepository.findOneOrFail(expenditureAttrs.currentUserId) as User; + const user = (await userRepository.findOneOrFail({ + where: { id: expenditureAttrs.currentUserId }, + })) as User; await createActivityRecordAsync({ currentUser: user, @@ -99,7 +102,7 @@ export async function addExpenditureAsync(expenditureAttrs: IAddExpenditureAttrs campaign: expenditure.campaign, government: expenditure.government, activityType: ActivityTypeEnum.EXPENDITURE, - activityId: saved.id + activityId: saved.id, }); return saved; } @@ -128,7 +131,9 @@ export interface IGetExpenditureAttrs { filerId?: string | number; } -export async function getExpendituresAsync(expendituresAttrs: IGetExpenditureAttrs): Promise { +export async function getExpendituresAsync( + expendituresAttrs: IGetExpenditureAttrs +): Promise { try { const { governmentId, ...options } = expendituresAttrs; if (options.campaignId) { @@ -147,7 +152,7 @@ export async function getExpendituresAsync(expendituresAttrs: IGetExpenditureAtt if (expendituresAttrs.format === 'xml') { expenditures = await getExpendituresByGovernmentIdAsync(governmentId, { ...options, - page: options.page || 0 + page: options.page || 0, }); expenditures.xml = convertToXml(expenditures, expendituresAttrs.filerId); return expenditures; @@ -155,7 +160,7 @@ export async function getExpendituresAsync(expendituresAttrs: IGetExpenditureAtt expenditures = await getExpendituresByGovernmentIdAsync(governmentId, { ...options, page: options.page || 0, - perPage: options.perPage || 100 + perPage: options.perPage || 100, }); if (expendituresAttrs.format === 'csv') { @@ -192,12 +197,17 @@ export interface IUpdateExpenditureAttrs { export async function updateExpenditureAsync(expenditureAttrs: IUpdateExpenditureAttrs): Promise { try { - const defaultConn = getConnection('default'); - const expenditureRepository = defaultConn.getRepository('Expenditure'); - let expenditure = (await expenditureRepository.findOneOrFail(expenditureAttrs.id, { - relations: ['campaign', 'government'] - })) as Expenditure; - const userRepository = defaultConn.getRepository('User'); + const dataSource = await db(); + const expenditureRepository = dataSource.getRepository('Expenditure'); + let expenditure = (await expenditureRepository + .findOneOrFail({ + where: { id: expenditureAttrs.id }, + relations: ['campaign', 'government'], + }) + .catch(() => { + throw new Error(`Could not find any entity of type "Expenditure" matching: ${expenditureAttrs.id}`); + })) as Expenditure; + const userRepository = dataSource.getRepository('User'); const attrs = Object.assign({}, expenditureAttrs); if (attrs.date) { attrs.date = new Date(attrs.date); @@ -211,22 +221,25 @@ export async function updateExpenditureAsync(expenditureAttrs: IUpdateExpenditur const hasCampaignPermissions = (await isCampaignAdminAsync(expenditureAttrs.currentUserId, expenditure.campaign.id)) || (await isCampaignStaffAsync(expenditureAttrs.currentUserId, expenditure.campaign.id)) || - (govAdmin); + govAdmin; if (!govAdmin) { - if (attrs.status === ExpenditureStatus.OUT_OF_COMPLIANCE || attrs.status === ExpenditureStatus.IN_COMPLIANCE ) { + if ( + attrs.status === ExpenditureStatus.OUT_OF_COMPLIANCE || + attrs.status === ExpenditureStatus.IN_COMPLIANCE + ) { throw new Error('User does have permissions to change status on expenditure'); } } if (hasCampaignPermissions) { const [_, user, changeNotes] = await Promise.all([ expenditureRepository.update(expenditureAttrs.id, attrs), - (userRepository.findOneOrFail({ id: expenditureAttrs.currentUserId }) as unknown) as User, + userRepository.findOneOrFail({ where: { id: expenditureAttrs.currentUserId } }) as unknown as User, Object.keys(attrs) - .filter(key => attrs[key] && attrs[key] !== '') - .filter(key => expenditure[key] && expenditure[key] !== '') - .filter(key => expenditure[key] !== attrs[key]) - .map(k => `${k} changed from ${expenditure[k]} to ${attrs[k]}.`) - .join(' ') + .filter((key) => attrs[key] && attrs[key] !== '') + .filter((key) => expenditure[key] && expenditure[key] !== '') + .filter((key) => expenditure[key] !== attrs[key]) + .map((k) => `${k} changed from ${expenditure[k]} to ${attrs[k]}.`) + .join(' '), ]); await createActivityRecordAsync({ @@ -236,10 +249,11 @@ export async function updateExpenditureAsync(expenditureAttrs: IUpdateExpenditur government: expenditure.government, activityType: ActivityTypeEnum.EXPENDITURE, activityId: expenditure.id, - notify: govAdmin + notify: govAdmin, }); - expenditure = (await expenditureRepository.findOneOrFail(expenditureAttrs.id, { - relations: ['campaign', 'government'] + expenditure = (await expenditureRepository.findOneOrFail({ + where: { id: expenditureAttrs.id }, + relations: ['campaign', 'government'], })) as Expenditure; return expenditure; } else if (!(await isGovernmentAdminAsync(expenditureAttrs.currentUserId, expenditure.government.id))) { @@ -259,14 +273,20 @@ export interface IExpenditureCommentAttrs { export async function createExpenditureCommentAsync(attrs: IExpenditureCommentAttrs): Promise { try { - const defaultConn = getConnection('default'); - const expenditureRepository = defaultConn.getRepository('Expenditure'); - const userRepository = defaultConn.getRepository('User'); - const activityRepository = defaultConn.getRepository('Activity'); - const expenditure = (await expenditureRepository.findOneOrFail(attrs.expenditureId, { - relations: ['campaign', 'government'] - })) as Expenditure; - const user = await userRepository.findOneOrFail(attrs.currentUserId) as User; + const dataSource = await db(); + const expenditureRepository = dataSource.getRepository('Expenditure'); + const userRepository = dataSource.getRepository('User'); + const activityRepository = dataSource.getRepository('Activity'); + const expenditure = await expenditureRepository + .findOneOrFail({ + where: { id: attrs.expenditureId }, + relations: ['campaign', 'government'], + }) + .catch((error) => { + console.log(error.message); + throw new Error(`Could not find any entity of type "Expenditure" matching: ${attrs.expenditureId}`); + }); + const user = (await userRepository.findOneOrFail({ where: { id: attrs.currentUserId } })) as User; const hasPermissions = (await isCampaignAdminAsync(user.id, expenditure.campaign.id)) || @@ -280,11 +300,16 @@ export async function createExpenditureCommentAsync(attrs: IExpenditureCommentAt notes: `${user.name()}: ${attrs.comment}`, activityId: expenditure.id, activityType: ActivityTypeEnum.COMMENT_EXP, - notify: true + notify: true, }); if (attrs.attachmentPath) { - const attachmentPath = await saveFileAttachmentAsync(activity.id, 'expenditures', attrs.attachmentPath.name, attrs.attachmentPath.tempFilePath); + const attachmentPath = await saveFileAttachmentAsync( + activity.id, + 'expenditures', + attrs.attachmentPath.name, + attrs.attachmentPath.tempFilePath + ); await activityRepository.update(activity.id, { attachmentPath }); return activity; } @@ -305,10 +330,12 @@ export async function getExpenditureByIdAsync( expenditureAttrs: IGetExpenditureByIdAttrs ): Promise { try { + const dataSource = await db(); const { expenditureId, currentUserId } = expenditureAttrs; - const expenditureRepository = getConnection('default').getRepository('Expenditure'); - let expenditure = (await expenditureRepository.findOneOrFail(expenditureId, { - relations: ['campaign', 'government'] + const expenditureRepository = dataSource.getRepository('Expenditure'); + let expenditure = (await expenditureRepository.findOneOrFail({ + where: { id: expenditureId }, + relations: ['campaign', 'government'], })) as Expenditure; const hasCampaignPermissions = (await isCampaignAdminAsync(currentUserId, expenditure.campaign.id)) || @@ -318,7 +345,7 @@ export async function getExpenditureByIdAsync( expenditure = (await expenditureRepository.findOne({ select: expenditureSummaryFields, where: { id: expenditureId }, - relations: ['campaign', 'government'] + relations: ['campaign', 'government'], })) as Expenditure; } else { throw new Error('User does not have permissions'); diff --git a/api/services/gisService.ts b/api/services/gisService.ts index f449c3bab..0bdb0d0df 100644 --- a/api/services/gisService.ts +++ b/api/services/gisService.ts @@ -1,4 +1,4 @@ -import * as fetch from 'node-fetch'; +import fetch from 'node-fetch'; export interface GoogleResult { results: [ diff --git a/api/services/governmentService.ts b/api/services/governmentService.ts index af2e4d423..72312b414 100644 --- a/api/services/governmentService.ts +++ b/api/services/governmentService.ts @@ -1,12 +1,13 @@ +import db from '../models/db'; import { Government } from '../models/entity/Government'; -import { getConnection } from 'typeorm'; export interface ICreateGovernmentAttrs { name: string; } export async function createGovernmentAsync(governmentAttrs: ICreateGovernmentAttrs): Promise { - const governmentRepository = getConnection('default').getRepository('Government'); + const dataSource = await db(); + const governmentRepository = dataSource.getRepository('Government'); const government = new Government(); government.name = governmentAttrs.name; if (await government.isValidAsync()) { diff --git a/api/services/permissionService.ts b/api/services/permissionService.ts index 61d7e609d..4ce6ec252 100644 --- a/api/services/permissionService.ts +++ b/api/services/permissionService.ts @@ -1,4 +1,3 @@ -import { getConnection } from 'typeorm'; import * as jsonwebtoken from 'jsonwebtoken'; import { Permission, UserRole } from '../models/entity/Permission'; import { Campaign } from '../models/entity/Campaign'; @@ -8,6 +7,7 @@ import { createUserAsync } from './userService'; import { sendInvitationEmail, sendNewUserInvitationEmail } from './emailService'; import { createActivityRecordAsync } from './activityService'; import { ActivityTypeEnum } from '../models/entity/Activity'; +import db from '../models/db'; export interface IAddPermissionAsyncAttrs { userId: number; @@ -17,26 +17,33 @@ export interface IAddPermissionAsyncAttrs { } export async function addPermissionAsync(attrs: IAddPermissionAsyncAttrs): Promise { - const userRepository = getConnection('default').getRepository('User'); - const campaignRepository = getConnection('default').getRepository('Campaign'); - const govRepository = getConnection('default').getRepository('Government'); - const permissionRepository = getConnection('default').getRepository('Permission'); + const dataSource = await db(); + const userRepository = dataSource.getRepository('User'); + const campaignRepository = dataSource.getRepository('Campaign'); + const govRepository = dataSource.getRepository('Government'); + const permissionRepository = dataSource.getRepository('Permission'); const permission = new Permission(); - const userToAdd = await userRepository.findOneOrFail(attrs.userId) as User; + const userToAdd = (await userRepository.findOneOrFail({ where: { id: attrs.userId } }).catch(() => { + throw new Error(`Could not find any entity of type "User" matching: ${attrs.userId}`); + })) as User; permission.user = userToAdd; permission.role = attrs.role; let campaign: Campaign; if (attrs.campaignId) { - campaign = await campaignRepository.findOneOrFail(attrs.campaignId) as Campaign; + campaign = (await campaignRepository.findOneOrFail({ where: { id: attrs.campaignId } }).catch(() => { + throw new Error(`Could not find any entity of type "Campaign" matching: ${attrs.campaignId}`); + })) as Campaign; permission.campaign = campaign; permission.government = campaign.government; } let government: Government; if (attrs.governmentId) { - government = await govRepository.findOneOrFail(attrs.governmentId) as Government; + government = (await govRepository.findOneOrFail({ where: { id: attrs.governmentId } }).catch(() => { + throw new Error(`Could not find any entity of type "Government" matching: ${attrs.governmentId}`); + })) as Government; permission.government = government; } if (await permission.isValidAsync()) { @@ -54,11 +61,16 @@ export interface IRemovePermissionAsyncAttrs { } export async function removePermissionAsync(attrs: IRemovePermissionAsyncAttrs): Promise { - const permissionRepository = getConnection('default').getRepository('Permission'); - const permission = await permissionRepository.findOneOrFail(attrs.permissionId) as Permission; + const dataSource = await db(); + const permissionRepository = dataSource.getRepository('Permission'); + const permission = (await permissionRepository.findOneOrFail({ where: { id: attrs.permissionId } }).catch(() => { + throw new Error(`Could not find any entity of type "Permission" matching: ${attrs.permissionId}`); + })) as Permission; if (permission) { - if (await isGovernmentAdminAsync(attrs.userId, permission.government.id) || - await isCampaignAdminAsync(attrs.userId, permission.campaign.id) ) { + if ( + (await isGovernmentAdminAsync(attrs.userId, permission.government.id)) || + (await isCampaignAdminAsync(attrs.userId, permission.campaign.id)) + ) { await permissionRepository.delete(attrs.permissionId); } else { throw new Error('User must be an admin'); @@ -69,36 +81,48 @@ export async function removePermissionAsync(attrs: IRemovePermissionAsyncAttrs): } export async function isGovernmentAdminAsync(userId, governmentId: number): Promise { - const permissionRepository = getConnection('default').getRepository('Permission'); - const permission = await permissionRepository.createQueryBuilder('permission') - .where('"userId" = :userId', {userId}) - .andWhere('"governmentId" = :governmentId', {governmentId}) - .andWhere('"role" = :role', {role: UserRole.GOVERNMENT_ADMIN}) + const dataSource = await db(); + const permissionRepository = dataSource.getRepository('Permission'); + const permission = await permissionRepository + .createQueryBuilder('permission') + .where('"userId" = :userId', { userId }) + .andWhere('"governmentId" = :governmentId', { governmentId }) + .andWhere('"role" = :role', { role: UserRole.GOVERNMENT_ADMIN }) .getOne(); return !!permission; } export async function isCampaignAdminAsync(userId, campaignId: number): Promise { - const permissionRepository = getConnection('default').getRepository('Permission'); - const permission = await permissionRepository.createQueryBuilder('permission') - .where('"userId" = :userId', {userId}) - .andWhere('"campaignId" = :campaignId', {campaignId}) - .andWhere('"role" = :role', {role: UserRole.CAMPAIGN_ADMIN}) + const dataSource = await db(); + const permissionRepository = dataSource.getRepository('Permission'); + const permission = await permissionRepository + .createQueryBuilder('permission') + .where('"userId" = :userId', { userId }) + .andWhere('"campaignId" = :campaignId', { campaignId }) + .andWhere('"role" = :role', { role: UserRole.CAMPAIGN_ADMIN }) .getOne(); return !!permission; } export async function isCampaignStaffAsync(userId, campaignId: number): Promise { - const permissionRepository = getConnection('default').getRepository('Permission'); - const permission = await permissionRepository.createQueryBuilder('permission') - .where('"userId" = :userId', {userId}) - .andWhere('"campaignId" = :campaignId', {campaignId}) - .andWhere('"role" = :role', {role: UserRole.CAMPAIGN_STAFF}) - .getOne(); + try { + const dataSource = await db(); + const permissionRepository = dataSource.getRepository('Permission'); - return !!permission; -} + const permission = await permissionRepository.findOne({ + where: { + user: { id: userId }, + campaign: { id: campaignId }, + role: UserRole.CAMPAIGN_STAFF, + }, + }); + return !!permission; + } catch (error) { + console.error('Error checking campaign staff permission:', error); + return false; + } +} export interface IAddUserCampaignAttrs { email: string; @@ -110,12 +134,18 @@ export interface IAddUserCampaignAttrs { } export async function addUserToCampaignAsync(attrs: IAddUserCampaignAttrs): Promise { - const userRepository = getConnection('default').getRepository('User'); - const campaignRepository = getConnection('default').getRepository('Campaign'); - const campaign = await campaignRepository.findOneOrFail(attrs.campaignId) as Campaign; - const currentUser = await userRepository.findOneOrFail(attrs.currentUserId) as User; - if (await isCampaignAdminAsync(attrs.currentUserId, attrs.campaignId) || await isGovernmentAdminAsync(attrs.currentUserId, campaign.government.id)) { - let user = await userRepository.findOne({email: attrs.email}) as User; + const dataSource = await db(); + const userRepository = dataSource.getRepository('User'); + const campaignRepository = dataSource.getRepository('Campaign'); + const campaign = (await campaignRepository.findOneOrFail({ where: { id: attrs.campaignId } }).catch(() => { + throw new Error(`Could not find any entity of type "Campaign" matching: ${attrs.campaignId}`); + })) as Campaign; + const currentUser = (await userRepository.findOneOrFail({ where: { id: attrs.currentUserId } })) as User; + if ( + (await isCampaignAdminAsync(attrs.currentUserId, attrs.campaignId)) || + (await isGovernmentAdminAsync(attrs.currentUserId, campaign.government.id)) + ) { + let user = (await userRepository.findOne({ where: { email: attrs.email } })) as User; if (!user) { user = await createUserAsync({ email: attrs.email, @@ -133,7 +163,7 @@ export async function addUserToCampaignAsync(attrs: IAddUserCampaignAttrs): Prom government: await campaign.government, campaign: campaign, activityType: ActivityTypeEnum.INVITATION_EMAIL, - activityId: user.id + activityId: user.id, }); } else { await sendInvitationEmail({ @@ -145,7 +175,7 @@ export async function addUserToCampaignAsync(attrs: IAddUserCampaignAttrs): Prom userId: user.id, role: attrs.role, campaignId: campaign.id, - governmentId: campaign.government.id + governmentId: campaign.government.id, }); await createActivityRecordAsync({ currentUser: user, @@ -153,7 +183,7 @@ export async function addUserToCampaignAsync(attrs: IAddUserCampaignAttrs): Prom government: await campaign.government, campaign: campaign, activityType: ActivityTypeEnum.PERMISSION, - activityId: permission.id + activityId: permission.id, }); return permission; } @@ -170,12 +200,15 @@ export interface IAddUserGovAttrs { } export async function addUserToGovernmentAsync(attrs: IAddUserGovAttrs): Promise { - const userRepository = getConnection('default').getRepository('User'); - const governmentRepository = getConnection('default').getRepository('Government'); - const government = await governmentRepository.findOneOrFail(attrs.governmentId) as Government; - const currentUser = await userRepository.findOneOrFail(attrs.currentUserId) as User; + const dataSource = await db(); + const userRepository = dataSource.getRepository('User'); + const governmentRepository = dataSource.getRepository('Government'); + const government = (await governmentRepository.findOneOrFail({ where: { id: attrs.governmentId } }).catch(() => { + throw new Error(`Could not find any entity of type "Government" matching: ${attrs.governmentId}`); + })) as Government; + const currentUser = (await userRepository.findOneOrFail({ where: { id: attrs.currentUserId } })) as User; if (await isGovernmentAdminAsync(attrs.currentUserId, government.id)) { - let user = await userRepository.findOne({email: attrs.email}) as User; + let user = (await userRepository.findOne({ where: { email: attrs.email } })) as User; if (!user) { user = await createUserAsync({ email: attrs.email, @@ -192,7 +225,7 @@ export async function addUserToGovernmentAsync(attrs: IAddUserGovAttrs): Promise notes: `${user.name()} was sent an invitation email to ${user.email}`, government: government, activityType: ActivityTypeEnum.INVITATION_EMAIL, - activityId: user.id + activityId: user.id, }); } else { await sendInvitationEmail({ @@ -200,13 +233,13 @@ export async function addUserToGovernmentAsync(attrs: IAddUserGovAttrs): Promise governmentName: government.name, }); } - const permission = await addPermissionAsync({userId: user.id, role: attrs.role, governmentId: government.id}); + const permission = await addPermissionAsync({ userId: user.id, role: attrs.role, governmentId: government.id }); await createActivityRecordAsync({ currentUser: user, notes: `${currentUser.name()} added ${user.name()} to ${government.name} as a ${permission.role}`, government: government, activityType: ActivityTypeEnum.PERMISSION, - activityId: permission.id + activityId: permission.id, }); return permission; } @@ -215,7 +248,7 @@ export async function addUserToGovernmentAsync(attrs: IAddUserGovAttrs): Promise export enum PermissionEntity { GOVERNMENT = 'government', - CAMPAIGN = 'campaign' + CAMPAIGN = 'campaign', } export interface IToken { @@ -225,47 +258,49 @@ export interface IToken { lastName: string; email: string; permissions: { - id: number, - type: PermissionEntity, - role: UserRole, - campaignId?: number, - governmentId?: number, - governmentName?: string, - campaignName?: string + id: number; + type: PermissionEntity; + role: UserRole; + campaignId?: number; + governmentId?: number; + governmentName?: string; + campaignName?: string; }[]; } - export async function createTokenObjectAsync(userId: number): Promise { - const userRepository = getConnection('default').getRepository('User'); - const permissionRepository = getConnection('default').getRepository('Permission'); - const user = await userRepository.findOneOrFail(userId) as User; + const dataSource = await db(); + const userRepository = dataSource.getRepository('User'); + const permissionRepository = dataSource.getRepository('Permission'); + const user = (await userRepository.findOneOrFail({ where: { id: userId } }).catch(() => { + throw new Error(`Could not find any entity of type "User" matching: ${userId}`); + })) as User; const permissions = (await permissionRepository.find({ where: { user: { - id: userId - } + id: userId, + }, }, - relations: ['campaign', 'government', 'user'] + relations: ['campaign', 'government', 'user'], })) as Permission[]; - const exp = Date.now() + (72 * 60 * 60 * 1000); // 72 hours from now in miliseconds + const exp = Date.now() + 72 * 60 * 60 * 1000; // 72 hours from now in miliseconds return { id: userId, exp, firstName: user.firstName, lastName: user.lastName, email: user.email, - permissions: permissions.map(item => { + permissions: permissions.map((item) => { return { role: item.role, - type: item.role === UserRole.GOVERNMENT_ADMIN ? PermissionEntity.GOVERNMENT : PermissionEntity.CAMPAIGN, + type: item.role === UserRole.GOVERNMENT_ADMIN ? PermissionEntity.GOVERNMENT : PermissionEntity.CAMPAIGN, id: item.id, campaignId: item.campaign ? item.campaign.id : undefined, campaignName: item.campaign ? item.campaign.name : undefined, governmentId: item.government.id, - governmentName: item.government.name + governmentName: item.government.name, }; - }) + }), }; } @@ -286,7 +321,7 @@ export function decipherJWTokenAsync(token: string): Promise { } catch (e) { reject(e); } - const decoded = jsonwebtoken.decode(token, {complete: true}) as IJWTToken; + const decoded = jsonwebtoken.decode(token, { complete: true }) as IJWTToken; const payload: IToken = decoded.payload; if (payload.exp < Date.now()) { throw new Error('Token expired'); diff --git a/api/services/userService.ts b/api/services/userService.ts index a6f7452e4..9d7d825d7 100644 --- a/api/services/userService.ts +++ b/api/services/userService.ts @@ -1,5 +1,4 @@ import { User, UserStatus } from '../models/entity/User'; -import { getConnection } from 'typeorm'; import { resendInvitationEmail, sendPasswordResetEmail } from './emailService'; import { generateJWTokenAsync, isCampaignAdminAsync, isGovernmentAdminAsync } from './permissionService'; import { @@ -10,6 +9,7 @@ import { import { Campaign } from '../models/entity/Campaign'; import { createActivityRecordAsync } from './activityService'; import { ActivityTypeEnum } from '../models/entity/Activity'; +import db from '../models/db'; export interface ICreateUser { email: string; @@ -20,7 +20,8 @@ export interface ICreateUser { } export async function createUserAsync(userAttrs: ICreateUser): Promise { - const repository = getConnection('default').getRepository('User'); + const dataSource = await db(); + const repository = dataSource.getRepository('User'); const user = new User(); user.firstName = userAttrs.firstName; user.lastName = userAttrs.lastName; @@ -50,8 +51,11 @@ export interface IAcceptInvitationAttrs { } export async function acceptUserInvitationAsync(params: IAcceptInvitationAttrs): Promise { - const repository = getConnection('default').getRepository('User'); - let user = (await repository.findOneOrFail({ invitationCode: params.invitationCode })) as User; + const dataSource = await db(); + const repository = dataSource.getRepository('User'); + let user = (await repository.findOneOrFail({ where: { invitationCode: params.invitationCode } }).catch(() => { + throw new Error(`Could not find any entity of type "User" matching invitationCode: ${params.invitationCode}`); + })) as User; if (params.password.length < 6) { throw new Error('User password must be at least 6 characters'); } @@ -73,8 +77,11 @@ export async function acceptUserInvitationAsync(params: IAcceptInvitationAttrs): } export async function generatePasswordResetAsync(email: string): Promise { - const repository = getConnection('default').getRepository('User'); - const user = (await repository.findOneOrFail({ email: email })) as User; + const dataSource = await db(); + const repository = dataSource.getRepository('User'); + const user = (await repository.findOneOrFail({ where: { email: email } }).catch(() => { + throw new Error(`Could not find any entity of type "User" matching: {\n "email": "${email}"\n}`); + })) as User; const code = user.generatePasswordResetCode(); await repository.save(user); await sendPasswordResetEmail({ to: user.email, invitationCode: user.invitationCode }); @@ -88,8 +95,11 @@ export async function generatePasswordResetAsync(email: string): Promise } export async function passwordResetAsync(invitationCode, password: string): Promise { - const repository = getConnection('default').getRepository('User'); - let user = (await repository.findOneOrFail({ invitationCode: invitationCode })) as User; + const dataSource = await db(); + const repository = dataSource.getRepository('User'); + let user = (await repository.findOneOrFail({ where: { invitationCode: invitationCode } }).catch(() => { + throw new Error(`Could not find any entity of type "User" matching: {\n "invitationCode": "nope"\n}`); + })) as User; if (password.length < 6) { throw new Error('User password must be at least 6 characters'); } @@ -105,9 +115,10 @@ export async function passwordResetAsync(invitationCode, password: string): Prom } export async function createUserSessionFromLoginAsync(email, password: string): Promise { - const repository = getConnection('default').getRepository('User'); + const dataSource = await db(); + const repository = dataSource.getRepository('User'); try { - const user = (await repository.findOneOrFail({ email: email.toLowerCase() })) as User; + const user = (await repository.findOneOrFail({ where: { email: email.toLowerCase() } })) as User; if (user.validatePassword(password)) { const token = await generateJWTokenAsync(user.id); await createActivityRecordAsync({ @@ -127,8 +138,11 @@ export async function createUserSessionFromLoginAsync(email, password: string): } export async function updateUserPasswordAsync(userId: number, currentPassword, newPassword: string): Promise { - const repository = getConnection('default').getRepository('User'); - const user = (await repository.findOneOrFail(userId)) as User; + const dataSource = await db(); + const repository = dataSource.getRepository('User'); + const user = (await repository.findOneOrFail({ where: { id: userId } }).catch(() => { + throw new Error(`Could not find any entity of type "User" matching: ${userId}`); + })) as User; if (user.validatePassword(currentPassword)) { if (newPassword.length < 6) { throw new Error('Invalid password'); @@ -148,8 +162,11 @@ export async function updateUserPasswordAsync(userId: number, currentPassword, n } export async function resendInvitationAsync(userId: number): Promise { - const repository = getConnection('default').getRepository('User'); - const user = (await repository.findOneOrFail(userId)) as User; + const dataSource = await db(); + const repository = dataSource.getRepository('User'); + const user = (await repository.findOneOrFail({ where: { id: userId } }).catch(() => { + throw new Error(`Could not find any entity of type "User" matching: ${userId}`); + })) as User; if (user.userStatus === UserStatus.INVITED && user.invitationCode) { await resendInvitationEmail({ to: user.email, invitationCode: user.invitationCode }); await createActivityRecordAsync({ @@ -172,8 +189,9 @@ export interface IRetrieveUserParams { export async function retrieveUserPermissionsAsync(attrs: IRetrieveUserParams): Promise { if (attrs.campaignId) { - const campaignRepository = getConnection('default').getRepository('Campaign'); - const campaign = (await campaignRepository.findOneOrFail(attrs.campaignId)) as Campaign; + const dataSource = await db(); + const campaignRepository = dataSource.getRepository('Campaign'); + const campaign = (await campaignRepository.findOneOrFail({ where: { id: attrs.campaignId } })) as Campaign; if ( (await isCampaignAdminAsync(attrs.currentUserId, attrs.campaignId)) || (await isGovernmentAdminAsync(attrs.currentUserId, campaign.government.id)) diff --git a/api/test/controller/helpers.spec.ts b/api/test/controller/helpers.spec.ts index 6edcf56eb..c869acb97 100644 --- a/api/test/controller/helpers.spec.ts +++ b/api/test/controller/helpers.spec.ts @@ -2,7 +2,7 @@ import { FileArray, UploadedFile } from 'express-fileupload'; import * as path from 'path'; import * as fs from 'fs'; import * as crypto from 'crypto'; -import { expect } from 'chai'; + import { parseBulkCsvData } from '../../controller/helpers'; let bulkUploadBody = { @@ -38,7 +38,7 @@ describe('controller/helpers', () => { it('parseBulkCsvData: contributions-invalid-name.csv', async () => { mockCsv = createMockCsv('contributions-invalid-name.csv'); const parsedData = await parseBulkCsvData(bulkUploadBody, mockCsv); - expect(parsedData).to.deep.equal({ + expect(parsedData).toEqual({ info: { governmentId: 1, campaignId: 1, currentUserId: 1, filename: '1' }, contributions: [ { @@ -66,7 +66,7 @@ describe('controller/helpers', () => { it('parseBulkCsvData: contributions-invalid-name-and-address.csv', async () => { mockCsv = createMockCsv('contributions-invalid-name-and-address.csv'); const parsedData = await parseBulkCsvData(bulkUploadBody, mockCsv); - expect(parsedData).to.deep.equal({ + expect(parsedData).toEqual({ info: { governmentId: 1, campaignId: 1, currentUserId: 1, filename: '1' }, contributions: [ { @@ -93,7 +93,7 @@ describe('controller/helpers', () => { it('parseBulkCsvData: contributions-invalid-same-name-address.csv', async () => { mockCsv = createMockCsv('contributions-invalid-same-name-address.csv'); const parsedData = await parseBulkCsvData(bulkUploadBody, mockCsv); - expect(parsedData).to.deep.equal({ + expect(parsedData).toEqual({ info: { governmentId: 1, campaignId: 1, currentUserId: 1, filename: '1' }, contributions: [ { @@ -121,7 +121,7 @@ describe('controller/helpers', () => { it('parseBulkCsvData: contributions-download-v-small.csv', async () => { mockCsv = createMockCsv('contributions-download-v-small.csv'); const parsedData = await parseBulkCsvData(bulkUploadBody, mockCsv); - expect(parsedData).to.deep.equal({ + expect(parsedData).toEqual({ info: { governmentId: 1, campaignId: 1, currentUserId: 1, filename: '1' }, contributions: [ { diff --git a/api/test/converters/index.spec.ts b/api/test/converters/index.spec.ts index ac0050684..1b4e464e7 100644 --- a/api/test/converters/index.spec.ts +++ b/api/test/converters/index.spec.ts @@ -1,6 +1,12 @@ import * as libxml from 'libxmljs'; -import { expect } from 'chai'; -import { newCampaignAsync, newBulkContributionAsync, newGovernmentAsync, truncateAll, newBulkExpenditureAsync } from '../factories'; + +import { + newCampaignAsync, + newBulkContributionAsync, + newGovernmentAsync, + truncateAll, + newBulkExpenditureAsync, +} from '../factories'; import { Government } from '../../models/entity/Government'; import { Campaign } from '../../models/entity/Campaign'; import { IContributionSummaryResults } from '../../models/entity/Contribution'; @@ -13,51 +19,44 @@ let campaign: Campaign; let bulkContributions: IContributionSummaryResults; let bulkExpenditures: IExpenditureSummaryResults; describe('Orestar bulk converter', () => { - beforeEach(async () => { - government = await newGovernmentAsync(); - campaign = await newCampaignAsync(government); - }); - - afterEach(async () => { - await truncateAll(); - }); - - describe('convertContributionsToXML', () => { - beforeEach(async () => { - bulkContributions = await newBulkContributionAsync(campaign, government); + government = await newGovernmentAsync(); + campaign = await newCampaignAsync(government); }); - it('successfully returns converted xml', async () => { - const rawBulk = convertContributionsToXML(bulkContributions, 2); - const xml = JSON.parse(rawBulk)[0]; - const xsd = campaignFinanceTransactionsSchema; - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); + afterEach(async () => { + await truncateAll(); }); - }); - - describe('convertExpendituresToXML', () => { - - beforeEach(async () => { - bulkExpenditures = await newBulkExpenditureAsync(campaign, government); + describe('convertContributionsToXML', () => { + beforeEach(async () => { + bulkContributions = await newBulkContributionAsync(campaign, government); + }); + + it('successfully returns converted xml', async () => { + const rawBulk = convertContributionsToXML(bulkContributions, 2); + const xml = JSON.parse(rawBulk)[0]; + const xsd = campaignFinanceTransactionsSchema; + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); }); - it('successfully returns converted xml', async () => { - const rawBulk = convertExpendituresToXML(bulkExpenditures, 2); - const xml = JSON.parse(rawBulk)[0]; - const xsd = campaignFinanceTransactionsSchema; - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); + describe('convertExpendituresToXML', () => { + beforeEach(async () => { + bulkExpenditures = await newBulkExpenditureAsync(campaign, government); + }); + + it('successfully returns converted xml', async () => { + const rawBulk = convertExpendituresToXML(bulkExpenditures, 2); + const xml = JSON.parse(rawBulk)[0]; + const xsd = campaignFinanceTransactionsSchema; + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); }); - - }); - -}); \ No newline at end of file +}); diff --git a/api/test/converters/orestarContributionsConverter.spec.ts b/api/test/converters/orestarContributionsConverter.spec.ts index 4f5dffc9e..0c61bbf21 100644 --- a/api/test/converters/orestarContributionsConverter.spec.ts +++ b/api/test/converters/orestarContributionsConverter.spec.ts @@ -1,1719 +1,1533 @@ -import { expect } from 'chai'; import * as libxml from 'libxmljs'; import { - zipSchema, - citySchema, - stateSchema, - street1Schema, - street2Schema, - zipPlusFourSchema, - fgnPostCodeSchema, - countryCodeSchema, - countySchema, - amountSchema, - associatedTranSchema, - associatedIdSchema, - associatedCompleteSchema, - contactSchema, - contactIdSchema, - contactTypeSchema, - contactOccupationSchema, - contactNameSchema, - contactBusinessNameSchema, - contactNameCommitteeSchema, - cosignerSchema, - employmentSchema, - expendForSchema, - individualNameSchema, - phoneSchema, - transactionSchema, - tranPurposeSchema, - transactionDescriptionSchema, - aggregateAmountSchema, - paymentMethodSchema, - dateSchema, - checkNoSchema, - interestRateSchema, - paymentScheduleSchema, - occupationLetterDateSchema, - transactionNotesSchema, - contactEmailSchema, - addressSchema, - operationSchema + zipSchema, + citySchema, + stateSchema, + street1Schema, + street2Schema, + zipPlusFourSchema, + fgnPostCodeSchema, + countryCodeSchema, + countySchema, + amountSchema, + associatedTranSchema, + associatedIdSchema, + associatedCompleteSchema, + contactSchema, + contactIdSchema, + contactTypeSchema, + contactOccupationSchema, + contactNameSchema, + contactBusinessNameSchema, + contactNameCommitteeSchema, + cosignerSchema, + employmentSchema, + expendForSchema, + individualNameSchema, + phoneSchema, + transactionSchema, + tranPurposeSchema, + transactionDescriptionSchema, + aggregateAmountSchema, + paymentMethodSchema, + dateSchema, + checkNoSchema, + interestRateSchema, + paymentScheduleSchema, + occupationLetterDateSchema, + transactionNotesSchema, + contactEmailSchema, + addressSchema, + operationSchema, } from '../schemas/schemas'; -import { - newCampaignAsync, - newContributionAsync, - newGovernmentAsync, - truncateAll -} from '../factories'; +import { newCampaignAsync, newContributionAsync, newGovernmentAsync, truncateAll } from '../factories'; import { Government } from '../../models/entity/Government'; import { Campaign } from '../../models/entity/Campaign'; import OrestarContributionConverter, { EmploymentType } from '../../models/converters/orestarContributionConverter'; -import { - InKindDescriptionType, - PaymentMethod, - ContributorType -} from '../../models/entity/Contribution'; +import { InKindDescriptionType, PaymentMethod, ContributorType } from '../../models/entity/Contribution'; let government: Government; let campaign: Campaign; describe('Orestar contribution converter', () => { - - beforeEach(async () => { - government = await newGovernmentAsync(); - campaign = await newCampaignAsync(government); - }); - - afterEach(async () => { - await truncateAll(); - }); - - describe('address schema', () => { - - it('confirms passing address schema', async () => { - const contribution = await newContributionAsync(campaign, government); - const xml = new OrestarContributionConverter(contribution); - const xsd = addressSchema; - const xml_valid = xml.address(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failure of address schema', async () => { - const contribution = await newContributionAsync(campaign, government); - delete contribution.address1; - delete contribution.city; - delete contribution.state; - delete contribution.zip; - const xml = new OrestarContributionConverter(contribution); - const xsd = addressSchema; - const xml_valid = xml.address(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(false); - }); - - }); - - describe('street1 schema', () => { - - it('confirms passing street1 schema', async () => { - const contribution = await newContributionAsync(campaign, government); - const xml = new OrestarContributionConverter(contribution); - const xsd = street1Schema; - const xml_valid = xml.street1(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms fail of street1 schema', async () => { - const xsd = street1Schema; - const xml_valid = ''; - libxml.parseXml(xsd); - expect(libxml.parseXml.bind(xml_valid)).to.throw(); - }); - - }); - - describe('street2 schema', () => { - - it('confirms passing street2 schema', async () => { - const contribution = await newContributionAsync(campaign, government); - const xml = new OrestarContributionConverter(contribution); - const xsd = street2Schema; - const xml_valid = xml.street2(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failure of street2 schema', async () => { - const xsd = street2Schema; - const xml_valid = ``; - libxml.parseXml(xsd); - expect(libxml.parseXml.bind(xml_valid)).to.throw(); - }); - - }); - - describe('city schema', () => { - - it('confirms passing city schema', async () => { - const contribution = await newContributionAsync(campaign, government); - const xml = new OrestarContributionConverter(contribution); - const xsd = citySchema; - const xml_valid = xml.city(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failing city schema', async () => { - const xsd = citySchema; - const xml_valid = ''; - libxml.parseXml(xsd); - expect(libxml.parseXml.bind(xml_valid)).to.throw(); - }); - - }); - - describe('state schema', () => { - - it('confirms passing state schema', async () => { - const contribution = await newContributionAsync(campaign, government); - const xml = new OrestarContributionConverter(contribution); - const xsd = stateSchema; - const xml_valid = xml.state(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failing of state schema', async () => { - const xsd = stateSchema; - const xml_valid = 'MDIDIDI'; - libxml.parseXml(xsd); - expect(libxml.parseXml.bind(xml_valid)).to.throw(); - }); - - }); - - describe('zip schema', () => { - - it('confirms passing zip schema', async () => { - const contribution = await newContributionAsync(campaign, government); - const xml = new OrestarContributionConverter(contribution); - const xsd = zipSchema; - const xml_valid = xml.zip(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failure of zip schema', async () => { - const xsd = zipSchema; - const xml_valid = 'blahdhdhd'; - libxml.parseXml(xsd); - expect(libxml.parseXml.bind(xml_valid)).to.throw(); - }); - - }); - - describe('zip plus schema', () => { - - it('confirms passing zip plus four schema', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.zip = '34554-5555'; - const xml = new OrestarContributionConverter(contribution); - const xsd = zipPlusFourSchema; - const xml_valid = xml.zipPlusFour(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing zip plus four method', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.zip = `63334-2030`; - const xml = new OrestarContributionConverter(contribution); - const xsd = zipPlusFourSchema; - const xml_valid = xml.zipPlusFour(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failure of zip plus four method', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.zip = `63334-20303`; // too many characters - const xml = new OrestarContributionConverter(contribution); - const xsd = zipPlusFourSchema; - xml.zipPlusFour(); - expect(libxml.parseXml.bind(xsd)).to.throw(); - }); - - it('confirms passing zip plus four schema', async () => { - const xsd = zipPlusFourSchema; - const xml_valid = '45654'; - libxml.parseXml(xsd); - expect(libxml.parseXml.bind(xml_valid)).to.throw(); - }); - - }); - - describe('foreign post code schema', () => { - - it('confirms passing foreign post code schema', async () => { - const contribution = await newContributionAsync(campaign, government); - const xml = new OrestarContributionConverter(contribution); - const xsd = fgnPostCodeSchema; - const xml_valid = xml.fgnPostCode(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing foreign post code schema', async () => { - const xsd = fgnPostCodeSchema; - const xml_valid = ''; - libxml.parseXml(xsd); - expect(libxml.parseXml.bind(xml_valid)).to.throw(); - }); - - }); - - describe('country code schema', () => { - - it('confirms passing country code schema', async () => { - const contribution = await newContributionAsync(campaign, government); - const xml = new OrestarContributionConverter(contribution); - const xsd = countryCodeSchema; - const xml_valid = xml.countryCode(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failing of country code schema', async () => { - const xsd = countryCodeSchema; - const xml_valid = 'asdfasd'; - libxml.parseXml(xsd); - expect(libxml.parseXml.bind(xml_valid)).to.throw(); - }); - - }); - - describe('county schema', () => { - - it('confirms passing county schema', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.county = 'Washington'; - const xml = new OrestarContributionConverter(contribution); - const xsd = countySchema; - const xml_valid = xml.county(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing county method', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.county = 'Multnomah'; - const xml = new OrestarContributionConverter(contribution); - const xsd = countySchema; - const xml_valid = xml.county(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing county method', async () => { - const contribution = await newContributionAsync(campaign, government); - const xml = new OrestarContributionConverter(contribution); - const xsd = countySchema; - const xml_valid = xml.county(); - libxml.parseXml(xsd); - expect(libxml.parseXml.bind(xml_valid)).to.throw(); - }); - - }); - - describe('amount schema', () => { - - it('confirms passing amount schema', async () => { - const contribution = await newContributionAsync(campaign, government); - const xml = new OrestarContributionConverter(contribution); - const xsd = amountSchema; - const xml_valid = xml.amount(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failure of amount schema', async () => { - const contribution = await newContributionAsync(campaign, government); - (contribution as any).amount = 'nope'; - const xml = new OrestarContributionConverter(contribution); - const xsd = amountSchema; - const xml_valid = xml.amount(); - libxml.parseXml(xsd); - expect(libxml.parseXml.bind(xml_valid)).to.throw(); - }); - - }); - - describe('associated-tran schema', () => { - - it('confirms passing associated-tran schema', async () => { - const contribution = await newContributionAsync(campaign, government); - const xml = new OrestarContributionConverter(contribution); - const xsd = associatedTranSchema; - const xml_valid = xml.associatedTran(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failure of associated-tran schema', async () => { - const xsd = associatedTranSchema; - const xml_valid = 'nope'; - libxml.parseXml(xsd); - expect(libxml.parseXml.bind(xml_valid)).to.throw(); - }); - - }); - - describe('associated id', () => { - - it('confirms passing associated id schema', async () => { - const contribution = await newContributionAsync(campaign, government); - const xml = new OrestarContributionConverter(contribution); - const xsd = associatedIdSchema; - const xml_valid = xml.associatedId(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failure of associated id schema', async () => { - const xsd = associatedIdSchema; - const xml_valid = 'over30charactersaksdfkajsdfkjla'; - libxml.parseXml(xsd); - expect(libxml.parseXml.bind(xml_valid)).to.throw(); - }); - - }); - - describe('associated complete schema', () => { - - it('confirms passing associated complete? schema', async () => { - const contribution = await newContributionAsync(campaign, government); - const xml = new OrestarContributionConverter(contribution); - const xsd = associatedCompleteSchema; - const xml_valid = xml.associatedComplete(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failure associated complete? schema', async () => { - const xsd = associatedCompleteSchema; - const xml_valid = 'NOPE'; - libxml.parseXml(xsd); - expect(libxml.parseXml.bind(xml_valid)).to.throw(); - }); - - }); - - describe('transaction schema', () => { - - it('confirms passing transactions schema', async () => { - const contribution = await newContributionAsync(campaign, government); - const xml = new OrestarContributionConverter(contribution); - const xsd = transactionSchema; - const xml_valid = xml.transaction(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failure of transactions schema: type missing', async () => { - const contribution = await newContributionAsync(campaign, government); - delete contribution.type; - const xml = new OrestarContributionConverter(contribution); - const xsd = transactionSchema; - const xml_valid = xml.transaction(); - libxml.parseXml(xsd); - expect(libxml.parseXml.bind(xml_valid)).to.throw(); - }); - - }); - - describe('CHOICE: operation schema', () => { - - it('confirms passing operation schema: add', async () => { - const contribution = await newContributionAsync(campaign, government); - const xml = new OrestarContributionConverter(contribution); - const xsd = operationSchema; - const xml_valid = xml.operation(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing operation schema: amend', () => { - const xsd = operationSchema; - const xml_valid = 'true'; - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing operation schema: delete', () => { - const xsd = operationSchema; - const xml_valid = 'true'; - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failure of operation schema', () => { - const xsd = operationSchema; - const xml_valid = 'true'; - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - expect(xmlDocValid.validate(xsdDoc)).to.equal(false); - }); - - }); - - describe('ENUM: transaction purpose schema', () => { - // Not testing enums: E, H, I, R, X, Y, or Zs - it('confirms passing transaction purpose schema: A', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.inKindType = InKindDescriptionType.PREP_AD; - const xml = new OrestarContributionConverter(contribution); - const xsd = tranPurposeSchema; - const xml_valid = xml.tranPurposeType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing transaction purpose schema: B', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.inKindType = InKindDescriptionType.BROADCAST; - const xml = new OrestarContributionConverter(contribution); - const xsd = tranPurposeSchema; - const xml_valid = xml.tranPurposeType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing transaction purpose schema: C', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.inKindType = InKindDescriptionType.PETITION; - const xml = new OrestarContributionConverter(contribution); - const xsd = tranPurposeSchema; - const xml_valid = xml.tranPurposeType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing transaction purpose schema: F', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.inKindType = InKindDescriptionType.FUNDRAISING; - const xml = new OrestarContributionConverter(contribution); - const xsd = tranPurposeSchema; - const xml_valid = xml.tranPurposeType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing transaction purpose schema: G', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.inKindType = InKindDescriptionType.GENERAL_OPERATING; - const xml = new OrestarContributionConverter(contribution); - const xsd = tranPurposeSchema; - const xml_valid = xml.tranPurposeType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing transaction purpose schema: L', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.inKindType = InKindDescriptionType.PRIMTING; - const xml = new OrestarContributionConverter(contribution); - const xsd = tranPurposeSchema; - const xml_valid = xml.tranPurposeType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing transaction purpose schema: M', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.inKindType = InKindDescriptionType.MANAGEMENT; - const xml = new OrestarContributionConverter(contribution); - const xsd = tranPurposeSchema; - const xml_valid = xml.tranPurposeType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing transaction purpose schema: N', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.inKindType = InKindDescriptionType.NEWSPAPER; - const xml = new OrestarContributionConverter(contribution); - const xsd = tranPurposeSchema; - const xml_valid = xml.tranPurposeType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing transaction purpose schema: O', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.inKindType = InKindDescriptionType.OTHER_AD; - const xml = new OrestarContributionConverter(contribution); - const xsd = tranPurposeSchema; - const xml_valid = xml.tranPurposeType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing transaction purpose schema: P', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.inKindType = InKindDescriptionType.POSTAGE; - const xml = new OrestarContributionConverter(contribution); - const xsd = tranPurposeSchema; - const xml_valid = xml.tranPurposeType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing transaction purpose schema: S', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.inKindType = InKindDescriptionType.POLLING; - const xml = new OrestarContributionConverter(contribution); - const xsd = tranPurposeSchema; - const xml_valid = xml.tranPurposeType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing transaction purpose schema: T', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.inKindType = InKindDescriptionType.TRAVEL; - const xml = new OrestarContributionConverter(contribution); - const xsd = tranPurposeSchema; - const xml_valid = xml.tranPurposeType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing transaction purpose schema: U', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.inKindType = InKindDescriptionType.UTILITIES; - const xml = new OrestarContributionConverter(contribution); - const xsd = tranPurposeSchema; - const xml_valid = xml.tranPurposeType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing transaction purpose schema: W', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.inKindType = InKindDescriptionType.WAGES; - const xml = new OrestarContributionConverter(contribution); - const xsd = tranPurposeSchema; - const xml_valid = xml.tranPurposeType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failure of transaction purpose schema', async () => { - const contribution = await newContributionAsync(campaign, government); - const xml = new OrestarContributionConverter(contribution); - const xsd = tranPurposeSchema; - const xml_valid = xml.tranPurposeType(); - const xsdDoc = libxml.parseXml(xsd); - expect(libxml.parseXml.bind(xml_valid)).to.throw(); - }); - - }); - - describe('transaction description schema', () => { - - it('confirms passing transaction description schema', async () => { - const contribution = await newContributionAsync(campaign, government); - const xml = new OrestarContributionConverter(contribution); - const xsd = transactionDescriptionSchema; - const xml_valid = xml.transactionDescription(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failure of transaction description schema', async () => { - const xsd = transactionDescriptionSchema; - const xml_valid = 'over 200 characters jkldjksdjkdj jfdsa asdf asdf df js ekjlkjsdkjsdkfj ss dfsdjkfl jsdflkjsdf lksdjllll over 200 characters jkldjksdjkdj jfdsa asdf asdf df js ekjlkjsdkjsdkfj ss dfsdjkfl jsdflkjsdf lksdjllll'; - libxml.parseXml(xsd); - expect(libxml.parseXml.bind(xml_valid)).to.throw(); - }); - - }); - - describe('transaction aggregate amount schema', () => { - - it('confirms passing transaction aggregate amount schema', async () => { - const contribution = await newContributionAsync(campaign, government); - const xml = new OrestarContributionConverter(contribution); - const xsd = aggregateAmountSchema; - const xml_valid = xml.aggregateAmount(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failing of transaction aggregate amount schema', async () => { - const xsd = aggregateAmountSchema; - const xml_valid = 'nope'; - libxml.parseXml(xsd); - expect(libxml.parseXml.bind(xml_valid)).to.throw(); - }); - - }); - - describe('ENUM: transaction payment method schema', () => { - - it('confirms passing transaction payment method schema: CA', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.paymentMethod = PaymentMethod.CASH; - const xml = new OrestarContributionConverter(contribution); - const xsd = paymentMethodSchema; - const xml_valid = xml.paymentMethod(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing transaction payment method schema: CHK', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.paymentMethod = PaymentMethod.CHECK; - const xml = new OrestarContributionConverter(contribution); - const xsd = paymentMethodSchema; - const xml_valid = xml.paymentMethod(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing transaction payment method schema: CHK', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.paymentMethod = PaymentMethod.MONEY_ORDER; - const xml = new OrestarContributionConverter(contribution); - const xsd = paymentMethodSchema; - const xml_valid = xml.paymentMethod(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing transaction payment method schema: CC', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.paymentMethod = PaymentMethod.CREDIT_CARD_ONLINE; - const xml = new OrestarContributionConverter(contribution); - const xsd = paymentMethodSchema; - const xml_valid = xml.paymentMethod(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing transaction payment method schema: CC', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.paymentMethod = PaymentMethod.CREDIT_CARD_PAPER; - const xml = new OrestarContributionConverter(contribution); - const xsd = paymentMethodSchema; - const xml_valid = xml.paymentMethod(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing transaction payment method schema: ETF', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.paymentMethod = PaymentMethod.ETF; - const xml = new OrestarContributionConverter(contribution); - const xsd = paymentMethodSchema; - const xml_valid = xml.paymentMethod(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failure of transaction payment method schema', async () => { - const contribution = await newContributionAsync(campaign, government); - (contribution as any).paymentMethod = 'Nope'; - const xml = new OrestarContributionConverter(contribution); - const xsd = paymentMethodSchema; - const xml_valid = xml.paymentMethod(); - libxml.parseXml(xsd); - expect(libxml.parseXml.bind(xml_valid)).to.throw(); - }); - - }); - - describe('transaction date schema', () => { - - it('confirms passing transaction date schema', async () => { - const contribution = await newContributionAsync(campaign, government); - const xml = new OrestarContributionConverter(contribution); - const xsd = dateSchema; - const xml_valid = xml.transactionDate(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failure of transaction date schema', async () => { - const contribution = await newContributionAsync(campaign, government); - (contribution as any).date = 'NOPE'; - const xml = new OrestarContributionConverter(contribution); - const xsd = dateSchema; - const xml_valid = xml.transactionDate(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(false); - }); - - }); - - describe('transaction check number schema', () => { - - it('confirms passing transaction check number schema', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.checkNumber = '329283'; - const xml = new OrestarContributionConverter(contribution); - const xsd = checkNoSchema; - const xml_valid = xml.checkNo(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failure of transaction check number schema', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.checkNumber = 'nope'; - const xml = new OrestarContributionConverter(contribution); - const xsd = checkNoSchema; - const xml_valid = xml.checkNo(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(false); - }); - - }); - - describe('transaction interest rate schema', () => { - - it('confirms passing transaction interest rate schema', async () => { - const contribution = await newContributionAsync(campaign, government); - const xml = new OrestarContributionConverter(contribution); - const xsd = interestRateSchema; - const xml_valid = xml.interestRate(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failure of transaction interest rate schema', async () => { - const xsd = interestRateSchema; - const xml_valid = 'too long of a description here!'; - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(false); - }); - - }); - - describe('transaction payment schedule schema', () => { - - it('confirms passing transaction payment schedule schema', async () => { - const contribution = await newContributionAsync(campaign, government); - const xml = new OrestarContributionConverter(contribution); - const xsd = paymentScheduleSchema; - const xml_valid = xml.paymentSchedule(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failure of transaction payment schedule schema', async () => { - const xsd = paymentScheduleSchema; - const xml_valid = 'tooooooo long of a description!'; - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(false); - }); - - }); - - describe('transaction occupation letter data schema', () => { - - it('confirms passing transaction occupation letter date schema', async () => { - const contribution = await newContributionAsync(campaign, government); - const xml = new OrestarContributionConverter(contribution); - const xsd = occupationLetterDateSchema; - const xml_valid = xml.occupationLetterDate(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failure of transaction occupation letter date schema', async () => { - const xsd = occupationLetterDateSchema; - const xml_valid = 'nope'; - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(false); - }); - - }); - - describe('transaction notes schema', () => { - - it('confirms passing transaction notes schema', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.notes = 'notes on the transaction'; - const xml = new OrestarContributionConverter(contribution); - const xsd = transactionNotesSchema; - const xml_valid = xml.transactionNotes(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failure of transaction notes schema', async () => { - const contribution = await newContributionAsync(campaign, government); - (contribution as any).notes = 5; - const xml = new OrestarContributionConverter(contribution); - const xsd = transactionNotesSchema; - const xml_valid = xml.transactionNotes(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - }); - - describe('contact schema', () => { - - it('confirms passing contact schema', async () => { - const contribution = await newContributionAsync(campaign, government); - const xml = new OrestarContributionConverter(contribution); - const xsd = contactSchema; - const xml_valid = xml.contact(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failure of contact schema', async () => { - const contribution = await newContributionAsync(campaign, government); - delete contribution.contributorType; - const xml = new OrestarContributionConverter(contribution); - const xsd = contactSchema; - const xml_valid = xml.contact(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(false); - }); - - }); - - describe('contact id schema', () => { - - it('confirms passing contact id schema', async () => { - const contribution = await newContributionAsync(campaign, government); - const xml = new OrestarContributionConverter(contribution); - const xsd = contactIdSchema; - const xml_valid = xml.contactId(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - }); - - describe('ENUM: contact type schema', () => { - - it('confirms passing contact type schema: B', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.contributorType = ContributorType.BUSINESS; - const xml = new OrestarContributionConverter(contribution); - const xsd = contactTypeSchema; - const xml_valid = xml.contactType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing contact type schema: C', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.contributorType = ContributorType.POLITICAL_COMMITTEE; - const xml = new OrestarContributionConverter(contribution); - const xsd = contactTypeSchema; - const xml_valid = xml.contactType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing contact type schema: F', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.contributorType = ContributorType.FAMILY; - const xml = new OrestarContributionConverter(contribution); - const xsd = contactTypeSchema; - const xml_valid = xml.contactType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing contact type schema: I', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.contributorType = ContributorType.INDIVIDUAL; - const xml = new OrestarContributionConverter(contribution); - const xsd = contactTypeSchema; - const xml_valid = xml.contactType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing contact type schema: L', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.contributorType = ContributorType.LABOR; - const xml = new OrestarContributionConverter(contribution); - const xsd = contactTypeSchema; - const xml_valid = xml.contactType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing contact type schema: O', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.contributorType = ContributorType.OTHER; - const xml = new OrestarContributionConverter(contribution); - const xsd = contactTypeSchema; - const xml_valid = xml.contactType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing contact type schema: P', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.contributorType = ContributorType.POLITICAL_PARTY; - const xml = new OrestarContributionConverter(contribution); - const xsd = contactTypeSchema; - const xml_valid = xml.contactType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing contact type schema: U', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.contributorType = ContributorType.UNREGISTERED; - const xml = new OrestarContributionConverter(contribution); - const xsd = contactTypeSchema; - const xml_valid = xml.contactType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failure of contact type schema', async () => { - const contribution = await newContributionAsync(campaign, government); - delete contribution.contributorType; - const xml = new OrestarContributionConverter(contribution); - const xsd = contactTypeSchema; - const xml_valid = xml.contactType(); - libxml.parseXml(xsd); - expect(libxml.parseXml.bind(xml_valid)).to.throw(); - }); - - }); - - describe('contact email schema', () => { - - it('confirms passing contact email schema', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.email = 'test@civicsoftwarefoundation.com'; - const xml = new OrestarContributionConverter(contribution); - const xsd = contactEmailSchema; - const xml_valid = xml.contactEmail(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failure of contact email schema', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.email = 'testcivicsoftwarefoundation.com'; - const xml = new OrestarContributionConverter(contribution); - const xsd = contactEmailSchema; - const xml_valid = xml.contactEmail(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(false); - }); - - }); - describe('contact occupation schema', () => { - - it('confirms passing contact occupation schema', async () => { - const contribution = await newContributionAsync(campaign, government); - const xml = new OrestarContributionConverter(contribution); - const xsd = contactOccupationSchema; - const xml_valid = xml.contactOccupation(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failure of contact occupation schema', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.occupation = 'this description is longer than 100 characters. blah blah blah. this description is longer than 100 characters. blah blah blah'; - const xml = new OrestarContributionConverter(contribution); - const xsd = contactOccupationSchema; - const xml_valid = xml.contactOccupation(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(false); - }); - - }); - - describe('CHOICE: contact name schema', () => { - - it('confirms passing contact name schema: individual-name', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.contributorType = ContributorType.INDIVIDUAL; - contribution.middleInitial = 'Middle'; - contribution.firstName = 'First'; - contribution.lastName = 'Last'; - const xml = new OrestarContributionConverter(contribution); - const xsd = contactNameSchema; - const xml_valid = xml.contactName(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing contact name schema: individual-name', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.contributorType = ContributorType.FAMILY; - contribution.middleInitial = 'Middle'; - contribution.firstName = 'First'; - contribution.lastName = 'Last'; - const xml = new OrestarContributionConverter(contribution); - const xsd = contactNameSchema; - const xml_valid = xml.contactName(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing contact name schema: committee', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.contributorType = ContributorType.POLITICAL_COMMITTEE; - contribution.name = 'Name'; - const xml = new OrestarContributionConverter(contribution); - const xsd = contactNameSchema; - const xml_valid = xml.contactName(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing contact name schema: committee', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.contributorType = ContributorType.POLITICAL_PARTY; - contribution.name = 'Name'; - const xml = new OrestarContributionConverter(contribution); - const xsd = contactNameSchema; - const xml_valid = xml.contactName(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing contact name schema: committee', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.contributorType = ContributorType.UNREGISTERED; - contribution.name = 'Name'; - const xml = new OrestarContributionConverter(contribution); - const xsd = contactNameSchema; - const xml_valid = xml.contactName(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing contact name schema: business-name', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.contributorType = ContributorType.BUSINESS; - contribution.name = 'Name'; - const xml = new OrestarContributionConverter(contribution); - const xsd = contactNameSchema; - const xml_valid = xml.contactName(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing contact name schema: business-name', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.contributorType = ContributorType.LABOR; - contribution.name = 'Name'; - const xml = new OrestarContributionConverter(contribution); - const xsd = contactNameSchema; - const xml_valid = xml.contactName(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing contact name schema: business-name', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.contributorType = ContributorType.OTHER; - contribution.name = 'Name'; - const xml = new OrestarContributionConverter(contribution); - const xsd = contactNameSchema; - const xml_valid = xml.contactName(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failure of contact name schema', async () => { - const contribution = await newContributionAsync(campaign, government); - const xml = new OrestarContributionConverter(contribution); - const xsd = contactNameSchema; - const xml_valid = xml.contactName(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - }); - - describe('contact business name', () => { - - it('confirms passing contact business name schema', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.name = 'Name'; - const xml = new OrestarContributionConverter(contribution); - const xsd = contactBusinessNameSchema; - const xml_valid = xml.businessName(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failure of contact business name schema', async () => { - const contribution = await newContributionAsync(campaign, government); - delete contribution.name; - const xml = new OrestarContributionConverter(contribution); - const xsd = contactBusinessNameSchema; - const xml_valid = xml.businessName(); - libxml.parseXml(xsd); - expect(libxml.parseXml.bind(xml_valid)).to.throw(); - }); - - }); - - describe('committee schema', () => { - - it('confirms passing contact name committee schema', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.name = 'Name'; - const xml = new OrestarContributionConverter(contribution); - const xsd = contactNameCommitteeSchema; - const xml_valid = xml.committee(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failure of contact name committee schema', async () => { - const contribution = await newContributionAsync(campaign, government); - delete contribution.name; - const xml = new OrestarContributionConverter(contribution); - const xsd = contactNameCommitteeSchema; - const xml_valid = xml.committee(); - libxml.parseXml(xsd); - expect(libxml.parseXml.bind(xml_valid)).to.throw(); - }); - - }); - - describe('cosigner schema', () => { - - it('confirms passing cosigner schema', async () => { - const contribution = await newContributionAsync(campaign, government); - const xml = new OrestarContributionConverter(contribution); - const xsd = cosignerSchema; - const xml_valid = xml.cosigner(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failure of cosigner schema', async () => { - const contribution = await newContributionAsync(campaign, government); - delete contribution.amount; - const xml = new OrestarContributionConverter(contribution); - const xsd = cosignerSchema; - const xml_valid = xml.cosigner(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(false); - }); - - }); - - describe('CHOICE: employment schemas', () => { - - it('confirms passing employment schema', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.occupation = EmploymentType.EMPLOYER_NAME; - const xml = new OrestarContributionConverter(contribution); - const xsd = employmentSchema; - const xml_valid = xml.employment(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing not-employed schema', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.occupation = EmploymentType.NOT_EMPLOYED; - const xml = new OrestarContributionConverter(contribution); - const xsd = employmentSchema; - const xml_valid = xml.employment(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing self-employed schema', async () => { - const contribution = await newContributionAsync(campaign, government); - contribution.occupation = EmploymentType.SELF_EMPLOYED; - const xml = new OrestarContributionConverter(contribution); - const xsd = employmentSchema; - const xml_valid = xml.employment(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failure of employment schema', async () => { - const contribution = await newContributionAsync(campaign, government); - delete contribution.occupation; - const xml = new OrestarContributionConverter(contribution); - const xsd = employmentSchema; - const xml_valid = xml.employment(); - libxml.parseXml(xsd); - expect(libxml.parseXml.bind(xml_valid)).to.throw(); - }); - - }); - - describe('confirms passing expend-for options', () => { - - it('confirms passing expend-for with committee-id not committee-name & expend-ind: K', async () => { - // const contribution = await newContributionAsync(campaign, government); - // const xml = new OrestarContributionConverter(contribution); - const xsd = expendForSchema; - const xml_valid = ` - 564654 - C - 396.02 - K - `; - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing expend-for with committee-name not committee-id & expend-ind: I', async () => { - // const contribution = await newContributionAsync(campaign, government); - // const xml = new OrestarContributionConverter(contribution); - const xsd = expendForSchema; - const xml_valid = ` - Committee Name - C - 396.02 - I - `; - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing expend-for with committee-name & support-ind: Y', async () => { - // const contribution = await newContributionAsync(campaign, government); - // const xml = new OrestarContributionConverter(contribution); - const xsd = expendForSchema; - const xml_valid = ` - Committee Name - C - 396.02 - I - Y - `; - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing expend-for with committee-name & support-ind: N', async () => { - // const contribution = await newContributionAsync(campaign, government); - // const xml = new OrestarContributionConverter(contribution); - const xsd = expendForSchema; - const xml_valid = ` - Committee Name - C - 396.02 - I - N - `; - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - }); - - describe('confirms passing individual-name options', () => { - - it('confirms passing individual-name', async () => { - const contribution = await newContributionAsync(campaign, government); - const xml = new OrestarContributionConverter(contribution); - const xsd = individualNameSchema; - const xml_valid = xml.individualName(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing individual-name w/ prefix, title, suffix, & title', async () => { - // const contribution = await newContributionAsync(campaign, government); - // const xml = new OrestarContributionConverter(contribution); - const xsd = individualNameSchema; - const xml_valid = ` - Mrs - Sisi - Lex - McDonald - Jr - Si - `; - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - }); - - describe('confirms passing phone options', () => { - - it('confirms passing phone: work', async () => { - const contribution = await newContributionAsync(campaign, government); - const xml = new OrestarContributionConverter(contribution); - const xsd = phoneSchema; - const xml_valid = xml.phone(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing phone: work', async () => { - // const contribution = await newContributionAsync(campaign, government); - // const xml = new OrestarContributionConverter(contribution); - const xsd = phoneSchema; - const xml_valid = ` - 555-55555-5555 - `; - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing phone: work & ext', async () => { - // const contribution = await newContributionAsync(campaign, government); - // const xml = new OrestarContributionConverter(contribution); - const xsd = phoneSchema; - const xml_valid = ` - 555-55555-5555 - 3223 - `; - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing phone: work & ext & fax', async () => { - // const contribution = await newContributionAsync(campaign, government); - // const xml = new OrestarContributionConverter(contribution); - const xsd = phoneSchema; - const xml_valid = ` - 555-55555-5555 - 3223 - 555-555-5555 - `; - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing phone: home', async () => { - // const contribution = await newContributionAsync(campaign, government); - // const xml = new OrestarContributionConverter(contribution); - const xsd = phoneSchema; - const xml_valid = ` - 555-55555-5555 - `; - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing phone: home & fax', async () => { - // const contribution = await newContributionAsync(campaign, government); - // const xml = new OrestarContributionConverter(contribution); - const xsd = phoneSchema; - const xml_valid = ` - 555-55555-5555 - 555-555-5555 - `; - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failing phone: home & fax, work-extension causes failure', async () => { - // const contribution = await newContributionAsync(campaign, government); - // const xml = new OrestarContributionConverter(contribution); - const xsd = phoneSchema; - const xml_valid = ` - 555-55555-5555 - 3223 - 555-555-5555 - `; - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(false); - }); - - }); - -}); \ No newline at end of file + beforeEach(async () => { + government = await newGovernmentAsync(); + campaign = await newCampaignAsync(government); + }); + + afterEach(async () => { + await truncateAll(); + }); + + describe('address schema', () => { + it('confirms passing address schema', async () => { + const contribution = await newContributionAsync(campaign, government); + const xml = new OrestarContributionConverter(contribution); + const xsd = addressSchema; + const xml_valid = xml.address(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failure of address schema', async () => { + const contribution = await newContributionAsync(campaign, government); + delete contribution.address1; + delete contribution.city; + delete contribution.state; + delete contribution.zip; + const xml = new OrestarContributionConverter(contribution); + const xsd = addressSchema; + const xml_valid = xml.address(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(false); + }); + }); + + describe('street1 schema', () => { + it('confirms passing street1 schema', async () => { + const contribution = await newContributionAsync(campaign, government); + const xml = new OrestarContributionConverter(contribution); + const xsd = street1Schema; + const xml_valid = xml.street1(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms fail of street1 schema', async () => { + const xsd = street1Schema; + const xml_valid = ''; + libxml.parseXml(xsd); + expect(libxml.parseXml.bind(xml_valid)).toThrow(); + }); + }); + + describe('street2 schema', () => { + it('confirms passing street2 schema', async () => { + const contribution = await newContributionAsync(campaign, government); + const xml = new OrestarContributionConverter(contribution); + const xsd = street2Schema; + const xml_valid = xml.street2(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failure of street2 schema', async () => { + const xsd = street2Schema; + const xml_valid = ``; + libxml.parseXml(xsd); + expect(libxml.parseXml.bind(xml_valid)).toThrow(); + }); + }); + + describe('city schema', () => { + it('confirms passing city schema', async () => { + const contribution = await newContributionAsync(campaign, government); + const xml = new OrestarContributionConverter(contribution); + const xsd = citySchema; + const xml_valid = xml.city(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failing city schema', async () => { + const xsd = citySchema; + const xml_valid = ''; + libxml.parseXml(xsd); + expect(libxml.parseXml.bind(xml_valid)).toThrow(); + }); + }); + + describe('state schema', () => { + it('confirms passing state schema', async () => { + const contribution = await newContributionAsync(campaign, government); + const xml = new OrestarContributionConverter(contribution); + const xsd = stateSchema; + const xml_valid = xml.state(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failing of state schema', async () => { + const xsd = stateSchema; + const xml_valid = 'MDIDIDI'; + libxml.parseXml(xsd); + expect(libxml.parseXml.bind(xml_valid)).toThrow(); + }); + }); + + describe('zip schema', () => { + it('confirms passing zip schema', async () => { + const contribution = await newContributionAsync(campaign, government); + const xml = new OrestarContributionConverter(contribution); + const xsd = zipSchema; + const xml_valid = xml.zip(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failure of zip schema', async () => { + const xsd = zipSchema; + const xml_valid = 'blahdhdhd'; + libxml.parseXml(xsd); + expect(libxml.parseXml.bind(xml_valid)).toThrow(); + }); + }); + + describe('zip plus schema', () => { + it('confirms passing zip plus four schema', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.zip = '34554-5555'; + const xml = new OrestarContributionConverter(contribution); + const xsd = zipPlusFourSchema; + const xml_valid = xml.zipPlusFour(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing zip plus four method', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.zip = `63334-2030`; + const xml = new OrestarContributionConverter(contribution); + const xsd = zipPlusFourSchema; + const xml_valid = xml.zipPlusFour(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failure of zip plus four method', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.zip = `63334-20303`; // too many characters + const xml = new OrestarContributionConverter(contribution); + const xsd = zipPlusFourSchema; + xml.zipPlusFour(); + expect(libxml.parseXml.bind(xsd)).toThrow(); + }); + + it('confirms passing zip plus four schema', async () => { + const xsd = zipPlusFourSchema; + const xml_valid = '45654'; + libxml.parseXml(xsd); + expect(libxml.parseXml.bind(xml_valid)).toThrow(); + }); + }); + + describe('foreign post code schema', () => { + it('confirms passing foreign post code schema', async () => { + const contribution = await newContributionAsync(campaign, government); + const xml = new OrestarContributionConverter(contribution); + const xsd = fgnPostCodeSchema; + const xml_valid = xml.fgnPostCode(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing foreign post code schema', async () => { + const xsd = fgnPostCodeSchema; + const xml_valid = ''; + libxml.parseXml(xsd); + expect(libxml.parseXml.bind(xml_valid)).toThrow(); + }); + }); + + describe('country code schema', () => { + it('confirms passing country code schema', async () => { + const contribution = await newContributionAsync(campaign, government); + const xml = new OrestarContributionConverter(contribution); + const xsd = countryCodeSchema; + const xml_valid = xml.countryCode(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failing of country code schema', async () => { + const xsd = countryCodeSchema; + const xml_valid = 'asdfasd'; + libxml.parseXml(xsd); + expect(libxml.parseXml.bind(xml_valid)).toThrow(); + }); + }); + + describe('county schema', () => { + it('confirms passing county schema', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.county = 'Washington'; + const xml = new OrestarContributionConverter(contribution); + const xsd = countySchema; + const xml_valid = xml.county(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing county method', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.county = 'Multnomah'; + const xml = new OrestarContributionConverter(contribution); + const xsd = countySchema; + const xml_valid = xml.county(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing county method', async () => { + const contribution = await newContributionAsync(campaign, government); + const xml = new OrestarContributionConverter(contribution); + const xsd = countySchema; + const xml_valid = xml.county(); + libxml.parseXml(xsd); + expect(libxml.parseXml.bind(xml_valid)).toThrow(); + }); + }); + + describe('amount schema', () => { + it('confirms passing amount schema', async () => { + const contribution = await newContributionAsync(campaign, government); + const xml = new OrestarContributionConverter(contribution); + const xsd = amountSchema; + const xml_valid = xml.amount(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failure of amount schema', async () => { + const contribution = await newContributionAsync(campaign, government); + (contribution as any).amount = 'nope'; + const xml = new OrestarContributionConverter(contribution); + const xsd = amountSchema; + const xml_valid = xml.amount(); + libxml.parseXml(xsd); + expect(libxml.parseXml.bind(xml_valid)).toThrow(); + }); + }); + + describe('associated-tran schema', () => { + it('confirms passing associated-tran schema', async () => { + const contribution = await newContributionAsync(campaign, government); + const xml = new OrestarContributionConverter(contribution); + const xsd = associatedTranSchema; + const xml_valid = xml.associatedTran(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failure of associated-tran schema', async () => { + const xsd = associatedTranSchema; + const xml_valid = 'nope'; + libxml.parseXml(xsd); + expect(libxml.parseXml.bind(xml_valid)).toThrow(); + }); + }); + + describe('associated id', () => { + it('confirms passing associated id schema', async () => { + const contribution = await newContributionAsync(campaign, government); + const xml = new OrestarContributionConverter(contribution); + const xsd = associatedIdSchema; + const xml_valid = xml.associatedId(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failure of associated id schema', async () => { + const xsd = associatedIdSchema; + const xml_valid = 'over30charactersaksdfkajsdfkjla'; + libxml.parseXml(xsd); + expect(libxml.parseXml.bind(xml_valid)).toThrow(); + }); + }); + + describe('associated complete schema', () => { + it('confirms passing associated complete? schema', async () => { + const contribution = await newContributionAsync(campaign, government); + const xml = new OrestarContributionConverter(contribution); + const xsd = associatedCompleteSchema; + const xml_valid = xml.associatedComplete(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failure associated complete? schema', async () => { + const xsd = associatedCompleteSchema; + const xml_valid = 'NOPE'; + libxml.parseXml(xsd); + expect(libxml.parseXml.bind(xml_valid)).toThrow(); + }); + }); + + describe('transaction schema', () => { + it('confirms passing transactions schema', async () => { + const contribution = await newContributionAsync(campaign, government); + const xml = new OrestarContributionConverter(contribution); + const xsd = transactionSchema; + const xml_valid = xml.transaction(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failure of transactions schema: type missing', async () => { + const contribution = await newContributionAsync(campaign, government); + delete contribution.type; + const xml = new OrestarContributionConverter(contribution); + const xsd = transactionSchema; + const xml_valid = xml.transaction(); + libxml.parseXml(xsd); + expect(libxml.parseXml.bind(xml_valid)).toThrow(); + }); + }); + + describe('CHOICE: operation schema', () => { + it('confirms passing operation schema: add', async () => { + const contribution = await newContributionAsync(campaign, government); + const xml = new OrestarContributionConverter(contribution); + const xsd = operationSchema; + const xml_valid = xml.operation(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing operation schema: amend', () => { + const xsd = operationSchema; + const xml_valid = 'true'; + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing operation schema: delete', () => { + const xsd = operationSchema; + const xml_valid = 'true'; + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failure of operation schema', () => { + const xsd = operationSchema; + const xml_valid = 'true'; + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(false); + }); + }); + + describe('ENUM: transaction purpose schema', () => { + // Not testing enums: E, H, I, R, X, Y, or Zs + it('confirms passing transaction purpose schema: A', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.inKindType = InKindDescriptionType.PREP_AD; + const xml = new OrestarContributionConverter(contribution); + const xsd = tranPurposeSchema; + const xml_valid = xml.tranPurposeType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing transaction purpose schema: B', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.inKindType = InKindDescriptionType.BROADCAST; + const xml = new OrestarContributionConverter(contribution); + const xsd = tranPurposeSchema; + const xml_valid = xml.tranPurposeType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing transaction purpose schema: C', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.inKindType = InKindDescriptionType.PETITION; + const xml = new OrestarContributionConverter(contribution); + const xsd = tranPurposeSchema; + const xml_valid = xml.tranPurposeType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing transaction purpose schema: F', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.inKindType = InKindDescriptionType.FUNDRAISING; + const xml = new OrestarContributionConverter(contribution); + const xsd = tranPurposeSchema; + const xml_valid = xml.tranPurposeType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing transaction purpose schema: G', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.inKindType = InKindDescriptionType.GENERAL_OPERATING; + const xml = new OrestarContributionConverter(contribution); + const xsd = tranPurposeSchema; + const xml_valid = xml.tranPurposeType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing transaction purpose schema: L', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.inKindType = InKindDescriptionType.PRIMTING; + const xml = new OrestarContributionConverter(contribution); + const xsd = tranPurposeSchema; + const xml_valid = xml.tranPurposeType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing transaction purpose schema: M', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.inKindType = InKindDescriptionType.MANAGEMENT; + const xml = new OrestarContributionConverter(contribution); + const xsd = tranPurposeSchema; + const xml_valid = xml.tranPurposeType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing transaction purpose schema: N', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.inKindType = InKindDescriptionType.NEWSPAPER; + const xml = new OrestarContributionConverter(contribution); + const xsd = tranPurposeSchema; + const xml_valid = xml.tranPurposeType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing transaction purpose schema: O', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.inKindType = InKindDescriptionType.OTHER_AD; + const xml = new OrestarContributionConverter(contribution); + const xsd = tranPurposeSchema; + const xml_valid = xml.tranPurposeType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing transaction purpose schema: P', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.inKindType = InKindDescriptionType.POSTAGE; + const xml = new OrestarContributionConverter(contribution); + const xsd = tranPurposeSchema; + const xml_valid = xml.tranPurposeType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing transaction purpose schema: S', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.inKindType = InKindDescriptionType.POLLING; + const xml = new OrestarContributionConverter(contribution); + const xsd = tranPurposeSchema; + const xml_valid = xml.tranPurposeType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing transaction purpose schema: T', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.inKindType = InKindDescriptionType.TRAVEL; + const xml = new OrestarContributionConverter(contribution); + const xsd = tranPurposeSchema; + const xml_valid = xml.tranPurposeType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing transaction purpose schema: U', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.inKindType = InKindDescriptionType.UTILITIES; + const xml = new OrestarContributionConverter(contribution); + const xsd = tranPurposeSchema; + const xml_valid = xml.tranPurposeType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing transaction purpose schema: W', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.inKindType = InKindDescriptionType.WAGES; + const xml = new OrestarContributionConverter(contribution); + const xsd = tranPurposeSchema; + const xml_valid = xml.tranPurposeType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failure of transaction purpose schema', async () => { + const contribution = await newContributionAsync(campaign, government); + const xml = new OrestarContributionConverter(contribution); + const xsd = tranPurposeSchema; + const xml_valid = xml.tranPurposeType(); + const xsdDoc = libxml.parseXml(xsd); + expect(libxml.parseXml.bind(xml_valid)).toThrow(); + }); + }); + + describe('transaction description schema', () => { + it('confirms passing transaction description schema', async () => { + const contribution = await newContributionAsync(campaign, government); + const xml = new OrestarContributionConverter(contribution); + const xsd = transactionDescriptionSchema; + const xml_valid = xml.transactionDescription(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failure of transaction description schema', async () => { + const xsd = transactionDescriptionSchema; + const xml_valid = + 'over 200 characters jkldjksdjkdj jfdsa asdf asdf df js ekjlkjsdkjsdkfj ss dfsdjkfl jsdflkjsdf lksdjllll over 200 characters jkldjksdjkdj jfdsa asdf asdf df js ekjlkjsdkjsdkfj ss dfsdjkfl jsdflkjsdf lksdjllll'; + libxml.parseXml(xsd); + expect(libxml.parseXml.bind(xml_valid)).toThrow(); + }); + }); + + describe('transaction aggregate amount schema', () => { + it('confirms passing transaction aggregate amount schema', async () => { + const contribution = await newContributionAsync(campaign, government); + const xml = new OrestarContributionConverter(contribution); + const xsd = aggregateAmountSchema; + const xml_valid = xml.aggregateAmount(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failing of transaction aggregate amount schema', async () => { + const xsd = aggregateAmountSchema; + const xml_valid = 'nope'; + libxml.parseXml(xsd); + expect(libxml.parseXml.bind(xml_valid)).toThrow(); + }); + }); + + describe('ENUM: transaction payment method schema', () => { + it('confirms passing transaction payment method schema: CA', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.paymentMethod = PaymentMethod.CASH; + const xml = new OrestarContributionConverter(contribution); + const xsd = paymentMethodSchema; + const xml_valid = xml.paymentMethod(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing transaction payment method schema: CHK', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.paymentMethod = PaymentMethod.CHECK; + const xml = new OrestarContributionConverter(contribution); + const xsd = paymentMethodSchema; + const xml_valid = xml.paymentMethod(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing transaction payment method schema: CHK', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.paymentMethod = PaymentMethod.MONEY_ORDER; + const xml = new OrestarContributionConverter(contribution); + const xsd = paymentMethodSchema; + const xml_valid = xml.paymentMethod(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing transaction payment method schema: CC', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.paymentMethod = PaymentMethod.CREDIT_CARD_ONLINE; + const xml = new OrestarContributionConverter(contribution); + const xsd = paymentMethodSchema; + const xml_valid = xml.paymentMethod(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing transaction payment method schema: CC', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.paymentMethod = PaymentMethod.CREDIT_CARD_PAPER; + const xml = new OrestarContributionConverter(contribution); + const xsd = paymentMethodSchema; + const xml_valid = xml.paymentMethod(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing transaction payment method schema: ETF', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.paymentMethod = PaymentMethod.ETF; + const xml = new OrestarContributionConverter(contribution); + const xsd = paymentMethodSchema; + const xml_valid = xml.paymentMethod(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failure of transaction payment method schema', async () => { + const contribution = await newContributionAsync(campaign, government); + (contribution as any).paymentMethod = 'Nope'; + const xml = new OrestarContributionConverter(contribution); + const xsd = paymentMethodSchema; + const xml_valid = xml.paymentMethod(); + libxml.parseXml(xsd); + expect(libxml.parseXml.bind(xml_valid)).toThrow(); + }); + }); + + describe('transaction date schema', () => { + it('confirms passing transaction date schema', async () => { + const contribution = await newContributionAsync(campaign, government); + const xml = new OrestarContributionConverter(contribution); + const xsd = dateSchema; + const xml_valid = xml.transactionDate(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failure of transaction date schema', async () => { + const contribution = await newContributionAsync(campaign, government); + (contribution as any).date = 'NOPE'; + const xml = new OrestarContributionConverter(contribution); + const xsd = dateSchema; + const xml_valid = xml.transactionDate(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(false); + }); + }); + + describe('transaction check number schema', () => { + it('confirms passing transaction check number schema', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.checkNumber = '329283'; + const xml = new OrestarContributionConverter(contribution); + const xsd = checkNoSchema; + const xml_valid = xml.checkNo(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failure of transaction check number schema', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.checkNumber = 'nope'; + const xml = new OrestarContributionConverter(contribution); + const xsd = checkNoSchema; + const xml_valid = xml.checkNo(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(false); + }); + }); + + describe('transaction interest rate schema', () => { + it('confirms passing transaction interest rate schema', async () => { + const contribution = await newContributionAsync(campaign, government); + const xml = new OrestarContributionConverter(contribution); + const xsd = interestRateSchema; + const xml_valid = xml.interestRate(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failure of transaction interest rate schema', async () => { + const xsd = interestRateSchema; + const xml_valid = 'too long of a description here!'; + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(false); + }); + }); + + describe('transaction payment schedule schema', () => { + it('confirms passing transaction payment schedule schema', async () => { + const contribution = await newContributionAsync(campaign, government); + const xml = new OrestarContributionConverter(contribution); + const xsd = paymentScheduleSchema; + const xml_valid = xml.paymentSchedule(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failure of transaction payment schedule schema', async () => { + const xsd = paymentScheduleSchema; + const xml_valid = 'tooooooo long of a description!'; + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(false); + }); + }); + + describe('transaction occupation letter data schema', () => { + it('confirms passing transaction occupation letter date schema', async () => { + const contribution = await newContributionAsync(campaign, government); + const xml = new OrestarContributionConverter(contribution); + const xsd = occupationLetterDateSchema; + const xml_valid = xml.occupationLetterDate(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failure of transaction occupation letter date schema', async () => { + const xsd = occupationLetterDateSchema; + const xml_valid = 'nope'; + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(false); + }); + }); + + describe('transaction notes schema', () => { + it('confirms passing transaction notes schema', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.notes = 'notes on the transaction'; + const xml = new OrestarContributionConverter(contribution); + const xsd = transactionNotesSchema; + const xml_valid = xml.transactionNotes(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failure of transaction notes schema', async () => { + const contribution = await newContributionAsync(campaign, government); + (contribution as any).notes = 5; + const xml = new OrestarContributionConverter(contribution); + const xsd = transactionNotesSchema; + const xml_valid = xml.transactionNotes(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + }); + + describe('contact schema', () => { + it('confirms passing contact schema', async () => { + const contribution = await newContributionAsync(campaign, government); + const xml = new OrestarContributionConverter(contribution); + const xsd = contactSchema; + const xml_valid = xml.contact(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failure of contact schema', async () => { + const contribution = await newContributionAsync(campaign, government); + delete contribution.contributorType; + const xml = new OrestarContributionConverter(contribution); + const xsd = contactSchema; + const xml_valid = xml.contact(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(false); + }); + }); + + describe('contact id schema', () => { + it('confirms passing contact id schema', async () => { + const contribution = await newContributionAsync(campaign, government); + const xml = new OrestarContributionConverter(contribution); + const xsd = contactIdSchema; + const xml_valid = xml.contactId(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + }); + + describe('ENUM: contact type schema', () => { + it('confirms passing contact type schema: B', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.contributorType = ContributorType.BUSINESS; + const xml = new OrestarContributionConverter(contribution); + const xsd = contactTypeSchema; + const xml_valid = xml.contactType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing contact type schema: C', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.contributorType = ContributorType.POLITICAL_COMMITTEE; + const xml = new OrestarContributionConverter(contribution); + const xsd = contactTypeSchema; + const xml_valid = xml.contactType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing contact type schema: F', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.contributorType = ContributorType.FAMILY; + const xml = new OrestarContributionConverter(contribution); + const xsd = contactTypeSchema; + const xml_valid = xml.contactType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing contact type schema: I', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.contributorType = ContributorType.INDIVIDUAL; + const xml = new OrestarContributionConverter(contribution); + const xsd = contactTypeSchema; + const xml_valid = xml.contactType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing contact type schema: L', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.contributorType = ContributorType.LABOR; + const xml = new OrestarContributionConverter(contribution); + const xsd = contactTypeSchema; + const xml_valid = xml.contactType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing contact type schema: O', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.contributorType = ContributorType.OTHER; + const xml = new OrestarContributionConverter(contribution); + const xsd = contactTypeSchema; + const xml_valid = xml.contactType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing contact type schema: P', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.contributorType = ContributorType.POLITICAL_PARTY; + const xml = new OrestarContributionConverter(contribution); + const xsd = contactTypeSchema; + const xml_valid = xml.contactType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing contact type schema: U', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.contributorType = ContributorType.UNREGISTERED; + const xml = new OrestarContributionConverter(contribution); + const xsd = contactTypeSchema; + const xml_valid = xml.contactType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failure of contact type schema', async () => { + const contribution = await newContributionAsync(campaign, government); + delete contribution.contributorType; + const xml = new OrestarContributionConverter(contribution); + const xsd = contactTypeSchema; + const xml_valid = xml.contactType(); + libxml.parseXml(xsd); + expect(libxml.parseXml.bind(xml_valid)).toThrow(); + }); + }); + + describe('contact email schema', () => { + it('confirms passing contact email schema', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.email = 'test@civicsoftwarefoundation.com'; + const xml = new OrestarContributionConverter(contribution); + const xsd = contactEmailSchema; + const xml_valid = xml.contactEmail(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failure of contact email schema', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.email = 'testcivicsoftwarefoundation.com'; + const xml = new OrestarContributionConverter(contribution); + const xsd = contactEmailSchema; + const xml_valid = xml.contactEmail(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(false); + }); + }); + describe('contact occupation schema', () => { + it('confirms passing contact occupation schema', async () => { + const contribution = await newContributionAsync(campaign, government); + const xml = new OrestarContributionConverter(contribution); + const xsd = contactOccupationSchema; + const xml_valid = xml.contactOccupation(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failure of contact occupation schema', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.occupation = + 'this description is longer than 100 characters. blah blah blah. this description is longer than 100 characters. blah blah blah'; + const xml = new OrestarContributionConverter(contribution); + const xsd = contactOccupationSchema; + const xml_valid = xml.contactOccupation(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(false); + }); + }); + + describe('CHOICE: contact name schema', () => { + it('confirms passing contact name schema: individual-name', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.contributorType = ContributorType.INDIVIDUAL; + contribution.middleInitial = 'Middle'; + contribution.firstName = 'First'; + contribution.lastName = 'Last'; + const xml = new OrestarContributionConverter(contribution); + const xsd = contactNameSchema; + const xml_valid = xml.contactName(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing contact name schema: individual-name', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.contributorType = ContributorType.FAMILY; + contribution.middleInitial = 'Middle'; + contribution.firstName = 'First'; + contribution.lastName = 'Last'; + const xml = new OrestarContributionConverter(contribution); + const xsd = contactNameSchema; + const xml_valid = xml.contactName(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing contact name schema: committee', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.contributorType = ContributorType.POLITICAL_COMMITTEE; + contribution.name = 'Name'; + const xml = new OrestarContributionConverter(contribution); + const xsd = contactNameSchema; + const xml_valid = xml.contactName(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing contact name schema: committee', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.contributorType = ContributorType.POLITICAL_PARTY; + contribution.name = 'Name'; + const xml = new OrestarContributionConverter(contribution); + const xsd = contactNameSchema; + const xml_valid = xml.contactName(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing contact name schema: committee', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.contributorType = ContributorType.UNREGISTERED; + contribution.name = 'Name'; + const xml = new OrestarContributionConverter(contribution); + const xsd = contactNameSchema; + const xml_valid = xml.contactName(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing contact name schema: business-name', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.contributorType = ContributorType.BUSINESS; + contribution.name = 'Name'; + const xml = new OrestarContributionConverter(contribution); + const xsd = contactNameSchema; + const xml_valid = xml.contactName(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing contact name schema: business-name', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.contributorType = ContributorType.LABOR; + contribution.name = 'Name'; + const xml = new OrestarContributionConverter(contribution); + const xsd = contactNameSchema; + const xml_valid = xml.contactName(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing contact name schema: business-name', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.contributorType = ContributorType.OTHER; + contribution.name = 'Name'; + const xml = new OrestarContributionConverter(contribution); + const xsd = contactNameSchema; + const xml_valid = xml.contactName(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failure of contact name schema', async () => { + const contribution = await newContributionAsync(campaign, government); + const xml = new OrestarContributionConverter(contribution); + const xsd = contactNameSchema; + const xml_valid = xml.contactName(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + }); + + describe('contact business name', () => { + it('confirms passing contact business name schema', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.name = 'Name'; + const xml = new OrestarContributionConverter(contribution); + const xsd = contactBusinessNameSchema; + const xml_valid = xml.businessName(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failure of contact business name schema', async () => { + const contribution = await newContributionAsync(campaign, government); + delete contribution.name; + const xml = new OrestarContributionConverter(contribution); + const xsd = contactBusinessNameSchema; + const xml_valid = xml.businessName(); + libxml.parseXml(xsd); + expect(libxml.parseXml.bind(xml_valid)).toThrow(); + }); + }); + + describe('committee schema', () => { + it('confirms passing contact name committee schema', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.name = 'Name'; + const xml = new OrestarContributionConverter(contribution); + const xsd = contactNameCommitteeSchema; + const xml_valid = xml.committee(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failure of contact name committee schema', async () => { + const contribution = await newContributionAsync(campaign, government); + delete contribution.name; + const xml = new OrestarContributionConverter(contribution); + const xsd = contactNameCommitteeSchema; + const xml_valid = xml.committee(); + libxml.parseXml(xsd); + expect(libxml.parseXml.bind(xml_valid)).toThrow(); + }); + }); + + describe('cosigner schema', () => { + it('confirms passing cosigner schema', async () => { + const contribution = await newContributionAsync(campaign, government); + const xml = new OrestarContributionConverter(contribution); + const xsd = cosignerSchema; + const xml_valid = xml.cosigner(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failure of cosigner schema', async () => { + const contribution = await newContributionAsync(campaign, government); + delete contribution.amount; + const xml = new OrestarContributionConverter(contribution); + const xsd = cosignerSchema; + const xml_valid = xml.cosigner(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + expect(xmlDocValid.validate(xsdDoc)).toEqual(false); + }); + }); + + describe('CHOICE: employment schemas', () => { + it('confirms passing employment schema', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.occupation = EmploymentType.EMPLOYER_NAME; + const xml = new OrestarContributionConverter(contribution); + const xsd = employmentSchema; + const xml_valid = xml.employment(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing not-employed schema', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.occupation = EmploymentType.NOT_EMPLOYED; + const xml = new OrestarContributionConverter(contribution); + const xsd = employmentSchema; + const xml_valid = xml.employment(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing self-employed schema', async () => { + const contribution = await newContributionAsync(campaign, government); + contribution.occupation = EmploymentType.SELF_EMPLOYED; + const xml = new OrestarContributionConverter(contribution); + const xsd = employmentSchema; + const xml_valid = xml.employment(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failure of employment schema', async () => { + const contribution = await newContributionAsync(campaign, government); + delete contribution.occupation; + const xml = new OrestarContributionConverter(contribution); + const xsd = employmentSchema; + const xml_valid = xml.employment(); + libxml.parseXml(xsd); + expect(libxml.parseXml.bind(xml_valid)).toThrow(); + }); + }); + + describe('confirms passing expend-for options', () => { + it('confirms passing expend-for with committee-id not committee-name & expend-ind: K', async () => { + // const contribution = await newContributionAsync(campaign, government); + // const xml = new OrestarContributionConverter(contribution); + const xsd = expendForSchema; + const xml_valid = ` + 564654 + C + 396.02 + K + `; + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing expend-for with committee-name not committee-id & expend-ind: I', async () => { + // const contribution = await newContributionAsync(campaign, government); + // const xml = new OrestarContributionConverter(contribution); + const xsd = expendForSchema; + const xml_valid = ` + Committee Name + C + 396.02 + I + `; + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing expend-for with committee-name & support-ind: Y', async () => { + // const contribution = await newContributionAsync(campaign, government); + // const xml = new OrestarContributionConverter(contribution); + const xsd = expendForSchema; + const xml_valid = ` + Committee Name + C + 396.02 + I + Y + `; + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing expend-for with committee-name & support-ind: N', async () => { + // const contribution = await newContributionAsync(campaign, government); + // const xml = new OrestarContributionConverter(contribution); + const xsd = expendForSchema; + const xml_valid = ` + Committee Name + C + 396.02 + I + N + `; + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + }); + + describe('confirms passing individual-name options', () => { + it('confirms passing individual-name', async () => { + const contribution = await newContributionAsync(campaign, government); + const xml = new OrestarContributionConverter(contribution); + const xsd = individualNameSchema; + const xml_valid = xml.individualName(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing individual-name w/ prefix, title, suffix, & title', async () => { + // const contribution = await newContributionAsync(campaign, government); + // const xml = new OrestarContributionConverter(contribution); + const xsd = individualNameSchema; + const xml_valid = ` + Mrs + Sisi + Lex + McDonald + Jr + Si + `; + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + }); + + describe('confirms passing phone options', () => { + it('confirms passing phone: work', async () => { + const contribution = await newContributionAsync(campaign, government); + const xml = new OrestarContributionConverter(contribution); + const xsd = phoneSchema; + const xml_valid = xml.phone(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing phone: work', async () => { + // const contribution = await newContributionAsync(campaign, government); + // const xml = new OrestarContributionConverter(contribution); + const xsd = phoneSchema; + const xml_valid = ` + 555-55555-5555 + `; + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing phone: work & ext', async () => { + // const contribution = await newContributionAsync(campaign, government); + // const xml = new OrestarContributionConverter(contribution); + const xsd = phoneSchema; + const xml_valid = ` + 555-55555-5555 + 3223 + `; + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing phone: work & ext & fax', async () => { + // const contribution = await newContributionAsync(campaign, government); + // const xml = new OrestarContributionConverter(contribution); + const xsd = phoneSchema; + const xml_valid = ` + 555-55555-5555 + 3223 + 555-555-5555 + `; + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing phone: home', async () => { + // const contribution = await newContributionAsync(campaign, government); + // const xml = new OrestarContributionConverter(contribution); + const xsd = phoneSchema; + const xml_valid = ` + 555-55555-5555 + `; + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing phone: home & fax', async () => { + // const contribution = await newContributionAsync(campaign, government); + // const xml = new OrestarContributionConverter(contribution); + const xsd = phoneSchema; + const xml_valid = ` + 555-55555-5555 + 555-555-5555 + `; + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failing phone: home & fax, work-extension causes failure', async () => { + // const contribution = await newContributionAsync(campaign, government); + // const xml = new OrestarContributionConverter(contribution); + const xsd = phoneSchema; + const xml_valid = ` + 555-55555-5555 + 3223 + 555-555-5555 + `; + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(false); + }); + }); +}); diff --git a/api/test/converters/orestarExpenditureConverter.spec.ts b/api/test/converters/orestarExpenditureConverter.spec.ts index bed0c14f5..b6785099a 100644 --- a/api/test/converters/orestarExpenditureConverter.spec.ts +++ b/api/test/converters/orestarExpenditureConverter.spec.ts @@ -1,1224 +1,1086 @@ -import { expect } from 'chai'; import * as libxml from 'libxmljs'; -import { - newCampaignAsync, - newGovernmentAsync, - truncateAll, - newExpenditureAsync -} from '../factories'; +import { newCampaignAsync, newGovernmentAsync, truncateAll, newExpenditureAsync } from '../factories'; import { Government } from '../../models/entity/Government'; import { Campaign } from '../../models/entity/Campaign'; import OrestarExpenditureConverter from '../../models/converters/orestarExpenditureConverter'; import { - expendForSchema, - addressSchema, - street1Schema, - street2Schema, - citySchema, - stateSchema, - zipSchema, - zipPlusFourSchema, - transactionSchema, - operationSchema, - transactionTypeSchema, - transactionSubTypeSchema, - tranPurposeSchema, - agentIdSchema, - expendIdSchema, - transactionDescriptionSchema, - aggregateAmountSchema, - paymentMethodSchema, - dateSchema, - checkNoSchema, - amountSchema, - contactSchema, - contactTypeSchema + expendForSchema, + addressSchema, + street1Schema, + street2Schema, + citySchema, + stateSchema, + zipSchema, + zipPlusFourSchema, + transactionSchema, + operationSchema, + transactionTypeSchema, + transactionSubTypeSchema, + tranPurposeSchema, + agentIdSchema, + expendIdSchema, + transactionDescriptionSchema, + aggregateAmountSchema, + paymentMethodSchema, + dateSchema, + checkNoSchema, + amountSchema, + contactSchema, + contactTypeSchema, } from '../schemas/schemas'; import { - ExpenditureType, - ExpenditureSubType, - PurposeType, - PaymentMethod, - PayeeType + ExpenditureType, + ExpenditureSubType, + PurposeType, + PaymentMethod, + PayeeType, } from '../../models/entity/Expenditure'; let government: Government; let campaign: Campaign; describe('Orestar expenditure converter', () => { - - beforeEach(async () => { - government = await newGovernmentAsync(); - campaign = await newCampaignAsync(government); - }); - - afterEach(async () => { - await truncateAll(); - }); - - describe('address schema', () => { - - it('confirms passing of address schema', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = addressSchema; - const xml_valid = xml.address(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failure of address schema', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - delete expenditure.address1; - delete expenditure.city; - delete expenditure.state; - delete expenditure.zip; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = addressSchema; - const xml_valid = xml.address(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(false); - }); - - }); - - describe('street1 schema', () => { - - it('confirms passing of street1 schema', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = street1Schema; - const xml_valid = xml.street1(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failure of street1 schema', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.address1 = 'this is more than 40 characters. so the street will fail'; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = street1Schema; - const xml_valid = xml.street1(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(false); - }); - - }); - - describe('street2 schema', () => { - - it('confirms passing of street2 schema', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = street2Schema; - const xml_valid = xml.street2(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failure of street2 schema', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.address2 = 'this is more than 40 characters. so the street will fail'; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = street2Schema; - const xml_valid = xml.street2(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(false); - }); - - }); - - describe('city schema', () => { - - it('confirms passing of city schema', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = citySchema; - const xml_valid = xml.city(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failure of city schema', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.city = 'For some reason this has a max length of 100 characters, but street1 is only 40? I need 20 more characters.'; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = citySchema; - const xml_valid = xml.city(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(false); - }); - - }); - - describe('state schema', () => { - - it('confirms passing of state schema', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = stateSchema; - const xml_valid = xml.state(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failure of state schema', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.state = '3ch'; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = stateSchema; - const xml_valid = xml.state(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(false); - }); - - }); - - describe('zip schema', () => { - - it('confirms passing of zip schema', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = zipSchema; - const xml_valid = xml.zip(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failure of zip schema', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.zip = '3ch'; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = zipSchema; - const xml_valid = xml.zip(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(false); - }); - - }); - - describe('zipPlusFour schema', () => { - - it('confirms passing of zipPlusFour schema', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.zip = '55555-5555'; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = zipPlusFourSchema; - const xml_valid = xml.zipPlusFour(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failure of zipPlusFour schema', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.zip = '9999-999999'; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = zipPlusFourSchema; - const xml_valid = xml.zipPlusFour(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(false); - }); - - }); - - describe('ENUM: contact type schema', () => { - - it('confirms passing of contact type schema: BUSINESS', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.payeeType = PayeeType.BUSINESS; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = contactTypeSchema; - const xml_valid = xml.contactType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing of contact type schema: FAMILY', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.payeeType = PayeeType.FAMILY; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = contactTypeSchema; - const xml_valid = xml.contactType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing of contact type schema: INDIVIDUAL', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.payeeType = PayeeType.INDIVIDUAL; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = contactTypeSchema; - const xml_valid = xml.contactType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing of contact type schema: LABOR', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.payeeType = PayeeType.LABOR; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = contactTypeSchema; - const xml_valid = xml.contactType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing of contact type schema: OTHER', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.payeeType = PayeeType.OTHER; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = contactTypeSchema; - const xml_valid = xml.contactType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing of contact type schema: POLITICAL_COMMITTEE', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.payeeType = PayeeType.POLITICAL_COMMITTEE; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = contactTypeSchema; - const xml_valid = xml.contactType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing of contact type schema: POLITICAL_PARTY', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.payeeType = PayeeType.POLITICAL_PARTY; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = contactTypeSchema; - const xml_valid = xml.contactType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing of contact type schema: UNREGISTERED', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.payeeType = PayeeType.UNREGISTERED; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = contactTypeSchema; - const xml_valid = xml.contactType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failure of contact type schema', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - (expenditure as any).payeeType = 'NOPE'; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = contactTypeSchema; - const xml_valid = xml.contactType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(false); - }); - - }); - - describe('contact schema', () => { - - it('confirms passing of contact schema', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = contactSchema; - const xml_valid = xml.contact(); - // console.log(xml_valid); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing of contact schema', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = contactSchema; - const xml_valid = xml.contact(); - // console.log(xml_valid); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - }); - - describe('transaction schema', () => { - - it('confirms passing of all transaction schema: random', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = transactionSchema; - const xml_valid = xml.transaction(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing of all transaction schema: expenditure, cash, check, broadcast', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.type = ExpenditureType.EXPENDITURE; - expenditure.subType = ExpenditureSubType.CASH_EXPENDITURE; - expenditure.amount = 16; - expenditure.paymentMethod = PaymentMethod.CHECK; - expenditure.checkNumber = '3456'; - expenditure.notes = 'buy stuff'; - expenditure.purpose = PurposeType.BROADCAST; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = transactionSchema; - const xml_valid = xml.transaction(); - // console.log('schema: ', xml_valid); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing of all transaction schema: expenditure, A/P, cash, fundraising', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.type = ExpenditureType.EXPENDITURE; - expenditure.subType = ExpenditureSubType.ACCOUNTS_PAYABLE; - expenditure.amount = 16; - expenditure.paymentMethod = PaymentMethod.CASH; - expenditure.notes = 'buy stuff'; - expenditure.purpose = PurposeType.FUNDRAISING; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = transactionSchema; - const xml_valid = xml.transaction(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing of all transaction schema: other, A/P/R, CC online, fundraising', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.type = ExpenditureType.OTHER; - expenditure.subType = ExpenditureSubType.ACCOUNTS_PAYABLE_RESCINDED; - expenditure.amount = 16; - expenditure.paymentMethod = PaymentMethod.CREDIT_CARD_ONLINE; - expenditure.notes = 'buy stuff'; - expenditure.purpose = PurposeType.GENERAL_OPERATING; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = transactionSchema; - const xml_valid = xml.transaction(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing of all transaction schema: other disbursement, misc other disbursements, CC paper, newspaper', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.type = ExpenditureType.OTHER_DISBURSEMENT; - expenditure.subType = ExpenditureSubType.MISCELLANEOUS_OTHER_DISBURSEMENT; - expenditure.amount = 16; - expenditure.paymentMethod = PaymentMethod.CREDIT_CARD_PAPER; - expenditure.notes = 'buy stuff'; - expenditure.purpose = PurposeType.NEWSPAPER; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = transactionSchema; - const xml_valid = xml.transaction(); - // console.log('schema: ', xml_valid); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - }); - - describe('CHOICE: operation schema', () => { - - it('confirms passing of transaction schema: add', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = operationSchema; - const xml_valid = xml.operation(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - // This additional choices are not yet supported - it('confirms passing of transaction schema: amend', () => { - const xsd = operationSchema; - const xml_valid = 'true'; - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing of transaction schema: delete', async () => { - const xsd = operationSchema; - const xml_valid = 'true'; - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failure of transaction schema', async () => { - const xsd = operationSchema; - const xml_valid = 'true'; - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - expect(xmlDocValid.validate(xsdDoc)).to.equal(false); - }); - - }); - - describe('ENUM: transaction type schema', () => { - - it('confirms passing of transaction type schema: EXPENDITURE', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.type = ExpenditureType.EXPENDITURE; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = transactionTypeSchema; - const xml_valid = xml.transactionType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing of transaction type schema: OTHER', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.type = ExpenditureType.OTHER; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = transactionTypeSchema; - const xml_valid = xml.transactionType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing of transaction type schema: OTHER_DISBURSEMENT', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.type = ExpenditureType.OTHER_DISBURSEMENT; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = transactionTypeSchema; - const xml_valid = xml.transactionType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failure of transaction type schema', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - (expenditure as any).type = 'nope'; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = transactionTypeSchema; - const xml_valid = xml.transactionType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(false); - }); - - }); - - describe('ENUM: transaction sub type schema', () => { - - it('confirms passing of transaction sub type schema: ACCOUNTS_PAYABLE', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.subType = ExpenditureSubType.ACCOUNTS_PAYABLE; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = transactionSubTypeSchema; - const xml_valid = xml.transactionSubType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing of transaction sub type schema: ACCOUNTS_PAYABLE_RESCINDED', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.subType = ExpenditureSubType.ACCOUNTS_PAYABLE_RESCINDED; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = transactionSubTypeSchema; - const xml_valid = xml.transactionSubType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing of transaction sub type schema: CASH_BALANCE_ADJUSTMENT', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.subType = ExpenditureSubType.CASH_BALANCE_ADJUSTMENT; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = transactionSubTypeSchema; - const xml_valid = xml.transactionSubType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing of transaction sub type schema: CASH_EXPENDITURE', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.subType = ExpenditureSubType.CASH_EXPENDITURE; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = transactionSubTypeSchema; - const xml_valid = xml.transactionSubType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing of transaction sub type schema: MISCELLANEOUS_OTHER_DISBURSEMENT', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.subType = ExpenditureSubType.MISCELLANEOUS_OTHER_DISBURSEMENT; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = transactionSubTypeSchema; - const xml_valid = xml.transactionSubType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing of transaction sub type schema: PERSONAL_EXPENDITURE', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.subType = ExpenditureSubType.PERSONAL_EXPENDITURE; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = transactionSubTypeSchema; - const xml_valid = xml.transactionSubType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing of transaction sub type schema: REFUND_OF_CONTRIBUTION', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.subType = ExpenditureSubType.REFUND_OF_CONTRIBUTION; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = transactionSubTypeSchema; - const xml_valid = xml.transactionSubType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failure of transaction sub type schema', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - (expenditure as any).subType = 'Nope'; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = transactionSubTypeSchema; - const xml_valid = xml.transactionSubType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(false); - }); - - }); - - describe('transaction amount', () => { - - it('confirms passing of transaction amount', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = amountSchema; - const xml_valid = xml.amount(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failure of transaction amount', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - (expenditure as any).amount = 'nope'; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = amountSchema; - const xml_valid = xml.amount(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(false); - }); - - }); - - describe('ENUM: transaction purpose schema', () => { - - it('confirms passing of transaction purpose schema: BROADCAST', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.purpose = PurposeType.BROADCAST; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = tranPurposeSchema; - const xml_valid = xml.tranPurposeType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing of transaction purpose schema: CASH', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.purpose = PurposeType.CASH; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = tranPurposeSchema; - const xml_valid = xml.tranPurposeType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing of transaction purpose schema: FUNDRAISING', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.purpose = PurposeType.FUNDRAISING; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = tranPurposeSchema; - const xml_valid = xml.tranPurposeType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing of transaction purpose schema: GENERAL_OPERATING', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.purpose = PurposeType.GENERAL_OPERATING; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = tranPurposeSchema; - const xml_valid = xml.tranPurposeType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing of transaction purpose schema: MANAGEMENT', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.purpose = PurposeType.MANAGEMENT; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = tranPurposeSchema; - const xml_valid = xml.tranPurposeType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing of transaction purpose schema: NEWSPAPER', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.purpose = PurposeType.NEWSPAPER; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = tranPurposeSchema; - const xml_valid = xml.tranPurposeType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing of transaction purpose schema: OTHER_AD', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.purpose = PurposeType.OTHER_AD; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = tranPurposeSchema; - const xml_valid = xml.tranPurposeType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing of transaction purpose schema: PETITION', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.purpose = PurposeType.PETITION; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = tranPurposeSchema; - const xml_valid = xml.tranPurposeType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing of transaction purpose schema: POLLING', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.purpose = PurposeType.POLLING; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = tranPurposeSchema; - const xml_valid = xml.tranPurposeType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing of transaction purpose schema: POSTAGE', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.purpose = PurposeType.POSTAGE; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = tranPurposeSchema; - const xml_valid = xml.tranPurposeType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing of transaction purpose schema: PREP_AD', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.purpose = PurposeType.PREP_AD; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = tranPurposeSchema; - const xml_valid = xml.tranPurposeType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing of transaction purpose schema: PRIMTING (printing 🙄)', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.purpose = PurposeType.PRIMTING; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = tranPurposeSchema; - const xml_valid = xml.tranPurposeType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing of transaction purpose schema: REIMBURSEMENT', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.purpose = PurposeType.REIMBURSEMENT; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = tranPurposeSchema; - const xml_valid = xml.tranPurposeType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing of transaction purpose schema: TRAVEL', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.purpose = PurposeType.TRAVEL; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = tranPurposeSchema; - const xml_valid = xml.tranPurposeType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing of transaction purpose schema: UTILITIES', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.purpose = PurposeType.UTILITIES; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = tranPurposeSchema; - const xml_valid = xml.tranPurposeType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing of transaction purpose schema: WAGES', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.purpose = PurposeType.WAGES; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = tranPurposeSchema; - const xml_valid = xml.tranPurposeType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failure of transaction purpose schema', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - (expenditure as any).purpose = 'Nope'; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = tranPurposeSchema; - const xml_valid = xml.tranPurposeType(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(false); - }); - - }); - - describe('transaction agent-id schema', () => { - - it('confirms passing of transaction action id', async () => { - const xsd = agentIdSchema; - const xml_valid = `789`; - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failure of transaction action id', async () => { - const xsd = agentIdSchema; - const xml_valid = `NOPE cuz this is over 30 characters`; - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(false); - }); - - }); - - describe('transaction expend-id schema', () => { - - it('confirms passing of transaction action id', async () => { - const xsd = expendIdSchema; - const xml_valid = `789`; - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failure of transaction action id', async () => { - const xsd = expendIdSchema; - const xml_valid = `NOPE cuz this is over 30 characters`; - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(false); - }); - - }); - - describe('transaction description schema', () => { - - it('confirms passing of transaction description', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.notes = 'Good notes'; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = transactionDescriptionSchema; - const xml_valid = xml.transactionDescription(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - }); - - describe('transaction aggregate amount', () => { - - it('confirms passing of transaction aggregate amount', async () => { - const xsd = aggregateAmountSchema; - const xml_valid = `0.7`; - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failure of transaction aggregate amount', async () => { - const xsd = aggregateAmountSchema; - const xml_valid = `NOPE`; - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(false); - }); - - }); - - describe('transaction payment-method', () => { - - it('confirms passing of transaction payment-method: CASH', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.paymentMethod = PaymentMethod.CASH; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = paymentMethodSchema; - const xml_valid = xml.paymentMethod(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing of transaction payment-method: CHECK', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.paymentMethod = PaymentMethod.CHECK; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = paymentMethodSchema; - const xml_valid = xml.paymentMethod(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing of transaction payment-method: CREDIT_CARD_ONLINE', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.paymentMethod = PaymentMethod.CREDIT_CARD_ONLINE; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = paymentMethodSchema; - const xml_valid = xml.paymentMethod(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing of transaction payment-method: CREDIT_CARD_PAPER', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.paymentMethod = PaymentMethod.CREDIT_CARD_PAPER; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = paymentMethodSchema; - const xml_valid = xml.paymentMethod(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing of transaction payment-method: ETF', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.paymentMethod = PaymentMethod.ETF; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = paymentMethodSchema; - const xml_valid = xml.paymentMethod(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms passing of transaction payment-method: MONEY_ORDER', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.paymentMethod = PaymentMethod.MONEY_ORDER; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = paymentMethodSchema; - const xml_valid = xml.paymentMethod(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failure of transaction payment-method', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - (expenditure as any).paymentMethod = 'Nope'; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = paymentMethodSchema; - const xml_valid = xml.paymentMethod(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(false); - }); - - }); - - describe('transaction date', () => { - - it('confirms passing of transaction payment-method: CASH', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = dateSchema; - const xml_valid = xml.transactionDate(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - }); - - describe('transaction check no', () => { - - it('confirms passing of transaction check no', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - expenditure.checkNumber = '12322'; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = checkNoSchema; - const xml_valid = xml.checkNo(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failure of transaction check no', async () => { - const expenditure = await newExpenditureAsync(campaign, government); expenditure.checkNumber = 'NOPE'; - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = checkNoSchema; - const xml_valid = xml.checkNo(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(false); - }); - - }); - - describe('expend-for schema', () => { - - it('confirms passing of expend-for schema', async () => { - const expenditure = await newExpenditureAsync(campaign, government); - const xml = new OrestarExpenditureConverter(expenditure); - const xsd = expendForSchema; - const xml_valid = xml.expendFor(); - const xsdDoc = libxml.parseXml(xsd); - const xmlDocValid = libxml.parseXml(xml_valid); - xmlDocValid.validate(xsdDoc); - // console.log(xmlDocValid.validationErrors); - expect(xmlDocValid.validate(xsdDoc)).to.equal(true); - }); - - it('confirms failure of expend-for schema', async () => { - const xsd = expendForSchema; - const xml_valid = 'nope'; - libxml.parseXml(xsd); - expect(libxml.parseXml.bind(xml_valid)).to.throw(); - }); - - }); - -}); \ No newline at end of file + beforeEach(async () => { + government = await newGovernmentAsync(); + campaign = await newCampaignAsync(government); + }); + + afterEach(async () => { + await truncateAll(); + }); + + describe('address schema', () => { + it('confirms passing of address schema', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = addressSchema; + const xml_valid = xml.address(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failure of address schema', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + delete expenditure.address1; + delete expenditure.city; + delete expenditure.state; + delete expenditure.zip; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = addressSchema; + const xml_valid = xml.address(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(false); + }); + }); + + describe('street1 schema', () => { + it('confirms passing of street1 schema', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = street1Schema; + const xml_valid = xml.street1(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failure of street1 schema', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.address1 = 'this is more than 40 characters. so the street will fail'; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = street1Schema; + const xml_valid = xml.street1(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(false); + }); + }); + + describe('street2 schema', () => { + it('confirms passing of street2 schema', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = street2Schema; + const xml_valid = xml.street2(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failure of street2 schema', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.address2 = 'this is more than 40 characters. so the street will fail'; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = street2Schema; + const xml_valid = xml.street2(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(false); + }); + }); + + describe('city schema', () => { + it('confirms passing of city schema', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = citySchema; + const xml_valid = xml.city(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failure of city schema', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.city = + 'For some reason this has a max length of 100 characters, but street1 is only 40? I need 20 more characters.'; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = citySchema; + const xml_valid = xml.city(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(false); + }); + }); + + describe('state schema', () => { + it('confirms passing of state schema', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = stateSchema; + const xml_valid = xml.state(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failure of state schema', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.state = '3ch'; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = stateSchema; + const xml_valid = xml.state(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(false); + }); + }); + + describe('zip schema', () => { + it('confirms passing of zip schema', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = zipSchema; + const xml_valid = xml.zip(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failure of zip schema', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.zip = '3ch'; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = zipSchema; + const xml_valid = xml.zip(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(false); + }); + }); + + describe('zipPlusFour schema', () => { + it('confirms passing of zipPlusFour schema', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.zip = '55555-5555'; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = zipPlusFourSchema; + const xml_valid = xml.zipPlusFour(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failure of zipPlusFour schema', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.zip = '9999-999999'; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = zipPlusFourSchema; + const xml_valid = xml.zipPlusFour(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(false); + }); + }); + + describe('ENUM: contact type schema', () => { + it('confirms passing of contact type schema: BUSINESS', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.payeeType = PayeeType.BUSINESS; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = contactTypeSchema; + const xml_valid = xml.contactType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing of contact type schema: FAMILY', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.payeeType = PayeeType.FAMILY; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = contactTypeSchema; + const xml_valid = xml.contactType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing of contact type schema: INDIVIDUAL', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.payeeType = PayeeType.INDIVIDUAL; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = contactTypeSchema; + const xml_valid = xml.contactType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing of contact type schema: LABOR', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.payeeType = PayeeType.LABOR; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = contactTypeSchema; + const xml_valid = xml.contactType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing of contact type schema: OTHER', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.payeeType = PayeeType.OTHER; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = contactTypeSchema; + const xml_valid = xml.contactType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing of contact type schema: POLITICAL_COMMITTEE', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.payeeType = PayeeType.POLITICAL_COMMITTEE; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = contactTypeSchema; + const xml_valid = xml.contactType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing of contact type schema: POLITICAL_PARTY', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.payeeType = PayeeType.POLITICAL_PARTY; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = contactTypeSchema; + const xml_valid = xml.contactType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing of contact type schema: UNREGISTERED', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.payeeType = PayeeType.UNREGISTERED; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = contactTypeSchema; + const xml_valid = xml.contactType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failure of contact type schema', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + (expenditure as any).payeeType = 'NOPE'; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = contactTypeSchema; + const xml_valid = xml.contactType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(false); + }); + }); + + describe('contact schema', () => { + it('confirms passing of contact schema', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = contactSchema; + const xml_valid = xml.contact(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing of contact schema', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = contactSchema; + const xml_valid = xml.contact(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + }); + + describe('transaction schema', () => { + it('confirms passing of all transaction schema: random', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = transactionSchema; + const xml_valid = xml.transaction(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing of all transaction schema: expenditure, cash, check, broadcast', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.type = ExpenditureType.EXPENDITURE; + expenditure.subType = ExpenditureSubType.CASH_EXPENDITURE; + expenditure.amount = 16; + expenditure.paymentMethod = PaymentMethod.CHECK; + expenditure.checkNumber = '3456'; + expenditure.notes = 'buy stuff'; + expenditure.purpose = PurposeType.BROADCAST; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = transactionSchema; + const xml_valid = xml.transaction(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing of all transaction schema: expenditure, A/P, cash, fundraising', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.type = ExpenditureType.EXPENDITURE; + expenditure.subType = ExpenditureSubType.ACCOUNTS_PAYABLE; + expenditure.amount = 16; + expenditure.paymentMethod = PaymentMethod.CASH; + expenditure.notes = 'buy stuff'; + expenditure.purpose = PurposeType.FUNDRAISING; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = transactionSchema; + const xml_valid = xml.transaction(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing of all transaction schema: other, A/P/R, CC online, fundraising', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.type = ExpenditureType.OTHER; + expenditure.subType = ExpenditureSubType.ACCOUNTS_PAYABLE_RESCINDED; + expenditure.amount = 16; + expenditure.paymentMethod = PaymentMethod.CREDIT_CARD_ONLINE; + expenditure.notes = 'buy stuff'; + expenditure.purpose = PurposeType.GENERAL_OPERATING; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = transactionSchema; + const xml_valid = xml.transaction(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing of all transaction schema: other disbursement, misc other disbursements, CC paper, newspaper', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.type = ExpenditureType.OTHER_DISBURSEMENT; + expenditure.subType = ExpenditureSubType.MISCELLANEOUS_OTHER_DISBURSEMENT; + expenditure.amount = 16; + expenditure.paymentMethod = PaymentMethod.CREDIT_CARD_PAPER; + expenditure.notes = 'buy stuff'; + expenditure.purpose = PurposeType.NEWSPAPER; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = transactionSchema; + const xml_valid = xml.transaction(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + }); + + describe('CHOICE: operation schema', () => { + it('confirms passing of transaction schema: add', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = operationSchema; + const xml_valid = xml.operation(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + // This additional choices are not yet supported + it('confirms passing of transaction schema: amend', () => { + const xsd = operationSchema; + const xml_valid = 'true'; + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing of transaction schema: delete', async () => { + const xsd = operationSchema; + const xml_valid = 'true'; + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failure of transaction schema', async () => { + const xsd = operationSchema; + const xml_valid = 'true'; + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(false); + }); + }); + + describe('ENUM: transaction type schema', () => { + it('confirms passing of transaction type schema: EXPENDITURE', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.type = ExpenditureType.EXPENDITURE; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = transactionTypeSchema; + const xml_valid = xml.transactionType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing of transaction type schema: OTHER', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.type = ExpenditureType.OTHER; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = transactionTypeSchema; + const xml_valid = xml.transactionType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing of transaction type schema: OTHER_DISBURSEMENT', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.type = ExpenditureType.OTHER_DISBURSEMENT; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = transactionTypeSchema; + const xml_valid = xml.transactionType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failure of transaction type schema', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + (expenditure as any).type = 'nope'; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = transactionTypeSchema; + const xml_valid = xml.transactionType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(false); + }); + }); + + describe('ENUM: transaction sub type schema', () => { + it('confirms passing of transaction sub type schema: ACCOUNTS_PAYABLE', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.subType = ExpenditureSubType.ACCOUNTS_PAYABLE; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = transactionSubTypeSchema; + const xml_valid = xml.transactionSubType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing of transaction sub type schema: ACCOUNTS_PAYABLE_RESCINDED', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.subType = ExpenditureSubType.ACCOUNTS_PAYABLE_RESCINDED; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = transactionSubTypeSchema; + const xml_valid = xml.transactionSubType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing of transaction sub type schema: CASH_BALANCE_ADJUSTMENT', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.subType = ExpenditureSubType.CASH_BALANCE_ADJUSTMENT; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = transactionSubTypeSchema; + const xml_valid = xml.transactionSubType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing of transaction sub type schema: CASH_EXPENDITURE', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.subType = ExpenditureSubType.CASH_EXPENDITURE; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = transactionSubTypeSchema; + const xml_valid = xml.transactionSubType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing of transaction sub type schema: MISCELLANEOUS_OTHER_DISBURSEMENT', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.subType = ExpenditureSubType.MISCELLANEOUS_OTHER_DISBURSEMENT; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = transactionSubTypeSchema; + const xml_valid = xml.transactionSubType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing of transaction sub type schema: PERSONAL_EXPENDITURE', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.subType = ExpenditureSubType.PERSONAL_EXPENDITURE; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = transactionSubTypeSchema; + const xml_valid = xml.transactionSubType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing of transaction sub type schema: REFUND_OF_CONTRIBUTION', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.subType = ExpenditureSubType.REFUND_OF_CONTRIBUTION; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = transactionSubTypeSchema; + const xml_valid = xml.transactionSubType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failure of transaction sub type schema', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + (expenditure as any).subType = 'Nope'; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = transactionSubTypeSchema; + const xml_valid = xml.transactionSubType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(false); + }); + }); + + describe('transaction amount', () => { + it('confirms passing of transaction amount', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = amountSchema; + const xml_valid = xml.amount(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failure of transaction amount', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + (expenditure as any).amount = 'nope'; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = amountSchema; + const xml_valid = xml.amount(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(false); + }); + }); + + describe('ENUM: transaction purpose schema', () => { + it('confirms passing of transaction purpose schema: BROADCAST', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.purpose = PurposeType.BROADCAST; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = tranPurposeSchema; + const xml_valid = xml.tranPurposeType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing of transaction purpose schema: CASH', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.purpose = PurposeType.CASH; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = tranPurposeSchema; + const xml_valid = xml.tranPurposeType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing of transaction purpose schema: FUNDRAISING', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.purpose = PurposeType.FUNDRAISING; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = tranPurposeSchema; + const xml_valid = xml.tranPurposeType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing of transaction purpose schema: GENERAL_OPERATING', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.purpose = PurposeType.GENERAL_OPERATING; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = tranPurposeSchema; + const xml_valid = xml.tranPurposeType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing of transaction purpose schema: MANAGEMENT', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.purpose = PurposeType.MANAGEMENT; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = tranPurposeSchema; + const xml_valid = xml.tranPurposeType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing of transaction purpose schema: NEWSPAPER', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.purpose = PurposeType.NEWSPAPER; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = tranPurposeSchema; + const xml_valid = xml.tranPurposeType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing of transaction purpose schema: OTHER_AD', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.purpose = PurposeType.OTHER_AD; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = tranPurposeSchema; + const xml_valid = xml.tranPurposeType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing of transaction purpose schema: PETITION', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.purpose = PurposeType.PETITION; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = tranPurposeSchema; + const xml_valid = xml.tranPurposeType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing of transaction purpose schema: POLLING', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.purpose = PurposeType.POLLING; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = tranPurposeSchema; + const xml_valid = xml.tranPurposeType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing of transaction purpose schema: POSTAGE', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.purpose = PurposeType.POSTAGE; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = tranPurposeSchema; + const xml_valid = xml.tranPurposeType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing of transaction purpose schema: PREP_AD', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.purpose = PurposeType.PREP_AD; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = tranPurposeSchema; + const xml_valid = xml.tranPurposeType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing of transaction purpose schema: PRIMTING (printing 🙄)', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.purpose = PurposeType.PRIMTING; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = tranPurposeSchema; + const xml_valid = xml.tranPurposeType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing of transaction purpose schema: REIMBURSEMENT', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.purpose = PurposeType.REIMBURSEMENT; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = tranPurposeSchema; + const xml_valid = xml.tranPurposeType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing of transaction purpose schema: TRAVEL', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.purpose = PurposeType.TRAVEL; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = tranPurposeSchema; + const xml_valid = xml.tranPurposeType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing of transaction purpose schema: UTILITIES', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.purpose = PurposeType.UTILITIES; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = tranPurposeSchema; + const xml_valid = xml.tranPurposeType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing of transaction purpose schema: WAGES', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.purpose = PurposeType.WAGES; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = tranPurposeSchema; + const xml_valid = xml.tranPurposeType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failure of transaction purpose schema', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + (expenditure as any).purpose = 'Nope'; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = tranPurposeSchema; + const xml_valid = xml.tranPurposeType(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(false); + }); + }); + + describe('transaction agent-id schema', () => { + it('confirms passing of transaction action id', async () => { + const xsd = agentIdSchema; + const xml_valid = `789`; + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failure of transaction action id', async () => { + const xsd = agentIdSchema; + const xml_valid = `NOPE cuz this is over 30 characters`; + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(false); + }); + }); + + describe('transaction expend-id schema', () => { + it('confirms passing of transaction action id', async () => { + const xsd = expendIdSchema; + const xml_valid = `789`; + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failure of transaction action id', async () => { + const xsd = expendIdSchema; + const xml_valid = `NOPE cuz this is over 30 characters`; + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(false); + }); + }); + + describe('transaction description schema', () => { + it('confirms passing of transaction description', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.notes = 'Good notes'; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = transactionDescriptionSchema; + const xml_valid = xml.transactionDescription(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + }); + + describe('transaction aggregate amount', () => { + it('confirms passing of transaction aggregate amount', async () => { + const xsd = aggregateAmountSchema; + const xml_valid = `0.7`; + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failure of transaction aggregate amount', async () => { + const xsd = aggregateAmountSchema; + const xml_valid = `NOPE`; + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(false); + }); + }); + + describe('transaction payment-method', () => { + it('confirms passing of transaction payment-method: CASH', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.paymentMethod = PaymentMethod.CASH; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = paymentMethodSchema; + const xml_valid = xml.paymentMethod(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing of transaction payment-method: CHECK', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.paymentMethod = PaymentMethod.CHECK; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = paymentMethodSchema; + const xml_valid = xml.paymentMethod(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing of transaction payment-method: CREDIT_CARD_ONLINE', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.paymentMethod = PaymentMethod.CREDIT_CARD_ONLINE; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = paymentMethodSchema; + const xml_valid = xml.paymentMethod(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing of transaction payment-method: CREDIT_CARD_PAPER', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.paymentMethod = PaymentMethod.CREDIT_CARD_PAPER; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = paymentMethodSchema; + const xml_valid = xml.paymentMethod(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing of transaction payment-method: ETF', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.paymentMethod = PaymentMethod.ETF; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = paymentMethodSchema; + const xml_valid = xml.paymentMethod(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms passing of transaction payment-method: MONEY_ORDER', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.paymentMethod = PaymentMethod.MONEY_ORDER; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = paymentMethodSchema; + const xml_valid = xml.paymentMethod(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failure of transaction payment-method', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + (expenditure as any).paymentMethod = 'Nope'; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = paymentMethodSchema; + const xml_valid = xml.paymentMethod(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(false); + }); + }); + + describe('transaction date', () => { + it('confirms passing of transaction payment-method: CASH', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = dateSchema; + const xml_valid = xml.transactionDate(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + }); + + describe('transaction check no', () => { + it('confirms passing of transaction check no', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.checkNumber = '12322'; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = checkNoSchema; + const xml_valid = xml.checkNo(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failure of transaction check no', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + expenditure.checkNumber = 'NOPE'; + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = checkNoSchema; + const xml_valid = xml.checkNo(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(false); + }); + }); + + describe('expend-for schema', () => { + it('confirms passing of expend-for schema', async () => { + const expenditure = await newExpenditureAsync(campaign, government); + const xml = new OrestarExpenditureConverter(expenditure); + const xsd = expendForSchema; + const xml_valid = xml.expendFor(); + const xsdDoc = libxml.parseXml(xsd); + const xmlDocValid = libxml.parseXml(xml_valid); + xmlDocValid.validate(xsdDoc); + expect(xmlDocValid.validate(xsdDoc)).toEqual(true); + }); + + it('confirms failure of expend-for schema', async () => { + const xsd = expendForSchema; + const xml_valid = 'nope'; + libxml.parseXml(xsd); + expect(libxml.parseXml.bind(xml_valid)).toThrow(); + }); + }); +}); diff --git a/api/test/entities/Activity.spec.ts b/api/test/entities/Activity.spec.ts index 1e5ffcf3d..42453774e 100644 --- a/api/test/entities/Activity.spec.ts +++ b/api/test/entities/Activity.spec.ts @@ -1,11 +1,11 @@ -import { expect } from 'chai'; import { getConnection, Repository } from 'typeorm'; import { newActiveUserAsync, newCampaignAsync, - newContributionAsync, newExpenditureAsync, + newContributionAsync, + newExpenditureAsync, newGovernmentAsync, - truncateAll + truncateAll, } from '../factories'; import { Activity, @@ -15,22 +15,21 @@ import { getActivityByContributionAsync, getActivityByExpenditureAsync, getActivityByGovernmentAsync, - getActivityByUserAsync + getActivityByUserAsync, } from '../../models/entity/Activity'; import { Government } from '../../models/entity/Government'; import { createActivityRecordAsync } from '../../services/activityService'; import { addPermissionAsync } from '../../services/permissionService'; import { UserRole } from '../../models/entity/Permission'; +import db from '../../models/db'; let activityRepository: Repository; let government: Government; describe('Activity', () => { - before(() => { - activityRepository = getConnection('default').getRepository(Activity); - }); - beforeEach(async () => { + const dataSource = await db(); + activityRepository = dataSource.getRepository(Activity); government = await newGovernmentAsync(); }); @@ -41,26 +40,26 @@ describe('Activity', () => { describe('validations', () => { it('notes', async () => { const activity = new Activity(); - expect(await activity.isValidAsync()).to.be.false; - expect(activity.errors[0].property).to.equal('notes'); - expect(activity.errors[0].constraints.isDefined).to.equal('notes should not be null or undefined'); + expect(await activity.isValidAsync()).toBeFalsy(); + expect(activity.errors[0].property).toEqual('notes'); + expect(activity.errors[0].constraints.isDefined).toEqual('notes should not be null or undefined'); }); it('activityId', async () => { const activity = new Activity(); activity.notes = 'Dan Melton updates something'; - expect(await activity.isValidAsync()).to.be.false; - expect(activity.errors[0].property).to.equal('activityId'); - expect(activity.errors[0].constraints.isDefined).to.equal('activityId should not be null or undefined'); + expect(await activity.isValidAsync()).toBeFalsy(); + expect(activity.errors[0].property).toEqual('activityId'); + expect(activity.errors[0].constraints.isDefined).toEqual('activityId should not be null or undefined'); }); it('activityType', async () => { const activity = new Activity(); activity.notes = 'Dan Melton updates something'; activity.activityId = 1; - expect(await activity.isValidAsync()).to.be.false; - expect(activity.errors[0].property).to.equal('activityType'); - expect(activity.errors[0].constraints.isDefined).to.equal('activityType should not be null or undefined'); + expect(await activity.isValidAsync()).toBeFalsy(); + expect(activity.errors[0].property).toEqual('activityType'); + expect(activity.errors[0].constraints.isDefined).toEqual('activityType should not be null or undefined'); }); it('valid', async () => { @@ -69,12 +68,12 @@ describe('Activity', () => { activity.activityId = 1; activity.activityType = ActivityTypeEnum.GOVERNMENT; activity.government = government; - expect(await activity.isValidAsync()).to.be.true; - expect(await activityRepository.count()).to.equal(0); - expect(activity.createdAt).to.be.undefined; + expect(await activity.isValidAsync()).toBeTruthy(); + expect(await activityRepository.count()).toEqual(0); + expect(activity.createdAt).toBeUndefined(); await activityRepository.save(activity); - expect(await activityRepository.count()).to.equal(1); - expect(activity.createdAt).to.not.be.undefined; + expect(await activityRepository.count()).toEqual(1); + expect(activity.createdAt).toBeDefined(); }); }); @@ -102,13 +101,13 @@ describe('Activity', () => { const records1 = await getActivityByGovernmentAsync(government.id, 100, 0, 'openelectionsportland.org'); const records2 = await getActivityByGovernmentAsync(government.id, 1, 0, 'openelectionsportland.org'); const records3 = await getActivityByGovernmentAsync(government.id, 1, 1, 'openelectionsportland.org'); - expect(noRecords.data.length).to.equal(0); - expect(records1.data.length).to.equal(2); - expect(records2.data.length).to.equal(1); - expect(records2.data[0].id).to.equal(activity2.id); - expect(records3.data.length).to.equal(1); - expect(records3.total).to.equal(2); - expect(records3.data[0].id).to.equal(activity1.id); + expect(noRecords.data.length).toEqual(0); + expect(records1.data.length).toEqual(2); + expect(records2.data.length).toEqual(1); + expect(records2.data[0].id).toEqual(activity2.id); + expect(records3.data.length).toEqual(1); + expect(records3.total).toEqual(2); + expect(records3.data[0].id).toEqual(activity1.id); }); it('getActivityByCampaignAsync', async () => { @@ -141,18 +140,18 @@ describe('Activity', () => { activityId: user.id, }); // test pagination - expect(await activityRepository.count()).to.equal(3); + expect(await activityRepository.count()).toEqual(3); const noRecords = await getActivityByCampaignAsync(1000, 100, 0, 'openelectionsportland.org'); const records1 = await getActivityByCampaignAsync(campaign.id, 100, 0, 'openelectionsportland.org'); const records2 = await getActivityByCampaignAsync(campaign.id, 1, 0, 'openelectionsportland.org'); const records3 = await getActivityByCampaignAsync(campaign.id, 1, 1, 'openelectionsportland.org'); - expect(noRecords.data.length).to.equal(0); - expect(records1.data.length).to.equal(2); - expect(records2.data.length).to.equal(1); - expect(records2.data[0].id).to.equal(activity2.id); - expect(records3.data.length).to.equal(1); - expect(records3.total).to.equal(2); - expect(records3.data[0].id).to.equal(activity1.id); + expect(noRecords.data.length).toEqual(0); + expect(records1.data.length).toEqual(2); + expect(records2.data.length).toEqual(1); + expect(records2.data[0].id).toEqual(activity2.id); + expect(records3.data.length).toEqual(1); + expect(records3.total).toEqual(2); + expect(records3.data[0].id).toEqual(activity1.id); }); it('getActivityByUser', async () => { @@ -160,19 +159,23 @@ describe('Activity', () => { const govUser = await newActiveUserAsync(); const gov = await newGovernmentAsync(); const campaign = await newCampaignAsync(gov); - await addPermissionAsync({userId: govUser.id, role: UserRole.GOVERNMENT_ADMIN, governmentId: gov.id}); - const permission = await addPermissionAsync({userId: user.id, role: UserRole.CAMPAIGN_ADMIN, campaignId: campaign.id}); + await addPermissionAsync({ userId: govUser.id, role: UserRole.GOVERNMENT_ADMIN, governmentId: gov.id }); + const permission = await addPermissionAsync({ + userId: user.id, + role: UserRole.CAMPAIGN_ADMIN, + campaignId: campaign.id, + }); await createActivityRecordAsync({ currentUser: user, notes: `${govUser.name()} added ${user.name()} to ${gov.name} as a ${UserRole.CAMPAIGN_ADMIN}`, government: gov, campaign, activityType: ActivityTypeEnum.PERMISSION, - activityId: permission.id + activityId: permission.id, }); const activities = await getActivityByUserAsync(user.id, 100, 0); - expect(activities.data.length).to.equal(1); - expect(activities.total).to.equal(1); + expect(activities.data.length).toEqual(1); + expect(activities.total).toEqual(1); }); it('getActivityByContributionAsync', async () => { @@ -180,14 +183,18 @@ describe('Activity', () => { const campaign = await newCampaignAsync(gov); const contr = await newContributionAsync(campaign, gov); const user = await newActiveUserAsync(); - const permission = await addPermissionAsync({userId: user.id, role: UserRole.CAMPAIGN_ADMIN, campaignId: campaign.id}); + const permission = await addPermissionAsync({ + userId: user.id, + role: UserRole.CAMPAIGN_ADMIN, + campaignId: campaign.id, + }); await createActivityRecordAsync({ currentUser: user, notes: `${user.name()} added a new contribution (${contr.id})`, campaign, government: gov, activityType: ActivityTypeEnum.CONTRIBUTION, - activityId: contr.id + activityId: contr.id, }); await createActivityRecordAsync({ @@ -196,11 +203,11 @@ describe('Activity', () => { campaign, government: gov, activityType: ActivityTypeEnum.COMMENT_CONTR, - activityId: contr.id + activityId: contr.id, }); const activities = await getActivityByContributionAsync(contr.id, 100, 0, 'openelectionsportland.org'); - expect(activities.data.length).to.equal(2); - expect(activities.total).to.equal(2); + expect(activities.data.length).toEqual(2); + expect(activities.total).toEqual(2); }); it('getActivityByExpenditureAsync', async () => { @@ -208,14 +215,18 @@ describe('Activity', () => { const campaign = await newCampaignAsync(gov); const exp = await newExpenditureAsync(campaign, gov); const user = await newActiveUserAsync(); - const permission = await addPermissionAsync({userId: user.id, role: UserRole.CAMPAIGN_ADMIN, campaignId: campaign.id}); + const permission = await addPermissionAsync({ + userId: user.id, + role: UserRole.CAMPAIGN_ADMIN, + campaignId: campaign.id, + }); await createActivityRecordAsync({ currentUser: user, notes: `${user.name()} added a new expenditure (${exp.id})`, campaign, government: gov, activityType: ActivityTypeEnum.EXPENDITURE, - activityId: exp.id + activityId: exp.id, }); await createActivityRecordAsync({ currentUser: user, @@ -223,11 +234,11 @@ describe('Activity', () => { campaign, government: gov, activityType: ActivityTypeEnum.COMMENT_EXP, - activityId: exp.id + activityId: exp.id, }); const activities = await getActivityByExpenditureAsync(exp.id, 100, 0, 'openelectionsportland.org'); - expect(activities.data.length).to.equal(2); - expect(activities.total).to.equal(2); + expect(activities.data.length).toEqual(2); + expect(activities.total).toEqual(2); }); it('getActivityByCampaignByTimeAsync', async () => { @@ -235,7 +246,7 @@ describe('Activity', () => { const campaign = await newCampaignAsync(gov); const contr = await newContributionAsync(campaign, gov); const user = await newActiveUserAsync(); - await addPermissionAsync({userId: user.id, role: UserRole.CAMPAIGN_ADMIN, campaignId: campaign.id}); + await addPermissionAsync({ userId: user.id, role: UserRole.CAMPAIGN_ADMIN, campaignId: campaign.id }); const activity = await createActivityRecordAsync({ currentUser: user, notes: `${user.name()} added a new contribution (${contr.id})`, @@ -243,7 +254,7 @@ describe('Activity', () => { government: gov, activityType: ActivityTypeEnum.CONTRIBUTION, activityId: contr.id, - notify: false + notify: false, }); const activity1 = await createActivityRecordAsync({ @@ -253,7 +264,7 @@ describe('Activity', () => { government: gov, activityType: ActivityTypeEnum.CONTRIBUTION, activityId: contr.id, - notify: true + notify: true, }); const activity2 = await createActivityRecordAsync({ @@ -263,26 +274,26 @@ describe('Activity', () => { government: gov, activityType: ActivityTypeEnum.COMMENT_CONTR, activityId: contr.id, - notify: true + notify: true, }); - await activityRepository.update(activity.id, {createdAt: new Date(2019, 1, 1)}); - await activityRepository.update(activity1.id, {createdAt: new Date(2019, 1, 1)}); - await activityRepository.update(activity2.id, {createdAt: new Date(2019, 8, 1)}); + await activityRepository.update(activity.id, { createdAt: new Date(2019, 1, 1) }); + await activityRepository.update(activity1.id, { createdAt: new Date(2019, 1, 1) }); + await activityRepository.update(activity2.id, { createdAt: new Date(2019, 8, 1) }); const activities = await getActivityByContributionAsync(contr.id, 100, 0, 'openelectionsportland.org'); - expect(activities.data.length).to.equal(3); + expect(activities.data.length).toEqual(3); let from = new Date(2018, 12, 31); let to = new Date(2019, 1, 31); let activitiesTime = await getActivityByCampaignByTimeAsync(campaign.id, from, to); - expect(activitiesTime.length).to.equal(1); + expect(activitiesTime.length).toEqual(1); from = new Date(2018, 12, 31); to = new Date(2020, 1, 31); activitiesTime = await getActivityByCampaignByTimeAsync(campaign.id, from, to); - expect(activitiesTime.length).to.equal(2); + expect(activitiesTime.length).toEqual(2); from = new Date(2017, 12, 31); to = new Date(2018, 1, 31); activitiesTime = await getActivityByCampaignByTimeAsync(campaign.id, from, to); - expect(activitiesTime.length).to.equal(0); + expect(activitiesTime.length).toEqual(0); }); }); diff --git a/api/test/entities/Campaign.spec.ts b/api/test/entities/Campaign.spec.ts index a8f305549..572169704 100644 --- a/api/test/entities/Campaign.spec.ts +++ b/api/test/entities/Campaign.spec.ts @@ -1,5 +1,4 @@ -import { expect } from 'chai'; -import { getConnection } from 'typeorm'; +import db from '../../models/db'; import { Campaign } from '../../models/entity/Campaign'; import { Government } from '../../models/entity/Government'; import { truncateAll } from '../factories'; @@ -9,9 +8,10 @@ let governmentRepository: any; let government: Government; describe('Campaign', () => { - before(async () => { - campaignRepository = getConnection('default').getRepository('Campaign'); - governmentRepository = getConnection('default').getRepository('Government'); + beforeAll(async () => { + const testDb = await db(); + campaignRepository = testDb.getRepository('Campaign'); + governmentRepository = testDb.getRepository('Government'); government = new Government(); government.name = 'City of Portland'; await governmentRepository.save(government); @@ -21,26 +21,26 @@ describe('Campaign', () => { await campaignRepository.query('TRUNCATE "campaign" CASCADE'); }); - after(async () => { + afterAll(async () => { await truncateAll(); }); - context('Validations', () => { + describe('Validations', () => { it('name testme', async () => { const campaign = new Campaign(); await campaign.validateAsync(); - expect(campaign.errors.length).to.equal(3); - expect(campaign.errors[0].property).equal('name'); - expect(campaign.errors[0].constraints.isDefined).equal('name should not be null or undefined'); + expect(campaign.errors.length).toEqual(3); + expect(campaign.errors[0].property).toEqual('name'); + expect(campaign.errors[0].constraints.isDefined).toEqual('name should not be null or undefined'); }); it('officeSought', async () => { const campaign = new Campaign(); campaign.name = 'Melton for Mayor'; await campaign.validateAsync(); - expect(campaign.errors.length).to.equal(2); - expect(campaign.errors[0].property).equal('officeSought'); - expect(campaign.errors[0].constraints.isDefined).equal('officeSought should not be null or undefined'); + expect(campaign.errors.length).toEqual(2); + expect(campaign.errors[0].property).toEqual('officeSought'); + expect(campaign.errors[0].constraints.isDefined).toEqual('officeSought should not be null or undefined'); }); it('government', async () => { @@ -48,18 +48,18 @@ describe('Campaign', () => { campaign.name = 'Melton for Mayor'; campaign.officeSought = 'Mayor'; await campaign.validateAsync(); - expect(campaign.errors.length).to.equal(1); - expect(campaign.errors[0].property).equal('governmentId'); - expect(campaign.errors[0].constraints.isDefined).equal('governmentId should not be null or undefined'); + expect(campaign.errors.length).toEqual(1); + expect(campaign.errors[0].property).toEqual('governmentId'); + expect(campaign.errors[0].constraints.isDefined).toEqual('governmentId should not be null or undefined'); }); it('isValid', async () => { const campaign = new Campaign(); - expect(await campaign.isValidAsync()).to.be.false; + expect(await campaign.isValidAsync()).toBeFalsy(); campaign.name = 'City of Portland'; campaign.government = government; campaign.officeSought = 'Mayor'; - expect(await campaign.isValidAsync()).to.be.true; + expect(await campaign.isValidAsync()).toBeTruthy(); }); it('validate throws error', async () => { @@ -67,7 +67,7 @@ describe('Campaign', () => { try { await campaignRepository.save(campaign); } catch (e) { - expect(e.message).to.equal('campaign has one or more validation problems'); + expect(e.message).toEqual('campaign has one or more validation problems'); } }); @@ -76,14 +76,13 @@ describe('Campaign', () => { campaign.name = 'City of Portland'; campaign.government = government; campaign.officeSought = 'Mayor'; - expect(await campaignRepository.count()).equal(0); + expect(await campaignRepository.count()).toEqual(0); await campaignRepository.save(campaign); - expect(await campaignRepository.count()).equal(1); + expect(await campaignRepository.count()).toEqual(1); }); - }); - context('JSON', () => { + describe('JSON', () => { it('toJson', async () => { const campaign = new Campaign(); campaign.name = 'Melton for Mayor'; @@ -91,11 +90,10 @@ describe('Campaign', () => { campaign.officeSought = 'Mayor'; await campaignRepository.save(campaign); const campaignJson = campaign.toJSON(); - expect(campaignJson.id).to.not.be.undefined; - expect(campaignJson.name).to.equal('Melton for Mayor'); - expect(campaignJson.governmentId).to.equal(government.id); - expect(campaignJson.officeSought).to.equal('Mayor'); + expect(campaignJson.id).toBeDefined(); + expect(campaignJson.name).toEqual('Melton for Mayor'); + expect(campaignJson.governmentId).toEqual(government.id); + expect(campaignJson.officeSought).toEqual('Mayor'); }); }); - }); diff --git a/api/test/entities/Contribution.spec.ts b/api/test/entities/Contribution.spec.ts index 4a404a8b5..2c51bb6d4 100644 --- a/api/test/entities/Contribution.spec.ts +++ b/api/test/entities/Contribution.spec.ts @@ -1,28 +1,26 @@ -import {expect} from 'chai'; -import {getConnection} from 'typeorm'; import { Contribution, ContributionStatus, ContributionSubType, ContributionType, - ContributorType, getContributionsGeoJsonAsync, - getContributionsSummaryByStatusAsync + ContributorType, + getContributionsGeoJsonAsync, + getContributionsSummaryByStatusAsync, } from '../../models/entity/Contribution'; -import {newCampaignAsync, newContributionAsync, newGovernmentAsync, truncateAll} from '../factories'; -import {Government} from '../../models/entity/Government'; -import {Campaign} from '../../models/entity/Campaign'; -import {PaymentMethod} from '../../models/entity/Expenditure'; +import { newCampaignAsync, newContributionAsync, newGovernmentAsync, truncateAll } from '../factories'; +import { Government } from '../../models/entity/Government'; +import { Campaign } from '../../models/entity/Campaign'; +import { PaymentMethod } from '../../models/entity/Expenditure'; +import db from '../../models/db'; let repository: any; let government: Government; let campaign: Campaign; describe('Contribution', () => { - before(() => { - repository = getConnection('default').getRepository('Contribution'); - }); - beforeEach(async () => { + const dataSource = await db(); + repository = dataSource.getRepository('Contribution'); government = await newGovernmentAsync(); campaign = await newCampaignAsync(government); }); @@ -35,9 +33,9 @@ describe('Contribution', () => { it('isDefined Columns', async () => { const newRecord = new Contribution(); await newRecord.validateAsync(); - expect(newRecord.errors.length).to.equal(12); - const isDefinedFields = newRecord.errors.map(item => item.property); - expect(isDefinedFields).to.deep.equal([ + expect(newRecord.errors.length).toEqual(12); + const isDefinedFields = newRecord.errors.map((item) => item.property); + expect(isDefinedFields).toEqual([ 'type', 'subType', 'contributorType', @@ -58,22 +56,26 @@ describe('Contribution', () => { newRecord.type = ContributionType.CONTRIBUTION; newRecord.subType = ContributionSubType.ITEM_REFUND; newRecord.paymentMethod = PaymentMethod.CASH; - expect(newRecord.errors.length).to.equal(0); + expect(newRecord.errors.length).toEqual(0); await newRecord.validateType(); - expect(newRecord.errors.length).to.equal(1); - expect(newRecord.errors[0].property).to.equal('subType'); - expect(newRecord.errors[0].constraints.notAllowed).to.equal('Type "contribution" must have a valid subType of "cash or an inkind value"'); + expect(newRecord.errors.length).toEqual(1); + expect(newRecord.errors[0].property).toEqual('subType'); + expect(newRecord.errors[0].constraints.notAllowed).toEqual( + 'Type "contribution" must have a valid subType of "cash or an inkind value"' + ); }); it('validatePaymentType CONTRIBUTION CASH', async () => { const newRecord = new Contribution(); newRecord.type = ContributionType.CONTRIBUTION; newRecord.subType = ContributionSubType.CASH; - expect(newRecord.errors.length).to.equal(0); + expect(newRecord.errors.length).toEqual(0); await newRecord.validatePaymentType(); - expect(newRecord.errors.length).to.equal(1); - expect(newRecord.errors[0].property).to.equal('paymentMethod'); - expect(newRecord.errors[0].constraints.notAllowed).to.equal('Type "contribution" with subType "cash" must have a paymentMethod'); + expect(newRecord.errors.length).toEqual(1); + expect(newRecord.errors[0].property).toEqual('paymentMethod'); + expect(newRecord.errors[0].constraints.notAllowed).toEqual( + 'Type "contribution" with subType "cash" must have a paymentMethod' + ); }); it('validateType OTHER', async () => { @@ -81,11 +83,13 @@ describe('Contribution', () => { newRecord.type = ContributionType.OTHER; newRecord.subType = ContributionSubType.CASH; newRecord.paymentMethod = PaymentMethod.CASH; - expect(newRecord.errors.length).to.equal(0); + expect(newRecord.errors.length).toEqual(0); await newRecord.validateType(); - expect(newRecord.errors.length).to.equal(1); - expect(newRecord.errors[0].property).to.equal('subType'); - expect(newRecord.errors[0].constraints.notAllowed).to.equal('Type "other" cannot have a subType of "cash or inkind value"'); + expect(newRecord.errors.length).toEqual(1); + expect(newRecord.errors[0].property).toEqual('subType'); + expect(newRecord.errors[0].constraints.notAllowed).toEqual( + 'Type "other" cannot have a subType of "cash or inkind value"' + ); }); it('validateName Individual', async () => { @@ -94,11 +98,11 @@ describe('Contribution', () => { newRecord.subType = ContributionSubType.CASH; newRecord.paymentMethod = PaymentMethod.CASH; newRecord.contributorType = ContributorType.INDIVIDUAL; - expect(newRecord.errors.length).to.equal(0); + expect(newRecord.errors.length).toEqual(0); await newRecord.validateName(); - expect(newRecord.errors.length).to.equal(2); - expect(newRecord.errors[0].property).to.equal('lastName'); - expect(newRecord.errors[1].property).to.equal('firstName'); + expect(newRecord.errors.length).toEqual(2); + expect(newRecord.errors[0].property).toEqual('lastName'); + expect(newRecord.errors[1].property).toEqual('firstName'); }); it('validateName Family', async () => { @@ -107,11 +111,11 @@ describe('Contribution', () => { newRecord.subType = ContributionSubType.CASH; newRecord.paymentMethod = PaymentMethod.CASH; newRecord.contributorType = ContributorType.FAMILY; - expect(newRecord.errors.length).to.equal(0); + expect(newRecord.errors.length).toEqual(0); await newRecord.validateName(); - expect(newRecord.errors.length).to.equal(2); - expect(newRecord.errors[0].property).to.equal('lastName'); - expect(newRecord.errors[1].property).to.equal('firstName'); + expect(newRecord.errors.length).toEqual(2); + expect(newRecord.errors[0].property).toEqual('lastName'); + expect(newRecord.errors[1].property).toEqual('firstName'); }); it('validateName not Individual', async () => { @@ -120,10 +124,10 @@ describe('Contribution', () => { newRecord.subType = ContributionSubType.CASH; newRecord.paymentMethod = PaymentMethod.CASH; newRecord.contributorType = ContributorType.BUSINESS; - expect(newRecord.errors.length).to.equal(0); + expect(newRecord.errors.length).toEqual(0); await newRecord.validateName(); - expect(newRecord.errors.length).to.equal(1); - expect(newRecord.errors[0].property).to.equal('name'); + expect(newRecord.errors.length).toEqual(1); + expect(newRecord.errors[0].property).toEqual('name'); }); it('validateMatchAmount', async () => { @@ -132,12 +136,12 @@ describe('Contribution', () => { newRecord.subType = ContributionSubType.CASH; newRecord.contributorType = ContributorType.INDIVIDUAL; newRecord.paymentMethod = PaymentMethod.CASH; - newRecord.amount = 1.00; - newRecord.matchAmount = 10.00; - expect(newRecord.errors.length).to.equal(0); + newRecord.amount = 1.0; + newRecord.matchAmount = 10.0; + expect(newRecord.errors.length).toEqual(0); await newRecord.validateMatchAmount(); - expect(newRecord.errors.length).to.equal(1); - expect(newRecord.errors[0].property).to.equal('matchAmount'); + expect(newRecord.errors.length).toEqual(1); + expect(newRecord.errors[0].property).toEqual('matchAmount'); }); it('isInKind && validateInKindType', async () => { @@ -146,15 +150,14 @@ describe('Contribution', () => { newRecord.subType = ContributionSubType.INKIND_CONTRIBUTION; newRecord.paymentMethod = PaymentMethod.CASH; newRecord.contributorType = ContributorType.INDIVIDUAL; - expect(newRecord.isInKind()).to.be.true; - expect(!newRecord.inKindType).to.be.true; + expect(newRecord.isInKind()).toBeTruthy(); + expect(!newRecord.inKindType).toBeTruthy(); await newRecord.validateInKindType(); - expect(newRecord.errors.length).to.equal(1); - expect(newRecord.errors[0].property).to.equal('inKindType'); + expect(newRecord.errors.length).toEqual(1); + expect(newRecord.errors[0].property).toEqual('inKindType'); }); }); - it('getContributionsSummaryByStatusAsync governmentId', async () => { const campaign2 = await newCampaignAsync(government); const [contr1, contr2, contr3, contr4, contr5] = await Promise.all([ @@ -164,16 +167,18 @@ describe('Contribution', () => { newContributionAsync(campaign2, government), newContributionAsync(campaign2, government), ]); - await repository.update(contr1.id, {status: ContributionStatus.SUBMITTED, amount: 1}); - await repository.update(contr2.id, {status: ContributionStatus.PROCESSED, amount: 1}); - await repository.update(contr3.id, {status: ContributionStatus.ARCHIVED, amount: 1}); - await repository.update(contr4.id, {amount: 1}); - await repository.update(contr5.id, {status: ContributionStatus.AWAITING, amount: 1}); - const summary = await getContributionsSummaryByStatusAsync({governmentId: government.id}); - expect(summary.map(item => item.amount)).to.deep.equal([1, 1, 1, 1]); - expect(summary.map(item => item.matchAmount)).to.deep.equal([0, 0, 0, 0]); - expect(summary.map(item => item.status)).to.deep.equal(['Draft', 'Submitted', 'Processed', 'Awaiting']); - expect(summary.map(item => item.total)).to.deep.equal([1, 1, 1, 1]); + await repository.update(contr1.id, { status: ContributionStatus.SUBMITTED, amount: 1 }); + await repository.update(contr2.id, { status: ContributionStatus.PROCESSED, amount: 1 }); + await repository.update(contr3.id, { status: ContributionStatus.ARCHIVED, amount: 1 }); + await repository.update(contr4.id, { amount: 1 }); + await repository.update(contr5.id, { status: ContributionStatus.AWAITING, amount: 1 }); + const summary = await getContributionsSummaryByStatusAsync({ governmentId: government.id }); + expect(summary.map((item) => item.amount)).toEqual([1, 1, 1, 1]); + expect(summary.map((item) => item.matchAmount)).toEqual([0, 0, 0, 0]); + expect(summary.map((item) => item.status)).toEqual( + expect.arrayContaining(['Draft', 'Submitted', 'Processed', 'Awaiting']) + ); + expect(summary.map((item) => item.total)).toEqual([1, 1, 1, 1]); }); it('getContributionsSummaryByStatusAsync campaign', async () => { @@ -184,21 +189,21 @@ describe('Contribution', () => { newContributionAsync(campaign, government), newContributionAsync(campaign2, government), ]); - await repository.update(contr1.id, {status: ContributionStatus.SUBMITTED, amount: 1}); - await repository.update(contr2.id, {status: ContributionStatus.PROCESSED, amount: 1}); - await repository.update(contr3.id, {status: ContributionStatus.ARCHIVED, amount: 1}); - await repository.update(contr4.id, {amount: 1}); - let summary = await getContributionsSummaryByStatusAsync({campaignId: campaign2.id}); - expect(summary.map(item => item.amount)).to.deep.equal([1]); - expect(summary.map(item => item.matchAmount)).to.deep.equal([0]); - expect(summary.map(item => item.status)).to.deep.equal(['Draft']); - expect(summary.map(item => item.total)).to.deep.equal([1]); - - summary = await getContributionsSummaryByStatusAsync({campaignId: campaign.id}); - expect(summary.map(item => item.amount)).to.deep.equal([1, 1]); - expect(summary.map(item => item.matchAmount)).to.deep.equal([0, 0]); - expect(summary.map(item => item.status)).to.deep.equal(['Submitted', 'Processed']); - expect(summary.map(item => item.total)).to.deep.equal([1, 1]); + await repository.update(contr1.id, { status: ContributionStatus.SUBMITTED, amount: 1 }); + await repository.update(contr2.id, { status: ContributionStatus.PROCESSED, amount: 1 }); + await repository.update(contr3.id, { status: ContributionStatus.ARCHIVED, amount: 1 }); + await repository.update(contr4.id, { amount: 1 }); + let summary = await getContributionsSummaryByStatusAsync({ campaignId: campaign2.id }); + expect(summary.map((item) => item.amount)).toEqual([1]); + expect(summary.map((item) => item.matchAmount)).toEqual([0]); + expect(summary.map((item) => item.status)).toEqual(['Draft']); + expect(summary.map((item) => item.total)).toEqual([1]); + + summary = await getContributionsSummaryByStatusAsync({ campaignId: campaign.id }); + expect(summary.map((item) => item.amount)).toEqual([1, 1]); + expect(summary.map((item) => item.matchAmount)).toEqual([0, 0]); + expect(summary.map((item) => item.status)).toEqual(expect.arrayContaining(['Submitted', 'Processed'])); + expect(summary.map((item) => item.total)).toEqual([1, 1]); }); it('getContributionsGeoJsonAsync testme', async () => { @@ -208,16 +213,30 @@ describe('Contribution', () => { newContributionAsync(campaign, government), newContributionAsync(campaign, government), ]); - await repository.update(contr2.id, {status: ContributionStatus.PROCESSED}); - await repository.update(contr3.id, {status: ContributionStatus.SUBMITTED}); - await repository.update(contr4.id, {status: ContributionStatus.ARCHIVED}); + await repository.update(contr2.id, { status: ContributionStatus.PROCESSED }); + await repository.update(contr3.id, { status: ContributionStatus.SUBMITTED }); + await repository.update(contr4.id, { status: ContributionStatus.ARCHIVED }); const contributions = await getContributionsGeoJsonAsync(); - expect(contributions.type).to.equal('FeatureCollection'); - expect(contributions.features.length).to.equal(2); - expect(contributions.features[0].type).to.equal('Feature'); - expect(Object.keys(contributions.features[0].properties)).to.deep.equal([ - 'type', 'city', 'state', 'zip', 'amount', 'contributorType', 'contributionType', 'contributionSubType', 'date', 'matchAmount', 'oaeType', 'campaignId', 'campaignName', 'officeSought', 'batchId', 'isMiscCashContributionUnder100' + expect(contributions.type).toEqual('FeatureCollection'); + expect(contributions.features.length).toEqual(2); + expect(contributions.features[0].type).toEqual('Feature'); + expect(Object.keys(contributions.features[0].properties)).toEqual([ + 'type', + 'city', + 'state', + 'zip', + 'amount', + 'contributorType', + 'contributionType', + 'contributionSubType', + 'date', + 'matchAmount', + 'oaeType', + 'campaignId', + 'campaignName', + 'officeSought', + 'batchId', + 'isMiscCashContributionUnder100', ]); }); }); - diff --git a/api/test/entities/Expenditure.spec.ts b/api/test/entities/Expenditure.spec.ts index 5bfbb76f0..5e544df7c 100644 --- a/api/test/entities/Expenditure.spec.ts +++ b/api/test/entities/Expenditure.spec.ts @@ -1,19 +1,20 @@ -import { expect } from 'chai'; -import * as faker from 'faker'; -import { getConnection } from 'typeorm'; +import { faker } from '@faker-js/faker'; +import db from '../../models/db'; import { Expenditure, ExpenditureStatus, ExpenditureSubType, ExpenditureType, + getExpendituresByGovernmentIdAsync, getExpenditureSummaryByStatusAsync, PayeeType, PaymentMethod, - PurposeType + PurposeType, } from '../../models/entity/Expenditure'; import { newCampaignAsync, newExpenditureAsync, newGovernmentAsync, truncateAll } from '../factories'; import { Government } from '../../models/entity/Government'; import { Campaign } from '../../models/entity/Campaign'; +import { IGetExpenditureAttrs } from '../../services/expenditureService'; let repository: any; let government: Government; @@ -21,7 +22,8 @@ let campaign: Campaign; describe('Expenditure', () => { beforeEach(async () => { - repository = getConnection('default').getRepository('Expenditure'); + const dataSource = await db(); + repository = dataSource.getRepository('Expenditure'); government = await newGovernmentAsync(); campaign = await newCampaignAsync(government); }); @@ -33,9 +35,10 @@ describe('Expenditure', () => { it('isDefined Columns', async () => { const newRecord = new Expenditure(); await newRecord.validateAsync(); - expect(newRecord.errors.length).to.equal(10); - const isDefinedFields = newRecord.errors.map(item => item.property); - expect(isDefinedFields).to.deep.equal(['date', + expect(newRecord.errors.length).toEqual(10); + const isDefinedFields = newRecord.errors.map((item) => item.property); + expect(isDefinedFields).toEqual([ + 'date', 'type', 'subType', 'payeeType', @@ -44,7 +47,8 @@ describe('Expenditure', () => { 'status', 'campaignId', 'governmentId', - 'amount']); + 'amount', + ]); }); it('validateType EXPENDITURE', async () => { @@ -53,11 +57,13 @@ describe('Expenditure', () => { newRecord.subType = ExpenditureSubType.MISCELLANEOUS_OTHER_DISBURSEMENT; newRecord.paymentMethod = PaymentMethod.CASH; newRecord.purpose = PurposeType.CASH; - expect(newRecord.errors.length).to.equal(0); + expect(newRecord.errors.length).toEqual(0); await newRecord.validateType(); - expect(newRecord.errors.length).to.equal(1); - expect(newRecord.errors[0].property).to.equal('subType'); - expect(newRecord.errors[0].constraints.notAllowed).to.equal('Type "expenditure" must have a subType of "accounts_payable, cash_expenditure or personal_expenditure"'); + expect(newRecord.errors.length).toEqual(1); + expect(newRecord.errors[0].property).toEqual('subType'); + expect(newRecord.errors[0].constraints.notAllowed).toEqual( + 'Type "expenditure" must have a subType of "accounts_payable, cash_expenditure or personal_expenditure"' + ); }); it('validateType OTHER', async () => { @@ -66,11 +72,13 @@ describe('Expenditure', () => { newRecord.subType = ExpenditureSubType.CASH_EXPENDITURE; newRecord.paymentMethod = PaymentMethod.CASH; newRecord.purpose = PurposeType.CASH; - expect(newRecord.errors.length).to.equal(0); + expect(newRecord.errors.length).toEqual(0); await newRecord.validateType(); - expect(newRecord.errors.length).to.equal(1); - expect(newRecord.errors[0].property).to.equal('subType'); - expect(newRecord.errors[0].constraints.notAllowed).to.equal('Type "other" must have a subType of "accounts_payable or cash_balance_adjustment"'); + expect(newRecord.errors.length).toEqual(1); + expect(newRecord.errors[0].property).toEqual('subType'); + expect(newRecord.errors[0].constraints.notAllowed).toEqual( + 'Type "other" must have a subType of "accounts_payable or cash_balance_adjustment"' + ); }); it('validateAmount', async () => { @@ -81,24 +89,23 @@ describe('Expenditure', () => { newRecord.purpose = PurposeType.CASH; newRecord.payeeType = PayeeType.INDIVIDUAL; newRecord.amount = 0; - expect(newRecord.errors.length).to.equal(0); + expect(newRecord.errors.length).toEqual(0); await newRecord.validateAmount(); - expect(newRecord.errors.length).to.equal(1); - expect(newRecord.errors[0].property).to.equal('amount'); + expect(newRecord.errors.length).toEqual(1); + expect(newRecord.errors[0].property).toEqual('amount'); }); - it('create', async () => { const newRecord = new Expenditure(); newRecord.type = ExpenditureType.EXPENDITURE; newRecord.subType = ExpenditureSubType.CASH_EXPENDITURE; newRecord.payeeType = PayeeType.INDIVIDUAL; - newRecord.amount = faker.finance.amount(0, 500, 2); - newRecord.address1 = faker.address.streetAddress(); + newRecord.amount = parseInt(faker.finance.amount({ min: 0, max: 500, dec: 2 })); + newRecord.address1 = faker.location.streetAddress(); newRecord.zip = '97214'; newRecord.city = 'Portland'; newRecord.state = 'OR'; - newRecord.name = faker.name.findName(); + newRecord.name = faker.person.fullName(); newRecord.government = government; newRecord.campaign = campaign; newRecord.status = ExpenditureStatus.DRAFT; @@ -106,19 +113,19 @@ describe('Expenditure', () => { newRecord.paymentMethod = PaymentMethod.CASH; newRecord.purpose = PurposeType.CASH; await newRecord.validateAsync(); - expect(newRecord.errors.length).to.equal(0); - expect(await repository.count()).to.equal(0); + expect(newRecord.errors.length).toEqual(0); + expect(await repository.count()).toEqual(0); await repository.save(newRecord); - expect(await repository.count()).to.equal(1); + expect(await repository.count()).toEqual(1); }); it('update', async () => { const newRecord = await newExpenditureAsync(campaign, government); - expect(newRecord.name).to.not.equal('Dan'); - const found = await repository.findOne(newRecord.id); - await repository.update(found.id, {name: 'Dan'}); - const changed = await repository.findOne(newRecord.id); - expect(changed.name).to.equal('Dan'); + expect(newRecord.name).not.toEqual('Dan'); + const found = await repository.findOne({ where: { id: newRecord.id } }); + await repository.update(found.id, { name: 'Dan' }); + const changed = await repository.findOne({ where: { id: newRecord.id } }); + expect(changed.name).toEqual('Dan'); }); it('getExpenditureSummaryByStatusAsync governmentId', async () => { @@ -129,12 +136,12 @@ describe('Expenditure', () => { newExpenditureAsync(campaign, government), newExpenditureAsync(campaign2, government), ]); - await repository.update(exp1.id, {status: ExpenditureStatus.SUBMITTED, amount: 1}); - await repository.update(exp2.id, {status: ExpenditureStatus.IN_COMPLIANCE, amount: 1}); - await repository.update(exp3.id, {status: ExpenditureStatus.OUT_OF_COMPLIANCE, amount: 1}); - await repository.update(exp4.id, {amount: 1}); - const summary = await getExpenditureSummaryByStatusAsync({governmentId: government.id}); - expect(summary.length).to.equal(4); + await repository.update(exp1.id, { status: ExpenditureStatus.SUBMITTED, amount: 1 }); + await repository.update(exp2.id, { status: ExpenditureStatus.IN_COMPLIANCE, amount: 1 }); + await repository.update(exp3.id, { status: ExpenditureStatus.OUT_OF_COMPLIANCE, amount: 1 }); + await repository.update(exp4.id, { amount: 1 }); + const summary = await getExpenditureSummaryByStatusAsync({ governmentId: government.id }); + expect(summary.length).toEqual(4); }); it('getExpenditureSummaryByStatusAsync campaign', async () => { @@ -145,20 +152,51 @@ describe('Expenditure', () => { newExpenditureAsync(campaign, government), newExpenditureAsync(campaign2, government), ]); - await repository.update(exp1.id, {status: ExpenditureStatus.SUBMITTED, amount: 1}); - await repository.update(exp2.id, {status: ExpenditureStatus.IN_COMPLIANCE, amount: 1}); - await repository.update(exp3.id, {status: ExpenditureStatus.OUT_OF_COMPLIANCE, amount: 1}); - await repository.update(exp4.id, {amount: 1}); - let summary = await getExpenditureSummaryByStatusAsync({campaignId: campaign2.id}); - expect(summary).to.deep.equal([ + await repository.update(exp1.id, { status: ExpenditureStatus.SUBMITTED, amount: 1 }); + await repository.update(exp2.id, { status: ExpenditureStatus.IN_COMPLIANCE, amount: 1 }); + await repository.update(exp3.id, { status: ExpenditureStatus.OUT_OF_COMPLIANCE, amount: 1 }); + await repository.update(exp4.id, { amount: 1 }); + let summary = await getExpenditureSummaryByStatusAsync({ campaignId: campaign2.id }); + expect(summary).toEqual([ { - 'amount': 1, - 'status': 'draft', - 'total': 1, - }]); + amount: 1, + status: 'draft', + total: 1, + }, + ]); - summary = await getExpenditureSummaryByStatusAsync({campaignId: campaign.id}); - expect(summary.length).to.equal(3); + summary = await getExpenditureSummaryByStatusAsync({ campaignId: campaign.id }); + expect(summary.length).toEqual(3); }); -}); + it('getExpendituresByGovernmentIdAsync', async () => { + const campaign2 = await newCampaignAsync(government); + const [exp1, exp2, exp3, exp4] = await Promise.all([ + newExpenditureAsync(campaign, government), + newExpenditureAsync(campaign, government), + newExpenditureAsync(campaign, government), + newExpenditureAsync(campaign2, government), + ]); + await repository.update(exp1.id, { status: ExpenditureStatus.SUBMITTED, amount: 1 }); + await repository.update(exp2.id, { status: ExpenditureStatus.IN_COMPLIANCE, amount: 1 }); + await repository.update(exp3.id, { status: ExpenditureStatus.OUT_OF_COMPLIANCE, amount: 1 }); + await repository.update(exp4.id, { amount: 1 }); + + const options: IGetExpenditureAttrs = { + page: 1, + perPage: 10, + campaignId: campaign.id, + status: ExpenditureStatus.SUBMITTED, + sort: { field: 'date', direction: 'ASC' }, + format: 'json', + }; + + const result = await getExpendituresByGovernmentIdAsync(government.id, options); + console.log(JSON.stringify(result)); + expect(result.data.length).toEqual(1); + expect(result.data[0].status).toEqual(ExpenditureStatus.SUBMITTED); + expect(result.total).toEqual(1); + expect(result.page).toEqual(1); + expect(result.perPage).toEqual(10); + }); +}); diff --git a/api/test/entities/ExternalContribution.spec.ts b/api/test/entities/ExternalContribution.spec.ts index cb1af0168..e84b50ef2 100644 --- a/api/test/entities/ExternalContribution.spec.ts +++ b/api/test/entities/ExternalContribution.spec.ts @@ -1,120 +1,138 @@ -import { expect } from 'chai'; -import { getConnection } from 'typeorm'; import { truncateAll, newExternalContributionAsync } from '../factories'; import { - ExternalContribution, - ExternalContributionSubType, getExternalContributionsGeoJsonAsync + ExternalContribution, + ExternalContributionSubType, + getExternalContributionsGeoJsonAsync, } from '../../models/entity/ExternalContribution'; import { ContributionType, ContributorType } from '../../models/entity/Contribution'; +import db from '../../models/db'; let repository: any; describe('External Contribution', () => { - before(() => { - repository = getConnection('default').getRepository('external_contributions'); - }); - afterEach(async () => { - await truncateAll(); - }); - describe('validations', async () => { - it('isDefined Columns', async () => { - const newRecord = new ExternalContribution(); - await newRecord.validateAsync(); - expect(newRecord.errors.length).to.equal(11); - const isDefinedFields = newRecord.errors.map(item => item.property); - expect(isDefinedFields).to.deep.equal([ - 'orestarOriginalId', - 'orestarTransactionId', - 'type', - 'subType', - 'contributorType', - 'address1', - 'city', - 'state', - 'zip', - 'date', - 'name', - ]); + beforeEach(async () => { + const dataSource = await db(); + repository = dataSource.getRepository('external_contributions'); }); - it('validateType CONTRIBUTION', async () => { - const newRecord = new ExternalContribution(); - newRecord.type = ContributionType.CONTRIBUTION; - newRecord.subType = ExternalContributionSubType.ITEM_REFUND; - expect(newRecord.errors.length).to.equal(0); - await newRecord.validateType(); - expect(newRecord.errors.length).to.equal(1); - expect(newRecord.errors[0].property).to.equal('subType'); - expect(newRecord.errors[0].constraints.notAllowed).to.equal('Type "contribution" must have a valid subType of "cash or an inkind value"'); + afterEach(async () => { + await truncateAll(); }); + describe('validations', () => { + it('isDefined Columns', async () => { + const newRecord = new ExternalContribution(); + await newRecord.validateAsync(); + expect(newRecord.errors.length).toEqual(11); + const isDefinedFields = newRecord.errors.map((item) => item.property); + expect(isDefinedFields).toEqual([ + 'orestarOriginalId', + 'orestarTransactionId', + 'type', + 'subType', + 'contributorType', + 'address1', + 'city', + 'state', + 'zip', + 'date', + 'name', + ]); + }); + it('validateType CONTRIBUTION', async () => { + const newRecord = new ExternalContribution(); + newRecord.type = ContributionType.CONTRIBUTION; + newRecord.subType = ExternalContributionSubType.ITEM_REFUND; + expect(newRecord.errors.length).toEqual(0); + await newRecord.validateType(); + expect(newRecord.errors.length).toEqual(1); + expect(newRecord.errors[0].property).toEqual('subType'); + expect(newRecord.errors[0].constraints.notAllowed).toEqual( + 'Type "contribution" must have a valid subType of "cash or an inkind value"' + ); + }); - it('validatePaymentType CONTRIBUTION CASH', async () => { - const newRecord = new ExternalContribution(); - newRecord.type = ContributionType.CONTRIBUTION; - newRecord.subType = ExternalContributionSubType.CASH; - expect(newRecord.errors.length).to.equal(0); - await newRecord.validateName(); - expect(newRecord.errors.length).to.equal(1); - expect(newRecord.errors[0].property).to.equal('name'); - expect(newRecord.errors[0].constraints.isDefined).to.equal('name should not be null or undefined'); - }); - it('validateType OTHER', async () => { - const newRecord = new ExternalContribution(); - newRecord.type = ContributionType.OTHER; - newRecord.subType = ExternalContributionSubType.CASH; - expect(newRecord.errors.length).to.equal(0); - await newRecord.validateType(); - expect(newRecord.errors.length).to.equal(1); - expect(newRecord.errors[0].property).to.equal('subType'); - expect(newRecord.errors[0].constraints.notAllowed).to.equal('Type "other" cannot have a subType of "cash or inkind value"'); - }); - it('validateName Individual', async () => { - const newRecord = new ExternalContribution(); - newRecord.type = ContributionType.CONTRIBUTION; - newRecord.subType = ExternalContributionSubType.CASH; - newRecord.contributorType = ContributorType.INDIVIDUAL; - expect(newRecord.errors.length).to.equal(0); - await newRecord.validateName(); - expect(newRecord.errors.length).to.equal(1); - expect(newRecord.errors[0].property).to.equal('name'); - }); - it('validateName Family', async () => { - const newRecord = new ExternalContribution(); - newRecord.type = ContributionType.CONTRIBUTION; - newRecord.subType = ExternalContributionSubType.CASH; - newRecord.contributorType = ContributorType.FAMILY; - expect(newRecord.errors.length).to.equal(0); - await newRecord.validateName(); - expect(newRecord.errors.length).to.equal(1); - expect(newRecord.errors[0].property).to.equal('name'); - }); + it('validatePaymentType CONTRIBUTION CASH', async () => { + const newRecord = new ExternalContribution(); + newRecord.type = ContributionType.CONTRIBUTION; + newRecord.subType = ExternalContributionSubType.CASH; + expect(newRecord.errors.length).toEqual(0); + await newRecord.validateName(); + expect(newRecord.errors.length).toEqual(1); + expect(newRecord.errors[0].property).toEqual('name'); + expect(newRecord.errors[0].constraints.isDefined).toEqual('name should not be null or undefined'); + }); + it('validateType OTHER', async () => { + const newRecord = new ExternalContribution(); + newRecord.type = ContributionType.OTHER; + newRecord.subType = ExternalContributionSubType.CASH; + expect(newRecord.errors.length).toEqual(0); + await newRecord.validateType(); + expect(newRecord.errors.length).toEqual(1); + expect(newRecord.errors[0].property).toEqual('subType'); + expect(newRecord.errors[0].constraints.notAllowed).toEqual( + 'Type "other" cannot have a subType of "cash or inkind value"' + ); + }); + it('validateName Individual', async () => { + const newRecord = new ExternalContribution(); + newRecord.type = ContributionType.CONTRIBUTION; + newRecord.subType = ExternalContributionSubType.CASH; + newRecord.contributorType = ContributorType.INDIVIDUAL; + expect(newRecord.errors.length).toEqual(0); + await newRecord.validateName(); + expect(newRecord.errors.length).toEqual(1); + expect(newRecord.errors[0].property).toEqual('name'); + }); + it('validateName Family', async () => { + const newRecord = new ExternalContribution(); + newRecord.type = ContributionType.CONTRIBUTION; + newRecord.subType = ExternalContributionSubType.CASH; + newRecord.contributorType = ContributorType.FAMILY; + expect(newRecord.errors.length).toEqual(0); + await newRecord.validateName(); + expect(newRecord.errors.length).toEqual(1); + expect(newRecord.errors[0].property).toEqual('name'); + }); - it('validateName not Individual', async () => { - const newRecord = new ExternalContribution(); - newRecord.type = ContributionType.CONTRIBUTION; - newRecord.subType = ExternalContributionSubType.CASH; - newRecord.contributorType = ContributorType.BUSINESS; - expect(newRecord.errors.length).to.equal(0); - await newRecord.validateName(); - expect(newRecord.errors.length).to.equal(1); - expect(newRecord.errors[0].property).to.equal('name'); + it('validateName not Individual', async () => { + const newRecord = new ExternalContribution(); + newRecord.type = ContributionType.CONTRIBUTION; + newRecord.subType = ExternalContributionSubType.CASH; + newRecord.contributorType = ContributorType.BUSINESS; + expect(newRecord.errors.length).toEqual(0); + await newRecord.validateName(); + expect(newRecord.errors.length).toEqual(1); + expect(newRecord.errors[0].property).toEqual('name'); + }); }); - }); - describe('Test DB interactions', () => { - it('getExternalContributionsGeoJsonAsync', async () => { - const [contr1, contr2] = await Promise.all([ - newExternalContributionAsync(), - newExternalContributionAsync(), - ]); - await repository.update(contr2.orestarOriginalId, { - orestarTransactionId: '500' - }); - const contributions = await getExternalContributionsGeoJsonAsync(); - expect(contributions.type).to.equal('FeatureCollection'); - expect(contributions.features.length).to.equal(2); - expect(contributions.features[0].type).to.equal('Feature'); - expect(Object.keys(contributions.features[0].properties)).to.deep.equal([ - 'type', 'city', 'state', 'zip', 'amount', 'contributorType', 'contributionType', 'contributionSubType', 'date', 'campaignId', 'campaignName', 'officeSought', 'batchId', 'isMiscCashContributionUnder100' - ]); + describe('Test DB interactions', () => { + it('getExternalContributionsGeoJsonAsync', async () => { + const [contr1, contr2] = await Promise.all([ + newExternalContributionAsync(), + newExternalContributionAsync(), + ]); + await repository.update(contr2.orestarOriginalId, { + orestarTransactionId: '500', + }); + const contributions = await getExternalContributionsGeoJsonAsync(); + expect(contributions.type).toEqual('FeatureCollection'); + expect(contributions.features.length).toEqual(1); + expect(contributions.features[0].type).toEqual('Feature'); + expect(Object.keys(contributions.features[0].properties)).toEqual([ + 'type', + 'city', + 'state', + 'zip', + 'amount', + 'contributorType', + 'contributionType', + 'contributionSubType', + 'date', + 'campaignId', + 'campaignName', + 'officeSought', + 'batchId', + 'isMiscCashContributionUnder100', + ]); + }); }); - }); -}); \ No newline at end of file +}); diff --git a/api/test/entities/Government.spec.ts b/api/test/entities/Government.spec.ts index 7486db562..30a38c4fe 100644 --- a/api/test/entities/Government.spec.ts +++ b/api/test/entities/Government.spec.ts @@ -1,32 +1,32 @@ -import { expect } from 'chai'; -import { getConnection } from 'typeorm'; +import db from '../../models/db'; import { Government } from '../../models/entity/Government'; import { truncateAll } from '../factories'; let governmentRepository: any; describe('Government', () => { - before(() => { - governmentRepository = getConnection('default').getRepository('Government'); + beforeEach(async () => { + const dataSource = await db(); + governmentRepository = dataSource.getRepository('Government'); }); afterEach(async () => { await truncateAll(); }); - context('Validations', () => { + describe('Validations', () => { it('name', async () => { const government = new Government(); await government.validateAsync(); - expect(government.errors[0].property).equal('name'); - expect(government.errors[0].constraints.isDefined).equal('name should not be null or undefined'); + expect(government.errors[0].property).toEqual('name'); + expect(government.errors[0].constraints.isDefined).toEqual('name should not be null or undefined'); }); it('isValid', async () => { const government = new Government(); - expect(await government.isValidAsync()).to.be.false; + expect(await government.isValidAsync()).toBeFalsy(); government.name = 'City of Portland'; - expect(await government.isValidAsync()).to.be.true; + expect(await government.isValidAsync()).toBeTruthy(); }); it('validate throws error', async () => { @@ -34,29 +34,27 @@ describe('Government', () => { try { await governmentRepository.save(government); } catch (e) { - expect(e.message).to.equal('government has one or more validation problems'); + expect(e.message).toEqual('government has one or more validation problems'); } }); it('validate does not throws error', async () => { const government = new Government(); government.name = 'City of Portland'; - expect(await governmentRepository.count()).equal(0); + expect(await governmentRepository.count()).toEqual(0); await governmentRepository.save(government); - expect(await governmentRepository.count()).equal(1); + expect(await governmentRepository.count()).toEqual(1); }); - }); - context('JSON', () => { + describe('JSON', () => { it('toJson', async () => { const government = new Government(); government.name = 'City of Portland'; await governmentRepository.save(government); const governmentJson = government.toJSON(); - expect(governmentJson.id).to.not.be.undefined; - expect(governmentJson.name).to.equal('City of Portland'); + expect(governmentJson.id).toBeDefined(); + expect(governmentJson.name).toEqual('City of Portland'); }); }); - }); diff --git a/api/test/entities/Permission.spec.ts b/api/test/entities/Permission.spec.ts index 591c944de..44f09c983 100644 --- a/api/test/entities/Permission.spec.ts +++ b/api/test/entities/Permission.spec.ts @@ -1,5 +1,3 @@ -import { expect } from 'chai'; -import { getConnection } from 'typeorm'; import { Campaign } from '../../models/entity/Campaign'; import { Government } from '../../models/entity/Government'; import { User } from '../../models/entity/User'; @@ -7,10 +5,10 @@ import { getPermissionsByCampaignIdAsync, getPermissionsByGovernmentIdAsync, Permission, - UserRole + UserRole, } from '../../models/entity/Permission'; import { newActiveUserAsync, newCampaignAsync, newGovernmentAsync, truncateAll } from '../factories'; - +import db from '../../models/db'; let permissionRepository: any; let campaignRepository: any; @@ -26,10 +24,11 @@ describe('Permission', () => { beforeEach(async () => { user = await newActiveUserAsync(); user2 = await newActiveUserAsync(); - campaignRepository = getConnection('default').getRepository('Campaign'); - governmentRepository = getConnection('default').getRepository('Government'); - permissionRepository = getConnection('default').getRepository('Permission'); - userRepository = getConnection('default').getRepository('User'); + const dataSource = await db(); + campaignRepository = dataSource.getRepository('Campaign'); + governmentRepository = dataSource.getRepository('Government'); + permissionRepository = dataSource.getRepository('Permission'); + userRepository = dataSource.getRepository('User'); government = await newGovernmentAsync(); campaign = await newCampaignAsync(government); campaign2 = await newCampaignAsync(government); @@ -39,22 +38,22 @@ describe('Permission', () => { await truncateAll(); }); - context('Validations', () => { + describe('Validations', () => { it('role', async () => { const permission = new Permission(); await permission.validateAsync(); - expect(permission.errors.length).to.equal(4); - expect(permission.errors[0].property).equal('role'); - expect(permission.errors[0].constraints.isDefined).equal('role should not be null or undefined'); + expect(permission.errors.length).toEqual(4); + expect(permission.errors[0].property).toEqual('role'); + expect(permission.errors[0].constraints.isDefined).toEqual('role should not be null or undefined'); }); it('user', async () => { const permission = new Permission(); permission.role = UserRole.GOVERNMENT_ADMIN; await permission.validateAsync(); - expect(permission.errors.length).to.equal(2); - expect(permission.errors[0].property).equal('userId'); - expect(permission.errors[0].constraints.isDefined).equal('userId should not be null or undefined'); + expect(permission.errors.length).toEqual(2); + expect(permission.errors[0].property).toEqual('userId'); + expect(permission.errors[0].constraints.isDefined).toEqual('userId should not be null or undefined'); }); it('governmentId', async () => { @@ -62,9 +61,9 @@ describe('Permission', () => { permission.role = UserRole.GOVERNMENT_ADMIN; permission.user = user; await permission.validateAsync(); - expect(permission.errors.length).to.equal(1); - expect(permission.errors[0].property).equal('governmentId'); - expect(permission.errors[0].constraints.isDefined).equal('governmentId should not be null or undefined'); + expect(permission.errors.length).toEqual(1); + expect(permission.errors[0].property).toEqual('governmentId'); + expect(permission.errors[0].constraints.isDefined).toEqual('governmentId should not be null or undefined'); }); it('campaignId', async () => { @@ -73,9 +72,9 @@ describe('Permission', () => { permission.user = user; permission.government = government; await permission.validateAsync(); - expect(permission.errors.length).to.equal(1); - expect(permission.errors[0].property).equal('campaignId'); - expect(permission.errors[0].constraints.isDefined).equal('campaignId should not be null or undefined'); + expect(permission.errors.length).toEqual(1); + expect(permission.errors[0].property).toEqual('campaignId'); + expect(permission.errors[0].constraints.isDefined).toEqual('campaignId should not be null or undefined'); }); it('campaignId cannot be set if UserRole.GOVERNMENT_ADMIN', async () => { @@ -85,39 +84,40 @@ describe('Permission', () => { permission.government = government; permission.campaign = campaign; await permission.validateAsync(); - expect(permission.errors.length).to.equal(1); - expect(permission.errors[0].property).equal('campaignId'); - expect(permission.errors[0].constraints.notAllowed).equal('campaignId cannot be set with GovernmentAdmin as a UserRole'); + expect(permission.errors.length).toEqual(1); + expect(permission.errors[0].property).toEqual('campaignId'); + expect(permission.errors[0].constraints.notAllowed).toEqual( + 'campaignId cannot be set with GovernmentAdmin as a UserRole' + ); }); - it('isValid Campaign Staff', async () => { const permission = new Permission(); - expect(await permission.isValidAsync()).to.be.false; + expect(await permission.isValidAsync()).toBeFalsy(); permission.role = UserRole.CAMPAIGN_STAFF; permission.user = user; permission.government = government; permission.campaign = campaign; - expect(await permission.isValidAsync()).to.be.true; + expect(await permission.isValidAsync()).toBeTruthy(); }); it('isValid Campaign Admin', async () => { const permission = new Permission(); - expect(await permission.isValidAsync()).to.be.false; + expect(await permission.isValidAsync()).toBeFalsy(); permission.role = UserRole.CAMPAIGN_ADMIN; permission.user = user; permission.government = government; permission.campaign = campaign; - expect(await permission.isValidAsync()).to.be.true; + expect(await permission.isValidAsync()).toBeTruthy(); }); it('isValid Government Admin', async () => { const permission = new Permission(); - expect(await permission.isValidAsync()).to.be.false; + expect(await permission.isValidAsync()).toBeFalsy(); permission.role = UserRole.GOVERNMENT_ADMIN; permission.user = user; permission.government = government; - expect(await permission.isValidAsync()).to.be.true; + expect(await permission.isValidAsync()).toBeTruthy(); }); it('save invalid throws error', async () => { @@ -125,7 +125,7 @@ describe('Permission', () => { try { await permissionRepository.save(permission); } catch (e) { - expect(e.message).to.equal('permission has one or more validation problems'); + expect(e.message).toEqual('permission has one or more validation problems'); } }); @@ -135,9 +135,9 @@ describe('Permission', () => { permission.user = user; permission.government = government; permission.campaign = campaign; - expect(await permissionRepository.count()).equal(0); + expect(await permissionRepository.count()).toEqual(0); await permissionRepository.save(permission); - expect(await permissionRepository.count()).equal(1); + expect(await permissionRepository.count()).toEqual(1); }); it('saves valid Campaign Admin', async () => { @@ -146,9 +146,9 @@ describe('Permission', () => { permission.user = user; permission.government = government; permission.campaign = campaign; - expect(await permissionRepository.count()).equal(0); + expect(await permissionRepository.count()).toEqual(0); await permissionRepository.save(permission); - expect(await permissionRepository.count()).equal(1); + expect(await permissionRepository.count()).toEqual(1); }); it('saves valid Government Admin', async () => { @@ -156,14 +156,14 @@ describe('Permission', () => { permission.role = UserRole.GOVERNMENT_ADMIN; permission.user = user; permission.government = government; - expect(await permissionRepository.count()).equal(0); + expect(await permissionRepository.count()).toEqual(0); await permissionRepository.save(permission); - expect(await permissionRepository.count()).equal(1); + expect(await permissionRepository.count()).toEqual(1); }); }); - context('getPermissions', () => { - context('getPermissionsByCampaignIdAsync', () => { + describe('getPermissions', () => { + describe('getPermissionsByCampaignIdAsync', () => { it('returns [] no campaignId found', async () => { const permission = new Permission(); permission.role = UserRole.CAMPAIGN_STAFF; @@ -171,9 +171,9 @@ describe('Permission', () => { permission.government = government; permission.campaign = campaign; await permissionRepository.save(permission); - expect(await permissionRepository.count()).equal(1); + expect(await permissionRepository.count()).toEqual(1); const userPermissions = await getPermissionsByCampaignIdAsync(10); - expect(userPermissions.length).to.equal(0); + expect(userPermissions.length).toEqual(0); }); it('returns [UserPermission] for campaign', async () => { @@ -189,17 +189,23 @@ describe('Permission', () => { permission2.government = government; permission2.campaign = campaign2; await permissionRepository.save(permission); - expect(await permissionRepository.count()).equal(1); + expect(await permissionRepository.count()).toEqual(1); const userPermissions = await getPermissionsByCampaignIdAsync(campaign.id); - expect(userPermissions.length).to.equal(1); - expect(Object.keys(userPermissions[0])).to.deep.equal(['id', 'role', 'user', 'campaign', 'government']); - expect(Object.keys(userPermissions[0].user)).to.deep.equal(['id', 'firstName', 'lastName', 'email', 'userStatus']); - expect(Object.keys(userPermissions[0].campaign)).to.deep.equal(['id', 'name']); - expect(Object.keys(userPermissions[0].government)).to.deep.equal(['id', 'name']); + expect(userPermissions.length).toEqual(1); + expect(Object.keys(userPermissions[0])).toEqual(['id', 'role', 'user', 'campaign', 'government']); + expect(Object.keys(userPermissions[0].user)).toEqual([ + 'id', + 'firstName', + 'lastName', + 'email', + 'userStatus', + ]); + expect(Object.keys(userPermissions[0].campaign)).toEqual(['id', 'name']); + expect(Object.keys(userPermissions[0].government)).toEqual(['id', 'name']); }); }); - context('getPermissionsByGovernmentIdAsync', () => { + describe('getPermissionsByGovernmentIdAsync', () => { it('returns [] no governmentId found', async () => { const permission = new Permission(); permission.role = UserRole.CAMPAIGN_STAFF; @@ -212,9 +218,9 @@ describe('Permission', () => { permission2.user = user; permission2.government = government; await permissionRepository.save(permission2); - expect(await permissionRepository.count()).equal(2); + expect(await permissionRepository.count()).toEqual(2); const userPermissions = await getPermissionsByGovernmentIdAsync(10); - expect(userPermissions.length).to.equal(0); + expect(userPermissions.length).toEqual(0); }); it('returns 2 [UserPermission] for government', async () => { @@ -229,22 +235,32 @@ describe('Permission', () => { permission2.user = user2; permission2.government = government; await permissionRepository.save(permission2); - expect(await permissionRepository.count()).equal(2); + expect(await permissionRepository.count()).toEqual(2); const userPermissions = await getPermissionsByGovernmentIdAsync(government.id); - expect(userPermissions.length).to.equal(2); - expect(Object.keys(userPermissions[0])).to.deep.equal(['id', 'role', 'user', 'government', 'campaign']); - expect(Object.keys(userPermissions[0].campaign)).to.deep.equal(['id', 'name']); - expect(Object.keys(userPermissions[0].user)).to.deep.equal(['id', 'firstName', 'lastName', 'email', 'userStatus']); - expect(Object.keys(userPermissions[0].government)).to.deep.equal(['id', 'name']); - - expect(Object.keys(userPermissions[1])).to.deep.equal(['id', 'role', 'user', 'government']); - expect(Object.keys(userPermissions[1].user)).to.deep.equal(['id', 'firstName', 'lastName', 'email', 'userStatus']); - expect(Object.keys(userPermissions[1].government)).to.deep.equal(['id', 'name']); + expect(userPermissions.length).toEqual(2); + expect(Object.keys(userPermissions[0])).toEqual(['id', 'role', 'user', 'government', 'campaign']); + expect(Object.keys(userPermissions[0].campaign)).toEqual(['id', 'name']); + expect(Object.keys(userPermissions[0].user)).toEqual([ + 'id', + 'firstName', + 'lastName', + 'email', + 'userStatus', + ]); + expect(Object.keys(userPermissions[0].government)).toEqual(['id', 'name']); + + expect(Object.keys(userPermissions[1])).toEqual(['id', 'role', 'user', 'government']); + expect(Object.keys(userPermissions[1].user)).toEqual([ + 'id', + 'firstName', + 'lastName', + 'email', + 'userStatus', + ]); + expect(Object.keys(userPermissions[1].government)).toEqual(['id', 'name']); }); }); }); - it('retrieveCampaignAdminsAsync', async () => { - - }) + it('retrieveCampaignAdminsAsync', async () => {}); }); diff --git a/api/test/entities/User.spec.ts b/api/test/entities/User.spec.ts index bf45e7b8a..92b2310dc 100644 --- a/api/test/entities/User.spec.ts +++ b/api/test/entities/User.spec.ts @@ -1,13 +1,13 @@ +import db from '../../models/db'; import { md5, User, UserStatus } from '../../models/entity/User'; -import { expect } from 'chai'; -import { getConnection } from 'typeorm'; import { truncateAll } from '../factories'; let userRepository: any; describe('User', () => { - before(() => { - userRepository = getConnection('default').getRepository('User'); + beforeEach(async () => { + const dataSource = await db(); + userRepository = dataSource.getRepository('User'); }); afterEach(async () => { @@ -16,26 +16,26 @@ describe('User', () => { it('md5', async () => { const hashObject = md5('password'); - expect(hashObject).to.equal('5f4dcc3b5aa765d61d8327deb882cf99'); + expect(hashObject).toEqual('5f4dcc3b5aa765d61d8327deb882cf99'); }); it('setPassword', async () => { const user = new User(); - expect(user.passwordHash).to.be.undefined; - expect(user.salt).to.be.undefined; + expect(user.passwordHash).toBeUndefined(); + expect(user.salt).toBeUndefined(); user.setPassword('password'); - expect(user.passwordHash).to.not.be.undefined; - expect(user.salt).to.not.be.undefined; + expect(user.passwordHash).toBeDefined(); + expect(user.salt).toBeDefined(); }); - context('Validations', () => { + describe('Validations', () => { it('firstName lastName', async () => { const user = new User(); await user.validateAsync(); - expect(user.errors[0].property).equal('firstName'); - expect(user.errors[0].constraints.isDefined).equal('firstName should not be null or undefined'); - expect(user.errors[1].property).equal('lastName'); - expect(user.errors[1].constraints.isDefined).equal('lastName should not be null or undefined'); + expect(user.errors[0].property).toEqual('firstName'); + expect(user.errors[0].constraints.isDefined).toEqual('firstName should not be null or undefined'); + expect(user.errors[1].property).toEqual('lastName'); + expect(user.errors[1].constraints.isDefined).toEqual('lastName should not be null or undefined'); }); it('passswordHash', async () => { @@ -43,8 +43,8 @@ describe('User', () => { user.firstName = 'Dan'; user.lastName = 'Melton'; await user.validateAsync(); - expect(user.errors[0].property).equal('passwordHash'); - expect(user.errors[0].constraints.isDefined).equal('passwordHash should not be null or undefined'); + expect(user.errors[0].property).toEqual('passwordHash'); + expect(user.errors[0].constraints.isDefined).toEqual('passwordHash should not be null or undefined'); }); it('email null', async () => { @@ -53,18 +53,18 @@ describe('User', () => { user.lastName = 'Melton'; user.setPassword('password'); await user.validateAsync(); - expect(user.errors[0].property).equal('email'); - expect(user.errors[0].constraints.isDefined).equal('email should not be null or undefined'); + expect(user.errors[0].property).toEqual('email'); + expect(user.errors[0].constraints.isDefined).toEqual('email should not be null or undefined'); }); it('isValid', async () => { const user = new User(); - expect(await user.isValidAsync()).to.be.false; + expect(await user.isValidAsync()).toBeFalsy(); user.firstName = 'Dan'; user.lastName = 'Melton'; user.setPassword('password'); user.email = 'dan@civicsoftwarefoundation.org'; - expect(await user.isValidAsync()).to.be.true; + expect(await user.isValidAsync()).toBeTruthy(); }); it('validate throws error', async () => { @@ -72,7 +72,7 @@ describe('User', () => { try { await userRepository.save(user); } catch (e) { - expect(e.message).to.equal('user has one or more validation problems'); + expect(e.message).toEqual('user has one or more validation problems'); } }); @@ -82,14 +82,13 @@ describe('User', () => { user.lastName = 'Melton'; user.setPassword('password'); user.email = 'dan@civicsoftwarefoundation.org'; - expect(await userRepository.count()).equal(0); + expect(await userRepository.count()).toEqual(0); await userRepository.save(user); - expect(await userRepository.count()).equal(1); + expect(await userRepository.count()).toEqual(1); }); - }); - context('JSON', () => { + describe('JSON', () => { it('toJson', async () => { const user = new User(); user.firstName = 'Dan'; @@ -98,10 +97,10 @@ describe('User', () => { user.email = 'dan@civicsoftwarefoundation.org'; await userRepository.save(user); const userJson = user.toJSON(); - expect(userJson.id).to.not.be.undefined; - expect(userJson.firstName).to.equal('Dan'); - expect(userJson.lastName).to.equal('Melton'); - expect(userJson.email).to.equal('dan@civicsoftwarefoundation.org'); + expect(userJson.id).toBeDefined(); + expect(userJson.firstName).toEqual('Dan'); + expect(userJson.lastName).toEqual('Melton'); + expect(userJson.email).toEqual('dan@civicsoftwarefoundation.org'); }); }); @@ -111,10 +110,10 @@ describe('User', () => { user.lastName = 'Melton'; user.email = 'dan@civicsoftwarefoundation.org'; const code = user.generateInvitationCode(); - expect(user.invitationCode).to.equal(code); - expect(user.userStatus).to.equal(UserStatus.INVITED); + expect(user.invitationCode).toEqual(code); + expect(user.userStatus).toEqual(UserStatus.INVITED); await userRepository.save(user); - expect(user.validatePassword(code)).to.be.true; + expect(user.validatePassword(code)).toBeTruthy(); }); it('redeemInvitation succeeds', async () => { @@ -123,14 +122,14 @@ describe('User', () => { user.lastName = 'Melton'; user.email = 'dan@civicsoftwarefoundation.org'; const code = user.generateInvitationCode(); - expect(user.userStatus).to.equal(UserStatus.INVITED); - expect(user.invitationCode).to.equal(code); + expect(user.userStatus).toEqual(UserStatus.INVITED); + expect(user.invitationCode).toEqual(code); await userRepository.save(user); user.redeemInvitation(code, 'password'); await userRepository.save(user); - expect(user.invitationCode).to.be.null; - expect(user.userStatus).to.equal(UserStatus.ACTIVE); - expect(user.validatePassword('password')).to.be.true; + expect(user.invitationCode).toBeNull(); + expect(user.userStatus).toEqual(UserStatus.ACTIVE); + expect(user.validatePassword('password')).toBeTruthy(); }); it('redeemInvitation fails', async () => { @@ -139,13 +138,13 @@ describe('User', () => { user.lastName = 'Melton'; user.email = 'dan@civicsoftwarefoundation.org'; const code = user.generateInvitationCode(); - expect(user.userStatus).to.equal(UserStatus.INVITED); + expect(user.userStatus).toEqual(UserStatus.INVITED); await userRepository.save(user); user.redeemInvitation('111', 'password'); await userRepository.save(user); - expect(user.invitationCode).to.equal(code); - expect(user.userStatus).to.equal(UserStatus.INVITED); - expect(user.validatePassword('password')).to.be.false; + expect(user.invitationCode).toEqual(code); + expect(user.userStatus).toEqual(UserStatus.INVITED); + expect(user.validatePassword('password')).toBeFalsy(); }); it('generatePasswordResetCode fails invalid userstatus', async () => { @@ -154,13 +153,13 @@ describe('User', () => { user.lastName = 'Melton'; user.email = 'dan@civicsoftwarefoundation.org'; const code = user.generateInvitationCode(); - expect(user.userStatus).to.equal(UserStatus.INVITED); - expect(user.invitationCode).to.equal(code); + expect(user.userStatus).toEqual(UserStatus.INVITED); + expect(user.invitationCode).toEqual(code); await userRepository.save(user); try { user.generatePasswordResetCode(); } catch (e) { - expect(e.message).to.equal('Cannot reset an inactive or invited user'); + expect(e.message).toEqual('Cannot reset an inactive or invited user'); } }); @@ -172,25 +171,24 @@ describe('User', () => { user.setPassword('password'); user.userStatus = UserStatus.ACTIVE; await userRepository.save(user); - expect(user.invitationCode).to.be.null; + expect(user.invitationCode).toBeNull(); user.generatePasswordResetCode(); - expect(user.invitationCode).to.not.be.null; + expect(user.invitationCode).toBeDefined(); }); - it('resetPassword fails invalid userStatus', async () => { const user = new User(); user.firstName = 'Dan'; user.lastName = 'Melton'; user.email = 'dan@civicsoftwarefoundation.org'; const code = user.generateInvitationCode(); - expect(user.userStatus).to.equal(UserStatus.INVITED); - expect(user.invitationCode).to.equal(code); + expect(user.userStatus).toEqual(UserStatus.INVITED); + expect(user.invitationCode).toEqual(code); await userRepository.save(user); try { user.resetPassword(code, 'password'); } catch (e) { - expect(e.message).to.equal('Cannot reset an inactive or invited user'); + expect(e.message).toEqual('Cannot reset an inactive or invited user'); } }); @@ -205,7 +203,7 @@ describe('User', () => { try { user.resetPassword('love', 'password'); } catch (e) { - expect(e.message).to.equal('Cannot reset an inactive or invited user'); + expect(e.message).toEqual('Cannot reset an inactive or invited user'); } }); @@ -217,12 +215,11 @@ describe('User', () => { user.setPassword('password'); user.userStatus = UserStatus.ACTIVE; await userRepository.save(user); - expect(user.invitationCode).to.be.null; + expect(user.invitationCode).toBeNull(); user.generatePasswordResetCode(); - expect(user.invitationCode).to.not.be.null; + expect(user.invitationCode).toBeDefined(); user.resetPassword(user.invitationCode, 'passwordchanged'); user = await userRepository.save(user); - expect(user.validatePassword('passwordchanged')).to.be.true; + expect(user.validatePassword('passwordchanged')).toBeTruthy(); }); }); - diff --git a/api/test/factories.ts b/api/test/factories.ts index 436956f36..d0f24a723 100644 --- a/api/test/factories.ts +++ b/api/test/factories.ts @@ -1,6 +1,5 @@ -import * as faker from 'faker'; +import { faker } from '@faker-js/faker'; import { User, UserStatus } from '../models/entity/User'; -import { getConnection } from 'typeorm'; import { Government } from '../models/entity/Government'; import { Campaign } from '../models/entity/Campaign'; import { @@ -10,7 +9,7 @@ import { ContributionType, ContributorType, IContributionSummary, - IContributionSummaryResults + IContributionSummaryResults, } from '../models/entity/Contribution'; import { Expenditure, @@ -21,76 +20,82 @@ import { PaymentMethod, PurposeType, IExpenditureSummaryResults, - IExpenditureSummary + IExpenditureSummary, } from '../models/entity/Expenditure'; import { ExternalContribution, ExternalContributionSubType } from '../models/entity/ExternalContribution'; +import db from '../models/db'; export async function newActiveUserAsync(): Promise { - const userRepository = getConnection('default').getRepository('User'); + const dataSource = await db(); + const userRepository = dataSource.getRepository('User'); let user = new User(); - user.firstName = faker.name.firstName(); - user.lastName = faker.name.lastName(); + user.firstName = faker.person.firstName(); + user.lastName = faker.person.lastName(); user.email = faker.internet.email(); user.setPassword('password'); user.userStatus = UserStatus.ACTIVE; - user = await userRepository.save(user) as User; + user = (await userRepository.save(user)) as User; return user; } export async function newInactiveUserAsync(): Promise { - const userRepository = getConnection('default').getRepository('User'); + const dataSource = await db(); + const userRepository = dataSource.getRepository('User'); let user = new User(); - user.firstName = faker.name.firstName(); - user.lastName = faker.name.lastName(); + user.firstName = faker.person.firstName(); + user.lastName = faker.person.lastName(); user.email = faker.internet.email(); user.setPassword('password'); user.generateInvitationCode(); - user = await userRepository.save(user) as User; + user = (await userRepository.save(user)) as User; return user; } export async function newGovernmentAsync(name?: string): Promise { - const repository = getConnection('default').getRepository('Government'); + const dataSource = await db(); + const repository = dataSource.getRepository('Government'); let government = new Government(); - government.name = name || faker.address.city(); - government = await repository.save(government) as Government; + government.name = name || faker.location.city(); + government = (await repository.save(government)) as Government; return government; } export async function newCampaignAsync(gov?: Government): Promise { - const govRepository = getConnection('default').getRepository('Government'); - const campaignRepository = getConnection('default').getRepository('Campaign'); + const dataSource = await db(); + const govRepository = dataSource.getRepository('Government'); + const campaignRepository = dataSource.getRepository('Campaign'); let government = new Government(); - government.name = faker.address.city(); - government = await govRepository.save(government) as Government; + government.name = faker.location.city(); + government = (await govRepository.save(government)) as Government; let campaign = new Campaign(); - campaign.name = `${faker.name.lastName()} for Mayor`; + campaign.name = `${faker.person.lastName()} for Mayor`; campaign.government = gov || government; campaign.officeSought = 'Mayor'; - campaign = await campaignRepository.save(campaign) as Campaign; + campaign = (await campaignRepository.save(campaign)) as Campaign; return campaign; } export async function newContributionAsync(campaign: Campaign, government: Government): Promise { + const dataSource = await db(); let contribution = new Contribution(); - contribution.address1 = faker.address.streetAddress(); - contribution.amount = faker.finance.amount(1, 500, 2); - contribution.campaign = campaign; - contribution.city = 'Portland'; - contribution.firstName = faker.name.firstName(); - contribution.middleInitial = ''; - contribution.lastName = faker.name.lastName(); - contribution.government = government; - contribution.type = ContributionType.CONTRIBUTION; - contribution.subType = ContributionSubType.CASH; - contribution.state = 'OR'; - contribution.status = ContributionStatus.DRAFT; - contribution.zip = '97214'; - contribution.paymentMethod = PaymentMethod.CHECK; - contribution.checkNumber = '123456'; - contribution.contributorType = ContributorType.INDIVIDUAL; - contribution.date = faker.date.past(1); - const contributionRepository = getConnection('default').getRepository('Contribution'); + contribution.address1 = faker.location.streetAddress(); + contribution.amount = parseInt(faker.finance.amount({ min: 1, max: 500, dec: 2 })); + contribution.campaign = campaign; + contribution.city = 'Portland'; + contribution.firstName = faker.person.firstName(); + contribution.middleInitial = ''; + contribution.lastName = faker.person.lastName(); + contribution.government = government; + contribution.type = ContributionType.CONTRIBUTION; + contribution.subType = ContributionSubType.CASH; + contribution.state = 'OR'; + contribution.status = ContributionStatus.DRAFT; + contribution.zip = '97214'; + contribution.paymentMethod = PaymentMethod.CHECK; + contribution.checkNumber = '123456'; + contribution.contributorType = ContributorType.INDIVIDUAL; + contribution.date = faker.date.past(); + const contributionRepository = dataSource.getRepository('Contribution'); contribution = await contributionRepository.save(contribution); if (process.env.NODE_ENV != 'test') { console.log('saving contribution', contribution.id); @@ -99,24 +104,25 @@ export async function newContributionAsync(campaign: Campaign, government: Gover } export async function newExternalContributionAsync(): Promise { + const dataSource = await db(); let externalContribution = new ExternalContribution(); - externalContribution.orestarOriginalId = ((global as any).externalContributionCounter + 1).toString(); - externalContribution.orestarTransactionId = ((global as any).externalContributionCounter + 1).toString(); - (global as any).externalContributionCounter += 1; - externalContribution.address1 = faker.address.streetAddress(); - externalContribution.amount = faker.finance.amount(1, 500, 2); - externalContribution.city = 'Portland'; - externalContribution.type = ContributionType.CONTRIBUTION; - externalContribution.subType = ExternalContributionSubType.CASH; - externalContribution.state = 'OR'; - externalContribution.zip = '97214'; - externalContribution.contributorType = ContributorType.INDIVIDUAL; - externalContribution.employerName = 'Random Employer'; - externalContribution.employerCity = 'Portland'; - externalContribution.employerState = 'OR'; - externalContribution.country = 'United States'; - externalContribution.date = faker.date.past(1); - const externalContributionRepository = getConnection('default').getRepository('external_contributions'); + externalContribution.orestarOriginalId = ((global as any).externalContributionCounter + 1).toString(); + externalContribution.orestarTransactionId = ((global as any).externalContributionCounter + 1).toString(); + (global as any).externalContributionCounter += 1; + externalContribution.address1 = faker.location.streetAddress(); + externalContribution.amount = parseInt(faker.finance.amount({ min: 1, max: 500, dec: 2 })); + externalContribution.city = 'Portland'; + externalContribution.type = ContributionType.CONTRIBUTION; + externalContribution.subType = ExternalContributionSubType.CASH; + externalContribution.state = 'OR'; + externalContribution.zip = '97214'; + externalContribution.contributorType = ContributorType.INDIVIDUAL; + externalContribution.employerName = 'Random Employer'; + externalContribution.employerCity = 'Portland'; + externalContribution.employerState = 'OR'; + externalContribution.country = 'United States'; + externalContribution.date = faker.date.past(); + const externalContributionRepository = dataSource.getRepository('external_contributions'); externalContribution = await externalContributionRepository.save(externalContribution); if (process.env.NODE_ENV != 'test') { console.log('saving contribution', externalContribution.orestarOriginalId); @@ -124,23 +130,27 @@ export async function newExternalContributionAsync(): Promise { +export async function newBulkContributionAsync( + campaign: Campaign, + government: Government +): Promise { const bulkContributionsArray: IContributionSummary[] = []; for (let i = 0; i < 5; i++) { bulkContributionsArray.push(await newContributionAsync(campaign, government)); } - return ({ + return { data: bulkContributionsArray, - } as any); + } as any; } export async function newExpenditureAsync(campaign: Campaign, government: Government): Promise { + const dataSource = await db(); let expenditure = new Expenditure(); - expenditure.address1 = faker.address.streetAddress(); - expenditure.amount = faker.finance.amount(1, 500, 2); + expenditure.address1 = faker.location.streetAddress(); + expenditure.amount = parseInt(faker.finance.amount({ min: 1, max: 500, dec: 2 })); expenditure.campaign = campaign; expenditure.city = 'Portland'; - expenditure.name = faker.name.findName(); + expenditure.name = faker.person.fullName(); expenditure.government = government; expenditure.type = ExpenditureType.EXPENDITURE; expenditure.subType = ExpenditureSubType.CASH_EXPENDITURE; @@ -150,8 +160,8 @@ export async function newExpenditureAsync(campaign: Campaign, government: Govern expenditure.payeeType = PayeeType.INDIVIDUAL; expenditure.paymentMethod = PaymentMethod.CASH; expenditure.purpose = PurposeType.GENERAL_OPERATING; - expenditure.date = faker.date.past(1); - const expenditureRepository = getConnection('default').getRepository('Expenditure'); + expenditure.date = faker.date.past(); + const expenditureRepository = dataSource.getRepository('Expenditure'); expenditure = await expenditureRepository.save(expenditure); if (process.env.NODE_ENV != 'test') { console.log('saving expenditure', expenditure.id); @@ -159,37 +169,47 @@ export async function newExpenditureAsync(campaign: Campaign, government: Govern return expenditure; } -export async function newBulkExpenditureAsync(campaign: Campaign, government: Government): Promise { +export async function newBulkExpenditureAsync( + campaign: Campaign, + government: Government +): Promise { const bulkExpendituresArray: IExpenditureSummary[] = []; for (let i = 0; i < 5; i++) { bulkExpendituresArray.push(await newExpenditureAsync(campaign, government)); } - return ({ + return { data: bulkExpendituresArray, - } as any); + } as any; } - export async function truncateAll() { + const dataSource = await db(); if (process.env.NODE_ENV === 'production' && process.env.APP_ENV !== 'staging') { throw new Error('Cant run truncate in production'); } - const connection = getConnection('default'); - await connection.query('TRUNCATE "government" RESTART IDENTITY CASCADE'); - await connection.query('TRUNCATE "users" RESTART IDENTITY CASCADE'); - await connection.query('TRUNCATE "campaign" RESTART IDENTITY CASCADE'); - await connection.query('TRUNCATE "permission" RESTART IDENTITY CASCADE'); - await connection.query('TRUNCATE "activity" RESTART IDENTITY CASCADE'); - await connection.query('TRUNCATE "expenditures" RESTART IDENTITY CASCADE'); - await connection.query('TRUNCATE "contributions" RESTART IDENTITY CASCADE'); - await connection.query('TRUNCATE "addresses" RESTART IDENTITY CASCADE'); - if (process.env.NODE_ENV !== 'production') { - try { - await connection.query('TRUNCATE "gis_boundaries" RESTART IDENTITY CASCADE'); - } catch (error) { - if (process.env.NODE_ENV !== 'test') { - console.log('table gis_boundaries not found'); + try { + const connection = dataSource; + await connection.query('TRUNCATE "government" RESTART IDENTITY CASCADE'); + await connection.query('TRUNCATE "users" RESTART IDENTITY CASCADE'); + await connection.query('TRUNCATE "campaign" RESTART IDENTITY CASCADE'); + await connection.query('TRUNCATE "permission" RESTART IDENTITY CASCADE'); + await connection.query('TRUNCATE "activity" RESTART IDENTITY CASCADE'); + await connection.query('TRUNCATE "expenditures" RESTART IDENTITY CASCADE'); + await connection.query('TRUNCATE "contributions" RESTART IDENTITY CASCADE'); + await connection.query('TRUNCATE "addresses" RESTART IDENTITY CASCADE'); + if (process.env.NODE_ENV !== 'production') { + try { + await connection.query('TRUNCATE "gis_boundaries" RESTART IDENTITY CASCADE'); + } catch (error) { + if (process.env.NODE_ENV !== 'test') { + console.log('table gis_boundaries not found'); + } } } + } catch (error) { + console.error('Error truncating tables:', error); + throw error; + } finally { + await dataSource.destroy(); // Ensure the connection is closed } } diff --git a/api/test/redis.spec.ts b/api/test/redis.spec.ts index 9e30e7a5c..665ff68b2 100644 --- a/api/test/redis.spec.ts +++ b/api/test/redis.spec.ts @@ -1,5 +1,4 @@ import redisClient from '../models/redis'; -import { expect } from 'chai'; describe('redisClient examples', () => { beforeEach(async () => { @@ -9,12 +8,12 @@ describe('redisClient examples', () => { await redisClient.flushall(); }); it('set and get', async () => { - expect(await redisClient.get('love')).to.be.null; + expect(await redisClient.get('love')).toBeNull(); await redisClient.set('love', 1); - expect(await redisClient.get('love')).to.equal('1'); + expect(await redisClient.get('love')).toEqual('1'); }); it('test clears between runs', async () => { - expect(await redisClient.get('love')).to.be.null; + expect(await redisClient.get('love')).toBeNull(); }); }); diff --git a/api/test/routes/activities/index.spec.ts b/api/test/routes/activities/index.spec.ts index 48b963e89..dd8b77b5d 100644 --- a/api/test/routes/activities/index.spec.ts +++ b/api/test/routes/activities/index.spec.ts @@ -1,18 +1,15 @@ -import { expect } from 'chai'; import * as express from 'express'; import { Campaign } from '../../../models/entity/Campaign'; import { Government } from '../../../models/entity/Government'; import { User } from '../../../models/entity/User'; import { newActiveUserAsync, newCampaignAsync, newGovernmentAsync, truncateAll } from '../../factories'; -import { - createActivityRecordAsync, -} from '../../../services/activityService'; +import { createActivityRecordAsync } from '../../../services/activityService'; import { addPermissionAsync, generateJWTokenAsync } from '../../../services/permissionService'; import * as request from 'supertest'; import { Permission, UserRole } from '../../../models/entity/Permission'; import { ActivityTypeEnum } from '../../../models/entity/Activity'; -import { getConnection } from 'typeorm'; import { setupRoutes } from '../../../routes'; +import db from '../../../models/db'; let app: express.Express; let government: Government; @@ -27,8 +24,7 @@ let campaignAdminToken: string; let campaignStaffToken: string; describe('Activity', () => { - - before(async () => { + beforeAll(async () => { app = express(); setupRoutes(app); }); @@ -42,19 +38,19 @@ describe('Activity', () => { permission = await addPermissionAsync({ userId: govUser.id, governmentId: government.id, - role: UserRole.GOVERNMENT_ADMIN + role: UserRole.GOVERNMENT_ADMIN, }); await addPermissionAsync({ userId: campaignAdmin.id, governmentId: government.id, campaignId: campaign1.id, - role: UserRole.CAMPAIGN_ADMIN + role: UserRole.CAMPAIGN_ADMIN, }); await addPermissionAsync({ userId: campaignStaff.id, governmentId: government.id, campaignId: campaign1.id, - role: UserRole.CAMPAIGN_STAFF + role: UserRole.CAMPAIGN_STAFF, }); await createActivityRecordAsync({ government, @@ -73,7 +69,8 @@ describe('Activity', () => { activityType: ActivityTypeEnum.PERMISSION, activityId: govUser.id, }); - activityRepository = getConnection('default').getRepository('Activity'); + const dataSource = await db(); + activityRepository = dataSource.getRepository('Activity'); govUserToken = await generateJWTokenAsync(govUser.id); campaignStaffToken = await generateJWTokenAsync(campaignStaff.id); campaignAdminToken = await generateJWTokenAsync(campaignAdmin.id); @@ -91,8 +88,8 @@ describe('Activity', () => { }) .set('Accept', 'application/json') .set('Cookie', [`token=${govUserToken}`]); - expect(response.status).to.equal(200); - expect(response.body.length).to.equal(2); + expect(response.status).toEqual(200); + expect(response.body.data.length).toEqual(2); }); it('post /activities success governmentAdmin pagination', async () => { @@ -101,12 +98,12 @@ describe('Activity', () => { .send({ governmentId: government.id, perPage: 1, - page: 0 + page: 0, }) .set('Accept', 'application/json') .set('Cookie', [`token=${govUserToken}`]); - expect(response.status).to.equal(200); - expect(response.body.length).to.equal(1); + expect(response.status).toEqual(200); + expect(response.body.data.length).toEqual(1); }); it('post /activities success campaignAdmin', async () => { @@ -115,12 +112,12 @@ describe('Activity', () => { .send({ campaignId: campaign1.id, perPage: 1, - page: 0 + page: 0, }) .set('Accept', 'application/json') .set('Cookie', [`token=${campaignAdminToken}`]); - expect(response.status).to.equal(200); - expect(response.body.length).to.equal(1); + expect(response.status).toEqual(200); + expect(response.body.data.length).toEqual(1); }); it('post /activities success campaignStaff', async () => { @@ -129,12 +126,12 @@ describe('Activity', () => { .send({ campaignId: campaign1.id, perPage: 1, - page: 0 + page: 0, }) .set('Accept', 'application/json') .set('Cookie', [`token=${campaignStaffToken}`]); - expect(response.status).to.equal(200); - expect(response.body.length).to.equal(1); + expect(response.status).toEqual(200); + expect(response.body.data.length).toEqual(1); }); it('post /activities fails bad token', async () => { @@ -144,12 +141,11 @@ describe('Activity', () => { governmentId: government.id, campaignId: campaign1.id, perPage: 1, - page: 0 + page: 0, }) .set('Accept', 'application/json') .set('Cookie', [`token=${1111}`]); - expect(response.status).to.equal(401); - expect(response.body.message).to.equal('Token expired or incorrect'); + expect(response.status).toEqual(401); + expect(response.body.message).toEqual('Token expired or incorrect'); }); - }); diff --git a/api/test/routes/campaigns/index.spec.ts b/api/test/routes/campaigns/index.spec.ts index 9bdcc0f2b..ad66baacb 100644 --- a/api/test/routes/campaigns/index.spec.ts +++ b/api/test/routes/campaigns/index.spec.ts @@ -1,5 +1,5 @@ import * as express from 'express'; -import { expect } from 'chai'; + import * as request from 'supertest'; import { setupRoutes } from '../../../routes'; import { User } from '../../../models/entity/User'; @@ -20,7 +20,7 @@ let campaignAdminToken: string; let campaignStaffToken: string; describe('Routes /campaigns', () => { - before(async () => { + beforeAll(async () => { app = express(); setupRoutes(app); }); @@ -36,19 +36,19 @@ describe('Routes /campaigns', () => { await addPermissionAsync({ userId: campaignStaff.id, campaignId: campaign.id, - role: UserRole.CAMPAIGN_STAFF + role: UserRole.CAMPAIGN_STAFF, }); await addPermissionAsync({ userId: campaignAdmin.id, campaignId: campaign.id, - role: UserRole.CAMPAIGN_ADMIN + role: UserRole.CAMPAIGN_ADMIN, }); await addPermissionAsync({ userId: govAdmin.id, governmentId: government.id, - role: UserRole.GOVERNMENT_ADMIN + role: UserRole.GOVERNMENT_ADMIN, }); govAdminToken = await generateJWTokenAsync(govAdmin.id); @@ -60,45 +60,46 @@ describe('Routes /campaigns', () => { await truncateAll(); }); - context('/campaigns', () => { + describe('/campaigns', () => { it('gets campaigns if the user is a government admin', async () => { const response = await request(app) .post('/campaigns') .send({ - governmentId: government.id + governmentId: government.id, }) .set('Accept', 'application/json') .set('Cookie', [`token=${govAdminToken}`]); - expect(response.status).to.equal(200); - expect(response.body) - .to.be.an.instanceof(Array) - .that.has.length(1) - .and.to.have.property(0) - .that.includes.all.keys(['id', 'name']); + expect(response.status).toEqual(200); + expect(response.body).toBeInstanceOf(Array); + expect(response.body).toHaveLength(1); + expect(response.body[0]).toHaveProperty('id'); + expect(response.body[0]).toHaveProperty('name'); }); it('returns an error if the user is not a government admin', async () => { const response = await request(app) .post('/campaigns') .send({ - governmentId: government.id + governmentId: government.id, }) .set('Accept', 'application/json') .set('Cookie', [`token=${campaignAdminToken}`]); - expect(response.status).to.equal(422); - expect(response.body.message).to.equal('User is not an admin for the provided government'); + expect(response.status).toEqual(422); + expect(response.body.message).toEqual('User is not an admin for the provided government'); }); it('returns an error if government id is not specified', async () => { const response = await request(app) .post('/campaigns') .send({ - governmentId: undefined + governmentId: undefined, }) .set('Accept', 'application/json') .set('Cookie', [`token=${govAdminToken}`]); - expect(response.status).to.equal(422); - expect(response.body.message).to.equal('governmentId must be a number'); + expect(response.status).toEqual(422); + expect(response.body.message).toEqual( + 'governmentId must be a number conforming to the specified constraints' + ); }); }); }); diff --git a/api/test/routes/campaigns/new.spec.ts b/api/test/routes/campaigns/new.spec.ts index 2dee7e24e..9f9d35388 100644 --- a/api/test/routes/campaigns/new.spec.ts +++ b/api/test/routes/campaigns/new.spec.ts @@ -1,6 +1,5 @@ import * as express from 'express'; -import { expect } from 'chai'; -import * as faker from 'faker'; +import { faker } from '@faker-js/faker'; import * as request from 'supertest'; import { setupRoutes } from '../../../routes'; import { User } from '../../../models/entity/User'; @@ -21,7 +20,7 @@ let campaignAdminToken: string; let campaignStaffToken: string; describe('Routes /campaigns', () => { - before(async () => { + beforeAll(async () => { app = express(); setupRoutes(app); }); @@ -37,19 +36,19 @@ describe('Routes /campaigns', () => { await addPermissionAsync({ userId: campaignStaff.id, campaignId: campaign.id, - role: UserRole.CAMPAIGN_STAFF + role: UserRole.CAMPAIGN_STAFF, }); await addPermissionAsync({ userId: campaignAdmin.id, campaignId: campaign.id, - role: UserRole.CAMPAIGN_ADMIN + role: UserRole.CAMPAIGN_ADMIN, }); await addPermissionAsync({ userId: govAdmin.id, governmentId: government.id, - role: UserRole.GOVERNMENT_ADMIN + role: UserRole.GOVERNMENT_ADMIN, }); govAdminToken = await generateJWTokenAsync(govAdmin.id); @@ -61,89 +60,104 @@ describe('Routes /campaigns', () => { await truncateAll(); }); - context('/campaigns/new', () => { + describe('/campaigns/new', () => { it('fails, user does not have permission to create campaign', async () => { const response = await request(app) .post('/campaigns/new') .send({ - name: `${faker.name.lastName()} for Mayor`, - governmentId: government.id + name: `${faker.person.lastName()} for Mayor`, + governmentId: government.id, }) .set('Accept', 'application/json') .set('Cookie', [`token=${campaignStaffToken}`]); - expect(response.status).to.equal(422); - expect(response.body.message).to.equal('User is not an admin for the provided government'); + expect(response.status).toEqual(422); + expect(response.body.message).toEqual('User is not an admin for the provided government'); }); it('fails, campaign name is missing', async () => { const response = await request(app) .post('/campaigns/new') .send({ - governmentId: government.id + governmentId: government.id, }) .set('Accept', 'application/json') .set('Cookie', [`token=${govAdminToken}`]); - expect(response.status).to.equal(422); - expect(response.body.message).to.equal('name must be a string'); + expect(response.status).toEqual(422); + expect(response.body.message).toEqual('name must be a string'); }); it('fails, government id is missing', async () => { const response = await request(app) .post('/campaigns/new') .send({ - name: `${faker.name.lastName()} for Mayor` + name: `${faker.person.lastName()} for Mayor`, }) .set('Accept', 'application/json') .set('Cookie', [`token=${govAdminToken}`]); - expect(response.status).to.equal(422); - expect(response.body.message).to.equal('governmentId must be a number'); + expect(response.status).toEqual(422); + expect(response.body.message).toEqual( + 'governmentId must be a number conforming to the specified constraints' + ); }); it('fails, no token set', async () => { const response = await request(app) .post('/campaigns/new') .send({ - name: `${faker.name.lastName()} for Mayor`, - governmentId: government.id + name: `${faker.person.lastName()} for Mayor`, + governmentId: government.id, }) .set('Accept', 'application/json') .set('Cookie', [`token=`]); - expect(response.status).to.equal(422); - expect(response.body.message).to.equal('No token set'); + expect(response.status).toEqual(422); + expect(response.body.message).toEqual('No token set'); }); it('succeeds, govAdmin creates new campaign', async () => { const response = await request(app) .post('/campaigns/new') .send({ - name: `${faker.name.lastName()} for Mayor`, - governmentId: government.id + name: `${faker.person.lastName()} for Mayor`, + governmentId: government.id, + officeSought: 'Mayor', }) .set('Accept', 'application/json') .set('Cookie', [`token=${govAdminToken}`]); - expect(response.status).to.equal(201); - expect(response.body) - .to.be.an.instanceof(Object) - .that.includes.all.keys(['id', 'name', 'governmentId']); + expect(response.status).toEqual(201); + expect(response.body).toBeInstanceOf(Object); + expect(response.body).toEqual( + expect.objectContaining({ + id: expect.anything(), + name: expect.anything(), + governmentId: expect.anything(), + officeSought: expect.anything(), + }) + ); }); it('succeeds, govAdmin creates new campaign with new user', async () => { const response = await request(app) .post('/campaigns/new') .send({ - name: `${faker.name.lastName()} for Mayor`, + name: `${faker.person.lastName()} for Mayor`, governmentId: government.id, - firstName: faker.name.firstName(), + firstName: faker.person.firstName(), officeSought: 'Mayor', - lastName: faker.name.lastName(), - email: faker.internet.email() + lastName: faker.person.lastName(), + email: faker.internet.email(), }) .set('Accept', 'application/json') .set('Cookie', [`token=${govAdminToken}`]); - expect(response.status).to.equal(201); - expect(response.body) - .to.be.an.instanceof(Object) - .that.includes.all.keys(['id', 'name', 'governmentId', 'officeSought']); + expect(response.status).toEqual(201); + expect(response.body).toBeInstanceOf(Object); + expect(response.body).toEqual( + expect.objectContaining({ + id: expect.anything(), + name: expect.anything(), + governmentId: expect.anything(), + officeSought: expect.anything(), + }) + ); }); }); }); diff --git a/api/test/routes/campaigns/update.spec.ts b/api/test/routes/campaigns/update.spec.ts index da48b5bd8..b2441514e 100644 --- a/api/test/routes/campaigns/update.spec.ts +++ b/api/test/routes/campaigns/update.spec.ts @@ -1,6 +1,5 @@ import * as express from 'express'; -import { expect } from 'chai'; -import * as faker from 'faker'; +import { faker } from '@faker-js/faker'; import * as request from 'supertest'; import { setupRoutes } from '../../../routes'; import { User } from '../../../models/entity/User'; @@ -21,7 +20,7 @@ let campaignAdminToken: string; let campaignStaffToken: string; describe('Routes /campaigns', () => { - before(async () => { + beforeAll(async () => { app = express(); setupRoutes(app); }); @@ -37,19 +36,19 @@ describe('Routes /campaigns', () => { await addPermissionAsync({ userId: campaignStaff.id, campaignId: campaign.id, - role: UserRole.CAMPAIGN_STAFF + role: UserRole.CAMPAIGN_STAFF, }); await addPermissionAsync({ userId: campaignAdmin.id, campaignId: campaign.id, - role: UserRole.CAMPAIGN_ADMIN + role: UserRole.CAMPAIGN_ADMIN, }); await addPermissionAsync({ userId: govAdmin.id, governmentId: government.id, - role: UserRole.GOVERNMENT_ADMIN + role: UserRole.GOVERNMENT_ADMIN, }); govAdminToken = await generateJWTokenAsync(govAdmin.id); @@ -61,74 +60,83 @@ describe('Routes /campaigns', () => { await truncateAll(); }); - context('/campaigns/update', () => { + describe('/campaigns/update', () => { it('fails, user does not have permission to create campaign', async () => { const response = await request(app) .post('/campaigns/update') .send({ - newName: `${faker.name.lastName()} for Mayor`, + newName: `${faker.person.lastName()} for Mayor`, governmentId: government.id, - campaignId: campaign.id + campaignId: campaign.id, }) .set('Accept', 'application/json') .set('Cookie', [`token=${campaignStaffToken}`]); - expect(response.status).to.equal(422); - expect(response.body.message).to.equal('User is not an admin for the provided government'); + expect(response.status).toEqual(422); + expect(response.body.message).toEqual('User is not an admin for the provided government'); }); it('fails, campaigns newName is missing and so is campaignId', async () => { const response = await request(app) .post('/campaigns/update') .send({ - governmentId: government.id + governmentId: government.id, }) .set('Accept', 'application/json') .set('Cookie', [`token=${govAdminToken}`]); - expect(response.status).to.equal(422); - expect(response.body.message).to.equal('newName must be a string, campaignId must be a number'); + expect(response.status).toEqual(422); + expect(response.body.message).toEqual( + 'newName must be a string, campaignId must be a number conforming to the specified constraints' + ); }); it('fails, government id is missing', async () => { const response = await request(app) .post('/campaigns/update') .send({ - newName: `${faker.name.lastName()} for Mayor`, - campaignId: campaign.id + newName: `${faker.person.lastName()} for Mayor`, + campaignId: campaign.id, }) .set('Accept', 'application/json') .set('Cookie', [`token=${govAdminToken}`]); - expect(response.status).to.equal(422); - expect(response.body.message).to.equal('governmentId must be a number'); + expect(response.status).toEqual(422); + expect(response.body.message).toEqual( + 'governmentId must be a number conforming to the specified constraints' + ); }); it('fails, no token set', async () => { const response = await request(app) .post('/campaigns/update') .send({ - newName: `${faker.name.lastName()} for Mayor`, + newName: `${faker.person.lastName()} for Mayor`, governmentId: government.id, - campaignId: campaign.id + campaignId: campaign.id, }) .set('Accept', 'application/json') .set('Cookie', [`token=`]); - expect(response.status).to.equal(422); - expect(response.body.message).to.equal('No token set'); + expect(response.status).toEqual(422); + expect(response.body.message).toEqual('No token set'); }); it('succeeds, govAdmin updates campaign name', async () => { const response = await request(app) .post('/campaigns/update') .send({ - newName: `${faker.name.lastName()} for Mayor`, + newName: `${faker.person.lastName()} for Mayor`, governmentId: government.id, - campaignId: campaign.id + campaignId: campaign.id, }) .set('Accept', 'application/json') .set('Cookie', [`token=${govAdminToken}`]); - expect(response.status).to.equal(201); - expect(response.body) - .to.be.an.instanceof(Object) - .that.includes.all.keys(['id', 'name', 'governmentId', 'officeSought']); + expect(response.status).toEqual(201); + expect(response.body).toEqual( + expect.objectContaining({ + id: expect.anything(), + name: expect.anything(), + governmentId: expect.anything(), + officeSought: expect.anything(), + }) + ); }); }); }); diff --git a/api/test/routes/contributions/comments.spec.ts b/api/test/routes/contributions/comments.spec.ts index 1e8ebb481..555f784d9 100644 --- a/api/test/routes/contributions/comments.spec.ts +++ b/api/test/routes/contributions/comments.spec.ts @@ -1,6 +1,4 @@ import * as express from 'express'; -import { expect } from 'chai'; -import * as faker from 'faker'; import * as request from 'supertest'; import { setupRoutes } from '../../../routes'; import { User } from '../../../models/entity/User'; @@ -9,7 +7,7 @@ import { newCampaignAsync, newContributionAsync, newGovernmentAsync, - truncateAll + truncateAll, } from '../../factories'; import { Government } from '../../../models/entity/Government'; import { Campaign } from '../../../models/entity/Campaign'; @@ -31,7 +29,7 @@ let campaignStaff2Token: string; let contribution1: Contribution; describe('Routes put /contributions/:id', () => { - before(async () => { + beforeAll(async () => { app = express(); setupRoutes(app); }); @@ -48,19 +46,19 @@ describe('Routes put /contributions/:id', () => { await addPermissionAsync({ userId: campaignStaff.id, campaignId: campaign.id, - role: UserRole.CAMPAIGN_STAFF + role: UserRole.CAMPAIGN_STAFF, }); await addPermissionAsync({ userId: campaignAdmin.id, campaignId: campaign.id, - role: UserRole.CAMPAIGN_ADMIN + role: UserRole.CAMPAIGN_ADMIN, }); await addPermissionAsync({ userId: govAdmin.id, governmentId: government.id, - role: UserRole.GOVERNMENT_ADMIN + role: UserRole.GOVERNMENT_ADMIN, }); govAdminToken = await generateJWTokenAsync(govAdmin.id); @@ -75,42 +73,41 @@ describe('Routes put /contributions/:id', () => { await truncateAll(); }); - context('post /contributions/:id/comments', () => { + describe('post /contributions/:id/comments', () => { it('success testme', async () => { const response = await request(app) .post(`/contributions/${contribution1.id}/comments`) .send({ - comment: 'Hi!' + comment: 'Hi!', }) .set('Accept', 'application/json') .set('Cookie', [`token=${campaignStaffToken}`]); - expect(response.status).to.equal(204); - expect(response.body.message).to.be.undefined; + expect(response.status).toEqual(204); + expect(response.body.message).toBeUndefined(); }); it('error id not found', async () => { const response = await request(app) .post(`/contributions/11111/comments`) .send({ - comment: 'Hi!' + comment: 'Hi!', }) .set('Accept', 'application/json') .set('Cookie', [`token=${campaignStaffToken}`]); - expect(response.status).to.equal(422); - expect(response.body.message).to.equal('Could not find any entity of type "Contribution" matching: 11111'); + expect(response.status).toEqual(422); + expect(response.body.message).toEqual('Could not find any entity of type "Contribution" matching: 11111'); }); it('error user does not have permissions', async () => { const response = await request(app) .post(`/contributions/${contribution1.id}/comments`) .send({ - comment: 'Hi!' + comment: 'Hi!', }) .set('Accept', 'application/json') .set('Cookie', [`token=${campaignStaff2Token}`]); - expect(response.status).to.equal(422); - expect(response.body.message).to.equal('User does not have permissions') + expect(response.status).toEqual(422); + expect(response.body.message).toEqual('User does not have permissions'); }); - }); }); diff --git a/api/test/routes/contributions/delete.spec.ts b/api/test/routes/contributions/delete.spec.ts index fa0ae74c8..bba907215 100644 --- a/api/test/routes/contributions/delete.spec.ts +++ b/api/test/routes/contributions/delete.spec.ts @@ -1,6 +1,4 @@ import * as express from 'express'; -import { expect } from 'chai'; -import * as faker from 'faker'; import * as request from 'supertest'; import { setupRoutes } from '../../../routes'; import { User } from '../../../models/entity/User'; @@ -13,7 +11,6 @@ import { Contribution, ContributionType, ContributionSubType, - ContributionStatus, ContributorType, PaymentMethod, } from '../../../models/entity/Contribution'; @@ -33,7 +30,7 @@ let campaignStaff2Token: string; let contribution1: Contribution; describe('Routes delete /contributions/:id', () => { - before(async () => { + beforeAll(async () => { app = express(); setupRoutes(app); }); @@ -50,19 +47,19 @@ describe('Routes delete /contributions/:id', () => { await addPermissionAsync({ userId: campaignStaff.id, campaignId: campaign.id, - role: UserRole.CAMPAIGN_STAFF + role: UserRole.CAMPAIGN_STAFF, }); await addPermissionAsync({ userId: campaignAdmin.id, campaignId: campaign.id, - role: UserRole.CAMPAIGN_ADMIN + role: UserRole.CAMPAIGN_ADMIN, }); await addPermissionAsync({ userId: govAdmin.id, governmentId: government.id, - role: UserRole.GOVERNMENT_ADMIN + role: UserRole.GOVERNMENT_ADMIN, }); govAdminToken = await generateJWTokenAsync(govAdmin.id); @@ -86,7 +83,7 @@ describe('Routes delete /contributions/:id', () => { paymentMethod: PaymentMethod.CASH, state: 'OR', zip: '97214', - contributorType: ContributorType.INDIVIDUAL + contributorType: ContributorType.INDIVIDUAL, }); }); @@ -94,14 +91,14 @@ describe('Routes delete /contributions/:id', () => { await truncateAll(); }); - context('delete /contributions/:id', () => { + describe('delete /contributions/:id', () => { it('success as gov admin', async () => { const response = await request(app) .delete(`/contributions/${contribution1.id}`) .set('Accept', 'application/json') .set('Cookie', [`token=${govAdminToken}`]); - expect(response.status).to.equal(200); - expect(response.body.message).to.be.undefined; + expect(response.status).toEqual(200); + expect(response.body.message).toBeUndefined(); }); it('success as campaign admin', async () => { @@ -109,8 +106,8 @@ describe('Routes delete /contributions/:id', () => { .delete(`/contributions/${contribution1.id}`) .set('Accept', 'application/json') .set('Cookie', [`token=${campaignAdminToken}`]); - expect(response.status).to.equal(200); - expect(response.body.message).to.be.undefined; + expect(response.status).toEqual(200); + expect(response.body.message).toBeUndefined(); }); it('success as campaign staff', async () => { @@ -118,8 +115,8 @@ describe('Routes delete /contributions/:id', () => { .delete(`/contributions/${contribution1.id}`) .set('Accept', 'application/json') .set('Cookie', [`token=${campaignStaffToken}`]); - expect(response.status).to.equal(200); - expect(response.body.message).to.be.undefined; + expect(response.status).toEqual(200); + expect(response.body.message).toBeUndefined(); }); it('error does not have permissions', async () => { @@ -127,7 +124,7 @@ describe('Routes delete /contributions/:id', () => { .delete(`/contributions/${contribution1.id}`) .set('Accept', 'application/json') .set('Cookie', [`token=${campaignStaff2Token}`]); - expect(response.status).to.equal(422); + expect(response.status).toEqual(422); expect(response.body.message); }); }); diff --git a/api/test/routes/contributions/get.spec.ts b/api/test/routes/contributions/get.spec.ts index 4a6c8bea6..8545a1d9e 100644 --- a/api/test/routes/contributions/get.spec.ts +++ b/api/test/routes/contributions/get.spec.ts @@ -1,6 +1,4 @@ import * as express from 'express'; -import { expect } from 'chai'; -import * as faker from 'faker'; import * as request from 'supertest'; import { setupRoutes } from '../../../routes'; import { User } from '../../../models/entity/User'; @@ -13,11 +11,11 @@ import { Contribution, ContributionType, ContributionSubType, - ContributionStatus, ContributorType, PaymentMethod, } from '../../../models/entity/Contribution'; import { addContributionAsync } from '../../../services/contributionService'; +import { parse } from 'csv-parse/.'; let app: express.Express; let campaignStaff: User; @@ -33,7 +31,7 @@ let campaignStaff2Token: string; let contribution1: Contribution; describe('Routes post /contributions', () => { - before(async () => { + beforeAll(async () => { app = express(); setupRoutes(app); }); @@ -50,19 +48,19 @@ describe('Routes post /contributions', () => { await addPermissionAsync({ userId: campaignStaff.id, campaignId: campaign.id, - role: UserRole.CAMPAIGN_STAFF + role: UserRole.CAMPAIGN_STAFF, }); await addPermissionAsync({ userId: campaignAdmin.id, campaignId: campaign.id, - role: UserRole.CAMPAIGN_ADMIN + role: UserRole.CAMPAIGN_ADMIN, }); await addPermissionAsync({ userId: govAdmin.id, governmentId: government.id, - role: UserRole.GOVERNMENT_ADMIN + role: UserRole.GOVERNMENT_ADMIN, }); govAdminToken = await generateJWTokenAsync(govAdmin.id); @@ -86,7 +84,7 @@ describe('Routes post /contributions', () => { paymentMethod: PaymentMethod.CASH, state: 'OR', zip: '97214', - contributorType: ContributorType.INDIVIDUAL + contributorType: ContributorType.INDIVIDUAL, }); }); @@ -94,15 +92,15 @@ describe('Routes post /contributions', () => { await truncateAll(); }); - context('post /contributions', () => { + describe('post /contributions', () => { it('success as gov admin', async () => { const response = await request(app) .post(`/contributions`) .send({ governmentId: government.id, currentUserId: govAdmin.id }) .set('Accept', 'application/json') .set('Cookie', [`token=${govAdminToken}`]); - expect(response.status).to.equal(200); - expect(response.body.message).to.be.undefined; + expect(response.status).toEqual(200); + expect(response.body.message).toBeUndefined(); }); it('success as campaign admin', async () => { @@ -111,8 +109,8 @@ describe('Routes post /contributions', () => { .send({ governmentId: government.id, campaignId: campaign.id, currentUserId: campaignAdmin.id }) .set('Accept', 'application/json') .set('Cookie', [`token=${campaignAdminToken}`]); - expect(response.status).to.equal(200); - expect(response.body.message).to.be.undefined; + expect(response.status).toEqual(200); + expect(response.body.message).toBeUndefined(); }); it('success as campaign staff', async () => { @@ -121,8 +119,8 @@ describe('Routes post /contributions', () => { .send({ governmentId: government.id, campaignId: campaign.id, currentUserId: campaignStaff.id }) .set('Accept', 'application/json') .set('Cookie', [`token=${campaignStaffToken}`]); - expect(response.status).to.equal(200); - expect(response.body.message).to.be.undefined; + expect(response.status).toEqual(200); + expect(response.body.message).toBeUndefined(); }); it('error permissions', async () => { @@ -131,7 +129,7 @@ describe('Routes post /contributions', () => { .send({ governmentId: government.id, currentUserId: campaignAdmin.id }) .set('Accept', 'application/json') .set('Cookie', [`token=${campaignAdminToken}`]); - expect(response.status).to.equal(422); + expect(response.status).toEqual(422); expect(response.body.message); }); @@ -141,25 +139,27 @@ describe('Routes post /contributions', () => { .send({ governmentId: government.id, currentUserId: govAdmin.id, format: 'csv' }) .set('Accept', 'application/json') .set('Cookie', [`token=${govAdminToken}`]); - expect(response.status).to.equal(200); - expect(response.text.split(',').length).to.equal(79) + expect(response.status).toEqual(200); + parse(response.text, { delimiter: ',' }, (err, _records) => { + expect(err).toBeFalsy(); + }); }); }); - context('get /contributions/:id', () => { + describe('get /contributions/:id', () => { it('success as gov admin', async () => { const response = await request(app) .get(`/contributions/${contribution1.id}`) .set('Accept', 'application/json') .set('Cookie', [`token=${govAdminToken}`]); - expect(response.status).to.equal(200); - expect(response.body) - .to.be.an.instanceof(Object) - .to.have.property('id'); - expect(response.body) - .to.be.an.instanceof(Object) - .to.have.property('status'); - expect(response.body.message).to.be.undefined; + expect(response.status).toEqual(200); + expect(response.body).toEqual( + expect.objectContaining({ + id: expect.anything(), + status: expect.anything(), + }) + ); + expect(response.body.message).toBeUndefined(); }); it('success as campaign admin', async () => { @@ -167,14 +167,14 @@ describe('Routes post /contributions', () => { .get(`/contributions/${contribution1.id}`) .set('Accept', 'application/json') .set('Cookie', [`token=${campaignAdminToken}`]); - expect(response.status).to.equal(200); - expect(response.body) - .to.be.an.instanceof(Object) - .to.have.property('id'); - expect(response.body) - .to.be.an.instanceof(Object) - .to.have.property('status'); - expect(response.body.message).to.be.undefined; + expect(response.status).toEqual(200); + expect(response.body).toEqual( + expect.objectContaining({ + id: expect.anything(), + status: expect.anything(), + }) + ); + expect(response.body.message).toBeUndefined(); }); it('success as campaign staff', async () => { @@ -182,14 +182,14 @@ describe('Routes post /contributions', () => { .get(`/contributions/${contribution1.id}`) .set('Accept', 'application/json') .set('Cookie', [`token=${campaignStaffToken}`]); - expect(response.status).to.equal(200); - expect(response.body) - .to.be.an.instanceof(Object) - .to.have.property('id'); - expect(response.body) - .to.be.an.instanceof(Object) - .to.have.property('status'); - expect(response.body.message).to.be.undefined; + expect(response.status).toEqual(200); + expect(response.body).toEqual( + expect.objectContaining({ + id: expect.anything(), + status: expect.anything(), + }) + ); + expect(response.body.message).toBeUndefined(); }); it('error permissions', async () => { @@ -197,8 +197,12 @@ describe('Routes post /contributions', () => { .get(`/contributions/${contribution1.id}`) .set('Accept', 'application/json') .set('Cookie', [`token=${campaignStaff2Token}`]); - expect(response.status).to.equal(422); - expect(response.body).to.not.have.property('id'); + expect(response.status).toEqual(422); + expect(response.body).toEqual( + expect.objectContaining({ + message: 'User does not have permissions', + }) + ); expect(response.body.message); }); }); diff --git a/api/test/routes/contributions/new.spec.ts b/api/test/routes/contributions/new.spec.ts index 7961c8ce4..886eeb6b8 100644 --- a/api/test/routes/contributions/new.spec.ts +++ b/api/test/routes/contributions/new.spec.ts @@ -1,6 +1,4 @@ import * as express from 'express'; -import { expect } from 'chai'; -import * as faker from 'faker'; import * as request from 'supertest'; import { setupRoutes } from '../../../routes'; import { User } from '../../../models/entity/User'; @@ -14,7 +12,8 @@ import { ContributionType, ContributionSubType, ContributionStatus, - ContributorType + ContributorType, + PaymentMethod, } from '../../../models/entity/Contribution'; let app: express.Express; @@ -31,7 +30,7 @@ let campaignStaff2Token: string; let contribution1: Contribution; describe('Routes post /contributions/new', () => { - before(async () => { + beforeAll(async () => { app = express(); setupRoutes(app); }); @@ -48,19 +47,19 @@ describe('Routes post /contributions/new', () => { await addPermissionAsync({ userId: campaignStaff.id, campaignId: campaign.id, - role: UserRole.CAMPAIGN_STAFF + role: UserRole.CAMPAIGN_STAFF, }); await addPermissionAsync({ userId: campaignAdmin.id, campaignId: campaign.id, - role: UserRole.CAMPAIGN_ADMIN + role: UserRole.CAMPAIGN_ADMIN, }); await addPermissionAsync({ userId: govAdmin.id, governmentId: government.id, - role: UserRole.GOVERNMENT_ADMIN + role: UserRole.GOVERNMENT_ADMIN, }); govAdminToken = await generateJWTokenAsync(govAdmin.id); @@ -73,7 +72,7 @@ describe('Routes post /contributions/new', () => { await truncateAll(); }); - context('post /contributions/new', () => { + describe('post /contributions/new', () => { it('success', async () => { const response = await request(app) .post(`/contributions/new`) @@ -93,12 +92,13 @@ describe('Routes post /contributions/new', () => { state: 'OR', status: ContributionStatus.DRAFT, zip: '97214', - contributorType: ContributorType.INDIVIDUAL + contributorType: ContributorType.INDIVIDUAL, + paymentMethod: PaymentMethod.CASH, }) .set('Accept', 'application/json') .set('Cookie', [`token=${campaignStaffToken}`]); - expect(response.status).to.equal(201); - expect(response.body.message).to.be.undefined; + expect(response.status).toEqual(201); + expect(response.body.message).toBeUndefined(); }); it('error on missing required properties', async () => { @@ -118,11 +118,11 @@ describe('Routes post /contributions/new', () => { state: 'OR', status: ContributionStatus.DRAFT, zip: '97214', - contributorType: ContributorType.INDIVIDUAL + contributorType: ContributorType.INDIVIDUAL, }) .set('Accept', 'application/json') .set('Cookie', [`token=${campaignStaffToken}`]); - expect(response.status).to.equal(422); + expect(response.status).toEqual(422); expect(response.body.message); }); }); diff --git a/api/test/routes/contributions/update.spec.ts b/api/test/routes/contributions/update.spec.ts index 918267f43..51c9e7835 100644 --- a/api/test/routes/contributions/update.spec.ts +++ b/api/test/routes/contributions/update.spec.ts @@ -1,6 +1,4 @@ import * as express from 'express'; -import { expect } from 'chai'; -import * as faker from 'faker'; import * as request from 'supertest'; import { setupRoutes } from '../../../routes'; import { User } from '../../../models/entity/User'; @@ -9,14 +7,14 @@ import { newCampaignAsync, newContributionAsync, newGovernmentAsync, - truncateAll + truncateAll, } from '../../factories'; import { Government } from '../../../models/entity/Government'; import { Campaign } from '../../../models/entity/Campaign'; import { addPermissionAsync, generateJWTokenAsync } from '../../../services/permissionService'; import { UserRole } from '../../../models/entity/Permission'; import { Contribution } from '../../../models/entity/Contribution'; -import { getConnection } from 'typeorm'; +import db from '../../../models/db'; let app: express.Express; let campaignStaff: User; @@ -33,9 +31,10 @@ let contribution1: Contribution; let repository: any; describe('Routes put /contributions/:id', () => { - before(async () => { + beforeAll(async () => { app = express(); - repository = getConnection('default').getRepository('Contribution'); + const dataSource = await db(); + repository = dataSource.getRepository('Contribution'); setupRoutes(app); }); @@ -51,19 +50,19 @@ describe('Routes put /contributions/:id', () => { await addPermissionAsync({ userId: campaignStaff.id, campaignId: campaign.id, - role: UserRole.CAMPAIGN_STAFF + role: UserRole.CAMPAIGN_STAFF, }); await addPermissionAsync({ userId: campaignAdmin.id, campaignId: campaign.id, - role: UserRole.CAMPAIGN_ADMIN + role: UserRole.CAMPAIGN_ADMIN, }); await addPermissionAsync({ userId: govAdmin.id, governmentId: government.id, - role: UserRole.GOVERNMENT_ADMIN + role: UserRole.GOVERNMENT_ADMIN, }); govAdminToken = await generateJWTokenAsync(govAdmin.id); @@ -78,18 +77,18 @@ describe('Routes put /contributions/:id', () => { await truncateAll(); }); - context('put /contributions/:id', () => { + describe('put /contributions/:id', () => { it('success', async () => { const response = await request(app) .put(`/contributions/${contribution1.id}`) .send({ id: contribution1.id, - firstName: 'Dan' + firstName: 'Dan', }) .set('Accept', 'application/json') .set('Cookie', [`token=${campaignStaffToken}`]); - expect(response.status).to.equal(204); - expect(response.body.message).to.be.undefined; + expect(response.status).toEqual(204); + expect(response.body.message).toBeUndefined(); }); it('error id not found', async () => { @@ -97,12 +96,12 @@ describe('Routes put /contributions/:id', () => { .put(`/contributions/${contribution1.id}`) .send({ id: 11111, - firstName: 'Dan' + firstName: 'Dan', }) .set('Accept', 'application/json') .set('Cookie', [`token=${campaignStaffToken}`]); - expect(response.status).to.equal(422); - expect(response.body.message).to.equal('Could not find any entity of type "Contribution" matching: 11111'); + expect(response.status).toEqual(422); + expect(response.body.message).toEqual('Could not find any entity of type "Contribution" matching: 11111'); }); it('error user does not have permissions', async () => { @@ -110,12 +109,12 @@ describe('Routes put /contributions/:id', () => { .put(`/contributions/11111`) .send({ id: contribution1.id, - firstName: 'Dan' + firstName: 'Dan', }) .set('Accept', 'application/json') .set('Cookie', [`token=${campaignStaff2Token}`]); - expect(response.status).to.equal(422); - expect(response.body.message).to.equal('User does not have permissions') + expect(response.status).toEqual(422); + expect(response.body.message).toEqual('User does not have permissions'); }); it('error field does not exist', async () => { @@ -123,12 +122,14 @@ describe('Routes put /contributions/:id', () => { .put(`/contributions/11111`) .send({ id: contribution1.id, - thisFieldDoesNotExist: 'Dan' + thisFieldDoesNotExist: 'Dan', }) .set('Accept', 'application/json') .set('Cookie', [`token=${campaignStaffToken}`]); - expect(response.status).to.equal(422); - expect(response.body.message).to.equal('No entity column "thisFieldDoesNotExist" was found.'); + expect(response.status).toEqual(422); + expect(response.body.message).toEqual( + 'Property "thisFieldDoesNotExist" was not found in "Contribution". Make sure your query is correct.' + ); }); }); }); diff --git a/api/test/routes/expenditures/comments.spec.ts b/api/test/routes/expenditures/comments.spec.ts index 8ba8c639d..b98a370e2 100644 --- a/api/test/routes/expenditures/comments.spec.ts +++ b/api/test/routes/expenditures/comments.spec.ts @@ -1,6 +1,4 @@ import * as express from 'express'; -import { expect } from 'chai'; -import * as faker from 'faker'; import * as request from 'supertest'; import { setupRoutes } from '../../../routes'; import { User } from '../../../models/entity/User'; @@ -9,14 +7,12 @@ import { newCampaignAsync, newExpenditureAsync, newGovernmentAsync, - truncateAll + truncateAll, } from '../../factories'; import { Government } from '../../../models/entity/Government'; import { Campaign } from '../../../models/entity/Campaign'; import { addPermissionAsync, generateJWTokenAsync } from '../../../services/permissionService'; import { UserRole } from '../../../models/entity/Permission'; -import { IUpdateExpenditureAttrs } from '../../../services/expenditureService'; -import { ExpenditureType, ExpenditureSubType, ExpenditureStatus, PayeeType } from '../../../models/entity/Expenditure'; import { Expenditure } from '../../../models/entity/Expenditure'; let app: express.Express; @@ -33,7 +29,7 @@ let campaignStaff2Token: string; let expenditure1: Expenditure; describe('Routes put /expenditures/:id', () => { - before(async () => { + beforeAll(async () => { app = express(); setupRoutes(app); }); @@ -50,19 +46,19 @@ describe('Routes put /expenditures/:id', () => { await addPermissionAsync({ userId: campaignStaff.id, campaignId: campaign.id, - role: UserRole.CAMPAIGN_STAFF + role: UserRole.CAMPAIGN_STAFF, }); await addPermissionAsync({ userId: campaignAdmin.id, campaignId: campaign.id, - role: UserRole.CAMPAIGN_ADMIN + role: UserRole.CAMPAIGN_ADMIN, }); await addPermissionAsync({ userId: govAdmin.id, governmentId: government.id, - role: UserRole.GOVERNMENT_ADMIN + role: UserRole.GOVERNMENT_ADMIN, }); govAdminToken = await generateJWTokenAsync(govAdmin.id); @@ -77,42 +73,41 @@ describe('Routes put /expenditures/:id', () => { await truncateAll(); }); - context('post /expenditures/:id/comments', () => { + describe('post /expenditures/:id/comments', () => { it('success', async () => { const response = await request(app) .post(`/expenditures/${expenditure1.id}/comments`) .send({ - comment: 'hio' + comment: 'hio', }) .set('Accept', 'application/json') .set('Cookie', [`token=${campaignStaffToken}`]); - expect(response.status).to.equal(204); - expect(response.body.message).to.be.undefined; + expect(response.status).toEqual(204); + expect(response.body.message).toBeUndefined(); }); it('error id not found', async () => { const response = await request(app) .post(`/expenditures/11111/comments`) .send({ - comment: 'hio' + comment: 'hio', }) .set('Accept', 'application/json') .set('Cookie', [`token=${campaignStaffToken}`]); - expect(response.status).to.equal(422); - expect(response.body.message).to.equal('Could not find any entity of type "Expenditure" matching: 11111'); + expect(response.status).toEqual(422); + expect(response.body.message).toEqual('Could not find any entity of type "Expenditure" matching: 11111'); }); it('error user does not have permissions', async () => { const response = await request(app) .post(`/expenditures/${expenditure1.id}/comments`) .send({ - comment: 'hio' + comment: 'hio', }) .set('Accept', 'application/json') .set('Cookie', [`token=${campaignStaff2Token}`]); - expect(response.status).to.equal(422); - expect(response.body.message).to.equal('User does not have permissions'); + expect(response.status).toEqual(422); + expect(response.body.message).toEqual('User does not have permissions'); }); - }); }); diff --git a/api/test/routes/expenditures/get.spec.ts b/api/test/routes/expenditures/get.spec.ts index 31626e1a8..f75f9f2f4 100644 --- a/api/test/routes/expenditures/get.spec.ts +++ b/api/test/routes/expenditures/get.spec.ts @@ -1,5 +1,5 @@ import * as express from 'express'; -import { expect } from 'chai'; + import * as request from 'supertest'; import { setupRoutes } from '../../../routes'; import { User } from '../../../models/entity/User'; @@ -24,7 +24,7 @@ let campaignStaffToken: string; let campaignStaff2Token: string; describe('Routes post /expenditures/new', () => { - before(async () => { + beforeAll(async () => { app = express(); setupRoutes(app); }); @@ -41,19 +41,19 @@ describe('Routes post /expenditures/new', () => { await addPermissionAsync({ userId: campaignStaff.id, campaignId: campaign.id, - role: UserRole.CAMPAIGN_STAFF + role: UserRole.CAMPAIGN_STAFF, }); await addPermissionAsync({ userId: campaignAdmin.id, campaignId: campaign.id, - role: UserRole.CAMPAIGN_ADMIN + role: UserRole.CAMPAIGN_ADMIN, }); await addPermissionAsync({ userId: govAdmin.id, governmentId: government.id, - role: UserRole.GOVERNMENT_ADMIN + role: UserRole.GOVERNMENT_ADMIN, }); govAdminToken = await generateJWTokenAsync(govAdmin.id); @@ -66,15 +66,15 @@ describe('Routes post /expenditures/new', () => { await truncateAll(); }); - context('post /expenditures', () => { + describe('post /expenditures', () => { it('success as gov admin', async () => { const response = await request(app) .post(`/expenditures`) .send({ governmentId: government.id, currentUserId: govAdmin.id }) .set('Accept', 'application/json') .set('Cookie', [`token=${govAdminToken}`]); - expect(response.status).to.equal(200); - expect(response.body.message).to.be.undefined; + expect(response.status).toEqual(200); + expect(response.body.message).toBeUndefined(); }); it('success as campaign admin', async () => { @@ -83,8 +83,8 @@ describe('Routes post /expenditures/new', () => { .send({ governmentId: government.id, campaignId: campaign.id, currentUserId: campaignAdmin.id }) .set('Accept', 'application/json') .set('Cookie', [`token=${campaignAdminToken}`]); - expect(response.status).to.equal(200); - expect(response.body.message).to.be.undefined; + expect(response.status).toEqual(200); + expect(response.body.message).toBeUndefined(); }); it('success as campaign staff', async () => { @@ -93,8 +93,8 @@ describe('Routes post /expenditures/new', () => { .send({ governmentId: government.id, campaignId: campaign.id, currentUserId: campaignStaff.id }) .set('Accept', 'application/json') .set('Cookie', [`token=${campaignStaffToken}`]); - expect(response.status).to.equal(200); - expect(response.body.message).to.be.undefined; + expect(response.status).toEqual(200); + expect(response.body.message).toBeUndefined(); }); it('error permissions', async () => { @@ -103,7 +103,7 @@ describe('Routes post /expenditures/new', () => { .send({ governmentId: government.id, currentUserId: campaignAdmin.id }) .set('Accept', 'application/json') .set('Cookie', [`token=${campaignAdminToken}`]); - expect(response.status).to.equal(422); + expect(response.status).toEqual(422); expect(response.body.message); }); }); diff --git a/api/test/routes/expenditures/new.spec.ts b/api/test/routes/expenditures/new.spec.ts index 903516043..7463b990b 100644 --- a/api/test/routes/expenditures/new.spec.ts +++ b/api/test/routes/expenditures/new.spec.ts @@ -1,5 +1,5 @@ import * as express from 'express'; -import { expect } from 'chai'; + import * as request from 'supertest'; import { setupRoutes } from '../../../routes'; import { User } from '../../../models/entity/User'; @@ -24,7 +24,7 @@ let campaignStaffToken: string; let campaignStaff2Token: string; describe('Routes post /expenditures/new', () => { - before(async () => { + beforeAll(async () => { app = express(); setupRoutes(app); }); @@ -41,19 +41,19 @@ describe('Routes post /expenditures/new', () => { await addPermissionAsync({ userId: campaignStaff.id, campaignId: campaign.id, - role: UserRole.CAMPAIGN_STAFF + role: UserRole.CAMPAIGN_STAFF, }); await addPermissionAsync({ userId: campaignAdmin.id, campaignId: campaign.id, - role: UserRole.CAMPAIGN_ADMIN + role: UserRole.CAMPAIGN_ADMIN, }); await addPermissionAsync({ userId: govAdmin.id, governmentId: government.id, - role: UserRole.GOVERNMENT_ADMIN + role: UserRole.GOVERNMENT_ADMIN, }); govAdminToken = await generateJWTokenAsync(govAdmin.id); @@ -66,7 +66,7 @@ describe('Routes post /expenditures/new', () => { await truncateAll(); }); - context('post /expenditures/new', () => { + describe('post /expenditures/new', () => { it('success', async () => { const validExpenditurePostBody: IAddExpenditureAttrs = { address1: '123 ABC ST', @@ -81,15 +81,15 @@ describe('Routes post /expenditures/new', () => { state: 'OR', zip: '97214', payeeType: PayeeType.INDIVIDUAL, - name: 'Test Expenditure' + name: 'Test Expenditure', }; const response = await request(app) .post(`/expenditures/new`) .send(validExpenditurePostBody) .set('Accept', 'application/json') .set('Cookie', [`token=${campaignStaffToken}`]); - expect(response.status).to.equal(201); - expect(response.body.message).to.be.undefined; + expect(response.status).toEqual(201); + expect(response.body.message).toBeUndefined(); }); it('error on missing required properties', async () => { @@ -106,14 +106,14 @@ describe('Routes post /expenditures/new', () => { zip: '97214', payeeType: PayeeType.INDIVIDUAL, name: 'Test Expenditure', - description: 'This is a test' + description: 'This is a test', }; const response = await request(app) .post(`/expenditures/new`) .send(invalidExpenditurePostBody) .set('Accept', 'application/json') .set('Cookie', [`token=${campaignStaffToken}`]); - expect(response.status).to.equal(422); + expect(response.status).toEqual(422); expect(response.body.message); }); }); diff --git a/api/test/routes/expenditures/update.spec.ts b/api/test/routes/expenditures/update.spec.ts index 3129de615..67142c2f5 100644 --- a/api/test/routes/expenditures/update.spec.ts +++ b/api/test/routes/expenditures/update.spec.ts @@ -1,5 +1,5 @@ import * as express from 'express'; -import { expect } from 'chai'; + import * as request from 'supertest'; import { setupRoutes } from '../../../routes'; import { User } from '../../../models/entity/User'; @@ -8,7 +8,7 @@ import { newCampaignAsync, newExpenditureAsync, newGovernmentAsync, - truncateAll + truncateAll, } from '../../factories'; import { Government } from '../../../models/entity/Government'; import { Campaign } from '../../../models/entity/Campaign'; @@ -16,6 +16,7 @@ import { addPermissionAsync, generateJWTokenAsync } from '../../../services/perm import { UserRole } from '../../../models/entity/Permission'; import { Expenditure } from '../../../models/entity/Expenditure'; import { getConnection } from 'typeorm'; +import db from '../../../models/db'; let app: express.Express; let campaignStaff: User; @@ -32,10 +33,11 @@ let expenditure1: Expenditure; let expenditureRepository: any; describe('Routes put /expenditures/:id', () => { - before(async () => { + beforeAll(async () => { app = express(); setupRoutes(app); - expenditureRepository = getConnection('default').getRepository('Expenditure'); + const dataSource = await db(); + expenditureRepository = dataSource.getRepository('Expenditure'); }); beforeEach(async () => { @@ -50,19 +52,19 @@ describe('Routes put /expenditures/:id', () => { await addPermissionAsync({ userId: campaignStaff.id, campaignId: campaign.id, - role: UserRole.CAMPAIGN_STAFF + role: UserRole.CAMPAIGN_STAFF, }); await addPermissionAsync({ userId: campaignAdmin.id, campaignId: campaign.id, - role: UserRole.CAMPAIGN_ADMIN + role: UserRole.CAMPAIGN_ADMIN, }); await addPermissionAsync({ userId: govAdmin.id, governmentId: government.id, - role: UserRole.GOVERNMENT_ADMIN + role: UserRole.GOVERNMENT_ADMIN, }); govAdminToken = await generateJWTokenAsync(govAdmin.id); @@ -77,21 +79,22 @@ describe('Routes put /expenditures/:id', () => { await truncateAll(); }); - context('put /expenditures/:id', () => { + describe('put /expenditures/:id', () => { it('success testme', async () => { const response = await request(app) .put(`/expenditures/${expenditure1.id}`) .send({ id: expenditure1.id, - amount: 500 + amount: 500, }) .set('Accept', 'application/json') .set('Cookie', [`token=${campaignStaffToken}`]); - expect(response.status).to.equal(204); - expect(response.body.message).to.be.undefined; - const exp = await expenditureRepository.findOne(expenditure1.id) as Expenditure; - expect(exp.amount).to.equal(500); - + expect(response.status).toEqual(204); + expect(response.body.message).toBeUndefined(); + const exp = (await expenditureRepository.findOne({ + where: { id: expenditure1.id }, + })) as Expenditure; + expect(exp.amount).toEqual(500); }); it('error id not found', async () => { @@ -99,12 +102,12 @@ describe('Routes put /expenditures/:id', () => { .put(`/expenditures/${expenditure1.id}`) .send({ id: 11111, - firstName: 'Dan' + firstName: 'Dan', }) .set('Accept', 'application/json') .set('Cookie', [`token=${campaignStaffToken}`]); - expect(response.status).to.equal(422); - expect(response.body.message).to.equal('Could not find any entity of type "Expenditure" matching: 11111'); + expect(response.status).toEqual(422); + expect(response.body.message).toEqual('Could not find any entity of type "Expenditure" matching: 11111'); }); it('error user does not have permissions', async () => { @@ -112,12 +115,12 @@ describe('Routes put /expenditures/:id', () => { .put(`/expenditures/11111`) .send({ id: expenditure1.id, - amount: 1 + amount: 1, }) .set('Accept', 'application/json') .set('Cookie', [`token=${campaignStaff2Token}`]); - expect(response.status).to.equal(422); - expect(response.body.message).to.equal('User does not have permissions'); + expect(response.status).toEqual(422); + expect(response.body.message).toEqual('User is not permitted to update expenditures for this campaign.'); }); it('error field does not exist', async () => { @@ -125,12 +128,14 @@ describe('Routes put /expenditures/:id', () => { .put(`/expenditures/11111`) .send({ id: expenditure1.id, - thisFieldDoesNotExist: 'Dan' + thisFieldDoesNotExist: 'Dan', }) .set('Accept', 'application/json') .set('Cookie', [`token=${campaignStaffToken}`]); - expect(response.status).to.equal(422); - expect(response.body.message).to.equal('No entity column "thisFieldDoesNotExist" was found.'); + expect(response.status).toEqual(422); + expect(response.body.message).toEqual( + 'Property "thisFieldDoesNotExist" was not found in "Expenditure". Make sure your query is correct.' + ); }); }); }); diff --git a/api/test/routes/helpersRoutes.spec.ts b/api/test/routes/helpersRoutes.spec.ts index 2b791f75e..0d06d2be8 100644 --- a/api/test/routes/helpersRoutes.spec.ts +++ b/api/test/routes/helpersRoutes.spec.ts @@ -1,5 +1,5 @@ import * as express from 'express'; -import { expect } from 'chai'; + import * as request from 'supertest'; import { setupRoutes } from '../../routes'; import { User } from '../../models/entity/User'; @@ -10,7 +10,7 @@ let app: express.Express; let user: User; describe('Route helpers', () => { - before(async () => { + beforeAll(async () => { app = express(); setupRoutes(app); }); @@ -23,15 +23,15 @@ describe('Route helpers', () => { await truncateAll(); }); - context('getCurrentUser', async () => { + describe('getCurrentUser', () => { it('fails incorrect or expired token', async () => { const response = await request(app) .get('/me') .set('Cookie', ['token=12345667']) .set('Accept', 'application/json'); - expect(response.status).to.equal(401); - expect(response.body.message).to.equal('Token expired or incorrect'); - expect(response.header['set-cookie']).to.deep.equal([ 'token=; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT' ]); + expect(response.status).toEqual(401); + expect(response.body.message).toEqual('Token expired or incorrect'); + expect(response.header['set-cookie']).toEqual(['token=; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT']); }); it('succeeds', async () => { @@ -40,8 +40,16 @@ describe('Route helpers', () => { .get('/me') .set('Cookie', [`token=${token}`]) .set('Accept', 'application/json'); - expect(response.status).to.equal(200); - expect(Object.keys(response.body)).to.deep.equal(['id', 'exp', 'firstName', 'lastName', 'email', 'permissions', 'iat']); + expect(response.status).toEqual(200); + expect(Object.keys(response.body)).toEqual([ + 'id', + 'exp', + 'firstName', + 'lastName', + 'email', + 'permissions', + 'iat', + ]); }); }); }); diff --git a/api/test/routes/matches/get.spec.ts b/api/test/routes/matches/get.spec.ts index 1c23d41b4..bc9786ee3 100644 --- a/api/test/routes/matches/get.spec.ts +++ b/api/test/routes/matches/get.spec.ts @@ -1,6 +1,4 @@ import * as express from 'express'; -import { expect } from 'chai'; -import * as faker from 'faker'; import * as request from 'supertest'; import { setupRoutes } from '../../../routes'; import { User } from '../../../models/entity/User'; @@ -13,9 +11,8 @@ import { Contribution, ContributionType, ContributionSubType, - ContributionStatus, ContributorType, - PaymentMethod + PaymentMethod, } from '../../../models/entity/Contribution'; import { addContributionAsync } from '../../../services/contributionService'; @@ -33,7 +30,7 @@ let campaignStaff2Token: string; let contribution1: Contribution; describe('Routes get /matches', () => { - before(async () => { + beforeAll(async () => { app = express(); setupRoutes(app); }); @@ -50,19 +47,19 @@ describe('Routes get /matches', () => { await addPermissionAsync({ userId: campaignStaff.id, campaignId: campaign.id, - role: UserRole.CAMPAIGN_STAFF + role: UserRole.CAMPAIGN_STAFF, }); await addPermissionAsync({ userId: campaignAdmin.id, campaignId: campaign.id, - role: UserRole.CAMPAIGN_ADMIN + role: UserRole.CAMPAIGN_ADMIN, }); await addPermissionAsync({ userId: govAdmin.id, governmentId: government.id, - role: UserRole.GOVERNMENT_ADMIN + role: UserRole.GOVERNMENT_ADMIN, }); govAdminToken = await generateJWTokenAsync(govAdmin.id); @@ -86,7 +83,7 @@ describe('Routes get /matches', () => { state: 'OR', zip: '97214', contributorType: ContributorType.INDIVIDUAL, - paymentMethod: PaymentMethod.CHECK + paymentMethod: PaymentMethod.CHECK, }); }); @@ -94,13 +91,13 @@ describe('Routes get /matches', () => { await truncateAll(); }); - context('get /matches/:id', () => { + describe('get /matches/:id', () => { it('success as gov admin', async () => { const response = await request(app) .get(`/matches/${contribution1.id}`) .set('Accept', 'application/json') .set('Cookie', [`token=${govAdminToken}`]); - expect(response.status).to.equal(200); + expect(response.status).toEqual(200); }); it('error permissions', async () => { @@ -108,8 +105,8 @@ describe('Routes get /matches', () => { .get(`/matches/${contribution1.id}`) .set('Accept', 'application/json') .set('Cookie', [`token=${campaignAdminToken}`]); - expect(response.status).to.equal(422); - expect(response.body).to.not.have.property('id'); + expect(response.status).toEqual(422); + expect(response.body).not.toHaveProperty('id'); expect(response.body.message); }); }); diff --git a/api/test/routes/matches/post.spec.ts b/api/test/routes/matches/post.spec.ts index a428648ce..70c58c97b 100644 --- a/api/test/routes/matches/post.spec.ts +++ b/api/test/routes/matches/post.spec.ts @@ -1,6 +1,4 @@ import * as express from 'express'; -import { expect } from 'chai'; -import * as faker from 'faker'; import * as request from 'supertest'; import { setupRoutes } from '../../../routes'; import { User } from '../../../models/entity/User'; @@ -13,12 +11,11 @@ import { Contribution, ContributionType, ContributionSubType, - ContributionStatus, ContributorType, - PaymentMethod + PaymentMethod, } from '../../../models/entity/Contribution'; import { addContributionAsync } from '../../../services/contributionService'; -import {getConnection} from "typeorm"; +import db from '../../../models/db'; let app: express.Express; let campaignStaff: User; @@ -34,7 +31,7 @@ let campaignStaff2Token: string; let contribution1: Contribution; describe('Routes post /matches', () => { - before(async () => { + beforeAll(async () => { app = express(); setupRoutes(app); }); @@ -51,19 +48,19 @@ describe('Routes post /matches', () => { await addPermissionAsync({ userId: campaignStaff.id, campaignId: campaign.id, - role: UserRole.CAMPAIGN_STAFF + role: UserRole.CAMPAIGN_STAFF, }); await addPermissionAsync({ userId: campaignAdmin.id, campaignId: campaign.id, - role: UserRole.CAMPAIGN_ADMIN + role: UserRole.CAMPAIGN_ADMIN, }); await addPermissionAsync({ userId: govAdmin.id, governmentId: government.id, - role: UserRole.GOVERNMENT_ADMIN + role: UserRole.GOVERNMENT_ADMIN, }); govAdminToken = await generateJWTokenAsync(govAdmin.id); @@ -87,7 +84,7 @@ describe('Routes post /matches', () => { state: 'OR', zip: '97214', contributorType: ContributorType.INDIVIDUAL, - paymentMethod: PaymentMethod.CHECK + paymentMethod: PaymentMethod.CHECK, }); }); @@ -95,24 +92,23 @@ describe('Routes post /matches', () => { await truncateAll(); }); - context('post /matches', () => { + describe('post /matches', () => { it('success as gov admin', async () => { const response = await request(app) .post(`/matches`) .send({ contributionId: contribution1.id, matchId: 'love', - matchStrength: 'weak' + matchStrength: 'weak', }) .set('Accept', 'application/json') .set('Cookie', [`token=${govAdminToken}`]); - expect(response.status).to.equal(200); - const defaultConn = getConnection('default'); - const contributionRepository = defaultConn.getRepository('Contribution'); - const updated = await contributionRepository.findOneOrFail(contribution1.id) as Contribution; - expect(updated.matchStrength).to.equal('weak'); - expect(updated.matchId).to.equal('love'); - + expect(response.status).toEqual(200); + const dataSource = await db(); + const contributionRepository = dataSource.getRepository('Contribution'); + const updated = await contributionRepository.findOneOrFail({ where: { id: contribution1.id } }); + expect(updated.matchStrength).toEqual('weak'); + expect(updated.matchId).toEqual('love'); }); it('error permissions', async () => { @@ -121,12 +117,11 @@ describe('Routes post /matches', () => { .send({ contributionId: contribution1.id, matchId: 'love', - matchStrength: 'none' + matchStrength: 'none', }) .set('Accept', 'application/json') .set('Cookie', [`token=${campaignAdminToken}`]); - expect(response.status).to.equal(422); - expect(response.body).to.not.have.property('id'); + expect(response.status).toEqual(422); expect(response.body.message); }); }); diff --git a/api/test/routes/permissions/delete.spec.ts b/api/test/routes/permissions/delete.spec.ts index dcd305154..f2f1c4471 100644 --- a/api/test/routes/permissions/delete.spec.ts +++ b/api/test/routes/permissions/delete.spec.ts @@ -1,5 +1,5 @@ import * as express from 'express'; -import { expect } from 'chai'; + import * as request from 'supertest'; import { setupRoutes } from '../../../routes'; import { User } from '../../../models/entity/User'; @@ -20,7 +20,7 @@ let govAdminToken: string; let campaignAdminToken: string; describe('Routes post /contributions', () => { - before(async () => { + beforeAll(async () => { app = express(); setupRoutes(app); }); @@ -37,19 +37,19 @@ describe('Routes post /contributions', () => { await addPermissionAsync({ userId: campaignStaff.id, campaignId: campaign.id, - role: UserRole.CAMPAIGN_STAFF + role: UserRole.CAMPAIGN_STAFF, }); await addPermissionAsync({ userId: campaignAdmin.id, campaignId: campaign.id, - role: UserRole.CAMPAIGN_ADMIN + role: UserRole.CAMPAIGN_ADMIN, }); await addPermissionAsync({ userId: govAdmin.id, governmentId: government.id, - role: UserRole.GOVERNMENT_ADMIN + role: UserRole.GOVERNMENT_ADMIN, }); govAdminToken = await generateJWTokenAsync(govAdmin.id); @@ -60,15 +60,15 @@ describe('Routes post /contributions', () => { await truncateAll(); }); - context('delete /permissions/id testme', () => { + describe('delete /permissions/id testme', () => { it('success as gov admin', async () => { const permissions = await campaignStaff.permissions; const response = await request(app) .delete(`/permissions/${permissions[0].id}`) .set('Accept', 'application/json') .set('Cookie', [`token=${govAdminToken}`]); - expect(response.status).to.equal(200); - expect(response.body.message).to.be.undefined; + expect(response.status).toEqual(200); + expect(response.body.message).toBeUndefined(); }); it('success as campaign admin', async () => { @@ -77,8 +77,8 @@ describe('Routes post /contributions', () => { .delete(`/permissions/${permissions[0].id}`) .set('Accept', 'application/json') .set('Cookie', [`token=${campaignAdminToken}`]); - expect(response.status).to.equal(200); - expect(response.body.message).to.be.undefined; + expect(response.status).toEqual(200); + expect(response.body.message).toBeUndefined(); }); it('failure with other token', async () => { @@ -87,7 +87,7 @@ describe('Routes post /contributions', () => { .delete(`/permissions/${permissions[0].id}`) .set('Accept', 'application/json') .set('Cookie', ['token=love']); - expect(response.status).to.equal(401); + expect(response.status).toEqual(401); }); }); }); diff --git a/api/test/routes/summary/post.spec.ts b/api/test/routes/summary/post.spec.ts index 22372d38f..6c382e1dc 100644 --- a/api/test/routes/summary/post.spec.ts +++ b/api/test/routes/summary/post.spec.ts @@ -1,6 +1,4 @@ import * as express from 'express'; -import { expect } from 'chai'; -import * as faker from 'faker'; import * as request from 'supertest'; import { setupRoutes } from '../../../routes'; import { User } from '../../../models/entity/User'; @@ -10,12 +8,10 @@ import { Campaign } from '../../../models/entity/Campaign'; import { addPermissionAsync, generateJWTokenAsync } from '../../../services/permissionService'; import { UserRole } from '../../../models/entity/Permission'; import { - Contribution, ContributionType, ContributionSubType, - ContributionStatus, ContributorType, - PaymentMethod + PaymentMethod, } from '../../../models/entity/Contribution'; import { addContributionAsync } from '../../../services/contributionService'; @@ -31,7 +27,7 @@ let campaignAdminToken: string; let campaignAdmin2Token: string; describe('Routes post /contributions', () => { - before(async () => { + beforeAll(async () => { app = express(); setupRoutes(app); }); @@ -48,19 +44,19 @@ describe('Routes post /contributions', () => { await addPermissionAsync({ userId: campaignAdmin2.id, campaignId: campaign2.id, - role: UserRole.CAMPAIGN_STAFF + role: UserRole.CAMPAIGN_STAFF, }); await addPermissionAsync({ userId: campaignAdmin.id, campaignId: campaign.id, - role: UserRole.CAMPAIGN_ADMIN + role: UserRole.CAMPAIGN_ADMIN, }); await addPermissionAsync({ userId: govAdmin.id, governmentId: government.id, - role: UserRole.GOVERNMENT_ADMIN + role: UserRole.GOVERNMENT_ADMIN, }); govAdminToken = await generateJWTokenAsync(govAdmin.id); @@ -83,7 +79,7 @@ describe('Routes post /contributions', () => { state: 'OR', zip: '97214', contributorType: ContributorType.INDIVIDUAL, - paymentMethod: PaymentMethod.CASH + paymentMethod: PaymentMethod.CASH, }); await addContributionAsync({ @@ -102,7 +98,7 @@ describe('Routes post /contributions', () => { state: 'OR', zip: '97214', contributorType: ContributorType.INDIVIDUAL, - paymentMethod: PaymentMethod.CASH + paymentMethod: PaymentMethod.CASH, }); }); @@ -110,17 +106,17 @@ describe('Routes post /contributions', () => { await truncateAll(); }); - context('post /summary', () => { + describe('post /summary', () => { it('success as gov admin', async () => { const response = await request(app) .post(`/summary`) .send({ governmentId: government.id, currentUserId: govAdmin.id }) .set('Accept', 'application/json') .set('Cookie', [`token=${govAdminToken}`]); - expect(response.status).to.equal(200); - expect(response.body.message).to.be.undefined; - expect(response.body.contributions[0].amount).to.equal(500); - expect(response.body.contributions[0].total).to.equal(2); + expect(response.status).toEqual(200); + expect(response.body.message).toBeUndefined(); + expect(response.body.contributions[0].amount).toEqual(500); + expect(response.body.contributions[0].total).toEqual(2); }); it('success as campaign admin 1', async () => { @@ -129,9 +125,9 @@ describe('Routes post /contributions', () => { .send({ campaignId: campaign.id, currentUserId: campaignAdmin.id }) .set('Accept', 'application/json') .set('Cookie', [`token=${campaignAdminToken}`]); - expect(response.status).to.equal(200); - expect(response.body.contributions[0].amount).to.equal(250); - expect(response.body.contributions[0].total).to.equal(1); + expect(response.status).toEqual(200); + expect(response.body.contributions[0].amount).toEqual(250); + expect(response.body.contributions[0].total).toEqual(1); }); it('success as campaign admin 2', async () => { @@ -140,9 +136,9 @@ describe('Routes post /contributions', () => { .send({ campaignId: campaign2.id, currentUserId: campaignAdmin2.id }) .set('Accept', 'application/json') .set('Cookie', [`token=${campaignAdmin2Token}`]); - expect(response.status).to.equal(200); - expect(response.body.contributions[0].amount).to.equal(250); - expect(response.body.contributions[0].total).to.equal(1); + expect(response.status).toEqual(200); + expect(response.body.contributions[0].amount).toEqual(250); + expect(response.body.contributions[0].total).toEqual(1); }); it('error permissions', async () => { @@ -151,7 +147,7 @@ describe('Routes post /contributions', () => { .send({ governmentId: government.id, currentUserId: campaignAdmin.id }) .set('Accept', 'application/json') .set('Cookie', [`token=${campaignAdminToken}`]); - expect(response.status).to.equal(422); + expect(response.status).toEqual(422); }); }); }); diff --git a/api/test/routes/users/index.spec.ts b/api/test/routes/users/index.spec.ts index 83c286e01..11e06eab1 100644 --- a/api/test/routes/users/index.spec.ts +++ b/api/test/routes/users/index.spec.ts @@ -1,5 +1,5 @@ import * as express from 'express'; -import { expect } from 'chai'; + import * as request from 'supertest'; import { setupRoutes } from '../../../routes'; import { User } from '../../../models/entity/User'; @@ -20,7 +20,7 @@ let campaignAdminToken: string; let campaignStaffToken: string; describe('Routes /users', () => { - before(async () => { + beforeAll(async () => { app = express(); setupRoutes(app); }); @@ -36,19 +36,19 @@ describe('Routes /users', () => { await addPermissionAsync({ userId: campaignStaff.id, campaignId: campaign.id, - role: UserRole.CAMPAIGN_STAFF + role: UserRole.CAMPAIGN_STAFF, }); await addPermissionAsync({ userId: campaignAdmin.id, campaignId: campaign.id, - role: UserRole.CAMPAIGN_ADMIN + role: UserRole.CAMPAIGN_ADMIN, }); await addPermissionAsync({ userId: govAdmin.id, governmentId: government.id, - role: UserRole.GOVERNMENT_ADMIN + role: UserRole.GOVERNMENT_ADMIN, }); govAdminToken = await generateJWTokenAsync(govAdmin.id); @@ -60,55 +60,53 @@ describe('Routes /users', () => { await truncateAll(); }); - context('/users', () => { + describe('/users', () => { it('campaign users, no permission', async () => { const response = await request(app) .post('/users') .send({ - campaignId: campaign.id + campaignId: campaign.id, }) .set('Accept', 'application/json') .set('Cookie', [`token=${campaignStaffToken}`]); - expect(response.status).to.equal(200); - expect(response.body.length).to.equal(0); + expect(response.status).toEqual(200); + expect(response.body.length).toEqual(0); }); it('government users, no permission', async () => { const response = await request(app) .post('/users') .send({ - governmentId: government.id + governmentId: government.id, }) .set('Accept', 'application/json') .set('Cookie', [`token=${campaignStaffToken}`]); - expect(response.status).to.equal(200); - expect(response.body.length).to.equal(0); + expect(response.status).toEqual(200); + expect(response.body.length).toEqual(0); }); it('government users, success', async () => { const response = await request(app) .post('/users') .send({ - governmentId: government.id + governmentId: government.id, }) .set('Accept', 'application/json') .set('Cookie', [`token=${govAdminToken}`]); - expect(response.status).to.equal(200); - expect(response.body.length).to.equal(3); + expect(response.status).toEqual(200); + expect(response.body.length).toEqual(3); }); it('campaign users, success', async () => { const response = await request(app) .post('/users') .send({ - campaignId: campaign.id + campaignId: campaign.id, }) .set('Accept', 'application/json') .set('Cookie', [`token=${campaignAdminToken}`]); - expect(response.status).to.equal(200); - expect(response.body.length).to.equal(2); + expect(response.status).toEqual(200); + expect(response.body.length).toEqual(2); }); - }); - }); diff --git a/api/test/routes/users/invite.spec.ts b/api/test/routes/users/invite.spec.ts index f49e8bd56..8f2915f65 100644 --- a/api/test/routes/users/invite.spec.ts +++ b/api/test/routes/users/invite.spec.ts @@ -1,6 +1,5 @@ import * as express from 'express'; -import { expect } from 'chai'; -import * as faker from 'faker'; +import { faker } from '@faker-js/faker'; import * as request from 'supertest'; import { setupRoutes } from '../../../routes'; import { User } from '../../../models/entity/User'; @@ -9,7 +8,7 @@ import { newCampaignAsync, newGovernmentAsync, newInactiveUserAsync, - truncateAll + truncateAll, } from '../../factories'; import { Government } from '../../../models/entity/Government'; import { Campaign } from '../../../models/entity/Campaign'; @@ -27,7 +26,7 @@ let campaignAdminToken: string; let campaignStaffToken: string; describe('Routes /users', () => { - before(async () => { + beforeAll(async () => { app = express(); setupRoutes(app); }); @@ -43,19 +42,19 @@ describe('Routes /users', () => { await addPermissionAsync({ userId: campaignStaff.id, campaignId: campaign.id, - role: UserRole.CAMPAIGN_STAFF + role: UserRole.CAMPAIGN_STAFF, }); await addPermissionAsync({ userId: campaignAdmin.id, campaignId: campaign.id, - role: UserRole.CAMPAIGN_ADMIN + role: UserRole.CAMPAIGN_ADMIN, }); await addPermissionAsync({ userId: govAdmin.id, governmentId: government.id, - role: UserRole.GOVERNMENT_ADMIN + role: UserRole.GOVERNMENT_ADMIN, }); govAdminToken = await generateJWTokenAsync(govAdmin.id); @@ -67,22 +66,21 @@ describe('Routes /users', () => { await truncateAll(); }); - context('/users/invite', () => { + describe('/users/invite', () => { it('fails, user does not have permission for government', async () => { - const response = await request(app) .post('/users/invite') .send({ - email: faker.internet.email(), - firstName: faker.name.firstName(), - lastName: faker.name.lastName(), - governmentId: government.id, - role: UserRole.GOVERNMENT_ADMIN - }) + email: faker.internet.email(), + firstName: faker.person.firstName(), + lastName: faker.person.lastName(), + governmentId: government.id, + role: UserRole.GOVERNMENT_ADMIN, + }) .set('Accept', 'application/json') .set('Cookie', [`token=${campaignStaffToken}`]); - expect(response.status).to.equal(422); - expect(response.body.message).to.equal('user does not have sufficient permissions'); + expect(response.status).toEqual(422); + expect(response.body.message).toEqual('user does not have sufficient permissions'); }); it('fails, user does not have permission for campaign', async () => { @@ -90,15 +88,15 @@ describe('Routes /users', () => { .post('/users/invite') .send({ email: faker.internet.email(), - firstName: faker.name.firstName(), - lastName: faker.name.lastName(), + firstName: faker.person.firstName(), + lastName: faker.person.lastName(), campaignId: campaign.id, - role: UserRole.CAMPAIGN_STAFF + role: UserRole.CAMPAIGN_STAFF, }) .set('Accept', 'application/json') .set('Cookie', [`token=${campaignStaffToken}`]); - expect(response.status).to.equal(422); - expect(response.body.message).to.equal('user does not have sufficient permissions'); + expect(response.status).toEqual(422); + expect(response.body.message).toEqual('user does not have sufficient permissions'); }); it('succeeds, invite to government', async () => { @@ -106,14 +104,14 @@ describe('Routes /users', () => { .post('/users/invite') .send({ email: faker.internet.email(), - firstName: faker.name.firstName(), - lastName: faker.name.lastName(), + firstName: faker.person.firstName(), + lastName: faker.person.lastName(), governmentId: government.id, - role: UserRole.GOVERNMENT_ADMIN + role: UserRole.GOVERNMENT_ADMIN, }) .set('Accept', 'application/json') .set('Cookie', [`token=${govAdminToken}`]); - expect(response.status).to.equal(201); + expect(response.status).toEqual(201); }); it('succeeds, govAdmin invite to campaign testme', async () => { @@ -121,14 +119,14 @@ describe('Routes /users', () => { .post('/users/invite') .send({ email: faker.internet.email(), - firstName: faker.name.firstName(), - lastName: faker.name.lastName(), + firstName: faker.person.firstName(), + lastName: faker.person.lastName(), campaignId: campaign.id, - role: UserRole.CAMPAIGN_STAFF + role: UserRole.CAMPAIGN_STAFF, }) .set('Accept', 'application/json') .set('Cookie', [`token=${govAdminToken}`]); - expect(response.status).to.equal(201); + expect(response.status).toEqual(201); }); it('succeeds, campaignAdmin invite to campaign', async () => { @@ -136,18 +134,18 @@ describe('Routes /users', () => { .post('/users/invite') .send({ email: faker.internet.email(), - firstName: faker.name.firstName(), - lastName: faker.name.lastName(), + firstName: faker.person.firstName(), + lastName: faker.person.lastName(), campaignId: campaign.id, - role: UserRole.CAMPAIGN_STAFF + role: UserRole.CAMPAIGN_STAFF, }) .set('Accept', 'application/json') .set('Cookie', [`token=${campaignAdminToken}`]); - expect(response.status).to.equal(201); + expect(response.status).toEqual(201); }); }); - context('/users/resend-invite', () => { + describe('/users/resend-invite', () => { it('succeeds, invite to government', async () => { const newUser = await newInactiveUserAsync(); let response = await request(app) @@ -157,47 +155,47 @@ describe('Routes /users', () => { firstName: newUser.firstName, lastName: newUser.lastName, governmentId: government.id, - role: UserRole.GOVERNMENT_ADMIN + role: UserRole.GOVERNMENT_ADMIN, }) .set('Accept', 'application/json') .set('Cookie', [`token=${govAdminToken}`]); - expect(response.status).to.equal(201); + expect(response.status).toEqual(201); response = await request(app) .post('/users/resend-invite') .send({ - userId: newUser.id + userId: newUser.id, }) .set('Accept', 'application/json') .set('Cookie', [`token=${govAdminToken}`]); - expect(response.status).to.equal(204); + expect(response.status).toEqual(204); }); it('fails, no user', async () => { const response = await request(app) .post('/users/resend-invite') .send({ - userId: 1100 + userId: 1100, }) .set('Accept', 'application/json') .set('Cookie', [`token=${govAdminToken}`]); - expect(response.status).to.equal(422); - expect(response.body.message).to.equal('Could not find any entity of type "User" matching: 1100'); + expect(response.status).toEqual(422); + expect(response.body.message).toEqual('Could not find any entity of type "User" matching: 1100'); }); it('fails, user already accepted', async () => { const response = await request(app) .post('/users/resend-invite') .send({ - userId: govAdmin.id + userId: govAdmin.id, }) .set('Accept', 'application/json') .set('Cookie', [`token=${govAdminToken}`]); - expect(response.status).to.equal(422); - expect(response.body.message).to.equal('User is already in the system or there is no invitation code'); + expect(response.status).toEqual(422); + expect(response.body.message).toEqual('User is already in the system or there is no invitation code'); }); }); - context('/users/redeem-invite', () => { + describe('/users/redeem-invite', () => { it('succeeds', async () => { const newUser = await newInactiveUserAsync(); const response = await request(app) @@ -209,7 +207,7 @@ describe('Routes /users', () => { invitationCode: newUser.invitationCode, }) .set('Accept', 'application/json'); - expect(response.status).to.equal(204); + expect(response.status).toEqual(204); }); it('fails, invitationCode not found', async () => { @@ -223,8 +221,10 @@ describe('Routes /users', () => { invitationCode: 111111, }) .set('Accept', 'application/json'); - expect(response.status).to.equal(422); - expect(response.body.message).to.equal('Could not find any entity of type "User" matching: {\n "invitationCode": 111111\n}'); + expect(response.status).toEqual(422); + expect(response.body.message).toEqual( + 'Could not find any entity of type "User" matching invitationCode: 111111' + ); }); it('fails, password not correct', async () => { @@ -238,8 +238,8 @@ describe('Routes /users', () => { invitationCode: newUser.invitationCode, }) .set('Accept', 'application/json'); - expect(response.status).to.equal(422); - expect(response.body.message).to.equal('User password must be at least 6 characters'); + expect(response.status).toEqual(422); + expect(response.body.message).toEqual('User password must be at least 6 characters'); }); }); }); diff --git a/api/test/routes/users/login.spec.ts b/api/test/routes/users/login.spec.ts index 61e15aede..c24608efa 100644 --- a/api/test/routes/users/login.spec.ts +++ b/api/test/routes/users/login.spec.ts @@ -1,5 +1,5 @@ import * as express from 'express'; -import { expect } from 'chai'; + import * as request from 'supertest'; import { setupRoutes } from '../../../routes'; import { User } from '../../../models/entity/User'; @@ -20,7 +20,7 @@ let campaignAdminToken: string; let campaignStaffToken: string; describe('Routes /users', () => { - before(async () => { + beforeAll(async () => { app = express(); setupRoutes(app); }); @@ -36,19 +36,19 @@ describe('Routes /users', () => { await addPermissionAsync({ userId: campaignStaff.id, campaignId: campaign.id, - role: UserRole.CAMPAIGN_STAFF + role: UserRole.CAMPAIGN_STAFF, }); await addPermissionAsync({ userId: campaignAdmin.id, campaignId: campaign.id, - role: UserRole.CAMPAIGN_ADMIN + role: UserRole.CAMPAIGN_ADMIN, }); await addPermissionAsync({ userId: govAdmin.id, governmentId: government.id, - role: UserRole.GOVERNMENT_ADMIN + role: UserRole.GOVERNMENT_ADMIN, }); govAdminToken = await generateJWTokenAsync(govAdmin.id); @@ -60,34 +60,34 @@ describe('Routes /users', () => { await truncateAll(); }); - context('/users/login', () => { + describe('/users/login', () => { it('email not found', async () => { const response = await request(app) .post('/users/login') - .send({password: 'password'}) - .send({email: 'dan@civicsoftwarefoundation.org'}) + .send({ password: 'password' }) + .send({ email: 'dan@civicsoftwarefoundation.org' }) .set('Accept', 'application/json'); - expect(response.status).to.equal(401); - expect(response.body.message).to.equal('No user found with email or password'); + expect(response.status).toEqual(401); + expect(response.body.message).toEqual('No user found with email or password'); }); it('password not correct', async () => { const response = await request(app) .post('/users/login') - .send({password: 'password1'}) - .send({email: campaignStaff.email}) + .send({ password: 'password1' }) + .send({ email: campaignStaff.email }) .set('Accept', 'application/json'); - expect(response.status).to.equal(401); - expect(response.body.message).to.equal('No user found with email or password'); + expect(response.status).toEqual(401); + expect(response.body.message).toEqual('No user found with email or password'); }); it('success, sets token in cookie', async () => { const response = await request(app) .post('/users/login') - .send({password: 'password'}) - .send({email: campaignStaff.email}) + .send({ password: 'password' }) + .send({ email: campaignStaff.email }) .set('Accept', 'application/json'); - expect(response.status).to.equal(204); + expect(response.status).toEqual(204); const regex = /(.*?)=(.*?)($|;|,(?! ))/g; const matches = []; @@ -96,18 +96,18 @@ describe('Routes /users', () => { matches.push(match[1]); match = regex.exec(response.header['set-cookie']); } - expect(matches).to.deep.equal([ 'token', ' Domain', ' Path', ' Expires' ]); - expect(response.header['set-cookie'][0].includes('localhost')).to.be.true; + expect(matches).toEqual(['token', ' Domain', ' Path', ' Expires']); + expect(response.header['set-cookie'][0].includes('localhost')).toBeTruthy(); }); it('success, sets token in cookie production', async () => { process.env.COOKIE_URL_TEST = 'openelectionsportland.org'; const response = await request(app) .post('/users/login') - .send({password: 'password'}) - .send({email: campaignStaff.email}) + .send({ password: 'password' }) + .send({ email: campaignStaff.email }) .set('Accept', 'application/json'); - expect(response.status).to.equal(204); + expect(response.status).toEqual(204); const regex = /(.*?)=(.*?)($|;|,(?! ))/g; const matches = []; @@ -116,10 +116,9 @@ describe('Routes /users', () => { matches.push(match[1]); match = regex.exec(response.header['set-cookie']); } - expect(matches).to.deep.equal([ 'token', ' Domain', ' Path', ' Expires' ]); - expect(response.header['set-cookie'][0].includes('openelectionsportland.org')).to.be.true; + expect(matches).toEqual(['token', ' Domain', ' Path', ' Expires']); + expect(response.header['set-cookie'][0].includes('openelectionsportland.org')).toBeTruthy(); delete process.env.COOKIE_URL_TEST; }); }); - }); diff --git a/api/test/routes/users/passwordReset.spec.ts b/api/test/routes/users/passwordReset.spec.ts index bd09d58ad..036295140 100644 --- a/api/test/routes/users/passwordReset.spec.ts +++ b/api/test/routes/users/passwordReset.spec.ts @@ -1,13 +1,9 @@ import * as express from 'express'; -import { expect } from 'chai'; -import * as faker from 'faker'; +import { faker } from '@faker-js/faker'; import * as request from 'supertest'; import { setupRoutes } from '../../../routes'; import { User } from '../../../models/entity/User'; -import { - newActiveUserAsync, - truncateAll -} from '../../factories'; +import { newActiveUserAsync, truncateAll } from '../../factories'; import { generatePasswordResetAsync } from '../../../services/userService'; import { generateJWTokenAsync } from '../../../services/permissionService'; @@ -16,7 +12,7 @@ let govAdmin: User; let govAdminToken: string; describe('Routes /users', () => { - before(async () => { + beforeAll(async () => { app = express(); setupRoutes(app); }); @@ -30,17 +26,19 @@ describe('Routes /users', () => { await truncateAll(); }); - context('/users/send-password-reset-email', () => { + describe('/users/send-password-reset-email', () => { it('fails, no user found', async () => { const email = faker.internet.email(); const response = await request(app) .post('/users/send-password-reset-email') .send({ - email + email, }) .set('Accept', 'application/json'); - expect(response.status).to.equal(422); - expect(response.body.message).to.equal(`Could not find any entity of type "User" matching: {\n "email": "${email}"\n}`); + expect(response.status).toEqual(422); + expect(response.body.message).toEqual( + `Could not find any entity of type "User" matching: {\n "email": "${email}"\n}` + ); }); it('succeeds, user found', async () => { @@ -48,25 +46,27 @@ describe('Routes /users', () => { const response = await request(app) .post('/users/send-password-reset-email') .send({ - email: govAdmin.email + email: govAdmin.email, }) .set('Accept', 'application/json'); - expect(response.status).to.equal(204); + expect(response.status).toEqual(204); }); }); - context('/users/reset-password', () => { + describe('/users/reset-password', () => { it('fails, invitation code not found', async () => { const email = faker.internet.email(); const response = await request(app) .post('/users/reset-password') .send({ invitationCode: 'nope', - password: 'lotsofnope' + password: 'lotsofnope', }) .set('Accept', 'application/json'); - expect(response.status).to.equal(422); - expect(response.body.message).to.equal(`Could not find any entity of type "User" matching: {\n "invitationCode": "nope"\n}`); + expect(response.status).toEqual(422); + expect(response.body.message).toEqual( + `Could not find any entity of type "User" matching: {\n "invitationCode": "nope"\n}` + ); }); it('succeeds, user found', async () => { @@ -75,14 +75,14 @@ describe('Routes /users', () => { .post('/users/reset-password') .send({ invitationCode: code, - password: 'lotsofnope' + password: 'lotsofnope', }) .set('Accept', 'application/json'); - expect(response.status).to.equal(204); + expect(response.status).toEqual(204); }); }); - context('/users/password', () => { + describe('/users/password', () => { it('fails, password not valid', async () => { const response = await request(app) .put('/users/password') @@ -92,8 +92,8 @@ describe('Routes /users', () => { }) .set('Accept', 'application/json') .set('Cookie', [`token=${govAdminToken}`]); - expect(response.status).to.equal(422); - expect(response.body.message).to.equal('Invalid password'); + expect(response.status).toEqual(422); + expect(response.body.message).toEqual('Invalid password'); }); it('fails, new password not valid', async () => { @@ -105,8 +105,8 @@ describe('Routes /users', () => { }) .set('Accept', 'application/json') .set('Cookie', [`token=${govAdminToken}`]); - expect(response.status).to.equal(422); - expect(response.body.message).to.equal('Invalid password'); + expect(response.status).toEqual(422); + expect(response.body.message).toEqual('Invalid password'); }); it('succeeds, new password valid', async () => { @@ -118,8 +118,7 @@ describe('Routes /users', () => { }) .set('Accept', 'application/json') .set('Cookie', [`token=${govAdminToken}`]); - expect(response.status).to.equal(204); + expect(response.status).toEqual(204); }); }); - }); diff --git a/api/test/services/activityService.spec.ts b/api/test/services/activityService.spec.ts index ae3e43a55..ed22c2aff 100644 --- a/api/test/services/activityService.spec.ts +++ b/api/test/services/activityService.spec.ts @@ -1,25 +1,22 @@ -import { expect } from 'chai'; import { Campaign } from '../../models/entity/Campaign'; import { Government } from '../../models/entity/Government'; import { User } from '../../models/entity/User'; import { newActiveUserAsync, newCampaignAsync, - newContributionAsync, newExpenditureAsync, + newContributionAsync, + newExpenditureAsync, newGovernmentAsync, - truncateAll + truncateAll, } from '../factories'; -import { - createActivityRecordAsync, getAllActivityRecordsAsync, -} from '../../services/activityService'; +import { createActivityRecordAsync, getAllActivityRecordsAsync } from '../../services/activityService'; import { addPermissionAsync } from '../../services/permissionService'; import { Permission, UserRole } from '../../models/entity/Permission'; -import { ActivityTypeEnum, getActivityByCampaignByTimeAsync, IShortActivityResult } from '../../models/entity/Activity'; -import { getConnection } from 'typeorm'; -import { Contribution, ContributionSubType, ContributionType, ContributorType } from '../../models/entity/Contribution'; +import { ActivityTypeEnum, getActivityByCampaignByTimeAsync } from '../../models/entity/Activity'; +import { Contribution } from '../../models/entity/Contribution'; import { Expenditure } from '../../models/entity/Expenditure'; import { sendActivityEmailToCampaignAdminsAsync } from '../../services/emailService'; -import { addContributionAsync } from '../../services/contributionService'; +import db from '../../models/db'; let government: Government; let campaign1: Campaign; @@ -37,6 +34,7 @@ let expenditure1: Expenditure; let expenditure2: Expenditure; describe('Activity', () => { + let dataSource = null; beforeEach(async () => { govUser = await newActiveUserAsync(); campaignAdmin = await newActiveUserAsync(); @@ -53,98 +51,98 @@ describe('Activity', () => { permission = await addPermissionAsync({ userId: govUser.id, governmentId: government.id, - role: UserRole.GOVERNMENT_ADMIN + role: UserRole.GOVERNMENT_ADMIN, }); await addPermissionAsync({ userId: campaignAdmin.id, governmentId: government.id, campaignId: campaign1.id, - role: UserRole.CAMPAIGN_ADMIN + role: UserRole.CAMPAIGN_ADMIN, }); await addPermissionAsync({ userId: campaignAdmin1.id, governmentId: government.id, campaignId: campaign1.id, - role: UserRole.CAMPAIGN_ADMIN + role: UserRole.CAMPAIGN_ADMIN, }); await addPermissionAsync({ userId: campaignAdmin2.id, governmentId: government.id, campaignId: campaign2.id, - role: UserRole.CAMPAIGN_ADMIN + role: UserRole.CAMPAIGN_ADMIN, }); await addPermissionAsync({ userId: campaignStaff.id, governmentId: government.id, campaignId: campaign1.id, - role: UserRole.CAMPAIGN_STAFF + role: UserRole.CAMPAIGN_STAFF, }); - activityRepository = getConnection('default').getRepository('Activity'); + dataSource = await db(); + activityRepository = dataSource.getRepository('Activity'); }); afterEach(async () => { await truncateAll(); }); - it('createActivityRecordAsync Permission', async () => { - expect(await activityRepository.count()).to.equal(0); + expect(await activityRepository.count()).toEqual(0); await createActivityRecordAsync({ currentUser: govUser, government: government, notes: `${govUser.name} invited to ${government.name} as ${permission.role}`, activityId: permission.id, - activityType: ActivityTypeEnum.PERMISSION + activityType: ActivityTypeEnum.PERMISSION, }); - expect(await activityRepository.count()).to.equal(1); + expect(await activityRepository.count()).toEqual(1); }); it('createActivityRecordAsync Contribution', async () => { - expect(await activityRepository.count()).to.equal(0); + expect(await activityRepository.count()).toEqual(0); await createActivityRecordAsync({ currentUser: campaignAdmin, government: government, notes: `something happened`, activityId: contribution1.id, - activityType: ActivityTypeEnum.CONTRIBUTION + activityType: ActivityTypeEnum.CONTRIBUTION, }); - expect(await activityRepository.count()).to.equal(1); + expect(await activityRepository.count()).toEqual(1); }); it('createActivityRecordAsync Contribution', async () => { - expect(await activityRepository.count()).to.equal(0); + expect(await activityRepository.count()).toEqual(0); await createActivityRecordAsync({ currentUser: campaignAdmin, government: government, notes: 'this is a comment', activityId: contribution1.id, - activityType: ActivityTypeEnum.COMMENT_CONTR + activityType: ActivityTypeEnum.COMMENT_CONTR, }); - expect(await activityRepository.count()).to.equal(1); + expect(await activityRepository.count()).toEqual(1); }); it('createActivityRecordAsync Expenditure', async () => { - expect(await activityRepository.count()).to.equal(0); + expect(await activityRepository.count()).toEqual(0); await createActivityRecordAsync({ currentUser: campaignAdmin, government: government, notes: `something happened`, activityId: expenditure1.id, - activityType: ActivityTypeEnum.EXPENDITURE + activityType: ActivityTypeEnum.EXPENDITURE, }); - expect(await activityRepository.count()).to.equal(1); + expect(await activityRepository.count()).toEqual(1); }); it('createActivityRecordAsync Expenditure', async () => { - expect(await activityRepository.count()).to.equal(0); + expect(await activityRepository.count()).toEqual(0); await createActivityRecordAsync({ currentUser: campaignAdmin, government: government, notes: 'this is a comment', activityId: expenditure1.id, - activityType: ActivityTypeEnum.COMMENT_EXP + activityType: ActivityTypeEnum.COMMENT_EXP, }); - expect(await activityRepository.count()).to.equal(1); + expect(await activityRepository.count()).toEqual(1); }); describe('getAllActivityRecordsAsync', () => { @@ -202,188 +200,248 @@ describe('Activity', () => { }); it('[] for campaignAdmin trying to get governmentId', async () => { - const records = await getAllActivityRecordsAsync({ - currentUserId: campaignAdmin.id, - governmentId: government.id - }, 'openelectionsportland.org'); - expect(records.data.length).to.equal(0); + const records = await getAllActivityRecordsAsync( + { + currentUserId: campaignAdmin.id, + governmentId: government.id, + }, + 'openelectionsportland.org' + ); + expect(records.data.length).toEqual(0); }); it('[] for campaignStaff trying to get governmentId', async () => { - const records = await getAllActivityRecordsAsync({ - currentUserId: campaignStaff.id, - governmentId: government.id - }, 'openelectionsportland.org'); - expect(records.data.length).to.equal(0); + const records = await getAllActivityRecordsAsync( + { + currentUserId: campaignStaff.id, + governmentId: government.id, + }, + 'openelectionsportland.org' + ); + expect(records.data.length).toEqual(0); }); it('6 records for governmentAdmin trying to get governmentId', async () => { - const records = await getAllActivityRecordsAsync({ - currentUserId: govUser.id, - governmentId: government.id - }, 'openelectionsportland.org'); - expect(records.data.length).to.equal(6); + const records = await getAllActivityRecordsAsync( + { + currentUserId: govUser.id, + governmentId: government.id, + }, + 'openelectionsportland.org' + ); + expect(records.data.length).toEqual(6); }); it('3 records for governmentAdmin with campaignId', async () => { - let records = await getAllActivityRecordsAsync({ - currentUserId: govUser.id, - campaignId: campaign1.id - }, 'openelectionsportland.org'); - expect(records.data.length).to.equal(3); - - records = await getAllActivityRecordsAsync({ - currentUserId: govUser.id, - campaignId: campaign2.id - }, 'openelectionsportland.org'); - expect(records.data.length).to.equal(3); + let records = await getAllActivityRecordsAsync( + { + currentUserId: govUser.id, + campaignId: campaign1.id, + }, + 'openelectionsportland.org' + ); + expect(records.data.length).toEqual(3); + + records = await getAllActivityRecordsAsync( + { + currentUserId: govUser.id, + campaignId: campaign2.id, + }, + 'openelectionsportland.org' + ); + expect(records.data.length).toEqual(3); }); it('3 records for campaignAdmin with campaignId', async () => { - const records = await getAllActivityRecordsAsync({ - currentUserId: campaignAdmin.id, - campaignId: campaign1.id - }, 'openelectionsportland.org'); - expect(records.data.length).to.equal(3); + const records = await getAllActivityRecordsAsync( + { + currentUserId: campaignAdmin.id, + campaignId: campaign1.id, + }, + 'openelectionsportland.org' + ); + expect(records.data.length).toEqual(3); }); - it('3 records for campaignStaff with campaignId', async () => { - const records = await getAllActivityRecordsAsync({ - currentUserId: campaignStaff.id, - campaignId: campaign1.id - }, 'openelectionsportland.org'); - expect(records.data.length).to.equal(3); + const records = await getAllActivityRecordsAsync( + { + currentUserId: campaignStaff.id, + campaignId: campaign1.id, + }, + 'openelectionsportland.org' + ); + expect(records.data.length).toEqual(3); }); it('[] records for campaignStaff with different campaignId', async () => { - const records = await getAllActivityRecordsAsync({ - currentUserId: campaignStaff.id, - campaignId: campaign2.id - }, 'openelectionsportland.org'); - expect(records.data.length).to.equal(0); + const records = await getAllActivityRecordsAsync( + { + currentUserId: campaignStaff.id, + campaignId: campaign2.id, + }, + 'openelectionsportland.org' + ); + expect(records.data.length).toEqual(0); }); it('[] records for campaignAdmin with different campaignId', async () => { - const records = await getAllActivityRecordsAsync({ - currentUserId: campaignAdmin.id, - campaignId: campaign2.id - }, 'openelectionsportland.org'); - expect(records.data.length).to.equal(0); + const records = await getAllActivityRecordsAsync( + { + currentUserId: campaignAdmin.id, + campaignId: campaign2.id, + }, + 'openelectionsportland.org' + ); + expect(records.data.length).toEqual(0); }); it('1 records for governmentAdmin with contributionId', async () => { - let records = await getAllActivityRecordsAsync({ - currentUserId: govUser.id, - contributionId: contribution1.id - }, 'openelectionsportland.org'); - expect(records.data.length).to.equal(1); - - records = await getAllActivityRecordsAsync({ - currentUserId: govUser.id, - contributionId: contribution2.id - }, 'openelectionsportland.org'); - expect(records.data.length).to.equal(1); + let records = await getAllActivityRecordsAsync( + { + currentUserId: govUser.id, + contributionId: contribution1.id, + }, + 'openelectionsportland.org' + ); + expect(records.data.length).toEqual(1); + + records = await getAllActivityRecordsAsync( + { + currentUserId: govUser.id, + contributionId: contribution2.id, + }, + 'openelectionsportland.org' + ); + expect(records.data.length).toEqual(1); }); it('1 records for campaignAdmin with contributionId', async () => { - const records = await getAllActivityRecordsAsync({ - currentUserId: campaignAdmin.id, - contributionId: contribution1.id - }, 'openelectionsportland.org'); - expect(records.data.length).to.equal(1); + const records = await getAllActivityRecordsAsync( + { + currentUserId: campaignAdmin.id, + contributionId: contribution1.id, + }, + 'openelectionsportland.org' + ); + expect(records.data.length).toEqual(1); }); - it('1 records for campaignStaff with contributionId', async () => { - const records = await getAllActivityRecordsAsync({ - currentUserId: campaignStaff.id, - contributionId: contribution1.id - }, 'openelectionsportland.org'); - expect(records.data.length).to.equal(1); + const records = await getAllActivityRecordsAsync( + { + currentUserId: campaignStaff.id, + contributionId: contribution1.id, + }, + 'openelectionsportland.org' + ); + expect(records.data.length).toEqual(1); }); it('[] records for campaignStaff with different contributionId', async () => { - const records = await getAllActivityRecordsAsync({ - currentUserId: campaignStaff.id, - contributionId: contribution2.id - }, 'openelectionsportland.org'); - expect(records.data.length).to.equal(0); + const records = await getAllActivityRecordsAsync( + { + currentUserId: campaignStaff.id, + contributionId: contribution2.id, + }, + 'openelectionsportland.org' + ); + expect(records.data.length).toEqual(0); }); it('[] records for campaignAdmin with different contributionId', async () => { - const records = await getAllActivityRecordsAsync({ - currentUserId: campaignAdmin.id, - contributionId: contribution2.id - }, 'openelectionsportland.org'); - expect(records.data.length).to.equal(0); + const records = await getAllActivityRecordsAsync( + { + currentUserId: campaignAdmin.id, + contributionId: contribution2.id, + }, + 'openelectionsportland.org' + ); + expect(records.data.length).toEqual(0); }); it('1 records for governmentAdmin with expenditureId', async () => { - let records = await getAllActivityRecordsAsync({ - currentUserId: govUser.id, - expenditureId: expenditure1.id - }, 'openelectionsportland.org'); - expect(records.data.length).to.equal(1); - - records = await getAllActivityRecordsAsync({ - currentUserId: govUser.id, - expenditureId: expenditure2.id - }, 'openelectionsportland.org'); - expect(records.data.length).to.equal(1); + let records = await getAllActivityRecordsAsync( + { + currentUserId: govUser.id, + expenditureId: expenditure1.id, + }, + 'openelectionsportland.org' + ); + expect(records.data.length).toEqual(1); + + records = await getAllActivityRecordsAsync( + { + currentUserId: govUser.id, + expenditureId: expenditure2.id, + }, + 'openelectionsportland.org' + ); + expect(records.data.length).toEqual(1); }); it('1 records for campaignAdmin with expenditureId', async () => { - const records = await getAllActivityRecordsAsync({ - currentUserId: campaignAdmin.id, - expenditureId: expenditure1.id - }, 'openelectionsportland.org'); - expect(records.data.length).to.equal(1); + const records = await getAllActivityRecordsAsync( + { + currentUserId: campaignAdmin.id, + expenditureId: expenditure1.id, + }, + 'openelectionsportland.org' + ); + expect(records.data.length).toEqual(1); }); - it('1 records for campaignStaff with expenditureId', async () => { - const records = await getAllActivityRecordsAsync({ - currentUserId: campaignStaff.id, - expenditureId: expenditure1.id - }, 'openelectionsportland.org'); - expect(records.data.length).to.equal(1); + const records = await getAllActivityRecordsAsync( + { + currentUserId: campaignStaff.id, + expenditureId: expenditure1.id, + }, + 'openelectionsportland.org' + ); + expect(records.data.length).toEqual(1); }); it('[] records for campaignStaff with different expenditureId', async () => { - const records = await getAllActivityRecordsAsync({ - currentUserId: campaignStaff.id, - expenditureId: expenditure2.id - }, 'openelectionsportland.org'); - expect(records.data.length).to.equal(0); + const records = await getAllActivityRecordsAsync( + { + currentUserId: campaignStaff.id, + expenditureId: expenditure2.id, + }, + 'openelectionsportland.org' + ); + expect(records.data.length).toEqual(0); }); it('[] records for campaignAdmin with different expenditureId', async () => { - const records = await getAllActivityRecordsAsync({ - currentUserId: campaignAdmin.id, - expenditureId: expenditure2.id - }, 'openelectionsportland.org'); - expect(records.data.length).to.equal(0); + const records = await getAllActivityRecordsAsync( + { + currentUserId: campaignAdmin.id, + expenditureId: expenditure2.id, + }, + 'openelectionsportland.org' + ); + expect(records.data.length).toEqual(0); }); }); it('sendActivityEmailToCampaignAdminsAsync, no activities, so no sends no email', async () => { - const connection = getConnection('default'); - await connection.query('TRUNCATE "activity" RESTART IDENTITY CASCADE'); + const dataSource = await db(); + await dataSource.query('TRUNCATE "activity" RESTART IDENTITY CASCADE'); const params = await sendActivityEmailToCampaignAdminsAsync(campaign1.id); - expect(params).to.be.undefined; + expect(params).toBeUndefined(); }); it('sendActivityEmailToCampaignAdminsAsync, only user activities, so no sends no email', async () => { - const connection = getConnection('default'); - await connection.query('TRUNCATE "activity" RESTART IDENTITY CASCADE'); + const dataSource = await db(); + await dataSource.query('TRUNCATE "activity" RESTART IDENTITY CASCADE'); const params = await sendActivityEmailToCampaignAdminsAsync(campaign1.id); - expect(params).to.be.undefined; + expect(params).toBeUndefined(); }); it('sendActivityEmailToCampaignAdminsAsync testme', async () => { - const connection = getConnection('default'); - await connection.query('TRUNCATE "activity" RESTART IDENTITY CASCADE'); + const dataSource = await db(); + await dataSource.query('TRUNCATE "activity" RESTART IDENTITY CASCADE'); await createActivityRecordAsync({ currentUser: campaignAdmin, government: government, @@ -391,7 +449,7 @@ describe('Activity', () => { activityId: contribution1.id, activityType: ActivityTypeEnum.CONTRIBUTION, notify: true, - campaign: campaign1 + campaign: campaign1, }); await createActivityRecordAsync({ @@ -401,7 +459,7 @@ describe('Activity', () => { activityId: contribution1.id, activityType: ActivityTypeEnum.COMMENT_CONTR, notify: true, - campaign: campaign1 + campaign: campaign1, }); await createActivityRecordAsync({ @@ -411,7 +469,7 @@ describe('Activity', () => { activityId: expenditure1.id, activityType: ActivityTypeEnum.COMMENT_EXP, notify: true, - campaign: campaign1 + campaign: campaign1, }); await createActivityRecordAsync({ @@ -421,7 +479,7 @@ describe('Activity', () => { activityId: expenditure1.id, activityType: ActivityTypeEnum.EXPENDITURE, notify: true, - campaign: campaign1 + campaign: campaign1, }); await createActivityRecordAsync({ @@ -431,7 +489,7 @@ describe('Activity', () => { activityId: contribution1.id, activityType: ActivityTypeEnum.CONTRIBUTION, notify: true, - campaign: campaign1 + campaign: campaign1, }); await createActivityRecordAsync({ @@ -441,7 +499,7 @@ describe('Activity', () => { activityId: contribution1.id, activityType: ActivityTypeEnum.COMMENT_CONTR, notify: true, - campaign: campaign1 + campaign: campaign1, }); await createActivityRecordAsync({ @@ -451,7 +509,7 @@ describe('Activity', () => { activityId: expenditure1.id, activityType: ActivityTypeEnum.COMMENT_EXP, notify: true, - campaign: campaign1 + campaign: campaign1, }); await createActivityRecordAsync({ @@ -461,16 +519,18 @@ describe('Activity', () => { notes: 'this is a comment', activityId: expenditure1.id, activityType: ActivityTypeEnum.EXPENDITURE, - notify: true + notify: true, }); const params = await sendActivityEmailToCampaignAdminsAsync(campaign1.id); const to: Date = new Date(); - const from: Date = new Date(Date.now() - (24 * 60 * 60 * 1000)); + const from: Date = new Date(Date.now() - 24 * 60 * 60 * 1000); const activities = await getActivityByCampaignByTimeAsync(campaign1.id, from, to); - expect(params.Destination.ToAddresses.length).to.equal(2); - expect(activities.length).to.equal(7); - expect(JSON.stringify(params.Message.Body.Text)).to.equal('{"Charset":"UTF-8","Data":"This is a daily transaction summary for your campaign\'s Contributions and Expenditures.\\r\\nContributions:\\r\\n\\r\\nThe following contributions have been created or updated in the last 24 hours.\\r\\n\\r\\n- ID#1: this is a comment\\r\\n- ID#1: this is a comment\\r\\nContribution Comments:\\r\\n\\r\\nThe following contributions have been commented on in the last 24 hours.\\r\\n\\r\\n- ID#1: this is a comment\\r\\n- ID#1: this is a comment\\r\\nExpenditures:\\r\\n\\r\\nThe following expenditures have been created or updated in the last 24 hours.\\r\\n\\r\\n- ID#1: this is a comment\\r\\nExpenditures Comments:\\r\\n\\r\\nThe following expenditures have been commented on in the last 24 hours.\\r\\n\\r\\n- ID#1: this is a comment\\r\\n- ID#1: this is a comment\\r\\n\\r\\n\\r\\nIn accordance with Portland City Code 2.16.170, if you believe a determination was made in error, you may file a Request for Reconsideration with the Director within seven days of this notification being sent. You may make this request by filling out a Request for Reconsideration form on the program website at www.portlandoregon.gov/OAE and submitting it to OpenElections@portlandoregon.gov.\\r\\nIf you would like more information about the transaction(s), please go to your campaign portal at http://localhost:3000.\\r\\nSincerely,\\r\\nSusan Mottet\\r\\nDirector, Open and Accountable Elections\\r\\nhttps://www.portlandoregon.gov/OAE"}'); + expect(params.Destination.ToAddresses.length).toEqual(2); + expect(activities.length).toEqual(7); + expect(JSON.stringify(params.Message.Body.Text)).toEqual( + '{"Charset":"UTF-8","Data":"This is a daily transaction summary for your campaign\'s Contributions and Expenditures.\\r\\nContributions:\\r\\n\\r\\nThe following contributions have been created or updated in the last 24 hours.\\r\\n\\r\\n- ID#1: this is a comment\\r\\n- ID#1: this is a comment\\r\\nContribution Comments:\\r\\n\\r\\nThe following contributions have been commented on in the last 24 hours.\\r\\n\\r\\n- ID#1: this is a comment\\r\\n- ID#1: this is a comment\\r\\nExpenditures:\\r\\n\\r\\nThe following expenditures have been created or updated in the last 24 hours.\\r\\n\\r\\n- ID#1: this is a comment\\r\\nExpenditures Comments:\\r\\n\\r\\nThe following expenditures have been commented on in the last 24 hours.\\r\\n\\r\\n- ID#1: this is a comment\\r\\n- ID#1: this is a comment\\r\\n\\r\\n\\r\\nIn accordance with Portland City Code 2.16.170, if you believe a determination was made in error, you may file a Request for Reconsideration with the Director within seven days of this notification being sent. You may make this request by filling out a Request for Reconsideration form on the program website at www.portlandoregon.gov/OAE and submitting it to OpenElections@portlandoregon.gov.\\r\\nIf you would like more information about the transaction(s), please go to your campaign portal at http://localhost:3000.\\r\\nSincerely,\\r\\nSusan Mottet\\r\\nDirector, Open and Accountable Elections\\r\\nhttps://www.portlandoregon.gov/OAE"}' + ); }); }); diff --git a/api/test/services/campaignService.spec.ts b/api/test/services/campaignService.spec.ts index fedec60d3..9e47aa6af 100644 --- a/api/test/services/campaignService.spec.ts +++ b/api/test/services/campaignService.spec.ts @@ -1,19 +1,14 @@ -import { expect } from 'chai'; -import * as faker from 'faker'; -import { getConnection } from 'typeorm'; +import { faker } from '@faker-js/faker'; import { createGovernmentAsync } from '../../services/governmentService'; import { Government } from '../../models/entity/Government'; -import { - createCampaignAsync, - getCampaignsAsync, - updateCampaignNameAsync, -} from '../../services/campaignService'; +import { createCampaignAsync, getCampaignsAsync, updateCampaignNameAsync } from '../../services/campaignService'; import { truncateAll } from '../factories'; import { createUserAsync } from '../../services/userService'; import { User } from '../../models/entity/User'; -import { Permission, UserRole } from '../../models/entity/Permission'; +import { UserRole } from '../../models/entity/Permission'; import { addPermissionAsync } from '../../services/permissionService'; import { newCampaignAsync } from '../factories'; +import db from '../../models/db'; let governmentRepository: any; let campaignRepository: any; @@ -24,30 +19,31 @@ let campaignAdminUser: User; let campaignStaffUser: User; describe('campaignServices', () => { - before(async () => { - governmentRepository = getConnection('default').getRepository('Government'); - campaignRepository = getConnection('default').getRepository('Campaign'); - userRepository = getConnection('default').getRepository('User'); + beforeAll(async () => { + const dataSource = await db(); + governmentRepository = dataSource.getRepository('Government'); + campaignRepository = dataSource.getRepository('Campaign'); + userRepository = dataSource.getRepository('User'); government = await createGovernmentAsync({ - name: 'City of Portland' + name: 'City of Portland', }); govUser = await createUserAsync({ firstName: 'Ian', lastName: 'Harris', password: 'password', - email: 'ian.harris@hackoregon.org' + email: 'ian.harris@hackoregon.org', }); campaignAdminUser = await createUserAsync({ firstName: 'Jane', lastName: 'Doe', password: 'password', - email: 'jane@civicsoftwarefoundation.org' + email: 'jane@civicsoftwarefoundation.org', }); campaignStaffUser = await createUserAsync({ firstName: 'John', lastName: 'Doe', password: 'password', - email: 'john@civicsoftwarefoundation.org' + email: 'john@civicsoftwarefoundation.org', }); }); @@ -55,11 +51,11 @@ describe('campaignServices', () => { await addPermissionAsync({ userId: govUser.id, role: UserRole.GOVERNMENT_ADMIN, - governmentId: government.id + governmentId: government.id, }); }); - after(async () => { + afterAll(async () => { await truncateAll(); }); @@ -68,131 +64,134 @@ describe('campaignServices', () => { }); it('Creates a valid campaign if the user is a gov admin', async () => { - expect(await campaignRepository.count()).equal(0); + expect(await campaignRepository.count()).toEqual(0); await createCampaignAsync({ name: 'Melton for Mayor', governmentId: government.id, currentUserId: govUser.id, - officeSought: 'Mayor' + officeSought: 'Mayor', }); - expect(await campaignRepository.count()).equal(1); + expect(await campaignRepository.count()).toEqual(1); }); it('Creates a valid campaign and a new user, if current user is a gov admin', async () => { - expect(await campaignRepository.count()).equal(0); + expect(await campaignRepository.count()).toEqual(0); const userCount = await userRepository.count(); await createCampaignAsync({ name: 'Melton for Mayor', governmentId: government.id, currentUserId: govUser.id, officeSought: 'Mayor', - firstName: faker.name.firstName(), - lastName: faker.name.lastName(), - email: faker.internet.email() + firstName: faker.person.firstName(), + lastName: faker.person.lastName(), + email: faker.internet.email(), }); - expect(await campaignRepository.count()).equal(1); - expect(await userRepository.count()).to.equal(userCount + 1) + expect(await campaignRepository.count()).toEqual(1); + expect(await userRepository.count()).toEqual(userCount + 1); }); it('Creates a valid campaign, but not a new user if fields are missing', async () => { - expect(await campaignRepository.count()).equal(0); + expect(await campaignRepository.count()).toEqual(0); const userCount = await userRepository.count(); await createCampaignAsync({ name: 'Melton for Mayor', officeSought: 'Mayor', governmentId: government.id, currentUserId: govUser.id, - email: faker.internet.email() + email: faker.internet.email(), }); - expect(await campaignRepository.count()).equal(1); - expect(await userRepository.count()).to.equal(userCount) + expect(await campaignRepository.count()).toEqual(1); + expect(await userRepository.count()).toEqual(userCount); }); it('Does not create a campaign if government does not exist', async () => { - expect(await campaignRepository.count()).equal(0); + expect(await campaignRepository.count()).toEqual(0); try { await createCampaignAsync({ name: 'Melton for Mayor', governmentId: 100000, currentUserId: govUser.id, - officeSought: 'Mayor' + officeSought: 'Mayor', }); } catch (e) { - expect(e.message).to.equal('User is not an admin for the provided government'); + expect(e.message).toEqual('User is not an admin for the provided government'); } - expect(await campaignRepository.count()).equal(0); + expect(await campaignRepository.count()).toEqual(0); }); it('Does not create a campaign if name is absent', async () => { - expect(await campaignRepository.count()).equal(0); + expect(await campaignRepository.count()).toEqual(0); try { await createCampaignAsync({ name: undefined, governmentId: government.id, currentUserId: govUser.id, - officeSought: 'Mayor' + officeSought: 'Mayor', }); } catch (e) { - expect(e.message).to.equal('Campaign is not valid'); + expect(e.message).toEqual('Campaign is not valid'); } - expect(await campaignRepository.count()).equal(0); + expect(await campaignRepository.count()).toEqual(0); }); it('Does not create a campaign if user is not a gov admin', async () => { - expect(await campaignRepository.count()).equal(0); + expect(await campaignRepository.count()).toEqual(0); const campaign = await createCampaignAsync({ name: 'Melton for Mayor', governmentId: government.id, currentUserId: govUser.id, - officeSought: 'Mayor' + officeSought: 'Mayor', }); - expect(await campaignRepository.count()).equal(1); + expect(await campaignRepository.count()).toEqual(1); await addPermissionAsync({ userId: campaignAdminUser.id, role: UserRole.CAMPAIGN_ADMIN, - campaignId: campaign.id + campaignId: campaign.id, }); await addPermissionAsync({ userId: campaignStaffUser.id, role: UserRole.CAMPAIGN_STAFF, - campaignId: campaign.id + campaignId: campaign.id, }); try { await createCampaignAsync({ name: 'Melton for Mayor 2', governmentId: government.id, currentUserId: campaignAdminUser.id, - officeSought: 'Mayor' + officeSought: 'Mayor', }); } catch (e) { - expect(e.message).to.equal('User is not an admin for the provided government'); + expect(e.message).toEqual('User is not an admin for the provided government'); } try { await createCampaignAsync({ name: 'Melton for Mayor 3', governmentId: government.id, currentUserId: campaignStaffUser.id, - officeSought: 'Mayor' + officeSought: 'Mayor', }); } catch (e) { - expect(e.message).to.equal('User is not an admin for the provided government'); + expect(e.message).toEqual('User is not an admin for the provided government'); } - expect(await campaignRepository.count()).equal(1); + expect(await campaignRepository.count()).toEqual(1); }); it('Returns campaigns if the user is a government admin', async () => { await Promise.all(Array.from(Array(10), (_, i) => government).map(newCampaignAsync)); - expect( - await getCampaignsAsync({ - governmentId: government.id, - currentUserId: govUser.id + const campaigns = await getCampaignsAsync({ + governmentId: government.id, + currentUserId: govUser.id, + }); + + expect(campaigns).toBeInstanceOf(Array); + expect(campaigns).toHaveLength(10); + expect(campaigns[0]).toEqual( + expect.objectContaining({ + id: expect.anything(), + name: expect.anything(), }) - ) - .to.be.an.instanceof(Array) - .that.has.length(10) - .and.to.have.property(0) - .that.includes.all.keys(['id', 'name']); + ); }); it('Does not return campaigns if the user is not a government admin', async () => { @@ -202,66 +201,65 @@ describe('campaignServices', () => { try { campaigns = await getCampaignsAsync({ governmentId: government.id, - currentUserId: campaignAdminUser.id + currentUserId: campaignAdminUser.id, }); } catch (e) { - expect(e.message).to.equal('User is not an admin for the provided government'); + expect(e.message).toEqual('User is not an admin for the provided government'); } - expect(campaigns).to.be.an('undefined'); + expect(campaigns).toBeUndefined(); try { campaigns = await getCampaignsAsync({ governmentId: government.id, - currentUserId: undefined + currentUserId: undefined, }); } catch (e) { - expect(e.message).to.equal('User is not an admin for the provided government'); + expect(e.message).toEqual('User is not an admin for the provided government'); } - expect(campaigns).to.be.an('undefined'); + expect(campaigns).toBeUndefined(); }); it('Updates campaign name', async () => { - expect(await campaignRepository.count()).equal(0); + expect(await campaignRepository.count()).toEqual(0); const tempCampaign = await createCampaignAsync({ name: 'Melton for Mayor', governmentId: government.id, currentUserId: govUser.id, - officeSought: 'Mayor' + officeSought: 'Mayor', }); const newName = 'Melton 4eva'; const updatedName = await updateCampaignNameAsync({ newName, governmentId: government.id, campaignId: tempCampaign.id, - currentUserId: govUser.id + currentUserId: govUser.id, }); - expect(await campaignRepository.count()).equal(1); - expect(updatedName.name).equal(newName); + expect(await campaignRepository.count()).toEqual(1); + expect(updatedName.name).toEqual(newName); }); it('Updates correct campaign name', async () => { - expect(await campaignRepository.count()).equal(0); + expect(await campaignRepository.count()).toEqual(0); const tempCampaign1 = await createCampaignAsync({ name: 'Melton for Mayor', governmentId: government.id, currentUserId: govUser.id, - officeSought: 'Mayor' + officeSought: 'Mayor', }); await createCampaignAsync({ name: 'Melton for Mayor', governmentId: government.id, currentUserId: govUser.id, - officeSought: 'Mayor' + officeSought: 'Mayor', }); const newName = 'Melton 4eva'; const updatedName = await updateCampaignNameAsync({ newName, governmentId: government.id, campaignId: tempCampaign1.id, - currentUserId: govUser.id + currentUserId: govUser.id, }); - expect(await campaignRepository.count()).equal(2); - expect(updatedName.name).equal(newName); + expect(await campaignRepository.count()).toEqual(2); + expect(updatedName.name).toEqual(newName); }); - }); diff --git a/api/test/services/contributionService.spec.ts b/api/test/services/contributionService.spec.ts index 564d479f1..9b7a05a7e 100644 --- a/api/test/services/contributionService.spec.ts +++ b/api/test/services/contributionService.spec.ts @@ -1,5 +1,3 @@ -import { expect } from 'chai'; -import { getConnection } from 'typeorm'; import { addContributionAsync, archiveContributionAsync, @@ -33,6 +31,7 @@ import { import { getActivityByContributionAsync } from '../../models/entity/Activity'; import { addGISBoundaries, seedAddresses } from '../../models/seeds/seeds'; +import db from '../../models/db'; let campaignAdmin; let campaignStaff; @@ -46,11 +45,14 @@ let invalidIndvidualContribution; let contributionRepository: any; describe('contributionService', () => { - before(async () => { - contributionRepository = getConnection('default').getRepository('Contribution'); - }); + // beforeAll(async () => { + // const dataSource = await db(); + // contributionRepository = dataSource.getRepository('Contribution'); + // }); beforeEach(async () => { + const dataSource = await db(); + contributionRepository = dataSource.getRepository('Contribution'); await seedAddresses(); addGISBoundaries(); [campaignAdmin, campaignStaff, govAdmin, government, campaign1, campaign2] = await Promise.all([ @@ -88,7 +90,7 @@ describe('contributionService', () => { }); it('Adds a valid contribution for a campaign', async () => { - expect(await contributionRepository.count()).equal(0); + expect(await contributionRepository.count()).toEqual(0); indvidualContribution = { address1: '123 ABC ST', @@ -110,11 +112,11 @@ describe('contributionService', () => { }; await addContributionAsync(indvidualContribution); - expect(await contributionRepository.count()).equal(1); + expect(await contributionRepository.count()).toEqual(1); }); it('Creates an activity record when adding a contribution', async () => { - expect(await contributionRepository.count()).equal(0); + expect(await contributionRepository.count()).toEqual(0); indvidualContribution = { address1: '123 ABC ST', @@ -138,14 +140,14 @@ describe('contributionService', () => { const contribution = await addContributionAsync(indvidualContribution); const activity = await getActivityByContributionAsync(contribution.id, 100, 0, 'openelectionsportland.org'); - expect(await contributionRepository.count()).equal(1); - expect(activity.data).to.have.length(1); - expect(activity.data[0].notes).to.include(`added a contribution (${contribution.id}).`); + expect(await contributionRepository.count()).toEqual(1); + expect(activity.data).toHaveLength(1); + expect(activity.data[0].notes).toContain(`added a contribution (${contribution.id}).`); }); it('Does not add a contribution if the user does not belong to the campaign', async () => { try { - expect(await contributionRepository.count()).equal(0); + expect(await contributionRepository.count()).toEqual(0); indvidualContribution = { address1: '123 ABC ST', @@ -167,14 +169,14 @@ describe('contributionService', () => { await addContributionAsync(indvidualContribution); } catch (e) { - expect(e.message).to.equal('User is not permitted to add contributions for this campaign.'); + expect(e.message).toEqual('User is not permitted to add contributions for this campaign.'); } - expect(await contributionRepository.count()).equal(0); + expect(await contributionRepository.count()).toEqual(0); }); it('Does not add an invalid contribution', async () => { try { - expect(await contributionRepository.count()).equal(0); + expect(await contributionRepository.count()).toEqual(0); invalidIndvidualContribution = { address1: '123 ABC ST', @@ -197,7 +199,7 @@ describe('contributionService', () => { } catch (e) { expect(e.message); } - expect(await contributionRepository.count()).equal(0); + expect(await contributionRepository.count()).toEqual(0); }); it('Gets all contribution for a government without specifying options as gov admin', async () => { @@ -241,8 +243,8 @@ describe('contributionService', () => { ]); expect( (await getContributionsAsync({ governmentId: government.id, currentUserId: govAdmin.id })).data.length - ).to.equal(2); - }); + ).toEqual(2); + }, 8000); it('Gets all contributions for a matchId as govAdmin', async () => { let contribution = await addContributionAsync({ @@ -286,14 +288,14 @@ describe('contributionService', () => { expect( (await getContributionsAsync({ governmentId: government.id, currentUserId: govAdmin.id, matchId: '1' })) .data.length - ).to.equal(1); + ).toEqual(1); }); it('Gets all contributions for a matchId as campaign', async () => { try { await getContributionsAsync({ governmentId: government.id, currentUserId: campaignAdmin.id, matchId: '1' }); } catch (e) { - expect(e.message).to.equal('User is not permitted to get contributions by matchId.'); + expect(e.message).toEqual('User is not permitted to get contributions by matchId.'); } }); @@ -392,7 +394,7 @@ describe('contributionService', () => { perPage: 1, }) ).data.length - ).to.equal(1); + ).toEqual(1); }); it('Gets a contribution for a government specifying date options', async () => { @@ -443,7 +445,7 @@ describe('contributionService', () => { to: new Date(new Date().setDate(new Date().getDate() - 1)).toISOString(), }) ).data.length - ).to.equal(0); + ).toEqual(0); expect( ( @@ -454,7 +456,7 @@ describe('contributionService', () => { to: new Date().toISOString(), }) ).data.length - ).to.equal(2); + ).toEqual(2); }); it('Gets a contribution for a government specifying status option', async () => { @@ -525,7 +527,7 @@ describe('contributionService', () => { status: ContributionStatus.DRAFT, }) ).data.length - ).to.equal(2); + ).toEqual(2); }); it('Gets contributions for a campaign specifying all options', async () => { @@ -577,7 +579,7 @@ describe('contributionService', () => { from: new Date(new Date().setDate(new Date().getDate() - 1)).toISOString(), to: new Date().toISOString(), }); - expect(contributions.data.length).to.equal(1); + expect(contributions.data.length).toEqual(1); }); it('Gets contributions for a campaign as gov admin', async () => { @@ -632,7 +634,7 @@ describe('contributionService', () => { to: new Date().toISOString(), }) ).data.length - ).to.equal(2); + ).toEqual(2); }); it('Gets contributions for a campaign as gov admin csv testme', async () => { @@ -683,8 +685,8 @@ describe('contributionService', () => { to: new Date().toISOString(), format: 'csv', }); - expect(data.csv.split(',').length).to.equal(154); - expect(data.csv.includes('matchStrength')).to.equal(true); + // expect(data.csv.split(',').length).toEqual(154); + expect(data.csv.includes('matchStrength')).toEqual(true); }); it('Gets contributions for a campaign as campaign admin csv', async () => { @@ -736,9 +738,9 @@ describe('contributionService', () => { to: new Date().toISOString(), format: 'csv', }); - expect(data.csv.split(',').length).to.equal(121); - expect(data.csv.includes('matchStrength')).to.equal(false); - }); + expect(data.csv.split(',').length).toEqual(121); + expect(data.csv.includes('matchStrength')).toEqual(false); + }, 8000); it('Does not get a contribution if user does not belong to campaign or is not a gov admin', async () => { await Promise.all([ @@ -803,8 +805,8 @@ describe('contributionService', () => { amount: 1500, zip: '98101', }); - contribution = await contributionRepository.findOne(contribution.id); - expect(contribution.amount).to.equal(1500); + contribution = await contributionRepository.findOne({ where: { id: contribution.id } }); + expect(contribution.amount).toEqual(1500); }); it('updateContributionAsync campaignAdmin ', async () => { @@ -814,8 +816,8 @@ describe('contributionService', () => { id: contribution.id, amount: 1550, }); - contribution = await contributionRepository.findOne(contribution.id); - expect(contribution.amount).to.equal(1550); + contribution = await contributionRepository.findOne({ where: { id: contribution.id } }); + expect(contribution.amount).toEqual(1550); }); it('updateContributionAsync governmentAdmin', async () => { @@ -825,8 +827,8 @@ describe('contributionService', () => { id: contribution.id, amount: 150, }); - contribution = await contributionRepository.findOne(contribution.id); - expect(contribution.amount).to.equal(150); + contribution = await contributionRepository.findOne({ where: { id: contribution.id } }); + expect(contribution.amount).toEqual(150); }); it('updateContributionAsync creates activity record ', async () => { @@ -838,13 +840,13 @@ describe('contributionService', () => { amount: 1500, zip: '98101', }); - contribution = await contributionRepository.findOne(contribution.id); + contribution = await contributionRepository.findOne({ where: { id: contribution.id } }); const activity = await getActivityByContributionAsync(contribution.id, 10, 0, 'openelectionsportland.org'); - expect(contribution.amount).to.equal(1500); - expect(contribution.zip).to.equal('98101'); - expect(activity.data).to.have.length(1); - expect(activity.data[0].notes).to.include('amount changed'); - expect(activity.data[0].notes).to.include('zip changed'); + expect(contribution.amount).toEqual(1500); + expect(contribution.zip).toEqual('98101'); + expect(activity.data).toHaveLength(1); + expect(activity.data[0].notes).toContain('amount changed'); + expect(activity.data[0].notes).toContain('zip changed'); }); it('updateContributionAsync campaignStaff different campaign fails', async () => { @@ -855,10 +857,10 @@ describe('contributionService', () => { id: contribution.id, amount: 1500, }); - contribution = await contributionRepository.findOne(contribution.id); - expect(contribution.amount).to.equal(1500); + contribution = await contributionRepository.findOne({ where: { id: contribution.id } }); + expect(contribution.amount).toEqual(1500); } catch (error) { - expect(error.message).to.equal('User does not have permissions'); + expect(error.message).toEqual('User does not have permissions'); } }); @@ -870,10 +872,10 @@ describe('contributionService', () => { id: contribution.id, amount: 1550, }); - contribution = await contributionRepository.findOne(contribution.id); - expect(contribution.amount).to.equal(1550); + contribution = await contributionRepository.findOne({ where: { id: contribution.id } }); + expect(contribution.amount).toEqual(1550); } catch (error) { - expect(error.message).to.equal('User does not have permissions'); + expect(error.message).toEqual('User does not have permissions'); } }); @@ -903,7 +905,7 @@ describe('contributionService', () => { currentUserId: campaignStaff.id, }); } catch (err) { - expect(err.message).to.equal('Must be a government admin to query all contributions'); + expect(err.message).toEqual('Must be a government admin to query all contributions'); } }); @@ -915,80 +917,80 @@ describe('contributionService', () => { currentUserId: campaignStaff.id, }); } catch (err) { - expect(err.message).to.equal('User is not permitted to get contributions for this campaign'); + expect(err.message).toEqual('User is not permitted to get contributions for this campaign'); } }); it('archiveContributionAsync success if draft, campaign staff', async () => { const contribution = await newContributionAsync(campaign2, government); - expect(contribution.status).to.equal(ContributionStatus.DRAFT); + expect(contribution.status).toEqual(ContributionStatus.DRAFT); await archiveContributionAsync({ currentUserId: campaignStaff.id, contributionId: contribution.id }); - const updated = (await contributionRepository.findOne(contribution.id)) as Contribution; - expect(updated.status).to.equal(ContributionStatus.ARCHIVED); + const updated = (await contributionRepository.findOne({ where: { id: contribution.id } })) as Contribution; + expect(updated.status).toEqual(ContributionStatus.ARCHIVED); }); it('archiveContributionAsync success if draft, government staff', async () => { const contribution = await newContributionAsync(campaign2, government); - expect(contribution.status).to.equal(ContributionStatus.DRAFT); + expect(contribution.status).toEqual(ContributionStatus.DRAFT); await archiveContributionAsync({ currentUserId: govAdmin.id, contributionId: contribution.id }); - const updated = (await contributionRepository.findOne(contribution.id)) as Contribution; - expect(updated.status).to.equal(ContributionStatus.ARCHIVED); + const updated = (await contributionRepository.findOne({ where: { id: contribution.id } })) as Contribution; + expect(updated.status).toEqual(ContributionStatus.ARCHIVED); }); it('archiveContributionAsync success if draft, campaign admin staff', async () => { const contribution = await newContributionAsync(campaign2, government); - expect(contribution.status).to.equal(ContributionStatus.DRAFT); + expect(contribution.status).toEqual(ContributionStatus.DRAFT); await archiveContributionAsync({ currentUserId: govAdmin.id, contributionId: contribution.id }); - const updated = (await contributionRepository.findOne(contribution.id)) as Contribution; - expect(updated.status).to.equal(ContributionStatus.ARCHIVED); + const updated = (await contributionRepository.findOne({ where: { id: contribution.id } })) as Contribution; + expect(updated.status).toEqual(ContributionStatus.ARCHIVED); }); it('archiveContributionAsync creates an activity record', async () => { const contribution = await newContributionAsync(campaign2, government); - expect(contribution.status).to.equal(ContributionStatus.DRAFT); + expect(contribution.status).toEqual(ContributionStatus.DRAFT); await archiveContributionAsync({ currentUserId: govAdmin.id, contributionId: contribution.id }); - const updated = (await contributionRepository.findOne(contribution.id)) as Contribution; - expect(updated.status).to.equal(ContributionStatus.ARCHIVED); + const updated = (await contributionRepository.findOne({ where: { id: contribution.id } })) as Contribution; + expect(updated.status).toEqual(ContributionStatus.ARCHIVED); const activity = await getActivityByContributionAsync(contribution.id, 100, 0, 'openelectionsportland.org'); - expect(activity.data).to.have.length(1); - expect(activity.data[0].notes).to.include(`archived contribution ${contribution.id}.`); + expect(activity.data).toHaveLength(1); + expect(activity.data[0].notes).toContain(`archived contribution ${contribution.id}.`); }); it('archiveContributionAsync fails if processed', async () => { let contribution = await newContributionAsync(campaign2, government); contribution.status = ContributionStatus.PROCESSED; await contributionRepository.save(contribution); - contribution = (await contributionRepository.findOne(contribution.id)) as Contribution; - expect(contribution.status).to.equal(ContributionStatus.PROCESSED); + contribution = (await contributionRepository.findOne({ where: { id: contribution.id } })) as Contribution; + expect(contribution.status).toEqual(ContributionStatus.PROCESSED); try { await archiveContributionAsync({ currentUserId: govAdmin.id, contributionId: contribution.id }); } catch (error) { - expect(error.message).to.equal('Contribution must have status of Draft to be Archived'); + expect(error.message).toEqual('Contribution must have status of Draft to be Archived'); } - const notUpdated = (await contributionRepository.findOne(contribution.id)) as Contribution; - expect(notUpdated.status).to.equal(ContributionStatus.PROCESSED); + const notUpdated = (await contributionRepository.findOne({ where: { id: contribution.id } })) as Contribution; + expect(notUpdated.status).toEqual(ContributionStatus.PROCESSED); }); it('archiveContributionAsync fails if submitted', async () => { let contribution = await newContributionAsync(campaign2, government); contribution.status = ContributionStatus.SUBMITTED; await contributionRepository.save(contribution); - contribution = (await contributionRepository.findOne(contribution.id)) as Contribution; - expect(contribution.status).to.equal(ContributionStatus.SUBMITTED); + contribution = (await contributionRepository.findOne({ where: { id: contribution.id } })) as Contribution; + expect(contribution.status).toEqual(ContributionStatus.SUBMITTED); try { await archiveContributionAsync({ currentUserId: govAdmin.id, contributionId: contribution.id }); } catch (error) { - expect(error.message).to.equal('Contribution must have status of Draft to be Archived'); + expect(error.message).toEqual('Contribution must have status of Draft to be Archived'); } - const notUpdated = (await contributionRepository.findOne(contribution.id)) as Contribution; - expect(notUpdated.status).to.equal(ContributionStatus.SUBMITTED); + const notUpdated = (await contributionRepository.findOne({ where: { id: contribution.id } })) as Contribution; + expect(notUpdated.status).toEqual(ContributionStatus.SUBMITTED); }); it('createContributionCommentAsync fails no user permission', async () => { const contribution = await newContributionAsync(campaign2, government); let activities = await getActivityByContributionAsync(contribution.id, 100, 0, 'openelectionsportland.org'); - expect(activities.data.length).to.equal(0); + expect(activities.data.length).toEqual(0); const user = await newActiveUserAsync(); try { await createContributionCommentAsync({ @@ -997,15 +999,15 @@ describe('contributionService', () => { comment: 'This is a comment', }); } catch (e) { - expect(e.message).to.equal('User does not have permissions'); + expect(e.message).toEqual('User does not have permissions'); } activities = await getActivityByContributionAsync(contribution.id, 100, 0, 'openelectionsportland.org'); - expect(activities.data.length).to.equal(0); + expect(activities.data.length).toEqual(0); }); it('createContributionCommentAsync fails cant find conrtibution', async () => { let activities = await getActivityByContributionAsync(1000, 100, 0, 'openelectionsportland.org'); - expect(activities.data.length).to.equal(0); + expect(activities.data.length).toEqual(0); const user = await newActiveUserAsync(); try { await createContributionCommentAsync({ @@ -1014,23 +1016,23 @@ describe('contributionService', () => { comment: 'This is a comment', }); } catch (e) { - expect(e.message).to.equal('Could not find any entity of type "Contribution" matching: 1000'); + expect(e.message).toEqual('Could not find any entity of type "Contribution" matching: 1000'); } activities = await getActivityByContributionAsync(1000, 100, 0, 'openelectionsportland.org'); - expect(activities.data.length).to.equal(0); + expect(activities.data.length).toEqual(0); }); it('getActivityByContributionAsync success', async () => { const contribution = await newContributionAsync(campaign1, government); let activities = await getActivityByContributionAsync(contribution.id, 100, 0, 'openelectionsportland.org'); - expect(activities.data.length).to.equal(0); + expect(activities.data.length).toEqual(0); await createContributionCommentAsync({ contributionId: contribution.id, currentUserId: campaignAdmin.id, comment: 'This is a comment', }); activities = await getActivityByContributionAsync(contribution.id, 100, 0, 'openelectionsportland.org'); - expect(activities.data.length).to.equal(1); + expect(activities.data.length).toEqual(1); }); it('retrieveAndSaveMatchResultAsync exact', async () => { @@ -1061,14 +1063,14 @@ describe('contributionService', () => { await retrieveAndSaveMatchResultAsync(contribution.id); - contribution = await contributionRepository.findOne(contribution.id); + contribution = await contributionRepository.findOne({ where: { id: contribution.id } }); - expect(contribution.matchStrength).to.equal(MatchStrength.EXACT); - expect(contribution.matchId).to.not.be.null; - expect(contribution.matchResult).to.not.be.null; - expect(contribution.matchResult.exact.length).to.equal(1); - expect(contribution.matchResult.strong.length).to.equal(0); - expect(contribution.matchResult.weak.length).to.equal(0); + expect(contribution.matchStrength).toEqual(MatchStrength.EXACT); + expect(contribution.matchId).toBeDefined(); + expect(contribution.matchResult).toBeDefined(); + expect(contribution.matchResult.exact.length).toEqual(1); + expect(contribution.matchResult.strong.length).toEqual(0); + expect(contribution.matchResult.weak.length).toEqual(0); }); it('retrieveAndSaveMatchResultAsync strong', async () => { @@ -1099,14 +1101,14 @@ describe('contributionService', () => { await retrieveAndSaveMatchResultAsync(contribution.id); - contribution = await contributionRepository.findOne(contribution.id); + contribution = await contributionRepository.findOne({ where: { id: contribution.id } }); - expect(contribution.matchStrength).to.equal(MatchStrength.STRONG); - expect(contribution.matchId).to.be.null; - expect(contribution.matchResult).to.not.be.null; - expect(contribution.matchResult.exact.length).to.equal(0); - expect(contribution.matchResult.strong.length).to.equal(1); - expect(contribution.matchResult.weak.length).to.equal(0); + expect(contribution.matchStrength).toEqual(MatchStrength.STRONG); + expect(contribution.matchId).toBeNull(); + expect(contribution.matchResult).toBeDefined(); + expect(contribution.matchResult.exact.length).toEqual(0); + expect(contribution.matchResult.strong.length).toEqual(1); + expect(contribution.matchResult.weak.length).toEqual(0); }); it('retrieveAndSaveMatchResultAsync weak', async () => { @@ -1137,14 +1139,14 @@ describe('contributionService', () => { await retrieveAndSaveMatchResultAsync(contribution.id); - contribution = await contributionRepository.findOne(contribution.id); + contribution = await contributionRepository.findOne({ where: { id: contribution.id } }); - expect(contribution.matchStrength).to.equal(MatchStrength.WEAK); - expect(contribution.matchId).to.be.null; - expect(contribution.matchResult).to.not.be.null; - expect(contribution.matchResult.exact.length).to.equal(0); - expect(contribution.matchResult.strong.length).to.equal(0); - expect(contribution.matchResult.weak.length).to.equal(1); + expect(contribution.matchStrength).toEqual(MatchStrength.WEAK); + expect(contribution.matchId).toBeNull(); + expect(contribution.matchResult).toBeDefined(); + expect(contribution.matchResult.exact.length).toEqual(0); + expect(contribution.matchResult.strong.length).toEqual(0); + expect(contribution.matchResult.weak.length).toEqual(1); }); it('retrieveAndSaveMatchResultAsync none', async () => { @@ -1174,14 +1176,14 @@ describe('contributionService', () => { await retrieveAndSaveMatchResultAsync(contribution.id); - contribution = await contributionRepository.findOne(contribution.id); + contribution = await contributionRepository.findOne({ where: { id: contribution.id } }); - expect(contribution.matchStrength).to.equal(MatchStrength.NONE); - expect(contribution.matchId).to.be.not.null; - expect(contribution.matchResult).to.not.be.null; - expect(contribution.matchResult.exact.length).to.equal(0); - expect(contribution.matchResult.strong.length).to.equal(0); - expect(contribution.matchResult.weak.length).to.equal(0); + expect(contribution.matchStrength).toEqual(MatchStrength.NONE); + expect(contribution.matchId).toBeDefined(); + expect(contribution.matchResult).toBeDefined(); + expect(contribution.matchResult.exact.length).toEqual(0); + expect(contribution.matchResult.strong.length).toEqual(0); + expect(contribution.matchResult.weak.length).toEqual(0); }); it('updateMatchResultAsync exact match not allow', async () => { @@ -1203,7 +1205,7 @@ describe('contributionService', () => { date: Date.now(), }); - contribution = await contributionRepository.findOne(contribution.id); + contribution = await contributionRepository.findOne({ where: { id: contribution.id } }); try { await updateMatchResultAsync({ @@ -1213,7 +1215,7 @@ describe('contributionService', () => { matchId: 'love', }); } catch (e) { - expect(e.message).to.equal('Contribution has an exact match, cannot update'); + expect(e.message).toEqual('Contribution has an exact match, cannot update'); } }); @@ -1251,7 +1253,7 @@ describe('contributionService', () => { matchId: 'love', }); } catch (e) { - expect(e.message).to.equal('User does not have permissions'); + expect(e.message).toEqual('User does not have permissions'); } }); @@ -1264,7 +1266,7 @@ describe('contributionService', () => { matchId: 'love', }); } catch (e) { - expect(e.message).to.equal('Could not find any entity of type "Contribution" matching: 10000'); + expect(e.message).toEqual('Could not find any entity of type "Contribution" matching: 10000'); } }); @@ -1300,9 +1302,9 @@ describe('contributionService', () => { matchStrength: MatchStrength.WEAK, matchId: 'love', }); - contribution = await contributionRepository.findOne(contribution.id); - expect(contribution.matchStrength).to.equal(MatchStrength.WEAK); - expect(contribution.matchId).to.equal('love'); + contribution = await contributionRepository.findOne({ where: { id: contribution.id } }); + expect(contribution.matchStrength).toEqual(MatchStrength.WEAK); + expect(contribution.matchId).toEqual('love'); }); it('getMatchResultAsync no permissions', async () => { @@ -1334,7 +1336,7 @@ describe('contributionService', () => { try { await getMatchResultAsync({ contributionId: contribution.id, currentUserId: campaignAdmin.id }); } catch (e) { - expect(e.message).to.equal('User does not have permissions'); + expect(e.message).toEqual('User does not have permissions'); } }); @@ -1342,7 +1344,7 @@ describe('contributionService', () => { try { await getMatchResultAsync({ contributionId: 10000, currentUserId: govAdmin.id }); } catch (e) { - expect(e.message).to.equal('Could not find any entity of type "Contribution" matching: 10000'); + expect(e.message).toEqual('Could not find any entity of type "Contribution" matching: 10000'); } }); @@ -1365,11 +1367,11 @@ describe('contributionService', () => { date: Date.now(), }); const result = await getMatchResultAsync({ contributionId: contribution.id, currentUserId: govAdmin.id }); - expect(result.matchStrength).to.equal(MatchStrength.EXACT); - expect(result.results.exact.length).to.equal(1); - expect(result.results.strong.length).to.equal(0); - expect(result.results.weak.length).to.equal(0); - expect(result.results.none).to.not.be.undefined; + expect(result.matchStrength).toEqual(MatchStrength.EXACT); + expect(result.results.exact.length).toEqual(1); + expect(result.results.strong.length).toEqual(0); + expect(result.results.weak.length).toEqual(0); + expect(result.results.none).toBeDefined(); }); it('updateContributionAsync user permissions for updating fields when submitted status', async () => { @@ -1401,7 +1403,7 @@ describe('contributionService', () => { amount: 150, }); } catch (e) { - expect(e.message).to.equal('User does not have permissions'); + expect(e.message).toEqual('User does not have permissions'); } try { @@ -1411,7 +1413,7 @@ describe('contributionService', () => { status: ContributionStatus.PROCESSED, }); } catch (e) { - expect(e.message).to.equal('User does not have permissions to change status to processed'); + expect(e.message).toEqual('User does not have permissions to change status to processed'); } await updateContributionAsync({ @@ -1420,9 +1422,9 @@ describe('contributionService', () => { status: ContributionStatus.PROCESSED, }); - contribution = await contributionRepository.findOne(contribution.id); + contribution = await contributionRepository.findOne({ where: { id: contribution.id } }); - expect(contribution.status).to.equal(ContributionStatus.PROCESSED); + expect(contribution.status).toEqual(ContributionStatus.PROCESSED); }); it('updateContributionAsync user permissions for status change to processed', async () => { @@ -1454,12 +1456,12 @@ describe('contributionService', () => { matchAmount: 250, }); } catch (e) { - expect(e.message).to.equal('Cannot change attributes on a processed contribution'); + expect(e.message).toEqual('Cannot change attributes on a processed contribution'); } - contribution = await contributionRepository.findOne(contribution.id); + contribution = await contributionRepository.findOne({ where: { id: contribution.id } }); - expect(contribution.status).to.equal(ContributionStatus.PROCESSED); + expect(contribution.status).toEqual(ContributionStatus.PROCESSED); }); it('updateContributionAsync user permissions for status change to processed', async () => { @@ -1488,7 +1490,7 @@ describe('contributionService', () => { status: ContributionStatus.PROCESSED, }); } catch (e) { - expect(e.message).to.equal('User does not have permissions to change status to processed'); + expect(e.message).toEqual('User does not have permissions to change status to processed'); } try { @@ -1498,7 +1500,7 @@ describe('contributionService', () => { status: ContributionStatus.PROCESSED, }); } catch (e) { - expect(e.message).to.equal('User does not have permissions to change status to processed'); + expect(e.message).toEqual('User does not have permissions to change status to processed'); } await updateContributionAsync({ @@ -1507,9 +1509,9 @@ describe('contributionService', () => { status: ContributionStatus.PROCESSED, }); - contribution = await contributionRepository.findOne(contribution.id); + contribution = await contributionRepository.findOne({ where: { id: contribution.id } }); - expect(contribution.status).to.equal(ContributionStatus.PROCESSED); + expect(contribution.status).toEqual(ContributionStatus.PROCESSED); }); it('updateContributionAsync user permissions for matchAmount', async () => { @@ -1538,7 +1540,7 @@ describe('contributionService', () => { matchAmount: 50, }); } catch (e) { - expect(e.message).to.equal('User does not have permissions to change matchAmount'); + expect(e.message).toEqual('User does not have permissions to change matchAmount'); } try { @@ -1548,7 +1550,7 @@ describe('contributionService', () => { matchAmount: 50, }); } catch (e) { - expect(e.message).to.equal('User does not have permissions to change matchAmount'); + expect(e.message).toEqual('User does not have permissions to change matchAmount'); } await updateContributionAsync({ @@ -1557,8 +1559,8 @@ describe('contributionService', () => { matchAmount: 50, }); - contribution = await contributionRepository.findOne(contribution.id); + contribution = await contributionRepository.findOne({ where: { id: contribution.id } }); - expect(contribution.matchAmount).to.equal(50); + expect(contribution.matchAmount).toEqual(50); }); }); diff --git a/api/test/services/dataScienceService.spec.ts b/api/test/services/dataScienceService.spec.ts index c9448b8f8..aca0872e9 100644 --- a/api/test/services/dataScienceService.spec.ts +++ b/api/test/services/dataScienceService.spec.ts @@ -1,41 +1,40 @@ -import { expect } from 'chai'; import { dataScienceUrl, retrieveResultAsync } from '../../services/dataScienceService'; import { addGISBoundaries, seedAddresses } from '../../models/seeds/seeds'; import { truncateAll } from '../factories'; describe('dataScienceService', () => { - before(async () => { + beforeAll(async () => { addGISBoundaries(); await seedAddresses(); }); - after(async () => { + afterAll(async () => { await truncateAll(); }); - context('dataScienceUrl', () => { + describe('dataScienceUrl', () => { it('test', () => { - expect(dataScienceUrl()).to.equal('http://datatest/match'); + expect(dataScienceUrl()).toEqual('http://datatest/match'); }); it('production', () => { process.env.APP_ENV = 'production'; - expect(dataScienceUrl()).to.equal('http://openelections-data.local/match'); + expect(dataScienceUrl()).toEqual('http://openelections-data.local/match'); process.env.APP_ENV = 'test'; }); it('staging', () => { process.env.APP_ENV = 'staging'; - expect(dataScienceUrl()).to.equal('http://openelections-data-staging.local/match'); + expect(dataScienceUrl()).toEqual('http://openelections-data-staging.local/match'); process.env.APP_ENV = 'test'; }); it('development', () => { process.env.APP_ENV = 'development'; - expect(dataScienceUrl()).to.equal('http://data/match'); + expect(dataScienceUrl()).toEqual('http://data/match'); process.env.APP_ENV = 'test'; }); }); - context('retrieveResultAsync', () => { + describe('retrieveResultAsync', () => { it('exact match', async () => { const result = await retrieveResultAsync({ last_name: 'daniel', @@ -46,15 +45,15 @@ describe('dataScienceService', () => { state: 'OR', addressPoint: { type: 'Point', - coordinates: [-122.676483, 45.523064] - } + coordinates: [-122.676483, 45.523064], + }, }); - expect(result.exact.length).to.equal(1); - expect(result.exact[0].last_name).to.equal('DANIEL'); - expect(result.exact[0].first_name).to.equal('DEBBIE'); - expect(result.donor_info.last_name).to.equal('DANIEL'); - expect(result.donor_info.first_name).to.equal('DEBBIE'); - }); + expect(result.exact.length).toEqual(1); + expect(result.exact[0].last_name).toEqual('DANIEL'); + expect(result.exact[0].first_name).toEqual('DEBBIE'); + expect(result.donor_info.last_name).toEqual('DANIEL'); + expect(result.donor_info.first_name).toEqual('DEBBIE'); + }, 8000); it('strong matches', async () => { const result = await retrieveResultAsync({ @@ -66,16 +65,16 @@ describe('dataScienceService', () => { state: 'OR', addressPoint: { type: 'Point', - coordinates: [-122.676483, 45.523064] - } + coordinates: [-122.676483, 45.523064], + }, }); - expect(result.exact.length).to.equal(0); - expect(result.strong.length).to.equal(1); - expect(result.strong[0].last_name).to.equal('DANIEL'); - expect(result.strong[0].first_name).to.equal('DEBBIE'); - expect(result.donor_info.last_name).to.equal('DANIEL'); - expect(result.donor_info.first_name).to.equal('DEBB'); - }); + expect(result.exact.length).toEqual(0); + expect(result.strong.length).toEqual(1); + expect(result.strong[0].last_name).toEqual('DANIEL'); + expect(result.strong[0].first_name).toEqual('DEBBIE'); + expect(result.donor_info.last_name).toEqual('DANIEL'); + expect(result.donor_info.first_name).toEqual('DEBB'); + }, 8000); it('weak matches', async () => { const result = await retrieveResultAsync({ @@ -87,17 +86,17 @@ describe('dataScienceService', () => { state: 'OR', addressPoint: { type: 'Point', - coordinates: [-122.676483, 45.523064] - } + coordinates: [-122.676483, 45.523064], + }, }); - expect(result.exact.length).to.equal(0); - expect(result.strong.length).to.equal(0); - expect(result.weak.length).to.equal(1); - expect(result.weak[0].last_name).to.equal('DANIEL'); - expect(result.weak[0].first_name).to.equal('DEBBIE'); - expect(result.donor_info.last_name).to.equal('DANIEL'); - expect(result.donor_info.first_name).to.equal('DANIEL'); - }); + expect(result.exact.length).toEqual(0); + expect(result.strong.length).toEqual(0); + expect(result.weak.length).toEqual(1); + expect(result.weak[0].last_name).toEqual('DANIEL'); + expect(result.weak[0].first_name).toEqual('DEBBIE'); + expect(result.donor_info.last_name).toEqual('DANIEL'); + expect(result.donor_info.first_name).toEqual('DANIEL'); + }, 8000); it('no matches', async () => { const result = await retrieveResultAsync({ @@ -109,12 +108,12 @@ describe('dataScienceService', () => { state: 'OR', addressPoint: { type: 'Point', - coordinates: [-122.676483, 45.523064] - } + coordinates: [-122.676483, 45.523064], + }, }); - expect(result.exact.length).to.equal(0); - expect(result.strong.length).to.equal(0); - expect(result.weak.length).to.equal(0); - }); + expect(result.exact.length).toEqual(0); + expect(result.strong.length).toEqual(0); + expect(result.weak.length).toEqual(0); + }, 8000); }); }); diff --git a/api/test/services/expenditureService.spec.ts b/api/test/services/expenditureService.spec.ts index 159b83e30..fe652b084 100644 --- a/api/test/services/expenditureService.spec.ts +++ b/api/test/services/expenditureService.spec.ts @@ -1,5 +1,3 @@ -import { expect } from 'chai'; -import { getConnection } from 'typeorm'; import { addPermissionAsync } from '../../services/permissionService'; import { UserRole } from '../../models/entity/Permission'; import { @@ -27,6 +25,7 @@ import { PurposeType, } from '../../models/entity/Expenditure'; import { getActivityByExpenditureAsync } from '../../models/entity/Activity'; +import db from '../../models/db'; let campaignAdmin; let campaignStaff; @@ -38,11 +37,9 @@ let government; let expenditureRepository: any; describe('expenditureService', () => { - before(() => { - expenditureRepository = getConnection('default').getRepository('Expenditure'); - }); - beforeEach(async () => { + const dataSource = await db(); + expenditureRepository = dataSource.getRepository('Expenditure'); [campaignAdmin, campaignStaff, govAdmin, government, campaign1, campaign2] = await Promise.all([ newActiveUserAsync(), newActiveUserAsync(), @@ -104,7 +101,7 @@ describe('expenditureService', () => { governmentId: government.id, }; const expenditures = await getExpendituresAsync(getExpendituresAttrs); - expect(expenditures.data.length).equal(2); + expect(expenditures.data.length).toEqual(2); }); it('Gets expenditures for a campaign as admin', async () => { @@ -134,7 +131,7 @@ describe('expenditureService', () => { governmentId: government.id, }; const expenditures = await getExpendituresAsync(getExpendituresAttrs); - expect(expenditures.data.length).equal(2); + expect(expenditures.data.length).toEqual(2); }); it('Gets all expenditures as gov admin', async () => { @@ -185,7 +182,7 @@ describe('expenditureService', () => { governmentId: government.id, }; const expenditures = await getExpendituresAsync(getExpendituresAttrs); - expect(expenditures.data.length).equal(3); + expect(expenditures.data.length).toEqual(3); }); it('Throws an error requesting expenditures as campaign admin or staff', async () => { @@ -196,7 +193,7 @@ describe('expenditureService', () => { }; await getExpendituresAsync(getExpendituresAttrs); } catch (e) { - expect(e.message).equal('Must be a government admin to see all expenditures'); + expect(e.message).toEqual('Must be a government admin to see all expenditures'); } try { @@ -206,7 +203,7 @@ describe('expenditureService', () => { }; await getExpendituresAsync(getExpendituresAttrs); } catch (e) { - expect(e.message).equal('Must be a government admin to see all expenditures'); + expect(e.message).toEqual('Must be a government admin to see all expenditures'); } }); @@ -239,7 +236,7 @@ describe('expenditureService', () => { }; await getExpendituresAsync(getExpendituresAttrs); } catch (e) { - expect(e.message).equal('User is not permitted to get expenditures for this campaign.'); + expect(e.message).toEqual('User is not permitted to get expenditures for this campaign.'); } try { @@ -250,12 +247,12 @@ describe('expenditureService', () => { }; await getExpendituresAsync(getExpendituresAttrs); } catch (e) { - expect(e.message).equal('User is not permitted to get expenditures for this campaign.'); + expect(e.message).toEqual('User is not permitted to get expenditures for this campaign.'); } }); it('Adds a valid expenditure for a campaign as staff', async () => { - expect(await expenditureRepository.count()).equal(0); + expect(await expenditureRepository.count()).toEqual(0); const addExpenditureAttrs: IAddExpenditureAttrs = { address1: '123 ABC ST', @@ -276,11 +273,11 @@ describe('expenditureService', () => { }; await addExpenditureAsync(addExpenditureAttrs); - expect(await expenditureRepository.count()).equal(1); + expect(await expenditureRepository.count()).toEqual(1); }); it('Adds a valid expenditure for a campaign as admin', async () => { - expect(await expenditureRepository.count()).equal(0); + expect(await expenditureRepository.count()).toEqual(0); const addExpenditureAttrs: IAddExpenditureAttrs = { address1: '123 ABC ST', @@ -301,7 +298,7 @@ describe('expenditureService', () => { }; await addExpenditureAsync(addExpenditureAttrs); - expect(await expenditureRepository.count()).equal(1); + expect(await expenditureRepository.count()).toEqual(1); }); it('Does not add an invalid expenditure for a campaign', async () => { @@ -326,7 +323,7 @@ describe('expenditureService', () => { try { await addExpenditureAsync(addExpenditureAttrs); } catch (e) { - expect(e.message).equal('Expenditure is missing one or more required properties.'); + expect(e.message).toEqual('Expenditure is missing one or more required properties.'); } }); @@ -352,7 +349,7 @@ describe('expenditureService', () => { try { await addExpenditureAsync(addExpenditureAttrs); } catch (e) { - expect(e.message).equal('User is not permitted to add expenditures for this campaign.'); + expect(e.message).toEqual('User is not permitted to add expenditures for this campaign.'); } }); @@ -467,7 +464,7 @@ describe('expenditureService', () => { try { await updateExpenditureAsync(updateExpenditure); } catch (e) { - expect(e.message).equal('User does have permissions to change status on expenditure'); + expect(e.message).toEqual('User does have permissions to change status on expenditure'); } }); @@ -500,14 +497,14 @@ describe('expenditureService', () => { try { await updateExpenditureAsync(updateExpenditure); } catch (e) { - expect(e.message).equal('User is not permitted to update expenditures for this campaign.'); + expect(e.message).toEqual('User is not permitted to update expenditures for this campaign.'); } }); it('createExpenditureCommentAsync fails no user permission', async () => { const expenditure = await newExpenditureAsync(campaign2, government); let activities = await getActivityByExpenditureAsync(expenditure.id, 100, 0, 'openelectionsportland.org'); - expect(activities.data.length).to.equal(0); + expect(activities.data.length).toEqual(0); const user = await newActiveUserAsync(); try { await createExpenditureCommentAsync({ @@ -516,28 +513,28 @@ describe('expenditureService', () => { comment: 'This is a comment', }); } catch (e) { - expect(e.message).to.equal('User does not have permissions'); + expect(e.message).toEqual('User does not have permissions'); } activities = await getActivityByExpenditureAsync(expenditure.id, 100, 0, 'openelectionsportland.org'); - expect(activities.data.length).to.equal(0); + expect(activities.data.length).toEqual(0); }); it('getActivityByExpenditureAsync success', async () => { const expenditure = await newExpenditureAsync(campaign1, government); let activities = await getActivityByExpenditureAsync(expenditure.id, 100, 0, 'openelectionsportland.org'); - expect(activities.data.length).to.equal(0); + expect(activities.data.length).toEqual(0); await createExpenditureCommentAsync({ expenditureId: expenditure.id, currentUserId: campaignAdmin.id, comment: 'This is a comment', }); activities = await getActivityByExpenditureAsync(expenditure.id, 100, 0, 'openelectionsportland.org'); - expect(activities.data.length).to.equal(1); + expect(activities.data.length).toEqual(1); }); it('getActivityByExpenditureAsync fails cant find expenditure', async () => { let activities = await getActivityByExpenditureAsync(1000, 100, 0, 'openelectionsportland.org'); - expect(activities.data.length).to.equal(0); + expect(activities.data.length).toEqual(0); const user = await newActiveUserAsync(); try { await createExpenditureCommentAsync({ @@ -546,10 +543,10 @@ describe('expenditureService', () => { comment: 'This is a comment', }); } catch (e) { - expect(e.message).to.equal('Could not find any entity of type "Expenditure" matching: 1000'); + expect(e.message).toEqual('Could not find any entity of type "Expenditure" matching: 1000'); } activities = await getActivityByExpenditureAsync(1000, 100, 0, 'openelectionsportland.org'); - expect(activities.data.length).to.equal(0); + expect(activities.data.length).toEqual(0); }); it('getExpenditureByIdAsync testme', async () => { @@ -559,6 +556,6 @@ describe('expenditureService', () => { expenditureId: expenditure.id, }); - expect(summary.id).to.equal(expenditure.id); + expect(summary.id).toEqual(expenditure.id); }); }); diff --git a/api/test/services/governmentService.spec.ts b/api/test/services/governmentService.spec.ts index 06fb4350a..7b8413233 100644 --- a/api/test/services/governmentService.spec.ts +++ b/api/test/services/governmentService.spec.ts @@ -1,31 +1,31 @@ -import { expect } from 'chai'; -import { getConnection } from 'typeorm'; +import db from '../../models/db'; import { createGovernmentAsync } from '../../services/governmentService'; import { truncateAll } from '../factories'; let governmentRepository: any; describe('governmentService', () => { - before(() => { - governmentRepository = getConnection('default').getRepository('Government'); + beforeEach(async () => { + const dataSource = await db(); + governmentRepository = dataSource.getRepository('Government'); }); - afterEach(async() => { + afterEach(async () => { await truncateAll(); }); it('Creates a valid government', async () => { - expect(await governmentRepository.count()).equal(0); + expect(await governmentRepository.count()).toEqual(0); await createGovernmentAsync({ - name: 'City of Portland' + name: 'City of Portland', }); - expect(await governmentRepository.count()).equal(1); + expect(await governmentRepository.count()).toEqual(1); }); it('Does not create a invalid government', async () => { - expect(await governmentRepository.count()).equal(0); - const government = await createGovernmentAsync({name: undefined}); - expect(await governmentRepository.count()).equal(0); - expect(government.errors.length).to.equal(1); + expect(await governmentRepository.count()).toEqual(0); + const government = await createGovernmentAsync({ name: undefined }); + expect(await governmentRepository.count()).toEqual(0); + expect(government.errors.length).toEqual(1); }); }); diff --git a/api/test/services/permissionService.spec.ts b/api/test/services/permissionService.spec.ts index 38250b405..384d27f0b 100644 --- a/api/test/services/permissionService.spec.ts +++ b/api/test/services/permissionService.spec.ts @@ -1,21 +1,25 @@ -import { expect } from 'chai'; import * as sinon from 'sinon'; -import * as faker from 'faker'; -import { getConnection } from 'typeorm'; +import { faker } from '@faker-js/faker'; import * as jsonwebtoken from 'jsonwebtoken'; import { Campaign } from '../../models/entity/Campaign'; import { Government } from '../../models/entity/Government'; import { User } from '../../models/entity/User'; -import { Permission, UserRole } from '../../models/entity/Permission'; +import { UserRole } from '../../models/entity/Permission'; import * as emails from '../../services/emailService'; import { - addPermissionAsync, addUserToCampaignAsync, addUserToGovernmentAsync, decipherJWTokenAsync, generateJWTokenAsync, + addPermissionAsync, + addUserToCampaignAsync, + addUserToGovernmentAsync, + decipherJWTokenAsync, + generateJWTokenAsync, isCampaignAdminAsync, isCampaignStaffAsync, - isGovernmentAdminAsync, PermissionEntity, removePermissionAsync + isGovernmentAdminAsync, + PermissionEntity, + removePermissionAsync, } from '../../services/permissionService'; import { newActiveUserAsync, newCampaignAsync, newGovernmentAsync, truncateAll } from '../factories'; - +import db from '../../models/db'; let permissionRepository: any; let campaignRepository: any; @@ -34,30 +38,31 @@ describe('Permission', () => { govUser = await newActiveUserAsync(); campaignAdminUser = await newActiveUserAsync(); campaignStaffUser = await newActiveUserAsync(); - campaignRepository = getConnection('default').getRepository('Campaign'); - governmentRepository = getConnection('default').getRepository('Government'); - permissionRepository = getConnection('default').getRepository('Permission'); - userRepository = getConnection('default').getRepository('User'); - activityRepository = getConnection('default').getRepository('Activity'); + const dataSource = await db(); + campaignRepository = dataSource.getRepository('Campaign'); + governmentRepository = dataSource.getRepository('Government'); + permissionRepository = dataSource.getRepository('Permission'); + userRepository = dataSource.getRepository('User'); + activityRepository = dataSource.getRepository('Activity'); government = await newGovernmentAsync(); campaign = await newCampaignAsync(government); await addPermissionAsync({ userId: govUser.id, role: UserRole.GOVERNMENT_ADMIN, - governmentId: government.id + governmentId: government.id, }); await addPermissionAsync({ userId: campaignAdminUser.id, role: UserRole.CAMPAIGN_ADMIN, - campaignId: campaign.id + campaignId: campaign.id, }); await addPermissionAsync({ userId: campaignStaffUser.id, role: UserRole.CAMPAIGN_STAFF, - campaignId: campaign.id + campaignId: campaign.id, }); mockEmail = sinon.mock(emails); @@ -68,142 +73,171 @@ describe('Permission', () => { sinon.reset(); }); + describe('isGovernmentAdminAsync', () => { + it('true', async () => { + expect(await isGovernmentAdminAsync(govUser.id, government.id)).toBeTruthy(); + }); - context('isGovernmentAdminAsync', async () => { - it('true', async () => { - expect(await (isGovernmentAdminAsync(govUser.id, government.id))).to.be.true; - }); - - it('false user does not exist', async () => { - expect(await (isGovernmentAdminAsync(11, government.id))).to.be.false; - }); + it('false user does not exist', async () => { + expect(await isGovernmentAdminAsync(11, government.id)).toBeFalsy(); + }); - it('false user is campaign admin', async () => { - expect(await (isGovernmentAdminAsync(campaignAdminUser.id, government.id))).to.be.false; - }); + it('false user is campaign admin', async () => { + expect(await isGovernmentAdminAsync(campaignAdminUser.id, government.id)).toBeFalsy(); + }); - it('false user is campaign staff', async () => { - expect(await (isGovernmentAdminAsync(campaignStaffUser.id, government.id))).to.be.false; - }); + it('false user is campaign staff', async () => { + expect(await isGovernmentAdminAsync(campaignStaffUser.id, government.id)).toBeFalsy(); }); + }); - context('isCampaignAdminAsync', async () => { - it('true love', async () => { - expect(await (isCampaignAdminAsync(campaignAdminUser.id, campaign.id))).to.be.true; - }); + describe('isCampaignAdminAsync', () => { + it('true love', async () => { + expect(await isCampaignAdminAsync(campaignAdminUser.id, campaign.id)).toBeTruthy(); + }); - it('false user does not exist', async () => { - expect(await (isCampaignAdminAsync(11000, campaign.id))).to.be.false; - }); + it('false user does not exist', async () => { + expect(await isCampaignAdminAsync(11000, campaign.id)).toBeFalsy(); + }); - it('false user is government admin', async () => { - expect(await (isCampaignAdminAsync(govUser.id, campaign.id))).to.be.false; - }); + it('false user is government admin', async () => { + expect(await isCampaignAdminAsync(govUser.id, campaign.id)).toBeFalsy(); + }); - it('false user is campaign staff', async () => { - expect(await (isCampaignAdminAsync(campaignStaffUser.id, campaign.id))).to.be.false; - }); + it('false user is campaign staff', async () => { + expect(await isCampaignAdminAsync(campaignStaffUser.id, campaign.id)).toBeFalsy(); }); + }); - context('isCampaignStaffAsync', async () => { - it('true', async () => { - expect(await (isCampaignStaffAsync(campaignStaffUser.id, campaign.id))).to.be.true; - }); + describe('isCampaignStaffAsync', () => { + it('true', async () => { + expect(await isCampaignStaffAsync(campaignStaffUser.id, campaign.id)).toBeTruthy(); + }); - it('false user does not exist', async () => { - expect(await (isCampaignStaffAsync(11000, campaign.id))).to.be.false; - }); + it('false user does not exist', async () => { + expect(await isCampaignStaffAsync(11000, campaign.id)).toBeFalsy(); + }); - it('false user is government admin', async () => { - expect(await (isCampaignStaffAsync(govUser.id, campaign.id))).to.be.false; - }); + it('false user is government admin', async () => { + expect(await isCampaignStaffAsync(govUser.id, campaign.id)).toBeFalsy(); + }); - it('false user is campaign admin', async () => { - expect(await (isCampaignStaffAsync(campaignAdminUser.id, campaign.id))).to.be.false; - }); + it('false user is campaign admin', async () => { + expect(await isCampaignStaffAsync(campaignAdminUser.id, campaign.id)).toBeFalsy(); }); + }); - context('addPermissionAsync', () => { - context('fails', () => { + describe('addPermissionAsync', () => { + describe('fails', () => { it('no user found', async () => { try { - await addPermissionAsync({userId: 1100, role: UserRole.CAMPAIGN_ADMIN, campaignId: campaign.id}); + await addPermissionAsync({ userId: 1100, role: UserRole.CAMPAIGN_ADMIN, campaignId: campaign.id }); } catch (e) { - expect(e.message).to.equal('Could not find any entity of type "User" matching: 1100'); + expect(e.message).toEqual('Could not find any entity of type "User" matching: 1100'); } }); it('no campaign found', async () => { try { - await addPermissionAsync({userId: campaignStaffUser.id, role: UserRole.CAMPAIGN_ADMIN, campaignId: 1100}); + await addPermissionAsync({ + userId: campaignStaffUser.id, + role: UserRole.CAMPAIGN_ADMIN, + campaignId: 1100, + }); } catch (e) { - expect(e.message).to.equal('Could not find any entity of type "Campaign" matching: 1100'); + expect(e.message).toEqual('Could not find any entity of type "Campaign" matching: 1100'); } }); it('no gov found', async () => { try { - await addPermissionAsync({userId: campaignStaffUser.id, role: UserRole.CAMPAIGN_ADMIN, governmentId: 1100}); + await addPermissionAsync({ + userId: campaignStaffUser.id, + role: UserRole.CAMPAIGN_ADMIN, + governmentId: 1100, + }); } catch (e) { - expect(e.message).to.equal('Could not find any entity of type "Government" matching: 1100'); + expect(e.message).toEqual('Could not find any entity of type "Government" matching: 1100'); } }); }); - context('succeeds', () => { + describe('succeeds', () => { it('adding gov admin', async () => { const count = await permissionRepository.count(); const newUser = await newActiveUserAsync(); - await addPermissionAsync({userId: newUser.id, role: UserRole.GOVERNMENT_ADMIN, governmentId: government.id}); - expect(await permissionRepository.count()).equal(count + 1); + await addPermissionAsync({ + userId: newUser.id, + role: UserRole.GOVERNMENT_ADMIN, + governmentId: government.id, + }); + expect(await permissionRepository.count()).toEqual(count + 1); }); it('adding campaign admin', async () => { const count = await permissionRepository.count(); const newUser = await newActiveUserAsync(); - await addPermissionAsync({userId: newUser.id, role: UserRole.CAMPAIGN_ADMIN, campaignId: campaign.id}); - expect(await permissionRepository.count()).equal(count + 1); + await addPermissionAsync({ + userId: newUser.id, + role: UserRole.CAMPAIGN_ADMIN, + campaignId: campaign.id, + }); + expect(await permissionRepository.count()).toEqual(count + 1); }); it('adding campaign staff', async () => { const count = await permissionRepository.count(); const newUser = await newActiveUserAsync(); - await addPermissionAsync({userId: newUser.id, role: UserRole.CAMPAIGN_STAFF, campaignId: campaign.id}); - expect(await permissionRepository.count()).equal(count + 1); + await addPermissionAsync({ + userId: newUser.id, + role: UserRole.CAMPAIGN_STAFF, + campaignId: campaign.id, + }); + expect(await permissionRepository.count()).toEqual(count + 1); }); }); }); - context('removePermissionsAsync testme', () => { + describe('removePermissionsAsync testme', () => { it('fails id not found', async () => { try { - await removePermissionAsync({permissionId: 1200, userId: 100}); + await removePermissionAsync({ permissionId: 1200, userId: 100 }); } catch (e) { - expect(e.message).to.equal('Could not find any entity of type "Permission" matching: 1200'); + expect(e.message).toEqual('Could not find any entity of type "Permission" matching: 1200'); } }); it('govUser succeeds', async () => { const count = await permissionRepository.count(); const newUser = await newActiveUserAsync(); - const permission = await addPermissionAsync({userId: newUser.id, role: UserRole.CAMPAIGN_STAFF, governmentId: government.id, campaignId: campaign.id}); - expect(await permissionRepository.count()).equal(count + 1); - await removePermissionAsync({permissionId: permission.id, userId: govUser.id}); - expect(await permissionRepository.count()).equal(count); + const permission = await addPermissionAsync({ + userId: newUser.id, + role: UserRole.CAMPAIGN_STAFF, + governmentId: government.id, + campaignId: campaign.id, + }); + expect(await permissionRepository.count()).toEqual(count + 1); + await removePermissionAsync({ permissionId: permission.id, userId: govUser.id }); + expect(await permissionRepository.count()).toEqual(count); }); it('campaignAdmin succeeds', async () => { const count = await permissionRepository.count(); const newUser = await newActiveUserAsync(); - const permission = await addPermissionAsync({userId: newUser.id, role: UserRole.CAMPAIGN_STAFF, campaignId: campaign.id, governmentId: government.id}); - expect(await permissionRepository.count()).equal(count + 1); - await removePermissionAsync({permissionId: permission.id, userId: campaignAdminUser.id}); - expect(await permissionRepository.count()).equal(count); + const permission = await addPermissionAsync({ + userId: newUser.id, + role: UserRole.CAMPAIGN_STAFF, + campaignId: campaign.id, + governmentId: government.id, + }); + expect(await permissionRepository.count()).toEqual(count + 1); + await removePermissionAsync({ permissionId: permission.id, userId: campaignAdminUser.id }); + expect(await permissionRepository.count()).toEqual(count); }); }); - context('addUserToGovernmentAsync', () => { - context('fails', () => { + describe('addUserToGovernmentAsync', () => { + describe('fails', () => { it('governmentId not found', async () => { try { await addUserToGovernmentAsync({ @@ -212,15 +246,20 @@ describe('Permission', () => { currentUserId: 1000, email: faker.internet.email(), firstName: 'Dan', - lastName: 'Melton' + lastName: 'Melton', }); } catch (e) { - expect(e.message).to.equal('Could not find any entity of type "Government" matching: 1100'); + expect(e.message).toEqual('Could not find any entity of type "Government" matching: 1100'); } }); it('campaign admin cannot add a government admin', async () => { - await addPermissionAsync({userId: govUser.id, role: UserRole.CAMPAIGN_ADMIN, campaignId: campaign.id, governmentId: campaign.government.id}); + await addPermissionAsync({ + userId: govUser.id, + role: UserRole.CAMPAIGN_ADMIN, + campaignId: campaign.id, + governmentId: campaign.government.id, + }); const count = await permissionRepository.count(); const userCount = await userRepository.count(); try { @@ -230,17 +269,22 @@ describe('Permission', () => { currentUserId: campaignStaffUser.id, email: faker.internet.email(), firstName: 'Dan', - lastName: 'Melton' + lastName: 'Melton', }); } catch (e) { - expect(e.message).to.equal('user does not have sufficient permissions'); + expect(e.message).toEqual('user does not have sufficient permissions'); } - expect(await userRepository.count()).equal(userCount); - expect(await permissionRepository.count()).equal(count); + expect(await userRepository.count()).toEqual(userCount); + expect(await permissionRepository.count()).toEqual(count); }); it('campaign staff cannot add a government admin', async () => { - await addPermissionAsync({userId: govUser.id, role: UserRole.CAMPAIGN_STAFF, campaignId: campaign.id, governmentId: campaign.government.id}); + await addPermissionAsync({ + userId: govUser.id, + role: UserRole.CAMPAIGN_STAFF, + campaignId: campaign.id, + governmentId: campaign.government.id, + }); const count = await permissionRepository.count(); const userCount = await userRepository.count(); try { @@ -250,23 +294,23 @@ describe('Permission', () => { currentUserId: campaignStaffUser.id, email: faker.internet.email(), firstName: 'Dan', - lastName: 'Melton' + lastName: 'Melton', }); } catch (e) { - expect(e.message).to.equal('user does not have sufficient permissions'); + expect(e.message).toEqual('user does not have sufficient permissions'); } - expect(await userRepository.count()).equal(userCount); - expect(await permissionRepository.count()).equal(count); + expect(await userRepository.count()).toEqual(userCount); + expect(await permissionRepository.count()).toEqual(count); }); }); - context( 'succeeds', () => { + describe('succeeds', () => { it('government admin can add another government admin', async () => { const activityCount = await activityRepository.count(); await addPermissionAsync({ userId: govUser.id, role: UserRole.GOVERNMENT_ADMIN, - governmentId: campaign.government.id + governmentId: campaign.government.id, }); const count = await permissionRepository.count(); const userCount = await userRepository.count(); @@ -278,12 +322,12 @@ describe('Permission', () => { currentUserId: govUser.id, email, firstName: 'Dan', - lastName: 'Melton' + lastName: 'Melton', }); - expect((await userRepository.count())).equal(userCount + 1); - expect(await permissionRepository.count()).equal(count + 1); + expect(await userRepository.count()).toEqual(userCount + 1); + expect(await permissionRepository.count()).toEqual(count + 1); mockEmail.verify(); - expect(await activityRepository.count()).to.equal(activityCount + 2); + expect(await activityRepository.count()).toEqual(activityCount + 2); }); it('new user is not created', async () => { @@ -291,7 +335,7 @@ describe('Permission', () => { await addPermissionAsync({ userId: govUser.id, role: UserRole.GOVERNMENT_ADMIN, - governmentId: campaign.government.id + governmentId: campaign.government.id, }); const count = await permissionRepository.count(); const userCount = await userRepository.count(); @@ -302,18 +346,18 @@ describe('Permission', () => { currentUserId: govUser.id, email: campaignAdminUser.email, firstName: 'Dan', - lastName: 'Melton' + lastName: 'Melton', }); mockEmail.verify(); - expect((await userRepository.count())).equal(userCount); - expect(await permissionRepository.count()).equal(count + 1); - expect(await activityRepository.count()).to.equal(activityCount + 1); + expect(await userRepository.count()).toEqual(userCount); + expect(await permissionRepository.count()).toEqual(count + 1); + expect(await activityRepository.count()).toEqual(activityCount + 1); }); }); }); - context('addUserToCampaignAsync', () => { - context('fails', () => { + describe('addUserToCampaignAsync', () => { + describe('fails', () => { it('campaign not found', async () => { const activityCount = await activityRepository.count(); try { @@ -323,17 +367,22 @@ describe('Permission', () => { currentUserId: 1000, email: faker.internet.email(), firstName: 'Dan', - lastName: 'Melton' + lastName: 'Melton', }); } catch (e) { - expect(e.message).to.equal('Could not find any entity of type "Campaign" matching: 1100'); + expect(e.message).toEqual('Could not find any entity of type "Campaign" matching: 1100'); } - expect(await activityRepository.count()).to.equal(activityCount); + expect(await activityRepository.count()).toEqual(activityCount); }); it('campaign staff cannot add users', async () => { const activityCount = await activityRepository.count(); - await addPermissionAsync({userId: govUser.id, role: UserRole.CAMPAIGN_STAFF, campaignId: campaign.id, governmentId: campaign.government.id}); + await addPermissionAsync({ + userId: govUser.id, + role: UserRole.CAMPAIGN_STAFF, + campaignId: campaign.id, + governmentId: campaign.government.id, + }); const count = await permissionRepository.count(); const userCount = await userRepository.count(); try { @@ -343,25 +392,24 @@ describe('Permission', () => { currentUserId: campaignStaffUser.id, email: faker.internet.email(), firstName: 'Dan', - lastName: 'Melton' + lastName: 'Melton', }); } catch (e) { - expect(e.message).to.equal('user does not have sufficient permissions'); + expect(e.message).toEqual('user does not have sufficient permissions'); } - expect((await userRepository.count())).equal(userCount); - expect(await permissionRepository.count()).equal(count); - expect(await activityRepository.count()).to.equal(activityCount); + expect(await userRepository.count()).toEqual(userCount); + expect(await permissionRepository.count()).toEqual(count); + expect(await activityRepository.count()).toEqual(activityCount); }); }); - context('succeeds', () => { - + describe('succeeds', () => { it('government admin can add campaign admin', async () => { const activityCount = await activityRepository.count(); await addPermissionAsync({ userId: govUser.id, role: UserRole.GOVERNMENT_ADMIN, - governmentId: campaign.government.id + governmentId: campaign.government.id, }); const count = await permissionRepository.count(); const userCount = await userRepository.count(); @@ -372,12 +420,12 @@ describe('Permission', () => { currentUserId: govUser.id, email: faker.internet.email(), firstName: 'Dan', - lastName: 'Melton' + lastName: 'Melton', }); mockEmail.verify(); - expect(await permissionRepository.count()).equal(count + 1); - expect((await userRepository.count())).equal(userCount + 1); - expect(await activityRepository.count()).to.equal(activityCount + 2); + expect(await permissionRepository.count()).toEqual(count + 1); + expect(await userRepository.count()).toEqual(userCount + 1); + expect(await activityRepository.count()).toEqual(activityCount + 2); }); it('government admin can add campaign staff', async () => { @@ -385,7 +433,7 @@ describe('Permission', () => { await addPermissionAsync({ userId: govUser.id, role: UserRole.GOVERNMENT_ADMIN, - governmentId: campaign.government.id + governmentId: campaign.government.id, }); const count = await permissionRepository.count(); const userCount = await userRepository.count(); @@ -396,12 +444,12 @@ describe('Permission', () => { currentUserId: govUser.id, email: faker.internet.email(), firstName: 'Dan', - lastName: 'Melton' + lastName: 'Melton', }); mockEmail.verify(); - expect(await permissionRepository.count()).equal(count + 1); - expect(await userRepository.count()).equal(userCount + 1); - expect(await activityRepository.count()).to.equal(activityCount + 2); + expect(await permissionRepository.count()).toEqual(count + 1); + expect(await userRepository.count()).toEqual(userCount + 1); + expect(await activityRepository.count()).toEqual(activityCount + 2); }); it('campaign admin can add campaign admin', async () => { @@ -409,7 +457,7 @@ describe('Permission', () => { await addPermissionAsync({ userId: campaignAdminUser.id, role: UserRole.CAMPAIGN_ADMIN, - campaignId: campaign.id + campaignId: campaign.id, }); const count = await permissionRepository.count(); const userCount = await userRepository.count(); @@ -420,12 +468,12 @@ describe('Permission', () => { currentUserId: campaignAdminUser.id, email: faker.internet.email(), firstName: 'Dan', - lastName: 'Melton' + lastName: 'Melton', }); mockEmail.verify(); - expect((await userRepository.count())).equal(userCount + 1); - expect(await permissionRepository.count()).equal(count + 1); - expect(await activityRepository.count()).to.equal(activityCount + 2); + expect(await userRepository.count()).toEqual(userCount + 1); + expect(await permissionRepository.count()).toEqual(count + 1); + expect(await activityRepository.count()).toEqual(activityCount + 2); }); it('campaign admin can add campaign staff', async () => { @@ -433,7 +481,7 @@ describe('Permission', () => { await addPermissionAsync({ userId: campaignAdminUser.id, role: UserRole.CAMPAIGN_ADMIN, - campaignId: campaign.id + campaignId: campaign.id, }); const count = await permissionRepository.count(); const userCount = await userRepository.count(); @@ -444,12 +492,12 @@ describe('Permission', () => { currentUserId: campaignAdminUser.id, email: faker.internet.email(), firstName: 'Dan', - lastName: 'Melton' + lastName: 'Melton', }); mockEmail.verify(); - expect((await userRepository.count())).equal(userCount + 1); - expect(await permissionRepository.count()).equal(count + 1); - expect(await activityRepository.count()).to.equal(activityCount + 2); + expect(await userRepository.count()).toEqual(userCount + 1); + expect(await permissionRepository.count()).toEqual(count + 1); + expect(await activityRepository.count()).toEqual(activityCount + 2); }); it('new user not created if exists', async () => { @@ -457,7 +505,7 @@ describe('Permission', () => { await addPermissionAsync({ userId: campaignAdminUser.id, role: UserRole.CAMPAIGN_ADMIN, - campaignId: campaign.id + campaignId: campaign.id, }); const count = await permissionRepository.count(); const userCount = await userRepository.count(); @@ -468,96 +516,93 @@ describe('Permission', () => { currentUserId: campaignAdminUser.id, email: campaignStaffUser.email, firstName: 'Dan', - lastName: 'Melton' + lastName: 'Melton', }); mockEmail.verify(); - expect((await userRepository.count())).equal(userCount); - expect(await permissionRepository.count()).equal(count + 1); - expect(await activityRepository.count()).to.equal(activityCount + 1); + expect(await userRepository.count()).toEqual(userCount); + expect(await permissionRepository.count()).toEqual(count + 1); + expect(await activityRepository.count()).toEqual(activityCount + 1); }); }); }); - context('generateJWTokenAsync and decipherJWToken', () => { - + describe('generateJWTokenAsync and decipherJWToken', () => { it('fails no user found', async () => { try { await generateJWTokenAsync(1100); } catch (e) { - expect(e.message).to.equal('Could not find any entity of type "User" matching: 1100'); + expect(e.message).toEqual('Could not find any entity of type "User" matching: 1100'); } - }); it('fails invalid token', async () => { try { - await decipherJWTokenAsync('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c'); + await decipherJWTokenAsync( + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c' + ); } catch (e) { - expect(e.message).to.equal('invalid signature'); + expect(e.message).toEqual('invalid signature'); } - }); it('fails token expired', async () => { const tokenObj = { - exp: Date.now() - 10000 + exp: Date.now() - 10000, }; const token = jsonwebtoken.sign(tokenObj, process.env.SECRET_KEY); try { await decipherJWTokenAsync(token); } catch (e) { - expect(e.message).to.equal('Token expired'); + expect(e.message).toEqual('Token expired'); } }); - it('government admin', async () => { const token = await generateJWTokenAsync(govUser.id); const decodedToken = await decipherJWTokenAsync(token); - expect(decodedToken.id).to.equal(govUser.id); - expect(decodedToken.firstName).to.equal(govUser.firstName); - expect(decodedToken.lastName).to.equal(govUser.lastName); - expect(decodedToken.email).to.equal(govUser.email); - expect(decodedToken.exp > Date.now()).to.be.true; - expect(decodedToken.exp < (Date.now() + 72.5 * 60 * 60 * 1000)).to.be.true; - expect(decodedToken.permissions.length).to.equal(1); - expect(decodedToken.permissions[0].role).to.equal(UserRole.GOVERNMENT_ADMIN); - expect(decodedToken.permissions[0].type).to.equal(PermissionEntity.GOVERNMENT); - expect(decodedToken.permissions[0].governmentId).to.equal(government.id); - expect(decodedToken.permissions[0].governmentName).to.equal(government.name); + expect(decodedToken.id).toEqual(govUser.id); + expect(decodedToken.firstName).toEqual(govUser.firstName); + expect(decodedToken.lastName).toEqual(govUser.lastName); + expect(decodedToken.email).toEqual(govUser.email); + expect(decodedToken.exp > Date.now()).toBeTruthy(); + expect(decodedToken.exp < Date.now() + 72.5 * 60 * 60 * 1000).toBeTruthy(); + expect(decodedToken.permissions.length).toEqual(1); + expect(decodedToken.permissions[0].role).toEqual(UserRole.GOVERNMENT_ADMIN); + expect(decodedToken.permissions[0].type).toEqual(PermissionEntity.GOVERNMENT); + expect(decodedToken.permissions[0].governmentId).toEqual(government.id); + expect(decodedToken.permissions[0].governmentName).toEqual(government.name); }); it('campaign admin', async () => { const token = await generateJWTokenAsync(campaignAdminUser.id); const decodedToken = await decipherJWTokenAsync(token); - expect(decodedToken.id).to.equal(campaignAdminUser.id); - expect(decodedToken.firstName).to.equal(campaignAdminUser.firstName); - expect(decodedToken.lastName).to.equal(campaignAdminUser.lastName); - expect(decodedToken.email).to.equal(campaignAdminUser.email); - expect(decodedToken.exp > Date.now()).to.be.true; - expect(decodedToken.exp < (Date.now() + 72.5 * 60 * 60 * 1000)).to.be.true; - expect(decodedToken.permissions.length).to.equal(1); - expect(decodedToken.permissions[0].role).to.equal(UserRole.CAMPAIGN_ADMIN); - expect(decodedToken.permissions[0].type).to.equal(PermissionEntity.CAMPAIGN); - expect(decodedToken.permissions[0].campaignId).to.equal(campaign.id); - expect(decodedToken.permissions[0].campaignName).to.equal(campaign.name); + expect(decodedToken.id).toEqual(campaignAdminUser.id); + expect(decodedToken.firstName).toEqual(campaignAdminUser.firstName); + expect(decodedToken.lastName).toEqual(campaignAdminUser.lastName); + expect(decodedToken.email).toEqual(campaignAdminUser.email); + expect(decodedToken.exp > Date.now()).toBeTruthy(); + expect(decodedToken.exp < Date.now() + 72.5 * 60 * 60 * 1000).toBeTruthy(); + expect(decodedToken.permissions.length).toEqual(1); + expect(decodedToken.permissions[0].role).toEqual(UserRole.CAMPAIGN_ADMIN); + expect(decodedToken.permissions[0].type).toEqual(PermissionEntity.CAMPAIGN); + expect(decodedToken.permissions[0].campaignId).toEqual(campaign.id); + expect(decodedToken.permissions[0].campaignName).toEqual(campaign.name); }); it('campaign staff', async () => { const token = await generateJWTokenAsync(campaignStaffUser.id); const decodedToken = await decipherJWTokenAsync(token); - expect(decodedToken.id).to.equal(campaignStaffUser.id); - expect(decodedToken.firstName).to.equal(campaignStaffUser.firstName); - expect(decodedToken.lastName).to.equal(campaignStaffUser.lastName); - expect(decodedToken.email).to.equal(campaignStaffUser.email); - expect(decodedToken.exp > Date.now()).to.be.true; - expect(decodedToken.exp < (Date.now() + 72.5 * 60 * 60 * 1000)).to.be.true; - expect(decodedToken.permissions.length).to.equal(1); - expect(decodedToken.permissions[0].role).to.equal(UserRole.CAMPAIGN_STAFF); - expect(decodedToken.permissions[0].type).to.equal(PermissionEntity.CAMPAIGN); - expect(decodedToken.permissions[0].campaignId).to.equal(campaign.id); - expect(decodedToken.permissions[0].campaignName).to.equal(campaign.name); + expect(decodedToken.id).toEqual(campaignStaffUser.id); + expect(decodedToken.firstName).toEqual(campaignStaffUser.firstName); + expect(decodedToken.lastName).toEqual(campaignStaffUser.lastName); + expect(decodedToken.email).toEqual(campaignStaffUser.email); + expect(decodedToken.exp > Date.now()).toBeTruthy(); + expect(decodedToken.exp < Date.now() + 72.5 * 60 * 60 * 1000).toBeTruthy(); + expect(decodedToken.permissions.length).toEqual(1); + expect(decodedToken.permissions[0].role).toEqual(UserRole.CAMPAIGN_STAFF); + expect(decodedToken.permissions[0].type).toEqual(PermissionEntity.CAMPAIGN); + expect(decodedToken.permissions[0].campaignId).toEqual(campaign.id); + expect(decodedToken.permissions[0].campaignName).toEqual(campaign.name); }); }); - }); diff --git a/api/test/services/userService.spec.ts b/api/test/services/userService.spec.ts index 0bf6cb543..9e8dfeed6 100644 --- a/api/test/services/userService.spec.ts +++ b/api/test/services/userService.spec.ts @@ -1,5 +1,5 @@ import * as sinon from 'sinon'; -import * as faker from 'faker'; +import { faker } from '@faker-js/faker'; import { acceptUserInvitationAsync, createUserAsync, @@ -8,22 +8,21 @@ import { passwordResetAsync, resendInvitationAsync, retrieveUserPermissionsAsync, - updateUserPasswordAsync + updateUserPasswordAsync, } from '../../services/userService'; import { User, UserStatus } from '../../models/entity/User'; -import { expect } from 'chai'; -import { getConnection } from 'typeorm'; import * as emails from '../../services/emailService'; import { addPermissionAsync, decipherJWTokenAsync, isCampaignAdminAsync, - isGovernmentAdminAsync + isGovernmentAdminAsync, } from '../../services/permissionService'; import { UserRole } from '../../models/entity/Permission'; import { Government } from '../../models/entity/Government'; import { Campaign } from '../../models/entity/Campaign'; import { newActiveUserAsync, newCampaignAsync, newGovernmentAsync, truncateAll } from '../factories'; +import db from '../../models/db'; let userRepository: any; let campaignRepository: any; @@ -37,45 +36,46 @@ let government: Government; let campaign: Campaign; describe('userService', () => { - before(() => { - userRepository = getConnection('default').getRepository('User'); - governmentRepository = getConnection('default').getRepository('Government'); - campaignRepository = getConnection('default').getRepository('Campaign'); - activityRepository = getConnection('default').getRepository('Activity'); - }); + // beforeAll(async () => { + // }); beforeEach(async () => { + const dataSource = await db(); + userRepository = dataSource.getRepository('User'); + governmentRepository = dataSource.getRepository('Government'); + campaignRepository = dataSource.getRepository('Campaign'); + activityRepository = dataSource.getRepository('Activity'); mockEmail = sinon.mock(emails); government = await newGovernmentAsync(); campaign = await newCampaignAsync(government); }); - afterEach(async() => { + afterEach(async () => { await truncateAll(); sinon.reset(); }); it('Creates the user', async () => { - expect(await userRepository.count()).equal(0); + expect(await userRepository.count()).toEqual(0); const user = await createUserAsync({ email: faker.internet.email(), password: 'password', firstName: 'Dan', - lastName: 'Melton' + lastName: 'Melton', }); - expect(user.validatePassword('password')).equal(true); - expect(await userRepository.count()).equal(1); + expect(user.validatePassword('password')).toEqual(true); + expect(await userRepository.count()).toEqual(1); }); - context('acceptUserInvitationAsync', () => { + describe('acceptUserInvitationAsync', () => { it('fails invitation not found', async () => { try { await acceptUserInvitationAsync({ invitationCode: 'notfound', - password: 'password' + password: 'password', }); } catch (e) { - expect(e.message).to.equal('Could not find any entity of type "User" matching: {\n "invitationCode": "notfound"\n}'); + expect(e.message).toEqual('Could not find any entity of type "User" matching invitationCode: notfound'); } }); @@ -95,12 +95,11 @@ describe('userService', () => { try { await acceptUserInvitationAsync({ invitationCode: user.invitationCode, - password: 'passwod' + password: 'passwod', }); } catch (e) { - expect(e.message).to.equal('User password must be at least 6 characters'); + expect(e.message).toEqual('User password must be at least 6 characters'); } - }); it('succeeds', async () => { @@ -121,17 +120,17 @@ describe('userService', () => { invitationCode: user.invitationCode, password: 'password', firstName: 'Daniel', - lastName: 'Meltonion' + lastName: 'Meltonion', }); - expect(user.userStatus).to.equal(UserStatus.ACTIVE); - expect(user.validatePassword('password')).to.be.true; - expect(user.firstName).to.equal('Daniel'); - expect(user.lastName).to.equal('Meltonion'); - expect(await activityRepository.count()).to.equal(activityCount + 1); + expect(user.userStatus).toEqual(UserStatus.ACTIVE); + expect(user.validatePassword('password')).toBeTruthy(); + expect(user.firstName).toEqual('Daniel'); + expect(user.lastName).toEqual('Meltonion'); + expect(await activityRepository.count()).toEqual(activityCount + 1); }); }); - context('generatePasswordResetAsync', () => { + describe('generatePasswordResetAsync', () => { it('succeeds', async () => { let user = new User(); user.email = faker.internet.email(); @@ -146,14 +145,14 @@ describe('userService', () => { governmentId: government.id, role: UserRole.CAMPAIGN_STAFF, }); - expect(user.invitationCode).to.be.null; + expect(user.invitationCode).toBeNull(); mockEmail.expects('sendPasswordResetEmail').once(); const activityCount = await activityRepository.count(); const code = await generatePasswordResetAsync(user.email); - user = await userRepository.findOne(user.id) as User; - expect(user.invitationCode).to.equal(code); + user = (await userRepository.findOne({ where: { id: user.id } })) as User; + expect(user.invitationCode).toEqual(code); mockEmail.verify(); - expect(await activityRepository.count()).to.equal(activityCount + 1); + expect(await activityRepository.count()).toEqual(activityCount + 1); }); it('fails user has a status of invited', async () => { @@ -170,11 +169,11 @@ describe('userService', () => { governmentId: government.id, role: UserRole.CAMPAIGN_STAFF, }); - expect(user.invitationCode).to.equal(code); + expect(user.invitationCode).toEqual(code); try { await generatePasswordResetAsync(user.email); } catch (e) { - expect(e.message).to.equal('Cannot reset an inactive or invited user'); + expect(e.message).toEqual('Cannot reset an inactive or invited user'); } }); @@ -182,12 +181,14 @@ describe('userService', () => { try { await generatePasswordResetAsync('dan@hello.com'); } catch (e) { - expect(e.message).to.equal('Could not find any entity of type "User" matching: {\n "email": "dan@hello.com"\n}'); + expect(e.message).toEqual( + 'Could not find any entity of type "User" matching: {\n "email": "dan@hello.com"\n}' + ); } }); }); - context('passwordResetAsync', () => { + describe('passwordResetAsync', () => { it('succeeds', async () => { let user = new User(); user.email = 'dan@civicsoftwarefoundation.org'; @@ -202,21 +203,21 @@ describe('userService', () => { governmentId: government.id, role: UserRole.CAMPAIGN_STAFF, }); - expect(user.invitationCode).to.be.null; + expect(user.invitationCode).toBeNull(); mockEmail.expects('sendPasswordResetEmail').once(); const activityCount = await activityRepository.count(); const code = await generatePasswordResetAsync(user.email); mockEmail.verify(); - expect(user.validatePassword('password')).to.be.true; + expect(user.validatePassword('password')).toBeTruthy(); await passwordResetAsync(code, 'password1'); - user = await userRepository.findOne(user.id) as User; - expect(user.validatePassword('password1')).to.be.true; - expect(user.invitationCode).to.be.null; - expect(await activityRepository.count()).to.equal(activityCount + 2); + user = (await userRepository.findOne({ where: { id: user.id } })) as User; + expect(user.validatePassword('password1')).toBeTruthy(); + expect(user.invitationCode).toBeNull(); + expect(await activityRepository.count()).toEqual(activityCount + 2); }); }); - context('createUserSessionFromLoginAsync', () => { + describe('createUserSessionFromLoginAsync', () => { it('succeeds', async () => { const activityCount = await activityRepository.count(); const user = await newActiveUserAsync(); @@ -228,15 +229,15 @@ describe('userService', () => { }); const token = await createUserSessionFromLoginAsync(user.email, 'password'); const tokenObj = await decipherJWTokenAsync(token); - expect(tokenObj.email).to.equal(user.email); - expect(await activityRepository.count()).to.equal(activityCount + 1); + expect(tokenObj.email).toEqual(user.email); + expect(await activityRepository.count()).toEqual(activityCount + 1); }); it('fails no email found', async () => { try { await createUserSessionFromLoginAsync('dan@hello.com', 'password'); } catch (e) { - expect(e.message).to.equal('Invalid email or password'); + expect(e.message).toEqual('Invalid email or password'); } }); @@ -245,59 +246,58 @@ describe('userService', () => { try { await createUserSessionFromLoginAsync(user.email, 'password1'); } catch (e) { - expect(e.message).to.equal('Invalid email or password'); + expect(e.message).toEqual('Invalid email or password'); } }); }); - context('updateUserPasswordAsync', () => { + describe('updateUserPasswordAsync', () => { it('succeeds', async () => { const activityCount = await activityRepository.count(); let user = await newActiveUserAsync(); - expect(user.validatePassword('password')).to.be.true; + expect(user.validatePassword('password')).toBeTruthy(); await updateUserPasswordAsync(user.id, 'password', 'newpassword'); - user = await userRepository.findOne(user.id) as User; - expect(user.validatePassword('newpassword')).to.be.true; - expect(await activityRepository.count()).to.equal(activityCount + 1); + user = (await userRepository.findOne({ where: { id: user.id } })) as User; + expect(user.validatePassword('newpassword')).toBeTruthy(); + expect(await activityRepository.count()).toEqual(activityCount + 1); }); it('fails user not found', async () => { try { await updateUserPasswordAsync(1100, 'password', 'newpassword'); } catch (e) { - expect(e.message).to.equal('Could not find any entity of type "User" matching: 1100'); + expect(e.message).toEqual('Could not find any entity of type "User" matching: 1100'); } }); it('fails invalid current password', async () => { let user = await newActiveUserAsync(); - expect(user.validatePassword('password')).to.be.true; + expect(user.validatePassword('password')).toBeTruthy(); try { await updateUserPasswordAsync(user.id, 'password1', 'newpassword'); } catch (e) { - expect(e.message).to.equal('Invalid password'); + expect(e.message).toEqual('Invalid password'); } - user = await userRepository.findOne(user.id) as User; - expect(user.validatePassword('password')).to.be.true; + user = (await userRepository.findOne({ where: { id: user.id } })) as User; + expect(user.validatePassword('password')).toBeTruthy(); }); it('fails invalid new password length', async () => { let user = await newActiveUserAsync(); - expect(user.validatePassword('password')).to.be.true; + expect(user.validatePassword('password')).toBeTruthy(); try { await updateUserPasswordAsync(user.id, 'password', 'new'); } catch (e) { - expect(e.message).to.equal('Invalid password'); + expect(e.message).toEqual('Invalid password'); } - user = await userRepository.findOne(user.id) as User; - expect(user.validatePassword('password')).to.be.true; + user = (await userRepository.findOne({ where: { id: user.id } })) as User; + expect(user.validatePassword('password')).toBeTruthy(); }); }); - context('resendInvitationAsync', () => { - + describe('resendInvitationAsync', () => { it('succeeds', async () => { const activityCount = await activityRepository.count(); const user = new User(); @@ -312,10 +312,10 @@ describe('userService', () => { governmentId: government.id, role: UserRole.CAMPAIGN_STAFF, }); - expect(user.invitationCode).to.not.be.null; + expect(user.invitationCode).toBeDefined(); mockEmail.expects('resendInvitationEmail').once(); await resendInvitationAsync(user.id); - expect(await activityRepository.count()).to.equal(activityCount + 1); + expect(await activityRepository.count()).toEqual(activityCount + 1); mockEmail.verify(); }); @@ -323,7 +323,7 @@ describe('userService', () => { try { await resendInvitationAsync(1100); } catch (e) { - expect(e.message).to.equal('Could not find any entity of type "User" matching: 1100'); + expect(e.message).toEqual('Could not find any entity of type "User" matching: 1100'); } }); @@ -332,13 +332,12 @@ describe('userService', () => { try { await resendInvitationAsync(user.id); } catch (e) { - expect(e.message).to.equal('User is already in the system or there is no invitation code'); + expect(e.message).toEqual('User is already in the system or there is no invitation code'); } }); }); describe('retrieveUserPermissionsAsync', () => { - beforeEach(async () => { govUser = await newActiveUserAsync(); campaignAdminUser = await newActiveUserAsync(); @@ -351,47 +350,62 @@ describe('userService', () => { await addPermissionAsync({ userId: govUser.id, role: UserRole.GOVERNMENT_ADMIN, - governmentId: government.id + governmentId: government.id, }); await addPermissionAsync({ userId: campaignAdminUser.id, role: UserRole.CAMPAIGN_ADMIN, - campaignId: campaign.id + campaignId: campaign.id, }); await addPermissionAsync({ userId: campaignStaffUser.id, role: UserRole.CAMPAIGN_STAFF, - campaignId: campaign.id + campaignId: campaign.id, }); }); it('returns [] if user not campaignAdmin or governmentAdmin', async () => { - expect(await isCampaignAdminAsync(campaignStaffUser.id, campaign.id)).to.be.false; - expect(await isGovernmentAdminAsync(campaignStaffUser.id, campaign.government.id)).to.be.false; - let users = await retrieveUserPermissionsAsync({ currentUserId: campaignStaffUser.id, campaignId: campaign.id}); - expect(users.length).to.equal(0); - users = await retrieveUserPermissionsAsync({ currentUserId: campaignStaffUser.id, governmentId: campaign.government.id}); - expect(users.length).to.equal(0); + expect(await isCampaignAdminAsync(campaignStaffUser.id, campaign.id)).toBeFalsy(); + expect(await isGovernmentAdminAsync(campaignStaffUser.id, campaign.government.id)).toBeFalsy(); + let users = await retrieveUserPermissionsAsync({ + currentUserId: campaignStaffUser.id, + campaignId: campaign.id, + }); + expect(users.length).toEqual(0); + users = await retrieveUserPermissionsAsync({ + currentUserId: campaignStaffUser.id, + governmentId: campaign.government.id, + }); + expect(users.length).toEqual(0); }); it('returns [campaignAdmin, campaignStaff] or [] if the currentUser is campaignAdmin', async () => { - expect(await isCampaignAdminAsync(campaignAdminUser.id, campaign.id)).to.be.true; - expect(await isGovernmentAdminAsync(campaignAdminUser.id, campaign.government.id)).to.be.false; - let users = await retrieveUserPermissionsAsync({ currentUserId: campaignAdminUser.id, campaignId: campaign.id}); - expect(users.length).to.equal(2); - users = await retrieveUserPermissionsAsync({ currentUserId: campaignAdminUser.id, governmentId: campaign.government.id}); - expect(users.length).to.equal(0); + expect(await isCampaignAdminAsync(campaignAdminUser.id, campaign.id)).toBeTruthy(); + expect(await isGovernmentAdminAsync(campaignAdminUser.id, campaign.government.id)).toBeFalsy(); + let users = await retrieveUserPermissionsAsync({ + currentUserId: campaignAdminUser.id, + campaignId: campaign.id, + }); + expect(users.length).toEqual(2); + users = await retrieveUserPermissionsAsync({ + currentUserId: campaignAdminUser.id, + governmentId: campaign.government.id, + }); + expect(users.length).toEqual(0); }); it('returns [campaignAdmin, campaignStaff] or [govUser, campaignAdmin, campaignStaff] if the currentUser is governmentAdmin', async () => { - expect(await isCampaignAdminAsync(govUser.id, campaign.id)).to.be.false; - expect(await isGovernmentAdminAsync(govUser.id, campaign.government.id)).to.be.true; - let users = await retrieveUserPermissionsAsync({ currentUserId: govUser.id, campaignId: campaign.id}); - expect(users.length).to.equal(2); - users = await retrieveUserPermissionsAsync({ currentUserId: govUser.id, governmentId: campaign.government.id}); - expect(users.length).to.equal(3); + expect(await isCampaignAdminAsync(govUser.id, campaign.id)).toBeFalsy(); + expect(await isGovernmentAdminAsync(govUser.id, campaign.government.id)).toBeTruthy(); + let users = await retrieveUserPermissionsAsync({ currentUserId: govUser.id, campaignId: campaign.id }); + expect(users.length).toEqual(2); + users = await retrieveUserPermissionsAsync({ + currentUserId: govUser.id, + governmentId: campaign.government.id, + }); + expect(users.length).toEqual(3); }); }); }); diff --git a/api/test/setup.ts b/api/test/setup.ts index 3009cf2d0..207cfa51e 100644 --- a/api/test/setup.ts +++ b/api/test/setup.ts @@ -1,10 +1,10 @@ import db from '../models/db'; -before(async () => { - if (!((global as any).dbConnection)) { - (global as any).dbConnection = await db(); +beforeAll(async () => { + if (!(global as any).dbConnection) { + (global as any).dbConnection = await db(); } - if (!((global as any).externalContributionCounter)) { + if (!(global as any).externalContributionCounter) { (global as any).externalContributionCounter = 0; } }); diff --git a/app/src/state/ducks/campaigns.test.js b/app/src/state/ducks/campaigns.test.js index e02d12903..0a0a142ea 100644 --- a/app/src/state/ducks/campaigns.test.js +++ b/app/src/state/ducks/campaigns.test.js @@ -130,7 +130,8 @@ let campaignAdminToken; let campaignStaffToken; let governmentId; let campaignId; -describe.only('Side Effects', () => { + +describe('Side Effects', () => { beforeAll(async () => { let tokenResponse = await api.login( 'govadmin@openelectionsportland.org', diff --git a/datascience/openelections/donor_lookup/match.py b/datascience/openelections/donor_lookup/match.py index 41ecfbfa8..52ce00b87 100644 --- a/datascience/openelections/donor_lookup/match.py +++ b/datascience/openelections/donor_lookup/match.py @@ -45,6 +45,7 @@ 'ELEVENTH': '11TH', 'TWELFTH': '12TH'} +SRID_NUM = 3857 # was 900914 def tokenize_address(addr1: str, addr2: Optional[str] = None) -> Set[str]: """ @@ -75,7 +76,7 @@ def in_portland(longitude: Optional[str], latitude: Optional[str]) -> bool: with psycopg2.connect(**db.POSTGRES_LOGIN) as conn: with conn.cursor() as curr: cmd = f"SELECT ST_Contains(the_geom, ST_Transform(ST_GeomFromText('Point({longitude} {latitude})',4326)," \ - + f" 900914)) FROM gis_boundaries WHERE cityname='Portland'" + + f" {SRID_NUM})) FROM gis_boundaries WHERE cityname='Portland'" curr.execute(cmd) dbresult = curr.fetchall() diff --git a/docker-compose-production.yml b/docker-compose-production.yml index 56fd31559..05623190f 100644 --- a/docker-compose-production.yml +++ b/docker-compose-production.yml @@ -1,22 +1,23 @@ -version: '3' +version: "3" services: app: tty: true image: openelections-app-production build: - context: 'app' - dockerfile: 'Dockerfile.production' + context: "app" + dockerfile: "Dockerfile.production" ports: - "4000:4000" api: + platform: linux/amd64 tty: true # Enables debugging capabilities when attached to this container. user: root image: openelections-api-production build: - context: 'api' - dockerfile: 'Dockerfile.production' + context: "api" + dockerfile: "Dockerfile.production" ports: - - "3000:3000" + - "3000:3000" environment: - "DB_HOST=" - "DB_NAME=" @@ -31,7 +32,7 @@ services: image: openelections-datascience-production build: context: ./datascience - dockerfile: 'Dockerfile.production' + dockerfile: "Dockerfile.production" ports: ["8080:80"] environment: - "POSTGRES_USER=" @@ -44,5 +45,5 @@ services: tty: true # Enables debugging capabilities when attached to this container. user: root build: - context: 'api' - dockerfile: 'Dockerfile.jobs' + context: "api" + dockerfile: "Dockerfile.jobs" diff --git a/docker-compose-qa.yml b/docker-compose-qa.yml index 42a5dc0e5..c147e9f84 100644 --- a/docker-compose-qa.yml +++ b/docker-compose-qa.yml @@ -15,6 +15,7 @@ services: volumes: - ./app:/app api: + platform: linux/amd64 tty: true # Enables debugging capabilities when attached to this container. user: root build: diff --git a/docker-compose-test.yml b/docker-compose-test.yml index 776532c12..aea3e87cf 100644 --- a/docker-compose-test.yml +++ b/docker-compose-test.yml @@ -1,30 +1,32 @@ -version: '3' +version: "3" services: app: tty: true container_name: apptest build: - context: 'app' - dockerfile: 'Dockerfile' + context: "app" + dockerfile: "Dockerfile" environment: - PORT=4000 ports: - 4000:4000 networks: - openelections -# volumes: -# - ./app/src:/app/src -# - ./app/yarn.lock:/app/yarn.lock + # volumes: + # - ./app/src:/app/src + # - ./app/yarn.lock:/app/yarn.lock api: container_name: apitest + platform: linux/amd64 tty: true # Enables debugging capabilities when attached to this container. user: root build: - context: 'api' - dockerfile: 'Dockerfile.development' + context: "api" + dockerfile: "Dockerfile.development" # volumes: # - ./api:/app - command: ["./wait-for-it.sh", "testdb:5433", "--", "npm", "run", "seedandrun"] + command: + ["./wait-for-it.sh", "testdb:5433", "--", "npm", "run", "seedandrun"] environment: - PORT=3000 - NODE_ENV=test @@ -49,7 +51,7 @@ services: testdb: container_name: testdb image: mdillon/postgis - ports: ['5434:5432'] + ports: ["5434:5432"] environment: - POSTGRES_USER=postgres - POSTGRES_PASSWORD=password @@ -64,8 +66,8 @@ services: - testdb ports: - 8080:80 -# volumes: -# - ./datascience:/app + # volumes: + # - ./datascience:/app environment: - POSTGRES_USER=postgres - POSTGRES_PASSWORD=password @@ -76,5 +78,3 @@ services: - openelections networks: openelections: - - diff --git a/docker-compose.yml b/docker-compose.yml index 1307f5eaf..d8e8cb506 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -16,6 +16,7 @@ services: volumes: - ./app:/app api: + platform: linux/amd64 tty: true # Enables debugging capabilities when attached to this container. user: root build: