Next.js + サーバーサイドTypeScript + 関数フレーバーでクリーンなアプリを作ったので実装意図とか書く Advent Calendar 2022
の11日目。株式会社mofmofに生息しているshwldです。
前日はエンティティバリデーションについて書きました
リポジトリ層
ORMとしてPrismaを使い、モデルの状態を永続化するため、モデルの状態ごとに永続化関数を書いています。
import { tryCatch } from 'core-domain';
import type { Aggregates } from 'core-domain';
import { db, handleError } from '../../lib/db';
import { convertToEntity } from './account-record';
import { picker } from '../../lib/picker';
// core-domainから集約のインタフェースを引っぱってきて型をつけます。
export const create: Aggregates['account']['create'] = input => {
const { id, createdById, ...columns } = input;
return tryCatch(
() =>
db.account
.create({
data: {
id,
...columns,
createdBy: {
connect: {
id: createdById,
},
},
accountMemberships: {
create: {
role: 'OWNER',
user: {
connect: {
id: createdById,
},
},
},
},
},
})
.then(convertToEntity),
handleError
);
};
/infrastructures/db/src/repositories/account/account-create.ts
インタフェースはこんな感じになっています。
create(attributes: Account_BuiltAttributes): Result<RuntimeError, AccountEntity>;
/domain/core/src/aggregates/repository-interfaces/account-repository.ts
PrismaはActiveRecordパターンではないので、慣れないRepositoryパターンを採用することになりましたが、一長一短あるなと感じつつも、レイヤーを分けるメリットはあるなと感じます。
結局テストの際にDBを入れずにテストしてもあまり意味があると思えないので、結局結合してテストしていて、あんま切り離す意味ないなーなどと感じなくもないですが、これは多分設計がイケてなくて、もっとリポジトリがコレクションを扱うことに徹するのが理想なんだろうか。
次回予告
明日はGraphQLサーバーを構成する要素について書きます。