obrigado-react-admin-backend-utils
Version:
Helper utilities for react-admin graphql backend.
377 lines • 17.3 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const type_graphql_1 = require("type-graphql");
const typeorm_1 = require("typeorm");
const apollo_server_errors_1 = require("apollo-server-errors");
const EntityUpdateHelper_1 = require("./EntityUpdateHelper");
const GQLReactAdminListParams_1 = require("./types/GQLReactAdminListParams");
const GQLReactAdminGetManyReferenceParams_1 = require("./types/GQLReactAdminGetManyReferenceParams");
const IdsList_1 = require("./types/IdsList");
const ReactAdminDataProvider_1 = require("./types/ReactAdminDataProvider");
function createBaseCrudResolver(objectTypeCls, inputTypeCls, ORMEntity, updateHelperOptions) {
console.warn("createBaseCrudResolver is deprececated");
return createAdminResolver({
create: inputTypeCls,
update: inputTypeCls,
return: objectTypeCls,
entity: ORMEntity,
updateHelperOptions
});
}
exports.createBaseCrudResolver = createBaseCrudResolver;
/**
* Generates base class for your resolver
* @param config Resolver config
*/
function createAdminResolver(config) {
const ORMEntity = config.entity;
const ReturnGQLClass = config.return;
const CreateGQLClass = config.create;
const UpdateGQLClass = config.update || config.create;
// @ts-ignore
const suffix = config.name || ORMEntity.name;
const updateHelperOptions = config.updateHelperOptions;
//@ts-ignore
let entityAlias = ORMEntity.name.toLowerCase();
let OutList = class OutList {
};
tslib_1.__decorate([
type_graphql_1.Field(type => [ReturnGQLClass], { nullable: true }),
tslib_1.__metadata("design:type", Object)
], OutList.prototype, "data", void 0);
tslib_1.__decorate([
type_graphql_1.Field(type => type_graphql_1.Int),
tslib_1.__metadata("design:type", Number)
], OutList.prototype, "total", void 0);
OutList = tslib_1.__decorate([
type_graphql_1.ObjectType(`${suffix}List`)
], OutList);
let BaseResolver = class BaseResolver extends ReactAdminDataProvider_1.ReactAdminDataProvider {
// GET LIST
async getListQuery(params, context) {
return this.getList(params, context);
}
async getList(params, context) {
const metadata = typeorm_1.getRepository(ORMEntity)
.metadata;
let query = typeorm_1.getRepository(ORMEntity).createQueryBuilder(entityAlias);
if (params.filter) {
this.applyFilterToQuery(query, params, metadata, context);
}
await this.alterGetListQuery(query, params);
let total = await query.getCount();
if (params.pagination) {
query
.take(params.pagination.perPage)
.skip(params.pagination.perPage *
(params.pagination.page - 1));
}
if (params.sort) {
query.orderBy(`${entityAlias}.${params.sort.field}`,
//@ts-ignore
params.sort.order);
}
let data = await query.getMany();
// @ts-ignore
return { data: data || [], total };
}
// GET ONE
async getOneQuery(id, context) {
return this.getOne(id, context);
}
async getOne(id, context) {
let where = {};
where[this.primaryKey] = id;
// @ts-ignore
return await typeorm_1.getRepository(ORMEntity).findOne({ where });
}
// GET_MANY
async getManyQuery(ids, context) {
return this.getMany(ids, context);
}
async getMany(ids, context) {
let where = {};
where[this.primaryKey] = typeorm_1.In(ids);
// @ts-ignore
return await typeorm_1.getRepository(ORMEntity).find({ where });
}
// GET_MANY_REFERENCE
async getManyReferenceQuery(params, context) {
return this.getManyReference(params, context);
}
async getManyReference(params, context) {
let query = typeorm_1.getRepository(ORMEntity).createQueryBuilder('entity').where(`entity.${params.target}=:id`, { id: params.id });
let total = await query.getCount();
if (params.pagination) {
query
.take(params.pagination.perPage)
.skip(params.pagination.perPage *
(params.pagination.page - 1));
}
if (params.sort) {
//@ts-ignore
query.orderBy(params.sort.field, params.sort.order);
}
return await { total, data: await query.getMany() };
}
// UPDATE
async updateMutation(id, data, context) {
return await this.update(id, data, context);
}
async update(id, data, context) {
let where = {};
where[this.primaryKey] = id;
let entity = await typeorm_1.getRepository(ORMEntity).findOne({ where });
if (!entity)
throw new apollo_server_errors_1.ApolloError('Entity not found for id ' + id, 'NOT_FOUND');
await EntityUpdateHelper_1.EntityUpdateHelper.update(entity, data, updateHelperOptions);
await typeorm_1.getRepository(ORMEntity).save(entity);
return entity;
}
//UPDATE_MANY
async updateManyMutation(ids, data, context) {
return this.updateMany(ids, data, context);
}
async updateMany(ids, data, context) {
let list = await typeorm_1.getRepository(ORMEntity).createQueryBuilder(entityAlias)
.whereInIds(ids)
.getMany();
for (let entity of list) {
await EntityUpdateHelper_1.EntityUpdateHelper.update(entity, data, updateHelperOptions);
await typeorm_1.getRepository(ORMEntity).save(entity);
}
return { ids };
}
//CREATE
async createMutation(data, context) {
return await this.create(data, context);
}
async create(data, context) {
let entity = typeorm_1.getRepository(ORMEntity).create();
await EntityUpdateHelper_1.EntityUpdateHelper.update(entity, data, updateHelperOptions);
await typeorm_1.getRepository(ORMEntity).save(entity);
return entity;
}
// DELETE
async deleteMutation(id, context) {
return this.delete(id, context);
}
async delete(id, context) {
// @ts-ignore
const entity = await validateEntityRelations(ORMEntity, id, this.primaryKey);
let clonedEntity = { ...entity };
// @ts-ignore
await typeorm_1.getRepository(ORMEntity).remove(entity);
return clonedEntity;
}
// DELETE_MANY
async deleteManyMutation(ids, context) {
return this.deleteMany(ids, context);
}
async deleteMany(ids, context) {
let errors = [];
let removedIds = [];
for (let id of ids) {
try {
// @ts-ignore
let entity = await validateEntityRelations(ORMEntity, id, this.primaryKey);
//@ts-ignore
await typeorm_1.getRepository(ORMEntity).remove(entity);
removedIds.push(id);
}
catch (e) {
errors.push(e.message);
}
}
if (errors.length > 0) {
throw new apollo_server_errors_1.ApolloError(errors.join(';'), 'DELETION_FAILED');
}
return { ids: removedIds };
}
async alterGetListQuery(qb, params) { }
applyFilterToQuery(qb, params, metadata, context) {
if (params.filter) {
let columnNames = metadata.columns.map(c => c.propertyName);
for (let f of params.filter) {
if (columnNames.includes(f.field)) {
let value = {};
value[f.field] = f.value;
qb.andWhere(`${entityAlias}.${f.field}=:${f.field}`, value);
}
else if (f.field === 'q') {
// build full text query
let ftColumnNames = [];
for (let ind of metadata.indices) {
if (ind.isFulltext) {
for (let column of ind.columns) {
ftColumnNames.push(`${entityAlias}.${column.propertyName}`);
}
}
}
let searchValue = f.value;
const specialCharacters = ['+', '*', '@', '%', '-', '(', ')', '"'];
specialCharacters.forEach(char => {
searchValue = searchValue.replace(char, '');
});
searchValue.length === 0 ? searchValue : searchValue = `${searchValue}*`;
if (ftColumnNames.length > 0)
qb.andWhere(`match(${ftColumnNames.join(',')}) against (:ftQuery IN BOOLEAN MODE)`, { ftQuery: searchValue });
}
}
}
}
get primaryKey() {
const metadata = typeorm_1.getRepository(ORMEntity).metadata;
return metadata.primaryColumns[0].databaseName;
}
};
tslib_1.__decorate([
type_graphql_1.Authorized('admin'),
type_graphql_1.Query(type => OutList, {
name: `admin${suffix}List`,
}),
tslib_1.__param(0, type_graphql_1.Arg('params', type => GQLReactAdminListParams_1.GQLReactAdminListParams)),
tslib_1.__param(1, type_graphql_1.Ctx()),
tslib_1.__metadata("design:type", Function),
tslib_1.__metadata("design:paramtypes", [GQLReactAdminListParams_1.GQLReactAdminListParams, Object]),
tslib_1.__metadata("design:returntype", Promise)
], BaseResolver.prototype, "getListQuery", null);
tslib_1.__decorate([
tslib_1.__param(1, type_graphql_1.Ctx()),
tslib_1.__metadata("design:type", Function),
tslib_1.__metadata("design:paramtypes", [GQLReactAdminListParams_1.GQLReactAdminListParams, Object]),
tslib_1.__metadata("design:returntype", Promise)
], BaseResolver.prototype, "getList", null);
tslib_1.__decorate([
type_graphql_1.Authorized('admin'),
type_graphql_1.Query(type => ReturnGQLClass, { name: `admin${suffix}GetOne` }),
tslib_1.__param(0, type_graphql_1.Arg('id')),
tslib_1.__param(1, type_graphql_1.Ctx()),
tslib_1.__metadata("design:type", Function),
tslib_1.__metadata("design:paramtypes", [String, Object]),
tslib_1.__metadata("design:returntype", Promise)
], BaseResolver.prototype, "getOneQuery", null);
tslib_1.__decorate([
type_graphql_1.Authorized('admin'),
type_graphql_1.Query(type => [ReturnGQLClass], {
name: `admin${suffix}GetMany`,
nullable: true,
}),
tslib_1.__param(0, type_graphql_1.Arg('ids', type => [type_graphql_1.Int])),
tslib_1.__param(1, type_graphql_1.Ctx()),
tslib_1.__metadata("design:type", Function),
tslib_1.__metadata("design:paramtypes", [Array, Object]),
tslib_1.__metadata("design:returntype", Promise)
], BaseResolver.prototype, "getManyQuery", null);
tslib_1.__decorate([
type_graphql_1.Authorized('admin'),
type_graphql_1.Query(type => OutList, {
name: `admin${suffix}GetManyReference`,
nullable: true,
}),
tslib_1.__param(0, type_graphql_1.Arg('params', type => GQLReactAdminGetManyReferenceParams_1.GQLReactAdminGetManyReferenceParams)),
tslib_1.__param(1, type_graphql_1.Ctx()),
tslib_1.__metadata("design:type", Function),
tslib_1.__metadata("design:paramtypes", [GQLReactAdminGetManyReferenceParams_1.GQLReactAdminGetManyReferenceParams, Object]),
tslib_1.__metadata("design:returntype", Promise)
], BaseResolver.prototype, "getManyReferenceQuery", null);
tslib_1.__decorate([
type_graphql_1.Authorized('admin'),
type_graphql_1.Mutation(type => ReturnGQLClass, { name: `admin${suffix}Update` }),
tslib_1.__param(0, type_graphql_1.Arg('id', type => type_graphql_1.Int)),
tslib_1.__param(1, type_graphql_1.Arg('data', type => UpdateGQLClass)),
tslib_1.__param(2, type_graphql_1.Ctx()),
tslib_1.__metadata("design:type", Function),
tslib_1.__metadata("design:paramtypes", [Number, Boolean, Object]),
tslib_1.__metadata("design:returntype", Promise)
], BaseResolver.prototype, "updateMutation", null);
tslib_1.__decorate([
type_graphql_1.Authorized('admin'),
type_graphql_1.Mutation(type => IdsList_1.IdsList, { name: `admin${suffix}UpdateMany` }),
tslib_1.__param(0, type_graphql_1.Arg('ids', type => [type_graphql_1.Int])),
tslib_1.__param(1, type_graphql_1.Arg('data', type => UpdateGQLClass)),
tslib_1.__param(2, type_graphql_1.Ctx()),
tslib_1.__metadata("design:type", Function),
tslib_1.__metadata("design:paramtypes", [Array, Boolean, Object]),
tslib_1.__metadata("design:returntype", Promise)
], BaseResolver.prototype, "updateManyMutation", null);
tslib_1.__decorate([
type_graphql_1.Authorized('admin'),
type_graphql_1.Mutation(type => ReturnGQLClass, { name: `admin${suffix}Create` }),
tslib_1.__param(0, type_graphql_1.Arg('data', type => CreateGQLClass)), tslib_1.__param(1, type_graphql_1.Ctx()),
tslib_1.__metadata("design:type", Function),
tslib_1.__metadata("design:paramtypes", [Boolean, Object]),
tslib_1.__metadata("design:returntype", Promise)
], BaseResolver.prototype, "createMutation", null);
tslib_1.__decorate([
type_graphql_1.Authorized('admin'),
type_graphql_1.Mutation(type => ReturnGQLClass, { name: `admin${suffix}Delete` }),
tslib_1.__param(0, type_graphql_1.Arg('id', type => type_graphql_1.Int)),
tslib_1.__param(1, type_graphql_1.Ctx()),
tslib_1.__metadata("design:type", Function),
tslib_1.__metadata("design:paramtypes", [Number, Object]),
tslib_1.__metadata("design:returntype", Promise)
], BaseResolver.prototype, "deleteMutation", null);
tslib_1.__decorate([
type_graphql_1.Authorized('admin'),
type_graphql_1.Mutation(type => IdsList_1.IdsList, { name: `admin${suffix}DeleteMany` }),
tslib_1.__param(0, type_graphql_1.Arg('ids', type => [type_graphql_1.Int])),
tslib_1.__param(1, type_graphql_1.Ctx()),
tslib_1.__metadata("design:type", Function),
tslib_1.__metadata("design:paramtypes", [Array, Object]),
tslib_1.__metadata("design:returntype", Promise)
], BaseResolver.prototype, "deleteManyMutation", null);
BaseResolver = tslib_1.__decorate([
type_graphql_1.Resolver({ isAbstract: true })
], BaseResolver);
//@ts-ignore
return BaseResolver;
}
exports.createAdminResolver = createAdminResolver;
async function validateEntityRelations(entityClass, id, primaryKey) {
const metadata = typeorm_1.getRepository(entityClass).metadata;
let errors = [];
let rQuery = await typeorm_1.createQueryBuilder(entityClass, 'entity').where(`entity.${primaryKey}=:id`, { id });
for (let r of metadata.relations) {
if (r.onDelete !== 'CASCADE' && !r.isCascadeRemove
&& !r.isManyToOne) {
rQuery.loadRelationCountAndMap(`entity.${r.propertyName}_count`, `entity.${r.propertyName}`);
}
}
let dataCounts = await rQuery.getOne();
for (let r of metadata.relations) {
//@ts-ignore
if (!r.isCascadeRemove &&
dataCounts &&
// @ts-ignore
dataCounts[`${r.propertyName}_count`] > 0) {
//@ts-ignore
let count = dataCounts[`${r.propertyName}_count`];
//@ts-ignore
errors.push(`${r.type.name} (${count})`);
}
}
if (errors.length > 0) {
throw new apollo_server_errors_1.ApolloError(`Entity ${id} has linked data : ${errors.join(',')}, unlink it first`, 'DELETION_FAILED');
}
//@ts-ignore
return dataCounts;
}
exports.validateEntityRelations = validateEntityRelations;
/*
import {GQLAdministrator} from "./types/GQLAdministrator"
import {GQLAdministratorInput} from "./types/GQLAdministratorInput"
import {Administrator} from "./models/Administrator"
const ZZZ=createAdminResolver({
return:GQLAdministrator,
create:GQLAdministratorInput,
update:GQLAdministrator,
entity:Administrator
})
class YYYY extends ZZZ{
async update(id: number, data: GQLAdministrator extends undefined ? GQLAdministratorInput : GQLAdministrator, context?: any): Promise<any> {
return super.update(id, data, context)
}
}*/
//# sourceMappingURL=BaseAdminResourceResolver.js.map