mikro-orm-find-dataloader
Version:
Additional dataloaders for the MikroORM EntityManager find/findOne/etc methods.
139 lines (138 loc) • 6.3 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.EntityDataLoader = void 0;
/* eslint-disable @typescript-eslint/dot-notation */
/* eslint-disable @typescript-eslint/ban-types */
/* eslint-disable @typescript-eslint/array-type */
const core_1 = require("@mikro-orm/core");
const dataloader_1 = __importDefault(require("dataloader"));
const findDataloader_1 = require("./findDataloader");
class EntityDataLoader {
em;
bypass;
findLoader;
constructor(em, bypass = false) {
this.em = em;
this.bypass = bypass;
this.findLoader = new dataloader_1.default(async (dataloaderFinds) => {
const queriesMap = (0, findDataloader_1.groupFindQueries)(dataloaderFinds);
(0, findDataloader_1.assertHasNewFilterAndMapKey)(dataloaderFinds);
const resultsMap = new Map();
await Promise.all(Array.from(queriesMap, async ([key, [filter, options]]) => {
const entityName = key.substring(0, key.indexOf("|"));
let entitiesOrError;
const findOptions = {
...(options?.populate != null && {
populate: options.populate === true ? ["*"] : Array.from(options.populate),
}),
};
try {
entitiesOrError = await em.getRepository(entityName).find(filter, findOptions);
}
catch (e) {
entitiesOrError = e;
}
resultsMap.set(key, entitiesOrError);
}));
return dataloaderFinds.map(({ filtersAndKeys, many }) => {
const res = filtersAndKeys.reduce((acc, { key, newFilter }) => {
const entitiesOrError = resultsMap.get(key);
if (entitiesOrError == null) {
throw new Error("Cannot match results");
}
if (!(entitiesOrError instanceof Error)) {
const res = entitiesOrError[many ? "filter" : "find"]((entity) => {
return filterResult(entity, newFilter);
});
acc.push(...(Array.isArray(res) ? res : [res]));
return acc;
}
else {
throw entitiesOrError;
}
}, []);
return many ? res : res[0] ?? null;
});
function filterResult(entity, filter) {
for (const [key, value] of Object.entries(filter)) {
const entityValue = entity[key];
if (Array.isArray(value)) {
if (Array.isArray(entityValue)) {
// Collection
if (!value.every((el) => entityValue.includes(el))) {
return false;
}
}
else {
// Single value
if (!value.includes(entityValue)) {
return false;
}
}
}
else {
// Object: recursion
if (!filterResult(entityValue, value)) {
return false;
}
}
}
return true;
}
});
}
async find(repoOrClass, filter, options) {
// Property 'entityName' is protected and only accessible within class 'EntityRepository<Entity>' and its subclasses.
const entityName = core_1.Utils.className(repoOrClass instanceof core_1.EntityRepository ? repoOrClass["entityName"] : repoOrClass);
return (options?.bypass ?? this.bypass)
? await (repoOrClass instanceof core_1.EntityRepository
? repoOrClass.find(filter, options)
: this.em.find(repoOrClass, filter, options))
: await this.findLoader.load({
entityName,
meta: this.em.getMetadata().get(entityName),
filter: filter,
options: options,
many: true,
});
}
async findOne(repoOrClass, filter, options) {
// Property 'entityName' is protected and only accessible within class 'EntityRepository<Entity>' and its subclasses.
const entityName = core_1.Utils.className(repoOrClass instanceof core_1.EntityRepository ? repoOrClass["entityName"] : repoOrClass);
return (options?.bypass ?? this.bypass)
? await (repoOrClass instanceof core_1.EntityRepository
? repoOrClass.findOne(filter, options)
: this.em.findOne(repoOrClass, filter, options))
: await this.findLoader.load({
entityName,
meta: this.em.getMetadata().get(entityName),
filter: filter,
options: options,
many: false,
});
}
async findOneOrFail(repoOrClass, filter, options) {
// Property 'entityName' is protected and only accessible within class 'EntityRepository<Entity>' and its subclasses.
const entityName = core_1.Utils.className(repoOrClass instanceof core_1.EntityRepository ? repoOrClass["entityName"] : repoOrClass);
if (options?.bypass ?? this.bypass) {
return await (repoOrClass instanceof core_1.EntityRepository
? repoOrClass.findOneOrFail(filter, options)
: this.em.findOneOrFail(repoOrClass, filter, options));
}
const one = (await this.findLoader.load({
entityName,
meta: this.em.getMetadata().get(entityName),
filter: filter,
options: options,
many: false,
}));
if (one == null) {
throw new Error("Cannot find result");
}
return one;
}
}
exports.EntityDataLoader = EntityDataLoader;