diff --git a/.env.example b/.env.example index 689474c..455d819 100644 --- a/.env.example +++ b/.env.example @@ -1,4 +1,6 @@ PORT=3000 GATEWAY_PORT=3052 GATEWAY_SUBGRAPHS='[{"name": "api", "url": "http://localhost:3000/graphql"}]' + +NATS_URL=nats://localhost:4222 SAMPLE_DATABASE_URL=postgres://postgres:postgres@localhost:5432/postgres?schema=public \ No newline at end of file diff --git a/apps/api/src/app/app.module.ts b/apps/api/src/app/app.module.ts index 464d70f..eb3f03e 100644 --- a/apps/api/src/app/app.module.ts +++ b/apps/api/src/app/app.module.ts @@ -9,6 +9,7 @@ import { ApolloFederationDriver, ApolloFederationDriverConfig, } from '@nestjs/apollo' +import { NatsModule } from 'core/nats' @Module({ imports: [ @@ -30,6 +31,9 @@ import { maxQueryExecutionTime: 5000, }, }), + NatsModule.forRoot({ + servers: env.get('NATS_URL').required().asString(), + }), ], controllers: [], providers: [], diff --git a/libs/core/common/.eslintrc.json b/libs/core/common/.eslintrc.json new file mode 100644 index 0000000..3456be9 --- /dev/null +++ b/libs/core/common/.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/core/common/README.md b/libs/core/common/README.md new file mode 100644 index 0000000..1573ff9 --- /dev/null +++ b/libs/core/common/README.md @@ -0,0 +1,11 @@ +# common + +This library was generated with [Nx](https://nx.dev). + +## Building + +Run `nx build common` to build the library. + +## Running unit tests + +Run `nx test common` to execute the unit tests via [Jest](https://jestjs.io). diff --git a/libs/core/common/jest.config.ts b/libs/core/common/jest.config.ts new file mode 100644 index 0000000..d2a54b7 --- /dev/null +++ b/libs/core/common/jest.config.ts @@ -0,0 +1,14 @@ +/* eslint-disable */ +export default { + displayName: 'common', + preset: '../../../jest.preset.js', + testEnvironment: 'node', + transform: { + '^.+\\.[tj]s$': [ + 'ts-jest', + { tsconfig: '/tsconfig.spec.json' }, + ], + }, + moduleFileExtensions: ['ts', 'js', 'html'], + coverageDirectory: '../../../coverage/libs/core/common', +} diff --git a/libs/core/common/project.json b/libs/core/common/project.json new file mode 100644 index 0000000..fa97f60 --- /dev/null +++ b/libs/core/common/project.json @@ -0,0 +1,30 @@ +{ + "name": "common", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "libs/core/common/src", + "projectType": "library", + "targets": { + "lint": { + "executor": "@nx/linter:eslint", + "outputs": ["{options.outputFile}"], + "options": { + "lintFilePatterns": ["libs/core/common/**/*.ts"] + } + }, + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], + "options": { + "jestConfig": "libs/core/common/jest.config.ts", + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "codeCoverage": true + } + } + } + }, + "tags": [] +} diff --git a/libs/core/common/src/index.ts b/libs/core/common/src/index.ts new file mode 100644 index 0000000..aeb8dee --- /dev/null +++ b/libs/core/common/src/index.ts @@ -0,0 +1,2 @@ +export * from './lib/errors/common-errors.enum' +export * from './lib/errors/common.error' diff --git a/libs/core/common/src/lib/errors/common-errors.enum.ts b/libs/core/common/src/lib/errors/common-errors.enum.ts new file mode 100644 index 0000000..4393184 --- /dev/null +++ b/libs/core/common/src/lib/errors/common-errors.enum.ts @@ -0,0 +1,21 @@ +export enum CommonErrorsEnum { + Error = 'ERROR-000', + NotFound = 'ERROR-001', + Forbidden = 'ERROR-002', + UnexpectedError = 'ERROR-003', + ValidationError = 'ERROR-004', + UniqueError = 'ERROR-005', + RequestError = 'ERROR-006', + UnauthorizedError = 'ERROR-007', +} + +export const COMMON_ERROR_TITLES = { + [CommonErrorsEnum.Error]: 'Error', + [CommonErrorsEnum.NotFound]: 'Not found', + [CommonErrorsEnum.Forbidden]: 'Forbidden', + [CommonErrorsEnum.UnexpectedError]: 'Unexpected error', + [CommonErrorsEnum.ValidationError]: 'Validation error', + [CommonErrorsEnum.UniqueError]: 'Unique error', + [CommonErrorsEnum.RequestError]: 'Request error', + [CommonErrorsEnum.UnauthorizedError]: 'Unauthorized', +} diff --git a/libs/core/common/src/lib/errors/common.error.ts b/libs/core/common/src/lib/errors/common.error.ts new file mode 100644 index 0000000..6dd07dd --- /dev/null +++ b/libs/core/common/src/lib/errors/common.error.ts @@ -0,0 +1,28 @@ +import { COMMON_ERROR_TITLES, CommonErrorsEnum } from './common-errors.enum' + +export class CommonError< + T extends string = CommonErrorsEnum, + M = Record, +> extends Error { + code: T + metadata?: M + + constructor( + code: T, + message?: { [code: string]: string } | string, + metadata?: M, + ) { + super( + message === undefined + ? COMMON_ERROR_TITLES[ + (code as string) || + COMMON_ERROR_TITLES[CommonErrorsEnum.Error] + ] + : typeof message === 'string' + ? message + : message[code], + ) + this.code = code + this.metadata = metadata + } +} diff --git a/libs/core/common/tsconfig.json b/libs/core/common/tsconfig.json new file mode 100644 index 0000000..25f7201 --- /dev/null +++ b/libs/core/common/tsconfig.json @@ -0,0 +1,16 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "module": "commonjs" + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ] +} diff --git a/libs/core/common/tsconfig.lib.json b/libs/core/common/tsconfig.lib.json new file mode 100644 index 0000000..6d18b27 --- /dev/null +++ b/libs/core/common/tsconfig.lib.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "declaration": true, + "types": ["node"], + "target": "es6" + }, + "include": ["src/**/*.ts"], + "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"] +} diff --git a/libs/core/common/tsconfig.spec.json b/libs/core/common/tsconfig.spec.json new file mode 100644 index 0000000..69a251f --- /dev/null +++ b/libs/core/common/tsconfig.spec.json @@ -0,0 +1,14 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"] + }, + "include": [ + "jest.config.ts", + "src/**/*.test.ts", + "src/**/*.spec.ts", + "src/**/*.d.ts" + ] +} diff --git a/libs/core/nats/.eslintrc.json b/libs/core/nats/.eslintrc.json new file mode 100644 index 0000000..3456be9 --- /dev/null +++ b/libs/core/nats/.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/core/nats/README.md b/libs/core/nats/README.md new file mode 100644 index 0000000..3f5e7bb --- /dev/null +++ b/libs/core/nats/README.md @@ -0,0 +1,11 @@ +# nats + +This library was generated with [Nx](https://nx.dev). + +## Building + +Run `nx build nats` to build the library. + +## Running unit tests + +Run `nx test nats` to execute the unit tests via [Jest](https://jestjs.io). diff --git a/libs/core/nats/jest.config.ts b/libs/core/nats/jest.config.ts new file mode 100644 index 0000000..6374427 --- /dev/null +++ b/libs/core/nats/jest.config.ts @@ -0,0 +1,14 @@ +/* eslint-disable */ +export default { + displayName: 'nats', + preset: '../../../jest.preset.js', + testEnvironment: 'node', + transform: { + '^.+\\.[tj]s$': [ + 'ts-jest', + { tsconfig: '/tsconfig.spec.json' }, + ], + }, + moduleFileExtensions: ['ts', 'js', 'html'], + coverageDirectory: '../../../coverage/libs/core/nats', +} diff --git a/libs/core/nats/project.json b/libs/core/nats/project.json new file mode 100644 index 0000000..937ab4d --- /dev/null +++ b/libs/core/nats/project.json @@ -0,0 +1,30 @@ +{ + "name": "nats", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "libs/core/nats/src", + "projectType": "library", + "targets": { + "lint": { + "executor": "@nx/linter:eslint", + "outputs": ["{options.outputFile}"], + "options": { + "lintFilePatterns": ["libs/core/nats/**/*.ts"] + } + }, + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], + "options": { + "jestConfig": "libs/core/nats/jest.config.ts", + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "codeCoverage": true + } + } + } + }, + "tags": [] +} diff --git a/libs/core/nats/src/index.ts b/libs/core/nats/src/index.ts new file mode 100644 index 0000000..a8abc36 --- /dev/null +++ b/libs/core/nats/src/index.ts @@ -0,0 +1,2 @@ +export * from './lib/nats-configs/nats-module.config' +export * from './lib/nats.module' diff --git a/libs/core/nats/src/lib/nats-configs/nats-module.config.ts b/libs/core/nats/src/lib/nats-configs/nats-module.config.ts new file mode 100644 index 0000000..108230a --- /dev/null +++ b/libs/core/nats/src/lib/nats-configs/nats-module.config.ts @@ -0,0 +1,32 @@ +import { ConfigurableModuleBuilder } from '@nestjs/common' +import { merge } from 'lodash' +import { ConnectionOptions } from 'nats' + +export interface NatsConfig extends ConnectionOptions { + temp?: false +} + +export const DEFAULT_NATS_CONFIG: Pick = { + temp: false, +} + +export function patchNatsConfig( + config: Pick, +) { + if (config) { + Object.assign( + config, + merge(DEFAULT_NATS_CONFIG, config), + ) as typeof NATS_OPTIONS_TYPE + } + return config +} + +export const { + ConfigurableModuleClass: NatsConfigurableModuleClass, + MODULE_OPTIONS_TOKEN: NATS_CONFIG, + ASYNC_OPTIONS_TYPE: NATS_ASYNC_OPTIONS_TYPE, + OPTIONS_TYPE: NATS_OPTIONS_TYPE, +} = new ConfigurableModuleBuilder({ + optionsInjectionToken: `NATS_CONFIG`, +}).build() diff --git a/libs/core/nats/src/lib/nats-errors/nats-errors.enum.ts b/libs/core/nats/src/lib/nats-errors/nats-errors.enum.ts new file mode 100644 index 0000000..511b122 --- /dev/null +++ b/libs/core/nats/src/lib/nats-errors/nats-errors.enum.ts @@ -0,0 +1,9 @@ +export enum NatsErrorsEnum { + Timeout = 'NATS-000', + NoResponders = 'NATS-001', +} + +export const NATS_ERROR_TITLES = { + [NatsErrorsEnum.Timeout]: `Someone is listening but didn't respond`, + [NatsErrorsEnum.NoResponders]: `No one is listening to this request`, +} diff --git a/libs/core/nats/src/lib/nats-indicators/nats-connection-health.indicator.ts b/libs/core/nats/src/lib/nats-indicators/nats-connection-health.indicator.ts new file mode 100644 index 0000000..ffb3c2b --- /dev/null +++ b/libs/core/nats/src/lib/nats-indicators/nats-connection-health.indicator.ts @@ -0,0 +1,35 @@ +import { Injectable } from '@nestjs/common' +import { HealthIndicator, HealthIndicatorResult } from 'core/health-checks' +import { NatsConnectionService } from '../nats-services/nats-connection.service' + +@Injectable() +export class NatsConnectionHealthIndicator implements HealthIndicator { + name = 'nats' + + constructor(private readonly natsConnection: NatsConnectionService) {} + + async isHealthy(): Promise { + try { + const status = this.natsConnection.status() + + if (status.connected) { + return { + name: this.name, + status: 'up', + } + } + + return { + name: this.name, + status: 'down', + error: status.error, + } + } catch (error) { + return { + name: this.name, + status: 'down', + error: error.message, + } + } + } +} diff --git a/libs/core/nats/src/lib/nats-interfaces/nats.interfaces.ts b/libs/core/nats/src/lib/nats-interfaces/nats.interfaces.ts new file mode 100644 index 0000000..ee5bc73 --- /dev/null +++ b/libs/core/nats/src/lib/nats-interfaces/nats.interfaces.ts @@ -0,0 +1,14 @@ +import { MsgHdrs, RequestOptions as NatsRequestOptions } from 'nats' + +export interface NatsResponse { + subject: string + data?: T + headers?: MsgHdrs +} + +export interface RequestOptions + extends Omit { + timeout?: number + // eslint-disable-next-line @typescript-eslint/no-explicit-any + headers: Record +} diff --git a/libs/core/nats/src/lib/nats-services/nats-client.service.ts b/libs/core/nats/src/lib/nats-services/nats-client.service.ts new file mode 100644 index 0000000..ae22b5e --- /dev/null +++ b/libs/core/nats/src/lib/nats-services/nats-client.service.ts @@ -0,0 +1,122 @@ +import { Injectable, Logger } from '@nestjs/common' +import { NatsConnectionService } from './nats-connection.service' +import { + Payload, + StringCodec, + JSONCodec, + Empty, + SubscriptionOptions, + Subscription, + headers, + ErrorCode, +} from 'nats' +import { + NatsResponse, + RequestOptions, +} from '../nats-interfaces/nats.interfaces' +import { isObject, isUndefined } from '@nestjs/common/utils/shared.utils' +import { CommonError, CommonErrorsEnum } from 'core/common' +import { NatsErrorsEnum } from '../nats-errors/nats-errors.enum' +import { NATS_ERROR_TITLES } from '../nats-errors/nats-errors.enum' + +@Injectable() +export class NatsClientService { + constructor(private readonly natsConnection: NatsConnectionService) {} + + async request( + subject: string, + payload?: T, + options?: RequestOptions, + ): Promise> { + const nc = this.natsConnection.getNatsConnection() + + const encodedPayload: Payload = this.encodeMessage(payload) + + const requestHeaders = headers() + if (options?.headers) { + for (const [k, v] of Object.entries(options.headers)) { + requestHeaders.append(k, v) + } + } + + try { + const msg = await nc.request(subject, encodedPayload, { + timeout: 10000, + ...options, + headers: requestHeaders, + }) + + return { + subject, + headers: msg.headers, + data: this.decodeMessage(msg.data), + } + } catch (error) { + if (error.code === ErrorCode.NoResponders) { + throw new CommonError( + NatsErrorsEnum.NoResponders, + NATS_ERROR_TITLES, + ) + } + + if (error.code === ErrorCode.Timeout) { + throw new CommonError(NatsErrorsEnum.Timeout, NATS_ERROR_TITLES) + } + + throw new CommonError( + CommonErrorsEnum.UnexpectedError, + error.message, + ) + } + } + + /** + * Subscribe to subject and reply with particular response + * + * Example: + * ```ts + * this.reply('hello.world', { + * callback: (error, message) => { + * const responseHeaders = headers() + * responseHeaders.append('key', 'value') + * message.respond(this.encodeMessage('hello'), { + * headers: responseHeaders, + * }) + * }, + * }) + * ``` + * @returns {Subscription} + */ + async reply( + subject: string, + options?: SubscriptionOptions, + ): Promise { + const nc = this.natsConnection.getNatsConnection() + + return nc.subscribe(subject, options) + } + + decodeMessage(data: Uint8Array): T { + const sc = StringCodec() + const jc = JSONCodec() + + try { + return jc.decode(data) + } catch { + return sc.decode(data) as T + } + } + + encodeMessage(data?: T): Uint8Array { + const sc = StringCodec() + const jc = JSONCodec() + + if (isObject(data)) { + return jc.encode(data) + } else if (!isUndefined(data)) { + return sc.encode(`${data}`) + } + + return Empty + } +} diff --git a/libs/core/nats/src/lib/nats-services/nats-connection.service.ts b/libs/core/nats/src/lib/nats-services/nats-connection.service.ts new file mode 100644 index 0000000..f7e5b8a --- /dev/null +++ b/libs/core/nats/src/lib/nats-services/nats-connection.service.ts @@ -0,0 +1,139 @@ +/* eslint-disable no-case-declarations */ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ +import { + Inject, + Injectable, + Logger, + OnModuleDestroy, + OnModuleInit, +} from '@nestjs/common' +import { + connect, + NatsConnection, + JetStreamManager, + JetStreamOptions, +} from 'nats' +import { NATS_CONFIG, NatsConfig } from '../nats-configs/nats-module.config' +import { isObject } from '@nestjs/common/utils/shared.utils' + +@Injectable() +export class NatsConnectionService implements OnModuleInit, OnModuleDestroy { + private logger = new Logger(NatsConnectionService.name) + private natsConnection?: NatsConnection + private natsConnectionStatus: { + connected: boolean + error?: string + } = { + connected: false, + } + + constructor( + @Inject(NATS_CONFIG) + private readonly config: NatsConfig, + ) {} + + async onModuleInit() { + try { + const natsConnection = await connect(this.config) + this.handleStatusUpdates(natsConnection) + + this.natsConnection = natsConnection + this.natsConnectionStatus.connected = true + } catch (error) { + this.natsConnectionStatus = { + connected: false, + error, + } + this.logger.error(error) + } + } + + async onModuleDestroy() { + if (this.natsConnection === undefined) { + return + } + + const connectionClosed = this.natsConnection?.closed() + + await this.natsConnection?.drain() + + const error = await connectionClosed + + if (error) { + this.logger.error(`Error closing NATS:`, error) + } + } + + status(): { connected: boolean; error?: string } { + return this.natsConnectionStatus + } + + getNatsConnection(): NatsConnection { + return this.natsConnection! + } + + async getJetStreamManager( + options?: JetStreamOptions, + ): Promise { + return await this.natsConnection!.jetstreamManager(options) + } + + // TODO: add LDM mode + public async handleStatusUpdates(natsConnection: NatsConnection) { + for await (const status of natsConnection.status()) { + const data = + status.data && isObject(status.data) + ? JSON.stringify(status.data) + : status.data + + switch (status.type) { + case 'error': + case 'disconnect': { + const message = `NatsError: type: "${status.type}", data: "${data}".` + + this.natsConnectionStatus.connected = false + this.natsConnectionStatus.error = message + + this.logger.error(message) + break + } + + case 'pingTimer': { + if (this.config.debug) { + this.logger.debug( + `NatsStatus: type: "${status.type}", data: "${data}".`, + ) + } + break + } + + case 'reconnect': { + const message = `NatsStatus: type: "${status.type}", data: "${data}".` + + this.natsConnectionStatus.connected = true + this.natsConnectionStatus.error = undefined + + this.logger.log(message) + break + } + + case 'reconnecting': { + const message = `NatsError: type: "${status.type}", data: "${data}".` + + this.natsConnectionStatus.connected = false + this.natsConnectionStatus.error = message + + this.logger.error(message) + break + } + + default: { + this.logger.log( + `NatsStatus: type: "${status.type}", data: "${data}".`, + ) + break + } + } + } + } +} diff --git a/libs/core/nats/src/lib/nats.module.ts b/libs/core/nats/src/lib/nats.module.ts new file mode 100644 index 0000000..28ef2b0 --- /dev/null +++ b/libs/core/nats/src/lib/nats.module.ts @@ -0,0 +1,78 @@ +import { DynamicModule, Module } from '@nestjs/common' +import { + NatsConfigurableModuleClass, + NATS_ASYNC_OPTIONS_TYPE, + NATS_CONFIG, + NATS_OPTIONS_TYPE, + patchNatsConfig, +} from './nats-configs/nats-module.config' +import { CustomInjectorModule } from 'nestjs-custom-injector' +import { NatsConnectionService } from './nats-services/nats-connection.service' +import { NatsConnectionHealthIndicator } from './nats-indicators/nats-connection-health.indicator' +import { HEALTH_CHECKS_PROVIDER } from 'core/health-checks' +import { NatsClientService } from './nats-services/nats-client.service' + +@Module({}) +export class NatsModule extends NatsConfigurableModuleClass { + static forRoot(options: typeof NATS_OPTIONS_TYPE): DynamicModule { + return { + ...this.forRootAsync({ + useFactory: async () => options, + }), + } + } + + static forRootAsync( + options?: typeof NATS_ASYNC_OPTIONS_TYPE, + ): DynamicModule { + const useFactory = options?.useFactory + const useClass = options?.useClass + + if (options?.useExisting) { + throw new Error(`options?.useExisting is not supported!`) + } + + return { + module: NatsModule, + imports: [...(options?.imports || []), CustomInjectorModule], + providers: [ + NatsConnectionService, + NatsClientService, + { + provide: HEALTH_CHECKS_PROVIDER, + useClass: NatsConnectionHealthIndicator, + }, + ...(useClass + ? [ + { + provide: `${String(NATS_CONFIG)}_TEMP`, + useClass, + }, + { + provide: NATS_CONFIG, + useFactory: async (config) => + patchNatsConfig(config), + inject: [`${String(NATS_CONFIG)}_TEMP`], + }, + ] + : []), + ...(useFactory + ? [ + { + provide: NATS_CONFIG, + useFactory: async (...args) => + patchNatsConfig(await useFactory(...args)), + inject: options?.inject || [], + }, + ] + : [ + { + provide: NATS_CONFIG, + useValue: patchNatsConfig({}), + }, + ]), + ], + exports: [NATS_CONFIG, NatsConnectionService, NatsClientService], + } + } +} diff --git a/libs/core/nats/tests/core-nats.spec.ts b/libs/core/nats/tests/core-nats.spec.ts new file mode 100644 index 0000000..e69de29 diff --git a/libs/core/nats/tsconfig.json b/libs/core/nats/tsconfig.json new file mode 100644 index 0000000..25f7201 --- /dev/null +++ b/libs/core/nats/tsconfig.json @@ -0,0 +1,16 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "module": "commonjs" + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ] +} diff --git a/libs/core/nats/tsconfig.lib.json b/libs/core/nats/tsconfig.lib.json new file mode 100644 index 0000000..6d18b27 --- /dev/null +++ b/libs/core/nats/tsconfig.lib.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "declaration": true, + "types": ["node"], + "target": "es6" + }, + "include": ["src/**/*.ts"], + "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"] +} diff --git a/libs/core/nats/tsconfig.spec.json b/libs/core/nats/tsconfig.spec.json new file mode 100644 index 0000000..69a251f --- /dev/null +++ b/libs/core/nats/tsconfig.spec.json @@ -0,0 +1,14 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"] + }, + "include": [ + "jest.config.ts", + "src/**/*.test.ts", + "src/**/*.spec.ts", + "src/**/*.d.ts" + ] +} diff --git a/libs/sample/src/lib/sample.module.ts b/libs/sample/src/lib/sample.module.ts index 82f6f0f..8f21a69 100644 --- a/libs/sample/src/lib/sample.module.ts +++ b/libs/sample/src/lib/sample.module.ts @@ -10,7 +10,6 @@ import { SampleResolver } from './sample.resolver' import { HEALTH_CHECKS_PROVIDER } from 'core/health-checks' import { SamplePrismaConnectionHealthIndicator } from './sample-indicators/sample-prisma-connection.health' import { SamplePrismaService } from './sample-services/sample-prisma.service' -import { CustomInjectorModule } from 'nestjs-custom-injector' @Module({}) export class SampleModule extends SampleConfigurableModuleClass { @@ -34,7 +33,7 @@ export class SampleModule extends SampleConfigurableModuleClass { return { module: SampleModule, - imports: [...(options?.imports || []), CustomInjectorModule], + imports: [...(options?.imports || [])], providers: [ SampleResolver, SamplePrismaService.instance diff --git a/tsconfig.base.json b/tsconfig.base.json index a96f18b..8f8da21 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -23,10 +23,12 @@ "esModuleInterop": true, "noImplicitAny": false, "paths": { + "core/common": ["libs/core/common/src/index.ts"], "core/eventloop-frozen-detector": [ "libs/core/eventloop-frozen-detector/src/index.ts" ], "core/health-checks": ["libs/core/health-checks/src/index.ts"], + "core/nats": ["libs/core/nats/src/index.ts"], "sample": ["libs/sample/src/index.ts"], "schematics": ["libs/schematics/src/index.ts"] }