From 132262186b922fcf3e4249cf11e027f103b02bd8 Mon Sep 17 00:00:00 2001 From: Peter Date: Fri, 20 Dec 2024 16:02:28 +0300 Subject: [PATCH 1/3] fix(build): do not build unnecessary js (#333) * Update package.json * Update tsconfig.json * Update tsconfig.json * Update Dockerfile * Update .eslintignore --- .eslintignore | 1 + Dockerfile | 2 +- package.json | 1 + tsconfig.json | 14 ++++++++++++-- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/.eslintignore b/.eslintignore index 58027caf..453a6f99 100644 --- a/.eslintignore +++ b/.eslintignore @@ -3,4 +3,5 @@ ecosystem.config.js node_modules /workers/release/tests/mock /workers/migrations +/workers/sentry/playground .github diff --git a/Dockerfile b/Dockerfile index ae49af03..01efa6f4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,4 +13,4 @@ RUN yarn install COPY runner.ts tsconfig.json ./ COPY lib/ ./lib/ -RUN yarn tsc +RUN yarn build diff --git a/package.json b/package.json index 4573826f..15f96965 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "workers/*" ], "scripts": { + "build": "tsc", "worker": "ts-node -T ./runner.ts", "migration-add": "migrate-mongo create", "migrate:up": "migrate-mongo up", diff --git a/tsconfig.json b/tsconfig.json index 93d1e1bc..1f1597bb 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,7 +6,7 @@ "target": "ES2020", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ "lib": ["ES2020"], /* Specify library files to be included in the compilation. */ - "allowJs": true, /* Allow javascript files to be compiled. */ + // "allowJs": true, /* Allow javascript files to be compiled. */ // "checkJs": true, /* Report errors in .js files. */ // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ // "declaration": true, /* Generates corresponding '.d.ts' file. */ @@ -64,5 +64,15 @@ /* Advanced Options */ "forceConsistentCasingInFileNames": true, /* Disallow inconsistently-cased references to the same file. */ "resolveJsonModule": true - } + }, + "exclude": [ + "node_modules", + "dist", + "bin", + "migrations", + "tools", + "coverage", + "workers/sentry/playground", + "tests" + ] } From 4d1973c8f84f39b096ab3d028b1a00bc03099d5e Mon Sep 17 00:00:00 2001 From: e11sy <130844513+e11sy@users.noreply.github.com> Date: Wed, 25 Dec 2024 20:36:47 +0300 Subject: [PATCH 2/3] Feat [ Test ]: migrate from redis-mock to redis testcontainer for tests (#336) * set up redis testcontainert instead of redis-mock * cherry-pick tests refactoring * rm redundant file * refactor grouper tests * lint fix * lint fix --- jest.setup.redis-mock.js | 25 ++- package.json | 5 +- workers/grouper/package.json | 3 +- workers/grouper/src/index.ts | 3 + workers/grouper/src/redisHelper.ts | 57 +++++- workers/grouper/tests/index.test.ts | 18 +- workers/limiter/package.json | 3 +- workers/limiter/src/index.ts | 4 + workers/limiter/src/redisHelper.ts | 66 ++++++- workers/limiter/tests/index.test.ts | 67 +++---- yarn.lock | 268 ++++++++++++++++++++++++---- 11 files changed, 411 insertions(+), 108 deletions(-) diff --git a/jest.setup.redis-mock.js b/jest.setup.redis-mock.js index 9af7d052..291ded59 100644 --- a/jest.setup.redis-mock.js +++ b/jest.setup.redis-mock.js @@ -1,4 +1,25 @@ +const { GenericContainer } = require('testcontainers'); + +let redisTestContainer; + /** - * Mock redis library + * Create test container with Redis, which could be used in tests */ -jest.mock('redis', () => jest.requireActual('redis-mock')); +beforeAll(async () => { + redisTestContainer = await new GenericContainer('redis') + .withExposedPorts(6379) + .start(); + + const port = redisTestContainer.getMappedPort(6379); + const host = redisTestContainer.getContainerIpAddress(); + + /** + * Set environment variable for redisHelper to connect to redis container + */ + process.env.REDIS_URL = `redis://${host}:${port}`; +} +); + +afterAll(async () => { + await redisTestContainer.stop(); +}); diff --git a/package.json b/package.json index 15f96965..16196084 100644 --- a/package.json +++ b/package.json @@ -67,16 +67,17 @@ "typescript": "^3.8.3", "uuid": "^8.3.0", "winston": "^3.2.1", - "yup": "^0.28.5" + "yup": "^0.28.5", + "redis": "^4.7.0" }, "devDependencies": { "@shelf/jest-mongodb": "^1.2.3", + "testcontainers": "^3.0.0", "eslint": "^7.14.0", "eslint-config-codex": "^1.6.1", "jest": "25.5.4", "nodemon": "^2.0.3", "random-words": "^1.1.1", - "redis-mock": "^0.56.3", "ts-jest": "25.4.0", "wait-for-expect": "^3.0.2", "webpack": "^4.43.0", diff --git a/workers/grouper/package.json b/workers/grouper/package.json index 6230c8e5..4b376934 100644 --- a/workers/grouper/package.json +++ b/workers/grouper/package.json @@ -10,7 +10,6 @@ "workerType": "grouper", "dependencies": { "@types/redis": "^2.8.28", - "js-levenshtein": "^1.1.6", - "redis": "^3.1.1" + "js-levenshtein": "^1.1.6" } } diff --git a/workers/grouper/src/index.ts b/workers/grouper/src/index.ts index 22a51771..d324c1bd 100644 --- a/workers/grouper/src/index.ts +++ b/workers/grouper/src/index.ts @@ -51,6 +51,8 @@ export default class GrouperWorker extends Worker { public async start(): Promise { await this.db.connect(); this.prepareCache(); + await this.redis.initialize(); + await super.start(); } @@ -61,6 +63,7 @@ export default class GrouperWorker extends Worker { await super.finish(); this.prepareCache(); await this.db.close(); + await this.redis.close(); } /** diff --git a/workers/grouper/src/redisHelper.ts b/workers/grouper/src/redisHelper.ts index 0dfd81ac..abf7ecb3 100644 --- a/workers/grouper/src/redisHelper.ts +++ b/workers/grouper/src/redisHelper.ts @@ -1,5 +1,5 @@ import HawkCatcher from '@hawk.so/nodejs'; -import redis from 'redis'; +import { createClient, RedisClientType } from 'redis'; import createLogger from '../../../lib/logger'; /** @@ -14,7 +14,7 @@ export default class RedisHelper { /** * Redis client for making queries */ - private readonly redisClient = redis.createClient({ url: process.env.REDIS_URL }); + private readonly redisClient: RedisClientType; /** * Logger instance @@ -22,6 +22,41 @@ export default class RedisHelper { */ private logger = createLogger(); + /** + * Constructor of the Redis helper class + * Initializes the Redis client and sets up error handling + */ + constructor() { + this.redisClient = createClient({ url: process.env.REDIS_URL }); + + this.redisClient.on('error', (error) => { + if (error) { + this.logger.error(error); + HawkCatcher.send(error); + } + }); + } + + /** + * Connect to redis client + */ + public async initialize(): Promise { + try { + await this.redisClient.connect(); + } catch (error) { + console.error('Error connecting to redis', error); + } + } + + /** + * Close redis client + */ + public async close(): Promise { + if (this.redisClient.isOpen) { + await this.redisClient.quit(); + } + } + /** * Checks if a lock exists on the given group hash and identifier pair. If it does not exist, creates a lock. * Returns true if lock exists @@ -29,12 +64,20 @@ export default class RedisHelper { * @param groupHash - event group hash * @param userId - event user id */ - public checkOrSetEventLock(groupHash: string, userId: string): Promise { - return new Promise((resolve, reject) => { - const callback = this.createCallback(resolve, reject); + public async checkOrSetEventLock(groupHash: string, userId: string): Promise { + const result = await this.redisClient.set( + `${groupHash}:${userId}`, + '1', + { + EX: RedisHelper.LOCK_TTL, + NX: true, + } as const + ); - this.redisClient.set(`${groupHash}:${userId}`, '1', 'EX', RedisHelper.LOCK_TTL, 'NX', callback); - }); + /** + * Result would be null if lock already exists, false otherwise + */ + return result === null; } /** diff --git a/workers/grouper/tests/index.test.ts b/workers/grouper/tests/index.test.ts index 36203a35..9ff9dd6b 100644 --- a/workers/grouper/tests/index.test.ts +++ b/workers/grouper/tests/index.test.ts @@ -1,7 +1,7 @@ import '../../../env-test'; import GrouperWorker from '../src'; import { GroupWorkerTask } from '../types/group-worker-task'; -import redis from 'redis'; +import { createClient, RedisClientType } from 'redis'; import { Collection, MongoClient } from 'mongodb'; import { EventAddons, EventDataAccepted } from '@hawk.so/types'; @@ -74,14 +74,16 @@ function generateTask(event: Partial> = undefined } describe('GrouperWorker', () => { - const worker = new GrouperWorker(); let connection: MongoClient; let eventsCollection: Collection; let dailyEventsCollection: Collection; let repetitionsCollection: Collection; - let redisClient; + let redisClient: RedisClientType; + let worker: GrouperWorker; beforeAll(async () => { + worker = new GrouperWorker(); + await worker.start(); connection = await MongoClient.connect(process.env.MONGO_EVENTS_DATABASE_URI, { useNewUrlParser: true, @@ -90,7 +92,10 @@ describe('GrouperWorker', () => { eventsCollection = connection.db().collection('events:' + projectIdMock); dailyEventsCollection = connection.db().collection('dailyEvents:' + projectIdMock); repetitionsCollection = connection.db().collection('repetitions:' + projectIdMock); - redisClient = redis.createClient({ url: process.env.REDIS_URL }); + + redisClient = createClient({ url: process.env.REDIS_URL }); + await redisClient.connect(); + jest.resetAllMocks(); }); @@ -104,8 +109,8 @@ describe('GrouperWorker', () => { await repetitionsCollection.deleteMany({}); }); - afterEach((done) => { - redisClient.flushall(done); + afterEach(async () => { + await redisClient.flushAll(); }); describe('Saving events', () => { @@ -299,6 +304,7 @@ describe('GrouperWorker', () => { }); afterAll(async () => { + await redisClient.quit(); await worker.finish(); await connection.close(); }); diff --git a/workers/limiter/package.json b/workers/limiter/package.json index 6a5a5bd2..7491ecc1 100644 --- a/workers/limiter/package.json +++ b/workers/limiter/package.json @@ -10,7 +10,6 @@ "workerType": "cron-tasks/limiter", "dependencies": { "@types/redis": "^2.8.28", - "axios": "^0.21.2", - "redis": "^3.1.1" + "axios": "^0.21.2" } } diff --git a/workers/limiter/src/index.ts b/workers/limiter/src/index.ts index 195cd886..b3452145 100644 --- a/workers/limiter/src/index.ts +++ b/workers/limiter/src/index.ts @@ -81,6 +81,9 @@ export default class LimiterWorker extends Worker { this.projectsCollection = accountDbConnection.collection('projects'); this.workspacesCollection = accountDbConnection.collection('workspaces'); + + await this.redis.initialize(); + await super.start(); } @@ -91,6 +94,7 @@ export default class LimiterWorker extends Worker { await super.finish(); await this.eventsDb.close(); await this.accountsDb.close(); + await this.redis.close(); } /** diff --git a/workers/limiter/src/redisHelper.ts b/workers/limiter/src/redisHelper.ts index 9e06f769..dd8ddb51 100644 --- a/workers/limiter/src/redisHelper.ts +++ b/workers/limiter/src/redisHelper.ts @@ -1,5 +1,5 @@ import HawkCatcher from '@hawk.so/nodejs'; -import redis from 'redis'; +import { createClient, RedisClientType } from 'redis'; import createLogger from '../../../lib/logger'; /** @@ -9,7 +9,8 @@ export default class RedisHelper { /** * Redis client for making queries */ - private readonly redisClient = redis.createClient({ url: process.env.REDIS_URL }); + // private readonly redisClient = redis.createClient({ url: process.env.REDIS_URL }); + private readonly redisClient: RedisClientType; /** * Logger instance @@ -22,6 +23,35 @@ export default class RedisHelper { */ private readonly redisDisabledProjectsKey = 'DisabledProjectsSet'; + /** + * Constructor of the Redis helper class + * Initializes the Redis client and sets up error handling + */ + constructor() { + this.redisClient = createClient({ url: process.env.REDIS_URL }); + + this.redisClient.on('error', (error) => { + this.logger.error(error); + HawkCatcher.send(error); + }); + } + + /** + * Connect to redis client + */ + public async initialize(): Promise { + await this.redisClient.connect(); + } + + /** + * Close redis client + */ + public async close(): Promise { + if (this.redisClient.isOpen) { + await this.redisClient.quit(); + } + } + /** * Saves banned project ids to redis * If there is no projects, then previous data in Redis will be erased @@ -33,12 +63,26 @@ export default class RedisHelper { const callback = this.createCallback(resolve, reject); if (projectIdsToBan.length) { - this.redisClient.multi() - .del(this.redisDisabledProjectsKey) - .sadd(this.redisDisabledProjectsKey, projectIdsToBan) - .exec(callback); + const pipeline = this.redisClient.multi(); + + pipeline.del(this.redisDisabledProjectsKey); + + pipeline.sAdd(this.redisDisabledProjectsKey, projectIdsToBan); + + try { + pipeline.exec(); + callback(null); + } catch (err) { + callback(err); + } } else { - this.redisClient.del(this.redisDisabledProjectsKey, callback); + this.redisClient.del(this.redisDisabledProjectsKey) + .then(() => { + callback(null); + }) + .catch((err) => { + callback(err); + }); } }); } @@ -53,7 +97,9 @@ export default class RedisHelper { const callback = this.createCallback(resolve, reject); if (projectIds.length) { - this.redisClient.sadd(this.redisDisabledProjectsKey, projectIds, callback); + this.redisClient.sAdd(this.redisDisabledProjectsKey, projectIds) + .then(() => callback(null)) + .catch((err) => callback(err)); } else { resolve(); } @@ -70,7 +116,9 @@ export default class RedisHelper { const callback = this.createCallback(resolve, reject); if (projectIds.length) { - this.redisClient.srem(this.redisDisabledProjectsKey, projectIds, callback); + this.redisClient.sRem(this.redisDisabledProjectsKey, projectIds) + .then(() => callback(null)) + .catch((err) => callback(err)); } else { resolve(); } diff --git a/workers/limiter/tests/index.test.ts b/workers/limiter/tests/index.test.ts index 64e80819..810a710e 100644 --- a/workers/limiter/tests/index.test.ts +++ b/workers/limiter/tests/index.test.ts @@ -2,7 +2,7 @@ import { Collection, Db, MongoClient, ObjectId } from 'mongodb'; import '../../../env-test'; import { GroupedEventDBScheme, PlanDBScheme, ProjectDBScheme, WorkspaceDBScheme } from '@hawk.so/types'; import LimiterWorker from '../src'; -import redis from 'redis'; +import { createClient } from 'redis'; import { mockedPlans } from './plans.mock'; import axios from 'axios'; import { mocked } from 'ts-jest/utils'; @@ -128,7 +128,8 @@ describe('Limiter worker', () => { projectCollection = db.collection('projects'); workspaceCollection = db.collection('workspaces'); planCollection = db.collection('plans'); - redisClient = redis.createClient({ url: process.env.REDIS_URL }); + redisClient = createClient({ url: process.env.REDIS_URL }); + await redisClient.connect(); /** * Insert mocked plans for using in tests @@ -225,11 +226,10 @@ describe('Limiter worker', () => { * * Gets all members of set with key 'DisabledProjectsSet' from Redis */ - redisClient.smembers('DisabledProjectsSet', (err, result) => { - expect(err).toBeNull(); - expect(result).toContain(project._id.toString()); - done(); - }); + const result = await redisClient.sMembers('DisabledProjectsSet'); + + expect(result).toContain(project._id.toString()); + done(); }); test('Should not ban project if it does not reach the limit', async (done) => { @@ -265,15 +265,10 @@ describe('Limiter worker', () => { * * Gets all members of set with key 'DisabledProjectsSet' from Redis */ - redisClient.smembers('DisabledProjectsSet', (err, result) => { - expect(err).toBeNull(); - - /** - * Redis shouldn't contain id of project 'Test project #2' from 'Test workspace #2' - */ - expect(result).not.toContain(project._id.toString()); - done(); - }); + const result = await redisClient.sMembers('DisabledProjectsSet'); + + expect(result).not.toContain(project._id.toString()); + done(); }); test('Should send a report with collected data', async () => { @@ -344,11 +339,10 @@ describe('Limiter worker', () => { * * Gets all members of set with key 'DisabledProjectsSet' from Redis */ - redisClient.smembers('DisabledProjectsSet', (err, result) => { - expect(err).toBeNull(); - expect(result).toContain(project._id.toString()); - done(); - }); + const result = await redisClient.sMembers('DisabledProjectsSet'); + + expect(result).toContain(project._id.toString()); + done(); }); }); @@ -405,15 +399,13 @@ describe('Limiter worker', () => { /** * Gets all members of set with key 'DisabledProjectsSet' from Redis */ - redisClient.smembers('DisabledProjectsSet', (err, result) => { - expect(err).toBeNull(); - - /** - * Redis shouldn't contain id of project 'Test project #2' from 'Test workspace #2' - */ - expect(result).not.toContain(project._id.toString()); - done(); - }); + const result = await redisClient.sMembers('DisabledProjectsSet'); + + /** + * Redis shouldn't contain id of project 'Test project #2' from 'Test workspace #2' + */ + expect(result).not.toContain(project._id.toString()); + done(); }); test('Should block workspace if the number of events exceed the limit', async (done) => { @@ -468,15 +460,11 @@ describe('Limiter worker', () => { /** * Gets all members of set with key 'DisabledProjectsSet' from Redis */ - redisClient.smembers('DisabledProjectsSet', (err, result) => { - expect(err).toBeNull(); - - /** - * Redis shouldn't contain id of the mocked project - */ - expect(result).toContain(project._id.toString()); - done(); - }); + + const result = await redisClient.sMembers('DisabledProjectsSet'); + + expect(result).toContain(project._id.toString()); + done(); }); test('Should correctly work if projects count equals 0', async () => { @@ -504,5 +492,6 @@ describe('Limiter worker', () => { afterAll(async () => { await connection.close(); + await redisClient.quit(); }); }); diff --git a/yarn.lock b/yarn.lock index 5318b637..a6b2649f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -297,6 +297,11 @@ "@babel/helper-validator-identifier" "^7.14.9" to-fast-properties "^2.0.0" +"@balena/dockerignore@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@balena/dockerignore/-/dockerignore-1.0.2.tgz#9ffe4726915251e8eb69f44ef3547e0da2c03e0d" + integrity sha512-wMue2Sy4GAVTk6Ic4tJVcnfdau+gx2EnG7S+uAEe+TWJFqE4YoWN4/H8MSLj4eYJKxGg26lZwboEniNiNwZQ6Q== + "@bcoe/v8-coverage@^0.2.3": version "0.2.3" resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" @@ -569,6 +574,40 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@redis/bloom@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@redis/bloom/-/bloom-1.2.0.tgz#d3fd6d3c0af3ef92f26767b56414a370c7b63b71" + integrity sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg== + +"@redis/client@1.6.0": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@redis/client/-/client-1.6.0.tgz#dcf4ae1319763db6fdddd6de7f0af68a352c30ea" + integrity sha512-aR0uffYI700OEEH4gYnitAnv3vzVGXCFvYfdpu/CJKvk4pHfLPEy/JSZyrpQ+15WhXe1yJRXLtfQ84s4mEXnPg== + dependencies: + cluster-key-slot "1.1.2" + generic-pool "3.9.0" + yallist "4.0.0" + +"@redis/graph@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@redis/graph/-/graph-1.1.1.tgz#8c10df2df7f7d02741866751764031a957a170ea" + integrity sha512-FEMTcTHZozZciLRl6GiiIB4zGm5z5F3F6a6FZCyrfxdKOhFlGkiAqlexWMBzCi4DcRoyiOsuLfW+cjlGWyExOw== + +"@redis/json@1.0.7": + version "1.0.7" + resolved "https://registry.yarnpkg.com/@redis/json/-/json-1.0.7.tgz#016257fcd933c4cbcb9c49cde8a0961375c6893b" + integrity sha512-6UyXfjVaTBTJtKNG4/9Z8PSpKE6XgSyEb8iwaqDcy+uKrd/DGYHTWkUdnQDyzm727V7p21WUMhsqz5oy65kPcQ== + +"@redis/search@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@redis/search/-/search-1.2.0.tgz#50976fd3f31168f585666f7922dde111c74567b8" + integrity sha512-tYoDBbtqOVigEDMAcTGsRlMycIIjwMCgD8eR2t0NANeQmgK/lvxNAvYyb6bZDD4frHRhIHkJu2TBRvB0ERkOmw== + +"@redis/time-series@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@redis/time-series/-/time-series-1.1.0.tgz#cba454c05ec201bd5547aaf55286d44682ac8eb5" + integrity sha512-c1Q99M5ljsIuc4YdaCwfUEXsofakb9c8+Zse2qxTadu8TalLXuAESzLvFAvNVbkmSlvlzIQOLpBCmWI9wTOt+g== + "@sentry/core@^8.45.1": version "8.45.1" resolved "https://registry.yarnpkg.com/@sentry/core/-/core-8.45.1.tgz#da3b13a8fd2276e8a1d4f5a38f9b8a0ed6647b49" @@ -669,6 +708,13 @@ dependencies: bson "*" +"@types/dockerode@^2.5.34": + version "2.5.34" + resolved "https://registry.yarnpkg.com/@types/dockerode/-/dockerode-2.5.34.tgz#9adb884f7cc6c012a6eb4b2ad794cc5d01439959" + integrity sha512-LcbLGcvcBwBAvjH9UrUI+4qotY+A5WCer5r43DR5XHv2ZIEByNXFdPLo1XxR+v/BjkGjlggW8qUiXuVEhqfkpA== + dependencies: + "@types/node" "*" + "@types/dotenv@^8.2.0": version "8.2.0" resolved "https://registry.yarnpkg.com/@types/dotenv/-/dotenv-8.2.0.tgz#5cd64710c3c98e82d9d15844375a33bf1b45d053" @@ -1175,6 +1221,11 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" +any-promise@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" + integrity sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A== + anymatch@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" @@ -1276,6 +1327,13 @@ asn1.js@^5.2.0: minimalistic-assert "^1.0.0" safer-buffer "^2.1.0" +asn1@^0.2.6: + version "0.2.6" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" + integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== + dependencies: + safer-buffer "~2.1.0" + asn1@~0.2.3: version "0.2.4" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" @@ -1442,10 +1500,10 @@ base@^0.11.1: mixin-deep "^1.2.0" pascalcase "^0.1.1" -bcrypt-pbkdf@^1.0.0: +bcrypt-pbkdf@^1.0.0, bcrypt-pbkdf@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" - integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= + integrity sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w== dependencies: tweetnacl "^0.14.3" @@ -1719,11 +1777,21 @@ buffer@^5.5.0, buffer@^5.6.0: base64-js "^1.3.1" ieee754 "^1.1.13" +buildcheck@~0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/buildcheck/-/buildcheck-0.0.6.tgz#89aa6e417cfd1e2196e3f8fe915eb709d2fe4238" + integrity sha512-8f9ZJCUXyT1M35Jx7MkBgmBMo3oHTTBIPLiY9xyL0pl3T5RwcPEY8cUHr5LBNfu/fk6c2T4DJZuVM/8ZZT2D2A== + builtin-status-codes@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= +byline@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/byline/-/byline-5.0.0.tgz#741c5216468eadc457b03410118ad77de8c1ddb1" + integrity sha512-s6webAy+R4SR8XVuJWt2V2rGvhnrhxN+9S15GNuTK3wKPOXFF6RNc+8ug2XhH+2s4f+uudG4kUVYmYOQWL2g0Q== + cacache@^12.0.2: version "12.0.4" resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.4.tgz#668bcbd105aeb5f1d92fe25570ec9525c8faa40c" @@ -1970,6 +2038,11 @@ clone@2.x: resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= +cluster-key-slot@1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz#88ddaa46906e303b5de30d3153b7d9fe0a0c19ac" + integrity sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA== + co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" @@ -2167,6 +2240,14 @@ core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== +cpu-features@~0.0.10: + version "0.0.10" + resolved "https://registry.yarnpkg.com/cpu-features/-/cpu-features-0.0.10.tgz#9aae536db2710c7254d7ed67cb3cbc7d29ad79c5" + integrity sha512-9IkYqtX3YHPCzoVg1Py+o9057a3i0fp7S530UWokCSaFVTc7CwXPRiOjRjBQQ18ZCNafx78YfnG+HALxtVmOGA== + dependencies: + buildcheck "~0.0.6" + nan "^2.19.0" + create-ecdh@^4.0.0: version "4.0.4" resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" @@ -2403,7 +2484,7 @@ delegates@^1.0.0: resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= -denque@^1.4.1, denque@^1.5.0: +denque@^1.4.1: version "1.5.1" resolved "https://registry.yarnpkg.com/denque/-/denque-1.5.1.tgz#07f670e29c9a78f8faecb2566a1e2c11929c5cbf" integrity sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw== @@ -2457,6 +2538,32 @@ dir-glob@^3.0.1: dependencies: path-type "^4.0.0" +docker-compose@^0.23.5: + version "0.23.19" + resolved "https://registry.yarnpkg.com/docker-compose/-/docker-compose-0.23.19.tgz#9947726e2fe67bdfa9e8efe1ff15aa0de2e10eb8" + integrity sha512-v5vNLIdUqwj4my80wxFDkNH+4S85zsRuH29SO7dCWVWPCMt/ohZBsGN6g6KXWifT0pzQ7uOxqEKCYCDPJ8Vz4g== + dependencies: + yaml "^1.10.2" + +docker-modem@^3.0.0: + version "3.0.8" + resolved "https://registry.yarnpkg.com/docker-modem/-/docker-modem-3.0.8.tgz#ef62c8bdff6e8a7d12f0160988c295ea8705e77a" + integrity sha512-f0ReSURdM3pcKPNS30mxOHSbaFLcknGmQjwSfmbcdOw1XWKXVhukM3NJHhr7NpY9BIyyWQb0EBo3KQvvuU5egQ== + dependencies: + debug "^4.1.1" + readable-stream "^3.5.0" + split-ca "^1.0.1" + ssh2 "^1.11.0" + +dockerode@^3.2.1: + version "3.3.5" + resolved "https://registry.yarnpkg.com/dockerode/-/dockerode-3.3.5.tgz#7ae3f40f2bec53ae5e9a741ce655fff459745629" + integrity sha512-/0YNa3ZDNeLr/tSckmD69+Gq+qVNhvKfAHNeZJBnp7EOP6RGKV8ORrJHkUn20So5wU+xxT7+1n5u8PjHbfjbSA== + dependencies: + "@balena/dockerignore" "^1.0.2" + docker-modem "^3.0.0" + tar-fs "~2.0.1" + doctrine@1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" @@ -3323,6 +3430,11 @@ gc-stats@^1.4.0: nan "^2.13.2" node-pre-gyp "^0.13.0" +generic-pool@3.9.0: + version "3.9.0" + resolved "https://registry.yarnpkg.com/generic-pool/-/generic-pool-3.9.0.tgz#36f4a678e963f4fdb8707eab050823abc4e8f5e4" + integrity sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g== + gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" @@ -3425,6 +3537,18 @@ glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4: once "^1.3.0" path-is-absolute "^1.0.0" +glob@^7.1.6: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + global-dirs@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-3.0.0.tgz#70a76fe84ea315ab37b1f5576cbde7d48ef72686" @@ -5107,6 +5231,13 @@ minimatch@3.0.4, minimatch@3.0.x, minimatch@^3.0.4: dependencies: brace-expansion "^1.1.7" +minimatch@^3.1.1: + 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" + minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" @@ -5151,6 +5282,11 @@ mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" +mkdirp-classic@^0.5.2: + version "0.5.3" + resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" + integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== + mkdirp@0.5.5, mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.5: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" @@ -5305,6 +5441,11 @@ nan@^2.12.1, nan@^2.13.2: resolved "https://registry.yarnpkg.com/nan/-/nan-2.15.0.tgz#3f34a473ff18e15c1b5626b62903b5ad6e665fee" integrity sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ== +nan@^2.19.0, nan@^2.20.0: + version "2.22.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.22.0.tgz#31bc433fc33213c97bad36404bb68063de604de3" + integrity sha512-nbajikzWTMwsW+eSsNm3QwlOs7het9gGJU5dDZzRTQGk03vyBOauxgI4VakDzE0PtsGTmXPsXTbbjVhRwR5mpw== + nanoid@^3.1.31: version "3.1.31" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.31.tgz#f5b58a1ce1b7604da5f0605757840598d8974dc6" @@ -5358,6 +5499,11 @@ node-cache@^5.1.2: dependencies: clone "2.x" +node-duration@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/node-duration/-/node-duration-1.0.4.tgz#3e94ecc0e473691c89c4560074503362071cecac" + integrity sha512-eUXYNSY7DL53vqfTosggWkvyIW3bhAcqBDIlolgNYlZhianXTrCL50rlUJWD1eRqkIxMppXTfiFbp+9SjpPrgA== + node-environment-flags@1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.6.tgz#a30ac13621f6f7d674260a54dede048c3982c088" @@ -6265,7 +6411,7 @@ read-pkg@^5.2.0: isarray "0.0.1" string_decoder "~0.10.x" -readable-stream@^3.1.1: +readable-stream@^3.1.1, readable-stream@^3.5.0: version "3.6.2" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== @@ -6311,37 +6457,17 @@ realpath-native@^2.0.0: resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-2.0.0.tgz#7377ac429b6e1fd599dc38d08ed942d0d7beb866" integrity sha512-v1SEYUOXXdbBZK8ZuNgO4TBjamPsiSgcFr0aP+tEKpQZK8vooEUqV6nm6Cv502mX4NF2EfsnVqtNAHG+/6Ur1Q== -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" - integrity sha1-62LSrbFeTq9GEMBK/hUpOEJQq60= - -redis-mock@^0.56.3: - version "0.56.3" - resolved "https://registry.yarnpkg.com/redis-mock/-/redis-mock-0.56.3.tgz#e96471bcc774ddc514c2fc49cdd03cab2baecd89" - integrity sha512-ynaJhqk0Qf3Qajnwvy4aOjS4Mdf9IBkELWtjd+NYhpiqu4QCNq6Vf3Q7c++XRPGiKiwRj9HWr0crcwy7EiPjYQ== - -redis-parser@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/redis-parser/-/redis-parser-3.0.0.tgz#b66d828cdcafe6b4b8a428a7def4c6bcac31c8b4" - integrity sha1-tm2CjNyv5rS4pCin3vTGvKwxyLQ= - dependencies: - redis-errors "^1.0.0" - -redis@^3.1.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/redis/-/redis-3.1.2.tgz#766851117e80653d23e0ed536254677ab647638c" - integrity sha512-grn5KoZLr/qrRQVwoSkmzdbw6pwF+/rwODtrOr6vuBRiR/f3rjSTGupbF90Zpqm2oenix8Do6RV7pYEkGwlKkw== +redis@^4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/redis/-/redis-4.7.0.tgz#b401787514d25dd0cfc22406d767937ba3be55d6" + integrity sha512-zvmkHEAdGMn+hMRXuMBtu4Vo5P6rHQjLoHftu+lBqq8ZTA3RCVC/WzD790bkKKiNFp7d5/9PcSD19fJyyRvOdQ== dependencies: - denque "^1.5.0" - redis-commands "^1.7.0" - redis-errors "^1.2.0" - redis-parser "^3.0.0" + "@redis/bloom" "1.2.0" + "@redis/client" "1.6.0" + "@redis/graph" "1.1.1" + "@redis/json" "1.0.7" + "@redis/search" "1.2.0" + "@redis/time-series" "1.1.0" regenerator-runtime@^0.13.4: version "0.13.9" @@ -6896,6 +7022,11 @@ spdx-license-ids@^3.0.0: resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.10.tgz#0d9becccde7003d6c658d487dd48a32f0bf3014b" integrity sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA== +split-ca@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/split-ca/-/split-ca-1.0.1.tgz#6c83aff3692fa61256e0cd197e05e9de157691a6" + integrity sha512-Q5thBSxp5t8WPTTJQS59LrGqOZqOsrhDGDVm8azCqIBjSBd7nd9o2PM+mDulQQkh8h//4U6hFZnc/mul8t5pWQ== + split-string@^3.0.1, split-string@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" @@ -6908,6 +7039,17 @@ sprintf-js@~1.0.2: resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= +ssh2@^1.11.0: + version "1.16.0" + resolved "https://registry.yarnpkg.com/ssh2/-/ssh2-1.16.0.tgz#79221d40cbf4d03d07fe881149de0a9de928c9f0" + integrity sha512-r1X4KsBGedJqo7h8F5c4Ybpcr5RjyP+aWIG007uBPRjmdQWfEiVLzSK71Zji1B9sKxwaCvD8y8cwSkYrlLiRRg== + dependencies: + asn1 "^0.2.6" + bcrypt-pbkdf "^1.0.2" + optionalDependencies: + cpu-features "~0.0.10" + nan "^2.20.0" + sshpk@^1.7.0: version "1.16.1" resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" @@ -6987,6 +7129,13 @@ stream-shift@^1.0.0: resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== +stream-to-array@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/stream-to-array/-/stream-to-array-2.3.0.tgz#bbf6b39f5f43ec30bc71babcb37557acecf34353" + integrity sha512-UsZtOYEn4tWU2RGLOXr/o/xjRBftZRlG3dEWoaHr8j4GuypJ3isitGbVyjQKAuMu+xbiop8q224TjiZWc4XTZA== + dependencies: + any-promise "^1.1.0" + string-length@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/string-length/-/string-length-3.1.0.tgz#107ef8c23456e187a8abd4a61162ff4ac6e25837" @@ -7179,7 +7328,27 @@ tapable@^1.0.0, tapable@^1.1.3: resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== -tar-stream@^2.1.4: +tar-fs@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.1.tgz#489a15ab85f1f0befabb370b7de4f9eb5cbe8784" + integrity sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng== + dependencies: + chownr "^1.1.1" + mkdirp-classic "^0.5.2" + pump "^3.0.0" + tar-stream "^2.1.4" + +tar-fs@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.0.1.tgz#e44086c1c60d31a4f0cf893b1c4e155dabfae9e2" + integrity sha512-6tzWDMeroL87uF/+lin46k+Q+46rAJ0SyPGz7OW7wTgblI273hsBqk2C1j0/xNadNLKDTUL9BukSjB7cwgmlPA== + dependencies: + chownr "^1.1.1" + mkdirp-classic "^0.5.2" + pump "^3.0.0" + tar-stream "^2.0.0" + +tar-stream@^2.0.0, tar-stream@^2.1.4: version "2.2.0" resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287" integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ== @@ -7251,6 +7420,22 @@ test-exclude@^6.0.0: glob "^7.1.4" minimatch "^3.0.4" +testcontainers@^3.0.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/testcontainers/-/testcontainers-3.5.0.tgz#da8a3fa53f1c6d106ccff7e0f71bf86d358c2589" + integrity sha512-iigGuzBDzOmTFlxfaTo1JO7EGMs4Dgf+XHd98XeEwp8J+WzOdkJfsSL5A8fdLSGQA5GvVAdxLcUfT4a32z4rbg== + dependencies: + "@types/dockerode" "^2.5.34" + byline "^5.0.0" + debug "^4.1.1" + docker-compose "^0.23.5" + dockerode "^3.2.1" + get-port "^5.1.1" + glob "^7.1.6" + node-duration "^1.0.4" + stream-to-array "^2.3.0" + tar-fs "^2.1.0" + text-hex@1.0.x: version "1.0.0" resolved "https://registry.yarnpkg.com/text-hex/-/text-hex-1.0.0.tgz#69dc9c1b17446ee79a92bf5b884bb4b9127506f5" @@ -7990,6 +8175,11 @@ y18n@^4.0.0: resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== +yallist@4.0.0, yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + yallist@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" @@ -8000,10 +8190,10 @@ yallist@^3.0.0, yallist@^3.0.2, yallist@^3.1.1: resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== -yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== +yaml@^1.10.2: + version "1.10.2" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" + integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== yargs-parser@13.1.2, yargs-parser@^13.1.2: version "13.1.2" From 6c8271eafa222409fd3a5b96c3196685daba737d Mon Sep 17 00:00:00 2001 From: Tatiana Fomina Date: Sat, 11 Jan 2025 23:25:06 +0300 Subject: [PATCH 3/3] Add isDebug (#339) * Add isDebug * Update index.ts * Update index.ts * Lint * Update ubuntu version --- workers/paymaster/src/index.ts | 40 ++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/workers/paymaster/src/index.ts b/workers/paymaster/src/index.ts index ab051024..2b0ee54b 100644 --- a/workers/paymaster/src/index.ts +++ b/workers/paymaster/src/index.ts @@ -63,12 +63,16 @@ export default class PaymasterWorker extends Worker { * Pay day is calculated by formula: last charge date + 30 days * * @param date - last charge date + * @param isDebug */ - private static isTimeToPay(date: Date): boolean { - const numberOfDays = 30; + private static isTimeToPay(date: Date, isDebug = false): boolean { const expectedPayDay = new Date(date); - expectedPayDay.setDate(date.getDate() + numberOfDays); + if (isDebug) { + expectedPayDay.setDate(date.getDate() + 1); + } else { + expectedPayDay.setMonth(date.getMonth() + 1); + } const now = new Date().getTime(); @@ -81,12 +85,16 @@ export default class PaymasterWorker extends Worker { * Pay day is calculated by formula: last charge date + 30 days * * @param date - last charge date + * @param isDebug */ - private static daysBeforePayday(date: Date): number { - const numberOfDays = 30; + private static daysBeforePayday(date: Date, isDebug = false): number { const expectedPayDay = new Date(date); - expectedPayDay.setDate(date.getDate() + numberOfDays); + if (isDebug) { + expectedPayDay.setDate(date.getDate() + 1); + } else { + expectedPayDay.setMonth(date.getMonth() + 1); + } const now = new Date().getTime(); @@ -99,12 +107,16 @@ export default class PaymasterWorker extends Worker { * Pay day is calculated by formula: last charge date + 30 days * * @param date - last charge date + * @param isDebug */ - private static daysAfterPayday(date: Date): number { - const numberOfDays = 30; + private static daysAfterPayday(date: Date, isDebug = false): number { const expectedPayDay = new Date(date); - expectedPayDay.setDate(date.getDate() + numberOfDays); + if (isDebug) { + expectedPayDay.setDate(date.getDate() + 1); + } else { + expectedPayDay.setMonth(date.getMonth() + 1); + } const now = new Date().getTime(); @@ -196,17 +208,20 @@ export default class PaymasterWorker extends Worker { /** * Is it time to pay */ - const isTimeToPay = PaymasterWorker.isTimeToPay(workspace.lastChargeDate); + // @ts-expect-error debug + const isTimeToPay = PaymasterWorker.isTimeToPay(workspace.lastChargeDate, workspace.isDebug); /** * How many days have passed since payments the expected day of payments */ - const daysAfterPayday = PaymasterWorker.daysAfterPayday(workspace.lastChargeDate); + // @ts-expect-error debug + const daysAfterPayday = PaymasterWorker.daysAfterPayday(workspace.lastChargeDate, workspace.isDebug); /** * How many days left for the expected day of payments */ - const daysLeft = PaymasterWorker.daysBeforePayday(workspace.lastChargeDate); + // @ts-expect-error debug + const daysLeft = PaymasterWorker.daysBeforePayday(workspace.lastChargeDate, workspace.isDebug); /** * Do we need to ask for money @@ -215,6 +230,7 @@ export default class PaymasterWorker extends Worker { /** * Today is not payday for workspace + * Alerting admins to pay for the workspace */ if (!isTimeToPay) { /**