fix: rename the module

This commit is contained in:
yassinedorbozgithub
2025-04-04 08:55:41 +01:00
parent cf350c1048
commit d73e4dc8cb
5 changed files with 1 additions and 1 deletions

View File

@@ -0,0 +1,110 @@
/*
* Copyright © 2025 Hexastack. All rights reserved.
*
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
* 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file).
*/
import { CACHE_MANAGER } from '@nestjs/cache-manager';
import { MongooseModule } from '@nestjs/mongoose';
import { AttachmentRepository } from '@/attachment/repositories/attachment.repository';
import { AttachmentModel } from '@/attachment/schemas/attachment.schema';
import { AttachmentService } from '@/attachment/services/attachment.service';
import { ChannelService } from '@/channel/channel.service';
import { SubscriberRepository } from '@/chat/repositories/subscriber.repository';
import { SubscriberModel } from '@/chat/schemas/subscriber.schema';
import { SubscriberService } from '@/chat/services/subscriber.service';
import LocalStorageHelper from '@/extensions/helpers/local-storage/index.helper';
import { HelperService } from '@/helper/helper.service';
import { LoggerService } from '@/logger/logger.service';
import { SettingRepository } from '@/setting/repositories/setting.repository';
import { Setting, SettingModel } from '@/setting/schemas/setting.schema';
import { SettingSeeder } from '@/setting/seeds/setting.seed';
import { SettingService } from '@/setting/services/setting.service';
import { installSettingFixtures } from '@/utils/test/fixtures/setting';
import {
closeInMongodConnection,
rootMongooseTestModule,
} from '@/utils/test/test';
import { buildTestingMocks } from '@/utils/test/utils';
import { CleanupService } from './cleanup.service';
import { TNamespace } from './types';
describe('CleanupService', () => {
let initialSettings: Setting[];
let helperService: HelperService;
let cleanupService: CleanupService;
let settingService: SettingService;
beforeAll(async () => {
const { getMocks, resolveMocks } = await buildTestingMocks({
imports: [
rootMongooseTestModule(installSettingFixtures),
MongooseModule.forFeature([
SettingModel,
SubscriberModel,
AttachmentModel,
]),
],
providers: [
CleanupService,
HelperService,
SettingService,
SettingRepository,
{
provide: CACHE_MANAGER,
useValue: {
del: jest.fn(),
get: jest.fn(),
set: jest.fn(),
},
},
SettingSeeder,
SubscriberService,
SubscriberRepository,
AttachmentService,
AttachmentRepository,
ChannelService,
],
});
[cleanupService, settingService, helperService] = await getMocks([
CleanupService,
SettingService,
HelperService,
,
]);
const [loggerService] = await resolveMocks([LoggerService]);
initialSettings = await settingService.findAll();
helperService.register(
new LocalStorageHelper(settingService, helperService, loggerService),
);
});
afterAll(closeInMongodConnection);
afterEach(jest.clearAllMocks);
describe('delete', () => {
it('should delete all the unregistered settings with a group suffix `_channel` or/and `_helper`', async () => {
const registeredNamespaces = [
...cleanupService.getChannelNamespaces(),
...cleanupService.getHelperNamespaces(),
];
await cleanupService.pruneExtensionSettings();
const cleanSettings = await settingService.findAll();
const filteredSettings = initialSettings.filter(
({ group }) =>
!/_(channel|helper)$/.test(group) !==
registeredNamespaces.includes(group as TNamespace),
);
expect(cleanSettings).toEqualPayload(filteredSettings);
});
});
});

View File

@@ -0,0 +1,64 @@
/*
* Copyright © 2025 Hexastack. All rights reserved.
*
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
* 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file).
*/
import { Injectable } from '@nestjs/common';
import { ChannelService } from '@/channel/channel.service';
import { HelperService } from '@/helper/helper.service';
import { LoggerService } from '@/logger/logger.service';
import { SettingService } from '@/setting/services/setting.service';
import { DeleteResult } from '@/utils/generics/base-repository';
import { TCriteria, TExtractExtension, TExtractNamespace } from './types';
@Injectable()
export class CleanupService {
constructor(
private readonly helperService: HelperService,
private readonly loggerService: LoggerService,
private readonly settingService: SettingService,
private readonly channelService: ChannelService,
) {}
private async deleteManyBySuffixAndNamespaces(
criteria: TCriteria[],
): Promise<DeleteResult> {
return await this.settingService.deleteMany({
$or: criteria.map(({ suffix, namespaces }) => ({
group: { $regex: suffix, $nin: namespaces },
})),
});
}
public getChannelNamespaces(): TExtractNamespace<'channel'>[] {
return this.channelService
.getAll()
.map((channel) => channel.getNamespace<TExtractExtension<'channel'>>());
}
public getHelperNamespaces(): TExtractNamespace<'helper'>[] {
return this.helperService
.getAll()
.map((helper) => helper.getNamespace<TExtractExtension<'helper'>>());
}
public async pruneExtensionSettings() {
const channels = this.getChannelNamespaces();
const helpers = this.getHelperNamespaces();
const { deletedCount } = await this.deleteManyBySuffixAndNamespaces([
{ suffix: '_channel', namespaces: channels },
{ suffix: '_helper', namespaces: helpers },
]);
if (deletedCount > 0) {
this.loggerService.log(
`${deletedCount} unused setting${deletedCount === 1 ? '' : 's'} ${deletedCount === 1 ? 'is' : 'are'} successfully deleted!`,
);
}
}
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright © 2025 Hexastack. All rights reserved.
*
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
* 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file).
*/
import { Global, Module, OnApplicationBootstrap } from '@nestjs/common';
import { LoggerService } from '@/logger/logger.service';
import { CleanupService } from './cleanup.service';
@Global()
@Module({
providers: [CleanupService],
exports: [CleanupService],
})
export class ExtensionModule implements OnApplicationBootstrap {
constructor(
private readonly loggerService: LoggerService,
private readonly cleanupService: CleanupService,
) {}
async onApplicationBootstrap() {
try {
await this.cleanupService.pruneExtensionSettings();
} catch (error) {
this.loggerService.error('Unable to delete unused settings', error);
}
}
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright © 2025 Hexastack. All rights reserved.
*
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
* 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file).
*/
import { ExtensionName } from '@/utils/types/extension';
type TExcludedExtension = 'plugin';
type TExcludeSuffix<
T,
S extends string = '_',
Suffix extends string = `${S}${TExcludedExtension}`,
> = T extends `${infer _Base}${Suffix}` ? never : T;
export type TExtensionName = TExcludeSuffix<ExtensionName, '-'>;
export type TExtension =
Extract<TExtensionName, `${string}-${string}`> extends `${string}-${infer S}`
? `${S}`
: never;
export type TNamespace = HyphenToUnderscore<TExtensionName>;
export type TExtractNamespace<
T extends TExtension = TExtension,
M extends TExtensionName = TExtensionName,
> = M extends `${string}${T}` ? HyphenToUnderscore<M> : never;
export type TExtractExtension<
T extends TExtension = TExtension,
M extends TExtensionName = TExtensionName,
> = M extends `${string}${T}` ? M : never;
export type TCriteria = {
suffix: `_${TExtension}`;
namespaces: TNamespace[];
};