-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(api): bootstrap domain features with organization domain (#214)
- Loading branch information
1 parent
4851793
commit 2379854
Showing
96 changed files
with
4,283 additions
and
1,305 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
# Architecture | ||
|
||
This document introduces the general architecture of Kordis with a focus on the | ||
API. In general, we want to follow the Clean Architecture Principle, which tries | ||
to achieve a state where: | ||
|
||
1. we are independent of frameworks, | ||
2. we ensure testability of our business logic, | ||
3. we are independent of UI logic, | ||
4. we are independent of the database and its access, | ||
5. we are independent of external dependencies. | ||
|
||
Since architecture is a lot about trade-offs, not every point mentioned above | ||
might be wise to follow in a project. The main goal is to have a solid | ||
separation of concerns. Every change should only have an isolated impact, and | ||
since Kordis is a System that will definitely grow over time with more features | ||
and external dependencies to join as components, it is a requirement to allow | ||
the system to be easily extendable and maintainable by multiple people. | ||
|
||
We aggregate the layers of the clean architecture approach in 2 layers, the | ||
**Core** and the **Infrastructure** layer, which tries to achieve a solid | ||
separation of concerns and a clear dependency direction, but also maintains a | ||
good balance between the effort of maintaining the architecture and the value it | ||
provides. | ||
|
||
**Core** (core) | ||
Contains the business logic, entities, events and domain exceptions. Everything | ||
in here is something business relevant, that should not be touched and | ||
influenced by changes not related to the business logic, such as changes to the | ||
database or the framework. Therefore, the layer should not have any dependency | ||
on other layers or components from outside its scope. This ensures that we can | ||
easily test the logic and that we can change the infrastructure without having | ||
to change the business logic. Nevertheless, we made some tradeoffs in the core | ||
layer. We allow the use of NestJS framework specific CQRS handler annotations, | ||
class validator annotations and annotations in the entity model for GraphQL | ||
input and argument models. This is due to the fact, that maintaining another | ||
layer on top of these decorators would be pure overhead, that would | ||
overcomplicate the codebase and does not outweigh the value of simpler changes | ||
in the infrastructure layer. Also, maintaining Input Models for GraphQL that | ||
share the same structure as the entity model would also not benefit the | ||
complexity of the codebase. Therefore, we decided to allow these annotations in | ||
the core layer, if they are unlikely to change on the Input/Argument side of the | ||
GraphQL API and the structure is equal. | ||
|
||
**Infrastructure** (infra) | ||
The infrastructure layer defines every external component the system interacts | ||
with. It provides concert implementations such as the repositories (data | ||
access), logging, external APIs, etc. The idea behind this is that all | ||
dependencies point towards the core layer. At no time should the core layer be | ||
based on any concrete implementation, framework or other specification. This | ||
ensures that we are flexible with changes in our infrastructure and we allow our | ||
domain to define what interfaces it requires. This should also result in easier | ||
testing. The best example is the repository, where the core layer defines which | ||
data it needs and the infrastructure layer implements this interface and hides | ||
all the concrete database logic. | ||
|
||
## CQRS | ||
|
||
tbd by @JSPRH | ||
|
||
Some resources used for this architecture are: | ||
|
||
- https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html | ||
- Clean Architecture: A Craftsman's Guide to Software Structure and Design | ||
(Robert C. Martin Series) | ||
- https://github.com/jasontaylordev/CleanArchitecture | ||
- https://learn.microsoft.com/en-us/dotnet/architecture/modern-web-apps-azure/common-web-application-architectures#clean-architecture |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,4 @@ | ||
export * from './lib/sentry-observability.module'; | ||
export * from './lib/dev-observability.module'; | ||
export * from './lib/decorators/trace.decorator'; | ||
export * from './lib/services/kordis-logger.interface'; |
19 changes: 19 additions & 0 deletions
19
libs/api/observability/src/lib/dev-observability.module.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { Logger, Module } from '@nestjs/common'; | ||
|
||
import { KORDIS_LOGGER_SERVICE } from './services/kordis-logger-service.interface'; | ||
import { KordisLoggerImpl } from './services/kordis.logger'; | ||
import { PinoLogger } from './services/pino-logger.service'; | ||
|
||
@Module({ | ||
providers: [ | ||
{ | ||
provide: KORDIS_LOGGER_SERVICE, | ||
useValue: new PinoLogger(true), | ||
}, | ||
{ | ||
provide: Logger, | ||
useClass: KordisLoggerImpl, | ||
}, | ||
], | ||
}) | ||
export class DevObservabilityModule {} |
63 changes: 63 additions & 0 deletions
63
libs/api/observability/src/lib/filters/exceptions.filter.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import * as Sentry from '@sentry/node'; | ||
|
||
import { PresentableException } from '@kordis/api/shared'; | ||
|
||
import { SentryExceptionsFilter } from './sentry-exceptions.filter'; | ||
|
||
describe('ExceptionsFilter', () => { | ||
let sentryExceptionsFilter: SentryExceptionsFilter; | ||
let addBreadcrumbMock: jest.Mock; | ||
let captureExceptionMock: jest.Mock; | ||
|
||
beforeEach(() => { | ||
addBreadcrumbMock = jest.fn(); | ||
captureExceptionMock = jest.fn(); | ||
|
||
(Sentry.addBreadcrumb as jest.Mock) = addBreadcrumbMock; | ||
(Sentry.captureException as jest.Mock) = captureExceptionMock; | ||
|
||
sentryExceptionsFilter = new SentryExceptionsFilter(); | ||
}); | ||
|
||
afterEach(() => { | ||
jest.clearAllMocks(); | ||
}); | ||
|
||
it('should capture a presentable exception as an info message', () => { | ||
class MockPresentableException extends PresentableException { | ||
code = 'code'; | ||
|
||
constructor() { | ||
super('message'); | ||
} | ||
} | ||
|
||
const presentableException = new MockPresentableException(); | ||
|
||
sentryExceptionsFilter.catch(presentableException); | ||
|
||
expect(addBreadcrumbMock).toHaveBeenCalledTimes(1); | ||
expect(addBreadcrumbMock).toHaveBeenCalledWith({ | ||
level: 'error', | ||
message: 'message', | ||
data: { | ||
name: 'Error', | ||
code: 'code', | ||
stack: expect.any(String), | ||
}, | ||
}); | ||
expect(captureExceptionMock).not.toHaveBeenCalled(); | ||
}); | ||
|
||
it('should capture a non-presentable exception as an error', () => { | ||
const exception = new Error('Some error'); | ||
|
||
sentryExceptionsFilter.catch(exception); | ||
|
||
expect(captureExceptionMock).toHaveBeenCalledTimes(1); | ||
expect(captureExceptionMock).toHaveBeenCalledWith(exception, { | ||
level: 'error', | ||
}); | ||
expect(addBreadcrumbMock).not.toHaveBeenCalled(); | ||
}); | ||
}); |
26 changes: 26 additions & 0 deletions
26
libs/api/observability/src/lib/filters/sentry-exceptions.filter.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { Catch, ExceptionFilter } from '@nestjs/common'; | ||
import * as Sentry from '@sentry/node'; | ||
|
||
import { PresentableException } from '@kordis/api/shared'; | ||
|
||
@Catch() | ||
export class SentryExceptionsFilter implements ExceptionFilter { | ||
catch(exception: unknown): void { | ||
if (exception instanceof PresentableException) { | ||
// if this is a presentable error, such as a validation error, we don't want to log it as an error but rather as an information to have the context for possible future debugging | ||
Sentry.addBreadcrumb({ | ||
level: 'error', | ||
message: exception.message, | ||
data: { | ||
code: exception.code, | ||
name: exception.name, | ||
stack: exception.stack, | ||
}, | ||
}); | ||
} else { | ||
Sentry.captureException(exception, { | ||
level: 'error', | ||
}); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.