UNPKG

@avonjs/avonjs

Version:

A fluent Node.js API generator.

201 lines (200 loc) 6.8 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const joi_1 = __importDefault(require("joi")); const FieldCollection_1 = __importDefault(require("../Collections/FieldCollection")); const Contracts_1 = require("../Contracts"); const BelongsToFilter_1 = __importDefault(require("./Filters/BelongsToFilter")); const Relation_1 = __importDefault(require("./Relation")); class BelongsTo extends Relation_1.default { /** * Indicates trashed items have to be included in the related resource. */ withTrashed = true; /** * Prevent the trashed item from being included in the query. */ withoutTrashed() { this.withTrashed = false; return this; } /** * Mutate the field value for response. */ getMutatedValue(request, value) { return this.isLoaded() ? super.getMutatedValue(request, value)[0] : value; } /** * Hydrate the given attribute on the model based on the incoming request. */ fillForAction(request, model) { if (request.exists(this.attribute)) { model.setAttribute(this.attribute, this.relatedResource .resolveRepository(request) .find(request.input(this.attribute))); } } /** * Hydrate the given attribute on the model based on the incoming request. */ fillAttributeFromRequest(request, requestAttribute, model, attribute) { if (!request.exists(requestAttribute)) { this.fillAttributeFromDefault(request, model, this.foreignKeyName(request)); return; } const value = request.get(requestAttribute); model.setAttribute(this.foreignKeyName(request), this.isValidNullValue(value) ? this.nullValue() : value); return async (request, model) => { await request .newResource(model) .authorizeTo(request, Contracts_1.Ability.add, [ await this.getRelatedResource(request, value), ]); }; } /** * Get related models for given resources. */ async searchRelatables(request, resources) { const repository = this.relatedResource.resolveRepository(request).where({ key: this.ownerKeyName(request), value: resources .map((resource) => resource.getAttribute(this.foreignKeyName(request))) .filter((value) => value), operator: Contracts_1.Operator.in, }); const query = this.relatableQueryCallback.apply(repository, [request, repository]) ?? repository; return this.softDeletes() //@ts-ignore ? query.withTrashed().all() : query.all(); } /** * Format the given related resource. */ formatRelatedResource(request, resource) { const repository = this.relatedResource.resolveRepository(request); const softDeleted = this.softDeletes() && repository.isSoftDeleted(resource); return { ...new FieldCollection_1.default(this.relatableFields(request)) .resolve(resource) .fieldValues(request), softDeleted, }; } /** * Indicates related resource soft deletes applied. */ softDeletes() { return this.withTrashed && this.relatedResource.softDeletes(); } /** * Make the field filter. */ makeFilter(request) { return new BelongsToFilter_1.default(this); } /** * Determine field is resolvable or not. */ resolvable() { return true; } /** * Determine if the underlying file should be pruned when the resource is deleted. */ isPrunable() { return false; } /** * Determine field is orderable or not. */ isOrderable() { return true; } /** * Define orderable attribute. */ orderableAttribute(request) { return this.foreignKeyName(request); } /** * Get the validation rules for this field. */ getRules(request) { const rules = this.isNullable() ? joi_1.default.any().allow(null) : joi_1.default.any().required(); return { [this.attribute]: rules.external(async (value, { error }) => { if (this.isValidNullValue(value)) { return this.nullValue(); } if ((await this.getRelatedResource(request, value)) === undefined) { return error('any.custom', { error: new Error(`Related resource with ID:'${value}' not found`), }); } return value; }), }; } async getRelatedResource(request, id) { const repository = this.relatedResource.resolveRepository(request).where({ key: this.ownerKeyName(request), operator: Contracts_1.Operator.eq, value: id, }); // to ensure only valid data attached const query = this.relatableQueryCallback.apply(repository, [request, repository]) ?? repository; return query.first(); } /** * Get the base swagger-ui schema. */ baseSchema(request) { return { ...super.baseSchema(request), default: this.isNullable() ? null : this.resolveDefaultValue(request), type: 'number', oneOf: [{ type: 'string' }, { type: 'number' }], }; } payloadSchema(request) { return { ...this.baseSchema(request), default: this.isNullable() ? null : this.resolveDefaultValue(request), description: [ this.helpText, `use the "associable/${this.attribute}" to retrieve data`, ].join('</br>'), }; } /** * Get the swagger-ui schema. */ responseSchema(request) { if (!this.isLoaded()) { return this.baseSchema(request); } return { ...super.responseSchema(request), type: 'object', properties: { ...new FieldCollection_1.default(this.schemaFields(request)).responseSchemas(request), softDeleted: { type: 'boolean', default: false, description: 'Indicates whether the related resource is soft-deleted or not', }, }, default: null, nullable: true, oneOf: undefined, }; } } exports.default = BelongsTo;