UNPKG

@avonjs/avonjs

Version:

A fluent Node.js API generator.

482 lines (481 loc) 13.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 Contracts_1 = require("../Contracts"); const AuthorizedToSee_1 = __importDefault(require("../Mixins/AuthorizedToSee")); const Filterable_1 = __importDefault(require("../Mixins/Filterable")); const Lookupable_1 = __importDefault(require("../Mixins/Lookupable")); const Nullable_1 = __importDefault(require("../Mixins/Nullable")); const Orderable_1 = __importDefault(require("../Mixins/Orderable")); const Presentable_1 = __importDefault(require("../Mixins/Presentable")); const mixin_1 = require("../support/mixin"); const TextFilter_1 = __importDefault(require("./Filters/TextFilter")); const Ordering_1 = __importDefault(require("./Orderings/Ordering")); class Field extends (0, mixin_1.mixin)(class { }, Lookupable_1.default, Nullable_1.default, Filterable_1.default, Orderable_1.default, Presentable_1.default, AuthorizedToSee_1.default) { /** * The attribute / column name of the field. */ attribute; /** * The validation attribute for the field. */ validationAttribute; /** * The field's resolved value. */ value; /** * The callback to be used to hydrate the model attribute. */ fillCallback; /** * The callback to be used to resolve the field's display value. */ displayCallback = (value, resource, attribute) => value; /** * The callback to be used to resolve the field's value. */ resolveCallback = (value, resource, attribute) => value; /** * The callback to be used for the field's default value. */ defaultCallback; /** * The validation rules callback for creation and updates. */ rulesSchema = joi_1.default.any(); /** * The validation rules callback for creation. */ creationRulesSchema = joi_1.default.any(); /** * The validation rules callback for updates. */ updateRulesSchema = joi_1.default.any(); /** * The help text for the field. */ helpText; /** * Custom label for the field. */ name; /** * Define the default orderable callback. */ defaultOrderingCallback() { return (request, repository, direction) => { repository.order({ key: this.orderableAttribute(request), direction: Contracts_1.Direction.ASC === direction ? Contracts_1.Direction.ASC : Contracts_1.Direction.DESC, }); }; } constructor(attribute, resolveCallback) { super(); this.attribute = attribute; if (resolveCallback !== undefined) { this.resolveCallback = resolveCallback; } } /** * Resolve the field's value for display. */ resolveForDisplay(resource, attribute) { this.resolve(resource, attribute); } /** * Resolve the field's value. */ resolve(resource, attribute) { const resolveAttribute = attribute ?? this.attribute; this.setValue(this.resolveCallback(this.resolveAttribute(resource, resolveAttribute), resource, resolveAttribute)); } /** * Resolve the given attribute from the given resource. */ resolveAttribute(resource, attribute) { return resource.getAttribute(attribute); } /** * Set the callback to be used for determining the field's default value. */ default(callback) { this.defaultCallback = callback; return this; } /** * Resolve the default value for the field. */ resolveDefaultValue(request) { if (request.isCreateOrAttachRequest() || request.isActionRequest() || request.isSchemaRequest()) { return this.defaultCallback?.apply(this, [request]); } } /** * Define the callback that should be used to display the field's value. */ displayUsing(displayCallback) { this.displayCallback = displayCallback; return this; } /** * Define the callback that should be used to resolve the field's value. */ resolveUsing(resolveCallback) { this.resolveCallback = resolveCallback; return this; } /** * Specify a callback that should be used to hydrate the model attribute for the field. */ fillUsing(fillCallback) { this.fillCallback = fillCallback; return this; } /** * Hydrate the given attribute on the model based on the incoming request. */ fill(request, model) { return this.fillInto(request, model, this.attribute); } /** * Hydrate the given attribute on the model based on the incoming request. */ fillForAction(request, model) { return this.fill(request, model); } /** * Hydrate the given attribute on the model based on the incoming request. */ fillInto(request, model, attribute, requestAttribute) { return this.fillAttribute(request, requestAttribute ?? this.attribute, model, attribute); } /** * Hydrate the given attribute on the model based on the incoming request. */ fillAttribute(request, requestAttribute, model, attribute) { return this.fillCallback !== undefined ? this.fillCallback(request, model, attribute, requestAttribute) : this.fillAttributeFromRequest(request, requestAttribute, model, 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, attribute); return; } const value = request.get(requestAttribute); model.setAttribute(attribute, this.isValidNullValue(value) ? this.nullValue() : value); } /** * Hydrate the given attribute on the model based on the default callback. */ fillAttributeFromDefault(request, model, attribute) { const value = this.resolveDefaultValue(request); if (value !== undefined) { model.setAttribute(attribute, this.isValidNullValue(value) ? this.nullValue() : value); } } /** * Get the value considered as null. */ nullValue() { return null; } /** * Set the value for the field. */ setValue(value) { this.value = value; return this; } /** * Set the validation rules for the field. */ rules(rules) { this.rulesSchema = this.rulesSchema.concat(rules); return this; } /** * Get the validation rules for this field. */ getRules(request) { return { [this.attribute]: this.rulesSchema }; } /** * Get the creation rules for this field. */ getCreationRules(request) { const rules = this.getRules(request); return { ...rules, [this.attribute]: rules[this.attribute].concat(this.creationRulesSchema), }; } /** * Set the creation validation rules for the field. */ creationRules(rules) { this.creationRulesSchema = this.creationRulesSchema.concat(rules); return this; } /** * Get the update rules for this field. */ getUpdateRules(request) { const rules = this.getRules(request); return { ...rules, [this.attribute]: rules[this.attribute].concat(this.updateRulesSchema), }; } /** * Set the creation validation rules for the field. */ updateRules(rules) { this.updateRulesSchema = this.updateRulesSchema.concat(rules); return this; } /** * Get the validation attribute for the field. */ getValidationAttribute(request) { return this.validationAttribute; } /** * Get field validator. */ validator() { return joi_1.default; } /** * Determine if the field is required. */ isRequired(request) { if (request.isResourceIndexRequest() || request.isActionRequest() || request.isCreateOrAttachRequest()) { return this.isRequiredForCreation(request); } if (request.isUpdateOrUpdateAttachedRequest()) { return this.isRequiredForUpdate(request); } return false; } /** * Determine if the field is required for creation. */ isRequiredForCreation(request) { const rules = this.getCreationRules(request)[this.attribute]; return rules.$_getFlag('presence') === 'required'; } /** * Determine if the field is required for update. */ isRequiredForUpdate(request) { const rules = this.getUpdateRules(request)[this.attribute]; return rules.$_getFlag('presence') === 'required'; } /** * Define filterable attribute. */ filterableAttribute(request) { return this.attribute; } /** * Define orderable attribute. */ orderableAttribute(request) { return this.attribute; } /** * Determine field is fillable or not. */ fillable() { return true; } /** * Determine field is resolvable or not. */ resolvable() { return true; } /** * Specify the field help text. */ help(helpText) { this.helpText = helpText; return this; } /** * Specify the field label. */ withName(name) { this.name = name; return this; } /** * Determine if the element should be displayed for the given request. */ authorize(request) { return this.authorizedToSee(request); } /** * Make the field filter. */ makeFilter(request) { return new TextFilter_1.default(this); } /** * Make the field filter. */ makeOrdering(request) { return new Ordering_1.default(this); } /** * Determine that the field should be nullable. */ nullable(nullable = true, validator) { super.nullable(nullable, validator); if (nullable) { this.rules(this.rulesSchema.allow(null)); } else { this.required(); } return this; } /** * Determine that the field should be filled in the request. */ required(required = true) { if (required) { this.rules(this.rulesSchema.required()); } return this; } /** * Determines that the field can be omitted from the request. */ optional(optional = true) { if (optional) { this.rules(this.rulesSchema.optional()); } return this; } /** * Get the value for the field. */ getValue(request) { if (this.value === undefined) { this.value = this.resolveDefaultValue(request); } const value = this.value !== undefined && !this.isValidNullValue(this.value) // ![undefined, this.nullValue()].includes(this.value) ? this.getMutatedValue(request, this.value) : this.nullValue(); return value ?? this.nullValue(); } /** * Get the swagger-ui schema. */ schema(request) { return { payload: this.payloadSchema(request), response: this.responseSchema(request), }; } /** * Get the swagger-ui schema. */ payloadSchema(request) { return this.baseSchema(request); } /** * Get the swagger-ui schema. */ responseSchema(request) { return this.baseSchema(request); } /** * Get the base swagger-ui schema. */ baseSchema(request) { return { type: 'string', nullable: this.isNullable(), description: this.helpText, title: this.name ?? this.attribute, default: this.resolveDefaultValue(request), }; } /** * Serialize parameters for schema. */ serializeParameters(request) { return [ { name: this.attribute, in: 'body', schema: this.schema(request).payload, }, ]; } lookupable(callback) { return super.lookupable(callback); } filterable(callback) { return super.filterable(callback); } orderable(callback) { return super.orderable(callback); } canSee(callback) { return super.canSee(callback); } hideFromIndex(callback) { return super.hideFromIndex(callback); } hideFromDetail(callback) { return super.hideFromDetail(callback); } hideWhenCreating(callback) { return super.hideWhenCreating(callback); } hideWhenUpdating(callback) { return super.hideWhenUpdating(callback); } showOnIndex(callback) { return super.showOnIndex(callback); } showOnDetail(callback) { return super.showOnDetail(callback); } showOnCreating(callback) { return super.showOnCreating(callback); } showOnUpdating(callback) { return super.showOnUpdating(callback); } onlyOnIndex() { return super.onlyOnIndex(); } onlyOnDetail() { return super.onlyOnDetail(); } onlyOnForms() { return super.onlyOnForms(); } exceptOnForms() { return super.exceptOnForms(); } } exports.default = Field;