@jrosadob/ms-sophia-framework-mysql 0.0.1 → 0.0.2

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 (71) hide show
  1. package/.prettierrc +4 -0
  2. package/README.md +21 -0
  3. package/bootstrap.yml +193 -0
  4. package/eslint.config.mjs +35 -0
  5. package/libs/ms-sophia-framework-mysql/src/app.module.ts +14 -0
  6. package/libs/ms-sophia-framework-mysql/src/core/amqp-clients/amqp-clients.module.ts +43 -0
  7. package/libs/ms-sophia-framework-mysql/src/core/amqp-clients/amqp-clients.ts +22 -0
  8. package/libs/ms-sophia-framework-mysql/src/core/amqp-clients/amqp-config.ts +3 -0
  9. package/libs/ms-sophia-framework-mysql/src/core/amqp-clients/amqp-pattern.ts +61 -0
  10. package/libs/ms-sophia-framework-mysql/src/core/amqp-clients/amqp-register.options.ts +6 -0
  11. package/libs/ms-sophia-framework-mysql/src/core/amqp-clients/amqp-sample.module.ts +20 -0
  12. package/libs/ms-sophia-framework-mysql/src/core/amqp-clients/amqp-sample.service.ts +34 -0
  13. package/libs/ms-sophia-framework-mysql/src/core/common/base/error.ts +5 -0
  14. package/libs/ms-sophia-framework-mysql/src/core/common/base/result.ts +15 -0
  15. package/libs/ms-sophia-framework-mysql/src/core/common/base/status-base.ts +12 -0
  16. package/libs/ms-sophia-framework-mysql/src/core/common/dto/change-status.dto.ts +13 -0
  17. package/libs/ms-sophia-framework-mysql/src/core/common/dto/log.dto.ts +29 -0
  18. package/libs/ms-sophia-framework-mysql/src/core/common/dto/order-by.dto.ts +9 -0
  19. package/libs/ms-sophia-framework-mysql/src/core/common/dto/pagination.dto.ts +10 -0
  20. package/libs/ms-sophia-framework-mysql/src/core/common/dto/search.dto.ts +8 -0
  21. package/libs/ms-sophia-framework-mysql/src/core/common/dto/select.dto.ts +23 -0
  22. package/libs/ms-sophia-framework-mysql/src/core/common/entity/base.entity.ts +16 -0
  23. package/libs/ms-sophia-framework-mysql/src/core/common/exceptions/app-badrequest.exception.ts +31 -0
  24. package/libs/ms-sophia-framework-mysql/src/core/common/exceptions/app-http.exception.ts +35 -0
  25. package/libs/ms-sophia-framework-mysql/src/core/common/exceptions/app-unauthorized.exception.ts +36 -0
  26. package/libs/ms-sophia-framework-mysql/src/core/common/filters/all-exception.filter.ts +42 -0
  27. package/libs/ms-sophia-framework-mysql/src/core/common/index.ts +24 -0
  28. package/libs/ms-sophia-framework-mysql/src/core/common/pipes/app-validation.pipe.ts +35 -0
  29. package/libs/ms-sophia-framework-mysql/src/core/common/result/bad-request.result.ts +17 -0
  30. package/libs/ms-sophia-framework-mysql/src/core/common/result/property.result.ts +8 -0
  31. package/libs/ms-sophia-framework-mysql/src/core/common/result/unauthorized.result.ts +14 -0
  32. package/libs/ms-sophia-framework-mysql/src/core/config/config.module.ts +22 -0
  33. package/libs/ms-sophia-framework-mysql/src/core/config/config.service.ts +37 -0
  34. package/libs/ms-sophia-framework-mysql/src/core/config/index.ts +2 -0
  35. package/libs/ms-sophia-framework-mysql/src/core/database/database.module.ts +18 -0
  36. package/libs/ms-sophia-framework-mysql/src/core/database/database.provider.ts +70 -0
  37. package/libs/ms-sophia-framework-mysql/src/core/database/index.ts +3 -0
  38. package/libs/ms-sophia-framework-mysql/src/core/database/providers.ts +3 -0
  39. package/libs/ms-sophia-framework-mysql/src/core/health/health.controller.ts +36 -0
  40. package/libs/ms-sophia-framework-mysql/src/core/health/health.module.ts +16 -0
  41. package/libs/ms-sophia-framework-mysql/src/core/interceptors/headers.interceptor.ts +16 -0
  42. package/libs/ms-sophia-framework-mysql/src/core/interceptors/index.ts +2 -0
  43. package/libs/ms-sophia-framework-mysql/src/core/interceptors/logging.interceptor.ts +43 -0
  44. package/libs/ms-sophia-framework-mysql/src/core/logger/index.ts +4 -0
  45. package/libs/ms-sophia-framework-mysql/src/core/logger/logger.module.ts +10 -0
  46. package/libs/ms-sophia-framework-mysql/src/core/logger/logger.request.ts +137 -0
  47. package/libs/ms-sophia-framework-mysql/src/core/logger/logger.ts +146 -0
  48. package/libs/ms-sophia-framework-mysql/src/core/logger/typeorm-logger.service.ts +76 -0
  49. package/libs/ms-sophia-framework-mysql/src/core/subscribers/entity.subscriber.ts +79 -0
  50. package/libs/ms-sophia-framework-mysql/src/core/subscribers/log.entity.ts +35 -0
  51. package/libs/ms-sophia-framework-mysql/src/core/tools/env-vars.ts +26 -0
  52. package/libs/ms-sophia-framework-mysql/src/core/tools/index.ts +4 -0
  53. package/libs/ms-sophia-framework-mysql/src/core/tools/nanoid.ts +4 -0
  54. package/libs/ms-sophia-framework-mysql/src/core/tools/query.ts +186 -0
  55. package/libs/ms-sophia-framework-mysql/src/core/tools/send-to-logstash.ts +103 -0
  56. package/libs/ms-sophia-framework-mysql/src/index.ts +1 -0
  57. package/libs/ms-sophia-framework-mysql/src/main.ts +230 -0
  58. package/libs/ms-sophia-framework-mysql/tsconfig.lib.json +9 -0
  59. package/nest-cli.json +20 -0
  60. package/package.json +30 -42
  61. package/pnpm-workspace.yaml +3 -0
  62. package/publish.sh +18 -0
  63. package/src/app.controller.spec.ts +22 -0
  64. package/src/app.controller.ts +12 -0
  65. package/src/app.module.ts +10 -0
  66. package/src/app.service.ts +8 -0
  67. package/src/main.ts +8 -0
  68. package/test/app.e2e-spec.ts +29 -0
  69. package/test/jest-e2e.json +16 -0
  70. package/tsconfig.build.json +4 -0
  71. package/tsconfig.json +33 -0
package/.prettierrc ADDED
@@ -0,0 +1,4 @@
1
+ {
2
+ "singleQuote": true,
3
+ "trailingComma": "all"
4
+ }
package/README.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # Sophia Framework
2
2
 
3
+ node -v
4
+ npm -v
5
+ nest --version
6
+ npm i -g @nestjs/cli
7
+ # Revisar disponibilidad
8
+ npm view ms-sophia-framework-mysql version
9
+ # Crear el workspace (No funciona con pnpm)
10
+ nest new ms-sophia-framework-mysql --package-manager npm
11
+ # Ingresar
12
+ cd ms-sophia-framework-mysql
13
+ # Generar la libreria
14
+ nest g library ms-sophia-framework-mysql
15
+ # Compilar
16
+ npm run build
17
+ # Validsate
18
+ nest build ms-sophia-framework-mysql
19
+ # Pack en tg.gz para despliegue local
20
+ npm pack
21
+ # Publish
22
+ npm publish --access public
23
+
3
24
  ## v47
4
25
  Define propiedes dinamicas para el datasource:
5
26
  entities, subscribers, synchronize, logging, logger: typeOrmLogger
package/bootstrap.yml ADDED
@@ -0,0 +1,193 @@
1
+ app:
2
+ name: gestor-backend
3
+ module: './dist/app.module.js'
4
+ version: 1.0.0
5
+ port: 3002
6
+ prefix: ''
7
+
8
+ swagger:
9
+ title: 'GestorCMS Backend API'
10
+ description: 'The Authentication API description (versión MySQL)'
11
+ version: '1.0'
12
+ prefix: 'swagger'
13
+
14
+ firebase:
15
+ storageBucket: ${FIREBASE_STORAGE_BUCKET}
16
+ basePath: ${FIREBASE_BASE_PATH}
17
+ serviceAccount:
18
+ projectId: ${FIREBASE_PROJECT_ID}
19
+ privateKey: '${FIREBASE_PRIVATE_KEY}'
20
+ clientEmail: ${FIREBASE_CLIENT_EMAIL}
21
+
22
+ cors:
23
+ origin:
24
+ - 'http://localhost:3000'
25
+ - 'http://localhost:3001'
26
+ - 'http://localhost:4200'
27
+ - 'https://localhost:3000'
28
+ - 'https://localhost:3001'
29
+ - 'https://localhost:4200'
30
+ - 'https://admin-appmovil.uwiener.edu.pe'
31
+ - 'https://dev-admin-appmovil.uwiener.edu.pe'
32
+ - 'https://test-admin-appmovil.uwiener.edu.pe'
33
+ - 'https://gestor-cms.mantix.com.pe'
34
+ methods:
35
+ - 'GET'
36
+ - 'PATCH'
37
+ - 'POST'
38
+ - 'PUT'
39
+ - 'DELETE'
40
+ - 'OPTIONS'
41
+ allowedHeaders:
42
+ - 'Content-Type'
43
+ - 'Authorization'
44
+ exposedHeaders:
45
+ - 'X-API-KEY'
46
+ credentials: true
47
+ maxAge: 3600
48
+
49
+ AMQP:
50
+ urls:
51
+ - 'amqp://MyRabbitUser:MyPassw0rdRMQ@localhost:5672'
52
+ queue: 'ms-accounts'
53
+ prefetchCount: 10
54
+ isGlobalPrefetchCount: false
55
+ noAck: false
56
+ queueOptions:
57
+ durable: true
58
+ arguments:
59
+ x-message-ttl: 60000
60
+ x-dead-letter-exchange: 'ms-accounts-dlx'
61
+ x-dead-letter-routing-key: 'ms-accounts-dlq'
62
+ persistent: true
63
+ exchange: 'exchange'
64
+ exchangeType: 'topic'
65
+ wildcards: true
66
+
67
+ AMQPClients:
68
+ common:
69
+ urls:
70
+ - amqp://localhost:5672
71
+ queueOptions:
72
+ durable: true
73
+ noAck: false
74
+ persistent: true
75
+
76
+ clients:
77
+ ms-account:
78
+ queue: ms-account
79
+ prefetchCount: 20
80
+
81
+ ms-auth:
82
+ queue: ms-auth
83
+ prefetchCount: 10
84
+
85
+ ms-sse:
86
+ queue: ms-sse
87
+ prefetchCount: 5
88
+
89
+ typeorm:
90
+ mysql:
91
+ type: mysql
92
+ host: ${TYPEORM_MYSQL_HOST}
93
+ port: ${TYPEORM_MYSQL_PORT}
94
+ database: ${TYPEORM_MYSQL_DATABASE}
95
+ username: ${TYPEORM_MYSQL_USERNAME}
96
+ password: ${TYPEORM_MYSQL_PASSWORD}
97
+ entities: ${TYPEORM_MYSQL_ENTITIES}
98
+ synchronize: ${TYPEORM_MYSQL_SYNCHRONIZE}
99
+ logging: ${TYPEORM_MYSQL_LOGGING}
100
+
101
+ Jwt:
102
+ SecretKey: ${JWT_SECRETKEY}
103
+ SignOptions:
104
+ ExpiresIn: ${JWT_SIGNOPTIONS_EXPIRESIN}
105
+ RefreshOptions:
106
+ ExpiresIn: ${JWT_REFRESHOPTIONS_EXPIRESIN}
107
+
108
+ httpServices:
109
+ niubizSecurity:
110
+ baseUrl: ${NIUBIZ_SECURITY_BASE_URL}
111
+ niubizSession:
112
+ baseUrl: ${NIUBIZ_SESSION_BASE_URL}
113
+ niubizCertificate:
114
+ baseUrl: ${NIUBIZ_CERTIFICATE_BASE_URL}
115
+ wienerService:
116
+ baseUrl: ${WIENER_SERVICE_BASE_URL}
117
+ # propagatedHeaders:
118
+ # - Authorization
119
+ # - X-Request-Id
120
+ # headers:
121
+ # name: ms-wiener
122
+ retryOptions:
123
+ maxRetries: 3
124
+ baseDelayMs: 1000
125
+ credentials:
126
+ typeId: ${WIENER_SERVICE_CREDENTIALS_TYPEID}
127
+ username: ${WIENER_SERVICE_CREDENTIALS_USERNAME}
128
+ password: ${WIENER_SERVICE_CREDENTIALS_PASSWORD}
129
+ userService:
130
+ baseUrl: 'https://api.com'
131
+ propagatedHeaders:
132
+ - Authorization
133
+ - X-Request-Id
134
+ headers:
135
+ name: ms-user
136
+ paymentService:
137
+ baseUrl: 'https://pay.com'
138
+ propagatedHeaders:
139
+ - Authorization
140
+ - X-Correlation-Id
141
+ headers:
142
+ name: ms-payment
143
+
144
+ logger:
145
+ http:
146
+ # host: http://localhost:5044
147
+
148
+ # Enable Entity Logs
149
+ entityLogs:
150
+ insertEnabled: false
151
+ updateEnabled: false
152
+ removeEnabled: false
153
+
154
+ # Global Pipes Configuration
155
+ validationPipe:
156
+ transform: true
157
+ whitelist: true
158
+ transformOptions:
159
+ enableImplicitConversion: true
160
+ # parseIntPipe:
161
+ # errorHttpStatusCode: 422
162
+
163
+ # parseArrayPipe:
164
+ # items: Number
165
+ # separator: ','
166
+
167
+ staticAssets:
168
+ path: '/public'
169
+
170
+ teams:
171
+ lengthResetPassword: 6
172
+
173
+ niubiz:
174
+ security:
175
+ url: ${NIUBIZ_SECURITY_BASE_URL}
176
+ path: ${NIUBIZ_SECURITY_BASE_PATH}
177
+ session:
178
+ url: ${NIUBIZ_SESSION_BASE_URL}
179
+ path: ${NIUBIZ_SESSION_BASE_PATH}
180
+ certificate:
181
+ url: ${NIUBIZ_CERTIFICATE_BASE_URL}
182
+ path: ${NIUBIZ_CERTIFICATE_BASE_PATH}
183
+ purchaseNumberLength: ${NIUBIZ_PURCHASE_NUMBER_LENGTH}
184
+ merchants:
185
+ - id: ${NIUBIZ_MERCHANTID01}
186
+ user: ${NIUBIZ_USER01}
187
+ password: ${NIUBIZ_PASSWORD01}
188
+ - id: ${NIUBIZ_MERCHANTID02}
189
+ user: ${NIUBIZ_USER02}
190
+ password: ${NIUBIZ_PASSWORD02}
191
+ - id: ${NIUBIZ_MERCHANTID03}
192
+ user: ${NIUBIZ_USER03}
193
+ password: ${NIUBIZ_PASSWORD03}
@@ -0,0 +1,35 @@
1
+ // @ts-check
2
+ import eslint from '@eslint/js';
3
+ import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended';
4
+ import globals from 'globals';
5
+ import tseslint from 'typescript-eslint';
6
+
7
+ export default tseslint.config(
8
+ {
9
+ ignores: ['eslint.config.mjs'],
10
+ },
11
+ eslint.configs.recommended,
12
+ ...tseslint.configs.recommendedTypeChecked,
13
+ eslintPluginPrettierRecommended,
14
+ {
15
+ languageOptions: {
16
+ globals: {
17
+ ...globals.node,
18
+ ...globals.jest,
19
+ },
20
+ sourceType: 'commonjs',
21
+ parserOptions: {
22
+ projectService: true,
23
+ tsconfigRootDir: import.meta.dirname,
24
+ },
25
+ },
26
+ },
27
+ {
28
+ rules: {
29
+ '@typescript-eslint/no-explicit-any': 'off',
30
+ '@typescript-eslint/no-floating-promises': 'warn',
31
+ '@typescript-eslint/no-unsafe-argument': 'warn',
32
+ "prettier/prettier": ["error", { endOfLine: "auto" }],
33
+ },
34
+ },
35
+ );
@@ -0,0 +1,14 @@
1
+ import { Module } from '@nestjs/common'
2
+ import { ConfigModule } from './core/config/config.module'
3
+ import { DatabaseModule } from './core/database/database.module'
4
+ import { LoggerModule } from './core/logger/logger.module'
5
+ import { Logger } from './core/logger/logger'
6
+ // import { HealthController } from './core/health/health.controller'
7
+ import { HealthModule } from './core/health/health.module'
8
+
9
+ @Module({
10
+ imports: [ConfigModule, DatabaseModule, LoggerModule, HealthModule],
11
+ providers: [Logger],
12
+ exports: [Logger],
13
+ })
14
+ export class AppModule {}
@@ -0,0 +1,43 @@
1
+ import { DynamicModule, Module, Provider } from '@nestjs/common'
2
+ import { ClientProxyFactory, Transport } from '@nestjs/microservices'
3
+ import { AmqpRegisterOptions } from './amqp-register.options'
4
+ import { AmqpConfig } from './amqp-config'
5
+
6
+ @Module({})
7
+ export class AmqpClientsModule {
8
+ static register(options: AmqpRegisterOptions): DynamicModule {
9
+ const root = 'AMQPClients'
10
+
11
+ const providers: Provider[] = options.clientTokens.map((token) => ({
12
+ provide: token,
13
+ inject: [options.configServiceToken],
14
+ useFactory: (config: AmqpConfig) => {
15
+ // Regla interna: MS_ACCOUNTS -> ms-accounts
16
+ const clientKey = token.toLowerCase().replace(/^ms_/, 'ms-').replace(/_/g, '-')
17
+
18
+ const common = config.get<Record<string, any>>(`${root}.common`) ?? {}
19
+ const client = config.get<Record<string, any>>(`${root}.clients.${clientKey}`) ?? {}
20
+
21
+ return ClientProxyFactory.create({
22
+ transport: Transport.RMQ,
23
+ options: {
24
+ urls: client.urls ?? common.urls,
25
+ queue: client.queue ?? clientKey,
26
+ queueOptions: client.queueOptions ?? common.queueOptions,
27
+ noAck: client.noAck ?? common.noAck,
28
+ prefetchCount: client.prefetchCount ?? common.prefetchCount,
29
+ isGlobalPrefetchCount:
30
+ client.isGlobalPrefetchCount ?? common.isGlobalPrefetchCount,
31
+ persistent: client.persistent ?? common.persistent,
32
+ },
33
+ })
34
+ },
35
+ }))
36
+
37
+ return {
38
+ module: AmqpClientsModule,
39
+ providers,
40
+ exports: providers,
41
+ }
42
+ }
43
+ }
@@ -0,0 +1,22 @@
1
+ export const AmqpClients = {
2
+ MS_ACCOUNTS: 'MS_ACCOUNTS', // Accounts, Usuarios, Roles, Permisos
3
+ MS_AUTH: 'MS_AUTH', // Autenticación, JWT, OAuth
4
+ MS_MENUS: 'MS_MENUS', // Menús, Submenús, Permisos de menú
5
+ MS_SEND_EMAILS: 'MS_SEND_EMAILS', // Envío de correos electrónicos
6
+ MS_SEND_NOTIFICATIONS: 'MS_SEND_NOTIFICATIONS', // Envío de notificaciones
7
+ MS_SSE: 'MS_SSE', // Server-Sent Events
8
+
9
+ MS_CORE: 'MS_CORE', // Core de negocio (Sistema simple de gestión empresarial)
10
+
11
+ MS_CUSTOMER: 'MS_CUSTOMER', // Clientes
12
+ MS_SALES_ORDERS: 'MS_SALES_ORDERS', // Pedidos
13
+ MS_SALES_DOCUMENTS: 'MS_SALES_DOCUMENTS', // Comprobantes de ventas
14
+ MS_ACCOUNTS_RECEIVABLE: 'MS_ACCOUNTS_RECEIVABLE', // Cuentas por cobrar
15
+
16
+ MS_SUPPLIERS: 'MS_SUPPLIERS', // Proveedores
17
+ MS_PURCHASE_ORDERS: 'MS_PURCHASE_ORDERS', // Pedidos
18
+ MS_PURCHASE_DOCUMENTS: 'MS_PURCHASE_DOCUMENTS', // Comprobantes de compras
19
+ MS_ACCOUNTS_PAYABLE: 'MS_ACCOUNTS_PAYABLE', // Cuentas por pagar
20
+
21
+ MS_ACCOUNTING: 'MS_ACCOUNTING', // Contabilidad
22
+ } as const
@@ -0,0 +1,3 @@
1
+ export type AmqpConfig = {
2
+ get<T = unknown>(key: string): T | undefined
3
+ }
@@ -0,0 +1,61 @@
1
+ export class AmqpPattern {
2
+ microservice: string = '';
3
+ module: string = '';
4
+ action: string = '';
5
+ }
6
+
7
+ export class MsAccountPattern extends AmqpPattern {
8
+ constructor(module: string, action: string) {
9
+ super();
10
+ this.microservice = 'ms-account'
11
+ this.module = module
12
+ this.action = action
13
+ }
14
+ }
15
+
16
+ export class MsAuthPattern extends AmqpPattern {
17
+ constructor(module: string, action: string) {
18
+ super();
19
+ this.microservice = 'ms-auth'
20
+ this.module = module
21
+ this.action = action
22
+ }
23
+ }
24
+
25
+ export class MsSsePattern extends AmqpPattern {
26
+ constructor(module: string, action: string) {
27
+ super();
28
+ this.microservice = 'ms-sse'
29
+ this.module = module
30
+ this.action = action
31
+ }
32
+ }
33
+
34
+ export class MsSendEmailsPattern extends AmqpPattern {
35
+ constructor(module: string, action: string) {
36
+ super();
37
+ this.microservice = 'ms-send-emails'
38
+ this.module = module
39
+ this.action = action
40
+ }
41
+ }
42
+
43
+ export class MsSendNotificationsPattern extends AmqpPattern {
44
+ constructor(module: string, action: string) {
45
+ super();
46
+ this.microservice = 'ms-send-notifications'
47
+ this.module = module
48
+ this.action = action
49
+ }
50
+ }
51
+ // https://portal-backend.mantix.com.pe/api/account/Xxxx ms-account
52
+ // https://portal-backend.mantix.com.pe/api/auth/Xxxx ms-auth
53
+ // https://portal-backend.mantix.com.pe/api/sse/Xxxx ms-sse
54
+ // https://portal-backend.mantix.com.pe/api/send-emails/Xxxx ms-send-emails
55
+ // https://portal-backend.mantix.com.pe/api/send-notifications/Xxxx ms-send-notifications
56
+
57
+ // Microservices Core
58
+ // ms-customer
59
+ // ms-billing
60
+ // ms-supply
61
+ // ms-menu
@@ -0,0 +1,6 @@
1
+ import { InjectionToken } from '@nestjs/common'
2
+
3
+ export type AmqpRegisterOptions = {
4
+ clientTokens: string[]
5
+ configServiceToken: InjectionToken
6
+ }
@@ -0,0 +1,20 @@
1
+ import { Module } from '@nestjs/common'
2
+ import { AmqpClientsModule } from './amqp-clients.module'
3
+ import { AmqpClients } from './amqp-clients'
4
+ import { ConfigService } from '../config'
5
+
6
+ @Module({
7
+ imports: [
8
+ AmqpClientsModule.register({
9
+ clientTokens: [
10
+ AmqpClients.MS_ACCOUNTS,
11
+ AmqpClients.MS_AUTH,
12
+ AmqpClients.MS_SSE,
13
+ AmqpClients.MS_SEND_EMAILS,
14
+ AmqpClients.MS_SEND_NOTIFICATIONS,
15
+ ],
16
+ configServiceToken: ConfigService,
17
+ }),
18
+ ],
19
+ })
20
+ export class MessagingModule {}
@@ -0,0 +1,34 @@
1
+ import { Inject, Injectable } from '@nestjs/common'
2
+ import { ClientProxy } from '@nestjs/microservices'
3
+ import { firstValueFrom } from 'rxjs'
4
+ import { AmqpClients } from './amqp-clients';
5
+ import { MsAccountPattern, MsAuthPattern, MsSsePattern } from './amqp-pattern';
6
+
7
+ @Injectable()
8
+ export class AmqpSampleService {
9
+ constructor(
10
+ @Inject(AmqpClients.MS_ACCOUNTS)
11
+ private readonly msAccountClient: ClientProxy,
12
+
13
+ @Inject(AmqpClients.MS_AUTH)
14
+ private readonly msAuthClient: ClientProxy,
15
+
16
+ @Inject(AmqpClients.MS_SSE)
17
+ private readonly msSseClient: ClientProxy,
18
+ ) {}
19
+
20
+ async emitAccountCreated(payload: any) {
21
+ const pattern = new MsAccountPattern('account', 'created')
22
+ await firstValueFrom(this.msAccountClient.emit(pattern, payload))
23
+ }
24
+
25
+ async sendValidateToken(payload: any) {
26
+ const pattern = new MsAuthPattern('auth', 'validate-token')
27
+ return await firstValueFrom(this.msAuthClient.send(pattern, payload))
28
+ }
29
+
30
+ async emitSseNotification(payload: any) {
31
+ const pattern = new MsSsePattern('sse', 'notify')
32
+ await firstValueFrom(this.msSseClient.emit(pattern, payload))
33
+ }
34
+ }
@@ -0,0 +1,5 @@
1
+ export class Error {
2
+ loggerId: string
3
+ statusCode: number
4
+ message: string
5
+ }
@@ -0,0 +1,15 @@
1
+ import { Error } from './error';
2
+ import { PaginationDto } from '../dto/pagination.dto';
3
+
4
+ export class Result<T> {
5
+ entity: T | null | undefined;
6
+ entities: T[] | null | undefined;
7
+ hasError: boolean = false;
8
+ errors: Error[] | null = null;
9
+ pagination: PaginationDto | undefined;
10
+ addError(loggerId: string, statusCode: number, message: string) {
11
+ this.hasError = true;
12
+ this.errors ??= [];
13
+ this.errors.push({ loggerId, statusCode, message });
14
+ }
15
+ }
@@ -0,0 +1,12 @@
1
+ import { Column, Entity } from "typeorm";
2
+
3
+ export class StatusBase {
4
+ @Column({ name: 'status_id', type: 'int', default: 1 })
5
+ statusId: number;
6
+
7
+ @Column({ name: 'reason_status', type: 'varchar', length: 128, nullable: true, default: 'Add record' })
8
+ reasonStatus: string;
9
+
10
+ @Column({ name: 'date_status', type: 'timestamp', nullable: true, default: () => 'CURRENT_TIMESTAMP' })
11
+ dateStatus: Date;
12
+ }
@@ -0,0 +1,13 @@
1
+ import { IsInt, IsNotEmpty, IsString } from "class-validator"
2
+
3
+ export class ChangeStatusDto {
4
+ @IsInt()
5
+ @IsNotEmpty()
6
+ fromStatusId: number
7
+ @IsInt()
8
+ @IsNotEmpty()
9
+ toStatusId: number
10
+ @IsString()
11
+ @IsNotEmpty()
12
+ reasonStatus: string
13
+ }
@@ -0,0 +1,29 @@
1
+ export class LogDto {
2
+ entity: string
3
+ primaryKeyGuid: string
4
+ primaryKeyNumber: number
5
+ action: string
6
+ reason: string
7
+ typeId: number
8
+ userId: string
9
+ roleId: number
10
+ bossId: string
11
+ statusId: number
12
+
13
+ get primaryKey(): string | number {
14
+ if (this.primaryKeyGuid === null) {
15
+ return this.primaryKeyNumber
16
+ } else {
17
+ return this.primaryKeyGuid
18
+ }
19
+ }
20
+
21
+ set primaryKey(value: string | number) {
22
+ if (typeof value === 'string') {
23
+ this.primaryKeyGuid = value
24
+ }
25
+ if (typeof value === 'number') {
26
+ this.primaryKeyNumber = value
27
+ }
28
+ }
29
+ }
@@ -0,0 +1,9 @@
1
+ import { IsIn, IsString } from 'class-validator';
2
+
3
+ export class OrderByDto {
4
+ @IsString()
5
+ orderBy: string;
6
+ @IsString()
7
+ @IsIn(['ASC', 'DESC'])
8
+ orderSort: 'ASC' | 'DESC';
9
+ }
@@ -0,0 +1,10 @@
1
+ import { IsNumber } from 'class-validator';
2
+
3
+ export class PaginationDto {
4
+ @IsNumber()
5
+ page: number;
6
+ @IsNumber()
7
+ pageSize: number;
8
+ @IsNumber()
9
+ totalPages: number;
10
+ }
@@ -0,0 +1,8 @@
1
+ import { IsString } from "class-validator";
2
+
3
+ export class SearchDto {
4
+ @IsString()
5
+ text: string;
6
+ @IsString({ each: true })
7
+ properties: string[];
8
+ }
@@ -0,0 +1,23 @@
1
+ import { Type } from 'class-transformer';
2
+ import { OrderByDto } from './order-by.dto';
3
+ import { PaginationDto } from './pagination.dto';
4
+ import { IsOptional } from 'class-validator';
5
+ import { SearchDto } from './search.dto';
6
+
7
+ export class SelectDto<T> {
8
+ @IsOptional()
9
+ @Type(() => SearchDto)
10
+ search: SearchDto;
11
+
12
+ @IsOptional()
13
+ @Type(() => Object)
14
+ where: T;
15
+
16
+ @IsOptional()
17
+ @Type(() => OrderByDto)
18
+ orderBy: OrderByDto[];
19
+
20
+ @IsOptional()
21
+ @Type(() => PaginationDto)
22
+ pagination: PaginationDto;
23
+ }
@@ -0,0 +1,16 @@
1
+ import { Column } from "typeorm";
2
+ import { LogDto } from "..";
3
+
4
+ export class BaseEntity {
5
+ // @Column({ type: 'int', update: false, select: false, insert: false })
6
+ log: LogDto
7
+
8
+ @Column({ type: 'int', default: 1, nullable: false })
9
+ statusId: number;
10
+
11
+ @Column({ type: 'varchar', length: 128, nullable: false, default: 'Add record' })
12
+ reasonStatus: string;
13
+
14
+ @Column({ type: 'timestamp', nullable: false, default: () => 'CURRENT_TIMESTAMP' })
15
+ dateStatus: Date;
16
+ }
@@ -0,0 +1,31 @@
1
+ import { BadRequestException, HttpStatus, Logger } from '@nestjs/common';
2
+ // import { nanoid } from 'src/core/tools';
3
+ import { BadRequestResult } from '../result/bad-request.result';
4
+ import { nanoid } from '../../tools';
5
+
6
+ export class AppBadRequestException extends BadRequestException {
7
+ constructor(message: string) {
8
+ super(message);
9
+ }
10
+
11
+ getResponse(): BadRequestResult {
12
+ const response = super.getResponse();
13
+ const loggerId = nanoid();
14
+ if (typeof response === 'string') {
15
+ Logger.log(`[${loggerId}]: ${response}`, 'AppBadRequestException');
16
+ return {
17
+ message: response,
18
+ error: 'Bad Request',
19
+ statusCode: HttpStatus.BAD_REQUEST,
20
+ loggerId: loggerId,
21
+ } as BadRequestResult;
22
+ }
23
+ // @ts-ignore: This line is to ignore the TypeScript error in response.message and response.error
24
+ const message = response.message ?? response.error;
25
+ Logger.log(`[${loggerId}]: ${message}`, 'AppBadRequestException');
26
+ return {
27
+ ...response,
28
+ loggerId: loggerId,
29
+ } as BadRequestResult;
30
+ }
31
+ }