dynamodb-toolbox
dynamodb-toolbox copied to clipboard
Is There a Recommended Way to Create a Generic Repository in DynamoDB Toolbox?
Hello,
I've been using DynamoDB Toolbox extensively for various projects and find it to be a robust solution for working with AWS DynamoDB. In my projects, I generally define a Model and a Repository class for each entity in my database schema. While this approach works well, I notice that there's a lot of repetitive boilerplate code in each repository class that can be shared among all repositories.
To streamline this, I've been attempting to create a generic repository that contains common methods, which can be extended or aggregated in each individual repository. While I've managed to make it work to some extent using TypeScript's ts-ignore
and redefining the Query object, I wonder if there is a more elegant or recommended approach to achieve this goal.
Here's a stripped-down example of my current implementation in TypeScript:
interface UserModel {
// User attributes
}
interface PostModel {
// Post attributes
}
export const UserEntity = new Entity({
name: 'User',
attributes: {
// ...
},
table: Table,
} as const);
export const PostEntity = new Entity({
name: 'Post',
attributes: {
// ...
},
table: Table,
} as const);
class GenericRespository<M> {
constructor(
private readonly entity: Entity
) {}
async queryOne(pk: string, query?: Query): Promise<M | undefined> {
const result = await this.entity.query(pk, query);
if (result?.Items?.length > 0) {
return result.Items[0] as M;
}
return undefined;
}
// Other generic methods
}
class UserRepository {
private readonly genericRepo: GenericRespository<UserModel>;
constructor() {
this.genericRepo = new GenericRespository<UserModel>(UserEntity);
}
async getByUserId(userId: string): Promise<UserModel | undefined> {
return await this.genericRepo.queryOne(`userId:${userId}`);
}
// ...
}
class PostRepository {
private readonly genericRepo: GenericRespository<PostModel>;
constructor() {
this.genericRepo = new GenericRespository<PostModel>(PostEntity);
}
async getByPostId(postId: string): Promise<PostModel | undefined> {
return await this.genericRepo.queryOne(`postId:${postId}`);
}
// ...
}
Would love to get the community's thoughts on this, especially if there's a more idiomatic way to achieve what I am aiming for.
Thank you in advance for your guidance!