refactor: changed directory structure a bit
This commit is contained in:
10
README.md
10
README.md
@@ -205,7 +205,7 @@ Ports (for Driven Adapters) are interfaces that define contracts which must be i
|
||||
- Ports should be created to fit the Domain needs, not simply mimic the tools APIs.
|
||||
- Mock implementations can be passed to ports while testing. Mocking makes your tests faster and independent from the environment.
|
||||
|
||||
Example file: [event-emitter.port.ts](src/application/ports/event-emitter.port.ts)
|
||||
Example file: [event-emitter.port.ts](src/core/ports/event-emitter.port.ts)
|
||||
|
||||
---
|
||||
|
||||
@@ -338,7 +338,7 @@ Lets distinguish two types of protection from illegal states: at **compile time*
|
||||
|
||||
Types give useful semantic information to a developer. Good code should be easy to use correctly, and hard to use incorrectly. Types system can be a good help for that. It can prevent some nasty errors at a compile time, so IDE will show type errors right away.
|
||||
|
||||
The simplest example may be using enums instead of constants, for example: [events.ts](src/application/events/events.ts). This file has enums of events that can occur in a program. Now, event emitter port [event-emitter.port.ts](src/application/ports/event-emitter.port.ts) uses that events type to prevent illegal types pass. If you try to pass anything that is not intended it will show type error.
|
||||
The simplest example may be using enums instead of constants, for example: [events.ts](src/core/events/events.ts). This file has enums of events that can occur in a program. Now, event emitter port [event-emitter.port.ts](src/core/ports/event-emitter.port.ts) uses that events type to prevent illegal types pass. If you try to pass anything that is not intended it will show type error.
|
||||
|
||||
More importantly, this approach can be used to make business logic safer.
|
||||
|
||||
@@ -379,7 +379,7 @@ Validating will inform immediately when `Value Object` is created with corrupted
|
||||
|
||||
To avoid repeating same validation code between different domain objects consider using [guards](https://medium.com/better-programming/refactoring-guard-clauses-2ceeaa1a9da).
|
||||
|
||||
Example file: [guard.ts](src/domain/guard.ts)
|
||||
Example file: [guard.ts](src/core/guard.ts)
|
||||
|
||||
**Keep in mind** that not all validations can be done in a single `Value Object`, it should validate only rules shared by all contexts. There are cases when validation may be different depending on a context, or one field may invole another field, or even a different entity. Handle those cases accordingly.
|
||||
|
||||
@@ -599,8 +599,8 @@ By default, Error objects seralize to JSON with output like this:
|
||||
|
||||
Consider serializing errors by creating a `toJSON()` method so it can be easily sent to other processes as a plain object.
|
||||
|
||||
- Exception abstract base class example: [exception.base.ts](/src/infrastructure/exceptions/exception.base.ts)
|
||||
- Domain Validation Exception class example: [domain-validation.exception.ts](src/infrastructure/exceptions/domain-validation.exception.ts)
|
||||
- Exception abstract base class example: [exception.base.ts](src/core/exceptions/exception.base.ts)
|
||||
- Domain Validation Exception class example: [domain-validation.exception.ts](src/core/exceptions/domain-validation.exception.ts)
|
||||
|
||||
Read more: [Better error handling in JavaScript](https://iaincollins.medium.com/error-handling-in-javascript-a6172ccdf9af)
|
||||
|
||||
|
||||
8
src/core/exceptions/index.ts
Normal file
8
src/core/exceptions/index.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
export * from './exception.base';
|
||||
export * from './argument-out-of-range.exception';
|
||||
export * from './business-rule-validation.exception';
|
||||
export * from './conflict.exception';
|
||||
export * from './domain-validation.exception';
|
||||
export * from './exception.types';
|
||||
export * from './input-validation.exception';
|
||||
export * from './not-found.exception';
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ID } from 'src/domain/value-objects/id.value-object';
|
||||
import { ID } from 'src/core/value-objects/id.value-object';
|
||||
|
||||
/* Most of repos will probably need generic
|
||||
save/find/delete operations, so it's easier
|
||||
@@ -1,4 +1,4 @@
|
||||
import { DomainValidationException } from 'src/infrastructure/exceptions/domain-validation.exception';
|
||||
import { DomainValidationException } from '@exceptions';
|
||||
import { ValueObject } from '../base-classes/value-object.base';
|
||||
|
||||
export class DateVO extends ValueObject {
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ArgumentOutOfRangeException } from 'src/infrastructure/exceptions/argument-out-of-range.exception';
|
||||
import { ArgumentOutOfRangeException } from '@exceptions';
|
||||
import { ValueObject } from '../base-classes/value-object.base';
|
||||
import { Guard } from '../guard';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { NestEventEmitter } from 'nest-event';
|
||||
import { EventEmitterPort } from '../../application/ports/event-emitter.port';
|
||||
import { EventEmitterPort } from 'src/core/ports/event-emitter.port';
|
||||
|
||||
export class EventEmitterAdapter extends NestEventEmitter
|
||||
implements EventEmitterPort {}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { EntityProps } from 'src/domain/base-classes/entity.base';
|
||||
import { DateVO } from 'src/domain/value-objects/date.value-object';
|
||||
import { ID } from 'src/domain/value-objects/id.value-object';
|
||||
import { EntityProps } from 'src/core/base-classes/entity.base';
|
||||
import { DateVO } from 'src/core/value-objects/date.value-object';
|
||||
import { ID } from 'src/core/value-objects/id.value-object';
|
||||
import {
|
||||
CreateDateColumn,
|
||||
PrimaryGeneratedColumn,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { RepositoryPort } from 'src/application/ports/generic.ports';
|
||||
import { ID } from 'src/domain/value-objects/id.value-object';
|
||||
import { NotFoundException } from 'src/infrastructure/exceptions/not-found.exception';
|
||||
import { RepositoryPort } from 'src/core/ports/generic.ports';
|
||||
import { ID } from 'src/core/value-objects/id.value-object';
|
||||
import { NotFoundException } from '@exceptions';
|
||||
import { Repository } from 'typeorm';
|
||||
import { OrmEntityBase } from './orm-entity.base';
|
||||
|
||||
|
||||
@@ -9,10 +9,12 @@ import {
|
||||
} from '@nestjs/common';
|
||||
import { Observable, throwError } from 'rxjs';
|
||||
import { catchError } from 'rxjs/operators';
|
||||
import { ConflictException } from '../exceptions/conflict.exception';
|
||||
import { ExceptionBase } from '../exceptions/exception.base';
|
||||
import { InputValidationException } from '../exceptions/input-validation.exception';
|
||||
import { NotFoundException } from '../exceptions/not-found.exception';
|
||||
import {
|
||||
ExceptionBase,
|
||||
ConflictException,
|
||||
NotFoundException,
|
||||
InputValidationException,
|
||||
} from '@exceptions';
|
||||
|
||||
export class ExceptionInterceptor implements NestInterceptor {
|
||||
intercept(
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { EntityProps } from 'src/domain/base-classes/entity.base';
|
||||
import { EntityProps } from 'src/core/base-classes/entity.base';
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IdResponseDTO } from '../dtos/id.response.dto';
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { RepositoryPort } from 'src/application/ports/generic.ports';
|
||||
import { RepositoryPort } from 'src/core/ports/generic.ports';
|
||||
import { UserEntity } from '../domain/entities/user.entity';
|
||||
|
||||
/* Repository port belongs to application's core, but since it usually
|
||||
|
||||
@@ -3,7 +3,7 @@ import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { UserEntity } from 'src/modules/user/domain/entities/user.entity';
|
||||
import { NotFoundException } from 'src/infrastructure/exceptions/not-found.exception';
|
||||
import { NotFoundException } from '@exceptions';
|
||||
import { OrmEntityBase } from 'src/infrastructure/database/base-classes/orm-entity.base';
|
||||
import { UserOrmEntity } from './user.orm-entity';
|
||||
import { UserRepositoryPort } from './user.repository.interface';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Entity, EntityProps } from 'src/domain/base-classes/entity.base';
|
||||
import { Entity, EntityProps } from 'src/core/base-classes/entity.base';
|
||||
import { Address } from '../value-objects/address.value-object';
|
||||
import { Email } from '../value-objects/email.value-object';
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { ValueObject } from 'src/domain/base-classes/value-object.base';
|
||||
import { Guard } from 'src/domain/guard';
|
||||
import { ArgumentOutOfRangeException } from 'src/infrastructure/exceptions/argument-out-of-range.exception';
|
||||
import { DomainValidationException } from 'src/infrastructure/exceptions/domain-validation.exception';
|
||||
import { ValueObject } from 'src/core/base-classes/value-object.base';
|
||||
import { Guard } from 'src/core/guard';
|
||||
import {
|
||||
ArgumentOutOfRangeException,
|
||||
DomainValidationException,
|
||||
} from '@exceptions';
|
||||
|
||||
export interface AddressProps {
|
||||
country: string;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ValueObject } from 'src/domain/base-classes/value-object.base';
|
||||
import { DomainValidationException } from 'src/infrastructure/exceptions/domain-validation.exception';
|
||||
import { ValueObject } from 'src/core/base-classes/value-object.base';
|
||||
import { DomainValidationException } from '@exceptions';
|
||||
|
||||
export class Email extends ValueObject {
|
||||
constructor(value: string) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { On } from 'nest-event';
|
||||
import { UserEvents } from 'src/application/events/events';
|
||||
import { UserEvents } from 'src/core/events/events';
|
||||
import { UserEntity } from '../../domain/entities/user.entity';
|
||||
|
||||
export class CreateUserEventHandler {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { ID } from 'src/domain/value-objects/id.value-object';
|
||||
import { EventEmitterPort } from 'src/application/ports/event-emitter.port';
|
||||
import { UserEvents } from 'src/application/events/events';
|
||||
import { ID } from 'src/core/value-objects/id.value-object';
|
||||
import { EventEmitterPort } from 'src/core/ports/event-emitter.port';
|
||||
import { UserEvents } from 'src/core/events/events';
|
||||
import { UserRepositoryPort } from '@modules/user/database/user.repository.interface';
|
||||
import { ConflictException } from 'src/infrastructure/exceptions/conflict.exception';
|
||||
import { ConflictException } from '@exceptions';
|
||||
import { CreateUserCommand } from './create-user.command';
|
||||
import { UserEntity } from '../../domain/entities/user.entity';
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { EventEmitterPort } from 'src/application/ports/event-emitter.port';
|
||||
import { UserEvents } from 'src/application/events/events';
|
||||
import { EventEmitterPort } from 'src/core/ports/event-emitter.port';
|
||||
import { UserEvents } from 'src/core/events/events';
|
||||
import { UserRepositoryPort } from '@modules/user/database/user.repository.interface';
|
||||
|
||||
export class DeleteUserService {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { On } from 'nest-event';
|
||||
import { UserEvents } from 'src/application/events/events';
|
||||
import { UserEvents } from 'src/core/events/events';
|
||||
import { UserEntity } from '../../domain/entities/user.entity';
|
||||
|
||||
export class UserDeletedEventHandler {
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
"incremental": true,
|
||||
"paths": {
|
||||
"@modules/*": ["src/modules/*"],
|
||||
"@config/*": ["src/infrastructure/configs/*"]
|
||||
"@config/*": ["src/infrastructure/configs/*"],
|
||||
"@exceptions": ["./src/core/exceptions"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user