From 7c9125c55263bc6798da734ef9fbf1417d1d3892 Mon Sep 17 00:00:00 2001 From: Andre Meyer Date: Wed, 20 Apr 2022 14:37:32 -0700 Subject: [PATCH 01/16] Automatically set table vacuum settings on startup based on numbers of rows --- .../migrations/1.3.11/atomicassets.sql | 4 -- definitions/migrations/1.3.11/database.sql | 5 -- src/bin/filler.ts | 8 +++- src/filler/set-autovac-settings.ts | 48 +++++++++++++++++++ 4 files changed, 55 insertions(+), 10 deletions(-) delete mode 100644 definitions/migrations/1.3.11/atomicassets.sql create mode 100644 src/filler/set-autovac-settings.ts diff --git a/definitions/migrations/1.3.11/atomicassets.sql b/definitions/migrations/1.3.11/atomicassets.sql deleted file mode 100644 index 7dfbb305..00000000 --- a/definitions/migrations/1.3.11/atomicassets.sql +++ /dev/null @@ -1,4 +0,0 @@ -ALTER TABLE atomicassets_templates SET (autovacuum_vacuum_scale_factor = 0.0); -ALTER TABLE atomicassets_templates SET (autovacuum_vacuum_threshold = 100); -ALTER TABLE atomicassets_templates SET (autovacuum_analyze_scale_factor = 0.0); -ALTER TABLE atomicassets_templates SET (autovacuum_analyze_threshold = 1000); diff --git a/definitions/migrations/1.3.11/database.sql b/definitions/migrations/1.3.11/database.sql index fe81cf9e..4a631a40 100644 --- a/definitions/migrations/1.3.11/database.sql +++ b/definitions/migrations/1.3.11/database.sql @@ -3,11 +3,6 @@ select brin_summarize_new_values('contract_traces_idx_global_sequence'::regclass select brin_summarize_new_values('contract_traces_idx_created_at_time'::regclass); -ALTER TABLE contract_traces SET (autovacuum_vacuum_scale_factor = 0.0); -ALTER TABLE contract_traces SET (autovacuum_vacuum_threshold = 100000); -ALTER TABLE contract_traces SET (autovacuum_analyze_scale_factor = 0.0); -ALTER TABLE contract_traces SET (autovacuum_analyze_threshold = 1000000); - alter index contract_traces_idx_global_sequence set (autosummarize = on); alter index contract_traces_idx_created_at_time set (autosummarize = on); diff --git a/src/bin/filler.ts b/src/bin/filler.ts index 3276f389..f64d1f5b 100644 --- a/src/bin/filler.ts +++ b/src/bin/filler.ts @@ -10,6 +10,7 @@ import {IConnectionsConfig, IReaderConfig} from '../types/config'; import {upgradeDb} from '../filler/upgrade-db'; import {MetricsCollectorHandler} from '../metrics/handler'; import {Registry} from 'prom-client'; +import {setAutoVacSettings} from '../filler/set-autovac-settings'; // eslint-disable-next-line @typescript-eslint/no-var-requires const readerConfigs: IReaderConfig[] = require('../../config/readers.config.json'); @@ -50,9 +51,14 @@ if (cluster.isPrimary || cluster.isMaster) { } catch (error) { logger.error('Failed to execute migration scripts', error); - return process.exit(1); + process.exit(1); } + setAutoVacSettings(connection.database).then( + () => logger.info('Finished setting autovacuum settings'), + error => logger.error('Failed setting autovacuum settings', error) + ); + for (let i = 0; i < readerConfigs.length; i++) { // @ts-ignore const worker = cluster.fork({config_index: i}); diff --git a/src/filler/set-autovac-settings.ts b/src/filler/set-autovac-settings.ts new file mode 100644 index 00000000..870281f4 --- /dev/null +++ b/src/filler/set-autovac-settings.ts @@ -0,0 +1,48 @@ +import PostgresConnection from '../connections/postgres'; + +const settingOverrides: {[key: string]: {scale: string, threshold: number}} = { + atomicassets_templates: { + scale: '0.0', + threshold: 100, + }, +}; + +export async function setAutoVacSettings(database: PostgresConnection): Promise { + await database.query('ANALYSE'); + + const {rows} = await database.query('SELECT schemaname, relname AS tablename, n_live_tup::INT AS rows FROM pg_stat_user_tables'); + + const sql = rows.map(table => { + let scale = '0.05'; + let threshold = 50; + + if (table.rows > 1_000_00) { + scale = '0.0'; + threshold = 10_000; + } + + if (table.rows > 5_000_000) { + threshold = 100_000; + } + + if (settingOverrides[table.tablename]?.scale !== undefined) { + scale = settingOverrides[table.tablename].scale; + } + if (settingOverrides[table.tablename]?.threshold !== undefined) { + threshold = settingOverrides[table.tablename].threshold; + } + + return ` + ALTER TABLE ${table.schemaname}.${table.tablename} SET ( + autovacuum_vacuum_scale_factor = ${scale}, + autovacuum_vacuum_threshold = ${threshold}, + autovacuum_analyze_scale_factor = ${scale}, + autovacuum_analyze_threshold = ${threshold * 10}, + autovacuum_vacuum_insert_scale_factor = ${scale}, + autovacuum_vacuum_insert_threshold = ${threshold * 10} + ); + `; + }).join('\n'); + + await database.query(sql); +} From c3cd3d016a23d27192ee776671c16a2413bc7c8a Mon Sep 17 00:00:00 2001 From: Andre Meyer Date: Wed, 20 Apr 2022 14:41:05 -0700 Subject: [PATCH 02/16] Enable automatic maintenance for atomicassets_mints_idx_asset_id Reduce fillfactor for atomicassets_templates --- definitions/migrations/1.3.12/atomicassets.sql | 7 +++++++ definitions/migrations/1.3.12/database.sql | 2 ++ package.json | 2 +- 3 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 definitions/migrations/1.3.12/atomicassets.sql create mode 100644 definitions/migrations/1.3.12/database.sql diff --git a/definitions/migrations/1.3.12/atomicassets.sql b/definitions/migrations/1.3.12/atomicassets.sql new file mode 100644 index 00000000..ef09955e --- /dev/null +++ b/definitions/migrations/1.3.12/atomicassets.sql @@ -0,0 +1,7 @@ + +select brin_summarize_new_values('atomicassets_mints_idx_asset_id'::regclass); + + +alter index atomicassets_mints_idx_asset_id set (autosummarize = on); + +ALTER TABLE atomicassets_templates SET (fillfactor = 90); diff --git a/definitions/migrations/1.3.12/database.sql b/definitions/migrations/1.3.12/database.sql new file mode 100644 index 00000000..93a89ab1 --- /dev/null +++ b/definitions/migrations/1.3.12/database.sql @@ -0,0 +1,2 @@ + +UPDATE dbinfo SET "value" = '1.3.12' WHERE name = 'version'; diff --git a/package.json b/package.json index 71175902..cbcce4d2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "eosio-contract-api", - "version": "1.3.11", + "version": "1.3.12", "description": "EOSIO Contract API", "author": "pink.gg", "license": "AGPL-3.0", From fe33228d9a6259b712c27e10fa1ae9b428303bd1 Mon Sep 17 00:00:00 2001 From: Andre Meyer Date: Thu, 21 Apr 2022 08:34:29 -0700 Subject: [PATCH 03/16] Remove analyse --- src/filler/set-autovac-settings.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/filler/set-autovac-settings.ts b/src/filler/set-autovac-settings.ts index 870281f4..a9207e0f 100644 --- a/src/filler/set-autovac-settings.ts +++ b/src/filler/set-autovac-settings.ts @@ -8,8 +8,6 @@ const settingOverrides: {[key: string]: {scale: string, threshold: number}} = { }; export async function setAutoVacSettings(database: PostgresConnection): Promise { - await database.query('ANALYSE'); - const {rows} = await database.query('SELECT schemaname, relname AS tablename, n_live_tup::INT AS rows FROM pg_stat_user_tables'); const sql = rows.map(table => { From 1e3609c9b035fa1d2c5a4853ea6a8a2b419a937d Mon Sep 17 00:00:00 2001 From: Andre Meyer Date: Thu, 21 Apr 2022 08:36:37 -0700 Subject: [PATCH 04/16] Update tables individually to prevent deadlocks --- src/filler/set-autovac-settings.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/filler/set-autovac-settings.ts b/src/filler/set-autovac-settings.ts index a9207e0f..1f798557 100644 --- a/src/filler/set-autovac-settings.ts +++ b/src/filler/set-autovac-settings.ts @@ -10,7 +10,7 @@ const settingOverrides: {[key: string]: {scale: string, threshold: number}} = { export async function setAutoVacSettings(database: PostgresConnection): Promise { const {rows} = await database.query('SELECT schemaname, relname AS tablename, n_live_tup::INT AS rows FROM pg_stat_user_tables'); - const sql = rows.map(table => { + for (const table of rows) { let scale = '0.05'; let threshold = 50; @@ -30,7 +30,7 @@ export async function setAutoVacSettings(database: PostgresConnection): Promise< threshold = settingOverrides[table.tablename].threshold; } - return ` + await database.query(` ALTER TABLE ${table.schemaname}.${table.tablename} SET ( autovacuum_vacuum_scale_factor = ${scale}, autovacuum_vacuum_threshold = ${threshold}, @@ -38,9 +38,8 @@ export async function setAutoVacSettings(database: PostgresConnection): Promise< autovacuum_analyze_threshold = ${threshold * 10}, autovacuum_vacuum_insert_scale_factor = ${scale}, autovacuum_vacuum_insert_threshold = ${threshold * 10} - ); - `; - }).join('\n'); + ) + `); + } - await database.query(sql); } From 17b360408c9b01b37edaf3e5e02c33d98f497079 Mon Sep 17 00:00:00 2001 From: Andre Meyer Date: Thu, 21 Apr 2022 13:27:32 -0700 Subject: [PATCH 05/16] Remove price filters and sorting from /v1/sales endpoint --- .../atomicmarket/handlers/sales.test.ts | 52 +++++++------------ .../namespaces/atomicmarket/handlers/sales.ts | 6 ++- src/api/namespaces/atomicmarket/utils.ts | 14 ++--- src/filler/handlers/atomicmarket/index.ts | 2 +- 4 files changed, 28 insertions(+), 46 deletions(-) diff --git a/src/api/namespaces/atomicmarket/handlers/sales.test.ts b/src/api/namespaces/atomicmarket/handlers/sales.test.ts index c49de329..15896c03 100644 --- a/src/api/namespaces/atomicmarket/handlers/sales.test.ts +++ b/src/api/namespaces/atomicmarket/handlers/sales.test.ts @@ -177,42 +177,28 @@ describe('AtomicMarket Sales API', () => { .to.deep.equal([sale_id]); }); - txit('throws error when maximum price filter is set without settlement symbol', async () => { + txit('filters by minimum price', async () => { let err; try { - await getSalesIds({max_price: '1'}); + await getSalesIds({min_price: '2'}); } catch (e) { err = e; } expect(err).to.be.instanceof(ApiError); - expect(err.message).to.equal('Price range filters require the "symbol" filter'); - }); - - txit('filters by minimum price', async () => { - await client.createSale({}); - - const {sale_id} = await client.createSale({ - listing_price: 200000000, - }); - - await client.query('REFRESH MATERIALIZED VIEW atomicmarket_sale_prices'); - - expect(await getSalesIds({symbol: 'TEST', min_price: '2'})) - .to.deep.equal([sale_id]); + expect(err.message).to.equal('Price filters are removed in /v1/sales, use /v2/sales'); }); txit('filters by maximum price', async () => { - await client.createSale({ - listing_price: 200000000, - }); - - const {sale_id} = await client.createSale({}); - - await client.query('REFRESH MATERIALIZED VIEW atomicmarket_sale_prices'); + let err; + try { + await getSalesIds({max_price: '1'}); + } catch (e) { + err = e; + } - expect(await getSalesIds({symbol: 'TEST', max_price: '1'})) - .to.deep.equal([sale_id]); + expect(err).to.be.instanceof(ApiError); + expect(err.message).to.equal('Price filters are removed in /v1/sales, use /v2/sales'); }); txit('filters out seller contracts unless whitelisted', async () => { @@ -670,15 +656,15 @@ describe('AtomicMarket Sales API', () => { }); txit('orders by price', async () => { - const sale_id2 = `${client.getId()}`; - const {sale_id: sale_id1} = await client.createSale({listing_price: 2}); - - await client.createSale({listing_price: 1, sale_id: sale_id2}); - - await client.query('REFRESH MATERIALIZED VIEW atomicmarket_sale_prices'); + let err; + try { + await getSalesIds({sort: 'price'}); + } catch (e) { + err = e; + } - expect(await getSalesIds({sort: 'price'})) - .to.deep.equal([sale_id1, sale_id2]); + expect(err).to.be.instanceof(ApiError); + expect(err.message).to.equal('Sorting by price removed in /v1/sales, use /v2/sales'); }); txit('orders by template_mint', async () => { diff --git a/src/api/namespaces/atomicmarket/handlers/sales.ts b/src/api/namespaces/atomicmarket/handlers/sales.ts index 60f5f6f4..6c357eb9 100644 --- a/src/api/namespaces/atomicmarket/handlers/sales.ts +++ b/src/api/namespaces/atomicmarket/handlers/sales.ts @@ -63,11 +63,14 @@ export async function getSalesAction(params: RequestValues, ctx: AtomicMarketCon count: {type: 'bool'} }); + if (args.sort === 'price') { + throw new ApiError('Sorting by price removed in /v1/sales, use /v2/sales', 400); + } + const query = new QueryBuilder(` SELECT listing.sale_id FROM atomicmarket_sales listing JOIN atomicassets_offers offer ON (listing.assets_contract = offer.contract AND listing.offer_id = offer.offer_id) - LEFT JOIN atomicmarket_sale_prices price ON (price.market_contract = listing.market_contract AND price.sale_id = listing.sale_id) `); query.equal('listing.market_contract', ctx.coreArgs.atomicmarket_account); @@ -96,7 +99,6 @@ export async function getSalesAction(params: RequestValues, ctx: AtomicMarketCon sale_id: {column: 'listing.sale_id', nullable: false, numericIndex: true}, created: {column: 'listing.created_at_time', nullable: false, numericIndex: true}, updated: {column: 'listing.updated_at_time', nullable: false, numericIndex: true}, - price: {column: args.state === '3' ? 'listing.final_price' : 'price.price', nullable: true, numericIndex: false}, template_mint: {column: 'LOWER(listing.template_mint)', nullable: true, numericIndex: false} }; diff --git a/src/api/namespaces/atomicmarket/utils.ts b/src/api/namespaces/atomicmarket/utils.ts index 7f197d49..7342c71b 100644 --- a/src/api/namespaces/atomicmarket/utils.ts +++ b/src/api/namespaces/atomicmarket/utils.ts @@ -120,6 +120,10 @@ export function buildSaleFilter(values: FilterValues, query: QueryBuilder): void template_blacklist: {type: 'int[]', min: 1}, }); + if (args.min_price || args.max_price) { + throw new ApiError('Price filters are removed in /v1/sales, use /v2/sales', 400); + } + buildListingFilter(values, query); if (args.template_blacklist.length || hasAssetFilter(values, ['collection_name']) || hasDataFilters(values)) { @@ -171,16 +175,6 @@ export function buildSaleFilter(values: FilterValues, query: QueryBuilder): void if (args.symbol) { query.equal('listing.settlement_symbol', args.symbol); - - if (args.min_price) { - query.addCondition('price.price >= 1.0 * ' + query.addVariable(args.min_price) + ' * POWER(10, price.settlement_precision)'); - } - - if (args.max_price) { - query.addCondition('price.price <= 1.0 * ' + query.addVariable(args.max_price) + ' * POWER(10, price.settlement_precision)'); - } - } else if (args.min_price || args.max_price) { - throw new ApiError('Price range filters require the "symbol" filter'); } if (args.state) { diff --git a/src/filler/handlers/atomicmarket/index.ts b/src/filler/handlers/atomicmarket/index.ts index a7985c4f..8e5acb2d 100644 --- a/src/filler/handlers/atomicmarket/index.ts +++ b/src/filler/handlers/atomicmarket/index.ts @@ -289,7 +289,7 @@ export default class AtomicMarketHandler extends ContractHandler { {name: 'atomicmarket_template_prices', priority: JobQueuePriority.LOW}, {name: 'atomicmarket_stats_prices', priority: JobQueuePriority.LOW}, {name: 'atomicmarket_stats_markets', priority: JobQueuePriority.LOW}, - {name: 'atomicmarket_sale_prices', priority: JobQueuePriority.MEDIUM}, + {name: 'atomicmarket_sale_prices', priority: JobQueuePriority.LOW}, ]; for (const view of materializedViews) { From c1929a82bba5a21a150de4fd7ade7bb503a45b89 Mon Sep 17 00:00:00 2001 From: Andre Meyer Date: Fri, 22 Apr 2022 12:02:44 -0700 Subject: [PATCH 06/16] Tests for /v1/sales/templates --- src/api/namespaces/atomicassets/test.ts | 2 +- src/api/namespaces/atomicmarket/format.ts | 15 +- .../sales.get-sales-templates.test.ts | 425 ++++++++++++++++++ ...{sales.test.ts => sales.get-sales.test.ts} | 0 4 files changed, 432 insertions(+), 10 deletions(-) create mode 100644 src/api/namespaces/atomicmarket/handlers/sales.get-sales-templates.test.ts rename src/api/namespaces/atomicmarket/handlers/{sales.test.ts => sales.get-sales.test.ts} (100%) diff --git a/src/api/namespaces/atomicassets/test.ts b/src/api/namespaces/atomicassets/test.ts index 8a42e6d3..48b8ca9b 100644 --- a/src/api/namespaces/atomicassets/test.ts +++ b/src/api/namespaces/atomicassets/test.ts @@ -63,7 +63,7 @@ export class AtomicAssetsTestClient extends TestClient { contract: 'aatest', offer_id: values.offer_id ?? (await this.createOffer()).offer_id, owner: 'owner', - index: 0, + index: 1, asset_id: values.asset_id ?? (await this.createAsset(assetValues)).asset_id, ...values, }); diff --git a/src/api/namespaces/atomicmarket/format.ts b/src/api/namespaces/atomicmarket/format.ts index 6a71c522..4f5fc810 100644 --- a/src/api/namespaces/atomicmarket/format.ts +++ b/src/api/namespaces/atomicmarket/format.ts @@ -60,27 +60,24 @@ export function formatBuyoffer(row: any): any { } export function formatSale(row: any): any { - const data = {...row}; + const {raw_price, sale_state, offer_state, ...data} = row; - data.price.amount = row.raw_price; + data.price.amount = raw_price; - if (row.sale_state === SaleState.WAITING.valueOf()) { + if (sale_state === SaleState.WAITING.valueOf()) { data.state = SaleApiState.WAITING.valueOf(); - } else if (row.sale_state === SaleState.LISTED.valueOf() && row.offer_state === OfferState.PENDING.valueOf()) { + } else if (sale_state === SaleState.LISTED.valueOf() && offer_state === OfferState.PENDING.valueOf()) { data.state = SaleApiState.LISTED.valueOf(); - } else if (row.sale_state === SaleState.CANCELED.valueOf()) { + } else if (sale_state === SaleState.CANCELED.valueOf()) { data.state = SaleApiState.CANCELED.valueOf(); - } else if (row.sale_state === SaleState.SOLD.valueOf()) { + } else if (sale_state === SaleState.SOLD.valueOf()) { data.state = SaleApiState.SOLD.valueOf(); } else { data.state = SaleApiState.INVALID.valueOf(); } - delete data.raw_price; delete data.raw_token_symbol; delete data.raw_token_precision; - delete data.sale_state; - delete data.offer_state; return data; } diff --git a/src/api/namespaces/atomicmarket/handlers/sales.get-sales-templates.test.ts b/src/api/namespaces/atomicmarket/handlers/sales.get-sales-templates.test.ts new file mode 100644 index 00000000..d9a69bb7 --- /dev/null +++ b/src/api/namespaces/atomicmarket/handlers/sales.get-sales-templates.test.ts @@ -0,0 +1,425 @@ +import 'mocha'; +import {expect} from 'chai'; +import { getSalesTemplatesAction } from './sales'; +import {RequestValues} from '../../utils'; +import {initAtomicMarketTest} from '../test'; +import {getTestContext} from '../../../../utils/test'; + +const {client, txit} = initAtomicMarketTest(); + +async function getSalesIds(values: RequestValues): Promise> { + const testContext = getTestContext(client); + + await client.query('REFRESH MATERIALIZED VIEW atomicmarket_sale_prices'); + + const result = await getSalesTemplatesAction({ + symbol: 'TEST', + ...values, + }, testContext); + + return result.map((s: any) => s.sale_id); +} + +async function initTest(saleValues: Record = {}): Promise<{template_id: number, sale_id: number}> { + const {template_id} = await client.createTemplate(); + + const {offer_id} = await client.createOfferAsset({}, {template_id}); + const {sale_id} = await client.createSale({ + offer_id, + ...saleValues, + }); + + return { + sale_id, + template_id: (await client.createTemplate()).template_id, + }; +} + +describe('AtomicMarket Sales API', () => { + + describe('getSalesTemplatesAction', () => { + + txit('filters by settlement symbol', async () => { + const {template_id} = await initTest(); + await client.createToken({token_symbol: 'TOKEN1'}); + const {offer_id} = await client.createOfferAsset({}, {template_id}); + const {sale_id} = await client.createSale({offer_id, settlement_symbol: 'TOKEN1'}); + + expect(await getSalesIds({symbol: 'TOKEN1', burned: false})) + .to.deep.equal([sale_id]); + }); + + txit('filters by minimum price', async () => { + const {template_id} = await initTest({ + listing_price: 100000000, + }); + + const {offer_id} = await client.createOfferAsset({}, {template_id}); + const {sale_id} = await client.createSale({ + offer_id, + listing_price: 200000000, + }); + + expect(await getSalesIds({min_price: '2', burned: false})) + .to.deep.equal([sale_id]); + }); + + txit('filters by maximum price', async () => { + const {template_id} = await initTest({ + listing_price: 300000000, + }); + + const {offer_id} = await client.createOfferAsset({}, {template_id}); + const {sale_id} = await client.createSale({ + offer_id, + listing_price: 200000000, + }); + + expect(await getSalesIds({max_price: '2', burned: false})) + .to.deep.equal([sale_id]); + }); + + txit('filters by collection', async () => { + const {template_id} = await initTest(); + + const {collection_name} = await client.createCollection({collection_name: 'x'}); + + const {offer_id} = await client.createOfferAsset({}, {template_id, collection_name}); + const {sale_id} = await client.createSale({offer_id, collection_name}); + + expect(await getSalesIds({collection_name: 'x,abc'})) + .to.deep.equal([sale_id]); + }); + + txit('filters by asset_id', async () => { + const {template_id} = await initTest(); + + const {asset_id, offer_id} = await client.createOfferAsset({}, {template_id}); + const {sale_id} = await client.createSale({offer_id}); + + expect(await getSalesIds({asset_id})) + .to.deep.equal([sale_id]); + }); + + txit('only returns the first asset in a bundle', async () => { + // in new version, ignore bundles + const {template_id} = await initTest(); + + const {asset_id, offer_id} = await client.createOfferAsset({}, {template_id}); + + const {asset_id: asset_id2} = await client.createOfferAsset({offer_id, index: 2}, { + template_id: (await client.createTemplate()).template_id, + }); + + const {sale_id} = await client.createSale({offer_id}); + + expect(await getSalesIds({asset_id: `${asset_id}, ${asset_id2}`})) + .to.deep.equal([sale_id]); + }); + + txit('filters by asset owner', async () => { + const {template_id} = await initTest(); + + const {offer_id} = await client.createOfferAsset({}, {template_id, owner: 'x'}); + const {sale_id} = await client.createSale({offer_id}); + + expect(await getSalesIds({owner: 'x,abc'})) + .to.deep.equal([sale_id]); + }); + + txit('filters by asset burned', async () => { + const {template_id} = await initTest(); + + const {offer_id} = await client.createOfferAsset({}, {template_id, owner: null}); + const {sale_id} = await client.createSale({offer_id}); + + expect(await getSalesIds({burned: 'true'})) + .to.deep.equal([sale_id]); + }); + + txit('filters by asset not burned', async () => { + const {template_id, sale_id} = await initTest(); + + const {offer_id} = await client.createOfferAsset({}, {template_id, owner: null}); + await client.createSale({offer_id}); + + expect(await getSalesIds({burned: 'false'})) + .to.deep.equal([sale_id]); + }); + + txit('filters by asset template', async () => { + const {template_id} = await initTest(); + + const {offer_id} = await client.createOfferAsset({}, {template_id}); + const {sale_id} = await client.createSale({offer_id}); + + expect(await getSalesIds({template_id: `${template_id},-1`})) + .to.deep.equal([sale_id]); + }); + + txit('ignores sales without a template', async () => { + const {sale_id} = await initTest(); + + const {offer_id} = await client.createOfferAsset(); + await client.createSale({offer_id}); + + expect(await getSalesIds({burned: false})) + .to.deep.equal([sale_id]); + }); + + txit('filters by schema', async () => { + const {template_id} = await initTest(); + + const {schema_name} = await client.createSchema(); + + const {offer_id} = await client.createOfferAsset({}, {template_id, schema_name}); + const {sale_id} = await client.createSale({offer_id}); + + expect(await getSalesIds({schema_name: `${schema_name},-1`})) + .to.deep.equal([sale_id]); + }); + + txit('filters by asset being transferable', async () => { + const offer1 = await client.createOfferAsset({}, { + template_id: (await client.createTemplate({transferable: false})).template_id, + }); + await client.createSale({offer_id: offer1.offer_id}); + + const {template_id} = await client.createTemplate({transferable: true}); + const {offer_id} = await client.createOfferAsset({}, {template_id}); + const {sale_id} = await client.createSale({offer_id}); + + expect(await getSalesIds({is_transferable: 'true'})) + .to.deep.equal([sale_id]); + }); + + txit('filters by asset not being transferable', async () => { + const offer1 = await client.createOfferAsset({}, { + template_id: (await client.createTemplate({transferable: true})).template_id, + }); + await client.createSale({offer_id: offer1.offer_id}); + + const {template_id} = await client.createTemplate({transferable: false}); + const {offer_id} = await client.createOfferAsset({}, {template_id}); + const {sale_id} = await client.createSale({offer_id}); + + expect(await getSalesIds({is_transferable: 'false'})) + .to.deep.equal([sale_id]); + }); + + txit('filters by asset being burnable', async () => { + const offer1 = await client.createOfferAsset({}, { + template_id: (await client.createTemplate({burnable: false})).template_id, + }); + await client.createSale({offer_id: offer1.offer_id}); + + const {template_id} = await client.createTemplate({burnable: true}); + const {offer_id} = await client.createOfferAsset({}, {template_id}); + const {sale_id} = await client.createSale({offer_id}); + + expect(await getSalesIds({is_burnable: 'true'})) + .to.deep.equal([sale_id]); + }); + + txit('filters by asset not being burnable', async () => { + const offer1 = await client.createOfferAsset({}, { + template_id: (await client.createTemplate({burnable: true})).template_id, + }); + await client.createSale({offer_id: offer1.offer_id}); + + const {template_id} = await client.createTemplate({burnable: false}); + const {offer_id} = await client.createOfferAsset({}, {template_id}); + const {sale_id} = await client.createSale({offer_id}); + + expect(await getSalesIds({is_burnable: 'false'})) + .to.deep.equal([sale_id]); + }); + + txit('filters by text data', async () => { + await initTest(); + + const {template_id} = await client.createTemplate({immutable_data: JSON.stringify({'prop': 'TheValue'})}); + const {offer_id} = await client.createOfferAsset({}, {template_id}); + const {sale_id} = await client.createSale({offer_id}); + + expect(await getSalesIds({'data:text.prop': 'TheValue', burned: false})) + .to.deep.equal([sale_id]); + }); + + txit('filters by number template_data', async () => { + await initTest(); + + const {template_id} = await client.createTemplate({immutable_data: JSON.stringify({'prop': 1})}); + const {offer_id} = await client.createOfferAsset({}, {template_id}); + const {sale_id} = await client.createSale({offer_id}); + + expect(await getSalesIds({'template_data:number.prop': 1, burned: false})) + .to.deep.equal([sale_id]); + }); + + txit('filters by bool mutable_data', async () => { + const {template_id} = await initTest(); + + const {offer_id} = await client.createOfferAsset({}, { + mutable_data: JSON.stringify({'prop': 1}), + template_id, + }); + const {sale_id} = await client.createSale({offer_id}); + + expect(await getSalesIds({'mutable_data:bool.prop': 'true', burned: false})) + .to.deep.equal([sale_id]); + }); + + txit('filters by untyped immutable_data', async () => { + const {template_id} = await initTest(); + + const {offer_id} = await client.createOfferAsset({}, { + immutable_data: JSON.stringify({'prop': 'this'}), + template_id, + }); + const {sale_id} = await client.createSale({offer_id}); + + expect(await getSalesIds({'immutable_data.prop': 'this', burned: false})) + .to.deep.equal([sale_id]); + }); + + txit('filters by match_immutable_name', async () => { + const {template_id} = await initTest(); + + const offer1 = await client.createOfferAsset(); + await client.createSale({offer_id: offer1.offer_id}); + + const {offer_id} = await client.createOfferAsset({}, { + immutable_data: JSON.stringify({name: 'prefix_par%_tial_postfix'}), + template_id, + }); + const {sale_id} = await client.createSale({offer_id}); + + expect(await getSalesIds({'match_immutable_name': 'par%_tial', burned: false})) + .to.deep.equal([sale_id]); + }); + + txit('filters by match_mutable_name', async () => { + const {template_id} = await initTest(); + + const {offer_id} = await client.createOfferAsset({}, { + mutable_data: JSON.stringify({name: 'prefix_par%_tial_postfix'}), + template_id, + }); + const {sale_id} = await client.createSale({offer_id}); + + expect(await getSalesIds({'match_mutable_name': 'par%_tial', burned: false})) + .to.deep.equal([sale_id]); + }); + + txit('filters by match (template name)', async () => { + await initTest(); + + const {template_id} = await client.createTemplate({immutable_data: JSON.stringify({name: 'prefix_par%_tial_postfix'})}); + const {offer_id} = await client.createOfferAsset({}, {template_id}); + const {sale_id} = await client.createSale({offer_id}); + + expect(await getSalesIds({'match': 'par%_tial', burned: false})) + .to.deep.equal([sale_id]); + }); + + txit('filters by collection_whitelist', async () => { + const {template_id} = await initTest(); + + const {collection_name} = await client.createCollection({collection_name: 'x'}); + + const {offer_id} = await client.createOfferAsset({}, {template_id, collection_name}); + const {sale_id} = await client.createSale({offer_id, collection_name}); + + expect(await getSalesIds({collection_whitelist: 'x,abc'})) + .to.deep.equal([sale_id]); + }); + + txit('filters by collection_blacklist', async () => { + const {collection_name} = await client.createCollection({collection_name: 'x'}); + const {template_id} = await initTest({collection_name}); + + const {offer_id} = await client.createOfferAsset({}, {template_id}); + const {sale_id} = await client.createSale({offer_id}); + + expect(await getSalesIds({collection_blacklist: 'x,abc', burned: false})) + .to.deep.equal([sale_id]); + }); + + txit('orders ascending', async () => { + const {template_id, sale_id: sale_id1} = await initTest(); + + const {offer_id} = await client.createOfferAsset({}, {template_id}); + const {sale_id: sale_id2} = await client.createSale({offer_id}); + + expect(await getSalesIds({burned: false, order: 'asc'})) + .to.deep.equal([sale_id1, sale_id2]); + }); + + txit('orders descending', async () => { + const {template_id, sale_id: sale_id1} = await initTest(); + + const {offer_id} = await client.createOfferAsset({}, {template_id}); + const {sale_id: sale_id2} = await client.createSale({offer_id}); + + expect(await getSalesIds({burned: false, order: 'desc'})) + .to.deep.equal([sale_id2, sale_id1]); + }); + + txit('orders by price', async () => { + const {template_id, sale_id: sale_id1} = await initTest({ + listing_price: 200000000, + }); + + const {offer_id} = await client.createOfferAsset({}, {template_id}); + const {sale_id: sale_id2} = await client.createSale({ + offer_id, + listing_price: 100000000, + }); + + expect(await getSalesIds({burned: false, sort: 'price'})) + .to.deep.equal([sale_id1, sale_id2]); + }); + + txit('orders by template_id', async () => { + const {template_id, sale_id: sale_id1} = await initTest(); + + const {offer_id} = await client.createOfferAsset({}, {template_id}); + const {sale_id: sale_id2} = await client.createSale({offer_id}); + + expect(await getSalesIds({burned: false, sort: 'template_id'})) + .to.deep.equal([sale_id2, sale_id1]); + }); + + txit('paginates', async () => { + const {template_id} = await initTest(); + + const {offer_id} = await client.createOfferAsset({}, {template_id}); + const {sale_id} = await client.createSale({offer_id}); + + expect(await getSalesIds({page: '2', limit: '1', burned: false, order: 'asc'})) + .to.deep.equal([sale_id]); + }); + + txit('formats and fills result', async () => { + const {template_id} = await client.createTemplate(); + const {offer_id} = await client.createOfferAsset({}, {template_id}); + const {sale_id} = await client.createSale({offer_id}); + + await client.query('REFRESH MATERIALIZED VIEW atomicmarket_sale_prices'); + + const testContext = getTestContext(client); + + const [result] = await getSalesTemplatesAction({symbol: 'TEST', burned: false}, testContext); + + expect(result).to.not.haveOwnProperty('raw_price'); + expect(result.sale_id).to.equal(sale_id); + expect(result).to.haveOwnProperty('state'); + expect(result).to.haveOwnProperty('price'); + expect(result.price).to.have.ownProperty('amount'); + expect(result).to.haveOwnProperty('collection'); + }); + }); + + after(async () => await client.end()); +}); diff --git a/src/api/namespaces/atomicmarket/handlers/sales.test.ts b/src/api/namespaces/atomicmarket/handlers/sales.get-sales.test.ts similarity index 100% rename from src/api/namespaces/atomicmarket/handlers/sales.test.ts rename to src/api/namespaces/atomicmarket/handlers/sales.get-sales.test.ts From f757aabb207a227cf1bb416a583879b94b62be56 Mon Sep 17 00:00:00 2001 From: Andre Meyer Date: Fri, 22 Apr 2022 13:19:13 -0700 Subject: [PATCH 07/16] /v1/sales/templates to use atomic_market_sales_filters --- .../sales2.get-sales-templates.test.ts | 423 ++++++++++++++++++ .../atomicmarket/handlers/sales2.ts | 70 ++- .../namespaces/atomicmarket/routes/sales.ts | 6 +- 3 files changed, 493 insertions(+), 6 deletions(-) create mode 100644 src/api/namespaces/atomicmarket/handlers/sales2.get-sales-templates.test.ts diff --git a/src/api/namespaces/atomicmarket/handlers/sales2.get-sales-templates.test.ts b/src/api/namespaces/atomicmarket/handlers/sales2.get-sales-templates.test.ts new file mode 100644 index 00000000..2c7d4672 --- /dev/null +++ b/src/api/namespaces/atomicmarket/handlers/sales2.get-sales-templates.test.ts @@ -0,0 +1,423 @@ +import 'mocha'; +import {expect} from 'chai'; +import {RequestValues} from '../../utils'; +import {initAtomicMarketTest} from '../test'; +import {getTestContext} from '../../../../utils/test'; +import {getSalesTemplatesV2Action} from './sales2'; + +const {client, txit} = initAtomicMarketTest(); + +async function getSalesIds(values: RequestValues): Promise> { + const testContext = getTestContext(client); + + await client.query('SELECT update_atomicmarket_sales_filters()'); + + const result = await getSalesTemplatesV2Action({ + symbol: 'TEST', + ...values, + }, testContext); + + return result.map((s: any) => s.sale_id); +} + +async function initTest(saleValues: Record = {}): Promise<{template_id: number, sale_id: number}> { + const {template_id} = await client.createTemplate(); + + const {offer_id} = await client.createOfferAsset({}, {template_id}); + const {sale_id} = await client.createSale({ + offer_id, + ...saleValues, + }); + + return { + sale_id, + template_id: (await client.createTemplate()).template_id, + }; +} + +describe('AtomicMarket Sales API', () => { + + describe('getSalesTemplatesAction', () => { + + txit('filters by settlement symbol', async () => { + const {template_id} = await initTest(); + await client.createToken({token_symbol: 'TOKEN1'}); + const {offer_id} = await client.createOfferAsset({}, {template_id}); + const {sale_id} = await client.createSale({offer_id, settlement_symbol: 'TOKEN1'}); + + expect(await getSalesIds({symbol: 'TOKEN1', burned: false})) + .to.deep.equal([sale_id]); + }); + + txit('filters by minimum price', async () => { + const {template_id} = await initTest({ + listing_price: 100000000, + }); + + const {offer_id} = await client.createOfferAsset({}, {template_id}); + const {sale_id} = await client.createSale({ + offer_id, + listing_price: 200000000, + }); + + expect(await getSalesIds({min_price: '2', burned: false})) + .to.deep.equal([sale_id]); + }); + + txit('filters by maximum price', async () => { + const {template_id} = await initTest({ + listing_price: 300000000, + }); + + const {offer_id} = await client.createOfferAsset({}, {template_id}); + const {sale_id} = await client.createSale({ + offer_id, + listing_price: 200000000, + }); + + expect(await getSalesIds({max_price: '2', burned: false})) + .to.deep.equal([sale_id]); + }); + + txit('filters by collection', async () => { + const {template_id} = await initTest(); + + const {collection_name} = await client.createCollection({collection_name: 'x'}); + + const {offer_id} = await client.createOfferAsset({}, {template_id, collection_name}); + const {sale_id} = await client.createSale({offer_id, collection_name}); + + expect(await getSalesIds({collection_name: 'x,abc'})) + .to.deep.equal([sale_id]); + }); + + txit('filters by asset_id', async () => { + const {template_id} = await initTest(); + + const {asset_id, offer_id} = await client.createOfferAsset({}, {template_id}); + const {sale_id} = await client.createSale({offer_id}); + + expect(await getSalesIds({asset_id})) + .to.deep.equal([sale_id]); + }); + + txit('only returns single asset sales', async () => { + const {template_id, sale_id} = await initTest(); + + const {offer_id} = await client.createOfferAsset({}, {template_id}); + await client.createOfferAsset({offer_id, index: 2}, { + template_id: (await client.createTemplate()).template_id, + }); + + await client.createSale({offer_id}); + + expect(await getSalesIds({burned: false})) + .to.deep.equal([sale_id]); + }); + + txit('filters by asset owner', async () => { + const {template_id} = await initTest(); + + const {offer_id} = await client.createOfferAsset({}, {template_id, owner: 'x'}); + const {sale_id} = await client.createSale({offer_id}); + + expect(await getSalesIds({owner: 'x,abc'})) + .to.deep.equal([sale_id]); + }); + + txit('filters by asset burned', async () => { + const {template_id} = await initTest(); + + const {offer_id} = await client.createOfferAsset({}, {template_id, owner: null}); + const {sale_id} = await client.createSale({offer_id}); + + expect(await getSalesIds({burned: 'true'})) + .to.deep.equal([sale_id]); + }); + + txit('filters by asset not burned', async () => { + const {template_id, sale_id} = await initTest(); + + const {offer_id} = await client.createOfferAsset({}, {template_id, owner: null}); + await client.createSale({offer_id}); + + expect(await getSalesIds({burned: 'false'})) + .to.deep.equal([sale_id]); + }); + + txit('filters by asset template', async () => { + const {template_id} = await initTest(); + + const {offer_id} = await client.createOfferAsset({}, {template_id}); + const {sale_id} = await client.createSale({offer_id}); + + expect(await getSalesIds({template_id: `${template_id},-1`})) + .to.deep.equal([sale_id]); + }); + + txit('ignores sales without a template', async () => { + const {sale_id} = await initTest(); + + const {offer_id} = await client.createOfferAsset(); + await client.createSale({offer_id}); + + expect(await getSalesIds({burned: false})) + .to.deep.equal([sale_id]); + }); + + txit('filters by schema', async () => { + const {template_id} = await initTest(); + + const {schema_name} = await client.createSchema(); + + const {offer_id} = await client.createOfferAsset({}, {template_id, schema_name}); + const {sale_id} = await client.createSale({offer_id}); + + expect(await getSalesIds({schema_name: `${schema_name},-1`})) + .to.deep.equal([sale_id]); + }); + + txit('filters by asset being transferable', async () => { + const offer1 = await client.createOfferAsset({}, { + template_id: (await client.createTemplate({transferable: false})).template_id, + }); + await client.createSale({offer_id: offer1.offer_id}); + + const {template_id} = await client.createTemplate({transferable: true}); + const {offer_id} = await client.createOfferAsset({}, {template_id}); + const {sale_id} = await client.createSale({offer_id}); + + expect(await getSalesIds({is_transferable: 'true'})) + .to.deep.equal([sale_id]); + }); + + txit('filters by asset not being transferable', async () => { + const offer1 = await client.createOfferAsset({}, { + template_id: (await client.createTemplate({transferable: true})).template_id, + }); + await client.createSale({offer_id: offer1.offer_id}); + + const {template_id} = await client.createTemplate({transferable: false}); + const {offer_id} = await client.createOfferAsset({}, {template_id}); + const {sale_id} = await client.createSale({offer_id}); + + expect(await getSalesIds({is_transferable: 'false'})) + .to.deep.equal([sale_id]); + }); + + txit('filters by asset being burnable', async () => { + const offer1 = await client.createOfferAsset({}, { + template_id: (await client.createTemplate({burnable: false})).template_id, + }); + await client.createSale({offer_id: offer1.offer_id}); + + const {template_id} = await client.createTemplate({burnable: true}); + const {offer_id} = await client.createOfferAsset({}, {template_id}); + const {sale_id} = await client.createSale({offer_id}); + + expect(await getSalesIds({is_burnable: 'true'})) + .to.deep.equal([sale_id]); + }); + + txit('filters by asset not being burnable', async () => { + const offer1 = await client.createOfferAsset({}, { + template_id: (await client.createTemplate({burnable: true})).template_id, + }); + await client.createSale({offer_id: offer1.offer_id}); + + const {template_id} = await client.createTemplate({burnable: false}); + const {offer_id} = await client.createOfferAsset({}, {template_id}); + const {sale_id} = await client.createSale({offer_id}); + + expect(await getSalesIds({is_burnable: 'false'})) + .to.deep.equal([sale_id]); + }); + + txit('filters by text data', async () => { + await initTest(); + + const {template_id} = await client.createTemplate({immutable_data: JSON.stringify({'prop': 'TheValue'})}); + const {offer_id} = await client.createOfferAsset({}, {template_id}); + const {sale_id} = await client.createSale({offer_id}); + + expect(await getSalesIds({'data:text.prop': 'TheValue', burned: false})) + .to.deep.equal([sale_id]); + }); + + txit('filters by number template_data', async () => { + await initTest(); + + const {template_id} = await client.createTemplate({immutable_data: JSON.stringify({'prop': 1})}); + const {offer_id} = await client.createOfferAsset({}, {template_id}); + const {sale_id} = await client.createSale({offer_id}); + + expect(await getSalesIds({'template_data:number.prop': 1, burned: false})) + .to.deep.equal([sale_id]); + }); + + txit('filters by bool mutable_data', async () => { + const {template_id} = await initTest(); + + const {offer_id} = await client.createOfferAsset({}, { + mutable_data: JSON.stringify({'prop': 1}), + template_id, + }); + const {sale_id} = await client.createSale({offer_id}); + + expect(await getSalesIds({'mutable_data:bool.prop': 'true', burned: false})) + .to.deep.equal([sale_id]); + }); + + txit('filters by untyped immutable_data', async () => { + const {template_id} = await initTest(); + + const {offer_id} = await client.createOfferAsset({}, { + immutable_data: JSON.stringify({'prop': 'this'}), + template_id, + }); + const {sale_id} = await client.createSale({offer_id}); + + expect(await getSalesIds({'immutable_data.prop': 'this', burned: false})) + .to.deep.equal([sale_id]); + }); + + txit('filters by match_immutable_name', async () => { + const {template_id} = await initTest(); + + const offer1 = await client.createOfferAsset(); + await client.createSale({offer_id: offer1.offer_id}); + + const {offer_id} = await client.createOfferAsset({}, { + immutable_data: JSON.stringify({name: 'prefix_par%_tial_postfix'}), + template_id, + }); + const {sale_id} = await client.createSale({offer_id}); + + expect(await getSalesIds({'match_immutable_name': 'par%_tial', burned: false})) + .to.deep.equal([sale_id]); + }); + + txit('filters by match_mutable_name', async () => { + const {template_id} = await initTest(); + + const {offer_id} = await client.createOfferAsset({}, { + mutable_data: JSON.stringify({name: 'prefix_par%_tial_postfix'}), + template_id, + }); + const {sale_id} = await client.createSale({offer_id}); + + expect(await getSalesIds({'match_mutable_name': 'par%_tial', burned: false})) + .to.deep.equal([sale_id]); + }); + + txit('filters by match (template name)', async () => { + await initTest(); + + const {template_id} = await client.createTemplate({immutable_data: JSON.stringify({name: 'prefix_par%_tial_postfix'})}); + const {offer_id} = await client.createOfferAsset({}, {template_id}); + const {sale_id} = await client.createSale({offer_id}); + + expect(await getSalesIds({'match': 'par%_tial', burned: false})) + .to.deep.equal([sale_id]); + }); + + txit('filters by collection_whitelist', async () => { + const {template_id} = await initTest(); + + const {collection_name} = await client.createCollection({collection_name: 'x'}); + + const {offer_id} = await client.createOfferAsset({}, {template_id, collection_name}); + const {sale_id} = await client.createSale({offer_id, collection_name}); + + expect(await getSalesIds({collection_whitelist: 'x,abc'})) + .to.deep.equal([sale_id]); + }); + + txit('filters by collection_blacklist', async () => { + const {collection_name} = await client.createCollection({collection_name: 'x'}); + const {template_id} = await initTest({collection_name}); + + const {offer_id} = await client.createOfferAsset({}, {template_id}); + const {sale_id} = await client.createSale({offer_id}); + + expect(await getSalesIds({collection_blacklist: 'x,abc', burned: false})) + .to.deep.equal([sale_id]); + }); + + txit('orders ascending', async () => { + const {template_id, sale_id: sale_id1} = await initTest(); + + const {offer_id} = await client.createOfferAsset({}, {template_id}); + const {sale_id: sale_id2} = await client.createSale({offer_id}); + + expect(await getSalesIds({burned: false, order: 'asc'})) + .to.deep.equal([sale_id1, sale_id2]); + }); + + txit('orders descending', async () => { + const {template_id, sale_id: sale_id1} = await initTest(); + + const {offer_id} = await client.createOfferAsset({}, {template_id}); + const {sale_id: sale_id2} = await client.createSale({offer_id}); + + expect(await getSalesIds({burned: false, order: 'desc'})) + .to.deep.equal([sale_id2, sale_id1]); + }); + + txit('orders by price', async () => { + const {template_id, sale_id: sale_id1} = await initTest({ + listing_price: 200000000, + }); + + const {offer_id} = await client.createOfferAsset({}, {template_id}); + const {sale_id: sale_id2} = await client.createSale({ + offer_id, + listing_price: 100000000, + }); + + expect(await getSalesIds({burned: false, sort: 'price'})) + .to.deep.equal([sale_id1, sale_id2]); + }); + + txit('orders by template_id', async () => { + const {template_id, sale_id: sale_id1} = await initTest(); + + const {offer_id} = await client.createOfferAsset({}, {template_id}); + const {sale_id: sale_id2} = await client.createSale({offer_id}); + + expect(await getSalesIds({burned: false, sort: 'template_id'})) + .to.deep.equal([sale_id2, sale_id1]); + }); + + txit('paginates', async () => { + const {template_id} = await initTest(); + + const {offer_id} = await client.createOfferAsset({}, {template_id}); + const {sale_id} = await client.createSale({offer_id}); + + expect(await getSalesIds({page: '2', limit: '1', burned: false, order: 'asc'})) + .to.deep.equal([sale_id]); + }); + + txit('formats and fills result', async () => { + const {template_id} = await client.createTemplate(); + const {offer_id} = await client.createOfferAsset({}, {template_id}); + const {sale_id} = await client.createSale({offer_id}); + + await client.query('SELECT update_atomicmarket_sales_filters()'); + + const testContext = getTestContext(client); + + const [result] = await getSalesTemplatesV2Action({symbol: 'TEST', burned: false}, testContext); + + expect(result).to.not.haveOwnProperty('raw_price'); + expect(result.sale_id).to.equal(sale_id); + expect(result).to.haveOwnProperty('state'); + expect(result).to.haveOwnProperty('price'); + expect(result.price).to.have.ownProperty('amount'); + expect(result).to.haveOwnProperty('collection'); + }); + }); + + after(async () => await client.end()); +}); diff --git a/src/api/namespaces/atomicmarket/handlers/sales2.ts b/src/api/namespaces/atomicmarket/handlers/sales2.ts index 7292a81a..f26fb5a0 100644 --- a/src/api/namespaces/atomicmarket/handlers/sales2.ts +++ b/src/api/namespaces/atomicmarket/handlers/sales2.ts @@ -7,6 +7,7 @@ import {ApiError} from '../../../error'; import {toInt} from '../../../../utils'; import moize from 'moize'; import {filterQueryArgs, FilterValues} from '../../validation'; +import {hasAssetFilter} from '../../atomicassets/utils'; type SalesSearchOptions = { values: FilterValues; @@ -92,21 +93,24 @@ export async function getSalesV2Action(params: RequestValues, ctx: AtomicMarketC query.append(`ORDER BY ${sortMapping[args.sort].column}${preventIndexUsage ? ' + 0' : ''} ${args.order}, listing.sale_id ASC`); query.paginate(args.page, args.limit); - const saleQuery = await ctx.db.query(query.buildString(), query.buildValues()); + const saleIds = await ctx.db.query(query.buildString(), query.buildValues()); + return await fillSalesIdRows(saleIds.rows, ctx); +} + +async function fillSalesIdRows(rows: any[], ctx: AtomicMarketContext): Promise { const result = await ctx.db.query(` SELECT * FROM atomicmarket_sales_master m JOIN UNNEST($2::BIGINT[]) WITH ORDINALITY AS f(sale_id) ON m.sale_id = f.sale_id WHERE market_contract = $1 AND m.sale_id = ANY($2::BIGINT[]) ORDER BY f.ordinality`, - [ctx.coreArgs.atomicmarket_account, saleQuery.rows.map(row => row.sale_id)] + [ctx.coreArgs.atomicmarket_account, rows.map((row: any) => row.sale_id)] ); return await fillSales( ctx.db, ctx.coreArgs.atomicassets_account, result.rows.map(formatSale) ); - } export async function getSalesCountV2Action(params: RequestValues, ctx: AtomicMarketContext): Promise { @@ -519,3 +523,63 @@ async function getTemplateIDsForPartialName(name: string, search: SalesSearchOpt return rows.length ? rows.map(r => r.template_id) : [-1]; } + +export async function getSalesTemplatesV2Action(params: RequestValues, ctx: AtomicMarketContext): Promise { + const maxLimit = ctx.coreArgs.limits?.sales_templates || 100; + const args = filterQueryArgs(params, { + symbol: {type: 'string', min: 1}, + collection_whitelist: {type: 'string', min: 1}, + + page: {type: 'int', min: 1, default: 1}, + limit: {type: 'int', min: 1, max: maxLimit, default: Math.min(maxLimit, 100)}, + sort: { + type: 'string', + allowedValues: ['template_id', 'price'], + default: 'template_id' + }, + order: {type: 'string', allowedValues: ['asc', 'desc'], default: 'desc'}, + }); + + if (!args.symbol) { + throw new ApiError('symbol parameter is required', 200); + } + + if (!hasAssetFilter(params) && !args.collection_whitelist) { + throw new ApiError('You need to specify an asset filter!', 200); + } + + const query = new QueryBuilder(` + SELECT DISTINCT ON (listing.assets_contract, template_id) + listing.market_contract, listing.sale_id, listing.assets_contract, SUBSTRING(u.f FROM 2)::BIGINT template_id, listing.price + FROM atomicmarket_sales_filters listing + JOIN LATERAL UNNEST(filter) u(f) ON u.f LIKE 't%' + `); + + query.equal('listing.market_contract', ctx.coreArgs.atomicmarket_account); + query.equal('listing.asset_count', 1); + + const search: SalesSearchOptions = { + values: params, + ctx, + query, + strongFilters: [], + saleStates: [SaleApiState.LISTED], + }; + + await buildSaleFilterV2(search); + + query.append('ORDER BY listing.assets_contract, template_id, listing.price'); + + const sortColumnMapping: {[key: string]: string} = { + price: 't1.price', + template_id: 't1.template_id', + }; + + const outerQuery = new QueryBuilder(`SELECT * FROM (${query.buildString()}) t1`, query.buildValues()); + outerQuery.append(`ORDER BY ${sortColumnMapping[args.sort]} ${args.order} NULLS LAST, t1.template_id`); + outerQuery.paginate(args.page, args.limit); + + const saleIds = await ctx.db.query(outerQuery.buildString(), outerQuery.buildValues()); + + return await fillSalesIdRows(saleIds.rows, ctx); +} diff --git a/src/api/namespaces/atomicmarket/routes/sales.ts b/src/api/namespaces/atomicmarket/routes/sales.ts index 4a76e4c7..645d112f 100644 --- a/src/api/namespaces/atomicmarket/routes/sales.ts +++ b/src/api/namespaces/atomicmarket/routes/sales.ts @@ -22,9 +22,9 @@ import { NotificationData } from '../../../../filler/notifier'; import { getSaleAction, getSaleLogsAction, - getSalesAction, getSalesCountAction, getSalesTemplatesAction + getSalesAction, getSalesCountAction } from '../handlers/sales'; -import { getSalesCountV2Action, getSalesV2Action } from '../handlers/sales2'; +import { getSalesCountV2Action, getSalesTemplatesV2Action, getSalesV2Action } from '../handlers/sales2'; export function salesEndpoints(core: AtomicMarketNamespace, server: HTTPServer, router: express.Router): any { const {caching, returnAsJSON} = server.web; @@ -43,7 +43,7 @@ export function salesEndpoints(core: AtomicMarketNamespace, server: HTTPServer, router.all('/v2/sales', caching(), returnAsJSON(getSalesV2Action, core)); router.all('/v2/sales/_count', caching(), returnAsJSON(getSalesCountV2Action, core)); - router.all('/v1/sales/templates', caching(), returnAsJSON(getSalesTemplatesAction, core)); + router.all('/v1/sales/templates', caching(), returnAsJSON(getSalesTemplatesV2Action, core)); router.all('/v1/sales/:sale_id', caching(), returnAsJSON(getSaleAction, core)); From b58a29b3cab18c5870616bc7187757ab144fdcf7 Mon Sep 17 00:00:00 2001 From: Andre Meyer Date: Fri, 22 Apr 2022 13:21:21 -0700 Subject: [PATCH 08/16] Remove old /v1/sales/templates action handler --- .../sales.get-sales-templates.test.ts | 425 ------------------ .../namespaces/atomicmarket/handlers/sales.ts | 100 +---- 2 files changed, 1 insertion(+), 524 deletions(-) delete mode 100644 src/api/namespaces/atomicmarket/handlers/sales.get-sales-templates.test.ts diff --git a/src/api/namespaces/atomicmarket/handlers/sales.get-sales-templates.test.ts b/src/api/namespaces/atomicmarket/handlers/sales.get-sales-templates.test.ts deleted file mode 100644 index d9a69bb7..00000000 --- a/src/api/namespaces/atomicmarket/handlers/sales.get-sales-templates.test.ts +++ /dev/null @@ -1,425 +0,0 @@ -import 'mocha'; -import {expect} from 'chai'; -import { getSalesTemplatesAction } from './sales'; -import {RequestValues} from '../../utils'; -import {initAtomicMarketTest} from '../test'; -import {getTestContext} from '../../../../utils/test'; - -const {client, txit} = initAtomicMarketTest(); - -async function getSalesIds(values: RequestValues): Promise> { - const testContext = getTestContext(client); - - await client.query('REFRESH MATERIALIZED VIEW atomicmarket_sale_prices'); - - const result = await getSalesTemplatesAction({ - symbol: 'TEST', - ...values, - }, testContext); - - return result.map((s: any) => s.sale_id); -} - -async function initTest(saleValues: Record = {}): Promise<{template_id: number, sale_id: number}> { - const {template_id} = await client.createTemplate(); - - const {offer_id} = await client.createOfferAsset({}, {template_id}); - const {sale_id} = await client.createSale({ - offer_id, - ...saleValues, - }); - - return { - sale_id, - template_id: (await client.createTemplate()).template_id, - }; -} - -describe('AtomicMarket Sales API', () => { - - describe('getSalesTemplatesAction', () => { - - txit('filters by settlement symbol', async () => { - const {template_id} = await initTest(); - await client.createToken({token_symbol: 'TOKEN1'}); - const {offer_id} = await client.createOfferAsset({}, {template_id}); - const {sale_id} = await client.createSale({offer_id, settlement_symbol: 'TOKEN1'}); - - expect(await getSalesIds({symbol: 'TOKEN1', burned: false})) - .to.deep.equal([sale_id]); - }); - - txit('filters by minimum price', async () => { - const {template_id} = await initTest({ - listing_price: 100000000, - }); - - const {offer_id} = await client.createOfferAsset({}, {template_id}); - const {sale_id} = await client.createSale({ - offer_id, - listing_price: 200000000, - }); - - expect(await getSalesIds({min_price: '2', burned: false})) - .to.deep.equal([sale_id]); - }); - - txit('filters by maximum price', async () => { - const {template_id} = await initTest({ - listing_price: 300000000, - }); - - const {offer_id} = await client.createOfferAsset({}, {template_id}); - const {sale_id} = await client.createSale({ - offer_id, - listing_price: 200000000, - }); - - expect(await getSalesIds({max_price: '2', burned: false})) - .to.deep.equal([sale_id]); - }); - - txit('filters by collection', async () => { - const {template_id} = await initTest(); - - const {collection_name} = await client.createCollection({collection_name: 'x'}); - - const {offer_id} = await client.createOfferAsset({}, {template_id, collection_name}); - const {sale_id} = await client.createSale({offer_id, collection_name}); - - expect(await getSalesIds({collection_name: 'x,abc'})) - .to.deep.equal([sale_id]); - }); - - txit('filters by asset_id', async () => { - const {template_id} = await initTest(); - - const {asset_id, offer_id} = await client.createOfferAsset({}, {template_id}); - const {sale_id} = await client.createSale({offer_id}); - - expect(await getSalesIds({asset_id})) - .to.deep.equal([sale_id]); - }); - - txit('only returns the first asset in a bundle', async () => { - // in new version, ignore bundles - const {template_id} = await initTest(); - - const {asset_id, offer_id} = await client.createOfferAsset({}, {template_id}); - - const {asset_id: asset_id2} = await client.createOfferAsset({offer_id, index: 2}, { - template_id: (await client.createTemplate()).template_id, - }); - - const {sale_id} = await client.createSale({offer_id}); - - expect(await getSalesIds({asset_id: `${asset_id}, ${asset_id2}`})) - .to.deep.equal([sale_id]); - }); - - txit('filters by asset owner', async () => { - const {template_id} = await initTest(); - - const {offer_id} = await client.createOfferAsset({}, {template_id, owner: 'x'}); - const {sale_id} = await client.createSale({offer_id}); - - expect(await getSalesIds({owner: 'x,abc'})) - .to.deep.equal([sale_id]); - }); - - txit('filters by asset burned', async () => { - const {template_id} = await initTest(); - - const {offer_id} = await client.createOfferAsset({}, {template_id, owner: null}); - const {sale_id} = await client.createSale({offer_id}); - - expect(await getSalesIds({burned: 'true'})) - .to.deep.equal([sale_id]); - }); - - txit('filters by asset not burned', async () => { - const {template_id, sale_id} = await initTest(); - - const {offer_id} = await client.createOfferAsset({}, {template_id, owner: null}); - await client.createSale({offer_id}); - - expect(await getSalesIds({burned: 'false'})) - .to.deep.equal([sale_id]); - }); - - txit('filters by asset template', async () => { - const {template_id} = await initTest(); - - const {offer_id} = await client.createOfferAsset({}, {template_id}); - const {sale_id} = await client.createSale({offer_id}); - - expect(await getSalesIds({template_id: `${template_id},-1`})) - .to.deep.equal([sale_id]); - }); - - txit('ignores sales without a template', async () => { - const {sale_id} = await initTest(); - - const {offer_id} = await client.createOfferAsset(); - await client.createSale({offer_id}); - - expect(await getSalesIds({burned: false})) - .to.deep.equal([sale_id]); - }); - - txit('filters by schema', async () => { - const {template_id} = await initTest(); - - const {schema_name} = await client.createSchema(); - - const {offer_id} = await client.createOfferAsset({}, {template_id, schema_name}); - const {sale_id} = await client.createSale({offer_id}); - - expect(await getSalesIds({schema_name: `${schema_name},-1`})) - .to.deep.equal([sale_id]); - }); - - txit('filters by asset being transferable', async () => { - const offer1 = await client.createOfferAsset({}, { - template_id: (await client.createTemplate({transferable: false})).template_id, - }); - await client.createSale({offer_id: offer1.offer_id}); - - const {template_id} = await client.createTemplate({transferable: true}); - const {offer_id} = await client.createOfferAsset({}, {template_id}); - const {sale_id} = await client.createSale({offer_id}); - - expect(await getSalesIds({is_transferable: 'true'})) - .to.deep.equal([sale_id]); - }); - - txit('filters by asset not being transferable', async () => { - const offer1 = await client.createOfferAsset({}, { - template_id: (await client.createTemplate({transferable: true})).template_id, - }); - await client.createSale({offer_id: offer1.offer_id}); - - const {template_id} = await client.createTemplate({transferable: false}); - const {offer_id} = await client.createOfferAsset({}, {template_id}); - const {sale_id} = await client.createSale({offer_id}); - - expect(await getSalesIds({is_transferable: 'false'})) - .to.deep.equal([sale_id]); - }); - - txit('filters by asset being burnable', async () => { - const offer1 = await client.createOfferAsset({}, { - template_id: (await client.createTemplate({burnable: false})).template_id, - }); - await client.createSale({offer_id: offer1.offer_id}); - - const {template_id} = await client.createTemplate({burnable: true}); - const {offer_id} = await client.createOfferAsset({}, {template_id}); - const {sale_id} = await client.createSale({offer_id}); - - expect(await getSalesIds({is_burnable: 'true'})) - .to.deep.equal([sale_id]); - }); - - txit('filters by asset not being burnable', async () => { - const offer1 = await client.createOfferAsset({}, { - template_id: (await client.createTemplate({burnable: true})).template_id, - }); - await client.createSale({offer_id: offer1.offer_id}); - - const {template_id} = await client.createTemplate({burnable: false}); - const {offer_id} = await client.createOfferAsset({}, {template_id}); - const {sale_id} = await client.createSale({offer_id}); - - expect(await getSalesIds({is_burnable: 'false'})) - .to.deep.equal([sale_id]); - }); - - txit('filters by text data', async () => { - await initTest(); - - const {template_id} = await client.createTemplate({immutable_data: JSON.stringify({'prop': 'TheValue'})}); - const {offer_id} = await client.createOfferAsset({}, {template_id}); - const {sale_id} = await client.createSale({offer_id}); - - expect(await getSalesIds({'data:text.prop': 'TheValue', burned: false})) - .to.deep.equal([sale_id]); - }); - - txit('filters by number template_data', async () => { - await initTest(); - - const {template_id} = await client.createTemplate({immutable_data: JSON.stringify({'prop': 1})}); - const {offer_id} = await client.createOfferAsset({}, {template_id}); - const {sale_id} = await client.createSale({offer_id}); - - expect(await getSalesIds({'template_data:number.prop': 1, burned: false})) - .to.deep.equal([sale_id]); - }); - - txit('filters by bool mutable_data', async () => { - const {template_id} = await initTest(); - - const {offer_id} = await client.createOfferAsset({}, { - mutable_data: JSON.stringify({'prop': 1}), - template_id, - }); - const {sale_id} = await client.createSale({offer_id}); - - expect(await getSalesIds({'mutable_data:bool.prop': 'true', burned: false})) - .to.deep.equal([sale_id]); - }); - - txit('filters by untyped immutable_data', async () => { - const {template_id} = await initTest(); - - const {offer_id} = await client.createOfferAsset({}, { - immutable_data: JSON.stringify({'prop': 'this'}), - template_id, - }); - const {sale_id} = await client.createSale({offer_id}); - - expect(await getSalesIds({'immutable_data.prop': 'this', burned: false})) - .to.deep.equal([sale_id]); - }); - - txit('filters by match_immutable_name', async () => { - const {template_id} = await initTest(); - - const offer1 = await client.createOfferAsset(); - await client.createSale({offer_id: offer1.offer_id}); - - const {offer_id} = await client.createOfferAsset({}, { - immutable_data: JSON.stringify({name: 'prefix_par%_tial_postfix'}), - template_id, - }); - const {sale_id} = await client.createSale({offer_id}); - - expect(await getSalesIds({'match_immutable_name': 'par%_tial', burned: false})) - .to.deep.equal([sale_id]); - }); - - txit('filters by match_mutable_name', async () => { - const {template_id} = await initTest(); - - const {offer_id} = await client.createOfferAsset({}, { - mutable_data: JSON.stringify({name: 'prefix_par%_tial_postfix'}), - template_id, - }); - const {sale_id} = await client.createSale({offer_id}); - - expect(await getSalesIds({'match_mutable_name': 'par%_tial', burned: false})) - .to.deep.equal([sale_id]); - }); - - txit('filters by match (template name)', async () => { - await initTest(); - - const {template_id} = await client.createTemplate({immutable_data: JSON.stringify({name: 'prefix_par%_tial_postfix'})}); - const {offer_id} = await client.createOfferAsset({}, {template_id}); - const {sale_id} = await client.createSale({offer_id}); - - expect(await getSalesIds({'match': 'par%_tial', burned: false})) - .to.deep.equal([sale_id]); - }); - - txit('filters by collection_whitelist', async () => { - const {template_id} = await initTest(); - - const {collection_name} = await client.createCollection({collection_name: 'x'}); - - const {offer_id} = await client.createOfferAsset({}, {template_id, collection_name}); - const {sale_id} = await client.createSale({offer_id, collection_name}); - - expect(await getSalesIds({collection_whitelist: 'x,abc'})) - .to.deep.equal([sale_id]); - }); - - txit('filters by collection_blacklist', async () => { - const {collection_name} = await client.createCollection({collection_name: 'x'}); - const {template_id} = await initTest({collection_name}); - - const {offer_id} = await client.createOfferAsset({}, {template_id}); - const {sale_id} = await client.createSale({offer_id}); - - expect(await getSalesIds({collection_blacklist: 'x,abc', burned: false})) - .to.deep.equal([sale_id]); - }); - - txit('orders ascending', async () => { - const {template_id, sale_id: sale_id1} = await initTest(); - - const {offer_id} = await client.createOfferAsset({}, {template_id}); - const {sale_id: sale_id2} = await client.createSale({offer_id}); - - expect(await getSalesIds({burned: false, order: 'asc'})) - .to.deep.equal([sale_id1, sale_id2]); - }); - - txit('orders descending', async () => { - const {template_id, sale_id: sale_id1} = await initTest(); - - const {offer_id} = await client.createOfferAsset({}, {template_id}); - const {sale_id: sale_id2} = await client.createSale({offer_id}); - - expect(await getSalesIds({burned: false, order: 'desc'})) - .to.deep.equal([sale_id2, sale_id1]); - }); - - txit('orders by price', async () => { - const {template_id, sale_id: sale_id1} = await initTest({ - listing_price: 200000000, - }); - - const {offer_id} = await client.createOfferAsset({}, {template_id}); - const {sale_id: sale_id2} = await client.createSale({ - offer_id, - listing_price: 100000000, - }); - - expect(await getSalesIds({burned: false, sort: 'price'})) - .to.deep.equal([sale_id1, sale_id2]); - }); - - txit('orders by template_id', async () => { - const {template_id, sale_id: sale_id1} = await initTest(); - - const {offer_id} = await client.createOfferAsset({}, {template_id}); - const {sale_id: sale_id2} = await client.createSale({offer_id}); - - expect(await getSalesIds({burned: false, sort: 'template_id'})) - .to.deep.equal([sale_id2, sale_id1]); - }); - - txit('paginates', async () => { - const {template_id} = await initTest(); - - const {offer_id} = await client.createOfferAsset({}, {template_id}); - const {sale_id} = await client.createSale({offer_id}); - - expect(await getSalesIds({page: '2', limit: '1', burned: false, order: 'asc'})) - .to.deep.equal([sale_id]); - }); - - txit('formats and fills result', async () => { - const {template_id} = await client.createTemplate(); - const {offer_id} = await client.createOfferAsset({}, {template_id}); - const {sale_id} = await client.createSale({offer_id}); - - await client.query('REFRESH MATERIALIZED VIEW atomicmarket_sale_prices'); - - const testContext = getTestContext(client); - - const [result] = await getSalesTemplatesAction({symbol: 'TEST', burned: false}, testContext); - - expect(result).to.not.haveOwnProperty('raw_price'); - expect(result.sale_id).to.equal(sale_id); - expect(result).to.haveOwnProperty('state'); - expect(result).to.haveOwnProperty('price'); - expect(result.price).to.have.ownProperty('amount'); - expect(result).to.haveOwnProperty('collection'); - }); - }); - - after(async () => await client.end()); -}); diff --git a/src/api/namespaces/atomicmarket/handlers/sales.ts b/src/api/namespaces/atomicmarket/handlers/sales.ts index 60f5f6f4..d2645466 100644 --- a/src/api/namespaces/atomicmarket/handlers/sales.ts +++ b/src/api/namespaces/atomicmarket/handlers/sales.ts @@ -6,9 +6,7 @@ import { AtomicMarketContext } from '../index'; import { applyActionGreylistFilters, getContractActionLogs } from '../../../utils'; import QueryBuilder from '../../../builder'; import { buildSaleFilter, hasListingFilter } from '../utils'; -import { buildAssetFilter, buildGreylistFilter, hasAssetFilter, hasDataFilters } from '../../atomicassets/utils'; -import { OfferState } from '../../../../filler/handlers/atomicassets'; -import { SaleState } from '../../../../filler/handlers/atomicmarket'; +import { buildGreylistFilter, hasAssetFilter, hasDataFilters } from '../../atomicassets/utils'; import { filterQueryArgs } from '../../validation'; export async function getSaleAction(params: RequestValues, ctx: AtomicMarketContext): Promise { @@ -124,99 +122,3 @@ export async function getSalesAction(params: RequestValues, ctx: AtomicMarketCon export async function getSalesCountAction(params: RequestValues, ctx: AtomicMarketContext): Promise { return await getSalesAction({...params, count: 'true'}, ctx); } - -export async function getSalesTemplatesAction(params: RequestValues, ctx: AtomicMarketContext): Promise { - const maxLimit = ctx.coreArgs.limits?.sales_templates || 100; - const args = filterQueryArgs(params, { - symbol: {type: 'string', min: 1}, - collection_name: {type: 'string', min: 1}, - collection_whitelist: {type: 'string', min: 1}, - - min_price: {type: 'float', min: 0}, - max_price: {type: 'float', min: 0}, - - page: {type: 'int', min: 1, default: 1}, - limit: {type: 'int', min: 1, max: maxLimit, default: Math.min(maxLimit, 100)}, - sort: { - type: 'string', - allowedValues: ['template_id', 'price'], - default: 'template_id' - }, - order: {type: 'string', allowedValues: ['asc', 'desc'], default: 'desc'}, - }); - - if (!args.symbol) { - throw new ApiError('symbol parameter is required', 200); - } - - if (!hasAssetFilter(params) && !args.collection_whitelist) { - throw new ApiError('You need to specify an asset filter!', 200); - } - - const query = new QueryBuilder(` - SELECT DISTINCT ON(asset.contract, asset.template_id) - sale.market_contract, sale.sale_id, asset.contract assets_contract, asset.template_id, price.price - FROM - atomicmarket_sales sale, atomicassets_offers offer, atomicassets_offers_assets offer_asset, - atomicassets_assets asset, atomicmarket_sale_prices price, atomicassets_templates "template" - `); - - query.addCondition(` - sale.assets_contract = offer.contract AND sale.offer_id = offer.offer_id AND - offer.contract = offer_asset.contract AND offer.offer_id = offer_asset.offer_id AND - offer_asset.contract = asset.contract AND offer_asset.asset_id = asset.asset_id AND - asset.contract = "template".contract AND asset.template_id = "template".template_id AND - sale.market_contract = price.market_contract AND sale.sale_id = price.sale_id AND - asset.template_id IS NOT NULL AND offer_asset.index = 1 AND - offer.state = ${OfferState.PENDING.valueOf()} AND sale.state = ${SaleState.LISTED.valueOf()} - `); - - query.equal('sale.market_contract', ctx.coreArgs.atomicmarket_account); - query.equal('sale.settlement_symbol', args.symbol); - - if (!args.collection_name) { - buildGreylistFilter(params, query, {collectionName: 'sale.collection_name'}); - } - - buildAssetFilter(params, query, {assetTable: '"asset"', templateTable: '"template"'}); - - if (args.min_price) { - query.addCondition('price.price >= ' + query.addVariable(args.min_price) + ' * POW(10, price.settlement_precision)'); - } - - if (args.max_price) { - query.addCondition('price.price <= ' + query.addVariable(args.max_price) + ' * POW(10, price.settlement_precision)'); - } - - if (args.collection_name) { - query.equalMany('sale.collection_name', args.collection_name.split(',')); - } - - query.append('ORDER BY asset.contract, asset.template_id, price.price ASC'); - - const sortColumnMapping: {[key: string]: string} = { - price: 't1.price', - template_id: 't1.template_id', - }; - - let queryString = 'SELECT * FROM (' + query.buildString() + ') t1 '; - queryString += 'ORDER BY ' + sortColumnMapping[args.sort] + ' ' + args.order + ' NULLS LAST, t1.template_id ASC '; - queryString += 'LIMIT ' + query.addVariable(args.limit) + ' OFFSET ' + query.addVariable((args.page - 1) * args.limit) + ' '; - - const saleResult = await ctx.db.query(queryString, query.buildValues()); - - const result = await ctx.db.query( - 'SELECT * FROM atomicmarket_sales_master WHERE market_contract = $1 AND sale_id = ANY ($2)', - [ctx.coreArgs.atomicmarket_account, saleResult.rows.map(row => row.sale_id)] - ); - - const saleLookup: {[key: string]: any} = result.rows.reduce((prev, current) => { - prev[String(current.sale_id)] = current; - - return prev; - }, {}); - - return await fillSales( - ctx.db, ctx.coreArgs.atomicassets_account, saleResult.rows.map((row) => formatSale(saleLookup[String(row.sale_id)])) - ); -} From 2cbac5294c6e2efdfba34f3a1453b862c329904d Mon Sep 17 00:00:00 2001 From: Fabian Emilius Date: Mon, 25 Apr 2022 00:50:28 +0200 Subject: [PATCH 09/16] Remove atomicmarket_sale_prices materialized view --- definitions/migrations/1.3.11/database.sql | 9 ++++----- definitions/migrations/1.3.12/atomicassets.sql | 6 ++---- definitions/migrations/1.3.12/atomicmarket.sql | 1 + definitions/migrations/1.3.12/database.sql | 1 - .../namespaces/atomicmarket/handlers/sales.ts | 1 + src/filler/handlers/atomicmarket/index.ts | 17 +++-------------- 6 files changed, 11 insertions(+), 24 deletions(-) create mode 100644 definitions/migrations/1.3.12/atomicmarket.sql diff --git a/definitions/migrations/1.3.11/database.sql b/definitions/migrations/1.3.11/database.sql index 4a631a40..f20772d6 100644 --- a/definitions/migrations/1.3.11/database.sql +++ b/definitions/migrations/1.3.11/database.sql @@ -1,9 +1,8 @@ -select brin_summarize_new_values('contract_traces_idx_global_sequence'::regclass); -select brin_summarize_new_values('contract_traces_idx_created_at_time'::regclass); +SELECT brin_summarize_new_values('contract_traces_idx_global_sequence'::regclass); +SELECT brin_summarize_new_values('contract_traces_idx_created_at_time'::regclass); - -alter index contract_traces_idx_global_sequence set (autosummarize = on); -alter index contract_traces_idx_created_at_time set (autosummarize = on); +ALTER INDEX contract_traces_idx_global_sequence set (autosummarize = on); +ALTER INDEX contract_traces_idx_created_at_time set (autosummarize = on); UPDATE dbinfo SET "value" = '1.3.11' WHERE name = 'version'; diff --git a/definitions/migrations/1.3.12/atomicassets.sql b/definitions/migrations/1.3.12/atomicassets.sql index ef09955e..151c6c31 100644 --- a/definitions/migrations/1.3.12/atomicassets.sql +++ b/definitions/migrations/1.3.12/atomicassets.sql @@ -1,7 +1,5 @@ +SELECT brin_summarize_new_values('atomicassets_mints_idx_asset_id'::regclass); -select brin_summarize_new_values('atomicassets_mints_idx_asset_id'::regclass); - - -alter index atomicassets_mints_idx_asset_id set (autosummarize = on); +ALTER INDEX atomicassets_mints_idx_asset_id set (autosummarize = on); ALTER TABLE atomicassets_templates SET (fillfactor = 90); diff --git a/definitions/migrations/1.3.12/atomicmarket.sql b/definitions/migrations/1.3.12/atomicmarket.sql new file mode 100644 index 00000000..4f77cf86 --- /dev/null +++ b/definitions/migrations/1.3.12/atomicmarket.sql @@ -0,0 +1 @@ +DROP MATERIALIZED VIEW IF EXISTS atomicmarket_sale_prices; diff --git a/definitions/migrations/1.3.12/database.sql b/definitions/migrations/1.3.12/database.sql index 93a89ab1..2da9ff56 100644 --- a/definitions/migrations/1.3.12/database.sql +++ b/definitions/migrations/1.3.12/database.sql @@ -1,2 +1 @@ - UPDATE dbinfo SET "value" = '1.3.12' WHERE name = 'version'; diff --git a/src/api/namespaces/atomicmarket/handlers/sales.ts b/src/api/namespaces/atomicmarket/handlers/sales.ts index a694cbc9..22d9ec9c 100644 --- a/src/api/namespaces/atomicmarket/handlers/sales.ts +++ b/src/api/namespaces/atomicmarket/handlers/sales.ts @@ -97,6 +97,7 @@ export async function getSalesAction(params: RequestValues, ctx: AtomicMarketCon sale_id: {column: 'listing.sale_id', nullable: false, numericIndex: true}, created: {column: 'listing.created_at_time', nullable: false, numericIndex: true}, updated: {column: 'listing.updated_at_time', nullable: false, numericIndex: true}, + price: {column: 'listing.final_price', nullable: true, numericIndex: true}, template_mint: {column: 'LOWER(listing.template_mint)', nullable: true, numericIndex: false} }; diff --git a/src/filler/handlers/atomicmarket/index.ts b/src/filler/handlers/atomicmarket/index.ts index 8e5acb2d..67bc1cd3 100644 --- a/src/filler/handlers/atomicmarket/index.ts +++ b/src/filler/handlers/atomicmarket/index.ts @@ -85,7 +85,7 @@ export default class AtomicMarketHandler extends ContractHandler { ]; const materializedViews = [ - 'atomicmarket_template_prices', 'atomicmarket_sale_prices', + 'atomicmarket_template_prices', 'atomicmarket_stats_prices', 'atomicmarket_stats_markets' ]; @@ -119,16 +119,6 @@ export default class AtomicMarketHandler extends ContractHandler { } static async upgrade(client: PoolClient, version: string): Promise { - if (version === '1.2.1') { - logger.info('Upgrading materialized view atomicmarket_sale_prices'); - - await client.query('DROP MATERIALIZED VIEW IF EXISTS atomicmarket_sale_prices;'); - - await client.query(fs.readFileSync('./definitions/materialized/atomicmarket_sale_prices.sql', {encoding: 'utf8'})); - - await client.query('REFRESH MATERIALIZED VIEW atomicmarket_sale_prices;'); - } - if (version === '1.2.2') { await client.query('DROP VIEW IF EXISTS atomicmarket_assets_master CASCADE;'); await client.query(fs.readFileSync('./definitions/views/atomicmarket_assets_master.sql', {encoding: 'utf8'})); @@ -261,7 +251,7 @@ export default class AtomicMarketHandler extends ContractHandler { } const materializedViews = [ - 'atomicmarket_template_prices', 'atomicmarket_sale_prices', + 'atomicmarket_template_prices', 'atomicmarket_stats_prices', 'atomicmarket_stats_markets' ]; @@ -288,8 +278,7 @@ export default class AtomicMarketHandler extends ContractHandler { const materializedViews: Array<{name: string, priority: JobQueuePriority}> = [ {name: 'atomicmarket_template_prices', priority: JobQueuePriority.LOW}, {name: 'atomicmarket_stats_prices', priority: JobQueuePriority.LOW}, - {name: 'atomicmarket_stats_markets', priority: JobQueuePriority.LOW}, - {name: 'atomicmarket_sale_prices', priority: JobQueuePriority.LOW}, + {name: 'atomicmarket_stats_markets', priority: JobQueuePriority.LOW} ]; for (const view of materializedViews) { From 0203f237b80d4520db21dcb60d5c791edd593481 Mon Sep 17 00:00:00 2001 From: Fabian Emilius Date: Mon, 25 Apr 2022 16:30:10 +0200 Subject: [PATCH 10/16] Fix error for symbol not found --- definitions/materialized/atomicmarket_sale_prices.sql | 6 ------ src/api/namespaces/atomicmarket/handlers/sales2.ts | 8 +++++++- 2 files changed, 7 insertions(+), 7 deletions(-) delete mode 100644 definitions/materialized/atomicmarket_sale_prices.sql diff --git a/definitions/materialized/atomicmarket_sale_prices.sql b/definitions/materialized/atomicmarket_sale_prices.sql deleted file mode 100644 index ed6759d3..00000000 --- a/definitions/materialized/atomicmarket_sale_prices.sql +++ /dev/null @@ -1,6 +0,0 @@ -CREATE MATERIALIZED VIEW IF NOT EXISTS atomicmarket_sale_prices AS - SELECT * FROM atomicmarket_sale_prices_master WHERE state NOT IN (2); - -CREATE UNIQUE INDEX atomicmarket_sale_prices_pkey ON atomicmarket_sale_prices (market_contract, sale_id); - -CREATE INDEX atomicmarket_sale_prices_price ON atomicmarket_sale_prices USING btree (price); diff --git a/src/api/namespaces/atomicmarket/handlers/sales2.ts b/src/api/namespaces/atomicmarket/handlers/sales2.ts index f26fb5a0..d5180d71 100644 --- a/src/api/namespaces/atomicmarket/handlers/sales2.ts +++ b/src/api/namespaces/atomicmarket/handlers/sales2.ts @@ -151,7 +151,13 @@ async function buildSaleFilterV2(search: SalesSearchOptions): Promise { if (args.symbol) { query.equal('listing.settlement_symbol', args.symbol); - const {token_precision} = (await ctx.db.query('SELECT token_precision FROM atomicmarket_tokens WHERE market_contract = $1 AND token_symbol = $2', [ctx.coreArgs.atomicmarket_account, args.symbol])).rows[0]; + const token = await ctx.db.query('SELECT token_precision FROM atomicmarket_tokens WHERE market_contract = $1 AND token_symbol = $2', [ctx.coreArgs.atomicmarket_account, args.symbol]); + + if (token.rows.length === 0) { + throw new ApiError('Symbol not found'); + } + + const {token_precision} = token.rows[0]; if (args.min_price) { query.addCondition(`listing.price >= 1.0 * ${query.addVariable(args.min_price)} * POWER(10, ${query.addVariable(token_precision)})`); From f3484a7453ddd1a34f1d159f5083bd2e8ca0598b Mon Sep 17 00:00:00 2001 From: fabian-emilius Date: Mon, 25 Apr 2022 22:50:27 +0200 Subject: [PATCH 11/16] Bump dependencies --- package.json | 52 +- src/connections/redis.ts | 10 +- yarn.lock | 999 ++++++++++++++++++++------------------- 3 files changed, 544 insertions(+), 517 deletions(-) diff --git a/package.json b/package.json index cbcce4d2..855e5ba5 100644 --- a/package.json +++ b/package.json @@ -22,55 +22,55 @@ "dependencies": { "async-exit-hook": "^2.0.1", "atomicassets": "^1.4.2", - "await-lock": "^2.1.0", - "body-parser": "^1.19.1", + "await-lock": "^2.2.1", + "body-parser": "^1.20.0", "common-tags": "^1.8.2", "cookie-parser": "^1.4.6", "cors": "^2.8.5", "eosjs": "^22.1.0", - "express": "^4.17.2", - "express-rate-limit": "^6.2.0", + "express": "^4.18.0", + "express-rate-limit": "^6.4.0", "int64-buffer": "^1.0.1", - "ioredis": "^4.28.3", - "moize": "^6.1.0", + "ioredis": "^5.0.4", + "moize": "^6.1.1", "node-fetch": "^2.6.7", "node-worker-threads-pool": "^1.5.1", "p-queue": "^6.6.2", - "pg": "^8.7.1", - "pm2": "^5.1.2", + "pg": "^8.7.3", + "pm2": "^5.2.0", "prom-client": "^14.0.1", - "rate-limit-redis": "^3.0.0", - "redis": "^4.0.3", - "socket.io": "^4.4.1", + "rate-limit-redis": "^3.0.1", + "redis": "^4.0.6", + "socket.io": "^4.5.0", "swagger-ui-express": "^4.3.0", "text-encoding": "^0.7.0", - "winston": "^3.3.3", - "ws": "^7.5.6" + "winston": "^3.7.2", + "ws": "^7.5.7" }, "devDependencies": { "@types/body-parser": "^1.19.2", - "@types/chai": "^4.3.0", + "@types/chai": "^4.3.1", "@types/common-tags": "^1.8.1", "@types/cookie-parser": "^1.4.2", "@types/cors": "^2.8.12", "@types/elliptic": "^6.4.14", "@types/express": "^4.17.13", - "@types/ioredis": "^4.28.7", - "@types/mocha": "^9.0.0", - "@types/node": "^16.11.12", - "@types/node-fetch": "^2.5.12", - "@types/pg": "^8.6.4", + "@types/ioredis": "^4.28.10", + "@types/mocha": "^9.1.1", + "@types/node": "^16.11.29", + "@types/node-fetch": "^2.6.1", + "@types/pg": "^8.6.5", "@types/swagger-ui-express": "^4.1.3", "@types/text-encoding": "^0.0.36", "@types/ws": "^7.4.7", - "@typescript-eslint/eslint-plugin": "^5.7.0", - "@typescript-eslint/parser": "^5.7.0", - "chai": "^4.3.4", + "@typescript-eslint/eslint-plugin": "^5.21.0", + "@typescript-eslint/parser": "^5.21.0", + "chai": "^4.3.6", "eslint": "^7.32.0", - "mocha": "^9.1.3", + "mocha": "^9.2.2", "rimraf": "^3.0.2", - "ts-loader": "^9.2.6", - "ts-node": "^10.4.0", - "typescript": "^4.5.5" + "ts-loader": "^9.2.8", + "ts-node": "^10.7.0", + "typescript": "^4.6.3" } } diff --git a/src/connections/redis.ts b/src/connections/redis.ts index 880fd87e..c32ecf9f 100644 --- a/src/connections/redis.ts +++ b/src/connections/redis.ts @@ -1,9 +1,9 @@ -import * as IORedis from 'ioredis'; +import Redis from 'ioredis'; import { createClient, RedisClientType } from 'redis'; export default class RedisConnection { - readonly ioRedis: IORedis.Redis; - readonly ioRedisSub: IORedis.Redis; + readonly ioRedis: Redis; + readonly ioRedisSub: Redis; readonly nodeRedis: RedisClientType; readonly nodeRedisSub: RedisClientType; @@ -11,8 +11,8 @@ export default class RedisConnection { private initialized = false; constructor(host: string, port: number) { - this.ioRedis = new IORedis({ host, port }); - this.ioRedisSub = new IORedis({ host, port }); + this.ioRedis = new Redis({ host, port }); + this.ioRedisSub = new Redis({ host, port }); this.nodeRedis = createClient({ url: `redis://${host}:${port}` }); this.nodeRedisSub = createClient({ url: `redis://${host}:${port}` }); diff --git a/yarn.lock b/yarn.lock index 287b1338..7bbcd222 100644 --- a/yarn.lock +++ b/yarn.lock @@ -15,14 +15,19 @@ integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw== "@babel/highlight@^7.10.4": - version "7.16.10" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.10.tgz#744f2eb81579d6eea753c227b0f570ad785aba88" - integrity sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw== + version "7.17.9" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.17.9.tgz#61b2ee7f32ea0454612def4fccdae0de232b73e3" + integrity sha512-J9PfEKCbFIv2X5bjTMiZu6Vf341N05QIY+d6FvVKynkG1S7G0j3I0QoRtWIrXhZ+/Nlb5Q0MzqL7TokEJ5BNHg== dependencies: "@babel/helper-validator-identifier" "^7.16.7" chalk "^2.0.0" js-tokens "^4.0.0" +"@colors/colors@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" + integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== + "@cspotcode/source-map-consumer@0.8.0": version "0.8.0" resolved "https://registry.yarnpkg.com/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz#33bf4b7b39c178821606f669bbc447a6a629786b" @@ -36,9 +41,9 @@ "@cspotcode/source-map-consumer" "0.8.0" "@dabh/diagnostics@^2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@dabh/diagnostics/-/diagnostics-2.0.2.tgz#290d08f7b381b8f94607dc8f471a12c675f9db31" - integrity sha512-+A1YivoVDNNVCdfozHSR8v/jyuuLTMXwjWuxPFlFlUapXoGc+Gj9mDlTDDfrwl7rXCl2tNZ0kE8sIBO6YOn96Q== + version "2.0.3" + resolved "https://registry.yarnpkg.com/@dabh/diagnostics/-/diagnostics-2.0.3.tgz#7f7e97ee9a725dffc7808d93668cc984e1dc477a" + integrity sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA== dependencies: colorspace "1.1.x" enabled "2.0.x" @@ -73,15 +78,20 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== +"@ioredis/commands@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@ioredis/commands/-/commands-1.1.1.tgz#2ba4299ea624a6bfac15b35f6df90b0015691ec3" + integrity sha512-fsR4P/ROllzf/7lXYyElUJCheWdTJVJvOTps8v9IWKFATxR61ANOlnoPqhH099xYLrJGpc2ZQ28B3rMeUt5VQg== + "@node-redis/bloom@1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@node-redis/bloom/-/bloom-1.0.1.tgz#144474a0b7dc4a4b91badea2cfa9538ce0a1854e" integrity sha512-mXEBvEIgF4tUzdIN89LiYsbi6//EdpFA7L8M+DHCvePXg+bfHWi+ct5VI6nHUFQE5+ohm/9wmgihCH3HSkeKsw== -"@node-redis/client@1.0.3": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@node-redis/client/-/client-1.0.3.tgz#ece282b7ee07283d744e6ab1fa72f2d47641402c" - integrity sha512-IXNgOG99PHGL3NxN3/e8J8MuX+H08I+OMNmheGmZBXngE0IntaCQwwrd7NzmiHA+zH3SKHiJ+6k3P7t7XYknMw== +"@node-redis/client@1.0.5": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@node-redis/client/-/client-1.0.5.tgz#ebac5e2bbf12214042a37621604973a954ede755" + integrity sha512-ESZ3bd1f+od62h4MaBLKum+klVJfA4wAeLHcVQBkoXa1l0viFesOWnakLQqKg+UyrlJhZmXJWtu0Y9v7iTMrig== dependencies: cluster-key-slot "1.1.0" generic-pool "3.8.2" @@ -98,15 +108,15 @@ resolved "https://registry.yarnpkg.com/@node-redis/json/-/json-1.0.2.tgz#8ad2d0f026698dc1a4238cc3d1eb099a3bee5ab8" integrity sha512-qVRgn8WfG46QQ08CghSbY4VhHFgaTY71WjpwRBGEuqGPfWwfRcIf3OqSpR7Q/45X+v3xd8mvYjywqh0wqJ8T+g== -"@node-redis/search@1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@node-redis/search/-/search-1.0.2.tgz#8cfc91006ea787df801d41410283e1f59027f818" - integrity sha512-gWhEeji+kTAvzZeguUNJdMSZNH2c5dv3Bci8Nn2f7VGuf6IvvwuZDSBOuOlirLVgayVuWzAG7EhwaZWK1VDnWQ== +"@node-redis/search@1.0.5": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@node-redis/search/-/search-1.0.5.tgz#96050007eb7c50a7e47080320b4f12aca8cf94c4" + integrity sha512-MCOL8iCKq4v+3HgEQv8zGlSkZyXSXtERgrAJ4TSryIG/eLFy84b57KmNNa/V7M1Q2Wd2hgn2nPCGNcQtk1R1OQ== -"@node-redis/time-series@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@node-redis/time-series/-/time-series-1.0.1.tgz#703149f8fa4f6fff377c61a0873911e7c1ba5cc3" - integrity sha512-+nTn6EewVj3GlUXPuD3dgheWqo219jTxlo6R+pg24OeVvFHx9aFGGiyOgj3vBPhWUdRZ0xMcujXV5ki4fbLyMw== +"@node-redis/time-series@1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@node-redis/time-series/-/time-series-1.0.2.tgz#5dd3638374edd85ebe0aa6b0e87addc88fb9df69" + integrity sha512-HGQ8YooJ8Mx7l28tD7XjtB3ImLEjlUxG1wC1PAjxu6hPJqjPshUZxAICzDqDjtIbhDTf48WXXUcx8TQJB1XTKA== "@nodelib/fs.scandir@2.1.5": version "2.1.5" @@ -257,10 +267,10 @@ "@types/connect" "*" "@types/node" "*" -"@types/chai@^4.3.0": - version "4.3.0" - resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.0.tgz#23509ebc1fa32f1b4d50d6a66c4032d5b8eaabdc" - integrity sha512-/ceqdqeRraGolFTcfoXNiqjyQhZzbINDngeoAq9GoHa8PPK1yNzTaxWjA6BFWp5Ua9JpXEMSS4s5i9tS0hOJtw== +"@types/chai@^4.3.1": + version "4.3.1" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.1.tgz#e2c6e73e0bdeb2521d00756d099218e9f5d90a04" + integrity sha512-/zPMqDkzSZ8t3VtxOa4KPq7uzzW978M9Tvh+j7GHKuo6k6GTLxPJ4J5gE5cjfJ26pnXst0N5Hax8Sr0T2Mi9zQ== "@types/common-tags@^1.8.1": version "1.8.1" @@ -322,50 +332,50 @@ "@types/qs" "*" "@types/serve-static" "*" -"@types/ioredis@^4.28.7": - version "4.28.7" - resolved "https://registry.yarnpkg.com/@types/ioredis/-/ioredis-4.28.7.tgz#ee79987ef80597ba8c17cfbf9345859ff9233c2d" - integrity sha512-jnSGCD2/TPk02j6v6CGqaCEl0LbmLgK6jUuk/AFaSNUBV+SCHiG7E7fnwJreN6hw9GqtLAFkJs4zFbkJrz11mQ== +"@types/ioredis@^4.28.10": + version "4.28.10" + resolved "https://registry.yarnpkg.com/@types/ioredis/-/ioredis-4.28.10.tgz#40ceb157a4141088d1394bb87c98ed09a75a06ff" + integrity sha512-69LyhUgrXdgcNDv7ogs1qXZomnfOEnSmrmMFqKgt1XMJxmoOSG/u3wYy13yACIfKuMJ8IhKgHafDO3sx19zVQQ== dependencies: "@types/node" "*" "@types/json-schema@^7.0.9": - version "7.0.9" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" - integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ== + version "7.0.11" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" + integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== "@types/mime@^1": version "1.3.2" resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a" integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw== -"@types/mocha@^9.0.0": - version "9.1.0" - resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-9.1.0.tgz#baf17ab2cca3fcce2d322ebc30454bff487efad5" - integrity sha512-QCWHkbMv4Y5U9oW10Uxbr45qMMSzl4OzijsozynUAgx3kEHUdXB00udx2dWDQ7f2TU2a2uuiFaRZjCe3unPpeg== +"@types/mocha@^9.1.1": + version "9.1.1" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-9.1.1.tgz#e7c4f1001eefa4b8afbd1eee27a237fee3bf29c4" + integrity sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw== -"@types/node-fetch@^2.5.12": - version "2.5.12" - resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.12.tgz#8a6f779b1d4e60b7a57fb6fd48d84fb545b9cc66" - integrity sha512-MKgC4dlq4kKNa/mYrwpKfzQMB5X3ee5U6fSprkKpToBqBmX4nFZL9cW5jl6sWn+xpRJ7ypWh2yyqqr8UUCstSw== +"@types/node-fetch@^2.6.1": + version "2.6.1" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.1.tgz#8f127c50481db65886800ef496f20bbf15518975" + integrity sha512-oMqjURCaxoSIsHSr1E47QHzbmzNR5rK8McHuNb11BOM9cHcIK3Avy0s/b2JlXHoQGTYS3NsvWzV1M0iK7l0wbA== dependencies: "@types/node" "*" form-data "^3.0.0" "@types/node@*", "@types/node@>=10.0.0": - version "17.0.10" - resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.10.tgz#616f16e9d3a2a3d618136b1be244315d95bd7cab" - integrity sha512-S/3xB4KzyFxYGCppyDt68yzBU9ysL88lSdIah4D6cptdcltc4NCPCAMc0+PCpg/lLIyC7IPvj2Z52OJWeIUkog== + version "17.0.27" + resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.27.tgz#f4df3981ae8268c066e8f49995639f855469081e" + integrity sha512-4/Ke7bbWOasuT3kceBZFGakP1dYN2XFd8v2l9bqF2LNWrmeU07JLpp56aEeG6+Q3olqO5TvXpW0yaiYnZJ5CXg== -"@types/node@^16.11.12": - version "16.11.21" - resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.21.tgz#474d7589a30afcf5291f59bd49cca9ad171ffde4" - integrity sha512-Pf8M1XD9i1ksZEcCP8vuSNwooJ/bZapNmIzpmsMaL+jMI+8mEYU3PKvs+xDNuQcJWF/x24WzY4qxLtB0zNow9A== +"@types/node@^16.11.29": + version "16.11.29" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.29.tgz#2422b0bf46afb2568dc71df903afa36f56bab8ea" + integrity sha512-9dDdonLyPJQJ/kdOlDxAah+bTI+u2ccF3k62FErhquDuggoCX6piWez7j7o6yNE+rP2IRcZVQ6Tw4N0P38+rWA== -"@types/pg@^8.6.4": - version "8.6.4" - resolved "https://registry.yarnpkg.com/@types/pg/-/pg-8.6.4.tgz#da1ae9d2f53f2dbfdd2b37e0eb478bf60d517f60" - integrity sha512-uYA7UMVzDFpJobCrqwW/iWkFmvizy6knIUgr0Quaw7K1Le3ZnF7hI3bKqFoxPZ+fju1Sc7zdTvOl9YfFZPcmeA== +"@types/pg@^8.6.5": + version "8.6.5" + resolved "https://registry.yarnpkg.com/@types/pg/-/pg-8.6.5.tgz#2dce9cb468a6a5e0f1296a59aea3ac75dd27b702" + integrity sha512-tOkGtAqRVkHa/PVZicq67zuujI4Oorfglsr2IbKofDwBSysnaqSx7W1mDqFqdkGE6Fbgh+PZAl0r/BWON/mozw== dependencies: "@types/node" "*" pg-protocol "*" @@ -409,14 +419,14 @@ dependencies: "@types/node" "*" -"@typescript-eslint/eslint-plugin@^5.7.0": - version "5.10.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.10.0.tgz#e90afea96dff8620892ad216b0e4ccdf8ee32d3a" - integrity sha512-XXVKnMsq2fuu9K2KsIxPUGqb6xAImz8MEChClbXmE3VbveFtBUU5bzM6IPVWqzyADIgdkS2Ws/6Xo7W2TeZWjQ== +"@typescript-eslint/eslint-plugin@^5.21.0": + version "5.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.21.0.tgz#bfc22e0191e6404ab1192973b3b4ea0461c1e878" + integrity sha512-fTU85q8v5ZLpoZEyn/u1S2qrFOhi33Edo2CZ0+q1gDaWWm0JuPh3bgOyU8lM0edIEYgKLDkPFiZX2MOupgjlyg== dependencies: - "@typescript-eslint/scope-manager" "5.10.0" - "@typescript-eslint/type-utils" "5.10.0" - "@typescript-eslint/utils" "5.10.0" + "@typescript-eslint/scope-manager" "5.21.0" + "@typescript-eslint/type-utils" "5.21.0" + "@typescript-eslint/utils" "5.21.0" debug "^4.3.2" functional-red-black-tree "^1.0.1" ignore "^5.1.8" @@ -424,69 +434,69 @@ semver "^7.3.5" tsutils "^3.21.0" -"@typescript-eslint/parser@^5.7.0": - version "5.10.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.10.0.tgz#8f59e036f5f1cffc178cacbd5ccdd02aeb96c91c" - integrity sha512-pJB2CCeHWtwOAeIxv8CHVGJhI5FNyJAIpx5Pt72YkK3QfEzt6qAlXZuyaBmyfOdM62qU0rbxJzNToPTVeJGrQw== +"@typescript-eslint/parser@^5.21.0": + version "5.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.21.0.tgz#6cb72673dbf3e1905b9c432175a3c86cdaf2071f" + integrity sha512-8RUwTO77hstXUr3pZoWZbRQUxXcSXafZ8/5gpnQCfXvgmP9gpNlRGlWzvfbEQ14TLjmtU8eGnONkff8U2ui2Eg== dependencies: - "@typescript-eslint/scope-manager" "5.10.0" - "@typescript-eslint/types" "5.10.0" - "@typescript-eslint/typescript-estree" "5.10.0" + "@typescript-eslint/scope-manager" "5.21.0" + "@typescript-eslint/types" "5.21.0" + "@typescript-eslint/typescript-estree" "5.21.0" debug "^4.3.2" -"@typescript-eslint/scope-manager@5.10.0": - version "5.10.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.10.0.tgz#bb5d872e8b9e36203908595507fbc4d3105329cb" - integrity sha512-tgNgUgb4MhqK6DoKn3RBhyZ9aJga7EQrw+2/OiDk5hKf3pTVZWyqBi7ukP+Z0iEEDMF5FDa64LqODzlfE4O/Dg== +"@typescript-eslint/scope-manager@5.21.0": + version "5.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.21.0.tgz#a4b7ed1618f09f95e3d17d1c0ff7a341dac7862e" + integrity sha512-XTX0g0IhvzcH/e3393SvjRCfYQxgxtYzL3UREteUneo72EFlt7UNoiYnikUtmGVobTbhUDByhJ4xRBNe+34kOQ== dependencies: - "@typescript-eslint/types" "5.10.0" - "@typescript-eslint/visitor-keys" "5.10.0" + "@typescript-eslint/types" "5.21.0" + "@typescript-eslint/visitor-keys" "5.21.0" -"@typescript-eslint/type-utils@5.10.0": - version "5.10.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.10.0.tgz#8524b9479c19c478347a7df216827e749e4a51e5" - integrity sha512-TzlyTmufJO5V886N+hTJBGIfnjQDQ32rJYxPaeiyWKdjsv2Ld5l8cbS7pxim4DeNs62fKzRSt8Q14Evs4JnZyQ== +"@typescript-eslint/type-utils@5.21.0": + version "5.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.21.0.tgz#ff89668786ad596d904c21b215e5285da1b6262e" + integrity sha512-MxmLZj0tkGlkcZCSE17ORaHl8Th3JQwBzyXL/uvC6sNmu128LsgjTX0NIzy+wdH2J7Pd02GN8FaoudJntFvSOw== dependencies: - "@typescript-eslint/utils" "5.10.0" + "@typescript-eslint/utils" "5.21.0" debug "^4.3.2" tsutils "^3.21.0" -"@typescript-eslint/types@5.10.0": - version "5.10.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.10.0.tgz#beb3cb345076f5b088afe996d57bcd1dfddaa75c" - integrity sha512-wUljCgkqHsMZbw60IbOqT/puLfyqqD5PquGiBo1u1IS3PLxdi3RDGlyf032IJyh+eQoGhz9kzhtZa+VC4eWTlQ== +"@typescript-eslint/types@5.21.0": + version "5.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.21.0.tgz#8cdb9253c0dfce3f2ab655b9d36c03f72e684017" + integrity sha512-XnOOo5Wc2cBlq8Lh5WNvAgHzpjnEzxn4CJBwGkcau7b/tZ556qrWXQz4DJyChYg8JZAD06kczrdgFPpEQZfDsA== -"@typescript-eslint/typescript-estree@5.10.0": - version "5.10.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.10.0.tgz#4be24a3dea0f930bb1397c46187d0efdd955a224" - integrity sha512-x+7e5IqfwLwsxTdliHRtlIYkgdtYXzE0CkFeV6ytAqq431ZyxCFzNMNR5sr3WOlIG/ihVZr9K/y71VHTF/DUQA== +"@typescript-eslint/typescript-estree@5.21.0": + version "5.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.21.0.tgz#9f0c233e28be2540eaed3df050f0d54fb5aa52de" + integrity sha512-Y8Y2T2FNvm08qlcoSMoNchh9y2Uj3QmjtwNMdRQkcFG7Muz//wfJBGBxh8R7HAGQFpgYpdHqUpEoPQk+q9Kjfg== dependencies: - "@typescript-eslint/types" "5.10.0" - "@typescript-eslint/visitor-keys" "5.10.0" + "@typescript-eslint/types" "5.21.0" + "@typescript-eslint/visitor-keys" "5.21.0" debug "^4.3.2" globby "^11.0.4" is-glob "^4.0.3" semver "^7.3.5" tsutils "^3.21.0" -"@typescript-eslint/utils@5.10.0": - version "5.10.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.10.0.tgz#c3d152a85da77c400e37281355561c72fb1b5a65" - integrity sha512-IGYwlt1CVcFoE2ueW4/ioEwybR60RAdGeiJX/iDAw0t5w0wK3S7QncDwpmsM70nKgGTuVchEWB8lwZwHqPAWRg== +"@typescript-eslint/utils@5.21.0": + version "5.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.21.0.tgz#51d7886a6f0575e23706e5548c7e87bce42d7c18" + integrity sha512-q/emogbND9wry7zxy7VYri+7ydawo2HDZhRZ5k6yggIvXa7PvBbAAZ4PFH/oZLem72ezC4Pr63rJvDK/sTlL8Q== dependencies: "@types/json-schema" "^7.0.9" - "@typescript-eslint/scope-manager" "5.10.0" - "@typescript-eslint/types" "5.10.0" - "@typescript-eslint/typescript-estree" "5.10.0" + "@typescript-eslint/scope-manager" "5.21.0" + "@typescript-eslint/types" "5.21.0" + "@typescript-eslint/typescript-estree" "5.21.0" eslint-scope "^5.1.1" eslint-utils "^3.0.0" -"@typescript-eslint/visitor-keys@5.10.0": - version "5.10.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.10.0.tgz#770215497ad67cd15a572b52089991d5dfe06281" - integrity sha512-GMxj0K1uyrFLPKASLmZzCuSddmjZVbVj3Ouy5QVuIGKZopxvOr24JsS7gruz6C3GExE01mublZ3mIBOaon9zuQ== +"@typescript-eslint/visitor-keys@5.21.0": + version "5.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.21.0.tgz#453fb3662409abaf2f8b1f65d515699c888dd8ae" + integrity sha512-SX8jNN+iHqAF0riZQMkm7e8+POXa/fXw5cxL+gjpyP+FI+JVNhii53EmQgDAfDcBpFekYSlO0fGytMQwRiMQCA== dependencies: - "@typescript-eslint/types" "5.10.0" + "@typescript-eslint/types" "5.21.0" eslint-visitor-keys "^3.0.0" "@ungap/promise-all-settled@1.1.2": @@ -494,13 +504,13 @@ resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44" integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q== -accepts@~1.3.4, accepts@~1.3.7: - version "1.3.7" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" - integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== +accepts@~1.3.4, accepts@~1.3.8: + version "1.3.8" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== dependencies: - mime-types "~2.1.24" - negotiator "0.6.2" + mime-types "~2.1.34" + negotiator "0.6.3" acorn-jsx@^5.3.1: version "5.3.2" @@ -540,9 +550,9 @@ ajv@^6.10.0, ajv@^6.12.4: uri-js "^4.2.2" ajv@^8.0.1: - version "8.9.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.9.0.tgz#738019146638824dea25edcf299dcba1b0e7eb18" - integrity sha512-qOKJyNj/h+OWx7s5DePL6Zu1KeM9jPZhwBqs+7DzP6bGOvqzVCSf0xueYmVuaC/oQ/VtS2zLMLHdQFbkka+XDQ== + version "8.11.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.11.0.tgz#977e91dd96ca669f54a11e23e378e33b884a565f" + integrity sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg== dependencies: fast-deep-equal "^3.1.1" json-schema-traverse "^1.0.0" @@ -651,9 +661,9 @@ async-listener@^0.6.0: shimmer "^1.1.0" async@^2.6.3, async@~2.6.1: - version "2.6.3" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" - integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg== + version "2.6.4" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221" + integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA== dependencies: lodash "^4.17.14" @@ -675,10 +685,10 @@ atomicassets@^1.4.2: big-integer "^1.6.48" pure-cache "^1.0.5" -await-lock@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/await-lock/-/await-lock-2.1.0.tgz#bc78c51d229a34d5d90965a1c94770e772c6145e" - integrity sha512-t7Zm5YGgEEc/3eYAicF32m/TNvL+XOeYZy9CvBUeJY/szM7frLolFylhrlZNWV/ohWhcUXygrBGjYmoQdxF4CQ== +await-lock@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/await-lock/-/await-lock-2.2.1.tgz#97477657dd16c5836978129ac4cebf33f93113c8" + integrity sha512-MPj/sdosJsfhW/6xsvj3Nk7bHc2F7Ghw8PewCjqbmFJfQGTZ1aVcZfPnb6T8qZswIMnXVWjepeiZv4n2t0luvQ== axios@^0.21.0: version "0.21.4" @@ -732,21 +742,23 @@ bodec@^0.1.0: resolved "https://registry.yarnpkg.com/bodec/-/bodec-0.1.0.tgz#bc851555430f23c9f7650a75ef64c6a94c3418cc" integrity sha1-vIUVVUMPI8n3ZQp172TGqUw0GMw= -body-parser@1.19.1, body-parser@^1.19.1: - version "1.19.1" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.1.tgz#1499abbaa9274af3ecc9f6f10396c995943e31d4" - integrity sha512-8ljfQi5eBk8EJfECMrgqNGWPEY5jWP+1IzkzkGdFFEwFQZZyaZ21UqdaHktgiMlH0xLHqIFtE/u2OYE5dOtViA== +body-parser@1.20.0, body-parser@^1.20.0: + version "1.20.0" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.0.tgz#3de69bd89011c11573d7bfee6a64f11b6bd27cc5" + integrity sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg== dependencies: - bytes "3.1.1" + bytes "3.1.2" content-type "~1.0.4" debug "2.6.9" - depd "~1.1.2" - http-errors "1.8.1" + depd "2.0.0" + destroy "1.2.0" + http-errors "2.0.0" iconv-lite "0.4.24" - on-finished "~2.3.0" - qs "6.9.6" - raw-body "2.4.2" + on-finished "2.4.1" + qs "6.10.3" + raw-body "2.5.1" type-is "~1.6.18" + unpipe "1.0.0" brace-expansion@^1.1.7: version "1.1.11" @@ -756,7 +768,7 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -braces@^3.0.1, braces@~3.0.2: +braces@^3.0.2, braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== @@ -783,10 +795,18 @@ buffer-writer@2.0.0: resolved "https://registry.yarnpkg.com/buffer-writer/-/buffer-writer-2.0.0.tgz#ce7eb81a38f7829db09c873f2fbb792c0c98ec04" integrity sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw== -bytes@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.1.tgz#3f018291cb4cbad9accb6e6970bca9c8889e879a" - integrity sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg== +bytes@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== + +call-bind@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" callsites@^3.0.0: version "3.1.0" @@ -798,15 +818,16 @@ camelcase@^6.0.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -chai@^4.3.4: - version "4.3.4" - resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.4.tgz#b55e655b31e1eac7099be4c08c21964fce2e6c49" - integrity sha512-yS5H68VYOCtN1cjfwumDSuzn/9c+yza4f3reKXlE5rUg7SFcCEy90gJvydNgOYtblyf4Zi6jIWRnXOgErta0KA== +chai@^4.3.6: + version "4.3.6" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.6.tgz#ffe4ba2d9fa9d6680cc0b370adae709ec9011e9c" + integrity sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q== dependencies: assertion-error "^1.1.0" check-error "^1.0.2" deep-eql "^3.0.1" get-func-name "^2.0.0" + loupe "^2.3.1" pathval "^1.1.1" type-detect "^4.0.5" @@ -845,22 +866,7 @@ check-error@^1.0.2: resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" integrity sha1-V00xLt2Iu13YkS6Sht1sCu1KrII= -chokidar@3.5.2: - version "3.5.2" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.2.tgz#dba3976fcadb016f66fd365021d91600d01c1e75" - integrity sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ== - 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" - optionalDependencies: - fsevents "~2.3.2" - -chokidar@^3.5.1: +chokidar@3.5.3, chokidar@^3.5.1: version "3.5.3" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== @@ -921,9 +927,9 @@ color-name@^1.0.0, color-name@~1.1.4: integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== color-string@^1.6.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.9.0.tgz#63b6ebd1bec11999d1df3a79a7569451ac2be8aa" - integrity sha512-9Mrz2AQLefkH1UvASKj6v6hj/7eWgjnT/cVsR8CumieLoT+g900exWeNogqtweI8dxloXN9BDQTYro1oWu/5CQ== + version "1.9.1" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.9.1.tgz#4467f9146f036f855b764dfb5bf8582bf342c7a4" + integrity sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg== dependencies: color-name "^1.0.0" simple-swizzle "^0.2.2" @@ -936,11 +942,6 @@ color@^3.1.3: color-convert "^1.9.3" color-string "^1.6.0" -colors@1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" - integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== - colorspace@1.1.x: version "1.1.4" resolved "https://registry.yarnpkg.com/colorspace/-/colorspace-1.1.4.tgz#8d442d1186152f60453bf8070cd66eb364e59243" @@ -1009,11 +1010,21 @@ cookie-signature@1.0.6: resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= -cookie@0.4.1, cookie@~0.4.1: +cookie@0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.1.tgz#afd713fe26ebd21ba95ceb61f9a8116e50a537d1" integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA== +cookie@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" + integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== + +cookie@~0.4.1: + version "0.4.2" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" + integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== + core-util-is@~1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" @@ -1032,12 +1043,10 @@ create-require@^1.1.0: resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== -cron@1.8.2: - version "1.8.2" - resolved "https://registry.yarnpkg.com/cron/-/cron-1.8.2.tgz#4ac5e3c55ba8c163d84f3407bde94632da8370ce" - integrity sha512-Gk2c4y6xKEO8FSAUTklqtfSr7oTq0CiPQeLBG5Fl0qoXpZyMcj1SG59YL+hqq04bu6/IuEA7lMkYDAplQNKkyg== - dependencies: - moment-timezone "^0.5.x" +croner@~4.1.92: + version "4.1.97" + resolved "https://registry.yarnpkg.com/croner/-/croner-4.1.97.tgz#6e373dc7bb3026fab2deb0d82685feef20796766" + integrity sha512-/f6gpQuxDaqXu+1kwQYSckUglPaOrHdbIlBAu0YuW8/Cdb45XwXYNUBXg3r/9Mo6n540Kn/smKcZWko5x99KrQ== cross-spawn@^7.0.2: version "7.0.3" @@ -1070,17 +1079,17 @@ debug@2.6.9: dependencies: ms "2.0.0" -debug@4, debug@^4.0.1, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@~4.3.1, debug@~4.3.2: - version "4.3.3" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" - integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== +debug@4, debug@^4.0.1, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@~4.3.1, debug@~4.3.2: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" -debug@4.3.2: - version "4.3.2" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b" - integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw== +debug@4.3.3: + version "4.3.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" + integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== dependencies: ms "2.1.2" @@ -1109,34 +1118,34 @@ deep-is@^0.1.3, deep-is@~0.1.3: integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== degenerator@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/degenerator/-/degenerator-3.0.1.tgz#7ef78ec0c8577a544477308ddf1d2d6e88d51f5b" - integrity sha512-LFsIFEeLPlKvAKXu7j3ssIG6RT0TbI7/GhsqrI0DnHASEQjXQ0LUSYcjJteGgRGmZbl1TnMSxpNQIAiJ7Du5TQ== + version "3.0.2" + resolved "https://registry.yarnpkg.com/degenerator/-/degenerator-3.0.2.tgz#6a61fcc42a702d6e50ff6023fe17bff435f68235" + integrity sha512-c0mef3SNQo56t6urUU6tdQAs+ThoD0o9B9MJ8HEt7NQcGEILCRFqQb7ZbP9JAv+QF1Ky5plydhMR/IrqWDm+TQ== dependencies: ast-types "^0.13.2" escodegen "^1.8.1" esprima "^4.0.0" - vm2 "^3.9.3" + vm2 "^3.9.8" delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= -denque@^1.1.0: - version "1.5.1" - resolved "https://registry.yarnpkg.com/denque/-/denque-1.5.1.tgz#07f670e29c9a78f8faecb2566a1e2c11929c5cbf" - integrity sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw== +denque@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/denque/-/denque-2.0.1.tgz#bcef4c1b80dc32efe97515744f21a4229ab8934a" + integrity sha512-tfiWc6BQLXNLpNiR5iGd0Ocu3P3VpxfzFiqubLgMfhfOw9WyvgJBd46CClNn9k3qfbjvT//0cf7AlYRX/OslMQ== -depd@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= +depd@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== -destroy@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" - integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= +destroy@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" + integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== diff@5.0.0: version "5.0.0" @@ -1202,17 +1211,17 @@ encodeurl@~1.0.2: resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= -engine.io-parser@~5.0.0: +engine.io-parser@~5.0.3: version "5.0.3" resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-5.0.3.tgz#ca1f0d7b11e290b4bfda251803baea765ed89c09" integrity sha512-BtQxwF27XUNnSafQLvDi0dQ8s3i6VgzSoQMJacpIcGNrlUdfHSKbgm3jmjCVvQluGzqwujQMPAoMai3oYSTurg== dependencies: "@socket.io/base64-arraybuffer" "~1.0.2" -engine.io@~6.1.0: - version "6.1.2" - resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-6.1.2.tgz#e7b9d546d90c62246ffcba4d88594be980d3855a" - integrity sha512-v/7eGHxPvO2AWsksyx2PUsQvBafuvqs0jJJQ0FdmJG1b9qIvgSbqDRGwNhfk2XHaTTbTXiC4quRE8Q9nRjsrQQ== +engine.io@~6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-6.2.0.tgz#003bec48f6815926f2b1b17873e576acd54f41d0" + integrity sha512-4KzwW3F3bk+KlzSOY57fj/Jx6LyRQ1nbcyIadehl+AnXjKT7gDO0ORdRi/84ixvMKTym6ZKuxvbzN62HDDU1Lg== dependencies: "@types/cookie" "^0.4.1" "@types/cors" "^2.8.12" @@ -1222,13 +1231,13 @@ engine.io@~6.1.0: cookie "~0.4.1" cors "~2.8.5" debug "~4.3.1" - engine.io-parser "~5.0.0" + engine.io-parser "~5.0.3" ws "~8.2.3" enhanced-resolve@^5.0.0: - version "5.8.3" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.8.3.tgz#6d552d465cce0423f5b3d718511ea53826a7b2f0" - integrity sha512-EGAbGvH7j7Xt2nc0E7D99La1OiEs8LnyimkRgwExpUMScN6O+3x9tIWs7PLQZVNx4YD+00skHXPXi1yQHpAmZA== + version "5.9.3" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.9.3.tgz#44a342c012cbc473254af5cc6ae20ebd0aae5d88" + integrity sha512-Bq9VSor+kjvW3f9/MiiR4eE3XYgOl7/rS8lnSxbRbF3kS0B2r+Y9w5krBWxZgDxASVZbdYrn5wT4j/Wb0J9qow== dependencies: graceful-fs "^4.2.4" tapable "^2.2.0" @@ -1315,9 +1324,9 @@ eslint-visitor-keys@^2.0.0: integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== eslint-visitor-keys@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.2.0.tgz#6fbb166a6798ee5991358bc2daa1ba76cc1254a1" - integrity sha512-IOzT0X126zn7ALX0dwFiUQEdsfzrm4+ISsQS8nukaJXwEyYKRSnEIIDULYg1mCtGp7UUXgfGl7BIolXREQK+XQ== + version "3.3.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" + integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== eslint@^7.32.0: version "7.32.0" @@ -1433,43 +1442,44 @@ eventemitter3@^4.0.4: resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== -express-rate-limit@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/express-rate-limit/-/express-rate-limit-6.2.0.tgz#be644be082d4d5da8c368aed07cef80152f6e218" - integrity sha512-q9xfttbPX79HiBsHA4LT3PZEeJR96CJ5/2jloAKSEECMx8XlOOOpjxx6iK/kBw3hFJ8uhx6Q9lCfSGp70yV0tQ== +express-rate-limit@^6.4.0: + version "6.4.0" + resolved "https://registry.yarnpkg.com/express-rate-limit/-/express-rate-limit-6.4.0.tgz#b7066afe21157a012ed2b7c9adde386e712485cd" + integrity sha512-lxQRZI4gi3qAWTf0/Uqsyugsz57h8bd7QyllXBgJvd6DJKokzW7C5DTaNvwzvAQzwHGFaItybfYGhC8gpu0V2A== -express@^4.17.2: - version "4.17.2" - resolved "https://registry.yarnpkg.com/express/-/express-4.17.2.tgz#c18369f265297319beed4e5558753cc8c1364cb3" - integrity sha512-oxlxJxcQlYwqPWKVJJtvQiwHgosH/LrLSPA+H4UxpyvSS6jC5aH+5MoHFM+KABgTOt0APue4w66Ha8jCUo9QGg== +express@^4.18.0: + version "4.18.0" + resolved "https://registry.yarnpkg.com/express/-/express-4.18.0.tgz#7a426773325d0dd5406395220614c0db10b6e8e2" + integrity sha512-EJEXxiTQJS3lIPrU1AE2vRuT7X7E+0KBbpm5GSoK524yl0K8X+er8zS2P14E64eqsVNoWbMCT7MpmQ+ErAhgRg== dependencies: - accepts "~1.3.7" + accepts "~1.3.8" array-flatten "1.1.1" - body-parser "1.19.1" + body-parser "1.20.0" content-disposition "0.5.4" content-type "~1.0.4" - cookie "0.4.1" + cookie "0.5.0" cookie-signature "1.0.6" debug "2.6.9" - depd "~1.1.2" + depd "2.0.0" encodeurl "~1.0.2" escape-html "~1.0.3" etag "~1.8.1" - finalhandler "~1.1.2" + 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.3.0" + on-finished "2.4.1" parseurl "~1.3.3" path-to-regexp "0.1.7" proxy-addr "~2.0.7" - qs "6.9.6" + qs "6.10.3" range-parser "~1.2.1" safe-buffer "5.2.1" - send "0.17.2" - serve-static "1.14.2" + send "0.18.0" + serve-static "1.15.0" setprototypeof "1.2.0" - statuses "~1.5.0" + statuses "2.0.1" type-is "~1.6.18" utils-merge "1.0.1" vary "~1.1.2" @@ -1479,10 +1489,10 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-equals@^2.0.1: - version "2.0.4" - resolved "https://registry.yarnpkg.com/fast-equals/-/fast-equals-2.0.4.tgz#3add9410585e2d7364c2deeb6a707beadb24b927" - integrity sha512-caj/ZmjHljPrZtbzJ3kfH5ia/k4mTJe/qSiXAGzxZWRZgsgDV0cvNaQULqUX8t0/JVlzzEdYOwCN5DmzTxoD4w== +fast-equals@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/fast-equals/-/fast-equals-3.0.1.tgz#1e1ae440c04a32478faf698527315cdcf3ee7db2" + integrity sha512-J9FxqqC9E/ja0C+SYhoG3Jl6pQuhP92HNcVC75xDEhB+GUzPnjEp3vMfPIxPprYZFfXS5hpVvvPCWUMiDSMS8Q== fast-glob@^3.2.9: version "3.2.11" @@ -1496,9 +1506,9 @@ fast-glob@^3.2.9: micromatch "^4.0.4" fast-json-patch@^3.0.0-1: - version "3.1.0" - resolved "https://registry.yarnpkg.com/fast-json-patch/-/fast-json-patch-3.1.0.tgz#ec8cd9b9c4c564250ec8b9140ef7a55f70acaee6" - integrity sha512-IhpytlsVTRndz0hU5t0/MGzS/etxLlfrpG5V5M9mVbuj9TrJLWaMfsox9REM5rkuGX0T+5qjpe8XA1o0gZ42nA== + version "3.1.1" + resolved "https://registry.yarnpkg.com/fast-json-patch/-/fast-json-patch-3.1.1.tgz#85064ea1b1ebf97a3f7ad01e23f9337e72c66947" + integrity sha512-vf6IHUX2SBcA+5/+4883dsIjpBTqmfBjmYiWK1savxQmFk4JfBMLa7ynTYOs1Rolp/T1betJxHiGD3g1Mn8lUQ== fast-json-stable-stringify@^2.0.0: version "2.1.0" @@ -1523,9 +1533,9 @@ fclone@1.0.11, fclone@~1.0.11: integrity sha1-EOhdo4v+p/xZk0HClu4ddyZu5kA= fecha@^4.2.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/fecha/-/fecha-4.2.1.tgz#0a83ad8f86ef62a091e22bb5a039cd03d23eecce" - integrity sha512-MMMQ0ludy/nBs1/o0zVOiKTpG7qMbonKUzjJgQFEuvq6INZ1OraKPRAWkBq5vlKLOUMpmNYG1JoN3oDPUQ9m3Q== + version "4.2.3" + resolved "https://registry.yarnpkg.com/fecha/-/fecha-4.2.3.tgz#4d9ccdbc61e8629b259fdca67e65891448d569fd" + integrity sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw== file-entry-cache@^6.0.1: version "6.0.1" @@ -1546,17 +1556,17 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" -finalhandler@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" - integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== +finalhandler@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" + integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== dependencies: debug "2.6.9" encodeurl "~1.0.2" escape-html "~1.0.3" - on-finished "~2.3.0" + on-finished "2.4.1" parseurl "~1.3.3" - statuses "~1.5.0" + statuses "2.0.1" unpipe "~1.0.0" find-up@5.0.0: @@ -1581,9 +1591,9 @@ flat@^5.0.2: integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== flatted@^3.1.0: - version "3.2.4" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.4.tgz#28d9969ea90661b5134259f312ab6aa7929ac5e2" - integrity sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw== + version "3.2.5" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.5.tgz#76c8584f4fc843db64702a6bd04ab7a8bd666da3" + integrity sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg== fn.name@1.x.x: version "1.1.0" @@ -1591,9 +1601,9 @@ fn.name@1.x.x: integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw== follow-redirects@^1.14.0: - version "1.14.8" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.8.tgz#016996fb9a11a100566398b1c6839337d7bfa8fc" - integrity sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA== + version "1.14.9" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.9.tgz#dd4ea157de7bfaf9ea9b3fbd85aa16951f78d8d7" + integrity sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w== form-data@^3.0.0: version "3.0.1" @@ -1666,6 +1676,15 @@ get-func-name@^2.0.0: resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE= +get-intrinsic@^1.0.2: + version "1.1.1" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" + integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + get-uri@3: version "3.0.2" resolved "https://registry.yarnpkg.com/get-uri/-/get-uri-3.0.2.tgz#f0ef1356faabc70e1f9404fa3b66b2ba9bfc725c" @@ -1695,19 +1714,7 @@ glob-parent@^5.1.2, glob-parent@~5.1.2: dependencies: is-glob "^4.0.1" -glob@7.1.7: - version "7.1.7" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" - integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== - 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" - -glob@^7.0.5, glob@^7.1.3: +glob@7.2.0, glob@^7.0.5, glob@^7.1.3: version "7.2.0" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== @@ -1720,9 +1727,9 @@ glob@^7.0.5, glob@^7.1.3: path-is-absolute "^1.0.0" globals@^13.6.0, globals@^13.9.0: - version "13.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.12.0.tgz#4d733760304230a0082ed96e21e5c565f898089e" - integrity sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg== + version "13.13.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.13.0.tgz#ac32261060d8070e2719dd6998406e27d2b5727b" + integrity sha512-EQ7Q18AJlPwp3vUDL4mKA0KXrXyNIQyWon6T6XQiBQF0XHvRsiCSrWmmeATpUzdJN2HhWZU6Pdl0a9zdep5p6A== dependencies: type-fest "^0.20.2" @@ -1739,9 +1746,9 @@ globby@^11.0.4: slash "^3.0.0" graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4: - version "4.2.9" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" - integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== + version "4.2.10" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" + integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== growl@1.10.5: version "1.10.5" @@ -1758,6 +1765,11 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== +has-symbols@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + has@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" @@ -1787,15 +1799,15 @@ hmac-drbg@^1.0.1: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" -http-errors@1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.1.tgz#7c3f28577cbc8a207388455dbd62295ed07bd68c" - integrity sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g== +http-errors@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" + integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== dependencies: - depd "~1.1.2" + depd "2.0.0" inherits "2.0.4" setprototypeof "1.2.0" - statuses ">= 1.5.0 < 2" + statuses "2.0.1" toidentifier "1.0.1" http-proxy-agent@^4.0.0, http-proxy-agent@^4.0.1: @@ -1808,9 +1820,9 @@ http-proxy-agent@^4.0.0, http-proxy-agent@^4.0.1: debug "4" https-proxy-agent@5, https-proxy-agent@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" - integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA== + version "5.0.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" + integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== dependencies: agent-base "6" debug "4" @@ -1868,19 +1880,17 @@ int64-buffer@^1.0.1: resolved "https://registry.yarnpkg.com/int64-buffer/-/int64-buffer-1.0.1.tgz#c78d841b444cadf036cd04f8683696c740f15dca" integrity sha512-+3azY4pXrjAupJHU1V9uGERWlhoqNswJNji6aD/02xac7oxol508AsMC5lxKhEqyZeDFy3enq5OGWXF4u75hiw== -ioredis@^4.28.3: - version "4.28.3" - resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-4.28.3.tgz#b13fce8a6a7c525ba22e666d72980a3c0ba799aa" - integrity sha512-9JOWVgBnuSxpIgfpjc1OeY1OLmA4t2KOWWURTDRXky+eWO0LZhI33pQNT9gYxANUXfh5p/zYephYni6GPRsksQ== +ioredis@^5.0.4: + version "5.0.4" + resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-5.0.4.tgz#0d4abfd818adfc5ef5029fddac4b8f503a1433b7" + integrity sha512-qFJw3MnPNsJF1lcIOP3vztbsasOXK3nDdNAgjQj7t7/Bn/w10PGchTOpqylQNxjzPbLoYDu34LjeJtSWiKBntQ== dependencies: + "@ioredis/commands" "^1.1.1" cluster-key-slot "^1.1.0" - debug "^4.3.1" - denque "^1.1.0" + debug "^4.3.4" + denque "^2.0.1" lodash.defaults "^4.2.0" - lodash.flatten "^4.4.0" lodash.isarguments "^3.1.0" - p-map "^2.1.0" - redis-commands "1.7.0" redis-errors "^1.2.0" redis-parser "^3.0.0" standard-as-callback "^2.1.0" @@ -1908,9 +1918,9 @@ is-binary-path@~2.1.0: binary-extensions "^2.0.0" is-core-module@^2.8.1: - version "2.8.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211" - integrity sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA== + version "2.9.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.9.0.tgz#e1c34429cd51c6dd9e09e0799e396e27b19a9c69" + integrity sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A== dependencies: has "^1.0.3" @@ -2056,11 +2066,6 @@ lodash.defaults@^4.2.0: resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" integrity sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw= -lodash.flatten@^4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f" - integrity sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8= - lodash.isarguments@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" @@ -2094,17 +2099,24 @@ log-symbols@4.1.0: chalk "^4.1.0" is-unicode-supported "^0.1.0" -logform@^2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/logform/-/logform-2.3.2.tgz#68babe6a74ab09a1fd15a9b1e6cbc7713d41cb5b" - integrity sha512-V6JiPThZzTsbVRspNO6TmHkR99oqYTs8fivMBYQkjZj6rxW92KxtDCPE6IkAk1DNBnYKNkjm4jYBm6JDUcyhOA== +logform@^2.3.2, logform@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/logform/-/logform-2.4.0.tgz#131651715a17d50f09c2a2c1a524ff1a4164bcfe" + integrity sha512-CPSJw4ftjf517EhXZGGvTHHkYobo7ZCc0kvwUoOYcjfR2UVrI66RHj8MCrfAdEitdmFqbu2BYdYs8FHHZSb6iw== dependencies: - colors "1.4.0" + "@colors/colors" "1.5.0" fecha "^4.2.0" ms "^2.1.1" - safe-stable-stringify "^1.1.0" + safe-stable-stringify "^2.3.1" triple-beam "^1.3.0" +loupe@^2.3.1: + version "2.3.4" + resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.4.tgz#7e0b9bffc76f148f9be769cb1321d3dcf3cb25f3" + integrity sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ== + dependencies: + get-func-name "^2.0.0" + lru-cache@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" @@ -2145,29 +2157,29 @@ methods@~1.1.2: integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= micro-memoize@^4.0.9: - version "4.0.9" - resolved "https://registry.yarnpkg.com/micro-memoize/-/micro-memoize-4.0.9.tgz#b44a38c9dffbee1cefc2fd139bc8947952268b62" - integrity sha512-Z2uZi/IUMGQDCXASdujXRqrXXEwSY0XffUrAOllhqzQI3wpUyZbiZTiE2JuYC0HSG2G7DbCS5jZmsEKEGZuemg== + version "4.0.10" + resolved "https://registry.yarnpkg.com/micro-memoize/-/micro-memoize-4.0.10.tgz#cedf7682df990cd2290700af4537afa6dba7d4e9" + integrity sha512-rk0OlvEQkShjbr2EvGn1+GdCsgLDgABQyM9ZV6VoHNU7hiNM+eSOkjGWhiNabU/XWiEalWbjNQrNO+zcqd+pEA== micromatch@^4.0.0, micromatch@^4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" - integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== dependencies: - braces "^3.0.1" - picomatch "^2.2.3" + braces "^3.0.2" + picomatch "^2.3.1" -mime-db@1.51.0: - version "1.51.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.51.0.tgz#d9ff62451859b18342d960850dc3cfb77e63fb0c" - integrity sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g== +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== -mime-types@^2.1.12, mime-types@~2.1.24: - version "2.1.34" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.34.tgz#5a712f9ec1503511a945803640fafe09d3793c24" - integrity sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A== +mime-types@^2.1.12, mime-types@~2.1.24, mime-types@~2.1.34: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== dependencies: - mime-db "1.51.0" + mime-db "1.52.0" mime@1.6.0: version "1.6.0" @@ -2184,10 +2196,17 @@ minimalistic-crypto-utils@^1.0.1: resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= -minimatch@3.0.4, minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== +minimatch@4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-4.2.1.tgz#40d9d511a46bdc4e563c22c3080cde9c0d8299b4" + integrity sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g== + dependencies: + brace-expansion "^1.1.7" + +minimatch@^3.0.4: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== dependencies: brace-expansion "^1.1.7" @@ -2201,32 +2220,32 @@ mkdirp@1.0.4: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== -mocha@^9.1.3: - version "9.1.4" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-9.1.4.tgz#5a332d6ade6345b975fd97b5b39139854c8e1b32" - integrity sha512-+q2aV5VlJZuLgCWoBvGI5zEwPF9eEI0kr/sAA9Jm4xMND7RfIEyF8JE7C0JIg8WXRG+P1sdIAb5ccoHPlXLzcw== +mocha@^9.2.2: + version "9.2.2" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-9.2.2.tgz#d70db46bdb93ca57402c809333e5a84977a88fb9" + integrity sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g== dependencies: "@ungap/promise-all-settled" "1.1.2" ansi-colors "4.1.1" browser-stdout "1.3.1" - chokidar "3.5.2" - debug "4.3.2" + chokidar "3.5.3" + debug "4.3.3" diff "5.0.0" escape-string-regexp "4.0.0" find-up "5.0.0" - glob "7.1.7" + glob "7.2.0" growl "1.10.5" he "1.2.0" js-yaml "4.1.0" log-symbols "4.1.0" - minimatch "3.0.4" + minimatch "4.2.1" ms "2.1.3" - nanoid "3.1.25" + nanoid "3.3.1" serialize-javascript "6.0.0" strip-json-comments "3.1.1" supports-color "8.1.1" which "2.0.2" - workerpool "6.1.5" + workerpool "6.2.0" yargs "16.2.0" yargs-parser "20.2.4" yargs-unparser "2.0.0" @@ -2236,26 +2255,14 @@ module-details-from-path@^1.0.3: resolved "https://registry.yarnpkg.com/module-details-from-path/-/module-details-from-path-1.0.3.tgz#114c949673e2a8a35e9d35788527aa37b679da2b" integrity sha1-EUyUlnPiqKNenTV4hSeqN7Z52is= -moize@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/moize/-/moize-6.1.0.tgz#736e505d30d0ff7751005ed2c66c74cf52941b87" - integrity sha512-WrMcM+C2Jy+qyOC/UMhA3BCHGowxV34dhDZnDNfxsREW/8N+33SFjmc23Q61Xv1WUthUA1vYopTitP1sZ5jkeg== +moize@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/moize/-/moize-6.1.1.tgz#e75f18734fcb22aec30205681eb97cd7eb3ffa51" + integrity sha512-6bryLehIBVByDdAkXhoaPP1fknkoq1hNPmVCDYIb/w5zwfidT02zLSto1uGbmnv1GKu02ysgAEaJ5Ic7QQaGQA== dependencies: - fast-equals "^2.0.1" + fast-equals "^3.0.1" micro-memoize "^4.0.9" -moment-timezone@^0.5.x: - version "0.5.34" - resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.34.tgz#a75938f7476b88f155d3504a9343f7519d9a405c" - integrity sha512-3zAEHh2hKUs3EXLESx/wsgw6IQdusOT8Bxm3D9UrHPQR7zlMmzwybC8zHEM1tQ4LJwP7fcxrWr8tuBg05fFCbg== - dependencies: - moment ">= 2.9.0" - -"moment@>= 2.9.0": - version "2.29.1" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3" - integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ== - ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -2276,10 +2283,10 @@ mute-stream@~0.0.4: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== -nanoid@3.1.25: - version "3.1.25" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.25.tgz#09ca32747c0e543f0e1814b7d3793477f9c8e152" - integrity sha512-rdwtIXaXCLFAQbnfqDRnI6jaRHp9fTcYBjtFKE8eezcZ7LuLjhUaQGNeMXf1HmRoCH32CLz6XwX0TtxEOS/A3Q== +nanoid@3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.1.tgz#6347a18cac88af88f58af0b3594b723d5e99bb35" + integrity sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw== natural-compare@^1.4.0: version "1.4.0" @@ -2295,10 +2302,10 @@ needle@2.4.0: iconv-lite "^0.4.4" sax "^1.2.4" -negotiator@0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" - integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== +negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== netmask@^2.0.1: version "2.0.2" @@ -2335,10 +2342,15 @@ object-assign@^4: resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= -on-finished@~2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= +object-inspect@^1.9.0: + version "1.12.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.0.tgz#6e2c120e868fd1fd18cb4f18c31741d0d6e776f0" + integrity sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g== + +on-finished@2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" + integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== dependencies: ee-first "1.1.1" @@ -2399,11 +2411,6 @@ p-locate@^5.0.0: dependencies: p-limit "^3.0.2" -p-map@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" - integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== - p-queue@^6.6.2: version "6.6.2" resolved "https://registry.yarnpkg.com/p-queue/-/p-queue-6.6.2.tgz#2068a9dcf8e67dd0ec3e7a2bcb76810faa85e426" @@ -2515,10 +2522,10 @@ pg-int8@1.0.1: resolved "https://registry.yarnpkg.com/pg-int8/-/pg-int8-1.0.1.tgz#943bd463bf5b71b4170115f80f8efc9a0c0eb78c" integrity sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw== -pg-pool@^3.4.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-3.4.1.tgz#0e71ce2c67b442a5e862a9c182172c37eda71e9c" - integrity sha512-TVHxR/gf3MeJRvchgNHxsYsTCHQ+4wm3VIHSS19z8NC0+gioEhq1okDY1sm/TYbfoP6JLFx01s0ShvZ3puP/iQ== +pg-pool@^3.5.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-3.5.1.tgz#f499ce76f9bf5097488b3b83b19861f28e4ed905" + integrity sha512-6iCR0wVrro6OOHFsyavV+i6KYL4lVNyYAB9RD18w66xSzN+d8b66HiwuP30Gp1SH5O9T82fckkzsRjlrhD0ioQ== pg-protocol@*, pg-protocol@^1.5.0: version "1.5.0" @@ -2536,15 +2543,15 @@ pg-types@^2.1.0, pg-types@^2.2.0: postgres-date "~1.0.4" postgres-interval "^1.1.0" -pg@^8.7.1: - version "8.7.1" - resolved "https://registry.yarnpkg.com/pg/-/pg-8.7.1.tgz#9ea9d1ec225980c36f94e181d009ab9f4ce4c471" - integrity sha512-7bdYcv7V6U3KAtWjpQJJBww0UEsWuh4yQ/EjNf2HeO/NnvKjpvhEIe/A/TleP6wtmSKnUnghs5A9jUoK6iDdkA== +pg@^8.7.3: + version "8.7.3" + resolved "https://registry.yarnpkg.com/pg/-/pg-8.7.3.tgz#8a5bdd664ca4fda4db7997ec634c6e5455b27c44" + integrity sha512-HPmH4GH4H3AOprDJOazoIcpI49XFsHCe8xlrjHkWiapdbHK+HLtbm/GQzXYAZwmPju/kzKhjaSfMACG+8cgJcw== dependencies: buffer-writer "2.0.0" packet-reader "1.0.0" pg-connection-string "^2.5.0" - pg-pool "^3.4.1" + pg-pool "^3.5.1" pg-protocol "^1.5.0" pg-types "^2.1.0" pgpass "1.x" @@ -2556,18 +2563,25 @@ pgpass@1.x: dependencies: split2 "^4.1.0" -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3: +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== -pidusage@2.0.21, pidusage@^2.0.21: +pidusage@^2.0.21: version "2.0.21" resolved "https://registry.yarnpkg.com/pidusage/-/pidusage-2.0.21.tgz#7068967b3d952baea73e57668c98b9eaa876894e" integrity sha512-cv3xAQos+pugVX+BfXpHsbyz/dLzX+lr44zNMsYiGxUw+kV5sgQCIcLd1z+0vq+KyC7dJ+/ts2PsfgWfSC3WXA== dependencies: safe-buffer "^5.2.1" +pidusage@~3.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pidusage/-/pidusage-3.0.0.tgz#69108079724c9afdd958644b920bc40bac964044" + integrity sha512-8VJLToXhj+RYZGNVw8oxc7dS54iCQXUJ+MDFHezQ/fwF5B8W4OWodAMboc1wb08S/4LiHwAmkT4ohf/d3YPPsw== + dependencies: + safe-buffer "^5.2.1" + pm2-axon-rpc@~0.7.0, pm2-axon-rpc@~0.7.1: version "0.7.1" resolved "https://registry.yarnpkg.com/pm2-axon-rpc/-/pm2-axon-rpc-0.7.1.tgz#2daec5383a63135b3f18babb70266dacdcbc429a" @@ -2611,10 +2625,10 @@ pm2-sysmonit@^1.2.8: systeminformation "^5.7" tx2 "~1.0.4" -pm2@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/pm2/-/pm2-5.1.2.tgz#bffe4e9a84ee013362717eaad1b39b4d73f0fcd0" - integrity sha512-2nJQeCWjkN0WnTkWctaoZpqrJTiUN/Icw76IMVHHzPhr/p7yQYlEQgHzlL5IFWxO2N1HdBNXNdZft2p4HUmUcA== +pm2@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/pm2/-/pm2-5.2.0.tgz#fda71fab4b8fcfa5b7f546ca55a6e59e9ec5a68d" + integrity sha512-PO5hMVhQ85cTszFM++6v07Me9hPJMkFbHjkFigtMMk+La8ty2wCi2dlBTeZYJDhPUSjK8Ccltpq2buNRcyMOTw== dependencies: "@pm2/agent" "~2.0.0" "@pm2/io" "~5.0.0" @@ -2626,7 +2640,7 @@ pm2@^5.1.2: chokidar "^3.5.1" cli-tableau "^2.0.0" commander "2.15.1" - cron "1.8.2" + croner "~4.1.92" dayjs "~1.8.25" debug "^4.3.1" enquirer "2.3.6" @@ -2634,7 +2648,7 @@ pm2@^5.1.2: fclone "1.0.11" mkdirp "1.0.4" needle "2.4.0" - pidusage "2.0.21" + pidusage "~3.0" pm2-axon "~4.0.1" pm2-axon-rpc "~0.7.1" pm2-deploy "~1.0.2" @@ -2738,10 +2752,12 @@ pure-cache@^1.0.5: dependencies: mitt "^3.0.0" -qs@6.9.6: - version "6.9.6" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.6.tgz#26ed3c8243a431b2924aca84cc90471f35d5a0ee" - integrity sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ== +qs@6.10.3: + version "6.10.3" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.3.tgz#d6cde1b2ffca87b5aa57889816c5f81535e22e8e" + integrity sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ== + dependencies: + side-channel "^1.0.4" queue-microtask@^1.2.2: version "1.2.3" @@ -2760,18 +2776,18 @@ range-parser@~1.2.1: resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== -rate-limit-redis@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/rate-limit-redis/-/rate-limit-redis-3.0.0.tgz#389d368aab95f40ec7fba74c3d5095d1f2afcea9" - integrity sha512-Y20y4v4G8oQLEVvCV8ORSjVgAjMMFtr9kbCFjcV5+ShyWWtrrsxDXJZUfbKKgNQCNiGvKDrSO+PgMvJC/YExzQ== +rate-limit-redis@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/rate-limit-redis/-/rate-limit-redis-3.0.1.tgz#f12425417e03c1a4b9a7cdfa153113fd649a898c" + integrity sha512-L6yhOUBrAZ8VEMX9DwlM3X6hfm8yq+gBO4LoOW7+JgmNq59zE7QmLz4v5VnwYPvLeSh/e7PDcrzUI3UumJw1iw== -raw-body@2.4.2, raw-body@^2.2.0: - version "2.4.2" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.2.tgz#baf3e9c21eebced59dd6533ac872b71f7b61cb32" - integrity sha512-RPMAFUJP19WIet/99ngh6Iv8fzAbqum4Li7AD6DtGaW2RpMB/11xDoalPiJMTbu6I3hkbMVkATvZrqb9EEqeeQ== +raw-body@2.5.1, raw-body@^2.2.0: + version "2.5.1" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" + integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== dependencies: - bytes "3.1.1" - http-errors "1.8.1" + bytes "3.1.2" + http-errors "2.0.0" iconv-lite "0.4.24" unpipe "1.0.0" @@ -2792,7 +2808,7 @@ readable-stream@1.1.x: isarray "0.0.1" string_decoder "~0.10.x" -readable-stream@^3.4.0: +readable-stream@^3.4.0, readable-stream@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== @@ -2808,11 +2824,6 @@ readdirp@~3.6.0: dependencies: picomatch "^2.2.1" -redis-commands@1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/redis-commands/-/redis-commands-1.7.0.tgz#15a6fea2d58281e27b1cd1acfb4b293e278c3a89" - integrity sha512-nJWqw3bTFy21hX/CPKHth6sfhZbdiHP6bTawSgQBlKOVRG7EZkfHbbHwQJnrE4vsQf0CMNE+3gJ4Fmm16vdVlQ== - redis-errors@^1.0.0, redis-errors@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/redis-errors/-/redis-errors-1.2.0.tgz#eb62d2adb15e4eaf4610c04afe1529384250abad" @@ -2825,17 +2836,17 @@ redis-parser@3.0.0, redis-parser@^3.0.0: dependencies: redis-errors "^1.0.0" -redis@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/redis/-/redis-4.0.3.tgz#f60931175de6f5b5727240a08e58a9ed5cf0f9de" - integrity sha512-SJMRXvgiQUYN0HaWwWv002J5ZgkhYXOlbLomzcrL3kP42yRNZ8Jx5nvLYhVpgmf10xcDpanFOxxJkphu2eyIFQ== +redis@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/redis/-/redis-4.0.6.tgz#a2ded4d9f4f4bad148e54781051618fc684cd858" + integrity sha512-IaPAxgF5dV0jx+A9l6yd6R9/PAChZIoAskDVRzUODeLDNhsMlq7OLLTmu0AwAr0xjrJ1bibW5xdpRwqIQ8Q0Xg== dependencies: "@node-redis/bloom" "1.0.1" - "@node-redis/client" "1.0.3" + "@node-redis/client" "1.0.5" "@node-redis/graph" "1.0.0" "@node-redis/json" "1.0.2" - "@node-redis/search" "1.0.2" - "@node-redis/time-series" "1.0.1" + "@node-redis/search" "1.0.5" + "@node-redis/time-series" "1.0.2" regexpp@^3.1.0, regexpp@^3.2.0: version "3.2.0" @@ -2904,10 +2915,10 @@ safe-buffer@5.2.1, safe-buffer@^5.1.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== -safe-stable-stringify@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-1.1.1.tgz#c8a220ab525cd94e60ebf47ddc404d610dc5d84a" - integrity sha512-ERq4hUjKDbJfE4+XtZLFPCDi8Vb1JqaxAPTxWFLBx8XcAlf9Bda/ZJdVezs/NAfsMQScyIlUMx+Yeu7P7rx5jw== +safe-stable-stringify@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.3.1.tgz#ab67cbe1fe7d40603ca641c5e765cb942d04fc73" + integrity sha512-kYBSfT+troD9cDA85VDnHZ1rpHC50O0g1e6WlGHVCz/g+JS+9WKLj+XwFYyR8UbrZN8ll9HUpDAAddY58MGisg== "safer-buffer@>= 2.1.2 < 3": version "2.1.2" @@ -2930,9 +2941,9 @@ semver@^5.3.0, semver@^5.5.0: integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== semver@^7.2, semver@^7.2.1, semver@^7.3.4, semver@^7.3.5: - version "7.3.5" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" - integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== + version "7.3.7" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f" + integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g== dependencies: lru-cache "^6.0.0" @@ -2941,24 +2952,24 @@ semver@~7.2.0: resolved "https://registry.yarnpkg.com/semver/-/semver-7.2.3.tgz#3641217233c6382173c76bf2c7ecd1e1c16b0d8a" integrity sha512-utbW9Z7ZxVvwiIWkdOMLOR9G/NFXh2aRucghkVrEMJWuC++r3lCkBC3LwqBinyHzGMAJxY5tn6VakZGHObq5ig== -send@0.17.2: - version "0.17.2" - resolved "https://registry.yarnpkg.com/send/-/send-0.17.2.tgz#926622f76601c41808012c8bf1688fe3906f7820" - integrity sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww== +send@0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" + integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== dependencies: debug "2.6.9" - depd "~1.1.2" - destroy "~1.0.4" + 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 "1.8.1" + http-errors "2.0.0" mime "1.6.0" ms "2.1.3" - on-finished "~2.3.0" + on-finished "2.4.1" range-parser "~1.2.1" - statuses "~1.5.0" + statuses "2.0.1" serialize-javascript@6.0.0: version "6.0.0" @@ -2967,15 +2978,15 @@ serialize-javascript@6.0.0: dependencies: randombytes "^2.1.0" -serve-static@1.14.2: - version "1.14.2" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.2.tgz#722d6294b1d62626d41b43a013ece4598d292bfa" - integrity sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ== +serve-static@1.15.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" + integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== dependencies: encodeurl "~1.0.2" escape-html "~1.0.3" parseurl "~1.3.3" - send "0.17.2" + send "0.18.0" setprototypeof@1.2.0: version "1.2.0" @@ -2999,10 +3010,19 @@ shimmer@^1.1.0, shimmer@^1.2.0: resolved "https://registry.yarnpkg.com/shimmer/-/shimmer-1.2.1.tgz#610859f7de327b587efebf501fb43117f9aff337" integrity sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw== +side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" + signal-exit@^3.0.3: - version "3.0.6" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.6.tgz#24e630c4b0f03fea446a2bd299e62b4a6ca8d0af" - integrity sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ== + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== simple-swizzle@^0.2.2: version "0.2.2" @@ -3025,15 +3045,15 @@ slice-ansi@^4.0.0: astral-regex "^2.0.0" is-fullwidth-code-point "^3.0.0" -smart-buffer@^4.1.0: +smart-buffer@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== -socket.io-adapter@~2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-2.3.3.tgz#4d6111e4d42e9f7646e365b4f578269821f13486" - integrity sha512-Qd/iwn3VskrpNO60BeRyCyr8ZWw9CPZyitW4AQwmRZ8zCiyDiL+znRnWX6tDHXnWn1sJrM1+b6Mn6wEDJJ4aYQ== +socket.io-adapter@~2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-2.4.0.tgz#b50a4a9ecdd00c34d4c8c808224daa1a786152a6" + integrity sha512-W4N+o69rkMEGVuk2D/cvca3uYsvGlMwsySWV447y99gUPghxq42BxqLNMndb+a1mm/5/7NeXVQS7RLa2XyXvYg== socket.io-parser@~4.0.4: version "4.0.4" @@ -3044,16 +3064,16 @@ socket.io-parser@~4.0.4: component-emitter "~1.3.0" debug "~4.3.1" -socket.io@^4.4.1: - version "4.4.1" - resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.4.1.tgz#cd6de29e277a161d176832bb24f64ee045c56ab8" - integrity sha512-s04vrBswdQBUmuWJuuNTmXUVJhP0cVky8bBDhdkf8y0Ptsu7fKU2LuLbts9g+pdmAdyMMn8F/9Mf1/wbtUN0fg== +socket.io@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.5.0.tgz#78ae2e84784c29267086a416620c18ef95b37186" + integrity sha512-slTYqU2jCgMjXwresG8grhUi/cC6GjzmcfqArzaH3BN/9I/42eZk9yamNvZJdBfTubkjEdKAKs12NEztId+bUA== dependencies: accepts "~1.3.4" base64id "~2.0.0" debug "~4.3.2" - engine.io "~6.1.0" - socket.io-adapter "~2.3.3" + engine.io "~6.2.0" + socket.io-adapter "~2.4.0" socket.io-parser "~4.0.4" socks-proxy-agent@5, socks-proxy-agent@^5.0.0: @@ -3066,12 +3086,12 @@ socks-proxy-agent@5, socks-proxy-agent@^5.0.0: socks "^2.3.3" socks@^2.3.3: - version "2.6.1" - resolved "https://registry.yarnpkg.com/socks/-/socks-2.6.1.tgz#989e6534a07cf337deb1b1c94aaa44296520d30e" - integrity sha512-kLQ9N5ucj8uIcxrDwjm0Jsqk06xdpBjGNQtpXy4Q8/QY2k+fY7nZH8CARy+hkbG+SGAovmzzuauCpBlb8FrnBA== + version "2.6.2" + resolved "https://registry.yarnpkg.com/socks/-/socks-2.6.2.tgz#ec042d7960073d40d94268ff3bb727dc685f111a" + integrity sha512-zDZhHhZRY9PxRruRMR7kMhnf3I8hDs4S3f9RecfnGxvcBHQcKcIH/oUcEWffsfl1XxdYlA7nnlGbbTvPz9D8gA== dependencies: ip "^1.1.5" - smart-buffer "^4.1.0" + smart-buffer "^4.2.0" source-map-support@0.5.19: version "0.5.19" @@ -3111,10 +3131,10 @@ standard-as-callback@^2.1.0: resolved "https://registry.yarnpkg.com/standard-as-callback/-/standard-as-callback-2.1.0.tgz#8953fc05359868a77b5b9739a665c5977bb7df45" integrity sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A== -"statuses@>= 1.5.0 < 2", statuses@~1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= +statuses@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" @@ -3176,9 +3196,9 @@ supports-preserve-symlinks-flag@^1.0.0: integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== swagger-ui-dist@>=4.1.3: - version "4.2.1" - resolved "https://registry.yarnpkg.com/swagger-ui-dist/-/swagger-ui-dist-4.2.1.tgz#d42ad2e68048edf61303d03ed9dfaccbbed312e0" - integrity sha512-ZzUeNKIIMXmKI53iLscAVCpQ7jblYxI2XX5EBaoBr6UBEfxT3L0vlnE+fzPBbHc9g0sgdOMLZGhC5OW++9pqlw== + version "4.10.3" + resolved "https://registry.yarnpkg.com/swagger-ui-dist/-/swagger-ui-dist-4.10.3.tgz#d67066716ce20cb6afb23474c9ca2727633a9eb3" + integrity sha512-eR4vsd7sYo0Sx7ZKRP5Z04yij7JkNmIlUQfrDQgC+xO5ABYx+waabzN+nDsQTLAJ4Z04bjkRd8xqkJtbxr3G7w== swagger-ui-express@^4.3.0: version "4.3.0" @@ -3188,9 +3208,9 @@ swagger-ui-express@^4.3.0: swagger-ui-dist ">=4.1.3" systeminformation@^5.7: - version "5.10.7" - resolved "https://registry.yarnpkg.com/systeminformation/-/systeminformation-5.10.7.tgz#82aecd2509cfa0f22eb7ec8c59f5b83dc603def1" - integrity sha512-elAv0h67BDuafy+zuS/yF9QCgQcROXaK9AXMnLz+NHq/LRv7p2/k5qWIwaVxwsSZE8r+dVyIw0BtFO/FoHtZaw== + version "5.11.14" + resolved "https://registry.yarnpkg.com/systeminformation/-/systeminformation-5.11.14.tgz#21fcb6f05d33e17d69c236b9c1b3d9c53d1d2b3a" + integrity sha512-m8CJx3fIhKohanB0ExTk5q53uI1J0g5B09p77kU+KxnxRVpADVqTAwCg1PFelqKsj4LHd+qmVnumb511Hg4xow== table@^6.0.9: version "6.8.0" @@ -3247,25 +3267,25 @@ tr46@~0.0.3: resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= -triple-beam@^1.2.0, triple-beam@^1.3.0: +triple-beam@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.3.0.tgz#a595214c7298db8339eeeee083e4d10bd8cb8dd9" integrity sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw== -ts-loader@^9.2.6: - version "9.2.6" - resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.2.6.tgz#9937c4dd0a1e3dbbb5e433f8102a6601c6615d74" - integrity sha512-QMTC4UFzHmu9wU2VHZEmWWE9cUajjfcdcws+Gh7FhiO+Dy0RnR1bNz0YCHqhI0yRowCE9arVnNxYHqELOy9Hjw== +ts-loader@^9.2.8: + version "9.2.8" + resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.2.8.tgz#e89aa32fa829c5cad0a1d023d6b3adecd51d5a48" + integrity sha512-gxSak7IHUuRtwKf3FIPSW1VpZcqF9+MBrHOvBp9cjHh+525SjtCIJKVGjRKIAfxBwDGDGCFF00rTfzB1quxdSw== dependencies: chalk "^4.1.0" enhanced-resolve "^5.0.0" micromatch "^4.0.0" semver "^7.3.4" -ts-node@^10.4.0: - version "10.4.0" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.4.0.tgz#680f88945885f4e6cf450e7f0d6223dd404895f7" - integrity sha512-g0FlPvvCXSIO1JDF6S232P5jPYqBkRL9qly81ZgAOSU7rwI0stphCgd2kLiCrU9DjQCrJMWEqcNSjQL02s6d8A== +ts-node@^10.7.0: + version "10.7.0" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.7.0.tgz#35d503d0fab3e2baa672a0e94f4b40653c2463f5" + integrity sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A== dependencies: "@cspotcode/source-map-support" "0.7.0" "@tsconfig/node10" "^1.0.7" @@ -3278,6 +3298,7 @@ ts-node@^10.4.0: create-require "^1.1.0" diff "^4.0.1" make-error "^1.1.1" + v8-compile-cache-lib "^3.0.0" yn "3.1.1" tslib@1.9.3: @@ -3291,9 +3312,9 @@ tslib@^1.8.1: integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== tslib@^2.0.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" - integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== + version "2.4.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" + integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== tsutils@^3.21.0: version "3.21.0" @@ -3346,10 +3367,10 @@ type-is@~1.6.18: media-typer "0.3.0" mime-types "~2.1.24" -typescript@^4.5.5: - version "4.5.5" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.5.tgz#d8c953832d28924a9e3d37c73d729c846c5896f3" - integrity sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA== +typescript@^4.6.3: + version "4.6.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.3.tgz#eefeafa6afdd31d725584c67a0eaba80f6fc6c6c" + integrity sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw== universalify@^0.1.0: version "0.1.2" @@ -3383,6 +3404,11 @@ uuid@^3.2.1: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== +v8-compile-cache-lib@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" + integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== + v8-compile-cache@^2.0.3: version "2.3.0" resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" @@ -3403,10 +3429,10 @@ vizion@~2.2.1: ini "^1.3.5" js-git "^0.7.8" -vm2@^3.9.3: - version "3.9.7" - resolved "https://registry.yarnpkg.com/vm2/-/vm2-3.9.7.tgz#bb87aa677c97c61e23a6cb6547e44e990517a6f6" - integrity sha512-g/GZ7V0Mlmch3eDVOATvAXr1GsJNg6kQ5PjvYy3HbJMCRn5slNbo/u73Uy7r5yUej1cRa3ZjtoVwcWSQuQ/fow== +vm2@^3.9.8: + version "3.9.9" + resolved "https://registry.yarnpkg.com/vm2/-/vm2-3.9.9.tgz#c0507bc5fbb99388fad837d228badaaeb499ddc5" + integrity sha512-xwTm7NLh/uOjARRBs8/95H0e8fT3Ukw5D/JJWhxMbhKzNh1Nu981jQKvkep9iKYNxzlVrdzD0mlBGkDKZWprlw== dependencies: acorn "^8.7.0" acorn-walk "^8.2.0" @@ -3431,39 +3457,40 @@ which@2.0.2, which@^2.0.1: dependencies: isexe "^2.0.0" -winston-transport@^4.4.2: - version "4.4.2" - resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.4.2.tgz#554efe3fce229d046df006e0e3c411d240652e51" - integrity sha512-9jmhltAr5ygt5usgUTQbEiw/7RYXpyUbEAFRCSicIacpUzPkrnQsQZSPGEI12aLK9Jth4zNcYJx3Cvznwrl8pw== +winston-transport@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.5.0.tgz#6e7b0dd04d393171ed5e4e4905db265f7ab384fa" + integrity sha512-YpZzcUzBedhlTAfJg6vJDlyEai/IFMIVcaEZZyl3UXIl4gmqRpU7AE89AHLkbzLUsv0NVmw7ts+iztqKxxPW1Q== dependencies: logform "^2.3.2" - readable-stream "^3.4.0" - triple-beam "^1.2.0" + readable-stream "^3.6.0" + triple-beam "^1.3.0" -winston@^3.3.3: - version "3.4.0" - resolved "https://registry.yarnpkg.com/winston/-/winston-3.4.0.tgz#7080f24b02a0684f8a37f9d5c6afb1ac23e95b84" - integrity sha512-FqilVj+5HKwCfIHQzMxrrd5tBIH10JTS3koFGbLVWBODjiIYq7zir08rFyBT4rrTYG/eaTqDcfSIbcjSM78YSw== +winston@^3.7.2: + version "3.7.2" + resolved "https://registry.yarnpkg.com/winston/-/winston-3.7.2.tgz#95b4eeddbec902b3db1424932ac634f887c400b1" + integrity sha512-QziIqtojHBoyzUOdQvQiar1DH0Xp9nF1A1y7NVy2DGEsz82SBDtOalS0ulTRGVT14xPX3WRWkCsdcJKqNflKng== dependencies: "@dabh/diagnostics" "^2.0.2" async "^3.2.3" is-stream "^2.0.0" - logform "^2.3.2" + logform "^2.4.0" one-time "^1.0.0" readable-stream "^3.4.0" + safe-stable-stringify "^2.3.1" stack-trace "0.0.x" triple-beam "^1.3.0" - winston-transport "^4.4.2" + winston-transport "^4.5.0" word-wrap@^1.2.3, word-wrap@~1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== -workerpool@6.1.5: - version "6.1.5" - resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.1.5.tgz#0f7cf076b6215fd7e1da903ff6f22ddd1886b581" - integrity sha512-XdKkCK0Zqc6w3iTxLckiuJ81tiD/o5rBE/m+nXpRCB+/Sq4DqkfXZ/x0jW02DG1tGsfUGXbTJyZDP+eu67haSw== +workerpool@6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.0.tgz#827d93c9ba23ee2019c3ffaff5c27fccea289e8b" + integrity sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A== wrap-ansi@^7.0.0: version "7.0.0" @@ -3479,10 +3506,10 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= -ws@^7.0.0, ws@^7.5.6: - version "7.5.6" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.6.tgz#e59fc509fb15ddfb65487ee9765c5a51dec5fe7b" - integrity sha512-6GLgCqo2cy2A2rjCNFlxQS6ZljG/coZfZXclldI8FB/1G3CCI36Zd8xy2HrFVACi8tfk5XrgLQEk+P0Tnz9UcA== +ws@^7.0.0, ws@^7.5.7: + version "7.5.7" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.7.tgz#9e0ac77ee50af70d58326ecff7e85eb3fa375e67" + integrity sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A== ws@~7.4.0: version "7.4.6" From aca98fe665f2c252111f7d216a38b3f601e57b8b Mon Sep 17 00:00:00 2001 From: fabian-emilius Date: Mon, 25 Apr 2022 23:17:44 +0200 Subject: [PATCH 12/16] Fix issue when ship reconnects while block is processed --- src/connections/ship.ts | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/connections/ship.ts b/src/connections/ship.ts index debdd1f0..5e91f4ec 100644 --- a/src/connections/ship.ts +++ b/src/connections/ship.ts @@ -222,6 +222,22 @@ export default class StateHistoryBlockReader { throw error; } + if (response.this_block) { + this.currentArgs.start_block_num = response.this_block.block_num + 1; + } else { + this.currentArgs.start_block_num += 1; + } + + if (response.this_block && response.last_irreversible) { + this.currentArgs.have_positions = this.currentArgs.have_positions.filter( + row => row.block_num > response.last_irreversible.block_num && row.block_num < response.this_block.block_num + ); + + if (response.this_block.block_num > response.last_irreversible.block_num) { + this.currentArgs.have_positions.push(response.this_block); + } + } + try { await this.processBlock({ this_block: response.this_block, @@ -246,22 +262,6 @@ export default class StateHistoryBlockReader { throw error; } - if (response.this_block) { - this.currentArgs.start_block_num = response.this_block.block_num + 1; - } else { - this.currentArgs.start_block_num += 1; - } - - if (response.this_block && response.last_irreversible) { - this.currentArgs.have_positions = this.currentArgs.have_positions.filter( - row => row.block_num > response.last_irreversible.block_num && row.block_num < response.this_block.block_num - ); - - if (response.this_block.block_num > response.last_irreversible.block_num) { - this.currentArgs.have_positions.push(response.this_block); - } - } - this.unconfirmed += 1; if (this.unconfirmed >= this.options.min_block_confirmation) { From 73352e9bb310629e4dfb740d8e374924f17086f7 Mon Sep 17 00:00:00 2001 From: fabian-emilius Date: Mon, 25 Apr 2022 23:18:50 +0200 Subject: [PATCH 13/16] Fix issue when ship reconnects while block is processed --- src/connections/ship.ts | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/connections/ship.ts b/src/connections/ship.ts index 5e91f4ec..837f300c 100644 --- a/src/connections/ship.ts +++ b/src/connections/ship.ts @@ -197,6 +197,22 @@ export default class StateHistoryBlockReader { } this.blocksQueue.add(async () => { + if (response.this_block) { + this.currentArgs.start_block_num = response.this_block.block_num + 1; + } else { + this.currentArgs.start_block_num += 1; + } + + if (response.this_block && response.last_irreversible) { + this.currentArgs.have_positions = this.currentArgs.have_positions.filter( + row => row.block_num > response.last_irreversible.block_num && row.block_num < response.this_block.block_num + ); + + if (response.this_block.block_num > response.last_irreversible.block_num) { + this.currentArgs.have_positions.push(response.this_block); + } + } + let deserializedTraces = []; let deserializedDeltas = []; @@ -222,22 +238,6 @@ export default class StateHistoryBlockReader { throw error; } - if (response.this_block) { - this.currentArgs.start_block_num = response.this_block.block_num + 1; - } else { - this.currentArgs.start_block_num += 1; - } - - if (response.this_block && response.last_irreversible) { - this.currentArgs.have_positions = this.currentArgs.have_positions.filter( - row => row.block_num > response.last_irreversible.block_num && row.block_num < response.this_block.block_num - ); - - if (response.this_block.block_num > response.last_irreversible.block_num) { - this.currentArgs.have_positions.push(response.this_block); - } - } - try { await this.processBlock({ this_block: response.this_block, From b8951fa44b746224f9cb1fe729878384cd50b317 Mon Sep 17 00:00:00 2001 From: fabian-emilius Date: Tue, 26 Apr 2022 00:29:52 +0200 Subject: [PATCH 14/16] Only update vacuum settings once per week --- src/bin/filler.ts | 2 +- src/filler/set-autovac-settings.ts | 49 ++++++++++++++++++++++-------- 2 files changed, 37 insertions(+), 14 deletions(-) diff --git a/src/bin/filler.ts b/src/bin/filler.ts index f64d1f5b..faa2a9ae 100644 --- a/src/bin/filler.ts +++ b/src/bin/filler.ts @@ -54,7 +54,7 @@ if (cluster.isPrimary || cluster.isMaster) { process.exit(1); } - setAutoVacSettings(connection.database).then( + setAutoVacSettings(connection).then( () => logger.info('Finished setting autovacuum settings'), error => logger.error('Failed setting autovacuum settings', error) ); diff --git a/src/filler/set-autovac-settings.ts b/src/filler/set-autovac-settings.ts index 1f798557..c1037e44 100644 --- a/src/filler/set-autovac-settings.ts +++ b/src/filler/set-autovac-settings.ts @@ -1,4 +1,5 @@ -import PostgresConnection from '../connections/postgres'; +import ConnectionManager from '../connections/manager'; +import logger from '../utils/winston'; const settingOverrides: {[key: string]: {scale: string, threshold: number}} = { atomicassets_templates: { @@ -7,8 +8,19 @@ const settingOverrides: {[key: string]: {scale: string, threshold: number}} = { }, }; -export async function setAutoVacSettings(database: PostgresConnection): Promise { - const {rows} = await database.query('SELECT schemaname, relname AS tablename, n_live_tup::INT AS rows FROM pg_stat_user_tables'); +export async function setAutoVacSettings(connection: ConnectionManager): Promise { + const dbinfo = await connection.database.query(`SELECT * FROM dbinfo WHERE name = 'vacuum_settings'`); + + if (dbinfo.rows.length > 0 && +dbinfo.rows[0].value + 3600 * 24 * 7 * 1000 > Date.now()) { + logger.info('Skipping updating vacuum settings'); + + return; + } + + const {rows} = await connection.database.query( + `SELECT schemaname, relname AS tablename, n_live_tup::INT AS rows FROM pg_stat_user_tables + WHERE schemaname = 'public'` + ); for (const table of rows) { let scale = '0.05'; @@ -30,16 +42,27 @@ export async function setAutoVacSettings(database: PostgresConnection): Promise< threshold = settingOverrides[table.tablename].threshold; } - await database.query(` - ALTER TABLE ${table.schemaname}.${table.tablename} SET ( - autovacuum_vacuum_scale_factor = ${scale}, - autovacuum_vacuum_threshold = ${threshold}, - autovacuum_analyze_scale_factor = ${scale}, - autovacuum_analyze_threshold = ${threshold * 10}, - autovacuum_vacuum_insert_scale_factor = ${scale}, - autovacuum_vacuum_insert_threshold = ${threshold * 10} - ) - `); + try { + await connection.database.query(` + ALTER TABLE ${table.schemaname}.${table.tablename} SET ( + autovacuum_vacuum_scale_factor = ${scale}, + autovacuum_vacuum_threshold = ${threshold}, + autovacuum_analyze_scale_factor = ${scale}, + autovacuum_analyze_threshold = ${threshold * 10}, + autovacuum_vacuum_insert_scale_factor = ${scale}, + autovacuum_vacuum_insert_threshold = ${threshold * 10} + ) + `); + } catch (error) { + logger.error(`Failed to change autovaccum settings for ${table.schemaname}.${table.tablename}`, error); + } + } + + if (dbinfo.rows.length === 0) { + await connection.database.query(`INSERT INTO dbinfo ("name", "value", updated) VALUES ('vacuum_settings', '${Date.now()}', extract(epoch from current_timestamp)::bigint);`); + } else { + await connection.database.query(`UPDATE dbinfo SET "value" = '${Date.now()}' WHERE name = 'vacuum_settings';`); } + logger.info('Updated vacuum settings for tables.') } From 923911efdfd378487bd1615e477aba054b9e8d60 Mon Sep 17 00:00:00 2001 From: fabian-emilius Date: Tue, 26 Apr 2022 00:43:10 +0200 Subject: [PATCH 15/16] Add log messages to vacuum settings update --- src/filler/set-autovac-settings.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/filler/set-autovac-settings.ts b/src/filler/set-autovac-settings.ts index c1037e44..9492f867 100644 --- a/src/filler/set-autovac-settings.ts +++ b/src/filler/set-autovac-settings.ts @@ -53,6 +53,8 @@ export async function setAutoVacSettings(connection: ConnectionManager): Promise autovacuum_vacuum_insert_threshold = ${threshold * 10} ) `); + + logger.info(`Updated autovaccum settings for ${table.schemaname}.${table.tablename}`) } catch (error) { logger.error(`Failed to change autovaccum settings for ${table.schemaname}.${table.tablename}`, error); } From dbbd0f86c176483f6bbe3ab0166a690603179a4d Mon Sep 17 00:00:00 2001 From: Fabian Emilius Date: Tue, 26 Apr 2022 12:52:50 +0200 Subject: [PATCH 16/16] Fix status codes --- src/api/namespaces/atomicmarket/handlers/sales2.ts | 4 ++-- src/filler/set-autovac-settings.ts | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/api/namespaces/atomicmarket/handlers/sales2.ts b/src/api/namespaces/atomicmarket/handlers/sales2.ts index d5180d71..0042538f 100644 --- a/src/api/namespaces/atomicmarket/handlers/sales2.ts +++ b/src/api/namespaces/atomicmarket/handlers/sales2.ts @@ -547,11 +547,11 @@ export async function getSalesTemplatesV2Action(params: RequestValues, ctx: Atom }); if (!args.symbol) { - throw new ApiError('symbol parameter is required', 200); + throw new ApiError('symbol parameter is required', 400); } if (!hasAssetFilter(params) && !args.collection_whitelist) { - throw new ApiError('You need to specify an asset filter!', 200); + throw new ApiError('You need to specify an asset filter!', 400); } const query = new QueryBuilder(` diff --git a/src/filler/set-autovac-settings.ts b/src/filler/set-autovac-settings.ts index 9492f867..dee78961 100644 --- a/src/filler/set-autovac-settings.ts +++ b/src/filler/set-autovac-settings.ts @@ -65,6 +65,4 @@ export async function setAutoVacSettings(connection: ConnectionManager): Promise } else { await connection.database.query(`UPDATE dbinfo SET "value" = '${Date.now()}' WHERE name = 'vacuum_settings';`); } - - logger.info('Updated vacuum settings for tables.') }