"use strict"; var __defProp = Object.defineProperty; var __defProps = Object.defineProperties; var __getOwnPropDescs = Object.getOwnPropertyDescriptors; var __getOwnPropSymbols = Object.getOwnPropertySymbols; var __hasOwnProp = Object.prototype.hasOwnProperty; var __propIsEnum = Object.prototype.propertyIsEnumerable; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp.call(b, prop)) __defNormalProp(a, prop, b[prop]); if (__getOwnPropSymbols) for (var prop of __getOwnPropSymbols(b)) { if (__propIsEnum.call(b, prop)) __defNormalProp(a, prop, b[prop]); } return a; }; var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b)); const Utils = require("./../utils"); const Helpers = require("./helpers"); const _ = require("lodash"); const Association = require("./base"); const Op = require("../operators"); class HasMany extends Association { constructor(source, target, options) { super(source, target, options); this.associationType = "HasMany"; this.targetAssociation = null; this.sequelize = source.sequelize; this.isMultiAssociation = true; this.foreignKeyAttribute = {}; if (this.options.through) { throw new Error("N:M associations are not supported with hasMany. Use belongsToMany instead"); } if (this.isSelfAssociation) { this.targetAssociation = this; } if (this.as) { this.isAliased = true; if (_.isPlainObject(this.as)) { this.options.name = this.as; this.as = this.as.plural; } else { this.options.name = { plural: this.as, singular: Utils.singularize(this.as) }; } } else { this.as = this.target.options.name.plural; this.options.name = this.target.options.name; } if (_.isObject(this.options.foreignKey)) { this.foreignKeyAttribute = this.options.foreignKey; this.foreignKey = this.foreignKeyAttribute.name || this.foreignKeyAttribute.fieldName; } else if (this.options.foreignKey) { this.foreignKey = this.options.foreignKey; } if (!this.foreignKey) { this.foreignKey = Utils.camelize([ this.source.options.name.singular, this.source.primaryKeyAttribute ].join("_")); } if (this.target.rawAttributes[this.foreignKey]) { this.identifierField = this.target.rawAttributes[this.foreignKey].field || this.foreignKey; this.foreignKeyField = this.target.rawAttributes[this.foreignKey].field || this.foreignKey; } this.sourceKey = this.options.sourceKey || this.source.primaryKeyAttribute; if (this.source.rawAttributes[this.sourceKey]) { this.sourceKeyAttribute = this.sourceKey; this.sourceKeyField = this.source.rawAttributes[this.sourceKey].field || this.sourceKey; } else { this.sourceKeyAttribute = this.source.primaryKeyAttribute; this.sourceKeyField = this.source.primaryKeyField; } const plural = _.upperFirst(this.options.name.plural); const singular = _.upperFirst(this.options.name.singular); this.associationAccessor = this.as; this.accessors = { get: `get${plural}`, set: `set${plural}`, addMultiple: `add${plural}`, add: `add${singular}`, create: `create${singular}`, remove: `remove${singular}`, removeMultiple: `remove${plural}`, hasSingle: `has${singular}`, hasAll: `has${plural}`, count: `count${plural}` }; } _injectAttributes() { const newAttributes = { [this.foreignKey]: __spreadValues({ type: this.options.keyType || this.source.rawAttributes[this.sourceKeyAttribute].type, allowNull: true }, this.foreignKeyAttribute) }; const constraintOptions = __spreadValues({}, this.options); if (this.options.constraints !== false) { const target = this.target.rawAttributes[this.foreignKey] || newAttributes[this.foreignKey]; constraintOptions.onDelete = constraintOptions.onDelete || (target.allowNull ? "SET NULL" : "CASCADE"); constraintOptions.onUpdate = constraintOptions.onUpdate || "CASCADE"; } Helpers.addForeignKeyConstraints(newAttributes[this.foreignKey], this.source, this.target, constraintOptions, this.sourceKeyField); Utils.mergeDefaults(this.target.rawAttributes, newAttributes); this.target.refreshAttributes(); this.source.refreshAttributes(); this.identifierField = this.target.rawAttributes[this.foreignKey].field || this.foreignKey; this.foreignKeyField = this.target.rawAttributes[this.foreignKey].field || this.foreignKey; this.sourceKeyField = this.source.rawAttributes[this.sourceKey].field || this.sourceKey; Helpers.checkNamingCollision(this); return this; } mixin(obj) { const methods = ["get", "count", "hasSingle", "hasAll", "set", "add", "addMultiple", "remove", "removeMultiple", "create"]; const aliases = { hasSingle: "has", hasAll: "has", addMultiple: "add", removeMultiple: "remove" }; Helpers.mixinMethods(this, obj, methods, aliases); } async get(instances, options = {}) { const where = {}; let Model = this.target; let instance; let values; if (!Array.isArray(instances)) { instance = instances; instances = void 0; } options = __spreadValues({}, options); if (this.scope) { Object.assign(where, this.scope); } if (instances) { values = instances.map((_instance) => _instance.get(this.sourceKey, { raw: true })); if (options.limit && instances.length > 1) { options.groupedLimit = { limit: options.limit, on: this, values }; delete options.limit; } else { where[this.foreignKey] = { [Op.in]: values }; delete options.groupedLimit; } } else { where[this.foreignKey] = instance.get(this.sourceKey, { raw: true }); } options.where = options.where ? { [Op.and]: [where, options.where] } : where; if (Object.prototype.hasOwnProperty.call(options, "scope")) { if (!options.scope) { Model = Model.unscoped(); } else { Model = Model.scope(options.scope); } } if (Object.prototype.hasOwnProperty.call(options, "schema")) { Model = Model.schema(options.schema, options.schemaDelimiter); } const results = await Model.findAll(options); if (instance) return results; const result = {}; for (const _instance of instances) { result[_instance.get(this.sourceKey, { raw: true })] = []; } for (const _instance of results) { result[_instance.get(this.foreignKey, { raw: true })].push(_instance); } return result; } async count(instance, options) { options = Utils.cloneDeep(options); options.attributes = [ [ this.sequelize.fn("COUNT", this.sequelize.col(`${this.target.name}.${this.target.primaryKeyField}`)), "count" ] ]; options.raw = true; options.plain = true; const result = await this.get(instance, options); return parseInt(result.count, 10); } async has(sourceInstance, targetInstances, options) { const where = {}; if (!Array.isArray(targetInstances)) { targetInstances = [targetInstances]; } options = __spreadProps(__spreadValues({}, options), { scope: false, attributes: [this.target.primaryKeyAttribute], raw: true }); where[Op.or] = targetInstances.map((instance) => { if (instance instanceof this.target) { return instance.where(); } return { [this.target.primaryKeyAttribute]: instance }; }); options.where = { [Op.and]: [ where, options.where ] }; const associatedObjects = await this.get(sourceInstance, options); return associatedObjects.length === targetInstances.length; } async set(sourceInstance, targetInstances, options) { if (targetInstances === null) { targetInstances = []; } else { targetInstances = this.toInstanceArray(targetInstances); } const oldAssociations = await this.get(sourceInstance, __spreadProps(__spreadValues({}, options), { scope: false, raw: true })); const promises = []; const obsoleteAssociations = oldAssociations.filter((old) => !targetInstances.find((obj) => obj[this.target.primaryKeyAttribute] === old[this.target.primaryKeyAttribute])); const unassociatedObjects = targetInstances.filter((obj) => !oldAssociations.find((old) => obj[this.target.primaryKeyAttribute] === old[this.target.primaryKeyAttribute])); let updateWhere; let update; if (obsoleteAssociations.length > 0) { update = {}; update[this.foreignKey] = null; updateWhere = { [this.target.primaryKeyAttribute]: obsoleteAssociations.map((associatedObject) => associatedObject[this.target.primaryKeyAttribute]) }; promises.push(this.target.unscoped().update(update, __spreadProps(__spreadValues({}, options), { where: updateWhere }))); } if (unassociatedObjects.length > 0) { updateWhere = {}; update = {}; update[this.foreignKey] = sourceInstance.get(this.sourceKey); Object.assign(update, this.scope); updateWhere[this.target.primaryKeyAttribute] = unassociatedObjects.map((unassociatedObject) => unassociatedObject[this.target.primaryKeyAttribute]); promises.push(this.target.unscoped().update(update, __spreadProps(__spreadValues({}, options), { where: updateWhere }))); } await Promise.all(promises); return sourceInstance; } async add(sourceInstance, targetInstances, options = {}) { if (!targetInstances) return Promise.resolve(); targetInstances = this.toInstanceArray(targetInstances); const update = __spreadValues({ [this.foreignKey]: sourceInstance.get(this.sourceKey) }, this.scope); const where = { [this.target.primaryKeyAttribute]: targetInstances.map((unassociatedObject) => unassociatedObject.get(this.target.primaryKeyAttribute)) }; await this.target.unscoped().update(update, __spreadProps(__spreadValues({}, options), { where })); return sourceInstance; } async remove(sourceInstance, targetInstances, options = {}) { const update = { [this.foreignKey]: null }; targetInstances = this.toInstanceArray(targetInstances); const where = { [this.foreignKey]: sourceInstance.get(this.sourceKey), [this.target.primaryKeyAttribute]: targetInstances.map((targetInstance) => targetInstance.get(this.target.primaryKeyAttribute)) }; await this.target.unscoped().update(update, __spreadProps(__spreadValues({}, options), { where })); return this; } async create(sourceInstance, values, options = {}) { if (Array.isArray(options)) { options = { fields: options }; } if (values === void 0) { values = {}; } if (this.scope) { for (const attribute of Object.keys(this.scope)) { values[attribute] = this.scope[attribute]; if (options.fields) options.fields.push(attribute); } } values[this.foreignKey] = sourceInstance.get(this.sourceKey); if (options.fields) options.fields.push(this.foreignKey); return await this.target.create(values, options); } verifyAssociationAlias(alias) { if (typeof alias === "string") { return this.as === alias; } if (alias && alias.plural) { return this.as === alias.plural; } return !this.isAliased; } } module.exports = HasMany; module.exports.HasMany = HasMany; module.exports.default = HasMany; //# sourceMappingURL=has-many.js.map