You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
316 lines
12 KiB
316 lines
12 KiB
"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
|
|
|