UNPKG

@adminjs/mikroorm

Version:
162 lines 5.61 kB
/* eslint-disable no-param-reassign */ import { BaseResource, BaseRecord, ValidationError, flat, } from 'adminjs'; import { wrap, ReferenceKind, } from '@mikro-orm/core'; import { Property } from './Property.js'; import { convertFilter } from './utils/convert-filter.js'; export class Resource extends BaseResource { static validate; orm; metadata; model; propertiesObject; constructor(args) { super(args); const { model, orm } = args; this.orm = orm; this.model = model; this.metadata = this.orm.getMetadata().find(model.name); this.propertiesObject = this.prepareProperties(); } databaseName() { const { database } = this.orm.config .getDriver() .getConnection() .getConnectionOptions(); return database || 'mikroorm'; } databaseType() { return this.databaseName(); } name() { return this.metadata?.name ?? this.metadata?.className ?? ''; } id() { return this.name(); } properties() { return [...Object.values(this.propertiesObject)]; } property(path) { return this.propertiesObject[path]; } build(params) { return new BaseRecord(flat.unflatten(params), this); } async count(filter) { return this.orm.em .fork() .getRepository(this.model) .count(convertFilter(filter)); } async find(filter, params = {}) { const { limit = 10, offset = 0, sort = {} } = params; const { direction, sortBy } = sort; const results = await this.orm.em .fork() .getRepository(this.model) .find(convertFilter(filter), { orderBy: { [sortBy]: direction, }, limit, offset, }); return results.map((result) => new BaseRecord(wrap(result).toObject(), this)); } async findOne(id) { const result = await this.orm.em .fork() .getRepository(this.model) .findOne(id); // mikroorm has incorrect types for `findOne` if (!result) return null; return new BaseRecord(wrap(result).toObject(), this); } async findMany(ids) { const pk = this.metadata?.primaryKeys[0]; if (!pk) return []; const results = await this.orm.em .fork() .getRepository(this.model) .find({ [pk]: { $in: ids } }); return results.map((result) => new BaseRecord(wrap(result).toObject(), this)); } async create(params) { const em = this.orm.em.fork(); const instance = em .getRepository(this.model) .create(flat.unflatten(params)); await this.validateAndSave(instance, em); const returnedParams = flat.flatten(wrap(instance).toObject()); return returnedParams; } async update(pk, params = {}) { const em = this.orm.em.fork(); const instance = await em.getRepository(this.model).findOne(pk); if (!instance) throw new Error('Record to update not found'); const updatedInstance = wrap(instance).assign(flat.unflatten(params)); await this.validateAndSave(updatedInstance, em); const returnedParams = flat.flatten(wrap(updatedInstance).toObject()); return returnedParams; } async delete(id) { await this.orm.em .fork() .getRepository(this.model) .nativeDelete(id); // mikroorm has incorrect types for nativeDelete } static isAdapterFor(args) { const { model, orm } = args ?? {}; return !!model?.name && !!orm?.getMetadata?.().find?.(model.name); } async validateAndSave(instance, em) { if (Resource.validate) { const errors = await Resource.validate(instance); if (errors && errors.length) { const validationErrors = errors.reduce((memo, error) => ({ ...memo, [error.property]: { type: Object.keys(error.constraints)[0], message: Object.values(error.constraints)[0], }, }), {}); throw new ValidationError(validationErrors); } } try { await em.persistAndFlush(instance); } catch (error) { // TODO: figure out how to get column name from MikroORM's error metadata // It currently seems to return only whole Entity console.log(error); if (error.name === 'QueryFailedError' || error.name === 'ValidationError') { throw new ValidationError({ [error.column]: { type: 'QueryFailedError', message: error.message, }, }); } } } prepareProperties() { const { hydrateProps = [] } = this.metadata ?? {}; return hydrateProps.reduce((memo, prop, index) => { if (![ ReferenceKind.SCALAR, ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE, ReferenceKind.MANY_TO_MANY, ].includes(prop.kind)) return memo; const property = new Property(prop, index); memo[property.path()] = property; return memo; }, {}); } } //# sourceMappingURL=Resource.js.map