@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
@@ -0,0 +1,230 @@
1
+ import { NestFactory } from '@nestjs/core'
2
+ import { Transport } from '@nestjs/microservices'
3
+ import { Logger as NestLogger, ParseArrayPipe, ParseIntPipe, PipeTransform } from '@nestjs/common'
4
+ import { Logger } from './core/logger/logger'
5
+ import { ConfigService } from './core/config/config.service'
6
+ import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'
7
+ import * as yaml from 'js-yaml'
8
+ import { readFileSync } from 'fs'
9
+ import path, { join } from 'path'
10
+ import { HeadersInterceptor, LoggingInterceptor } from './core/interceptors'
11
+ import { AllExceptionsFilter, AppValidationPipe } from './core/common'
12
+ import { CorsOptions } from '@nestjs/common/interfaces/external/cors-options.interface'
13
+ import { replaceEnvVars } from './core/tools'
14
+
15
+ interface AppConfig {
16
+ name: string
17
+ module: string
18
+ version: string
19
+ port: number
20
+ prefix: string
21
+ }
22
+
23
+ export async function bootstrap({
24
+ preHook,
25
+ postHook,
26
+ }: {
27
+ preHook?: (app: any, configService: ConfigService, logger: Logger) => Promise<void>
28
+ postHook?: (app: any, configService: ConfigService, logger: Logger) => Promise<void>
29
+ } = {}) {
30
+ let appModule: string = ''
31
+
32
+ try {
33
+ require('dotenv').config({ path: 'bootstrap.env' })
34
+ const configData = yaml.load(replaceEnvVars(readFileSync('bootstrap.yml', 'utf8'))) as Record<
35
+ string,
36
+ any
37
+ >
38
+ const configService = new ConfigService(configData)
39
+ const logstashUrl = configService.get<string>('logger.http.host') ?? ''
40
+ const appConfig = configService.get<AppConfig>('app')
41
+
42
+ const logger = new Logger(configService)
43
+ logger.setContext('Bootstrap')
44
+ const appModulePath = path.resolve(process.cwd(), appConfig?.module ?? '/app.module')
45
+ const { AppModule } = await import(appModulePath)
46
+
47
+ let app: any
48
+ try {
49
+ // app = await NestFactory.create(AppModule, { bufferLogs: true })
50
+ app = await NestFactory.create(AppModule)
51
+ } catch (createError: unknown) {
52
+ const createErr = createError as { message?: string; stack?: string; cause?: unknown }
53
+ console.error('Line: NestFactory.create(AppModule) failed')
54
+ console.error(`Create error message: ${createErr.message ?? 'unknown'}`)
55
+ console.error(`Create error stack: ${createErr.stack ?? 'no stack'}`)
56
+ if (createErr.cause) {
57
+ console.error(`Create error cause: ${String(createErr.cause)}`)
58
+ }
59
+ throw createError
60
+ }
61
+
62
+ Logger.setApplicationContext(app)
63
+ Logger.setLogstashUrl(logstashUrl)
64
+ logger.setContext('Bootstrap')
65
+ NestLogger.overrideLogger(logger)
66
+ Logger.log(`Loading app module from ${appModulePath}...`)
67
+
68
+ app.useLogger(logger)
69
+ const appPrefix = appConfig?.prefix ?? 'api'
70
+ app.setGlobalPrefix(appPrefix)
71
+ app.useGlobalInterceptors(new HeadersInterceptor())
72
+ app.useGlobalInterceptors(new LoggingInterceptor(configService))
73
+
74
+ useGlobalPipes(app, configService)
75
+ addSwagger(app, configService)
76
+ enableCors(app, configService)
77
+ useStaticAssets(app, configService)
78
+
79
+ const port = appConfig?.port ?? 3000
80
+
81
+ if (preHook) {
82
+ await preHook(app, configService, logger)
83
+ }
84
+
85
+ if (configService.get<Record<string, any>>('AMQP')) {
86
+ const amqpUrls = configService.get<string[]>('AMQP.urls') ?? []
87
+ const amqpQueue = configService.get<string>('AMQP.queue') ?? ''
88
+ app.connectMicroservice({
89
+ transport: Transport.RMQ,
90
+ options: {
91
+ urls: amqpUrls,
92
+ queue: amqpQueue,
93
+ prefetchCount: configService.get<number>('AMQP.prefetchCount') ?? 10,
94
+ isGlobalPrefetchCount: configService.get<boolean>('AMQP.isGlobalPrefetchCount') ?? false,
95
+ noAck: configService.get<boolean>('AMQP.noAck') ?? false,
96
+ queueOptions: {
97
+ durable: configService.get<boolean>('AMQP.queueOptions.durable'),
98
+ arguments: {
99
+ 'x-message-ttl': configService.get<number>('AMQP.queueOptions.arguments.x-message-ttl'),
100
+ 'x-dead-letter-exchange': configService.get<string>('AMQP.queueOptions.arguments.x-dead-letter-exchange'),
101
+ 'x-dead-letter-routing-key': configService.get<string>('AMQP.queueOptions.arguments.x-dead-letter-routing-key'),
102
+ }
103
+ },
104
+ persistent: configService.get<boolean>('AMQP.queueOptions.persistent') ?? true,
105
+ exchange: configService.get<string>('AMQP.queueOptions.exchange') ?? '',
106
+ exchangeType: configService.get<string>('AMQP.queueOptions.exchangeType') ?? 'direct',
107
+ wildcards: (configService.get<string>('AMQP.queueOptions.exchangeType') ?? '') == 'topic' ? configService.get<string>('AMQP.queueOptions.exchangeType') ?? true : false,
108
+ },
109
+ })
110
+ await app.startAllMicroservices();
111
+ logger.log(`Transport.RMQ: Connected to queue: ${amqpQueue} in ${maskUrlsCredentials(amqpUrls)}`, 'Bootstrap')
112
+ }
113
+ await app.listen(port)
114
+
115
+ if (postHook) {
116
+ await postHook(app, configService, logger)
117
+ }
118
+
119
+ const appUrl = (await app.getUrl()).replace('[::1]', 'localhost')
120
+ const swaggerPrefix = configService.get<string>('swagger.prefix') ?? '/swagger'
121
+ Logger.log(`Application is running on: ${appUrl}/${appPrefix}`, 'Bootstrap')
122
+ logger.log(`Swagger is running on: ${appUrl}/${swaggerPrefix}`, 'Bootstrap')
123
+ } catch (error: unknown) {
124
+ const err = error as { code?: string; stack?: string }
125
+
126
+ if (err.code === 'MODULE_NOT_FOUND') {
127
+ console.error(
128
+ `Error in the bootstrap method. Cannot find module ${appModule}\nStack trace: ${err.stack}`,
129
+ )
130
+ } else {
131
+ console.error(
132
+ `Error in the bootstrap method. Terminating the application.\nStack trace: ${err.stack}`,
133
+ )
134
+ }
135
+ console.error(`Error details: ${JSON.stringify(error)}`)
136
+ process.exit(1)
137
+ }
138
+ }
139
+
140
+ function maskUrlsCredentials(urls: string[]): string[] {
141
+ return urls.map((url) =>
142
+ url.replace(/\/\/([^:@/\s]+)(:([^@/\s]*))?@/g, (_, username: string, __: string, password: string) => {
143
+ const maskedUsername = '*'.repeat(username.length)
144
+ if (password !== undefined) {
145
+ return `//${maskedUsername}:${'*'.repeat(password.length)}@`
146
+ }
147
+ return `//${maskedUsername}@`
148
+ }),
149
+ )
150
+ }
151
+
152
+ async function addSwagger(app: any, configService: ConfigService) {
153
+ const swaggerConfig = configService.get('swagger')
154
+
155
+ if (swaggerConfig) {
156
+ Logger.log(`Swagger is enabled`, 'Bootstrap')
157
+ const config = new DocumentBuilder()
158
+ .setTitle(configService.get<string>('swagger.title') ?? 'Undefined title API')
159
+ .setDescription(
160
+ configService.get<string>('swagger.description') ?? 'Undefined description API',
161
+ )
162
+ .setVersion(configService.get<string>('swagger.version') ?? 'Undefined version API')
163
+ .build()
164
+
165
+ const documentFactory = () => SwaggerModule.createDocument(app, config)
166
+
167
+ SwaggerModule.setup(
168
+ configService.get<string>('swagger.basePath') ?? '/swagger',
169
+ app,
170
+ documentFactory,
171
+ {
172
+ swaggerOptions: {
173
+ tagsSorter: 'alpha', // Ordena los controladores alfabéticamente
174
+ },
175
+ },
176
+ )
177
+ } else {
178
+ Logger.log(`Swagger is disabled`, 'Bootstrap')
179
+ }
180
+ }
181
+
182
+ function useGlobalPipes(app: any, configService: ConfigService) {
183
+ const globalPipes: PipeTransform[] = []
184
+
185
+ const validationPipeOptions = configService.get('validationPipe')
186
+ if (validationPipeOptions) {
187
+ // exceptionFactory
188
+
189
+ globalPipes.push(new AppValidationPipe(validationPipeOptions))
190
+ Logger.log(`Using ValidationPipe in useGlobalPipes()`, 'Bootstrap')
191
+ }
192
+
193
+ const parseIntPipeOptions = configService.get('parseIntPipe')
194
+ if (parseIntPipeOptions) {
195
+ globalPipes.push(new ParseIntPipe(parseIntPipeOptions))
196
+ Logger.log(`Using ParseIntPipe in useGlobalPipes()`, 'Bootstrap')
197
+ }
198
+
199
+ const parseArrayPipeOptions = configService.get('parseArrayPipe')
200
+ if (parseArrayPipeOptions) {
201
+ globalPipes.push(new ParseArrayPipe(parseArrayPipeOptions))
202
+ Logger.log(`Using ParseArrayPipe in useGlobalPipes()`, 'Bootstrap')
203
+ }
204
+
205
+ if (globalPipes.length > 0) {
206
+ app.useGlobalPipes(...globalPipes)
207
+ Logger.log(`Global Pipes are enabled`, 'Bootstrap')
208
+ }
209
+ }
210
+
211
+ function enableCors(app: any, configService: ConfigService) {
212
+ const corsOptions = configService.get<CorsOptions>('cors')
213
+
214
+ if (corsOptions) {
215
+ Logger.log(`CORS has been enabled per the configured settings.`, 'Bootstrap')
216
+ app.enableCors(corsOptions)
217
+ } else {
218
+ Logger.warn(`CORS has not been configured.`, 'Bootstrap')
219
+ }
220
+ }
221
+
222
+ function useStaticAssets(app: any, configService: ConfigService) {
223
+ const staticAssetsConfig = configService.get<{ path?: string }>('staticAssets')
224
+ if (staticAssetsConfig) {
225
+ const configPath = staticAssetsConfig.path ?? './public'
226
+ const staticPath = join(process.cwd(), configPath)
227
+ app.useStaticAssets(staticPath)
228
+ Logger.warn(`Static assets are being served from path: ${configPath}`, 'Bootstrap')
229
+ }
230
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "declaration": true,
5
+ "outDir": "../../dist/libs/ms-sophia-framework-mysql"
6
+ },
7
+ "include": ["src/**/*"],
8
+ "exclude": ["node_modules", "dist", "test", "**/*spec.ts"]
9
+ }
package/nest-cli.json ADDED
@@ -0,0 +1,20 @@
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
+ },
9
+ "projects": {
10
+ "ms-sophia-framework-mysql": {
11
+ "type": "library",
12
+ "root": "libs/ms-sophia-framework-mysql",
13
+ "entryFile": "index",
14
+ "sourceRoot": "libs/ms-sophia-framework-mysql/src",
15
+ "compilerOptions": {
16
+ "tsConfigPath": "libs/ms-sophia-framework-mysql/tsconfig.lib.json"
17
+ }
18
+ }
19
+ }
20
+ }
package/package.json CHANGED
@@ -1,50 +1,31 @@
1
1
  {
2
2
  "name": "@jrosadob/ms-sophia-framework-mysql",
3
- "version": "0.0.1",
4
- "description": "Sophia Framework para microservicios en NestJS",
5
- "main": "dist/core/index.js",
6
- "files": [
7
- "dist"
8
- ],
9
- "peerDependencies": {
10
- "@nestjs/common": "^11.0.1"
11
- },
12
- "keywords": [
13
- "nest",
14
- "nestjs",
15
- "sophia",
16
- "framework",
17
- "microservices"
18
- ],
19
- "author": {
20
- "name": "Javier A. Rosado Baltazar",
21
- "email": "jrosadob@hotmail.com"
22
- },
23
- "publishConfig": {
24
- "access": "public"
25
- },
26
- "license": "MIT",
3
+ "version": "0.0.2",
4
+ "description": "",
5
+ "author": "",
6
+ "private": false,
7
+ "license": "UNLICENSED",
27
8
  "dependencies": {
28
9
  "@nestjs/common": "^11.0.1",
29
- "@nestjs/config": "^4.0.2",
10
+ "@nestjs/config": "^4.0.4",
30
11
  "@nestjs/core": "^11.0.1",
31
- "@nestjs/microservices": "^11.1.27",
12
+ "@nestjs/microservices": "^11.1.28",
32
13
  "@nestjs/platform-express": "^11.0.1",
33
- "@nestjs/swagger": "^11.2.0",
34
- "@nestjs/typeorm": "^11.0.0",
14
+ "@nestjs/swagger": "^11.4.6",
15
+ "@nestjs/typeorm": "^11.0.3",
35
16
  "amqp-connection-manager": "^5.0.0",
36
17
  "amqplib": "^2.0.1",
37
- "axios": "^1.12.2",
18
+ "axios": "^1.18.1",
38
19
  "class-transformer": "^0.5.1",
39
- "class-validator": "^0.14.2",
40
- "dotenv": "^17.2.3",
20
+ "class-validator": "^0.15.1",
21
+ "dotenv": "^17.4.2",
41
22
  "js": "^0.1.0",
42
- "js-yaml": "^4.1.0",
43
- "mysql2": "^3.14.5",
44
- "nanoid": "^5.1.5",
23
+ "js-yaml": "^5.2.2",
24
+ "mysql2": "^3.23.1",
25
+ "nanoid": "^6.0.0",
45
26
  "reflect-metadata": "^0.2.2",
46
27
  "rxjs": "^7.8.1",
47
- "typeorm": "^0.3.26"
28
+ "typeorm": "^1.1.0"
48
29
  },
49
30
  "devDependencies": {
50
31
  "@eslint/eslintrc": "^3.2.0",
@@ -54,12 +35,12 @@
54
35
  "@nestjs/testing": "^11.0.1",
55
36
  "@types/express": "^5.0.0",
56
37
  "@types/jest": "^30.0.0",
57
- "@types/node": "^22.10.7",
58
- "@types/supertest": "^6.0.2",
38
+ "@types/node": "^24.0.0",
39
+ "@types/supertest": "^7.0.0",
59
40
  "eslint": "^9.18.0",
60
41
  "eslint-config-prettier": "^10.0.1",
61
42
  "eslint-plugin-prettier": "^5.2.2",
62
- "globals": "^16.0.0",
43
+ "globals": "^17.0.0",
63
44
  "jest": "^30.0.0",
64
45
  "prettier": "^3.4.2",
65
46
  "source-map-support": "^0.5.21",
@@ -77,7 +58,7 @@
77
58
  "json",
78
59
  "ts"
79
60
  ],
80
- "rootDir": "src",
61
+ "rootDir": ".",
81
62
  "testRegex": ".*\\.spec\\.ts$",
82
63
  "transform": {
83
64
  "^.+\\.(t|j)s$": "ts-jest"
@@ -85,12 +66,19 @@
85
66
  "collectCoverageFrom": [
86
67
  "**/*.(t|j)s"
87
68
  ],
88
- "coverageDirectory": "../coverage",
89
- "testEnvironment": "node"
69
+ "coverageDirectory": "./coverage",
70
+ "testEnvironment": "node",
71
+ "roots": [
72
+ "<rootDir>/src/",
73
+ "<rootDir>/libs/"
74
+ ],
75
+ "moduleNameMapper": {
76
+ "^@sophia/ms-sophia-framework-mysql(|/.*)$": "<rootDir>/libs/ms-sophia-framework-mysql/src/$1"
77
+ }
90
78
  },
91
79
  "scripts": {
92
80
  "build": "nest build",
93
- "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
81
+ "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\" \"libs/**/*.ts\"",
94
82
  "start": "nest start",
95
83
  "start:dev": "nest start --watch",
96
84
  "start:debug": "nest start --debug --watch",
@@ -0,0 +1,3 @@
1
+ allowBuilds:
2
+ '@scarf/scarf': set this to true or false
3
+ unrs-resolver: set this to true or false
package/publish.sh ADDED
@@ -0,0 +1,18 @@
1
+ #!/bin/bash
2
+
3
+ # Requiere login
4
+ # npm login
5
+
6
+ # Version npm
7
+ # npm run build
8
+ # cd dist/
9
+ # npm publish
10
+ # cd ..
11
+
12
+ # Requiere login
13
+ # pnpm login
14
+
15
+ # Version pnpm
16
+ pnpm run build
17
+ pnpm publish --no-git-checks
18
+ cd ..
@@ -0,0 +1,22 @@
1
+ import { Test, TestingModule } from '@nestjs/testing';
2
+ import { AppController } from './app.controller';
3
+ import { AppService } from './app.service';
4
+
5
+ describe('AppController', () => {
6
+ let appController: AppController;
7
+
8
+ beforeEach(async () => {
9
+ const app: TestingModule = await Test.createTestingModule({
10
+ controllers: [AppController],
11
+ providers: [AppService],
12
+ }).compile();
13
+
14
+ appController = app.get<AppController>(AppController);
15
+ });
16
+
17
+ describe('root', () => {
18
+ it('should return "Hello World!"', () => {
19
+ expect(appController.getHello()).toBe('Hello World!');
20
+ });
21
+ });
22
+ });
@@ -0,0 +1,12 @@
1
+ import { Controller, Get } from '@nestjs/common';
2
+ import { AppService } from './app.service';
3
+
4
+ @Controller()
5
+ export class AppController {
6
+ constructor(private readonly appService: AppService) {}
7
+
8
+ @Get()
9
+ getHello(): string {
10
+ return this.appService.getHello();
11
+ }
12
+ }
@@ -0,0 +1,10 @@
1
+ import { Module } from '@nestjs/common';
2
+ import { AppController } from './app.controller';
3
+ import { AppService } from './app.service';
4
+
5
+ @Module({
6
+ imports: [],
7
+ controllers: [AppController],
8
+ providers: [AppService],
9
+ })
10
+ export class AppModule {}
@@ -0,0 +1,8 @@
1
+ import { Injectable } from '@nestjs/common';
2
+
3
+ @Injectable()
4
+ export class AppService {
5
+ getHello(): string {
6
+ return 'Hello World!';
7
+ }
8
+ }
package/src/main.ts ADDED
@@ -0,0 +1,8 @@
1
+ import { NestFactory } from '@nestjs/core';
2
+ import { AppModule } from './app.module';
3
+
4
+ async function bootstrap() {
5
+ const app = await NestFactory.create(AppModule);
6
+ await app.listen(process.env.PORT ?? 3000);
7
+ }
8
+ bootstrap();
@@ -0,0 +1,29 @@
1
+ import { Test, TestingModule } from '@nestjs/testing';
2
+ import { INestApplication } from '@nestjs/common';
3
+ import request from 'supertest';
4
+ import { App } from 'supertest/types';
5
+ import { AppModule } from './../src/app.module';
6
+
7
+ describe('AppController (e2e)', () => {
8
+ let app: INestApplication<App>;
9
+
10
+ beforeEach(async () => {
11
+ const moduleFixture: TestingModule = await Test.createTestingModule({
12
+ imports: [AppModule],
13
+ }).compile();
14
+
15
+ app = moduleFixture.createNestApplication();
16
+ await app.init();
17
+ });
18
+
19
+ it('/ (GET)', () => {
20
+ return request(app.getHttpServer())
21
+ .get('/')
22
+ .expect(200)
23
+ .expect('Hello World!');
24
+ });
25
+
26
+ afterEach(async () => {
27
+ await app.close();
28
+ });
29
+ });
@@ -0,0 +1,16 @@
1
+ {
2
+ "moduleFileExtensions": [
3
+ "js",
4
+ "json",
5
+ "ts"
6
+ ],
7
+ "rootDir": ".",
8
+ "testEnvironment": "node",
9
+ "testRegex": ".e2e-spec.ts$",
10
+ "transform": {
11
+ "^.+\\.(t|j)s$": "ts-jest"
12
+ },
13
+ "moduleNameMapper": {
14
+ "^@sophia/ms-sophia-framework-mysql(|/.*)$": "<rootDir>/../libs/ms-sophia-framework-mysql/src/$1"
15
+ }
16
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "exclude": ["node_modules", "test", "dist", "**/*spec.ts"]
4
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "compilerOptions": {
3
+ "module": "nodenext",
4
+ "moduleResolution": "nodenext",
5
+ "resolvePackageJsonExports": true,
6
+ "esModuleInterop": true,
7
+ "isolatedModules": true,
8
+ "declaration": true,
9
+ "removeComments": true,
10
+ "emitDecoratorMetadata": true,
11
+ "experimentalDecorators": true,
12
+ "allowSyntheticDefaultImports": true,
13
+ "target": "ES2023",
14
+ "sourceMap": true,
15
+ "outDir": "./dist",
16
+ "baseUrl": "./",
17
+ "incremental": true,
18
+ "skipLibCheck": true,
19
+ "strictNullChecks": true,
20
+ "forceConsistentCasingInFileNames": true,
21
+ "noImplicitAny": false,
22
+ "strictBindCallApply": false,
23
+ "noFallthroughCasesInSwitch": false,
24
+ // "paths": {
25
+ // "@sophia/ms-sophia-framework-mysql": [
26
+ // "libs/ms-sophia-framework-mysql/src"
27
+ // ],
28
+ // "@sophia/ms-sophia-framework-mysql/*": [
29
+ // "libs/ms-sophia-framework-mysql/src/*"
30
+ // ]
31
+ // }
32
+ }
33
+ }