import { BaseModel as LucidBaseModel } from '@ioc:Adonis/Lucid/Orm'; // import { ManyToManyQueryClient } from '@ioc:Adonis/Lucid/Orm'; // export class CustomManyToManyQueryClient extends ManyToManyQueryClient { // public attach( // relatedIds: any | any[], // pivotAttributes: any = {}, // trx?: ReturnType // ) { // return super.attach(relatedIds, (row) => { // row.pivot.fill(pivotAttributes); // }, trx); // } // } /** * Helper to find if value is a valid Object or * not */ export function isObject(value: any): boolean { return value !== null && typeof value === 'object' && !Array.isArray(value); } export default class BaseModel extends LucidBaseModel { /** * When `fill` method is called, then we may have a situation where it * removed the values which exists in `original` and hence the dirty * diff has to do a negative diff as well */ // private fillInvoked: boolean = false; public static fillable: string[] = []; public fill(attributes: any, allowExtraProperties: boolean = false): this { this.$attributes = {}; // const Model = this.constructor as typeof BaseModel; // for (const key in attributes) { // if (Model.fillable.includes(key)) { // const value = attributes[key]; // if (Model.$hasColumn(key)) { // this[key] = value; // } // } // } this.mergeFillableAttributes(attributes, allowExtraProperties); // this.fillInvoked = true; return this; } /** * Merge bulk attributes with existing attributes. * * 1. If key is unknown, it will be added to the `extras` object. * 2. If key is defined as a relationship, it will be ignored and one must call `$setRelated`. */ public mergeFillableAttributes(values: any, allowExtraProperties: boolean = false): this { const Model = this.constructor as typeof BaseModel; /** * Merge values with the attributes */ if (isObject(values)) { // Object.keys(values).forEach((key) => { for (const key in values) { if (Model.fillable.includes(key)) { const value = values[key]; /** * Set as column */ if (Model.$hasColumn(key)) { this[key] = value; continue; } /** * Resolve the attribute name from the column names. Since people * usaully define the column names directly as well by * accepting them directly from the API. */ const attributeName = Model.$keys.columnsToAttributes.get(key); if (attributeName) { this[attributeName] = value; continue; } /** * If key is defined as a relation, then ignore it, since one * must pass a qualified model to `this.$setRelated()` */ if (Model.$relationsDefinitions.has(key)) { continue; } /** * If the property already exists on the model, then set it * as it is vs defining it as an extra property */ if (this.hasOwnProperty(key)) { this[key] = value; continue; } /** * Raise error when not instructed to ignore non-existing properties. */ if (!allowExtraProperties) { throw new Error(`Cannot define "${key}" on "${Model.name}" model, since it is not defined as a model property`); } this.$extras[key] = value; } } } return this; } }