@21jumpclick/nestjs-tools 1.0.0

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/README.md ADDED
@@ -0,0 +1,138 @@
1
+ # @21jumpclick/nestjs-tools
2
+
3
+ Bibliothèque d'outils NestJS pour les projets 21JumpClick, avec un focus sur le logging et les utilitaires RMQ.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @21jumpclick/nestjs-tools
9
+ ```
10
+
11
+ ## Utilisation
12
+
13
+ ### Logging Module
14
+
15
+ Le module de logging fournit des fonctionnalités de logging avancées avec Pino et des utilitaires pour RabbitMQ.
16
+
17
+ ```typescript
18
+ import { Module } from '@nestjs/common';
19
+ import { LoggingModule } from '@21jumpclick/nestjs-tools';
20
+
21
+ @Module({
22
+ imports: [
23
+ LoggingModule, // Module global - automatiquement disponible partout
24
+ ],
25
+ })
26
+ export class AppModule {}
27
+ ```
28
+
29
+ ### Logging Service
30
+
31
+ Utilisez le service de logging pour enregistrer les messages RMQ et créer des clients avec logging intégré.
32
+
33
+ ```typescript
34
+ import { Injectable } from '@nestjs/common';
35
+ import { LoggingService } from '@21jumpclick/nestjs-tools';
36
+
37
+ @Injectable()
38
+ export class MyService {
39
+ constructor(private readonly loggingService: LoggingService) {}
40
+
41
+ async someMethod() {
42
+ // Logger un message RMQ entrant
43
+ this.loggingService.logRmqMessage('pattern.name', { data: 'example' });
44
+
45
+ // Logger un message RMQ sortant
46
+ this.loggingService.logRmqOutgoing('pattern.name', { data: 'example' }, {
47
+ durationMs: 150,
48
+ status: 'sent'
49
+ });
50
+ }
51
+ }
52
+ ```
53
+
54
+ ### RMQ Module
55
+
56
+ Module simplifié pour la configuration des clients RabbitMQ.
57
+
58
+ ```typescript
59
+ import { Module } from '@nestjs/common';
60
+ import { RmqModule } from '@21jumpclick/nestjs-tools';
61
+
62
+ @Module({
63
+ imports: [
64
+ RmqModule.register({
65
+ name: 'MY_SERVICE',
66
+ urls: ['amqp://localhost:5672'],
67
+ queue: 'my_queue',
68
+ isGlobal: true,
69
+ }),
70
+ ],
71
+ })
72
+ export class AppModule {}
73
+ ```
74
+
75
+ ### Configuration RMQ Avancée
76
+
77
+ ```typescript
78
+ import { Module } from '@nestjs/common';
79
+ import { RmqModule } from '@21jumpclick/nestjs-tools';
80
+
81
+ @Module({
82
+ imports: [
83
+ RmqModule.registerAsync({
84
+ name: 'MY_SERVICE',
85
+ useFactory: (configService: ConfigService) => ({
86
+ urls: configService.get('RMQ_URLS'),
87
+ queue: configService.get('MY_QUEUE'),
88
+ queueOptions: {
89
+ durable: true,
90
+ },
91
+ prefetchCount: 20,
92
+ }),
93
+ inject: [ConfigService],
94
+ }),
95
+ ],
96
+ })
97
+ export class AppModule {}
98
+ ```
99
+
100
+ ### Interceptors
101
+
102
+ Interceptors pour le logging automatique des requêtes HTTP et messages RMQ.
103
+
104
+ ```typescript
105
+ import { Module } from '@nestjs/common';
106
+ import { APP_INTERCEPTOR } from '@nestjs/core';
107
+ import { LoggingInterceptor } from '@21jumpclick/nestjs-tools';
108
+
109
+ @Module({
110
+ providers: [
111
+ {
112
+ provide: APP_INTERCEPTOR,
113
+ useClass: LoggingInterceptor,
114
+ },
115
+ ],
116
+ })
117
+ export class AppModule {}
118
+ ```
119
+
120
+ ## Features
121
+
122
+ - **Logging structuré** avec Pino
123
+ - **Support RMQ** avec logging automatique
124
+ - **Masquage des données sensibles** (passwords, tokens, etc.)
125
+ - **Configuration flexible** pour différents environnements
126
+ - **Interceptors** pour le logging automatique
127
+ - **Types TypeScript** complets
128
+
129
+ ## Configuration
130
+
131
+ Le module de logging utilise les variables d'environnement suivantes :
132
+
133
+ - `NODE_ENV`: Détermine si le logging est en mode production ou développement
134
+ - `APP_NAME`: Nom de l'application pour les headers RMQ
135
+
136
+ ## License
137
+
138
+ UNLICENSED
package/dist/main.js ADDED
@@ -0,0 +1,13 @@
1
+ /******/ (() => { // webpackBootstrap
2
+ /******/ "use strict";
3
+ var __webpack_exports__ = {};
4
+ // This entry needs to be wrapped in an IIFE because it uses a non-standard name for the exports (exports).
5
+ (() => {
6
+ var exports = __webpack_exports__;
7
+
8
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
9
+
10
+ })();
11
+
12
+ /******/ })()
13
+ ;
package/lefthook.yml ADDED
@@ -0,0 +1,42 @@
1
+ # EXAMPLE USAGE:
2
+ #
3
+ # Refer for explanation to following link:
4
+ # https://lefthook.dev/configuration/
5
+ #
6
+ # pre-push:
7
+ # jobs:
8
+ # - name: packages audit
9
+ # tags:
10
+ # - frontend
11
+ # - security
12
+ # run: yarn audit
13
+ #
14
+ # - name: gems audit
15
+ # tags:
16
+ # - backend
17
+ # - security
18
+ # run: bundle audit
19
+ #
20
+ # pre-commit:
21
+ # parallel: true
22
+ # jobs:
23
+ # - run: yarn eslint {staged_files}
24
+ # glob: "*.{js,ts,jsx,tsx}"
25
+ #
26
+ # - name: rubocop
27
+ # glob: "*.rb"
28
+ # exclude:
29
+ # - config/application.rb
30
+ # - config/routes.rb
31
+ # run: bundle exec rubocop --force-exclusion {all_files}
32
+ #
33
+ # - name: govet
34
+ # files: git ls-files -m
35
+ # glob: "*.go"
36
+ # run: go vet {files}
37
+ #
38
+ # - script: "hello.js"
39
+ # runner: node
40
+ #
41
+ # - script: "hello.go"
42
+ # runner: go run
package/nest-cli.json ADDED
@@ -0,0 +1,10 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/nest-cli",
3
+ "collection": "@nestjs/schematics",
4
+ "sourceRoot": "src",
5
+ "compilerOptions": {
6
+ "deleteOutDir": true,
7
+ "webpack": true,
8
+ "webpackConfigPath": "webpack.config.js"
9
+ }
10
+ }
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@21jumpclick/nestjs-tools",
3
+ "version": "1.0.0",
4
+ "description": "NestJS tools library with logging and other utilities",
5
+ "author": "21JumpClick",
6
+ "license": "UNLICENSED",
7
+ "main": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "publishConfig": {
10
+ "access": "public"
11
+ },
12
+ "scripts": {
13
+ "build": "nest build",
14
+ "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
15
+ "start": "nest start",
16
+ "start:dev": "nest build --webpack --webpackPath webpack-hmr.config.js --watch",
17
+ "start:debug": "nest start --debug --watch",
18
+ "start:prod": "node dist/main",
19
+ "lint": "npx @biomejs/biome check",
20
+ "lint:fix": "npx @biomejs/biome check --fix",
21
+ "prepublish": "npm run build"
22
+ },
23
+ "dependencies": {
24
+ "@nestjs/common": "^11.0.7",
25
+ "@nestjs/core": "^11.0.7",
26
+ "@nestjs/microservices": "^11.0.7",
27
+ "nestjs-pino": "^4.5.0",
28
+ "pino-http": "^11.0.0",
29
+ "pino-pretty": "^13.1.3",
30
+ "reflect-metadata": "^0.2.2",
31
+ "rxjs": "^7.8.1"
32
+ },
33
+ "devDependencies": {
34
+ "@biomejs/biome": "^1.9.4",
35
+ "@nestjs/cli": "^11.0.2",
36
+ "@nestjs/schematics": "^11.0.0",
37
+ "@swc/cli": "^0.6.0",
38
+ "@swc/core": "^1.10.12",
39
+ "@types/node": "^22.13.0",
40
+ "lefthook": "^1.10.10",
41
+ "run-script-webpack-plugin": "^0.2.0",
42
+ "source-map-support": "^0.5.21",
43
+ "ts-loader": "^9.5.2",
44
+ "ts-node": "^10.9.2",
45
+ "tsconfig-paths": "^4.2.0",
46
+ "typescript": "^5.7.3",
47
+ "webpack": "^5.97.1",
48
+ "webpack-node-externals": "^3.0.0"
49
+ },
50
+ "peerDependencies": {
51
+ "@nestjs/common": "^10.0.0 || ^11.0.0",
52
+ "@nestjs/core": "^10.0.0 || ^11.0.0"
53
+ }
54
+ }
package/src/index.ts ADDED
@@ -0,0 +1,3 @@
1
+ export * from './logging';
2
+ export * from './rmq';
3
+ export * from './interceptors';
@@ -0,0 +1 @@
1
+ export * from './logging.interceptor';
@@ -0,0 +1,20 @@
1
+ import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from "@nestjs/common";
2
+ import { Observable } from "rxjs";
3
+ import { tap } from "rxjs/operators";
4
+
5
+ @Injectable()
6
+ export class LoggingInterceptor implements NestInterceptor {
7
+ intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
8
+ const startedAt = Date.now();
9
+ const request = context.switchToHttp().getRequest();
10
+
11
+ console.log(`Incoming request: ${request.method} ${request.url}`);
12
+
13
+ return next.handle().pipe(
14
+ tap(() => {
15
+ const durationMs = Date.now() - startedAt;
16
+ console.log(`Request completed in ${durationMs}ms`);
17
+ })
18
+ );
19
+ }
20
+ }
@@ -0,0 +1,3 @@
1
+ export * from './logging.module';
2
+ export * from './logging.service';
3
+ export * from './rmq-client.interceptor';
@@ -0,0 +1,43 @@
1
+ import { Global, Module } from "@nestjs/common";
2
+ import { LoggerModule } from "nestjs-pino";
3
+ import { LoggingService } from "./logging.service";
4
+ import { RmqClientInterceptor } from "./rmq-client.interceptor";
5
+
6
+ export interface LoggingModuleOptions {
7
+ pinoHttp?: any;
8
+ }
9
+
10
+ @Global()
11
+ @Module({
12
+ imports: [
13
+ LoggerModule.forRoot({
14
+ pinoHttp: {
15
+ formatters: {
16
+ level: (label) => ({ level: label.toUpperCase() }),
17
+ },
18
+ genReqId: (req) => req.headers["x-request-id"] || crypto.randomUUID(),
19
+ transport:
20
+ process.env.NODE_ENV !== "production"
21
+ ? {
22
+ target: "pino-pretty",
23
+ options: {
24
+ colorize: true,
25
+ levelFirst: true,
26
+ translateTime: "HH:MM:ss",
27
+ messageFormat: "{context}: {msg}",
28
+ ignore: "pid,hostname",
29
+ },
30
+ }
31
+ : undefined,
32
+ redact: [
33
+ "req.headers.authorization",
34
+ "req.body.password",
35
+ "res.headers.cookie",
36
+ ],
37
+ },
38
+ }),
39
+ ],
40
+ providers: [LoggingService, RmqClientInterceptor],
41
+ exports: [LoggingService, LoggerModule],
42
+ })
43
+ export class LoggingModule {}
@@ -0,0 +1,223 @@
1
+ import { Injectable, Logger } from "@nestjs/common";
2
+ import { ClientProxy, MicroserviceOptions, Transport } from "@nestjs/microservices";
3
+ import { catchError, finalize, Observable, throwError } from "rxjs";
4
+
5
+ @Injectable()
6
+ export class LoggingService {
7
+ private readonly rmqLogger = new Logger("RMQ-Traffic");
8
+
9
+ logRmqMessage(pattern: string, data: any) {
10
+ const logData = {
11
+ transport: "RMQ_IN",
12
+ pattern,
13
+ data: this.sanitizeData(data),
14
+ duration: "0ms",
15
+ status: "received",
16
+ };
17
+
18
+ this.rmqLogger.log(logData);
19
+ }
20
+
21
+ logRmqOutgoing(
22
+ pattern: string,
23
+ data: any,
24
+ options?: {
25
+ durationMs?: number;
26
+ status?: "sent" | "error";
27
+ error?: unknown;
28
+ },
29
+ ) {
30
+ const logData = {
31
+ transport: "RMQ_OUT",
32
+ pattern,
33
+ data: this.sanitizeData(data),
34
+ duration:
35
+ typeof options?.durationMs === "number"
36
+ ? `${options.durationMs}ms`
37
+ : "0ms",
38
+ status: options?.status ?? "sent",
39
+ ...(options?.error ? { error: this.sanitizeData(options.error) } : {}),
40
+ };
41
+
42
+ this.rmqLogger.log(logData);
43
+ }
44
+
45
+ createLoggedClientProxy(client: ClientProxy, clientName: string): ClientProxy {
46
+ const logging = this;
47
+
48
+ const wrapper: Partial<ClientProxy> = {
49
+ send<TResult = any, TInput = any>(pattern: any, data: TInput): Observable<TResult> {
50
+ const startedAt = Date.now();
51
+ let hadError = false;
52
+
53
+ return client.send<TResult, TInput>(pattern, data).pipe(
54
+ catchError((err) => {
55
+ hadError = true;
56
+ const durationMs = Date.now() - startedAt;
57
+ logging.logRmqOutgoing(`${clientName}:${logging.patternToString(pattern)}`, data, {
58
+ durationMs,
59
+ status: "error",
60
+ error: err,
61
+ });
62
+ return throwError(() => err);
63
+ }),
64
+ finalize(() => {
65
+ const durationMs = Date.now() - startedAt;
66
+ if (!hadError) {
67
+ logging.logRmqOutgoing(`${clientName}:${logging.patternToString(pattern)}`, data, {
68
+ durationMs,
69
+ status: "sent",
70
+ });
71
+ }
72
+ }),
73
+ );
74
+ },
75
+
76
+ emit<TResult = any, TInput = any>(pattern: any, data: TInput): Observable<TResult> {
77
+ const startedAt = Date.now();
78
+ let hadError = false;
79
+
80
+ logging.logRmqOutgoing(`${clientName}:${logging.patternToString(pattern)}`, data, {
81
+ status: "sent",
82
+ });
83
+
84
+ return client.emit<TResult, TInput>(pattern, data).pipe(
85
+ catchError((err) => {
86
+ hadError = true;
87
+ const durationMs = Date.now() - startedAt;
88
+ logging.logRmqOutgoing(`${clientName}:${logging.patternToString(pattern)}`, data, {
89
+ durationMs,
90
+ status: "error",
91
+ error: err,
92
+ });
93
+ return throwError(() => err);
94
+ }),
95
+ );
96
+ },
97
+
98
+ connect(): Promise<any> {
99
+ return client.connect();
100
+ },
101
+ close(): any {
102
+ return client.close();
103
+ },
104
+ };
105
+
106
+ return new Proxy(client as any, {
107
+ get(target, prop, receiver) {
108
+ if (prop in wrapper) {
109
+ const v = (wrapper as any)[prop];
110
+ return typeof v === "function" ? v.bind(receiver) : v;
111
+ }
112
+ const value = Reflect.get(target, prop, receiver);
113
+ return typeof value === "function" ? value.bind(target) : value;
114
+ },
115
+ }) as ClientProxy;
116
+ }
117
+
118
+ createRmqMicroservice(options: {
119
+ urls: string[];
120
+ queue: string;
121
+ queueOptions?: { durable?: boolean };
122
+ customDeserializer?: boolean;
123
+ }): MicroserviceOptions {
124
+ return {
125
+ transport: Transport.RMQ,
126
+ options: {
127
+ urls: options.urls,
128
+ queue: options.queue,
129
+ queueOptions: {
130
+ durable: true,
131
+ ...options.queueOptions,
132
+ },
133
+ ...(options.customDeserializer && {
134
+ deserializer: {
135
+ deserialize: (value: any) => {
136
+ const pattern =
137
+ typeof value === "object" && !value.pattern
138
+ ? options.queue
139
+ : value?.pattern || "unknown";
140
+ const data = value?.data || value;
141
+
142
+ this.logRmqMessage(pattern, data);
143
+
144
+ if (typeof value === "object" && !value.pattern) {
145
+ return { pattern: options.queue, data: value };
146
+ }
147
+ return value;
148
+ },
149
+ },
150
+ }),
151
+ },
152
+ };
153
+ }
154
+
155
+ createRmqClient(name: string, urls: string[], queue: string): any {
156
+ return {
157
+ name,
158
+ transport: Transport.RMQ,
159
+ options: {
160
+ urls,
161
+ queue,
162
+ queueOptions: {
163
+ durable: true,
164
+ },
165
+ headers: {
166
+ origin: process.env.APP_NAME || "unknown",
167
+ },
168
+ },
169
+ serializer: {
170
+ serialize: (value: any) => {
171
+ this.logRmqOutgoing(queue, value);
172
+ return value;
173
+ },
174
+ },
175
+ };
176
+ }
177
+
178
+ private patternToString(pattern: any): string {
179
+ if (typeof pattern === "string") return pattern;
180
+ if (typeof pattern === "number") return pattern.toString();
181
+ try {
182
+ return JSON.stringify(pattern);
183
+ } catch {
184
+ return "[unserializable-pattern]";
185
+ }
186
+ }
187
+
188
+ private sanitizeData(data: any): any {
189
+ if (!data) return null;
190
+
191
+ const sanitized = JSON.parse(JSON.stringify(data));
192
+ const sensitiveKeys = [
193
+ "password",
194
+ "token",
195
+ "secret",
196
+ "key",
197
+ "authorization",
198
+ ];
199
+
200
+ const maskSensitive = (obj: any): any => {
201
+ if (typeof obj !== "object" || obj === null) return obj;
202
+
203
+ if (Array.isArray(obj)) {
204
+ return obj.map(maskSensitive);
205
+ }
206
+
207
+ const result: any = {};
208
+ for (const [key, value] of Object.entries(obj)) {
209
+ const lowerKey = key.toLowerCase();
210
+ if (sensitiveKeys.some((sensitive) => lowerKey.includes(sensitive))) {
211
+ result[key] = "[MASKED]";
212
+ } else if (typeof value === "object") {
213
+ result[key] = maskSensitive(value);
214
+ } else {
215
+ result[key] = value;
216
+ }
217
+ }
218
+ return result;
219
+ };
220
+
221
+ return maskSensitive(sanitized);
222
+ }
223
+ }
@@ -0,0 +1,27 @@
1
+ import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from "@nestjs/common";
2
+ import { Observable } from "rxjs";
3
+ import { tap } from "rxjs/operators";
4
+ import { LoggingService } from "../logging/logging.service";
5
+
6
+ @Injectable()
7
+ export class RmqClientInterceptor implements NestInterceptor {
8
+ constructor(private readonly loggingService: LoggingService) {}
9
+
10
+ intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
11
+ const startedAt = Date.now();
12
+ const pattern = context.getPattern();
13
+ const data = context.getArgByIndex(0);
14
+
15
+ this.loggingService.logRmqMessage(
16
+ typeof pattern === "string" ? pattern : JSON.stringify(pattern),
17
+ data
18
+ );
19
+
20
+ return next.handle().pipe(
21
+ tap(() => {
22
+ const durationMs = Date.now() - startedAt;
23
+ console.log(`RMQ message processed in ${durationMs}ms`);
24
+ })
25
+ );
26
+ }
27
+ }
@@ -0,0 +1,2 @@
1
+ export * from './rmq.module';
2
+ export * from './rmq.service';
@@ -0,0 +1,87 @@
1
+ import { Module } from "@nestjs/common";
2
+ import { ClientsModule, Transport } from "@nestjs/microservices";
3
+ import { LoggingService } from "../logging/logging.service";
4
+
5
+ export interface RmqModuleOptions {
6
+ name: string;
7
+ urls: string[];
8
+ queue: string;
9
+ queueOptions?: { durable?: boolean };
10
+ noAck?: boolean;
11
+ prefetchCount?: number;
12
+ isGlobal?: boolean;
13
+ }
14
+
15
+ @Module({})
16
+ export class RmqModule {
17
+ static register(options: RmqModuleOptions) {
18
+ const moduleOptions = {
19
+ name: options.name,
20
+ transport: Transport.RMQ,
21
+ options: {
22
+ urls: options.urls,
23
+ queue: options.queue,
24
+ queueOptions: {
25
+ durable: true,
26
+ ...options.queueOptions,
27
+ },
28
+ noAck: options.noAck ?? false,
29
+ prefetchCount: options.prefetchCount ?? 10,
30
+ headers: {
31
+ origin: process.env.APP_NAME || "unknown",
32
+ },
33
+ },
34
+ };
35
+
36
+ const module = ClientsModule.register([moduleOptions]);
37
+
38
+ if (options.isGlobal) {
39
+ return {
40
+ ...module,
41
+ global: true,
42
+ };
43
+ }
44
+
45
+ return module;
46
+ }
47
+
48
+ static registerAsync(options: RmqModuleOptions & {
49
+ useFactory: (...args: any[]) => Promise<RmqModuleOptions> | RmqModuleOptions;
50
+ inject?: any[];
51
+ }) {
52
+ const asyncOptions = {
53
+ name: options.name,
54
+ useFactory: async (...args: any[]) => {
55
+ const factoryOptions = await options.useFactory(...args);
56
+ return {
57
+ transport: Transport.RMQ,
58
+ options: {
59
+ urls: factoryOptions.urls,
60
+ queue: factoryOptions.queue,
61
+ queueOptions: {
62
+ durable: true,
63
+ ...factoryOptions.queueOptions,
64
+ },
65
+ noAck: factoryOptions.noAck ?? false,
66
+ prefetchCount: factoryOptions.prefetchCount ?? 10,
67
+ headers: {
68
+ origin: process.env.APP_NAME || "unknown",
69
+ },
70
+ },
71
+ };
72
+ },
73
+ inject: options.inject || [],
74
+ };
75
+
76
+ const module = ClientsModule.registerAsync([asyncOptions]);
77
+
78
+ if (options.isGlobal) {
79
+ return {
80
+ ...module,
81
+ global: true,
82
+ };
83
+ }
84
+
85
+ return module;
86
+ }
87
+ }
@@ -0,0 +1,25 @@
1
+ import { Injectable } from "@nestjs/common";
2
+ import { ClientProxy } from "@nestjs/microservices";
3
+ import { LoggingService } from "../logging/logging.service";
4
+
5
+ @Injectable()
6
+ export class RmqService {
7
+ constructor(private readonly loggingService: LoggingService) {}
8
+
9
+ createLoggedClientProxy(client: ClientProxy, clientName: string): ClientProxy {
10
+ return this.loggingService.createLoggedClientProxy(client, clientName);
11
+ }
12
+
13
+ createRmqClient(name: string, urls: string[], queue: string): any {
14
+ return this.loggingService.createRmqClient(name, urls, queue);
15
+ }
16
+
17
+ createRmqMicroservice(options: {
18
+ urls: string[];
19
+ queue: string;
20
+ queueOptions?: { durable?: boolean };
21
+ customDeserializer?: boolean;
22
+ }) {
23
+ return this.loggingService.createRmqMicroservice(options);
24
+ }
25
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "compilerOptions": {
3
+ "module": "commonjs",
4
+ "declaration": true,
5
+ "removeComments": true,
6
+ "emitDecoratorMetadata": true,
7
+ "experimentalDecorators": true,
8
+ "allowSyntheticDefaultImports": true,
9
+ "target": "ES2021",
10
+ "sourceMap": true,
11
+ "outDir": "./dist",
12
+ "baseUrl": "./",
13
+ "incremental": true,
14
+ "skipLibCheck": true,
15
+ "strictNullChecks": false,
16
+ "noImplicitAny": false,
17
+ "strictBindCallApply": false,
18
+ "forceConsistentCasingInFileNames": false,
19
+ "noFallthroughCasesInSwitch": false,
20
+ "paths": {
21
+ "@/*": ["src/*"]
22
+ }
23
+ },
24
+ "exclude": ["node_modules", "dist"]
25
+ }
@@ -0,0 +1,24 @@
1
+ const path = require('path');
2
+
3
+ module.exports = (options, webpack) => {
4
+ const lazyImports = [
5
+ '@nestjs/microservices',
6
+ '@nestjs/websockets',
7
+ 'cache-manager',
8
+ 'class-validator',
9
+ 'class-transformer',
10
+ ];
11
+
12
+ return {
13
+ ...options,
14
+ externals: [],
15
+ plugins: [
16
+ ...options.plugins,
17
+ new webpack.IgnorePlugin({
18
+ checkResource(resource) {
19
+ return lazyImports.includes(resource);
20
+ },
21
+ }),
22
+ ],
23
+ };
24
+ };