refactor: inventory cost process

This commit is contained in:
Ahmed Bouhuolia
2025-03-14 03:51:45 +02:00
parent 197d173db9
commit 08de50e2b1
14 changed files with 346 additions and 96 deletions

View File

@@ -24,6 +24,7 @@
"@bigcapital/pdf-templates": "*",
"@bigcapital/server": "*",
"@bigcapital/utils": "*",
"@liaoliaots/nestjs-redis": "^10.0.0",
"@nestjs/bull": "^10.2.1",
"@nestjs/bullmq": "^10.2.2",
"@nestjs/cache-manager": "^2.2.2",
@@ -55,6 +56,7 @@
"express-validator": "^7.2.0",
"form-data": "^4.0.0",
"fp-ts": "^2.16.9",
"ioredis": "^5.6.0",
"is-my-json-valid": "^2.20.5",
"js-money": "^0.6.3",
"knex": "^3.1.0",
@@ -66,6 +68,7 @@
"mysql2": "^3.11.3",
"nestjs-cls": "^5.2.0",
"nestjs-i18n": "^10.4.9",
"nestjs-redis": "^1.3.3",
"nodemailer": "^6.3.0",
"object-hash": "^2.0.3",
"objection": "^3.1.5",

View File

@@ -0,0 +1,8 @@
import { registerAs } from '@nestjs/config';
export default registerAs('redis', () => ({
host: process.env.REDIS_HOST || 'localhost',
port: parseInt(process.env.REDIS_PORT, 10) || 6379,
password: process.env.REDIS_PASSWORD || undefined,
db: parseInt(process.env.REDIS_DB, 10) || 0,
}));

View File

@@ -23,7 +23,7 @@ export class AccountRepository extends TenantRepository {
private readonly tenancyContext: TenancyContext,
@Inject(TENANCY_DB_CONNECTION)
private readonly tenantDBKnex: Knex,
private readonly tenantDBKnex: () => Knex,
) {
super();
}
@@ -32,7 +32,7 @@ export class AccountRepository extends TenantRepository {
* Gets the repository's model.
*/
get model(): typeof Account {
return Account.bindKnex(this.tenantDBKnex);
return Account.bindKnex(this.tenantDBKnex());
}
/**

View File

@@ -71,6 +71,7 @@ import { StripePaymentModule } from '../StripePayment/StripePayment.module';
import { FeaturesModule } from '../Features/Features.module';
import { InventoryCostModule } from '../InventoryCost/InventoryCost.module';
import { WarehousesTransfersModule } from '../WarehousesTransfers/WarehouseTransfers.module';
import { RedisModule } from '@liaoliaots/nestjs-redis';
@Module({
imports: [
@@ -124,6 +125,16 @@ import { WarehousesTransfersModule } from '../WarehousesTransfers/WarehouseTrans
saveReq: true,
},
}),
RedisModule.forRootAsync({
imports: [ConfigModule],
useFactory: (configService: ConfigService) => ({
config: {
host: configService.get('redis.host') || 'localhost',
port: configService.get('redis.port') || 6379,
},
}),
inject: [ConfigService],
}),
TenancyDatabaseModule,
TenancyModelsModule,
ChromiumlyTenancyModule,

View File

@@ -12,13 +12,10 @@ export class AppService {
) {}
getHello(): string {
console.log(this.configService.get('DATABASE_PORT'));
const payload = {};
const accessToken = this.jwtService.sign(payload);
console.log(accessToken);
return accessToken;
}
}

View File

@@ -0,0 +1,8 @@
import { Module } from '@nestjs/common';
import { ImportAls } from './ImportALS';
@Module({
providers: [ImportAls],
exports: [ImportAls],
})
export class ImportModule {}

View File

@@ -1,4 +1,4 @@
import { Module } from '@nestjs/common';
import { forwardRef, Module } from '@nestjs/common';
import { InventoryCostGLStorage } from './commands/InventoryCostGLStorage.service';
import { RegisterTenancyModel } from '../Tenancy/TenancyModels/Tenancy.module';
import { InventoryCostLotTracker } from './models/InventoryCostLotTracker';
@@ -20,6 +20,9 @@ import { BullModule } from '@nestjs/bullmq';
import { InventoryAverageCostMethodService } from './commands/InventoryAverageCostMethod.service';
import { InventoryItemCostService } from './commands/InventoryCosts.service';
import { InventoryItemOpeningAvgCostService } from './commands/InventoryItemOpeningAvgCost.service';
import { InventoryCostSubscriber } from './subscribers/InventoryCost.subscriber';
import { SaleInvoicesModule } from '../SaleInvoices/SaleInvoices.module';
import { ImportModule } from '../Import/Import.module';
const models = [
RegisterTenancyModel(InventoryCostLotTracker),
@@ -34,6 +37,8 @@ const models = [
BullModule.registerQueue({
name: WriteInventoryTransactionsGLEntriesQueue,
}),
forwardRef(() => SaleInvoicesModule),
ImportModule,
],
providers: [
InventoryCostGLBeforeWriteSubscriber,
@@ -48,7 +53,13 @@ const models = [
InventoryAverageCostMethodService,
InventoryItemCostService,
InventoryItemOpeningAvgCostService,
InventoryCostSubscriber,
],
exports: [
...models,
InventoryTransactionsService,
InventoryItemCostService,
InventoryComputeCostService,
],
exports: [...models, InventoryTransactionsService, InventoryItemCostService],
})
export class InventoryCostModule {}

View File

@@ -1,30 +1,51 @@
import { pick } from 'lodash';
import { Queue } from 'bullmq';
import { ClsService } from 'nestjs-cls';
import Redis from 'ioredis';
import { Inject, Injectable } from '@nestjs/common';
import { Knex } from 'knex';
import { UnitOfWork } from '../../Tenancy/TenancyDB/UnitOfWork.service';
import { Item } from '../../Items/models/Item';
import { SETTINGS_PROVIDER } from '../../Settings/Settings.types';
import { SettingsStore } from '../../Settings/SettingsStore';
import { InventoryTransaction } from '../models/InventoryTransaction';
import { IItemEntryTransactionType } from '../../TransactionItemEntry/ItemEntry.types';
import { ModelObject } from 'objection';
import { ItemEntry } from '../../TransactionItemEntry/models/ItemEntry';
import { TInventoryTransactionDirection } from '../types/InventoryCost.types';
import {
ComputeItemCostQueue,
ComputeItemCostQueueJob,
} from '../types/InventoryCost.types';
import { InventoryAverageCostMethodService } from './InventoryAverageCostMethod.service';
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
import { InjectQueue } from '@nestjs/bullmq';
import { RedisService } from '@liaoliaots/nestjs-redis';
@Injectable()
export class InventoryComputeCostService {
private readonly redisClient: Redis;
/**
* @param {UnitOfWork} uow - Unit of work.
* @param {InventoryAverageCostMethodService} inventoryAverageCostMethod - Inventory average cost method.
* @param {RedisService} redisService - Redis service.
* @param {ClsService} clsService - Cls service.
* @param {Queue} computeItemCostProcessor - Compute item cost processor.
* @param {TenantModelProxy<typeof Item>} itemModel - Item model.
* @param {() => SettingsStore} settingsStore - Settings store.
*/
constructor(
private readonly uow: UnitOfWork,
private readonly inventoryAverageCostMethod: InventoryAverageCostMethodService,
private readonly clsService: ClsService,
private readonly redisService: RedisService,
@InjectQueue(ComputeItemCostQueue)
private readonly computeItemCostProcessor: Queue,
@Inject(Item.name)
private readonly itemModel: TenantModelProxy<typeof Item>,
@Inject(SETTINGS_PROVIDER)
private readonly settingsStore: () => SettingsStore,
) {}
) {
this.redisClient = this.redisService.getOrThrow();
}
/**
* Compute item cost.
@@ -67,63 +88,45 @@ export class InventoryComputeCostService {
/**
* Schedule item cost compute job.
* @param {number} tenantId
* @param {number} itemId
* @param {Date} startingDate
*/
async scheduleComputeItemCost(
itemId: number,
startingDate: Date | string,
) {
// const agenda = Container.get('agenda');
// const commonJobsQuery = {
// name: 'compute-item-cost',
// lastRunAt: { $exists: false },
// 'data.tenantId': tenantId,
// 'data.itemId': itemId,
// };
// // Cancel any `compute-item-cost` in the queue has upper starting date
// // with the same given item.
// await agenda.cancel({
// ...commonJobsQuery,
// 'data.startingDate': { $lte: startingDate },
// });
// // Retrieve any `compute-item-cost` in the queue has lower starting date
// // with the same given item.
// const dependsJobs = await agenda.jobs({
// ...commonJobsQuery,
// 'data.startingDate': { $gte: startingDate },
// });
// // If the depends jobs cleared.
// if (dependsJobs.length === 0) {
// await agenda.schedule(
// this.config.get('inventory.scheduleComputeItemCost'),
// 'compute-item-cost',
// {
// startingDate,
// itemId,
// tenantId,
// },
// );
// // Triggers `onComputeItemCostJobScheduled` event.
// await this.eventEmitter.emitAsync(
// events.inventory.onComputeItemCostJobScheduled,
// {
// startingDate,
// itemId,
// tenantId,
// } as IInventoryItemCostScheduledPayload,
// );
// } else {
// // Re-schedule the jobs that have higher date from current moment.
// await Promise.all(
// dependsJobs.map((job) =>
// job
// .schedule(this.config.get('inventory.scheduleComputeItemCost'))
// .save(),
// ),
// );
// }
async scheduleComputeItemCost(itemId: number, startingDate: Date | string) {
const debounceKey = `inventory-cost-compute-debounce:${itemId}`;
const debounceTime = 1000 * 60; // 1 minute
// Generate a unique job ID or use a custom identifier
const jobId = `task-${Date.now()}-${Math.random().toString(36).substring(2)}`;
// Check if there's an existing debounced job
const existingJobId = await this.redisClient.get(debounceKey);
if (existingJobId) {
// Attempt to remove or mark the previous job as skippable
const existingJob =
await this.computeItemCostProcessor.getJob(existingJobId);
const state = await existingJob?.getState();
if (existingJob && ['waiting', 'delayed'].includes(state)) {
await existingJob.remove(); // Remove the previous job if it's still waiting
}
}
const organizationId = this.clsService.get('organizationId');
const userId = this.clsService.get('userId');
// Add the new job with a delay (debounce period)
const job = await this.computeItemCostProcessor.add(
ComputeItemCostQueueJob,
{ itemId, startingDate, jobId, organizationId, userId },
{
jobId, // Custom job ID
delay: debounceTime, // Delay execution by 1 minute
},
);
// Store the latest job ID in Redis with an expiration
await this.redisClient.set(debounceKey, jobId, 'PX', debounceTime);
return { jobId, message: 'Task added with debounce' };
}
/**

View File

@@ -92,7 +92,7 @@ export class InventoryItemsQuantitySyncService {
const changeQuantityOper = this.itemModel()
.query(trx)
.where({ id: itemQuantity.itemId, type: 'inventory' })
.modify('quantityOnHand', itemQuantity.balanceChange);
.modify('updateQuantityOnHand', itemQuantity.balanceChange);
opers.push(changeQuantityOper);
});

View File

@@ -6,14 +6,18 @@ import { ClsService } from 'nestjs-cls';
import { TenantJobPayload } from '@/interfaces/Tenant';
import { InventoryComputeCostService } from '../commands/InventoryComputeCost.service';
import { events } from '@/common/events/events';
import { ComputeItemCostQueueJob } from '../types/InventoryCost.types';
import {
ComputeItemCostQueue,
ComputeItemCostQueueJob,
} from '../types/InventoryCost.types';
import { Process } from '@nestjs/bull';
interface ComputeItemCostJobPayload extends TenantJobPayload {
itemId: number;
startingDate: Date;
}
@Processor({
name: ComputeItemCostQueueJob,
name: ComputeItemCostQueue,
scope: Scope.REQUEST,
})
export class ComputeItemCostProcessor extends WorkerHost {
@@ -34,9 +38,12 @@ export class ComputeItemCostProcessor extends WorkerHost {
* Process the compute item cost job.
* @param {Job<ComputeItemCostJobPayload>} job - The job to process
*/
@Process(ComputeItemCostQueueJob)
async process(job: Job<ComputeItemCostJobPayload>) {
const { itemId, startingDate, organizationId, userId } = job.data;
console.log(`Compute item cost for item ${itemId} started`);
this.clsService.set('organizationId', organizationId);
this.clsService.set('userId', userId);
@@ -50,6 +57,8 @@ export class ComputeItemCostProcessor extends WorkerHost {
events.inventory.onComputeItemCostJobCompleted,
{ startingDate, itemId, organizationId, userId },
);
console.log(`Compute item cost for item ${itemId} completed`);
} catch (error) {
console.error('Error computing item cost:', error);
throw error;

View File

@@ -14,7 +14,7 @@ import { Injectable } from '@nestjs/common';
import { InventoryComputeCostService } from '../commands/InventoryComputeCost.service';
@Injectable()
export default class InventorySubscriber {
export class InventoryCostSubscriber {
constructor(
private readonly saleInvoicesCost: SaleInvoicesCost,
private readonly itemsQuantitySync: InventoryItemsQuantitySyncService,

View File

@@ -32,6 +32,25 @@ export class Item extends TenantBaseModel {
return 'items';
}
/**
* Model modifiers.
*/
static get modifiers() {
return {
updateQuantityOnHand(query, value: number) {
const q = query.where('type', 'inventory');
if (value > 0) {
q.increment('quantityOnHand', value);
}
if (value < 0) {
q.decrement('quantityOnHand', Math.abs(value));
}
return q;
},
};
}
/**
* Relationship mapping.
*/

View File

@@ -1,4 +1,4 @@
import { Module } from '@nestjs/common';
import { forwardRef, Module } from '@nestjs/common';
import { TenancyContext } from '../Tenancy/TenancyContext.service';
import { TenancyDatabaseModule } from '../Tenancy/TenancyDB/TenancyDB.module';
import { TransformerInjectable } from '../Transformer/TransformerInjectable.service';
@@ -55,6 +55,7 @@ import { SaleInvoiceWriteInventoryTransactionsSubscriber } from './subscribers/I
import { SaleInvoiceCostGLEntries } from './SaleInvoiceCostGLEntries';
import { InvoicePaymentsGLEntriesRewrite } from './InvoicePaymentsGLRewrite';
import { PaymentsReceivedModule } from '../PaymentReceived/PaymentsReceived.module';
import { SaleInvoicesCost } from './SalesInvoicesCost';
@Module({
imports: [
@@ -70,7 +71,7 @@ import { PaymentsReceivedModule } from '../PaymentReceived/PaymentsReceived.modu
AccountsModule,
MailModule,
MailNotificationModule,
InventoryCostModule,
forwardRef(() => InventoryCostModule),
DynamicListModule,
BullModule.registerQueue({ name: SendSaleInvoiceQueue }),
],
@@ -115,8 +116,9 @@ import { PaymentsReceivedModule } from '../PaymentReceived/PaymentsReceived.modu
InvoiceCostGLEntriesSubscriber,
InvoicePaymentGLRewriteSubscriber,
SaleInvoiceWriteInventoryTransactionsSubscriber,
InvoicePaymentsGLEntriesRewrite
InvoicePaymentsGLEntriesRewrite,
SaleInvoicesCost,
],
exports: [GetSaleInvoice],
exports: [GetSaleInvoice, SaleInvoicesCost],
})
export class SaleInvoicesModule {}

219
pnpm-lock.yaml generated
View File

@@ -490,9 +490,15 @@ importers:
'@bigcapital/pdf-templates':
specifier: '*'
version: link:../../shared/pdf-templates
'@bigcapital/server':
specifier: '*'
version: link:../server
'@bigcapital/utils':
specifier: '*'
version: link:../../shared/bigcapital-utils
'@liaoliaots/nestjs-redis':
specifier: ^10.0.0
version: 10.0.0(@nestjs/common@10.4.7)(@nestjs/core@10.4.7)(ioredis@5.6.0)
'@nestjs/bull':
specifier: ^10.2.1
version: 10.2.2(@nestjs/common@10.4.7)(@nestjs/core@10.4.7)(bull@4.16.4)
@@ -586,6 +592,9 @@ importers:
fp-ts:
specifier: ^2.16.9
version: 2.16.9
ioredis:
specifier: ^5.6.0
version: 5.6.0
is-my-json-valid:
specifier: ^2.20.5
version: 2.20.6
@@ -619,6 +628,9 @@ importers:
nestjs-i18n:
specifier: ^10.4.9
version: 10.5.0(@nestjs/common@10.4.7)(@nestjs/core@10.4.7)(class-validator@0.14.1)(rxjs@7.8.1)
nestjs-redis:
specifier: ^1.3.3
version: 1.3.3(@nestjs/platform-express@10.4.7)(cache-manager@6.1.3)(class-transformer@0.5.1)(class-validator@0.14.1)
nodemailer:
specifier: ^6.3.0
version: 6.9.13
@@ -7168,6 +7180,20 @@ packages:
npmlog: 6.0.2
dev: true
/@liaoliaots/nestjs-redis@10.0.0(@nestjs/common@10.4.7)(@nestjs/core@10.4.7)(ioredis@5.6.0):
resolution: {integrity: sha512-uCTmlzM4q+UYADwsJEQph0mbf4u0MrktFhByi50M5fNy/+fJoWlhSqrgvjtVKjHnqydxy1gyuU6vHJEOBp9cjg==}
engines: {node: '>=16.13.0'}
peerDependencies:
'@nestjs/common': ^10.0.0
'@nestjs/core': ^10.0.0
ioredis: ^5.0.0
dependencies:
'@nestjs/common': 10.4.7(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1)
'@nestjs/core': 10.4.7(@nestjs/common@10.4.7)(@nestjs/platform-express@10.4.7)(reflect-metadata@0.2.2)(rxjs@7.8.1)
ioredis: 5.6.0
tslib: 2.7.0
dev: false
/@ljharb/through@2.3.13:
resolution: {integrity: sha512-/gKJun8NNiWGZJkGzI/Ragc53cOdcLNdzjLaIa+GEjguQs0ulsurx8WN0jijdK9yPqDvziX995sMRLyLt1uZMQ==}
engines: {node: '>= 0.4'}
@@ -7415,6 +7441,35 @@ packages:
tslib: 2.7.0
uid: 2.0.2
/@nestjs/common@7.6.18(cache-manager@6.1.3)(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@6.6.7):
resolution: {integrity: sha512-BUJQHNhWzwWOkS4Ryndzd4HTeRObcAWV2Fh+ermyo3q3xYQQzNoEWclJVL/wZec8AONELwIJ+PSpWI53VP0leg==}
peerDependencies:
cache-manager: '*'
class-transformer: '*'
class-validator: '*'
reflect-metadata: ^0.1.12
rxjs: ^6.0.0
peerDependenciesMeta:
cache-manager:
optional: true
class-transformer:
optional: true
class-validator:
optional: true
dependencies:
axios: 0.21.1
cache-manager: 6.1.3
class-transformer: 0.5.1
class-validator: 0.14.1
iterare: 1.2.1
reflect-metadata: 0.2.2
rxjs: 6.6.7
tslib: 2.2.0
uuid: 8.3.2
transitivePeerDependencies:
- debug
dev: false
/@nestjs/common@8.4.7(cache-manager@6.1.3)(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1):
resolution: {integrity: sha512-m/YsbcBal+gA5CFrDpqXqsSfylo+DIQrkFY3qhVIltsYRfu8ct8J9pqsTO6OPf3mvqdOpFGrV5sBjoyAzOBvsw==}
peerDependencies:
@@ -7488,6 +7543,39 @@ packages:
transitivePeerDependencies:
- encoding
/@nestjs/core@7.6.18(@nestjs/common@7.6.18)(@nestjs/platform-express@10.4.7)(reflect-metadata@0.2.2)(rxjs@6.6.7):
resolution: {integrity: sha512-CGu20OjIxgFDY7RJT5t1TDGL8wSlTSlbZEkn8U5OlICZEB3WIpi98G7ajJpnRWmEgW8S4aDJmRKGjT+Ntj5U4A==}
requiresBuild: true
peerDependencies:
'@nestjs/common': ^7.0.0
'@nestjs/microservices': ^7.0.0
'@nestjs/platform-express': ^7.0.0
'@nestjs/websockets': ^7.0.0
reflect-metadata: ^0.1.12
rxjs: ^6.0.0
peerDependenciesMeta:
'@nestjs/microservices':
optional: true
'@nestjs/platform-express':
optional: true
'@nestjs/websockets':
optional: true
dependencies:
'@nestjs/common': 7.6.18(cache-manager@6.1.3)(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@6.6.7)
'@nestjs/platform-express': 10.4.7(@nestjs/common@10.4.7)(@nestjs/core@10.4.7)
'@nuxtjs/opencollective': 0.3.2
fast-safe-stringify: 2.0.7
iterare: 1.2.1
object-hash: 2.1.1
path-to-regexp: 3.2.0
reflect-metadata: 0.2.2
rxjs: 6.6.7
tslib: 2.2.0
uuid: 8.3.2
transitivePeerDependencies:
- encoding
dev: false
/@nestjs/event-emitter@2.1.1(@nestjs/common@10.4.7)(@nestjs/core@10.4.7):
resolution: {integrity: sha512-6L6fBOZTyfFlL7Ih/JDdqlCzZeCW0RjCX28wnzGyg/ncv5F/EOeT1dfopQr1loBRQ3LTgu8OWM7n4zLN4xigsg==}
peerDependencies:
@@ -7833,7 +7921,7 @@ packages:
nx: 19.0.7
semver: 7.6.2
tmp: 0.2.3
tslib: 2.6.2
tslib: 2.8.0
yargs-parser: 21.1.1
dev: true
@@ -12199,6 +12287,15 @@ packages:
resolution: {integrity: sha512-RI4LFAraGrimMTxXkediCMXGVLC6ksXIIo3U+d3E4n+Mhw3uIDbmokO7DHlPB/eu6Tn6KBv4IUE1WrrEDRdNUQ==}
dev: false
/@types/ioredis@5.0.0:
resolution: {integrity: sha512-zJbJ3FVE17CNl5KXzdeSPtdltc4tMT3TzC6fxQS0sQngkbFZ6h+0uTafsRqu+eSLIugf6Yb0Ea0SUuRr42Nk9g==}
deprecated: This is a stub types definition. ioredis provides its own type definitions, so you do not need this installed.
dependencies:
ioredis: 5.6.0
transitivePeerDependencies:
- supports-color
dev: false
/@types/istanbul-lib-coverage@2.0.6:
resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==}
@@ -12618,6 +12715,10 @@ packages:
resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==}
dev: true
/@types/uuid@10.0.0:
resolution: {integrity: sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==}
dev: false
/@types/validator@13.12.2:
resolution: {integrity: sha512-6SlHBzUW8Jhf3liqrGGXyTJSIFe4nqlJ5A5KaMZ2l/vbM3Wh3KSybots/wfWVzNLK4D1NZluDlSQIbIEPx6oyA==}
@@ -12746,7 +12847,7 @@ packages:
'@typescript-eslint/scope-manager': 5.62.0
'@typescript-eslint/type-utils': 5.62.0(eslint@8.57.0)(typescript@4.9.5)
'@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@4.9.5)
debug: 4.3.4
debug: 4.3.7(supports-color@5.5.0)
eslint: 8.57.0
graphemer: 1.4.0
ignore: 5.3.1
@@ -12867,7 +12968,7 @@ packages:
'@typescript-eslint/scope-manager': 5.62.0
'@typescript-eslint/types': 5.62.0
'@typescript-eslint/typescript-estree': 5.62.0(typescript@4.9.5)
debug: 4.3.4
debug: 4.3.7(supports-color@5.5.0)
eslint: 8.57.0
typescript: 4.9.5
transitivePeerDependencies:
@@ -12922,7 +13023,7 @@ packages:
dependencies:
'@typescript-eslint/typescript-estree': 5.62.0(typescript@3.9.10)
'@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@3.9.10)
debug: 4.3.4
debug: 4.3.7(supports-color@5.5.0)
eslint: 8.57.0
tsutils: 3.21.0(typescript@3.9.10)
typescript: 3.9.10
@@ -12942,7 +13043,7 @@ packages:
dependencies:
'@typescript-eslint/typescript-estree': 5.62.0(typescript@4.9.5)
'@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@4.9.5)
debug: 4.3.4
debug: 4.3.7(supports-color@5.5.0)
eslint: 8.57.0
tsutils: 3.21.0(typescript@4.9.5)
typescript: 4.9.5
@@ -13010,7 +13111,7 @@ packages:
dependencies:
'@typescript-eslint/types': 5.62.0
'@typescript-eslint/visitor-keys': 5.62.0
debug: 4.3.4
debug: 4.3.7(supports-color@5.5.0)
globby: 11.1.0
is-glob: 4.0.3
semver: 7.6.2
@@ -13031,7 +13132,7 @@ packages:
dependencies:
'@typescript-eslint/types': 5.62.0
'@typescript-eslint/visitor-keys': 5.62.0
debug: 4.3.4
debug: 4.3.7(supports-color@5.5.0)
globby: 11.1.0
is-glob: 4.0.3
semver: 7.6.2
@@ -13052,7 +13153,7 @@ packages:
dependencies:
'@typescript-eslint/types': 5.62.0
'@typescript-eslint/visitor-keys': 5.62.0
debug: 4.3.4
debug: 4.3.7(supports-color@5.5.0)
globby: 11.1.0
is-glob: 4.0.3
semver: 7.6.2
@@ -14487,6 +14588,14 @@ packages:
engines: {node: '>=4'}
dev: false
/axios@0.21.1:
resolution: {integrity: sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==}
dependencies:
follow-redirects: 1.15.6
transitivePeerDependencies:
- debug
dev: false
/axios@0.21.4:
resolution: {integrity: sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==}
dependencies:
@@ -15456,7 +15565,7 @@ packages:
dependencies:
cron-parser: 4.9.0
get-port: 5.1.1
ioredis: 5.4.1
ioredis: 5.6.0
lodash: 4.17.21
msgpackr: 1.11.2
semver: 7.6.2
@@ -15469,7 +15578,7 @@ packages:
resolution: {integrity: sha512-jxpa/DB02V20CqBAgyqpQazT630CJm0r4fky8EchH3mcJAomRtKXLS6tRA0J8tb29BDGlr/LXhlUuZwdBJBSdA==}
dependencies:
cron-parser: 4.9.0
ioredis: 5.4.1
ioredis: 5.6.0
msgpackr: 1.11.2
node-abort-controller: 3.1.1
semver: 7.6.2
@@ -18104,7 +18213,7 @@ packages:
base64id: 2.0.0
cookie: 0.4.2
cors: 2.8.5
debug: 4.3.4
debug: 4.3.7(supports-color@5.5.0)
engine.io-parser: 5.2.2
ws: 8.11.0
transitivePeerDependencies:
@@ -19555,7 +19664,7 @@ packages:
engines: {node: '>= 10.17.0'}
hasBin: true
dependencies:
debug: 4.3.1
debug: 4.3.7(supports-color@5.5.0)
get-stream: 5.2.0
yauzl: 2.10.0
optionalDependencies:
@@ -19634,6 +19743,10 @@ packages:
resolution: {integrity: sha512-8EZzEP0eKkEEVX+drtd9mtuQ+/QrlfW/5MlwcwK5Nds6EkZ/tRzEexkzUY2mIssnAyVLT+TKHuRXmFNNXYUd6g==}
dev: false
/fast-safe-stringify@2.0.7:
resolution: {integrity: sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==}
dev: false
/fast-safe-stringify@2.1.1:
resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==}
@@ -21538,7 +21651,7 @@ packages:
engines: {node: '>= 6'}
dependencies:
agent-base: 6.0.2
debug: 4.3.1
debug: 4.3.7(supports-color@5.5.0)
transitivePeerDependencies:
- supports-color
dev: false
@@ -21865,8 +21978,27 @@ packages:
engines: {node: '>=0.10.0'}
dev: false
/ioredis@5.4.1:
resolution: {integrity: sha512-2YZsvl7jopIa1gaePkeMtd9rAcSjOOjPtpcLlOeusyO+XH2SK5ZcT+UCrElPP+WVIInh2TzeI4XW9ENaSLVVHA==}
/ioredis@4.29.1:
resolution: {integrity: sha512-iq4u3AC9h9/P/gBXH1cUR7Ln0exKexqMaYDwUaoZJzkvvgJs9W5+CLQFS0APyG8uyvJJjn6q6Vx7LwmZQu3h5A==}
engines: {node: '>=6'}
dependencies:
'@ioredis/commands': 1.2.0
cluster-key-slot: 1.1.2
debug: 4.3.7(supports-color@5.5.0)
denque: 1.5.1
lodash.defaults: 4.2.0
lodash.flatten: 4.4.0
lodash.isarguments: 3.1.0
p-map: 2.1.0
redis-errors: 1.2.0
redis-parser: 3.0.0
standard-as-callback: 2.1.0
transitivePeerDependencies:
- supports-color
dev: false
/ioredis@5.6.0:
resolution: {integrity: sha512-tBZlIIWbndeWBWCXWZiqtOF/yxf6yZX3tAlTJ7nfo5jhd6dctNxF7QnYlZLZ1a0o0pDoen7CgZqO+zjNaFbJAg==}
engines: {node: '>=12.22.0'}
dependencies:
'@ioredis/commands': 1.2.0
@@ -22534,7 +22666,7 @@ packages:
resolution: {integrity: sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==}
engines: {node: '>=6'}
dependencies:
debug: 4.3.4
debug: 4.3.7(supports-color@5.5.0)
istanbul-lib-coverage: 2.0.5
make-dir: 2.1.0
rimraf: 2.7.1
@@ -24522,6 +24654,10 @@ packages:
resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==}
dev: false
/lodash.flatten@4.4.0:
resolution: {integrity: sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==}
dev: false
/lodash.flattendeep@4.4.0:
resolution: {integrity: sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==}
dev: true
@@ -25869,6 +26005,29 @@ packages:
string-format: 2.0.0
dev: false
/nestjs-redis@1.3.3(@nestjs/platform-express@10.4.7)(cache-manager@6.1.3)(class-transformer@0.5.1)(class-validator@0.14.1):
resolution: {integrity: sha512-YLvWtVKP38Uica7pL8T955jPi0MFmJ4+Wj3R/IHbLpsdCJkdA9wtfO9NoUpiZpM1aO1dEGcOBoStvgb0Uy7MGA==}
dependencies:
'@nestjs/common': 7.6.18(cache-manager@6.1.3)(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@6.6.7)
'@nestjs/core': 7.6.18(@nestjs/common@7.6.18)(@nestjs/platform-express@10.4.7)(reflect-metadata@0.2.2)(rxjs@6.6.7)
'@types/ioredis': 5.0.0
'@types/uuid': 10.0.0
ioredis: 4.29.1
reflect-metadata: 0.2.2
rxjs: 6.6.7
uuid: 8.3.2
transitivePeerDependencies:
- '@nestjs/microservices'
- '@nestjs/platform-express'
- '@nestjs/websockets'
- cache-manager
- class-transformer
- class-validator
- debug
- encoding
- supports-color
dev: false
/newrelic@11.17.0:
resolution: {integrity: sha512-gI5FGsfvHyGLUW/+q3op1SsF8jisW5wV+NVOoxV9J58GOEEsP1B4/9D5jyL3iiL5QO1REeWtK5n15d2OsiYAIg==}
engines: {node: '>=16', npm: '>=6.0.0'}
@@ -26407,7 +26566,7 @@ packages:
tar-stream: 2.2.0
tmp: 0.2.3
tsconfig-paths: 4.2.0
tslib: 2.6.2
tslib: 2.8.0
yargs: 17.7.2
yargs-parser: 21.1.1
optionalDependencies:
@@ -26502,6 +26661,11 @@ packages:
engines: {node: '>= 0.10.0'}
dev: true
/object-hash@2.1.1:
resolution: {integrity: sha512-VOJmgmS+7wvXf8CjbQmimtCnEx3IAoLxI3fp2fbWehxrWBcAQFbk+vcwb6vzR0VZv/eNCJ/27j151ZTwqW/JeQ==}
engines: {node: '>= 6'}
dev: false
/object-hash@2.2.0:
resolution: {integrity: sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==}
engines: {node: '>= 6'}
@@ -27292,6 +27456,10 @@ packages:
dependencies:
isarray: 0.0.1
/path-to-regexp@3.2.0:
resolution: {integrity: sha512-jczvQbCUS7XmS7o+y1aEO9OBVFeZBQ1MDSEqmO7xSoPgOPoowY/SxLpZ6Vh97/8qHZOteiCKb7gkG9gA2ZUxJA==}
dev: false
/path-to-regexp@3.3.0:
resolution: {integrity: sha512-qyCH421YQPS2WFDxDjftfc1ZR5WKQzVzqsp4n9M2kQhVOo/ByahFoUNJfl58kOcEGfQ//7weFTDhm+ss8Ecxgw==}
@@ -30944,6 +31112,13 @@ packages:
resolution: {integrity: sha512-cLgakCUf6PedEu15t8kbsjnwIFFR2D4RfL+W3iWFJ4iac7z4B0ZI8fxy4R3J956kAI68HclCFGL8MPoUVC3qVA==}
dev: false
/rxjs@6.6.7:
resolution: {integrity: sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==}
engines: {npm: '>=2.0.0'}
dependencies:
tslib: 1.14.1
dev: false
/rxjs@7.8.1:
resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==}
dependencies:
@@ -31587,7 +31762,7 @@ packages:
/socket.io-adapter@2.5.4:
resolution: {integrity: sha512-wDNHGXGewWAjQPt3pyeYBtpWSq9cLE5UW1ZUPL/2eGK9jtse/FpXib7epSTsz0Q0m+6sg6Y4KtcFTlah1bdOVg==}
dependencies:
debug: 4.3.4
debug: 4.3.7(supports-color@5.5.0)
ws: 8.11.0
transitivePeerDependencies:
- bufferutil
@@ -31614,7 +31789,7 @@ packages:
engines: {node: '>=10.0.0'}
dependencies:
'@socket.io/component-emitter': 3.1.2
debug: 4.3.4
debug: 4.3.7(supports-color@5.5.0)
transitivePeerDependencies:
- supports-color
dev: false
@@ -32449,7 +32624,7 @@ packages:
dependencies:
component-emitter: 1.3.1
cookiejar: 2.1.4
debug: 4.3.4
debug: 4.3.7(supports-color@5.5.0)
fast-safe-stringify: 2.1.1
form-data: 4.0.0
formidable: 2.1.2
@@ -33423,6 +33598,10 @@ packages:
/tslib@1.14.1:
resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==}
/tslib@2.2.0:
resolution: {integrity: sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==}
dev: false
/tslib@2.4.0:
resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==}
dev: false