Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
0720fbe
#RI-4186 BE poc for custom tutorials
Feb 20, 2023
c5726ba
#RI-4186 BE poc add uri + create manifest tree from existing tutirials
Feb 20, 2023
4a9e01a
#RI-4186 BE poc serve custom tutorials static files
Feb 20, 2023
cf695ea
#RI-4186 change uri calculation
Feb 20, 2023
72f4fa8
#RI-4186 BE delete custom tutorial
Feb 20, 2023
ed3c3d0
#RI-4186 BE move '/' from uri
Feb 20, 2023
2271bdf
#RI-4186 BE reworked poc
Feb 21, 2023
2afbf48
#RI-4186 BE fix schema
Feb 21, 2023
23da1b0
fix manifest generation issue
Feb 21, 2023
79f7302
#RI-4186 - add order by createdAt DESC + add manifest as response for…
Feb 21, 2023
0135980
#RI-4186 - UTests
Feb 21, 2023
8e6857f
#RI-4186 added migrations + file size validation (10MB max)
Feb 23, 2023
37bf272
#RI-4186 - initial fe implementation for custom tutorials
rsergeenko Feb 23, 2023
d4ef5b6
#RI-4186 - get parent label by manifest, add validation for tutorial …
rsergeenko Feb 23, 2023
e514b2e
#RI-4186 fix custom tutorials dir for different envs
Feb 23, 2023
ffba3ab
Merge branch 'be/feature/RI-4186-Upload_custom_tutorials' into fe/fea…
Feb 23, 2023
2fd0c3b
#RI-4186 - fix tests, additional functionality
rsergeenko Feb 27, 2023
1ad8fac
Merge pull request #1756 from RedisInsight/be/feature/RI-4186-Upload_…
Feb 27, 2023
f381d33
Merge pull request #1774 from RedisInsight/fe/feature/RI-4186-custom-…
rsergeenko Feb 27, 2023
857fa51
Merge branch 'main' into feature/RI-4186-Upload_custom_tutorials
rsergeenko Feb 27, 2023
09ef126
resolve conflicts
rsergeenko Feb 27, 2023
b0231aa
#RI-4231 BE move to array-based structure
Feb 27, 2023
9108b99
#RI-4234 [BE] Upload custom tutorials by link. Initial implementation
Feb 27, 2023
1c32a19
#RI-4198 [BE] Import markdown guides and tutorials without a .json ma…
Feb 27, 2023
70d2499
#RI-4231 - migrate to arrays
rsergeenko Feb 28, 2023
f91c046
#RI-4186 - add telemetry events, fix tests
rsergeenko Mar 1, 2023
75adfa0
fix label + fix _manifest.json path + change download links
Mar 2, 2023
1445b6f
update paths to guides and tutorials, fix tutorial upload
rsergeenko Mar 2, 2023
e61ad2d
Merge pull request #1783 from RedisInsight/be/feature/RI-4231-migrate…
Mar 2, 2023
84d504c
Merge pull request #1789 from RedisInsight/fe/feature/RI-4231_RI-4213…
rsergeenko Mar 2, 2023
35e726a
#RI-4260 - fix tutorials margins
rsergeenko Mar 3, 2023
6eb1bf4
#RI-4261 - close popover on second delete button click
rsergeenko Mar 3, 2023
c5f3d99
#RI-4186 - add unit tests for custom tutorials feature
rsergeenko Mar 3, 2023
ea25483
Merge pull request #1806 from RedisInsight/fe/bugfix/RI-4260
rsergeenko Mar 3, 2023
2cc0fba
Merge pull request #1807 from RedisInsight/fe/feature/RI-4186-Upload_…
rsergeenko Mar 3, 2023
ac43e56
do not extract __MACOSX folders
Mar 6, 2023
d2d1a0b
#RI-4186 UTests final
Mar 7, 2023
62dcc18
Add tests https://redislabs.atlassian.net/browse/RI-4186, https://red…
nmammadli Mar 7, 2023
3692570
Add comments and more checks
nmammadli Mar 7, 2023
27046df
#RI-4186 ITests
Mar 8, 2023
1722642
#RI-4186 fix UTests
Mar 8, 2023
eeeeae6
Merge pull request #1813 from RedisInsight/be/feature/RI-4186-Upload_…
Mar 8, 2023
0fd2df2
#RI-4175 cover telemetry events with ITests
Mar 8, 2023
692d051
Merge pull request #1817 from RedisInsight/e2e/feature/RI-4186-Upload…
nmammadli Mar 9, 2023
54892d3
#RI-4279 - add welcome screen for my tutorials
rsergeenko Mar 15, 2023
f0558e0
#RI-4279 - remove console.log
rsergeenko Mar 15, 2023
32faacd
#RI-4105 - highlight my tutorials
rsergeenko Mar 17, 2023
0b8d316
Merge branch 'main' into feature/RI-4186-Upload_custom_tutorials
rsergeenko Mar 17, 2023
12f3f0b
Merge pull request #1840 from RedisInsight/fe/feature/RI-4279_my-tuto…
nmammadli Mar 17, 2023
fee9dde
Merge pull request #1843 from RedisInsight/fe/feature/RI-4105_highlig…
nmammadli Mar 17, 2023
fe13194
change link
rsergeenko Mar 20, 2023
626d21a
#RI-4302 change tutorial structure + metadata + validation
Mar 21, 2023
8df79ca
#RI-4302 Analytics + UTests
Mar 21, 2023
5a0e8bc
#RI-4302 - update tutorials structure, update tests, remove name from…
rsergeenko Mar 21, 2023
e84caf6
#RI-4302 Itests
Mar 22, 2023
ba9e0ff
#RI-4308 wait for populating default data on startup
Mar 22, 2023
5b88498
#RI-4308 fix. function was not invoked
Mar 22, 2023
10ab008
Merge pull request #1853 from RedisInsight/be/feature/RI-4302-custom_…
Mar 22, 2023
87f5fce
Merge pull request #1854 from RedisInsight/fe/feature/RI-4302
Mar 22, 2023
d5fb515
Merge pull request #1822 from RedisInsight/be/feature/RI-telemetry_tests
Mar 22, 2023
c6f920e
Merge branch 'main' into feature/RI-4186-Upload_custom_tutorials
vlad-dargel Mar 22, 2023
b7d8b2d
Merge branch 'main' into feature/RI-4186-Upload_custom_tutorials
vlad-dargel Mar 22, 2023
1e9fe52
#RI-4321 throw BadRequest when unable to parse manifest.json
Mar 23, 2023
d7b7036
Merge pull request #1866 from RedisInsight/be/feature/RI-4312-incorre…
vlad-dargel Mar 23, 2023
4b22c21
Merge branch 'main' into feature/RI-4186-Upload_custom_tutorials
Mar 28, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions redisinsight/api/config/default.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export default {
logs: join(homedir, 'logs'),
defaultPlugins: join(staticDir, 'plugins'),
customPlugins: join(homedir, 'plugins'),
customTutorials: join(homedir, 'custom-tutorials'),
pluginsAssets: join(staticDir, 'resources', 'plugins'),
commands: join(homedir, 'commands'),
defaultCommandsDir: join(defaultsDir, 'commands'),
Expand All @@ -45,6 +46,7 @@ export default {
staticUri: '/static',
guidesUri: '/static/guides',
tutorialsUri: '/static/tutorials',
customTutorialsUri: '/static/custom-tutorials',
contentUri: '/static/content',
defaultPluginsUri: '/static/plugins',
pluginsAssetsUri: '/static/resources/plugins',
Expand Down Expand Up @@ -95,6 +97,7 @@ export default {
},
analytics: {
writeKey: process.env.SEGMENT_WRITE_KEY || 'SOURCE_WRITE_KEY',
flushInterval: parseInt(process.env.ANALYTICS_FLUSH_INTERVAL, 10) || 3000,
},
logger: {
logLevel: process.env.LOG_LEVEL || 'info', // log level
Expand All @@ -108,14 +111,14 @@ export default {
},
guides: {
updateUrl: process.env.GUIDES_UPDATE_URL
|| 'https://github.com/RedisInsight/Guides/releases/download/release',
|| 'https://github.com/RedisInsight/Guides/releases/download/2.x.x',
zip: process.env.GUIDES_ZIP || dataZipFileName,
buildInfo: process.env.GUIDES_CHECKSUM || buildInfoFileName,
devMode: !!process.env.GUIDES_DEV_PATH,
},
tutorials: {
updateUrl: process.env.TUTORIALS_UPDATE_URL
|| 'https://github.com/RedisInsight/Tutorials/releases/download/release',
|| 'https://github.com/RedisInsight/Tutorials/releases/download/2.x.x',
zip: process.env.TUTORIALS_ZIP || dataZipFileName,
buildInfo: process.env.TUTORIALS_CHECKSUM || buildInfoFileName,
devMode: !!process.env.TUTORIALS_DEV_PATH,
Expand Down
2 changes: 2 additions & 0 deletions redisinsight/api/config/ormconfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { ClientCertificateEntity } from 'src/modules/certificate/entities/client
import { DatabaseEntity } from 'src/modules/database/entities/database.entity';
import { SshOptionsEntity } from 'src/modules/ssh/entities/ssh-options.entity';
import { BrowserHistoryEntity } from 'src/modules/browser/entities/browser-history.entity';
import { CustomTutorialEntity } from 'src/modules/custom-tutorial/entities/custom-tutorial.entity';
import migrations from '../migration';
import * as config from '../src/utils/config';

Expand All @@ -35,6 +36,7 @@ const ormConfig = {
DatabaseAnalysisEntity,
BrowserHistoryEntity,
SshOptionsEntity,
CustomTutorialEntity,
],
migrations,
};
Expand Down
2 changes: 2 additions & 0 deletions redisinsight/api/config/production.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export default {
prevHomedir,
logs: join(homedir, 'logs'),
customPlugins: join(homedir, 'plugins'),
customTutorials: join(homedir, 'custom-tutorials'),
commands: join(homedir, 'commands'),
guides: process.env.GUIDES_DEV_PATH || join(homedir, 'guides'),
tutorials: process.env.TUTORIALS_DEV_PATH || join(homedir, 'tutorials'),
Expand All @@ -24,6 +25,7 @@ export default {
},
analytics: {
writeKey: process.env.SEGMENT_WRITE_KEY || 'lK5MNZgHbxj6vQwFgqZxygA0BiDQb32n',
flushInterval: parseInt(process.env.ANALYTICS_FLUSH_INTERVAL, 10) || 10000,
},
db: {
database: join(homedir, 'redisinsight.db'),
Expand Down
1 change: 1 addition & 0 deletions redisinsight/api/config/staging.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export default {
prevHomedir,
logs: join(homedir, 'logs'),
customPlugins: join(homedir, 'plugins'),
customTutorials: join(homedir, 'custom-tutorials'),
commands: join(homedir, 'commands'),
guides: process.env.GUIDES_DEV_PATH || join(homedir, 'guides'),
tutorials: process.env.TUTORIALS_DEV_PATH || join(homedir, 'tutorials'),
Expand Down
14 changes: 14 additions & 0 deletions redisinsight/api/migration/1677135091633-custom-tutorials.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { MigrationInterface, QueryRunner } from "typeorm";

export class customTutorials1677135091633 implements MigrationInterface {
name = 'customTutorials1677135091633'

public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`CREATE TABLE "custom_tutorials" ("id" varchar PRIMARY KEY NOT NULL, "name" varchar NOT NULL, "link" varchar, "createdAt" datetime NOT NULL DEFAULT (datetime('now')))`);
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`DROP TABLE "custom_tutorials"`);
}

}
2 changes: 2 additions & 0 deletions redisinsight/api/migration/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { browserHistory1674539211397 } from './1674539211397-browser-history';
import { databaseAnalysisRecommendations1674660306971 } from './1674660306971-database-analysis-recommendations';
import { databaseTimeout1675398140189 } from './1675398140189-database-timeout';
import { databaseCompressor1678182722874 } from './1678182722874-database-compressor';
import { customTutorials1677135091633 } from './1677135091633-custom-tutorials';

export default [
initialMigration1614164490968,
Expand Down Expand Up @@ -60,4 +61,5 @@ export default [
browserHistory1674539211397,
databaseTimeout1675398140189,
databaseCompressor1678182722874,
customTutorials1677135091633,
];
3 changes: 3 additions & 0 deletions redisinsight/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
"lodash": "^4.17.20",
"nest-router": "^1.0.9",
"nest-winston": "^1.4.0",
"nestjs-form-data": "^1.8.7",
"node-version-compare": "^1.0.3",
"reflect-metadata": "^0.1.13",
"rxjs": "^7.5.6",
Expand All @@ -83,6 +84,7 @@
"@nestjs/cli": "^9.1.2",
"@nestjs/schematics": "^9.0.3",
"@nestjs/testing": "^9.0.11",
"@types/adm-zip": "^0.5.0",
"@types/axios": "^0.14.0",
"@types/express": "^4.17.3",
"@types/jest": "^26.0.15",
Expand All @@ -108,6 +110,7 @@
"mocha": "^8.4.0",
"mocha-junit-reporter": "^2.0.0",
"mocha-multi-reporters": "^1.5.1",
"nock": "^13.3.0",
"nyc": "^15.1.0",
"object-diff": "^0.0.4",
"rimraf": "^3.0.2",
Expand Down
180 changes: 180 additions & 0 deletions redisinsight/api/src/__mocks__/custom-tutorial.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
import { CustomTutorial, CustomTutorialActions } from 'src/modules/custom-tutorial/models/custom-tutorial';
import { CustomTutorialEntity } from 'src/modules/custom-tutorial/entities/custom-tutorial.entity';
import { CustomTutorialManifestType } from 'src/modules/custom-tutorial/models/custom-tutorial.manifest';
import { MemoryStoredFile } from 'nestjs-form-data';
import { UploadCustomTutorialDto } from 'src/modules/custom-tutorial/dto/upload.custom-tutorial.dto';
import AdmZip from 'adm-zip';

export const mockCustomTutorialId = 'a77b23c1-7816-4ea4-b61f-d37795a0f805-ct-id';

export const mockCustomTutorialId2 = 'a77b23c1-7816-4ea4-b61f-d37795a0f805-ct-id-2';

export const mockCustomTutorialTmpPath = '/tmp/path';

export const mockCustomTutorialsHttpLink = 'https://somesime.com/archive.zip';

export const mockCustomTutorial = Object.assign(new CustomTutorial(), {
id: mockCustomTutorialId,
name: 'custom tutorial',
createdAt: new Date(),
});

export const mockCustomTutorialEntity = Object.assign(new CustomTutorialEntity(), {
...mockCustomTutorial,
});

export const mockCustomTutorial2 = Object.assign(new CustomTutorial(), {
id: mockCustomTutorialId2,
name: 'custom tutorial 2',
link: mockCustomTutorialsHttpLink,
createdAt: new Date(),
});

export const mockCustomTutorialZipFile = Object.assign(new MemoryStoredFile(), {
size: 100,
buffer: Buffer.from('zip-content', 'utf8'),
});

export const mockCustomTutorialZipFileAxiosResponse = {
data: mockCustomTutorialZipFile.buffer,
};

export const mockCustomTutorialAdmZipEntry = {
entryName: 'somefolder/info.md',
} as AdmZip.IZipEntry;

export const mockCustomTutorialMacosxAdmZipEntry = {
entryName: '__MACOSX/info.md',
} as AdmZip.IZipEntry;

export const mockUploadCustomTutorialDto = Object.assign(new UploadCustomTutorialDto(), {
file: mockCustomTutorialZipFile,
});

export const mockUploadCustomTutorialExternalLinkDto = Object.assign(new UploadCustomTutorialDto(), {
link: mockCustomTutorialsHttpLink,
});

export const mockCustomTutorialManifestJson = {
type: CustomTutorialManifestType.Group,
id: mockCustomTutorialId,
label: mockCustomTutorial.name,
children: [
{
type: 'group',
id: 'ct-folder-1',
label: 'ct-folder-1',
children: [
{
type: CustomTutorialManifestType.Group,
id: 'ct-sub-folder-1',
label: 'ct-sub-folder-1',
children: [
{
type: CustomTutorialManifestType.InternalLink,
id: 'introduction',
label: 'introduction',
args: {
path: '/ct-folder-1/ct-sub-folder-1/introduction.md',
},
},
{
type: CustomTutorialManifestType.InternalLink,
id: 'working-with-hashes',
label: 'working-with-hashes',
args: {
path: '/ct-folder-1/ct-sub-folder-1/working-with-hashes.md',
},
},
],
},
{
type: CustomTutorialManifestType.Group,
id: 'ct-sub-folder-2',
label: 'ct-sub-folder-2',
children: [
{
type: CustomTutorialManifestType.InternalLink,
id: 'introduction',
label: 'introduction',
args: {
path: '/ct-folder-1/ct-sub-folder-2/introduction.md',
},
},
{
type: CustomTutorialManifestType.InternalLink,
id: 'working-with-graphs',
label: 'working-with-graphs',
args: {
path: '/ct-folder-1/ct-sub-folder-2/working-with-graphs.md',
},
},
],
},
],
},
],
};

export const mockCustomTutorialManifest = {
...mockCustomTutorialManifestJson,
type: CustomTutorialManifestType.Group,
id: mockCustomTutorialId,
label: mockCustomTutorial.name,
_actions: mockCustomTutorial.actions,
_path: mockCustomTutorial.path,
};

export const mockCustomTutorialManifest2 = {
type: CustomTutorialManifestType.Group,
id: mockCustomTutorialId2,
label: mockCustomTutorial2.name,
_actions: mockCustomTutorial2.actions,
_path: mockCustomTutorial2.path,
children: [mockCustomTutorialManifestJson],
};

export const globalCustomTutorialManifest = {
type: CustomTutorialManifestType.Group,
id: 'custom-tutorials',
label: 'MY TUTORIALS',
_actions: [CustomTutorialActions.CREATE],
args: {
withBorder: true,
initialIsOpen: true,
},
children: [
mockCustomTutorialManifest,
mockCustomTutorialManifest2,
],
};

export const mockCustomTutorialFsProvider = jest.fn(() => ({
unzipFromMemoryStoredFile: jest.fn().mockResolvedValue(mockCustomTutorialTmpPath),
unzipFromExternalLink: jest.fn().mockResolvedValue(mockCustomTutorialTmpPath),
unzipToTmpFolder: jest.fn().mockResolvedValue(mockCustomTutorialTmpPath),
moveFolder: jest.fn(),
removeFolder: jest.fn(),
}));

export const mockCustomTutorialManifestProvider = jest.fn(() => ({
getOriginalManifestJson: jest.fn().mockResolvedValue(mockCustomTutorialManifestJson),
getManifestJson: jest.fn().mockResolvedValue(mockCustomTutorialManifestJson),
generateTutorialManifest: jest.fn().mockResolvedValue(mockCustomTutorialManifest),
isOriginalManifestExists: jest.fn().mockResolvedValue(true),
}));

export const mockCustomTutorialRepository = jest.fn(() => ({
get: jest.fn().mockResolvedValue(mockCustomTutorial),
create: jest.fn().mockResolvedValue(mockCustomTutorial),
delete: jest.fn(),
list: jest.fn().mockResolvedValue([
mockCustomTutorial,
mockCustomTutorial2,
]),
}));

export const mockCustomTutorialAnalytics = jest.fn(() => ({
sendImportSucceeded: jest.fn(),
sendImportFailed: jest.fn(),
}));
1 change: 1 addition & 0 deletions redisinsight/api/src/__mocks__/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export * from './analytics';
export * from './profiler';
export * from './user';
export * from './databases';
export * from './custom-tutorial';
export * from './autodiscovery';
export * from './redis';
export * from './server';
Expand Down
2 changes: 2 additions & 0 deletions redisinsight/api/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { CoreModule } from 'src/core.module';
import { AutodiscoveryModule } from 'src/modules/autodiscovery/autodiscovery.module';
import { DatabaseImportModule } from 'src/modules/database-import/database-import.module';
import { DummyAuthMiddleware } from 'src/common/middlewares/dummy-auth.middleware';
import { CustomTutorialModule } from 'src/modules/custom-tutorial/custom-tutorial.module';
import { BrowserModule } from './modules/browser/browser.module';
import { RedisEnterpriseModule } from './modules/redis-enterprise/redis-enterprise.module';
import { RedisSentinelModule } from './modules/redis-sentinel/redis-sentinel.module';
Expand Down Expand Up @@ -53,6 +54,7 @@ const PATH_CONFIG = config.get('dir_path');
NotificationModule,
BulkActionsModule,
ClusterMonitorModule,
CustomTutorialModule.register(),
DatabaseAnalysisModule,
DatabaseImportModule,
...(SERVER_CONFIG.staticContent
Expand Down
9 changes: 9 additions & 0 deletions redisinsight/api/src/common/utils/errors.util.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { HttpException, InternalServerErrorException } from '@nestjs/common';

export const wrapHttpError = (error: Error, message?: string) => {
if (error instanceof HttpException) {
return error;
}

return new InternalServerErrorException(error.message || message);
};
1 change: 1 addition & 0 deletions redisinsight/api/src/common/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './certificate-import.util';
export * from './errors.util';
2 changes: 2 additions & 0 deletions redisinsight/api/src/constants/error-messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ export default {
PROFILER_LOG_FILE_NOT_FOUND: 'Profiler log file was not found.',
CONSUMER_GROUP_NOT_FOUND: 'Consumer Group with such name was not found.',
PLUGIN_STATE_NOT_FOUND: 'Plugin state was not found.',
CUSTOM_TUTORIAL_NOT_FOUND: 'Custom Tutorial was not found.',
CUSTOM_TUTORIAL_UNABLE_TO_FETCH_FROM_EXTERNAL: 'Unable fetch zip file from external source.',
UNDEFINED_INSTANCE_ID: 'Undefined redis database instance id.',
NO_CONNECTION_TO_REDIS_DB: 'No connection to the Redis Database.',
WRONG_DATABASE_TYPE: 'Wrong database type.',
Expand Down
3 changes: 3 additions & 0 deletions redisinsight/api/src/constants/telemetry-events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ export enum TelemetryEvents {
WorkbenchCommandExecuted = 'WORKBENCH_COMMAND_EXECUTED',
WorkbenchCommandErrorReceived = 'WORKBENCH_COMMAND_ERROR_RECEIVED',
WorkbenchCommandDeleted = 'WORKBENCH_COMMAND_DELETE_COMMAND',
// Custom tutorials
WorkbenchEnablementAreaImportSucceeded = 'WORKBENCH_ENABLEMENT_AREA_IMPORT_SUCCEEDED',
WorkbenchEnablementAreaImportFailed = 'WORKBENCH_ENABLEMENT_AREA_IMPORT_FAILED',

// Profiler
ProfilerLogDownloaded = 'PROFILER_LOG_DOWNLOADED',
Expand Down
3 changes: 3 additions & 0 deletions redisinsight/api/src/core.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { EventEmitterModule } from '@nestjs/event-emitter';
import { RedisModule } from 'src/modules/redis/redis.module';
import { AnalyticsModule } from 'src/modules/analytics/analytics.module';
import { SshModule } from 'src/modules/ssh/ssh.module';
import { NestjsFormDataModule } from 'nestjs-form-data';

@Global()
@Module({
Expand All @@ -19,6 +20,7 @@ import { SshModule } from 'src/modules/ssh/ssh.module';
DatabaseModule.register(),
RedisModule,
SshModule,
NestjsFormDataModule,
],
exports: [
EncryptionModule,
Expand All @@ -27,6 +29,7 @@ import { SshModule } from 'src/modules/ssh/ssh.module';
DatabaseModule,
RedisModule,
SshModule,
NestjsFormDataModule,
],
})
export class CoreModule {}
Loading