【发布时间】:2021-10-05 13:43:41
【问题描述】:
我开始学习如何基于 TypeScript 和 NestJS 构建 Clean Architecture。在我开始实现存储库适配器和控制器之前,一切都很好。主要问题是 API 方法和用例的返回类型不兼容。
想法是将实体和用例放在 core 文件夹中,其中用例使用存储库适配器(通过 DI)。此适配器也实现了 core 文件夹中的存储库接口。
app 中包含的存储库适配器的实现。 app 还包含 NestJS 实现、TypeOrm 实体等。但我也想为一些控制器使用存储库,例如 getAll query。
!!!还有问题!!!
对于几乎每个命令,我都必须使用Mappers,因为 TypeORM 实体和域实体是不兼容的类型。我认为如果我们将这些数据传递给用例就可以了,因为我们需要将数据从 TypeOrm 形状转换为域形状。
但是如果我只是在控制器中调用存储库适配器方法,我需要再次将数据映射回来......而且我不知道如何跳过不必要的步骤。
在我的想象中,我可以在app服务中调用repository方法,就是这样。
如果我跳过映射,那么所有数据属性都将具有前缀 _(
也许有人遇到过同样的问题?
//核心区
帐户实体 (/domain/account):
export type AccountId = string;
export class Account {
constructor(
private readonly _id: AccountId,
private readonly _firstName: string
) {}
get id(): AccountId {
return this._id;
}
get firstName() {
return this._firstName;
}
}
存储库接口(@987654326@):
import { Account } from '../domains/account';
export interface AccountRepository {
getAccountById(id: string): Promise<Account>;
getAllAccounts(): Promise<Account[]>;
}
存储库用例示例:
import { AccountRepository } from '../../repositories/account-repository';
export class ToDoSomething {
constructor(private readonly _accountRepository: AccountRepository) {}
async doSomethingWithAccount(command): Promise<boolean> {
const account = await this._accountRepository.getAccountById(
command.accountId,
);
if (!account) {
return false;
}
return true;
}
}
//应用专区
存储库适配器:
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Account } from '../../../../core/domains/account';
import { AccountRepository } from '../../../../core/repositories/account-repository';
import { AccountEntity } from '../account.entity';
import { AccountMapper } from '../account.mapper';
@Injectable()
export class AccountRepositoryAdapter implements AccountRepository {
constructor(
@InjectRepository(AccountEntity)
private readonly _accountRepository: Repository<AccountEntity>,
) {}
async getAccountById(id: string): Promise<Account> {
return this._accountRepository.findOne({ id: id });
// will return { id: 1, firstName: "name" }
// and because I need to use MapToDomain
}
async getAllAccounts(): Promise<Account[]> {
return this._accountRepository.find();
// Here too I need to use MapToDomain for every item
}
}
TypeOrm 帐户:
import {
Column,
Entity,
PrimaryGeneratedColumn,
} from 'typeorm';
@Entity({ name: 'account' })
export class AccountEntity {
@PrimaryGeneratedColumn()
id: string;
@Column()
firstName: string;
}
【问题讨论】:
标签: typescript backend nestjs typeorm clean-architecture