From 568137f7557c7cd427f9e71ecc14114ddda16428 Mon Sep 17 00:00:00 2001 From: Thomas Dekiere Date: Sat, 28 Dec 2024 19:20:32 +0100 Subject: [PATCH 1/7] build: enable remix v3 feature flags --- apps/books-app/remix.config.js | 7 +++++++ apps/remix-app/.env.local | 1 - 2 files changed, 7 insertions(+), 1 deletion(-) delete mode 100644 apps/remix-app/.env.local diff --git a/apps/books-app/remix.config.js b/apps/books-app/remix.config.js index 9281bb9..e359d88 100644 --- a/apps/books-app/remix.config.js +++ b/apps/books-app/remix.config.js @@ -13,5 +13,12 @@ export default { // assetsBuildDirectory: "public/build", // serverBuildPath: "build/index.js", // publicPath: "/build/", + future: { + v3_fetcherPersist: true, + v3_lazyRouteDiscovery: true, + v3_relativeSplatPath: true, + v3_singleFetch: true, + v3_throwAbortReason: true, + }, watchPaths: () => createWatchPaths(__dirname), }; diff --git a/apps/remix-app/.env.local b/apps/remix-app/.env.local deleted file mode 100644 index 75f3b58..0000000 --- a/apps/remix-app/.env.local +++ /dev/null @@ -1 +0,0 @@ -API_URL=http://localhost:3000/api From bf7cca73719d59b1cbb8220024209a7f4c39924e Mon Sep 17 00:00:00 2001 From: Thomas Dekiere Date: Sun, 29 Dec 2024 19:23:23 +0100 Subject: [PATCH 2/7] feat: add custom nest logger service using pino --- apps/books-api/src/app/app.module.ts | 9 +- apps/books-api/src/main.ts | 2 + libs/nest-logger/.eslintrc.json | 18 +++ libs/nest-logger/README.md | 3 + libs/nest-logger/project.json | 9 ++ libs/nest-logger/src/index.ts | 3 + .../nest-logger/src/lib/nest-logger.module.ts | 22 +++ .../src/lib/nest-logger.service.ts | 108 ++++++++++++++ libs/nest-logger/src/lib/tokens.ts | 1 + libs/nest-logger/tsconfig.json | 18 +++ libs/nest-logger/tsconfig.lib.json | 15 ++ package-lock.json | 138 ++++++++++++++---- package.json | 3 + tsconfig.base.json | 1 + 14 files changed, 321 insertions(+), 29 deletions(-) create mode 100644 libs/nest-logger/.eslintrc.json create mode 100644 libs/nest-logger/README.md create mode 100644 libs/nest-logger/project.json create mode 100644 libs/nest-logger/src/index.ts create mode 100644 libs/nest-logger/src/lib/nest-logger.module.ts create mode 100644 libs/nest-logger/src/lib/nest-logger.service.ts create mode 100644 libs/nest-logger/src/lib/tokens.ts create mode 100644 libs/nest-logger/tsconfig.json create mode 100644 libs/nest-logger/tsconfig.lib.json diff --git a/apps/books-api/src/app/app.module.ts b/apps/books-api/src/app/app.module.ts index f389167..b63a0f8 100644 --- a/apps/books-api/src/app/app.module.ts +++ b/apps/books-api/src/app/app.module.ts @@ -3,9 +3,16 @@ import { Module } from '@nestjs/common'; import { AppController } from './app.controller'; import { AppService } from './app.service'; import { BooksModule } from '../books/books.module'; +import { NestLoggerModule } from '@nx-demo/nest-logger'; +import pino from 'pino'; @Module({ - imports: [BooksModule], + imports: [ + BooksModule, + NestLoggerModule.forRoot({ + pinoLogger: pino(), + }), + ], controllers: [AppController], providers: [AppService], }) diff --git a/apps/books-api/src/main.ts b/apps/books-api/src/main.ts index a124382..d128891 100644 --- a/apps/books-api/src/main.ts +++ b/apps/books-api/src/main.ts @@ -7,9 +7,11 @@ import { Logger } from '@nestjs/common'; import { NestFactory } from '@nestjs/core'; import { AppModule } from './app/app.module'; +import { NestPinoLogger } from '@nx-demo/nest-logger'; async function bootstrap() { const app = await NestFactory.create(AppModule); + app.useLogger(app.get(NestPinoLogger)); const globalPrefix = 'api'; app.setGlobalPrefix(globalPrefix); const port = process.env.PORT || 3000; diff --git a/libs/nest-logger/.eslintrc.json b/libs/nest-logger/.eslintrc.json new file mode 100644 index 0000000..9d9c0db --- /dev/null +++ b/libs/nest-logger/.eslintrc.json @@ -0,0 +1,18 @@ +{ + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], + "rules": {} + }, + { + "files": ["*.ts", "*.tsx"], + "rules": {} + }, + { + "files": ["*.js", "*.jsx"], + "rules": {} + } + ] +} diff --git a/libs/nest-logger/README.md b/libs/nest-logger/README.md new file mode 100644 index 0000000..bde7b3e --- /dev/null +++ b/libs/nest-logger/README.md @@ -0,0 +1,3 @@ +# nest-logger + +This library was generated with [Nx](https://nx.dev). diff --git a/libs/nest-logger/project.json b/libs/nest-logger/project.json new file mode 100644 index 0000000..f06dddc --- /dev/null +++ b/libs/nest-logger/project.json @@ -0,0 +1,9 @@ +{ + "name": "nest-logger", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "libs/nest-logger/src", + "projectType": "library", + "tags": [], + "// targets": "to see all targets run: nx show project nest-logger --web", + "targets": {} +} diff --git a/libs/nest-logger/src/index.ts b/libs/nest-logger/src/index.ts new file mode 100644 index 0000000..3f73729 --- /dev/null +++ b/libs/nest-logger/src/index.ts @@ -0,0 +1,3 @@ +export * from './lib/nest-logger.module'; +export * from './lib/nest-logger.service'; +export * from './lib/tokens'; diff --git a/libs/nest-logger/src/lib/nest-logger.module.ts b/libs/nest-logger/src/lib/nest-logger.module.ts new file mode 100644 index 0000000..5fb6691 --- /dev/null +++ b/libs/nest-logger/src/lib/nest-logger.module.ts @@ -0,0 +1,22 @@ +import { Global, Module } from '@nestjs/common'; +import { NestPinoLogger } from './nest-logger.service'; +import pino, { Logger } from 'pino'; +import { PINO_LOGGER_TOKEN } from './tokens'; + +@Global() +@Module({}) +export class NestLoggerModule { + static forRoot({ pinoLogger }: { pinoLogger?: Logger }) { + return { + module: NestLoggerModule, + providers: [ + { + provide: PINO_LOGGER_TOKEN, + useValue: pinoLogger ? pinoLogger : pino(), + }, + NestPinoLogger, + ], + exports: [NestPinoLogger, PINO_LOGGER_TOKEN], + }; + } +} diff --git a/libs/nest-logger/src/lib/nest-logger.service.ts b/libs/nest-logger/src/lib/nest-logger.service.ts new file mode 100644 index 0000000..b5a492f --- /dev/null +++ b/libs/nest-logger/src/lib/nest-logger.service.ts @@ -0,0 +1,108 @@ +import { LoggerService, Injectable, Inject } from '@nestjs/common'; +import { Logger } from 'pino'; +import { PINO_LOGGER_TOKEN } from './tokens'; + +/** + * Wraps the methods of nestjs LoggerService to use pino logger. + * All types and jsdoc comments are copied from the targetting pino methods. + */ +@Injectable() +export class NestPinoLogger implements LoggerService { + constructor(@Inject(PINO_LOGGER_TOKEN) private readonly logger: Logger) {} + + /** + * Log at `'info'` level the given msg. If the first argument is an object, all its properties will be included in the JSON line. + * If more args follows `msg`, these will be used to format `msg` using `util.format`. + * + * @typeParam T: the interface of the object being serialized. Default is object. + * @param obj: object to be serialized + * @param msg: the log message to write + * @param ...args: format string values when `msg` is a format string + */ + log(obj: T, msg?: string, ...args: any[]): void; + log(obj: unknown, msg?: string, ...args: any[]): void; + log(msg: string, ...args: any[]): void; + log(message: any, ...optionalParams: any[]) { + this.logger.info(message, ...optionalParams); + } + + /** + * Log at `'fatal'` level the given msg. If the first argument is an object, all its properties will be included in the JSON line. + * If more args follows `msg`, these will be used to format `msg` using `util.format`. + * + * @typeParam T: the interface of the object being serialized. Default is object. + * @param obj: object to be serialized + * @param msg: the log message to write + * @param ...args: format string values when `msg` is a format string + */ + fatal(obj: T, msg?: string, ...args: any[]): void; + fatal(obj: unknown, msg?: string, ...args: any[]): void; + fatal(msg: string, ...args: any[]): void; + fatal(message: any, ...optionalParams: any[]) { + this.logger.fatal(message, ...optionalParams); + } + + /** + * Log at `'error'` level the given msg. If the first argument is an object, all its properties will be included in the JSON line. + * If more args follows `msg`, these will be used to format `msg` using `util.format`. + * + * @typeParam T: the interface of the object being serialized. Default is object. + * @param obj: object to be serialized + * @param msg: the log message to write + * @param ...args: format string values when `msg` is a format string + */ + error(obj: T, msg?: string, ...args: any[]): void; + error(obj: unknown, msg?: string, ...args: any[]): void; + error(msg: string, ...args: any[]): void; + error(message: any, ...optionalParams: any[]) { + this.logger.error(message, ...optionalParams); + } + + /** + * Log at `'warn'` level the given msg. If the first argument is an object, all its properties will be included in the JSON line. + * If more args follows `msg`, these will be used to format `msg` using `util.format`. + * + * @typeParam T: the interface of the object being serialized. Default is object. + * @param obj: object to be serialized + * @param msg: the log message to write + * @param ...args: format string values when `msg` is a format string + */ + warn(obj: T, msg?: string, ...args: any[]): void; + warn(obj: unknown, msg?: string, ...args: any[]): void; + warn(msg: string, ...args: any[]): void; + warn(message: any, ...optionalParams: any[]) { + this.logger.warn(message, ...optionalParams); + } + + /** + * Log at `'debug'` level the given msg. If the first argument is an object, all its properties will be included in the JSON line. + * If more args follows `msg`, these will be used to format `msg` using `util.format`. + * + * @typeParam T: the interface of the object being serialized. Default is object. + * @param obj: object to be serialized + * @param msg: the log message to write + * @param ...args: format string values when `msg` is a format string + */ + debug(obj: T, msg?: string, ...args: any[]): void; + debug(obj: unknown, msg?: string, ...args: any[]): void; + debug(msg: string, ...args: any[]): void; + debug(message: any, ...optionalParams: any[]) { + this.logger.debug(message, ...optionalParams); + } + + /** + * Log at `'trace'` level the given msg. If the first argument is an object, all its properties will be included in the JSON line. + * If more args follows `msg`, these will be used to format `msg` using `util.format`. + * + * @typeParam T: the interface of the object being serialized. Default is object. + * @param obj: object to be serialized + * @param msg: the log message to write + * @param ...args: format string values when `msg` is a format string + */ + verbose(obj: T, msg?: string, ...args: any[]): void; + verbose(obj: unknown, msg?: string, ...args: any[]): void; + verbose(msg: string, ...args: any[]): void; + verbose(message: any, ...optionalParams: any[]) { + this.logger.trace(message, ...optionalParams); + } +} diff --git a/libs/nest-logger/src/lib/tokens.ts b/libs/nest-logger/src/lib/tokens.ts new file mode 100644 index 0000000..391757c --- /dev/null +++ b/libs/nest-logger/src/lib/tokens.ts @@ -0,0 +1 @@ +export const PINO_LOGGER_TOKEN = 'PinoLogger'; diff --git a/libs/nest-logger/tsconfig.json b/libs/nest-logger/tsconfig.json new file mode 100644 index 0000000..b8eadf3 --- /dev/null +++ b/libs/nest-logger/tsconfig.json @@ -0,0 +1,18 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "noPropertyAccessFromIndexSignature": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + } + ] +} diff --git a/libs/nest-logger/tsconfig.lib.json b/libs/nest-logger/tsconfig.lib.json new file mode 100644 index 0000000..0260985 --- /dev/null +++ b/libs/nest-logger/tsconfig.lib.json @@ -0,0 +1,15 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "declaration": true, + "types": ["node"], + "target": "es2021", + "strictNullChecks": true, + "noImplicitAny": true, + "strictBindCallApply": true, + "forceConsistentCasingInFileNames": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src/**/*.ts"] +} diff --git a/package-lock.json b/package-lock.json index ff4f59f..112e3b1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,6 +20,8 @@ "axios": "^1.6.0", "got": "^14.4.2", "isbot": "^4.4.0", + "lorem-ipsum": "^2.0.8", + "pino": "^9.6.0", "react": "^18.2.0", "react-dom": "^18.2.0", "reflect-metadata": "^0.1.13", @@ -70,6 +72,7 @@ "prettier": "^2.6.2", "ts-jest": "^29.1.0", "ts-node": "10.9.1", + "tslib": "^2.3.0", "typescript": "^5.7.2", "verdaccio": "^5.0.4", "vite": "^5.4.3", @@ -10760,6 +10763,53 @@ "url": "https://opencollective.com/verdaccio" } }, + "node_modules/@verdaccio/logger/node_modules/pino": { + "version": "8.17.2", + "resolved": "https://registry.npmjs.org/pino/-/pino-8.17.2.tgz", + "integrity": "sha512-LA6qKgeDMLr2ux2y/YiUt47EfgQ+S9LznBWOJdN3q1dx2sv0ziDLUBeVpyVv17TEcGCBuWf0zNtg3M5m1NhhWQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "atomic-sleep": "^1.0.0", + "fast-redact": "^3.1.1", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "v1.1.0", + "pino-std-serializers": "^6.0.0", + "process-warning": "^3.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^3.7.0", + "thread-stream": "^2.0.0" + }, + "bin": { + "pino": "bin.js" + } + }, + "node_modules/@verdaccio/logger/node_modules/pino-std-serializers": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.2.2.tgz", + "integrity": "sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@verdaccio/logger/node_modules/process-warning": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-3.0.0.tgz", + "integrity": "sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@verdaccio/logger/node_modules/thread-stream": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-2.7.0.tgz", + "integrity": "sha512-qQiRWsU/wvNolI6tbbCKd9iKaTnCXsTwVxhhKM6nctPdujTyztjlbUkUTUymidWcMnZ5pWR0ej4a0tjsW021vw==", + "dev": true, + "license": "MIT", + "dependencies": { + "real-require": "^0.2.0" + } + }, "node_modules/@verdaccio/middleware": { "version": "7.0.0-next-7.20", "resolved": "https://registry.npmjs.org/@verdaccio/middleware/-/middleware-7.0.0-next-7.20.tgz", @@ -12139,7 +12189,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=8.0.0" @@ -17030,7 +17079,6 @@ "version": "3.5.0", "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.5.0.tgz", "integrity": "sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -21248,6 +21296,31 @@ "loose-envify": "cli.js" } }, + "node_modules/lorem-ipsum": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/lorem-ipsum/-/lorem-ipsum-2.0.8.tgz", + "integrity": "sha512-5RIwHuCb979RASgCJH0VKERn9cQo/+NcAi2BMe9ddj+gp7hujl6BI+qdOG4nVsLDpwWEJwTVYXNKP6BGgbcoGA==", + "license": "ISC", + "dependencies": { + "commander": "^9.3.0" + }, + "bin": { + "lorem-ipsum": "dist/bin/lorem-ipsum.bin.js" + }, + "engines": { + "node": ">= 8.x", + "npm": ">= 5.x" + } + }, + "node_modules/lorem-ipsum/node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || >=14" + } + }, "node_modules/loupe": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", @@ -23435,7 +23508,6 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", - "dev": true, "license": "MIT", "engines": { "node": ">=14.0.0" @@ -23949,23 +24021,22 @@ } }, "node_modules/pino": { - "version": "8.17.2", - "resolved": "https://registry.npmjs.org/pino/-/pino-8.17.2.tgz", - "integrity": "sha512-LA6qKgeDMLr2ux2y/YiUt47EfgQ+S9LznBWOJdN3q1dx2sv0ziDLUBeVpyVv17TEcGCBuWf0zNtg3M5m1NhhWQ==", - "dev": true, + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-9.6.0.tgz", + "integrity": "sha512-i85pKRCt4qMjZ1+L7sy2Ag4t1atFcdbEt76+7iRJn1g2BvsnRMGu9p8pivl9fs63M2kF/A0OacFZhTub+m/qMg==", "license": "MIT", "dependencies": { "atomic-sleep": "^1.0.0", "fast-redact": "^3.1.1", "on-exit-leak-free": "^2.1.0", - "pino-abstract-transport": "v1.1.0", - "pino-std-serializers": "^6.0.0", - "process-warning": "^3.0.0", + "pino-abstract-transport": "^2.0.0", + "pino-std-serializers": "^7.0.0", + "process-warning": "^4.0.0", "quick-format-unescaped": "^4.0.3", "real-require": "^0.2.0", "safe-stable-stringify": "^2.3.1", - "sonic-boom": "^3.7.0", - "thread-stream": "^2.0.0" + "sonic-boom": "^4.0.1", + "thread-stream": "^3.0.0" }, "bin": { "pino": "bin.js" @@ -24025,19 +24096,35 @@ } }, "node_modules/pino-std-serializers": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.2.2.tgz", - "integrity": "sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==", - "dev": true, + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz", + "integrity": "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==", "license": "MIT" }, + "node_modules/pino/node_modules/pino-abstract-transport": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz", + "integrity": "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==", + "license": "MIT", + "dependencies": { + "split2": "^4.0.0" + } + }, "node_modules/pino/node_modules/process-warning": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-3.0.0.tgz", - "integrity": "sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==", - "dev": true, + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-4.0.0.tgz", + "integrity": "sha512-/MyYDxttz7DfGMMHiysAsFE4qF+pQYAA8ziO/3NcRVrQ5fSk+Mns4QZA/oRPFzvcqNoVJXQNWNAsdwBXLUkQKw==", "license": "MIT" }, + "node_modules/pino/node_modules/sonic-boom": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.0.tgz", + "integrity": "sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==", + "license": "MIT", + "dependencies": { + "atomic-sleep": "^1.0.0" + } + }, "node_modules/pirates": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", @@ -25261,7 +25348,6 @@ "version": "4.0.4", "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==", - "dev": true, "license": "MIT" }, "node_modules/quick-lru": { @@ -25478,7 +25564,6 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 12.13.0" @@ -26175,7 +26260,6 @@ "version": "2.5.0", "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", - "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -26895,7 +26979,6 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", - "dev": true, "license": "ISC", "engines": { "node": ">= 10.x" @@ -27924,10 +28007,9 @@ } }, "node_modules/thread-stream": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-2.7.0.tgz", - "integrity": "sha512-qQiRWsU/wvNolI6tbbCKd9iKaTnCXsTwVxhhKM6nctPdujTyztjlbUkUTUymidWcMnZ5pWR0ej4a0tjsW021vw==", - "dev": true, + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.1.0.tgz", + "integrity": "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==", "license": "MIT", "dependencies": { "real-require": "^0.2.0" diff --git a/package.json b/package.json index 39137ae..f75d5f4 100644 --- a/package.json +++ b/package.json @@ -57,6 +57,7 @@ "prettier": "^2.6.2", "ts-jest": "^29.1.0", "ts-node": "10.9.1", + "tslib": "^2.3.0", "typescript": "^5.7.2", "verdaccio": "^5.0.4", "vite": "^5.4.3", @@ -78,6 +79,8 @@ "axios": "^1.6.0", "got": "^14.4.2", "isbot": "^4.4.0", + "lorem-ipsum": "^2.0.8", + "pino": "^9.6.0", "react": "^18.2.0", "react-dom": "^18.2.0", "reflect-metadata": "^0.1.13", diff --git a/tsconfig.base.json b/tsconfig.base.json index 20362c6..ab171aa 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -15,6 +15,7 @@ "skipDefaultLibCheck": true, "baseUrl": ".", "paths": { + "@nx-demo/nest-logger": ["libs/nest-logger/src/index.ts"], "@thdk/books-api-client": ["libs/books-api-client/src/index.ts"], "@thdk/books-api-contracts/schemas": [ "libs/books-api-contracts/src/schemas.ts" From 3c489556838de671de49ffdf58fc5a8e0cda00ea Mon Sep 17 00:00:00 2001 From: Thomas Dekiere Date: Sun, 29 Dec 2024 19:44:22 +0100 Subject: [PATCH 3/7] feat: add summary to book response --- .github/workflows/ci.yml | 18 ++++----- apps/books-api/src/books/books.controller.ts | 20 +++------- apps/books-api/src/books/books.module.ts | 17 +++++++++ apps/books-api/src/books/books.service.ts | 36 ++++++++++++++++++ apps/books-api/src/books/tokens.ts | 1 + .../src/lib/books/get-books.schema.ts | 1 + .../src/lib/books/get-books.spec.ts | 1 + libs/lorem-book-summarizer/.eslintrc.json | 30 +++++++++++++++ libs/lorem-book-summarizer/README.md | 11 ++++++ libs/lorem-book-summarizer/jest.config.ts | 10 +++++ libs/lorem-book-summarizer/package.json | 13 +++++++ libs/lorem-book-summarizer/project.json | 19 ++++++++++ libs/lorem-book-summarizer/src/index.ts | 1 + .../src/lib/lorem-book-summarizer.spec.ts | 18 +++++++++ .../src/lib/lorem-book-summarizer.ts | 38 +++++++++++++++++++ libs/lorem-book-summarizer/tsconfig.json | 21 ++++++++++ libs/lorem-book-summarizer/tsconfig.lib.json | 10 +++++ libs/lorem-book-summarizer/tsconfig.spec.json | 15 ++++++++ nx.json | 5 +++ tsconfig.base.json | 3 ++ 20 files changed, 264 insertions(+), 24 deletions(-) create mode 100644 apps/books-api/src/books/books.service.ts create mode 100644 apps/books-api/src/books/tokens.ts create mode 100644 libs/lorem-book-summarizer/.eslintrc.json create mode 100644 libs/lorem-book-summarizer/README.md create mode 100644 libs/lorem-book-summarizer/jest.config.ts create mode 100644 libs/lorem-book-summarizer/package.json create mode 100644 libs/lorem-book-summarizer/project.json create mode 100644 libs/lorem-book-summarizer/src/index.ts create mode 100644 libs/lorem-book-summarizer/src/lib/lorem-book-summarizer.spec.ts create mode 100644 libs/lorem-book-summarizer/src/lib/lorem-book-summarizer.ts create mode 100644 libs/lorem-book-summarizer/tsconfig.json create mode 100644 libs/lorem-book-summarizer/tsconfig.lib.json create mode 100644 libs/lorem-book-summarizer/tsconfig.spec.json diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c52267a..57955de 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -54,19 +54,17 @@ jobs: THDK_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | if [[ "${{ steps.git.outputs.branch-name }}" == "main" ]]; then - npx nx release --skip-publish --verbose + npx nx release \ + --skip-publish \ + --verbose else - npx nx release version --preid ${{ steps.git.outputs.commit-sha-short }} --no-git-commit --no-git-tag --verbose + npx nx release version \ + --preid ${{ steps.git.outputs.commit-sha-short }} \ + --no-git-commit \ + --no-git-tag \ + --verbose fi - - name: Push version bumps, tags and changelogs - if: ${{ steps.git.outputs.branch-name == 'main' }} - run: | - git push - git push --tags - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Publish run: | npx nx release publish --yes --verbose diff --git a/apps/books-api/src/books/books.controller.ts b/apps/books-api/src/books/books.controller.ts index 10558db..bc5322e 100644 --- a/apps/books-api/src/books/books.controller.ts +++ b/apps/books-api/src/books/books.controller.ts @@ -1,24 +1,16 @@ -import { Controller, Get, UseInterceptors } from '@nestjs/common'; +import { Controller, Get, Logger, UseInterceptors } from '@nestjs/common'; import { ZodResponseValidationInterceptor } from '../validation/zod-response-validation-interceptor'; import { getBooksSchema } from '@thdk/books-api-contracts/schemas'; +import { BooksService } from './books.service'; @Controller('books') export class BooksController { + constructor(private readonly booksService: BooksService) {} + @Get() @UseInterceptors(new ZodResponseValidationInterceptor(getBooksSchema)) async books() { - return [ - { id: 1, title: 'The Great Gatsby' }, - { id: 2, title: 'The Catcher in the Rye' }, - { id: 3, title: 'To Kill a Mockingbird' }, - { id: 4, title: '1984' }, - { id: 5, title: 'The Lord of the Rings' }, - { id: 6, title: 'Pride and Prejudice' }, - { id: 7, title: 'The Book Thief' }, - { id: 8, title: 'Harry Potter' }, - { id: 9, title: 'The Hobbit' }, - { id: 10, title: 'The Chronicles of Narnia' }, - { id: 11, title: 'The Hunger Games' }, - ]; + Logger.log('Getting books'); + return this.booksService.getBooks(); } } diff --git a/apps/books-api/src/books/books.module.ts b/apps/books-api/src/books/books.module.ts index 99a4483..4bb5b71 100644 --- a/apps/books-api/src/books/books.module.ts +++ b/apps/books-api/src/books/books.module.ts @@ -1,7 +1,24 @@ import { Module } from '@nestjs/common'; import { BooksController } from './books.controller'; +import { summerizeBook } from '@nx-demo/lorem-book-summarizer'; +import { PINO_LOGGER_TOKEN } from '@nx-demo/nest-logger'; +import { Logger } from 'pino'; +import { BOOK_SUMMARIZER_TOKEN } from './tokens'; +import { BooksService } from './books.service'; @Module({ controllers: [BooksController], + providers: [ + BooksService, + { + provide: BOOK_SUMMARIZER_TOKEN, + useFactory: (logger: Logger) => { + return (data: { title: string; author: string }) => { + return summerizeBook(data, { logger }); + }; + }, + inject: [{ token: PINO_LOGGER_TOKEN, optional: false }], + }, + ], }) export class BooksModule {} diff --git a/apps/books-api/src/books/books.service.ts b/apps/books-api/src/books/books.service.ts new file mode 100644 index 0000000..07c79bc --- /dev/null +++ b/apps/books-api/src/books/books.service.ts @@ -0,0 +1,36 @@ +import { Inject } from '@nestjs/common'; +import { BOOK_SUMMARIZER_TOKEN } from './tokens'; + +export type BookSummarizerFunction = (data: { + title: string; + author: string; +}) => string; + +export class BooksService { + constructor( + @Inject(BOOK_SUMMARIZER_TOKEN) + private readonly bookSummarizer: BookSummarizerFunction + ) {} + + getBooks() { + return [ + { id: 1, title: 'The Great Gatsby' }, + { id: 2, title: 'The Catcher in the Rye' }, + { id: 3, title: 'To Kill a Mockingbird' }, + { id: 4, title: '1984' }, + { id: 5, title: 'The Lord of the Rings' }, + { id: 6, title: 'Pride and Prejudice' }, + { id: 7, title: 'The Book Thief' }, + { id: 8, title: 'Harry Potter' }, + { id: 9, title: 'The Hobbit' }, + { id: 10, title: 'The Chronicles of Narnia' }, + { id: 11, title: 'The Hunger Games' }, + ].map((book) => ({ + ...book, + summary: this.bookSummarizer({ + title: book.title, + author: 'Unknown', + }), + })); + } +} diff --git a/apps/books-api/src/books/tokens.ts b/apps/books-api/src/books/tokens.ts new file mode 100644 index 0000000..f7ebb3a --- /dev/null +++ b/apps/books-api/src/books/tokens.ts @@ -0,0 +1 @@ +export const BOOK_SUMMARIZER_TOKEN = 'BookSummarizer'; diff --git a/libs/books-api-contracts/src/lib/books/get-books.schema.ts b/libs/books-api-contracts/src/lib/books/get-books.schema.ts index ec1be47..ea2cf80 100644 --- a/libs/books-api-contracts/src/lib/books/get-books.schema.ts +++ b/libs/books-api-contracts/src/lib/books/get-books.schema.ts @@ -4,5 +4,6 @@ export const getBooksSchema = z.array( z.object({ title: z.string(), id: z.number(), + summary: z.string(), }) ); diff --git a/libs/books-api-contracts/src/lib/books/get-books.spec.ts b/libs/books-api-contracts/src/lib/books/get-books.spec.ts index e9017ea..92e3e05 100644 --- a/libs/books-api-contracts/src/lib/books/get-books.spec.ts +++ b/libs/books-api-contracts/src/lib/books/get-books.spec.ts @@ -7,6 +7,7 @@ describe('getBooksSchema', () => { { id: 1, title: 'The Great Gatsby', + summary: 'A book by F. Scott Fitzgerald', }, ]; diff --git a/libs/lorem-book-summarizer/.eslintrc.json b/libs/lorem-book-summarizer/.eslintrc.json new file mode 100644 index 0000000..703b92b --- /dev/null +++ b/libs/lorem-book-summarizer/.eslintrc.json @@ -0,0 +1,30 @@ +{ + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], + "rules": {} + }, + { + "files": ["*.ts", "*.tsx"], + "rules": {} + }, + { + "files": ["*.js", "*.jsx"], + "rules": {} + }, + { + "files": ["*.json"], + "parser": "jsonc-eslint-parser", + "rules": { + "@nx/dependency-checks": [ + "error", + { + "ignoredFiles": ["{projectRoot}/eslint.config.{js,cjs,mjs}"] + } + ] + } + } + ] +} diff --git a/libs/lorem-book-summarizer/README.md b/libs/lorem-book-summarizer/README.md new file mode 100644 index 0000000..3f9b12a --- /dev/null +++ b/libs/lorem-book-summarizer/README.md @@ -0,0 +1,11 @@ +# lorem-book-summarizer + +This library was generated with [Nx](https://nx.dev). + +## Building + +Run `nx build lorem-book-summarizer` to build the library. + +## Running unit tests + +Run `nx test lorem-book-summarizer` to execute the unit tests via [Jest](https://jestjs.io). diff --git a/libs/lorem-book-summarizer/jest.config.ts b/libs/lorem-book-summarizer/jest.config.ts new file mode 100644 index 0000000..4dcc90c --- /dev/null +++ b/libs/lorem-book-summarizer/jest.config.ts @@ -0,0 +1,10 @@ +export default { + displayName: 'lorem-book-summarizer', + preset: '../../jest.preset.js', + testEnvironment: 'node', + transform: { + '^.+\\.[tj]s$': ['ts-jest', { tsconfig: '/tsconfig.spec.json' }], + }, + moduleFileExtensions: ['ts', 'js', 'html'], + coverageDirectory: '../../coverage/libs/lorem-book-summarizer', +}; diff --git a/libs/lorem-book-summarizer/package.json b/libs/lorem-book-summarizer/package.json new file mode 100644 index 0000000..fce1d52 --- /dev/null +++ b/libs/lorem-book-summarizer/package.json @@ -0,0 +1,13 @@ +{ + "name": "@nx-demo/lorem-book-summarizer", + "version": "0.0.1", + "dependencies": { + "tslib": "^2.3.0", + "lorem-ipsum": "^2.0.8", + "pino": "^9.6.0" + }, + "type": "commonjs", + "main": "./src/index.js", + "typings": "./src/index.d.ts", + "private": true +} diff --git a/libs/lorem-book-summarizer/project.json b/libs/lorem-book-summarizer/project.json new file mode 100644 index 0000000..6c15003 --- /dev/null +++ b/libs/lorem-book-summarizer/project.json @@ -0,0 +1,19 @@ +{ + "name": "lorem-book-summarizer", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "libs/lorem-book-summarizer/src", + "projectType": "library", + "tags": [], + "targets": { + "build": { + "executor": "@nx/js:tsc", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/libs/lorem-book-summarizer", + "main": "libs/lorem-book-summarizer/src/index.ts", + "tsConfig": "libs/lorem-book-summarizer/tsconfig.lib.json", + "assets": ["libs/lorem-book-summarizer/*.md"] + } + } + } +} diff --git a/libs/lorem-book-summarizer/src/index.ts b/libs/lorem-book-summarizer/src/index.ts new file mode 100644 index 0000000..bea773b --- /dev/null +++ b/libs/lorem-book-summarizer/src/index.ts @@ -0,0 +1 @@ +export * from './lib/lorem-book-summarizer'; diff --git a/libs/lorem-book-summarizer/src/lib/lorem-book-summarizer.spec.ts b/libs/lorem-book-summarizer/src/lib/lorem-book-summarizer.spec.ts new file mode 100644 index 0000000..65b6a1f --- /dev/null +++ b/libs/lorem-book-summarizer/src/lib/lorem-book-summarizer.spec.ts @@ -0,0 +1,18 @@ +import pino from 'pino'; +import { summerizeBook } from './lorem-book-summarizer'; + +describe('summarizeBook', () => { + it('should add a generated summary', () => { + expect( + summerizeBook( + { + author: 'F. Scott Fitzgerald', + title: 'The Great Gatsby', + }, + { + logger: pino({ level: 'silent' }), + } + ) + ).toEqual(expect.any(String)); + }); +}); diff --git a/libs/lorem-book-summarizer/src/lib/lorem-book-summarizer.ts b/libs/lorem-book-summarizer/src/lib/lorem-book-summarizer.ts new file mode 100644 index 0000000..eda3123 --- /dev/null +++ b/libs/lorem-book-summarizer/src/lib/lorem-book-summarizer.ts @@ -0,0 +1,38 @@ +import { LoremIpsum } from 'lorem-ipsum'; +import Pino from 'pino'; + +export function summerizeBook( + { + title, + author, + }: { + readonly title: string; + readonly author: string; + }, + { + logger, + }: { + logger: Pino.Logger; + } +): string { + logger.info( + { + title, + author, + }, + 'Summarizing book' + ); + + const lorem = new LoremIpsum({ + sentencesPerParagraph: { + max: 8, + min: 4, + }, + wordsPerSentence: { + max: 16, + min: 4, + }, + }); + + return lorem.generateParagraphs(3); +} diff --git a/libs/lorem-book-summarizer/tsconfig.json b/libs/lorem-book-summarizer/tsconfig.json new file mode 100644 index 0000000..0fce068 --- /dev/null +++ b/libs/lorem-book-summarizer/tsconfig.json @@ -0,0 +1,21 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "noPropertyAccessFromIndexSignature": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ] +} diff --git a/libs/lorem-book-summarizer/tsconfig.lib.json b/libs/lorem-book-summarizer/tsconfig.lib.json new file mode 100644 index 0000000..33eca2c --- /dev/null +++ b/libs/lorem-book-summarizer/tsconfig.lib.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "declaration": true, + "types": ["node"] + }, + "include": ["src/**/*.ts"], + "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"] +} diff --git a/libs/lorem-book-summarizer/tsconfig.spec.json b/libs/lorem-book-summarizer/tsconfig.spec.json new file mode 100644 index 0000000..0d3c604 --- /dev/null +++ b/libs/lorem-book-summarizer/tsconfig.spec.json @@ -0,0 +1,15 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "moduleResolution": "node10", + "types": ["jest", "node"] + }, + "include": [ + "jest.config.ts", + "src/**/*.test.ts", + "src/**/*.spec.ts", + "src/**/*.d.ts" + ] +} diff --git a/nx.json b/nx.json index 69a28f6..24767f0 100644 --- a/nx.json +++ b/nx.json @@ -75,6 +75,11 @@ "cache": true, "dependsOn": ["^build"], "inputs": ["production", "^production"] + }, + "@nx/js:tsc": { + "cache": true, + "dependsOn": ["^build"], + "inputs": ["production", "^production"] } }, "release": { diff --git a/tsconfig.base.json b/tsconfig.base.json index ab171aa..0f6f6a7 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -15,6 +15,9 @@ "skipDefaultLibCheck": true, "baseUrl": ".", "paths": { + "@nx-demo/lorem-book-summarizer": [ + "libs/lorem-book-summarizer/src/index.ts" + ], "@nx-demo/nest-logger": ["libs/nest-logger/src/index.ts"], "@thdk/books-api-client": ["libs/books-api-client/src/index.ts"], "@thdk/books-api-contracts/schemas": [ From 6ba9cbf851933416479f787df9437e836f3e8b2a Mon Sep 17 00:00:00 2001 From: Thomas Dekiere Date: Sun, 29 Dec 2024 20:14:40 +0100 Subject: [PATCH 4/7] feat: prepare serverless version of books-api --- apps/books-api-serverless/.eslintrc.json | 18 +++++++++ apps/books-api-serverless/project.json | 38 +++++++++++++++++++ .../src/app/app.controller.spec.ts | 21 ++++++++++ .../src/app/app.controller.ts | 12 ++++++ .../src/app/app.module.ts | 10 +++++ .../src/app/app.service.spec.ts | 20 ++++++++++ .../src/app/app.service.ts | 8 ++++ apps/books-api-serverless/src/assets/.gitkeep | 0 apps/books-api-serverless/src/main.ts | 21 ++++++++++ apps/books-api-serverless/tsconfig.app.json | 11 ++++++ apps/books-api-serverless/tsconfig.json | 13 +++++++ apps/books-api-serverless/webpack.config.js | 20 ++++++++++ nx.json | 5 ++- 13 files changed, 196 insertions(+), 1 deletion(-) create mode 100644 apps/books-api-serverless/.eslintrc.json create mode 100644 apps/books-api-serverless/project.json create mode 100644 apps/books-api-serverless/src/app/app.controller.spec.ts create mode 100644 apps/books-api-serverless/src/app/app.controller.ts create mode 100644 apps/books-api-serverless/src/app/app.module.ts create mode 100644 apps/books-api-serverless/src/app/app.service.spec.ts create mode 100644 apps/books-api-serverless/src/app/app.service.ts create mode 100644 apps/books-api-serverless/src/assets/.gitkeep create mode 100644 apps/books-api-serverless/src/main.ts create mode 100644 apps/books-api-serverless/tsconfig.app.json create mode 100644 apps/books-api-serverless/tsconfig.json create mode 100644 apps/books-api-serverless/webpack.config.js diff --git a/apps/books-api-serverless/.eslintrc.json b/apps/books-api-serverless/.eslintrc.json new file mode 100644 index 0000000..9d9c0db --- /dev/null +++ b/apps/books-api-serverless/.eslintrc.json @@ -0,0 +1,18 @@ +{ + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], + "rules": {} + }, + { + "files": ["*.ts", "*.tsx"], + "rules": {} + }, + { + "files": ["*.js", "*.jsx"], + "rules": {} + } + ] +} diff --git a/apps/books-api-serverless/project.json b/apps/books-api-serverless/project.json new file mode 100644 index 0000000..d7db733 --- /dev/null +++ b/apps/books-api-serverless/project.json @@ -0,0 +1,38 @@ +{ + "name": "books-api-serverless", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "apps/books-api-serverless/src", + "projectType": "application", + "tags": [], + "targets": { + "build": { + "executor": "nx:run-commands", + "options": { + "command": "webpack-cli build", + "args": ["node-env=production"] + }, + "configurations": { + "development": { + "args": ["node-env=development"] + } + } + }, + "serve": { + "executor": "@nx/js:node", + "defaultConfiguration": "development", + "dependsOn": ["build"], + "options": { + "buildTarget": "books-api-serverless:build", + "runBuildTargetDependencies": false + }, + "configurations": { + "development": { + "buildTarget": "books-api-serverless:build:development" + }, + "production": { + "buildTarget": "books-api-serverless:build:production" + } + } + } + } +} diff --git a/apps/books-api-serverless/src/app/app.controller.spec.ts b/apps/books-api-serverless/src/app/app.controller.spec.ts new file mode 100644 index 0000000..f27e3af --- /dev/null +++ b/apps/books-api-serverless/src/app/app.controller.spec.ts @@ -0,0 +1,21 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { AppController } from './app.controller'; +import { AppService } from './app.service'; + +describe('AppController', () => { + let app: TestingModule; + + beforeAll(async () => { + app = await Test.createTestingModule({ + controllers: [AppController], + providers: [AppService], + }).compile(); + }); + + describe('getData', () => { + it('should return "Hello API"', () => { + const appController = app.get(AppController); + expect(appController.getData()).toEqual({ message: 'Hello API' }); + }); + }); +}); diff --git a/apps/books-api-serverless/src/app/app.controller.ts b/apps/books-api-serverless/src/app/app.controller.ts new file mode 100644 index 0000000..aa4a3dd --- /dev/null +++ b/apps/books-api-serverless/src/app/app.controller.ts @@ -0,0 +1,12 @@ +import { Controller, Get } from '@nestjs/common'; +import { AppService } from './app.service'; + +@Controller() +export class AppController { + constructor(private readonly appService: AppService) {} + + @Get() + getData() { + return this.appService.getData(); + } +} diff --git a/apps/books-api-serverless/src/app/app.module.ts b/apps/books-api-serverless/src/app/app.module.ts new file mode 100644 index 0000000..8662803 --- /dev/null +++ b/apps/books-api-serverless/src/app/app.module.ts @@ -0,0 +1,10 @@ +import { Module } from '@nestjs/common'; +import { AppController } from './app.controller'; +import { AppService } from './app.service'; + +@Module({ + imports: [], + controllers: [AppController], + providers: [AppService], +}) +export class AppModule {} diff --git a/apps/books-api-serverless/src/app/app.service.spec.ts b/apps/books-api-serverless/src/app/app.service.spec.ts new file mode 100644 index 0000000..99d5d8c --- /dev/null +++ b/apps/books-api-serverless/src/app/app.service.spec.ts @@ -0,0 +1,20 @@ +import { Test } from '@nestjs/testing'; +import { AppService } from './app.service'; + +describe('AppService', () => { + let service: AppService; + + beforeAll(async () => { + const app = await Test.createTestingModule({ + providers: [AppService], + }).compile(); + + service = app.get(AppService); + }); + + describe('getData', () => { + it('should return "Hello API"', () => { + expect(service.getData()).toEqual({ message: 'Hello API' }); + }); + }); +}); diff --git a/apps/books-api-serverless/src/app/app.service.ts b/apps/books-api-serverless/src/app/app.service.ts new file mode 100644 index 0000000..cd8cede --- /dev/null +++ b/apps/books-api-serverless/src/app/app.service.ts @@ -0,0 +1,8 @@ +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class AppService { + getData(): { message: string } { + return { message: 'Hello API' }; + } +} diff --git a/apps/books-api-serverless/src/assets/.gitkeep b/apps/books-api-serverless/src/assets/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/apps/books-api-serverless/src/main.ts b/apps/books-api-serverless/src/main.ts new file mode 100644 index 0000000..ee84ced --- /dev/null +++ b/apps/books-api-serverless/src/main.ts @@ -0,0 +1,21 @@ +/** + * This is not a production server yet! + * This is only a minimal backend to get started. + */ + +import { Logger } from '@nestjs/common'; +import { NestFactory } from '@nestjs/core'; +import { AppModule } from './app/app.module'; + +async function bootstrap() { + const app = await NestFactory.create(AppModule); + const globalPrefix = 'api'; + app.setGlobalPrefix(globalPrefix); + const port = process.env.PORT || 3000; + await app.listen(port); + Logger.log( + `🚀 Application is running on: http://localhost:${port}/${globalPrefix}` + ); +} + +bootstrap(); diff --git a/apps/books-api-serverless/tsconfig.app.json b/apps/books-api-serverless/tsconfig.app.json new file mode 100644 index 0000000..0f89060 --- /dev/null +++ b/apps/books-api-serverless/tsconfig.app.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["node"], + "emitDecoratorMetadata": true, + "target": "es2021" + }, + "include": ["src/**/*.ts"] +} diff --git a/apps/books-api-serverless/tsconfig.json b/apps/books-api-serverless/tsconfig.json new file mode 100644 index 0000000..3685ac7 --- /dev/null +++ b/apps/books-api-serverless/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.app.json" + } + ], + "compilerOptions": { + "esModuleInterop": true + } +} diff --git a/apps/books-api-serverless/webpack.config.js b/apps/books-api-serverless/webpack.config.js new file mode 100644 index 0000000..0cbd715 --- /dev/null +++ b/apps/books-api-serverless/webpack.config.js @@ -0,0 +1,20 @@ +const { NxAppWebpackPlugin } = require('@nx/webpack/app-plugin'); +const { join } = require('path'); + +module.exports = { + output: { + path: join(__dirname, '../../dist/apps/books-api-serverless'), + }, + plugins: [ + new NxAppWebpackPlugin({ + target: 'node', + compiler: 'tsc', + main: './src/main.ts', + tsConfig: './tsconfig.app.json', + assets: ['./src/assets'], + optimization: false, + outputHashing: 'none', + generatePackageJson: true, + }), + ], +}; diff --git a/nx.json b/nx.json index 24767f0..fb62d94 100644 --- a/nx.json +++ b/nx.json @@ -59,7 +59,10 @@ "options": { "targetName": "test" }, - "exclude": ["apps/books-api-e2e/**/*"] + "exclude": [ + "apps/books-api-e2e/**/*", + "apps/books-api-serverless-e2e/**/*" + ] } ], "targetDefaults": { From 739d7dfcd435741b0c4ef5622bebeeb69b24782e Mon Sep 17 00:00:00 2001 From: Thomas Dekiere Date: Mon, 30 Dec 2024 09:21:23 +0100 Subject: [PATCH 5/7] refactor: create nest-bootstrap module lib --- apps/books-api-serverless/project.json | 38 ------- .../src/app/app.controller.spec.ts | 21 ---- .../src/app/app.controller.ts | 12 --- .../src/app/app.module.ts | 10 -- .../src/app/app.service.spec.ts | 20 ---- apps/books-api-serverless/src/assets/.gitkeep | 0 apps/books-api-serverless/src/main.ts | 21 ---- apps/books-api-serverless/tsconfig.app.json | 11 --- apps/books-api-serverless/tsconfig.json | 13 --- apps/books-api-serverless/webpack.config.js | 20 ---- apps/books-api/src/app/app.service.ts | 8 -- apps/books-api/src/main.ts | 28 +----- .../books-api-lib}/.eslintrc.json | 0 libs/books-api-lib/README.md | 7 ++ .../books-api-lib}/jest.config.ts | 5 +- libs/books-api-lib/project.json | 9 ++ libs/books-api-lib/src/index.ts | 4 + .../src/lib}/app/app.controller.spec.ts | 0 .../src/lib}/app/app.controller.ts | 0 .../books-api-lib/src/lib}/app/app.module.ts | 10 +- .../src/lib}/app/app.service.spec.ts | 0 .../books-api-lib/src/lib}/app/app.service.ts | 0 .../src/lib/books-api-lib.module.ts | 8 ++ .../src/lib}/books/books.controller.ts | 0 .../src/lib}/books/books.module.ts | 0 .../src/lib}/books/books.service.ts | 0 .../books-api-lib/src/lib}/books/tokens.ts | 0 .../src/lib}/pipes/zod-validation-pipe.ts | 0 .../zod-response-validation-interceptor.ts | 0 libs/books-api-lib/tsconfig.json | 21 ++++ libs/books-api-lib/tsconfig.lib.json | 16 +++ .../books-api-lib}/tsconfig.spec.json | 2 + libs/nest-bootstrap/.eslintrc.json | 18 ++++ libs/nest-bootstrap/README.md | 3 + libs/nest-bootstrap/project.json | 9 ++ libs/nest-bootstrap/src/index.ts | 2 + .../src/lib/bootstrap.module.ts | 17 ++++ libs/nest-bootstrap/src/lib/nest-bootstrap.ts | 26 +++++ libs/nest-bootstrap/tsconfig.json | 19 ++++ libs/nest-bootstrap/tsconfig.lib.json | 15 +++ package-lock.json | 98 +++++++++++++++++++ package.json | 1 + tsconfig.base.json | 2 + 43 files changed, 286 insertions(+), 208 deletions(-) delete mode 100644 apps/books-api-serverless/project.json delete mode 100644 apps/books-api-serverless/src/app/app.controller.spec.ts delete mode 100644 apps/books-api-serverless/src/app/app.controller.ts delete mode 100644 apps/books-api-serverless/src/app/app.module.ts delete mode 100644 apps/books-api-serverless/src/app/app.service.spec.ts delete mode 100644 apps/books-api-serverless/src/assets/.gitkeep delete mode 100644 apps/books-api-serverless/src/main.ts delete mode 100644 apps/books-api-serverless/tsconfig.app.json delete mode 100644 apps/books-api-serverless/tsconfig.json delete mode 100644 apps/books-api-serverless/webpack.config.js delete mode 100644 apps/books-api/src/app/app.service.ts rename {apps/books-api-serverless => libs/books-api-lib}/.eslintrc.json (100%) create mode 100644 libs/books-api-lib/README.md rename {apps/books-api => libs/books-api-lib}/jest.config.ts (68%) create mode 100644 libs/books-api-lib/project.json create mode 100644 libs/books-api-lib/src/index.ts rename {apps/books-api/src => libs/books-api-lib/src/lib}/app/app.controller.spec.ts (100%) rename {apps/books-api/src => libs/books-api-lib/src/lib}/app/app.controller.ts (100%) rename {apps/books-api/src => libs/books-api-lib/src/lib}/app/app.module.ts (61%) rename {apps/books-api/src => libs/books-api-lib/src/lib}/app/app.service.spec.ts (100%) rename {apps/books-api-serverless/src => libs/books-api-lib/src/lib}/app/app.service.ts (100%) create mode 100644 libs/books-api-lib/src/lib/books-api-lib.module.ts rename {apps/books-api/src => libs/books-api-lib/src/lib}/books/books.controller.ts (100%) rename {apps/books-api/src => libs/books-api-lib/src/lib}/books/books.module.ts (100%) rename {apps/books-api/src => libs/books-api-lib/src/lib}/books/books.service.ts (100%) rename {apps/books-api/src => libs/books-api-lib/src/lib}/books/tokens.ts (100%) rename {apps/books-api/src => libs/books-api-lib/src/lib}/pipes/zod-validation-pipe.ts (100%) rename {apps/books-api/src => libs/books-api-lib/src/lib}/validation/zod-response-validation-interceptor.ts (100%) create mode 100644 libs/books-api-lib/tsconfig.json create mode 100644 libs/books-api-lib/tsconfig.lib.json rename {apps/books-api => libs/books-api-lib}/tsconfig.spec.json (79%) create mode 100644 libs/nest-bootstrap/.eslintrc.json create mode 100644 libs/nest-bootstrap/README.md create mode 100644 libs/nest-bootstrap/project.json create mode 100644 libs/nest-bootstrap/src/index.ts create mode 100644 libs/nest-bootstrap/src/lib/bootstrap.module.ts create mode 100644 libs/nest-bootstrap/src/lib/nest-bootstrap.ts create mode 100644 libs/nest-bootstrap/tsconfig.json create mode 100644 libs/nest-bootstrap/tsconfig.lib.json diff --git a/apps/books-api-serverless/project.json b/apps/books-api-serverless/project.json deleted file mode 100644 index d7db733..0000000 --- a/apps/books-api-serverless/project.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "name": "books-api-serverless", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "sourceRoot": "apps/books-api-serverless/src", - "projectType": "application", - "tags": [], - "targets": { - "build": { - "executor": "nx:run-commands", - "options": { - "command": "webpack-cli build", - "args": ["node-env=production"] - }, - "configurations": { - "development": { - "args": ["node-env=development"] - } - } - }, - "serve": { - "executor": "@nx/js:node", - "defaultConfiguration": "development", - "dependsOn": ["build"], - "options": { - "buildTarget": "books-api-serverless:build", - "runBuildTargetDependencies": false - }, - "configurations": { - "development": { - "buildTarget": "books-api-serverless:build:development" - }, - "production": { - "buildTarget": "books-api-serverless:build:production" - } - } - } - } -} diff --git a/apps/books-api-serverless/src/app/app.controller.spec.ts b/apps/books-api-serverless/src/app/app.controller.spec.ts deleted file mode 100644 index f27e3af..0000000 --- a/apps/books-api-serverless/src/app/app.controller.spec.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { AppController } from './app.controller'; -import { AppService } from './app.service'; - -describe('AppController', () => { - let app: TestingModule; - - beforeAll(async () => { - app = await Test.createTestingModule({ - controllers: [AppController], - providers: [AppService], - }).compile(); - }); - - describe('getData', () => { - it('should return "Hello API"', () => { - const appController = app.get(AppController); - expect(appController.getData()).toEqual({ message: 'Hello API' }); - }); - }); -}); diff --git a/apps/books-api-serverless/src/app/app.controller.ts b/apps/books-api-serverless/src/app/app.controller.ts deleted file mode 100644 index aa4a3dd..0000000 --- a/apps/books-api-serverless/src/app/app.controller.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Controller, Get } from '@nestjs/common'; -import { AppService } from './app.service'; - -@Controller() -export class AppController { - constructor(private readonly appService: AppService) {} - - @Get() - getData() { - return this.appService.getData(); - } -} diff --git a/apps/books-api-serverless/src/app/app.module.ts b/apps/books-api-serverless/src/app/app.module.ts deleted file mode 100644 index 8662803..0000000 --- a/apps/books-api-serverless/src/app/app.module.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Module } from '@nestjs/common'; -import { AppController } from './app.controller'; -import { AppService } from './app.service'; - -@Module({ - imports: [], - controllers: [AppController], - providers: [AppService], -}) -export class AppModule {} diff --git a/apps/books-api-serverless/src/app/app.service.spec.ts b/apps/books-api-serverless/src/app/app.service.spec.ts deleted file mode 100644 index 99d5d8c..0000000 --- a/apps/books-api-serverless/src/app/app.service.spec.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Test } from '@nestjs/testing'; -import { AppService } from './app.service'; - -describe('AppService', () => { - let service: AppService; - - beforeAll(async () => { - const app = await Test.createTestingModule({ - providers: [AppService], - }).compile(); - - service = app.get(AppService); - }); - - describe('getData', () => { - it('should return "Hello API"', () => { - expect(service.getData()).toEqual({ message: 'Hello API' }); - }); - }); -}); diff --git a/apps/books-api-serverless/src/assets/.gitkeep b/apps/books-api-serverless/src/assets/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/apps/books-api-serverless/src/main.ts b/apps/books-api-serverless/src/main.ts deleted file mode 100644 index ee84ced..0000000 --- a/apps/books-api-serverless/src/main.ts +++ /dev/null @@ -1,21 +0,0 @@ -/** - * This is not a production server yet! - * This is only a minimal backend to get started. - */ - -import { Logger } from '@nestjs/common'; -import { NestFactory } from '@nestjs/core'; -import { AppModule } from './app/app.module'; - -async function bootstrap() { - const app = await NestFactory.create(AppModule); - const globalPrefix = 'api'; - app.setGlobalPrefix(globalPrefix); - const port = process.env.PORT || 3000; - await app.listen(port); - Logger.log( - `🚀 Application is running on: http://localhost:${port}/${globalPrefix}` - ); -} - -bootstrap(); diff --git a/apps/books-api-serverless/tsconfig.app.json b/apps/books-api-serverless/tsconfig.app.json deleted file mode 100644 index 0f89060..0000000 --- a/apps/books-api-serverless/tsconfig.app.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["node"], - "emitDecoratorMetadata": true, - "target": "es2021" - }, - "include": ["src/**/*.ts"] -} diff --git a/apps/books-api-serverless/tsconfig.json b/apps/books-api-serverless/tsconfig.json deleted file mode 100644 index 3685ac7..0000000 --- a/apps/books-api-serverless/tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.app.json" - } - ], - "compilerOptions": { - "esModuleInterop": true - } -} diff --git a/apps/books-api-serverless/webpack.config.js b/apps/books-api-serverless/webpack.config.js deleted file mode 100644 index 0cbd715..0000000 --- a/apps/books-api-serverless/webpack.config.js +++ /dev/null @@ -1,20 +0,0 @@ -const { NxAppWebpackPlugin } = require('@nx/webpack/app-plugin'); -const { join } = require('path'); - -module.exports = { - output: { - path: join(__dirname, '../../dist/apps/books-api-serverless'), - }, - plugins: [ - new NxAppWebpackPlugin({ - target: 'node', - compiler: 'tsc', - main: './src/main.ts', - tsConfig: './tsconfig.app.json', - assets: ['./src/assets'], - optimization: false, - outputHashing: 'none', - generatePackageJson: true, - }), - ], -}; diff --git a/apps/books-api/src/app/app.service.ts b/apps/books-api/src/app/app.service.ts deleted file mode 100644 index cd8cede..0000000 --- a/apps/books-api/src/app/app.service.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { Injectable } from '@nestjs/common'; - -@Injectable() -export class AppService { - getData(): { message: string } { - return { message: 'Hello API' }; - } -} diff --git a/apps/books-api/src/main.ts b/apps/books-api/src/main.ts index d128891..09b856b 100644 --- a/apps/books-api/src/main.ts +++ b/apps/books-api/src/main.ts @@ -1,24 +1,6 @@ -/** - * This is not a production server yet! - * This is only a minimal backend to get started. - */ +import { bootstrap } from '@nx-demo/nest-bootstrap'; +import { AppModule } from '@nx-demo/books-api-lib'; -import { Logger } from '@nestjs/common'; -import { NestFactory } from '@nestjs/core'; - -import { AppModule } from './app/app.module'; -import { NestPinoLogger } from '@nx-demo/nest-logger'; - -async function bootstrap() { - const app = await NestFactory.create(AppModule); - app.useLogger(app.get(NestPinoLogger)); - const globalPrefix = 'api'; - app.setGlobalPrefix(globalPrefix); - const port = process.env.PORT || 3000; - await app.listen(port); - Logger.log( - `🚀 Application is running on: http://localhost:${port}/${globalPrefix}` - ); -} - -bootstrap(); +bootstrap(AppModule, { + globalPrefix: 'api', +}); diff --git a/apps/books-api-serverless/.eslintrc.json b/libs/books-api-lib/.eslintrc.json similarity index 100% rename from apps/books-api-serverless/.eslintrc.json rename to libs/books-api-lib/.eslintrc.json diff --git a/libs/books-api-lib/README.md b/libs/books-api-lib/README.md new file mode 100644 index 0000000..5cf677f --- /dev/null +++ b/libs/books-api-lib/README.md @@ -0,0 +1,7 @@ +# books-api-lib + +This library was generated with [Nx](https://nx.dev). + +## Running unit tests + +Run `nx test books-api-lib` to execute the unit tests via [Jest](https://jestjs.io). diff --git a/apps/books-api/jest.config.ts b/libs/books-api-lib/jest.config.ts similarity index 68% rename from apps/books-api/jest.config.ts rename to libs/books-api-lib/jest.config.ts index 7f37015..26e7005 100644 --- a/apps/books-api/jest.config.ts +++ b/libs/books-api-lib/jest.config.ts @@ -1,11 +1,10 @@ -/* eslint-disable */ export default { - displayName: 'books-api', + displayName: 'books-api-lib', preset: '../../jest.preset.js', testEnvironment: 'node', transform: { '^.+\\.[tj]s$': ['ts-jest', { tsconfig: '/tsconfig.spec.json' }], }, moduleFileExtensions: ['ts', 'js', 'html'], - coverageDirectory: '../../coverage/apps/books-api', + coverageDirectory: '../../coverage/libs/books-api-lib', }; diff --git a/libs/books-api-lib/project.json b/libs/books-api-lib/project.json new file mode 100644 index 0000000..a83f51f --- /dev/null +++ b/libs/books-api-lib/project.json @@ -0,0 +1,9 @@ +{ + "name": "books-api-lib", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "libs/books-api-lib/src", + "projectType": "library", + "tags": [], + "// targets": "to see all targets run: nx show project books-api-lib --web", + "targets": {} +} diff --git a/libs/books-api-lib/src/index.ts b/libs/books-api-lib/src/index.ts new file mode 100644 index 0000000..754770b --- /dev/null +++ b/libs/books-api-lib/src/index.ts @@ -0,0 +1,4 @@ +export * from './lib/app/app.module'; +export * from './lib/app/app.service'; +export * from './lib/pipes/zod-validation-pipe'; +export * from './lib/validation/zod-response-validation-interceptor'; diff --git a/apps/books-api/src/app/app.controller.spec.ts b/libs/books-api-lib/src/lib/app/app.controller.spec.ts similarity index 100% rename from apps/books-api/src/app/app.controller.spec.ts rename to libs/books-api-lib/src/lib/app/app.controller.spec.ts diff --git a/apps/books-api/src/app/app.controller.ts b/libs/books-api-lib/src/lib/app/app.controller.ts similarity index 100% rename from apps/books-api/src/app/app.controller.ts rename to libs/books-api-lib/src/lib/app/app.controller.ts diff --git a/apps/books-api/src/app/app.module.ts b/libs/books-api-lib/src/lib/app/app.module.ts similarity index 61% rename from apps/books-api/src/app/app.module.ts rename to libs/books-api-lib/src/lib/app/app.module.ts index b63a0f8..f6c3371 100644 --- a/apps/books-api/src/app/app.module.ts +++ b/libs/books-api-lib/src/lib/app/app.module.ts @@ -3,16 +3,10 @@ import { Module } from '@nestjs/common'; import { AppController } from './app.controller'; import { AppService } from './app.service'; import { BooksModule } from '../books/books.module'; -import { NestLoggerModule } from '@nx-demo/nest-logger'; -import pino from 'pino'; +import { BootstrapModule } from '@nx-demo/nest-bootstrap'; @Module({ - imports: [ - BooksModule, - NestLoggerModule.forRoot({ - pinoLogger: pino(), - }), - ], + imports: [BooksModule, BootstrapModule.forRoot()], controllers: [AppController], providers: [AppService], }) diff --git a/apps/books-api/src/app/app.service.spec.ts b/libs/books-api-lib/src/lib/app/app.service.spec.ts similarity index 100% rename from apps/books-api/src/app/app.service.spec.ts rename to libs/books-api-lib/src/lib/app/app.service.spec.ts diff --git a/apps/books-api-serverless/src/app/app.service.ts b/libs/books-api-lib/src/lib/app/app.service.ts similarity index 100% rename from apps/books-api-serverless/src/app/app.service.ts rename to libs/books-api-lib/src/lib/app/app.service.ts diff --git a/libs/books-api-lib/src/lib/books-api-lib.module.ts b/libs/books-api-lib/src/lib/books-api-lib.module.ts new file mode 100644 index 0000000..5bbe173 --- /dev/null +++ b/libs/books-api-lib/src/lib/books-api-lib.module.ts @@ -0,0 +1,8 @@ +import { Module } from '@nestjs/common'; + +@Module({ + controllers: [], + providers: [], + exports: [], +}) +export class BooksApiLibModule {} diff --git a/apps/books-api/src/books/books.controller.ts b/libs/books-api-lib/src/lib/books/books.controller.ts similarity index 100% rename from apps/books-api/src/books/books.controller.ts rename to libs/books-api-lib/src/lib/books/books.controller.ts diff --git a/apps/books-api/src/books/books.module.ts b/libs/books-api-lib/src/lib/books/books.module.ts similarity index 100% rename from apps/books-api/src/books/books.module.ts rename to libs/books-api-lib/src/lib/books/books.module.ts diff --git a/apps/books-api/src/books/books.service.ts b/libs/books-api-lib/src/lib/books/books.service.ts similarity index 100% rename from apps/books-api/src/books/books.service.ts rename to libs/books-api-lib/src/lib/books/books.service.ts diff --git a/apps/books-api/src/books/tokens.ts b/libs/books-api-lib/src/lib/books/tokens.ts similarity index 100% rename from apps/books-api/src/books/tokens.ts rename to libs/books-api-lib/src/lib/books/tokens.ts diff --git a/apps/books-api/src/pipes/zod-validation-pipe.ts b/libs/books-api-lib/src/lib/pipes/zod-validation-pipe.ts similarity index 100% rename from apps/books-api/src/pipes/zod-validation-pipe.ts rename to libs/books-api-lib/src/lib/pipes/zod-validation-pipe.ts diff --git a/apps/books-api/src/validation/zod-response-validation-interceptor.ts b/libs/books-api-lib/src/lib/validation/zod-response-validation-interceptor.ts similarity index 100% rename from apps/books-api/src/validation/zod-response-validation-interceptor.ts rename to libs/books-api-lib/src/lib/validation/zod-response-validation-interceptor.ts diff --git a/libs/books-api-lib/tsconfig.json b/libs/books-api-lib/tsconfig.json new file mode 100644 index 0000000..0fce068 --- /dev/null +++ b/libs/books-api-lib/tsconfig.json @@ -0,0 +1,21 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "noPropertyAccessFromIndexSignature": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ] +} diff --git a/libs/books-api-lib/tsconfig.lib.json b/libs/books-api-lib/tsconfig.lib.json new file mode 100644 index 0000000..c297a24 --- /dev/null +++ b/libs/books-api-lib/tsconfig.lib.json @@ -0,0 +1,16 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "declaration": true, + "types": ["node"], + "target": "es2021", + "strictNullChecks": true, + "noImplicitAny": true, + "strictBindCallApply": true, + "forceConsistentCasingInFileNames": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src/**/*.ts"], + "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"] +} diff --git a/apps/books-api/tsconfig.spec.json b/libs/books-api-lib/tsconfig.spec.json similarity index 79% rename from apps/books-api/tsconfig.spec.json rename to libs/books-api-lib/tsconfig.spec.json index d41aea4..0d3c604 100644 --- a/apps/books-api/tsconfig.spec.json +++ b/libs/books-api-lib/tsconfig.spec.json @@ -2,6 +2,8 @@ "extends": "./tsconfig.json", "compilerOptions": { "outDir": "../../dist/out-tsc", + "module": "commonjs", + "moduleResolution": "node10", "types": ["jest", "node"] }, "include": [ diff --git a/libs/nest-bootstrap/.eslintrc.json b/libs/nest-bootstrap/.eslintrc.json new file mode 100644 index 0000000..9d9c0db --- /dev/null +++ b/libs/nest-bootstrap/.eslintrc.json @@ -0,0 +1,18 @@ +{ + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], + "rules": {} + }, + { + "files": ["*.ts", "*.tsx"], + "rules": {} + }, + { + "files": ["*.js", "*.jsx"], + "rules": {} + } + ] +} diff --git a/libs/nest-bootstrap/README.md b/libs/nest-bootstrap/README.md new file mode 100644 index 0000000..4a74496 --- /dev/null +++ b/libs/nest-bootstrap/README.md @@ -0,0 +1,3 @@ +# nest-bootstrap + +This library was generated with [Nx](https://nx.dev). diff --git a/libs/nest-bootstrap/project.json b/libs/nest-bootstrap/project.json new file mode 100644 index 0000000..3068842 --- /dev/null +++ b/libs/nest-bootstrap/project.json @@ -0,0 +1,9 @@ +{ + "name": "nest-bootstrap", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "libs/nest-bootstrap/src", + "projectType": "library", + "tags": [], + "// targets": "to see all targets run: nx show project nest-bootstrap --web", + "targets": {} +} diff --git a/libs/nest-bootstrap/src/index.ts b/libs/nest-bootstrap/src/index.ts new file mode 100644 index 0000000..a8c2963 --- /dev/null +++ b/libs/nest-bootstrap/src/index.ts @@ -0,0 +1,2 @@ +export * from './lib/nest-bootstrap'; +export * from './lib/bootstrap.module'; diff --git a/libs/nest-bootstrap/src/lib/bootstrap.module.ts b/libs/nest-bootstrap/src/lib/bootstrap.module.ts new file mode 100644 index 0000000..ed251e6 --- /dev/null +++ b/libs/nest-bootstrap/src/lib/bootstrap.module.ts @@ -0,0 +1,17 @@ +import { Module } from '@nestjs/common'; +import { NestLoggerModule } from '@nx-demo/nest-logger'; +import pino from 'pino'; + +@Module({}) +export class BootstrapModule { + static forRoot({ pinoOptions }: { pinoOptions?: pino.LoggerOptions } = {}) { + return { + module: BootstrapModule, + imports: [ + NestLoggerModule.forRoot({ + pinoLogger: pino(pinoOptions), + }), + ], + }; + } +} diff --git a/libs/nest-bootstrap/src/lib/nest-bootstrap.ts b/libs/nest-bootstrap/src/lib/nest-bootstrap.ts new file mode 100644 index 0000000..61575a5 --- /dev/null +++ b/libs/nest-bootstrap/src/lib/nest-bootstrap.ts @@ -0,0 +1,26 @@ +import { Logger } from '@nestjs/common'; +import { NestFactory } from '@nestjs/core'; +import { NestPinoLogger } from '@nx-demo/nest-logger'; + +export async function bootstrap( + module: unknown, + { + globalPrefix, + port = process.env['PORT'] ? Number(process.env['PORT']) : 3000, + }: { + globalPrefix?: string; + port?: number; + } = {} +) { + const app = await NestFactory.create(module); + app.useLogger(app.get(NestPinoLogger)); + + if (globalPrefix !== undefined) { + app.setGlobalPrefix(globalPrefix); + } + await app.listen(port); + + Logger.log( + `🚀 Application is running on: http://localhost:${port}/${globalPrefix}` + ); +} diff --git a/libs/nest-bootstrap/tsconfig.json b/libs/nest-bootstrap/tsconfig.json new file mode 100644 index 0000000..2820e89 --- /dev/null +++ b/libs/nest-bootstrap/tsconfig.json @@ -0,0 +1,19 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "module": "commonjs", + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "noPropertyAccessFromIndexSignature": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + } + ] +} diff --git a/libs/nest-bootstrap/tsconfig.lib.json b/libs/nest-bootstrap/tsconfig.lib.json new file mode 100644 index 0000000..0260985 --- /dev/null +++ b/libs/nest-bootstrap/tsconfig.lib.json @@ -0,0 +1,15 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "declaration": true, + "types": ["node"], + "target": "es2021", + "strictNullChecks": true, + "noImplicitAny": true, + "strictBindCallApply": true, + "forceConsistentCasingInFileNames": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src/**/*.ts"] +} diff --git a/package-lock.json b/package-lock.json index 112e3b1..d7d1f37 100644 --- a/package-lock.json +++ b/package-lock.json @@ -69,6 +69,7 @@ "jest-environment-node": "^29.7.0", "jsdom": "~22.1.0", "nx": "20.3.0", + "pino-pretty": "^13.0.0", "prettier": "^2.6.2", "ts-jest": "^29.1.0", "ts-node": "10.9.1", @@ -14630,6 +14631,16 @@ "node": ">=4.0" } }, + "node_modules/dateformat": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", + "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, "node_modules/dayjs": { "version": "1.11.10", "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", @@ -17034,6 +17045,13 @@ ], "license": "MIT" }, + "node_modules/fast-copy": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.2.tgz", + "integrity": "sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==", + "dev": true, + "license": "MIT" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -18252,6 +18270,13 @@ "he": "bin/he" } }, + "node_modules/help-me": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", + "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==", + "dev": true, + "license": "MIT" + }, "node_modules/homedir-polyfill": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", @@ -20462,6 +20487,16 @@ "dev": true, "license": "MIT" }, + "node_modules/joycon": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", + "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -24095,6 +24130,62 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/pino-pretty": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-13.0.0.tgz", + "integrity": "sha512-cQBBIVG3YajgoUjo1FdKVRX6t9XPxwB9lcNJVD5GCnNM4Y6T12YYx8c6zEejxQsU0wrg9TwmDulcE9LR7qcJqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "colorette": "^2.0.7", + "dateformat": "^4.6.3", + "fast-copy": "^3.0.2", + "fast-safe-stringify": "^2.1.1", + "help-me": "^5.0.0", + "joycon": "^3.1.1", + "minimist": "^1.2.6", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^2.0.0", + "pump": "^3.0.0", + "secure-json-parse": "^2.4.0", + "sonic-boom": "^4.0.1", + "strip-json-comments": "^3.1.1" + }, + "bin": { + "pino-pretty": "bin.js" + } + }, + "node_modules/pino-pretty/node_modules/pino-abstract-transport": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz", + "integrity": "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "split2": "^4.0.0" + } + }, + "node_modules/pino-pretty/node_modules/pump": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", + "dev": true, + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/pino-pretty/node_modules/sonic-boom": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.0.tgz", + "integrity": "sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==", + "dev": true, + "license": "MIT", + "dependencies": { + "atomic-sleep": "^1.0.0" + } + }, "node_modules/pino-std-serializers": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz", @@ -26383,6 +26474,13 @@ "dev": true, "license": "MIT" }, + "node_modules/secure-json-parse": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", + "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==", + "dev": true, + "license": "BSD-3-Clause" + }, "node_modules/select-hose": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", diff --git a/package.json b/package.json index f75d5f4..f5f5911 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,7 @@ "jest-environment-node": "^29.7.0", "jsdom": "~22.1.0", "nx": "20.3.0", + "pino-pretty": "^13.0.0", "prettier": "^2.6.2", "ts-jest": "^29.1.0", "ts-node": "10.9.1", diff --git a/tsconfig.base.json b/tsconfig.base.json index 0f6f6a7..f35f255 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -15,9 +15,11 @@ "skipDefaultLibCheck": true, "baseUrl": ".", "paths": { + "@nx-demo/books-api-lib": ["libs/books-api-lib/src/index.ts"], "@nx-demo/lorem-book-summarizer": [ "libs/lorem-book-summarizer/src/index.ts" ], + "@nx-demo/nest-bootstrap": ["libs/nest-bootstrap/src/index.ts"], "@nx-demo/nest-logger": ["libs/nest-logger/src/index.ts"], "@thdk/books-api-client": ["libs/books-api-client/src/index.ts"], "@thdk/books-api-contracts/schemas": [ From 49d5caafa3ef29ad856e4673a6670837d035a583 Mon Sep 17 00:00:00 2001 From: Thomas Dekiere Date: Mon, 30 Dec 2024 09:34:39 +0100 Subject: [PATCH 6/7] build: use nx db cache instead of file system cache --- nx.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/nx.json b/nx.json index fb62d94..2647c7f 100644 --- a/nx.json +++ b/nx.json @@ -150,6 +150,5 @@ } } }, - "nxCloudAccessToken": "NzY1ODc3OWUtNzg4OS00NzNkLTliNmMtZTRhY2I3NjEzNjU0fHJlYWQtd3JpdGU=", - "useLegacyCache": true + "nxCloudAccessToken": "NzY1ODc3OWUtNzg4OS00NzNkLTliNmMtZTRhY2I3NjEzNjU0fHJlYWQtd3JpdGU=" } From 8feaa207040b92e91af41bb1c93d8bd7dcc37a28 Mon Sep 17 00:00:00 2001 From: Thomas Dekiere Date: Mon, 30 Dec 2024 09:43:56 +0100 Subject: [PATCH 7/7] feat: add hello api app --- apps/books-api/tsconfig.json | 3 -- apps/hello-api/.eslintrc.json | 18 ++++++++ apps/hello-api/project.json | 43 +++++++++++++++++++ apps/hello-api/src/assets/.gitkeep | 0 apps/hello-api/src/main.ts | 3 ++ apps/hello-api/tsconfig.app.json | 11 +++++ apps/hello-api/tsconfig.json | 13 ++++++ apps/hello-api/webpack.config.js | 20 +++++++++ libs/hello-api-lib/.eslintrc.json | 18 ++++++++ libs/hello-api-lib/README.md | 7 +++ libs/hello-api-lib/jest.config.ts | 10 +++++ libs/hello-api-lib/project.json | 9 ++++ libs/hello-api-lib/src/index.ts | 1 + .../src/lib/app/app.controller.spec.ts | 21 +++++++++ .../src/lib/app/app.controller.ts | 12 ++++++ libs/hello-api-lib/src/lib/app/app.module.ts | 11 +++++ .../src/lib/app/app.service.spec.ts | 20 +++++++++ libs/hello-api-lib/src/lib/app/app.service.ts | 8 ++++ libs/hello-api-lib/tsconfig.json | 21 +++++++++ libs/hello-api-lib/tsconfig.lib.json | 16 +++++++ libs/hello-api-lib/tsconfig.spec.json | 15 +++++++ nx.json | 3 +- tsconfig.base.json | 1 + 23 files changed, 280 insertions(+), 4 deletions(-) create mode 100644 apps/hello-api/.eslintrc.json create mode 100644 apps/hello-api/project.json create mode 100644 apps/hello-api/src/assets/.gitkeep create mode 100644 apps/hello-api/src/main.ts create mode 100644 apps/hello-api/tsconfig.app.json create mode 100644 apps/hello-api/tsconfig.json create mode 100644 apps/hello-api/webpack.config.js create mode 100644 libs/hello-api-lib/.eslintrc.json create mode 100644 libs/hello-api-lib/README.md create mode 100644 libs/hello-api-lib/jest.config.ts create mode 100644 libs/hello-api-lib/project.json create mode 100644 libs/hello-api-lib/src/index.ts create mode 100644 libs/hello-api-lib/src/lib/app/app.controller.spec.ts create mode 100644 libs/hello-api-lib/src/lib/app/app.controller.ts create mode 100644 libs/hello-api-lib/src/lib/app/app.module.ts create mode 100644 libs/hello-api-lib/src/lib/app/app.service.spec.ts create mode 100644 libs/hello-api-lib/src/lib/app/app.service.ts create mode 100644 libs/hello-api-lib/tsconfig.json create mode 100644 libs/hello-api-lib/tsconfig.lib.json create mode 100644 libs/hello-api-lib/tsconfig.spec.json diff --git a/apps/books-api/tsconfig.json b/apps/books-api/tsconfig.json index c1e2dd4..3685ac7 100644 --- a/apps/books-api/tsconfig.json +++ b/apps/books-api/tsconfig.json @@ -5,9 +5,6 @@ "references": [ { "path": "./tsconfig.app.json" - }, - { - "path": "./tsconfig.spec.json" } ], "compilerOptions": { diff --git a/apps/hello-api/.eslintrc.json b/apps/hello-api/.eslintrc.json new file mode 100644 index 0000000..9d9c0db --- /dev/null +++ b/apps/hello-api/.eslintrc.json @@ -0,0 +1,18 @@ +{ + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], + "rules": {} + }, + { + "files": ["*.ts", "*.tsx"], + "rules": {} + }, + { + "files": ["*.js", "*.jsx"], + "rules": {} + } + ] +} diff --git a/apps/hello-api/project.json b/apps/hello-api/project.json new file mode 100644 index 0000000..ddba2d0 --- /dev/null +++ b/apps/hello-api/project.json @@ -0,0 +1,43 @@ +{ + "name": "hello-api", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "apps/hello-api/src", + "projectType": "application", + "tags": [], + "targets": { + "build": { + "executor": "nx:run-commands", + "options": { + "command": "webpack-cli build", + "args": ["node-env=production"] + }, + "configurations": { + "development": { + "args": ["node-env=development"] + } + } + }, + "serve": { + "executor": "@nx/js:node", + "defaultConfiguration": "development", + "dependsOn": ["build"], + "options": { + "buildTarget": "hello-api:build", + "runBuildTargetDependencies": false + }, + "configurations": { + "development": { + "buildTarget": "hello-api:build:development" + }, + "production": { + "buildTarget": "hello-api:build:production" + } + } + }, + "test": { + "options": { + "passWithNoTests": true + } + } + } +} diff --git a/apps/hello-api/src/assets/.gitkeep b/apps/hello-api/src/assets/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/apps/hello-api/src/main.ts b/apps/hello-api/src/main.ts new file mode 100644 index 0000000..43f2a2b --- /dev/null +++ b/apps/hello-api/src/main.ts @@ -0,0 +1,3 @@ +import { bootstrap } from '@nx-demo/nest-bootstrap'; +import { AppModule } from '@nx-demo/hello-api-lib'; +bootstrap(AppModule); diff --git a/apps/hello-api/tsconfig.app.json b/apps/hello-api/tsconfig.app.json new file mode 100644 index 0000000..a11e32b --- /dev/null +++ b/apps/hello-api/tsconfig.app.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "types": ["node"], + "emitDecoratorMetadata": true, + "target": "es2021" + }, + "include": ["src/**/*.ts"], + "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"] +} diff --git a/apps/hello-api/tsconfig.json b/apps/hello-api/tsconfig.json new file mode 100644 index 0000000..3685ac7 --- /dev/null +++ b/apps/hello-api/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.app.json" + } + ], + "compilerOptions": { + "esModuleInterop": true + } +} diff --git a/apps/hello-api/webpack.config.js b/apps/hello-api/webpack.config.js new file mode 100644 index 0000000..0ab6a4b --- /dev/null +++ b/apps/hello-api/webpack.config.js @@ -0,0 +1,20 @@ +const { NxAppWebpackPlugin } = require('@nx/webpack/app-plugin'); +const { join } = require('path'); + +module.exports = { + output: { + path: join(__dirname, '../../dist/apps/hello-api'), + }, + plugins: [ + new NxAppWebpackPlugin({ + target: 'node', + compiler: 'tsc', + main: './src/main.ts', + tsConfig: './tsconfig.app.json', + assets: ['./src/assets'], + optimization: false, + outputHashing: 'none', + generatePackageJson: true, + }), + ], +}; diff --git a/libs/hello-api-lib/.eslintrc.json b/libs/hello-api-lib/.eslintrc.json new file mode 100644 index 0000000..9d9c0db --- /dev/null +++ b/libs/hello-api-lib/.eslintrc.json @@ -0,0 +1,18 @@ +{ + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], + "rules": {} + }, + { + "files": ["*.ts", "*.tsx"], + "rules": {} + }, + { + "files": ["*.js", "*.jsx"], + "rules": {} + } + ] +} diff --git a/libs/hello-api-lib/README.md b/libs/hello-api-lib/README.md new file mode 100644 index 0000000..95a0323 --- /dev/null +++ b/libs/hello-api-lib/README.md @@ -0,0 +1,7 @@ +# hello-api-lib + +This library was generated with [Nx](https://nx.dev). + +## Running unit tests + +Run `nx test hello-api-lib` to execute the unit tests via [Jest](https://jestjs.io). diff --git a/libs/hello-api-lib/jest.config.ts b/libs/hello-api-lib/jest.config.ts new file mode 100644 index 0000000..0746357 --- /dev/null +++ b/libs/hello-api-lib/jest.config.ts @@ -0,0 +1,10 @@ +export default { + displayName: 'hello-api-lib', + preset: '../../jest.preset.js', + testEnvironment: 'node', + transform: { + '^.+\\.[tj]s$': ['ts-jest', { tsconfig: '/tsconfig.spec.json' }], + }, + moduleFileExtensions: ['ts', 'js', 'html'], + coverageDirectory: '../../coverage/libs/hello-api-lib', +}; diff --git a/libs/hello-api-lib/project.json b/libs/hello-api-lib/project.json new file mode 100644 index 0000000..6ca002d --- /dev/null +++ b/libs/hello-api-lib/project.json @@ -0,0 +1,9 @@ +{ + "name": "hello-api-lib", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "libs/hello-api-lib/src", + "projectType": "library", + "tags": [], + "// targets": "to see all targets run: nx show project hello-api-lib --web", + "targets": {} +} diff --git a/libs/hello-api-lib/src/index.ts b/libs/hello-api-lib/src/index.ts new file mode 100644 index 0000000..79ceee4 --- /dev/null +++ b/libs/hello-api-lib/src/index.ts @@ -0,0 +1 @@ +export * from './lib/app/app.module'; diff --git a/libs/hello-api-lib/src/lib/app/app.controller.spec.ts b/libs/hello-api-lib/src/lib/app/app.controller.spec.ts new file mode 100644 index 0000000..f27e3af --- /dev/null +++ b/libs/hello-api-lib/src/lib/app/app.controller.spec.ts @@ -0,0 +1,21 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { AppController } from './app.controller'; +import { AppService } from './app.service'; + +describe('AppController', () => { + let app: TestingModule; + + beforeAll(async () => { + app = await Test.createTestingModule({ + controllers: [AppController], + providers: [AppService], + }).compile(); + }); + + describe('getData', () => { + it('should return "Hello API"', () => { + const appController = app.get(AppController); + expect(appController.getData()).toEqual({ message: 'Hello API' }); + }); + }); +}); diff --git a/libs/hello-api-lib/src/lib/app/app.controller.ts b/libs/hello-api-lib/src/lib/app/app.controller.ts new file mode 100644 index 0000000..aa4a3dd --- /dev/null +++ b/libs/hello-api-lib/src/lib/app/app.controller.ts @@ -0,0 +1,12 @@ +import { Controller, Get } from '@nestjs/common'; +import { AppService } from './app.service'; + +@Controller() +export class AppController { + constructor(private readonly appService: AppService) {} + + @Get() + getData() { + return this.appService.getData(); + } +} diff --git a/libs/hello-api-lib/src/lib/app/app.module.ts b/libs/hello-api-lib/src/lib/app/app.module.ts new file mode 100644 index 0000000..5501bad --- /dev/null +++ b/libs/hello-api-lib/src/lib/app/app.module.ts @@ -0,0 +1,11 @@ +import { Module } from '@nestjs/common'; +import { AppController } from './app.controller'; +import { AppService } from './app.service'; +import { BootstrapModule } from '@nx-demo/nest-bootstrap'; + +@Module({ + imports: [BootstrapModule.forRoot()], + controllers: [AppController], + providers: [AppService], +}) +export class AppModule {} diff --git a/libs/hello-api-lib/src/lib/app/app.service.spec.ts b/libs/hello-api-lib/src/lib/app/app.service.spec.ts new file mode 100644 index 0000000..99d5d8c --- /dev/null +++ b/libs/hello-api-lib/src/lib/app/app.service.spec.ts @@ -0,0 +1,20 @@ +import { Test } from '@nestjs/testing'; +import { AppService } from './app.service'; + +describe('AppService', () => { + let service: AppService; + + beforeAll(async () => { + const app = await Test.createTestingModule({ + providers: [AppService], + }).compile(); + + service = app.get(AppService); + }); + + describe('getData', () => { + it('should return "Hello API"', () => { + expect(service.getData()).toEqual({ message: 'Hello API' }); + }); + }); +}); diff --git a/libs/hello-api-lib/src/lib/app/app.service.ts b/libs/hello-api-lib/src/lib/app/app.service.ts new file mode 100644 index 0000000..cd8cede --- /dev/null +++ b/libs/hello-api-lib/src/lib/app/app.service.ts @@ -0,0 +1,8 @@ +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class AppService { + getData(): { message: string } { + return { message: 'Hello API' }; + } +} diff --git a/libs/hello-api-lib/tsconfig.json b/libs/hello-api-lib/tsconfig.json new file mode 100644 index 0000000..0fce068 --- /dev/null +++ b/libs/hello-api-lib/tsconfig.json @@ -0,0 +1,21 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "noPropertyAccessFromIndexSignature": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ] +} diff --git a/libs/hello-api-lib/tsconfig.lib.json b/libs/hello-api-lib/tsconfig.lib.json new file mode 100644 index 0000000..c297a24 --- /dev/null +++ b/libs/hello-api-lib/tsconfig.lib.json @@ -0,0 +1,16 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "declaration": true, + "types": ["node"], + "target": "es2021", + "strictNullChecks": true, + "noImplicitAny": true, + "strictBindCallApply": true, + "forceConsistentCasingInFileNames": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src/**/*.ts"], + "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"] +} diff --git a/libs/hello-api-lib/tsconfig.spec.json b/libs/hello-api-lib/tsconfig.spec.json new file mode 100644 index 0000000..0d3c604 --- /dev/null +++ b/libs/hello-api-lib/tsconfig.spec.json @@ -0,0 +1,15 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "moduleResolution": "node10", + "types": ["jest", "node"] + }, + "include": [ + "jest.config.ts", + "src/**/*.test.ts", + "src/**/*.spec.ts", + "src/**/*.d.ts" + ] +} diff --git a/nx.json b/nx.json index 2647c7f..b279153 100644 --- a/nx.json +++ b/nx.json @@ -61,7 +61,8 @@ }, "exclude": [ "apps/books-api-e2e/**/*", - "apps/books-api-serverless-e2e/**/*" + "apps/books-api-serverless-e2e/**/*", + "apps/hello-api-e2e/**/*" ] } ], diff --git a/tsconfig.base.json b/tsconfig.base.json index f35f255..9dd64e3 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -16,6 +16,7 @@ "baseUrl": ".", "paths": { "@nx-demo/books-api-lib": ["libs/books-api-lib/src/index.ts"], + "@nx-demo/hello-api-lib": ["libs/hello-api-lib/src/index.ts"], "@nx-demo/lorem-book-summarizer": [ "libs/lorem-book-summarizer/src/index.ts" ],