Currently, I am working on incorporating the repository generic pattern with Facebook dataloader for a GraphQL API.
In an abstract base class where the error occurs, here is the code snippet:
import { Collection, Db, InsertOneWriteOpResult, ObjectId } from "mongodb";
import { RepositoryGeneric } from "../../types/database";
export default abstract class BaseRepository<TEntity, TLoaders> implements RepositoryGeneric<TEntity> {
protected mongoCollection: Collection<TEntity>;
protected dataLoaders: TLoaders;
public constructor(database: Db, collection: string, loaders: TLoaders) {
this.mongoCollection = database.collection(collection);
this.dataLoaders = loaders;
}
public async findOne(id: ObjectId | string): Promise<TEntity | null> {
if (typeof id === "string") {
id = ObjectId.createFromHexString(id);
}
// The issue arises at this line
return this.dataLoaders.id.load(id);
}
public async create(entity: TEntity): Promise<TEntity> {
const result: InsertOneWriteOpResult = await this.mongoCollection.insertOne(entity);
if (!result.result.ok) {
throw new Error();
}
return result.ops[0];
}
}
The next section showcases a class that extends the aforementioned abstract base class:
import { MongoClient } from "mongodb";
import { EntityBusiness } from "../../types/database";
import BusinessLoaders from "../loaders/businessLoaders";
import BaseRepository from "./baseRepository";
export default class BusinessRepository extends BaseRepository<EntityBusiness, BusinessLoaders> {
public constructor(mongoClient: MongoClient, businessLoaders: BusinessLoaders) {
super(mongoClient.db(), "business", businessLoaders);
// Ensure no errors are present
console.log(businessLoaders.id);
}
}
Lastly, there's a class focused on implementing the dataloader functionality:
import DataLoader from "dataloader";
import { AggregationCursor, Collection, MongoClient, ObjectId } from "mongodb";
import { EntityBusiness, LoaderCommon } from "../../types/database";
export default class BusinessLoaders implements LoaderCommon<EntityBusiness> {
private idLoader: DataLoader<ObjectId, EntityBusiness>;
public constructor(mongoClient: MongoClient) {
this.idLoader = new DataLoader((keys) => this.idBatch(mongoClient, keys), {
cacheKeyFn: (key) => key.toHexString(),
});
}
public get id(): DataLoader<ObjectId, EntityBusiness> {
return this.idLoader;
}
private async idBatch(mongoClient: MongoClient, keys: ObjectId[]): Promise<EntityBusiness[]> {
const collection: Collection<EntityBusiness> = mongoClient.db().collection("business");
const aggregation: AggregationCursor<EntityBusiness> = collection.aggregate([
{ $match: { _id: { $in: keys } } },
{ $addFields: { __order: { $indexOfArray: [keys, "$_id"] } } },
{ $sort: { __order: 1 } },
{ $project: { __order: 0 } },
]);
return aggregation.toArray();
}
}
Even though I lack extensive experience in typescript, I didn't anticipate any errors but encountered the following:
Error TS2339: Property 'id' does not exist on type 'TLoaders'.