@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.
- package/CHANGELOG.md +11 -0
- package/jest.config.ts +0 -1
- package/package.json +4 -2
- package/project.json +4 -7
- package/src/http/index.ts +1 -0
- package/src/http/types.ts +4 -0
- package/src/index.ts +2 -2
- package/src/keyv.store.adapter.factory.ts +31 -25
- package/src/nest/add-ons/add-on.interface.ts +5 -0
- package/src/nest/add-ons/add-on.wrapper.ts +31 -0
- package/src/{add-ons → nest/add-ons}/implementations/security/security.add-on.ts +3 -4
- package/src/nest/add-ons/implementations/sentry/sentry.add-on.interface.ts +8 -0
- package/src/{add-ons → nest/add-ons}/implementations/sentry/sentry.add-on.state.interface.ts +1 -1
- package/src/{add-ons → nest/add-ons}/implementations/sentry/sentry.add-on.ts +8 -9
- package/src/nest/add-ons/implementations/swagger/swagger.add-on.interface.ts +8 -0
- package/src/{add-ons → nest/add-ons}/implementations/swagger/swagger.add-on.state.interface.ts +3 -2
- package/src/nest/add-ons/implementations/swagger/swagger.add-on.ts +59 -0
- package/src/nest/add-ons/implementations/swagger/types.ts +1 -0
- package/src/nest/add-ons/index.ts +6 -0
- package/src/nest/add-ons/types.ts +7 -0
- package/src/nest/application.base.ts +18 -0
- package/src/nest/application.factory.ts +23 -0
- package/src/nest/filters/http.exception.filter.ts +23 -0
- package/src/nest/filters/index.ts +1 -0
- package/src/nest/index.ts +6 -0
- package/src/nest/interceptors/error.interceptor.ts +25 -0
- package/src/nest/interceptors/index.ts +2 -0
- package/src/nest/interceptors/response.format.interceptor.ts +29 -0
- package/src/nest/modules/health/health.module.ts +20 -0
- package/src/nest/modules/health/index.ts +1 -0
- package/src/nest/modules/health/middlewares/index.ts +1 -0
- package/src/nest/modules/health/middlewares/ping.middleware.ts +9 -0
- package/src/nest/modules/index.ts +2 -0
- package/src/nest/modules/requirement/index.ts +1 -0
- package/src/nest/modules/requirement/requirement.module.ts +56 -0
- package/src/scripts/move-keyv-data.script.ts +69 -48
- package/src/scripts/update-dependencies-versions.script.ts +164 -130
- package/src/secrets/docker.secret.getter.ts +6 -5
- package/src/secrets/file.secret.getter.ts +19 -16
- package/src/secrets/index.ts +2 -2
- package/src/secrets/local.secret.getter.ts +6 -5
- package/src/tmp.ts +15 -0
- package/src/add-ons/add-on.interface.ts +0 -5
- package/src/add-ons/add-on.wrapper.ts +0 -36
- package/src/add-ons/implementations/sentry/sentry.add-on.interface.ts +0 -8
- package/src/add-ons/implementations/swagger/swagger.add-on.interface.ts +0 -7
- package/src/add-ons/implementations/swagger/swagger.add-on.ts +0 -43
- package/src/add-ons/implementations/swagger/types.ts +0 -1
- package/src/add-ons/index.ts +0 -1
- package/src/add-ons/types.ts +0 -7
- package/src/application.base.ts +0 -15
- package/src/requirement.module.ts +0 -57
- package/src/utils/index.ts +0 -1
- 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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ask-ell/back-end",
|
|
3
|
-
"version": "0.
|
|
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';
|
package/src/index.ts
CHANGED
|
@@ -1,37 +1,43 @@
|
|
|
1
|
-
import { Injectable } from
|
|
2
|
-
import { KeyvStoreAdapter } from
|
|
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
|
|
5
|
+
import { ILogger, MaybeUndefined } from '@ask-ell/core';
|
|
6
6
|
import { NestLogger } from '@ask-ell/nest';
|
|
7
|
-
import { join } from
|
|
7
|
+
import { join } from 'node:path';
|
|
8
8
|
|
|
9
|
-
import { createTmpFolder, TMP_FOLDER_PATH } from
|
|
9
|
+
import { createTmpFolder, TMP_FOLDER_PATH } from './tmp';
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
11
|
+
export type CreateKeyvStoreAdapterOptions = {
|
|
12
|
+
postgresUri: MaybeUndefined<string>;
|
|
13
|
+
};
|
|
15
14
|
|
|
16
15
|
@Injectable()
|
|
17
16
|
export class KeyvStoreAdapterFactory {
|
|
18
|
-
|
|
17
|
+
private logger: ILogger = NestLogger.fromClass(KeyvStoreAdapterFactory);
|
|
19
18
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
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,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
|
|
1
|
+
import { INestApplication, ValidationPipe } from '@nestjs/common';
|
|
2
2
|
import helmet from 'helmet';
|
|
3
3
|
|
|
4
|
-
import { IAddOn } from
|
|
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
|
}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { Entity, type IResult, ok } from
|
|
2
|
-
import { NestSentryConfiguration } from
|
|
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
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
publicKey,
|
|
20
|
+
host,
|
|
21
|
+
projectId,
|
|
23
22
|
}).init();
|
|
24
23
|
}
|
|
25
|
-
}
|
|
24
|
+
}
|
|
@@ -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,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,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 @@
|
|
|
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 {}
|