@ask-ell/back-end 0.1.1 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/jest.config.ts +0 -1
  3. package/package.json +4 -2
  4. package/project.json +4 -7
  5. package/src/http/index.ts +1 -0
  6. package/src/http/types.ts +4 -0
  7. package/src/index.ts +2 -2
  8. package/src/keyv.store.adapter.factory.ts +31 -25
  9. package/src/nest/add-ons/add-on.interface.ts +5 -0
  10. package/src/nest/add-ons/add-on.wrapper.ts +31 -0
  11. package/src/{add-ons → nest/add-ons}/implementations/security/security.add-on.ts +3 -4
  12. package/src/nest/add-ons/implementations/sentry/sentry.add-on.interface.ts +8 -0
  13. package/src/{add-ons → nest/add-ons}/implementations/sentry/sentry.add-on.state.interface.ts +1 -1
  14. package/src/{add-ons → nest/add-ons}/implementations/sentry/sentry.add-on.ts +8 -9
  15. package/src/nest/add-ons/implementations/swagger/swagger.add-on.interface.ts +8 -0
  16. package/src/{add-ons → nest/add-ons}/implementations/swagger/swagger.add-on.state.interface.ts +3 -2
  17. package/src/nest/add-ons/implementations/swagger/swagger.add-on.ts +59 -0
  18. package/src/nest/add-ons/implementations/swagger/types.ts +1 -0
  19. package/src/nest/add-ons/index.ts +6 -0
  20. package/src/nest/add-ons/types.ts +7 -0
  21. package/src/nest/application.base.ts +18 -0
  22. package/src/nest/application.factory.ts +23 -0
  23. package/src/nest/filters/http.exception.filter.ts +23 -0
  24. package/src/nest/filters/index.ts +1 -0
  25. package/src/nest/index.ts +6 -0
  26. package/src/nest/interceptors/error.interceptor.ts +25 -0
  27. package/src/nest/interceptors/index.ts +2 -0
  28. package/src/nest/interceptors/response.format.interceptor.ts +29 -0
  29. package/src/nest/modules/health/health.module.ts +20 -0
  30. package/src/nest/modules/health/index.ts +1 -0
  31. package/src/nest/modules/health/middlewares/index.ts +1 -0
  32. package/src/nest/modules/health/middlewares/ping.middleware.ts +9 -0
  33. package/src/nest/modules/index.ts +2 -0
  34. package/src/nest/modules/requirement/index.ts +1 -0
  35. package/src/nest/modules/requirement/requirement.module.ts +56 -0
  36. package/src/scripts/move-keyv-data.script.ts +69 -48
  37. package/src/scripts/update-dependencies-versions.script.ts +164 -130
  38. package/src/secrets/docker.secret.getter.ts +6 -5
  39. package/src/secrets/file.secret.getter.ts +19 -16
  40. package/src/secrets/index.ts +2 -2
  41. package/src/secrets/local.secret.getter.ts +6 -5
  42. package/src/tmp.ts +15 -0
  43. package/src/add-ons/add-on.interface.ts +0 -5
  44. package/src/add-ons/add-on.wrapper.ts +0 -36
  45. package/src/add-ons/implementations/sentry/sentry.add-on.interface.ts +0 -8
  46. package/src/add-ons/implementations/swagger/swagger.add-on.interface.ts +0 -7
  47. package/src/add-ons/implementations/swagger/swagger.add-on.ts +0 -43
  48. package/src/add-ons/implementations/swagger/types.ts +0 -1
  49. package/src/add-ons/index.ts +0 -1
  50. package/src/add-ons/types.ts +0 -7
  51. package/src/application.base.ts +0 -15
  52. package/src/requirement.module.ts +0 -57
  53. package/src/utils/index.ts +0 -1
  54. package/src/utils/tmp.ts +0 -16
package/CHANGELOG.md ADDED
@@ -0,0 +1,11 @@
1
+ # @ask-ell/back-end
2
+
3
+ ## 0.2.3
4
+
5
+ ### Patch Changes
6
+
7
+ - [`473e25b`](https://github.com/ask-ell/stacks/commit/473e25b399b8ac336dabb5f8c9fda3b1428cabb6) Thanks [@timbitwin](https://github.com/timbitwin)! - Exported `CreateKeyvStoreAdapterOptions`, `ErrorInterceptorProps`, `NestApplicationFactoryParams`, and the `update-dependencies-versions` script types so they resolve correctly in generated documentation. Also wired up the `http`, `add-ons`, `filters`, `interceptors`, and `modules` barrels that were left disconnected from the package entry point after the last refactor, so the public API is fully reachable and documented from `index.ts`.
8
+ - Updated dependencies [[`473e25b`](https://github.com/ask-ell/stacks/commit/473e25b399b8ac336dabb5f8c9fda3b1428cabb6), [`473e25b`](https://github.com/ask-ell/stacks/commit/473e25b399b8ac336dabb5f8c9fda3b1428cabb6), [`473e25b`](https://github.com/ask-ell/stacks/commit/473e25b399b8ac336dabb5f8c9fda3b1428cabb6)]:
9
+ - @ask-ell/core@1.3.6
10
+ - @ask-ell/nest@0.0.15
11
+ - @ask-ell/node@0.0.5
package/jest.config.ts CHANGED
@@ -1,4 +1,3 @@
1
-
2
1
  import { readFileSync } from 'fs';
3
2
 
4
3
  // Reading the SWC compilation config for the spec files
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ask-ell/back-end",
3
- "version": "0.1.1",
3
+ "version": "0.2.3",
4
4
  "private": false,
5
5
  "type": "commonjs",
6
6
  "main": "./src/index.js",
@@ -17,9 +17,11 @@
17
17
  "@nestjs/swagger": "*",
18
18
  "@nestjs/throttler": "*",
19
19
  "@sentry/nestjs": "*",
20
+ "express": "*",
20
21
  "helmet": "*",
21
22
  "keyv": "*",
22
23
  "pg": "*",
23
- "tslib": "*"
24
+ "tslib": "*",
25
+ "rxjs": "*"
24
26
  }
25
27
  }
package/project.json CHANGED
@@ -8,22 +8,19 @@
8
8
  "build": {
9
9
  "executor": "@nx/js:tsc",
10
10
  "dependsOn": ["^build"],
11
- "outputs": [
12
- "{options.outputPath}"
13
- ],
11
+ "outputs": ["{options.outputPath}"],
14
12
  "options": {
15
13
  "outputPath": "dist/packages/back-end",
16
14
  "main": "packages/back-end/src/index.ts",
17
15
  "tsConfig": "packages/back-end/tsconfig.lib.json",
18
- "assets": [
19
- "packages/back-end/*.md"
20
- ]
16
+ "assets": ["packages/back-end/*.md"]
21
17
  }
22
18
  },
23
19
  "test": {
24
20
  "options": {
25
21
  "passWithNoTests": true
26
22
  }
27
- }
23
+ },
24
+ "format": {}
28
25
  }
29
26
  }
@@ -0,0 +1 @@
1
+ export * from './types';
@@ -0,0 +1,4 @@
1
+ export type HttpResponseBody<Data = unknown> = {
2
+ message: string;
3
+ data?: Data;
4
+ };
package/src/index.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @module @ask-ell/back-end
3
3
  */
4
- export * from './add-ons';
5
4
  export * from './scripts';
5
+ export * from './http';
6
+ export * from './nest';
6
7
  export * from './keyv.store.adapter.factory';
7
- export * from "./application.base";
@@ -1,37 +1,43 @@
1
- import { Injectable } from "@nestjs/common";
2
- import { KeyvStoreAdapter } from "keyv";
1
+ import { Injectable } from '@nestjs/common';
2
+ import { KeyvStoreAdapter } from 'keyv';
3
3
  import KeyvSqlite from '@keyv/sqlite';
4
4
  import KeyvPostgres from '@keyv/postgres';
5
- import { ILogger, MaybeUndefined } from "@ask-ell/core";
5
+ import { ILogger, MaybeUndefined } from '@ask-ell/core';
6
6
  import { NestLogger } from '@ask-ell/nest';
7
- import { join } from "node:path";
7
+ import { join } from 'node:path';
8
8
 
9
- import { createTmpFolder, TMP_FOLDER_PATH } from "./utils";
9
+ import { createTmpFolder, TMP_FOLDER_PATH } from './tmp';
10
10
 
11
-
12
- type CreateKeyvStoreAdapterOptions = {
13
- postgresUri: MaybeUndefined<string>;
14
- }
11
+ export type CreateKeyvStoreAdapterOptions = {
12
+ postgresUri: MaybeUndefined<string>;
13
+ };
15
14
 
16
15
  @Injectable()
17
16
  export class KeyvStoreAdapterFactory {
18
- private logger: ILogger = NestLogger.fromClass(KeyvStoreAdapterFactory);
17
+ private logger: ILogger = NestLogger.fromClass(KeyvStoreAdapterFactory);
19
18
 
20
- create(options: CreateKeyvStoreAdapterOptions): KeyvStoreAdapter {
21
- const adapter: KeyvStoreAdapter = this.getKeyvStoreAdapter(options);
22
- this.logger.log(`Connected to database with adapter "${adapter.constructor.name}"`);
23
- return adapter;
24
- }
19
+ create(options: CreateKeyvStoreAdapterOptions): KeyvStoreAdapter {
20
+ const adapter: KeyvStoreAdapter = this.getKeyvStoreAdapter(options);
21
+ this.logger.log(
22
+ `Connected to database with adapter "${adapter.constructor.name}"`
23
+ );
24
+ return adapter;
25
+ }
25
26
 
26
- private getKeyvStoreAdapter({ postgresUri }: CreateKeyvStoreAdapterOptions): KeyvStoreAdapter {
27
- if (!postgresUri) {
28
- createTmpFolder(this.logger);
29
- const localDatabaseFilePath: string = join(TMP_FOLDER_PATH, 'database.sqlite');
30
- return new KeyvSqlite(localDatabaseFilePath);
31
- }
32
-
33
- return new KeyvPostgres({
34
- uri: postgresUri,
35
- });
27
+ private getKeyvStoreAdapter({
28
+ postgresUri,
29
+ }: CreateKeyvStoreAdapterOptions): KeyvStoreAdapter {
30
+ if (!postgresUri) {
31
+ createTmpFolder(this.logger);
32
+ const localDatabaseFilePath: string = join(
33
+ TMP_FOLDER_PATH,
34
+ 'database.sqlite'
35
+ );
36
+ return new KeyvSqlite(localDatabaseFilePath);
36
37
  }
38
+
39
+ return new KeyvPostgres({
40
+ uri: postgresUri,
41
+ });
42
+ }
37
43
  }
@@ -0,0 +1,5 @@
1
+ import { INestApplication } from '@nestjs/common';
2
+
3
+ export interface IAddOn<T> {
4
+ apply(application: INestApplication<T>): void;
5
+ }
@@ -0,0 +1,31 @@
1
+ import { INestApplication } from '@nestjs/common';
2
+
3
+ import { IAddOn } from './add-on.interface';
4
+ import { SecurityAddOn } from './implementations/security/security.add-on';
5
+ import { AddOnWrapperParams } from './types';
6
+ import { SwaggerAddon } from './implementations/swagger/swagger.add-on';
7
+ import { SentryAddon } from './implementations/sentry/sentry.add-on';
8
+
9
+ export class AddOnWrapper<T> implements IAddOn<T> {
10
+ private implementations: IAddOn<T>[] = [new SecurityAddOn()];
11
+
12
+ constructor(private params: AddOnWrapperParams) {
13
+ this.appendImplementations();
14
+ }
15
+
16
+ apply(application: INestApplication<T>): void {
17
+ this.implementations.forEach((addOn: IAddOn<T>): void => {
18
+ addOn.apply(application);
19
+ });
20
+ }
21
+
22
+ private appendImplementations(): void {
23
+ const { sentry, swagger } = this.params;
24
+ if (swagger) {
25
+ this.implementations.push(new SwaggerAddon(swagger));
26
+ }
27
+ if (sentry) {
28
+ this.implementations.push(new SentryAddon(sentry));
29
+ }
30
+ }
31
+ }
@@ -1,8 +1,7 @@
1
- import { INestApplication, ValidationPipe } from "@nestjs/common";
1
+ import { INestApplication, ValidationPipe } from '@nestjs/common';
2
2
  import helmet from 'helmet';
3
3
 
4
- import { IAddOn } from "../../add-on.interface";
5
-
4
+ import { IAddOn } from '../../add-on.interface';
6
5
 
7
6
  export class SecurityAddOn<T> implements IAddOn<T> {
8
7
  apply(application: INestApplication<T>): void {
@@ -11,7 +10,7 @@ export class SecurityAddOn<T> implements IAddOn<T> {
11
10
  application.useGlobalPipes(
12
11
  new ValidationPipe({
13
12
  transform: true,
14
- whitelist: false
13
+ whitelist: false,
15
14
  })
16
15
  );
17
16
  }
@@ -0,0 +1,8 @@
1
+ import { IEntity } from '@ask-ell/core';
2
+
3
+ import { ISentryAddOnState } from './sentry.add-on.state.interface';
4
+ import { IAddOn } from '../../add-on.interface';
5
+
6
+ export interface ISentryAddOn<T>
7
+ extends IEntity<ISentryAddOnState>,
8
+ IAddOn<T> {}
@@ -2,4 +2,4 @@ export interface ISentryAddOnState {
2
2
  publicKey: string;
3
3
  host: string;
4
4
  projectId: string;
5
- }
5
+ }
@@ -1,9 +1,8 @@
1
- import { Entity, type IResult, ok } from "@ask-ell/core";
2
- import { NestSentryConfiguration } from "@ask-ell/nest"
3
-
4
- import { ISentryAddOnState } from "./sentry.add-on.state.interface";
5
- import { ISentryAddOn } from "./sentry.add-on.interface";
1
+ import { Entity, type IResult, ok } from '@ask-ell/core';
2
+ import { NestSentryConfiguration } from '@ask-ell/nest';
6
3
 
4
+ import { ISentryAddOnState } from './sentry.add-on.state.interface';
5
+ import { ISentryAddOn } from './sentry.add-on.interface';
7
6
 
8
7
  export class SentryAddon<T>
9
8
  extends Entity<ISentryAddOnState>
@@ -17,9 +16,9 @@ export class SentryAddon<T>
17
16
  const { host, projectId, publicKey } = this.getSnapshot();
18
17
 
19
18
  new NestSentryConfiguration({
20
- publicKey,
21
- host,
22
- projectId
19
+ publicKey,
20
+ host,
21
+ projectId,
23
22
  }).init();
24
23
  }
25
- }
24
+ }
@@ -0,0 +1,8 @@
1
+ import { IEntity } from '@ask-ell/core';
2
+
3
+ import { ISwaggerAddOnState } from './swagger.add-on.state.interface';
4
+ import { IAddOn } from '../../add-on.interface';
5
+
6
+ export interface ISwaggerAddOn<T>
7
+ extends IEntity<ISwaggerAddOnState>,
8
+ IAddOn<T> {}
@@ -1,6 +1,7 @@
1
- import { AuthMethod } from "./types";
1
+ import { AuthMethod } from './types';
2
2
 
3
3
  export interface ISwaggerAddOnState {
4
4
  title: string;
5
5
  auths?: AuthMethod[];
6
- }
6
+ enabledInProduction?: boolean;
7
+ }
@@ -0,0 +1,59 @@
1
+ import {
2
+ Entity,
3
+ ILogger,
4
+ type IResult,
5
+ isOnDevelopmentMode,
6
+ ok,
7
+ } from '@ask-ell/core';
8
+ import { NestLogger } from '@ask-ell/nest';
9
+ import { type INestApplication } from '@nestjs/common';
10
+ import {
11
+ DocumentBuilder,
12
+ type OpenAPIObject,
13
+ SwaggerModule,
14
+ } from '@nestjs/swagger';
15
+
16
+ import { ISwaggerAddOnState } from './swagger.add-on.state.interface';
17
+ import { ISwaggerAddOn } from './swagger.add-on.interface';
18
+ import { AuthMethod } from './types';
19
+
20
+ export class SwaggerAddon<T>
21
+ extends Entity<ISwaggerAddOnState>
22
+ implements ISwaggerAddOn<T>
23
+ {
24
+ private logger: ILogger = NestLogger.fromClass(SwaggerAddon);
25
+
26
+ checkStateValidity(): IResult<void> {
27
+ return ok();
28
+ }
29
+
30
+ apply(application: INestApplication<T>): void {
31
+ const { title, auths, enabledInProduction } = this.getSnapshot();
32
+
33
+ if (!enabledInProduction && !isOnDevelopmentMode()) {
34
+ return;
35
+ }
36
+
37
+ const documentBuilder: DocumentBuilder = new DocumentBuilder().setTitle(
38
+ title
39
+ );
40
+
41
+ auths?.forEach((auth: AuthMethod): void => {
42
+ if (auth === 'bearer') {
43
+ documentBuilder.addBearerAuth();
44
+ }
45
+ });
46
+
47
+ const documentBuild: Omit<OpenAPIObject, 'paths'> = documentBuilder.build();
48
+
49
+ const documentFactory = (): OpenAPIObject =>
50
+ SwaggerModule.createDocument(application, documentBuild);
51
+
52
+ SwaggerModule.setup('/swagger', application, documentFactory, {
53
+ customSiteTitle: title,
54
+ jsonDocumentUrl: '/swagger/json',
55
+ });
56
+
57
+ this.logger.log('Swagger initialized');
58
+ }
59
+ }
@@ -0,0 +1 @@
1
+ export type AuthMethod = 'bearer' | 'cookie';
@@ -0,0 +1,6 @@
1
+ export * from './add-on.interface';
2
+ export * from './add-on.wrapper';
3
+ export * from './types';
4
+ export * from './implementations/sentry/sentry.add-on.state.interface';
5
+ export * from './implementations/swagger/swagger.add-on.state.interface';
6
+ export * from './implementations/swagger/types';
@@ -0,0 +1,7 @@
1
+ import { ISentryAddOnState } from './implementations/sentry/sentry.add-on.state.interface';
2
+ import { ISwaggerAddOnState } from './implementations/swagger/swagger.add-on.state.interface';
3
+
4
+ export type AddOnWrapperParams = Partial<{
5
+ swagger: ISwaggerAddOnState;
6
+ sentry: ISentryAddOnState;
7
+ }>;
@@ -0,0 +1,18 @@
1
+ import { DynamicModule, Provider, Module, Global } from '@nestjs/common';
2
+
3
+ import { RequirementModule } from './modules';
4
+
5
+ @Global()
6
+ @Module({
7
+ imports: [RequirementModule],
8
+ })
9
+ export class ApplicationBase {
10
+ static withProviders(providers: Provider[]): DynamicModule {
11
+ const providersAndExports: Provider[] = [...providers];
12
+ return {
13
+ module: this,
14
+ providers: providersAndExports,
15
+ exports: [...providersAndExports],
16
+ };
17
+ }
18
+ }
@@ -0,0 +1,23 @@
1
+ import { ConsoleLogger, DynamicModule, INestApplication } from '@nestjs/common';
2
+ import { NestFactory } from '@nestjs/core';
3
+ import { IServerProvider } from '@ask-ell/node';
4
+
5
+ import { AddOnWrapper, AddOnWrapperParams } from './add-ons';
6
+
7
+ export type NestApplicationFactoryParams = {
8
+ addons: AddOnWrapperParams;
9
+ module: DynamicModule;
10
+ };
11
+
12
+ export async function createNestApplication({
13
+ module,
14
+ addons: addonsParams,
15
+ }: NestApplicationFactoryParams): Promise<IServerProvider> {
16
+ const application: INestApplication = await NestFactory.create(module, {
17
+ logger: new ConsoleLogger({
18
+ json: true,
19
+ }),
20
+ });
21
+ new AddOnWrapper(addonsParams).apply(application);
22
+ return application;
23
+ }
@@ -0,0 +1,23 @@
1
+ import {
2
+ type ExceptionFilter,
3
+ type ArgumentsHost,
4
+ Catch,
5
+ HttpException,
6
+ } from '@nestjs/common';
7
+ import type { HttpArgumentsHost } from '@nestjs/common/interfaces';
8
+ import type { Response } from 'express';
9
+
10
+ import type { HttpResponseBody } from '../../http';
11
+
12
+ @Catch(HttpException)
13
+ export class HttpExceptionFilter implements ExceptionFilter {
14
+ catch(exception: HttpException, host: ArgumentsHost): void {
15
+ const context: HttpArgumentsHost = host.switchToHttp();
16
+ const response: Response = context.getResponse<Response>();
17
+ const status: number = exception.getStatus();
18
+ const responseData: HttpResponseBody = {
19
+ message: exception.message,
20
+ };
21
+ response.status(status).json(responseData);
22
+ }
23
+ }
@@ -0,0 +1 @@
1
+ export * from './http.exception.filter';
@@ -0,0 +1,6 @@
1
+ export * from './add-ons';
2
+ export * from './application.base';
3
+ export * from './application.factory';
4
+ export * from './filters';
5
+ export * from './interceptors';
6
+ export * from './modules';
@@ -0,0 +1,25 @@
1
+ import { Entity, IResult, ok } from '@ask-ell/core';
2
+ import { CallHandler, ExecutionContext, NestInterceptor } from '@nestjs/common';
3
+ import { catchError, Observable, throwError } from 'rxjs';
4
+
5
+ export type ErrorInterceptorProps = {
6
+ errorConvertor: (error: unknown) => unknown;
7
+ };
8
+
9
+ export class ErrorInterceptor
10
+ extends Entity<ErrorInterceptorProps>
11
+ implements NestInterceptor
12
+ {
13
+ override checkStateValidity(): IResult {
14
+ return ok();
15
+ }
16
+
17
+ intercept(_: ExecutionContext, next: CallHandler): Observable<unknown> {
18
+ const { errorConvertor } = this.getSnapshot();
19
+ return next.handle().pipe(
20
+ catchError((error: unknown): Observable<never> => {
21
+ return throwError((): unknown => errorConvertor(error));
22
+ })
23
+ );
24
+ }
25
+ }
@@ -0,0 +1,2 @@
1
+ export * from './error.interceptor';
2
+ export * from './response.format.interceptor';
@@ -0,0 +1,29 @@
1
+ import {
2
+ Injectable,
3
+ NestInterceptor,
4
+ ExecutionContext,
5
+ CallHandler,
6
+ } from '@nestjs/common';
7
+ import { Observable } from 'rxjs';
8
+ import { map } from 'rxjs/operators';
9
+
10
+ import { HttpResponseBody } from '../../http/types';
11
+
12
+ @Injectable()
13
+ export class ResponseFormatInterceptor<T>
14
+ implements NestInterceptor<T, HttpResponseBody<T>>
15
+ {
16
+ intercept(
17
+ _context: ExecutionContext,
18
+ next: CallHandler
19
+ ): Observable<HttpResponseBody<T>> {
20
+ return next.handle().pipe(
21
+ map(
22
+ (data: T): HttpResponseBody<T> => ({
23
+ data,
24
+ message: 'ok',
25
+ })
26
+ )
27
+ );
28
+ }
29
+ }
@@ -0,0 +1,20 @@
1
+ import {
2
+ MiddlewareConsumer,
3
+ Module,
4
+ NestModule,
5
+ RequestMethod,
6
+ } from '@nestjs/common';
7
+
8
+ import { PingMiddleware } from './middlewares';
9
+
10
+ @Module({
11
+ providers: [PingMiddleware],
12
+ })
13
+ export class HealthModule implements NestModule {
14
+ configure(consumer: MiddlewareConsumer): void {
15
+ consumer.apply(PingMiddleware).forRoutes({
16
+ path: '/health/ping',
17
+ method: RequestMethod.GET,
18
+ });
19
+ }
20
+ }
@@ -0,0 +1 @@
1
+ export * from './health.module';
@@ -0,0 +1 @@
1
+ export * from './ping.middleware';
@@ -0,0 +1,9 @@
1
+ import { Injectable, NestMiddleware } from '@nestjs/common';
2
+ import type { Request, Response } from 'express';
3
+
4
+ @Injectable()
5
+ export class PingMiddleware implements NestMiddleware {
6
+ use(_request: Request, response: Response): void {
7
+ response.end('Pong');
8
+ }
9
+ }
@@ -0,0 +1,2 @@
1
+ export * from './health';
2
+ export * from './requirement';
@@ -0,0 +1 @@
1
+ export * from './requirement.module';
@@ -0,0 +1,56 @@
1
+ import { Module } from '@nestjs/common';
2
+ import { ConfigModule } from '@nestjs/config';
3
+ import { APP_FILTER, APP_GUARD, APP_INTERCEPTOR } from '@nestjs/core';
4
+ import { ThrottlerGuard, ThrottlerModule } from '@nestjs/throttler';
5
+ import type { ILogger } from '@ask-ell/core';
6
+ import { NestLogger } from '@ask-ell/nest';
7
+ import { SentryGlobalFilter, SentryModule } from '@sentry/nestjs/setup';
8
+
9
+ import { KeyvStoreAdapterFactory } from '../../../keyv.store.adapter.factory';
10
+ import { dockerSecretGetter, localSecretGetter } from '../../../secrets';
11
+ import { HealthModule } from '../health';
12
+ import { ResponseFormatInterceptor } from '../../interceptors';
13
+ import { HttpExceptionFilter } from '../../filters';
14
+
15
+ const configModuleLogger: ILogger = NestLogger.fromClass(ConfigModule);
16
+
17
+ @Module({
18
+ imports: [
19
+ HealthModule,
20
+ SentryModule.forRoot(),
21
+ ThrottlerModule.forRoot([
22
+ {
23
+ ttl: 60000,
24
+ limit: 30,
25
+ },
26
+ ]),
27
+ ConfigModule.forRoot({
28
+ isGlobal: true,
29
+ load: [
30
+ dockerSecretGetter(configModuleLogger),
31
+ localSecretGetter(configModuleLogger),
32
+ ],
33
+ }),
34
+ ],
35
+ providers: [
36
+ KeyvStoreAdapterFactory,
37
+ {
38
+ provide: APP_GUARD,
39
+ useClass: ThrottlerGuard,
40
+ },
41
+ {
42
+ provide: APP_INTERCEPTOR,
43
+ useClass: ResponseFormatInterceptor,
44
+ },
45
+ {
46
+ provide: APP_FILTER,
47
+ useClass: HttpExceptionFilter,
48
+ },
49
+ {
50
+ provide: APP_FILTER,
51
+ useClass: SentryGlobalFilter,
52
+ },
53
+ ],
54
+ exports: [ConfigModule, SentryModule, KeyvStoreAdapterFactory],
55
+ })
56
+ export class RequirementModule {}