has-one.js 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. "use strict";
  2. var __defProp = Object.defineProperty;
  3. var __defProps = Object.defineProperties;
  4. var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
  5. var __getOwnPropSymbols = Object.getOwnPropertySymbols;
  6. var __hasOwnProp = Object.prototype.hasOwnProperty;
  7. var __propIsEnum = Object.prototype.propertyIsEnumerable;
  8. var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
  9. var __spreadValues = (a, b) => {
  10. for (var prop in b || (b = {}))
  11. if (__hasOwnProp.call(b, prop))
  12. __defNormalProp(a, prop, b[prop]);
  13. if (__getOwnPropSymbols)
  14. for (var prop of __getOwnPropSymbols(b)) {
  15. if (__propIsEnum.call(b, prop))
  16. __defNormalProp(a, prop, b[prop]);
  17. }
  18. return a;
  19. };
  20. var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
  21. const Utils = require("./../utils");
  22. const Helpers = require("./helpers");
  23. const _ = require("lodash");
  24. const Association = require("./base");
  25. const Op = require("../operators");
  26. class HasOne extends Association {
  27. constructor(source, target, options) {
  28. super(source, target, options);
  29. this.associationType = "HasOne";
  30. this.isSingleAssociation = true;
  31. this.foreignKeyAttribute = {};
  32. if (this.as) {
  33. this.isAliased = true;
  34. this.options.name = {
  35. singular: this.as
  36. };
  37. } else {
  38. this.as = this.target.options.name.singular;
  39. this.options.name = this.target.options.name;
  40. }
  41. if (_.isObject(this.options.foreignKey)) {
  42. this.foreignKeyAttribute = this.options.foreignKey;
  43. this.foreignKey = this.foreignKeyAttribute.name || this.foreignKeyAttribute.fieldName;
  44. } else if (this.options.foreignKey) {
  45. this.foreignKey = this.options.foreignKey;
  46. }
  47. if (!this.foreignKey) {
  48. this.foreignKey = Utils.camelize([
  49. Utils.singularize(this.options.as || this.source.name),
  50. this.source.primaryKeyAttribute
  51. ].join("_"));
  52. }
  53. if (this.options.sourceKey && !this.source.rawAttributes[this.options.sourceKey]) {
  54. throw new Error(`Unknown attribute "${this.options.sourceKey}" passed as sourceKey, define this attribute on model "${this.source.name}" first`);
  55. }
  56. this.sourceKey = this.sourceKeyAttribute = this.options.sourceKey || this.source.primaryKeyAttribute;
  57. this.sourceKeyField = this.source.rawAttributes[this.sourceKey].field || this.sourceKey;
  58. this.sourceKeyIsPrimary = this.sourceKey === this.source.primaryKeyAttribute;
  59. this.associationAccessor = this.as;
  60. this.options.useHooks = options.useHooks;
  61. if (this.target.rawAttributes[this.foreignKey]) {
  62. this.identifierField = this.target.rawAttributes[this.foreignKey].field || this.foreignKey;
  63. }
  64. const singular = _.upperFirst(this.options.name.singular);
  65. this.accessors = {
  66. get: `get${singular}`,
  67. set: `set${singular}`,
  68. create: `create${singular}`
  69. };
  70. }
  71. _injectAttributes() {
  72. const newAttributes = {
  73. [this.foreignKey]: __spreadValues({
  74. type: this.options.keyType || this.source.rawAttributes[this.sourceKey].type,
  75. allowNull: true
  76. }, this.foreignKeyAttribute)
  77. };
  78. if (this.options.constraints !== false) {
  79. const target = this.target.rawAttributes[this.foreignKey] || newAttributes[this.foreignKey];
  80. this.options.onDelete = this.options.onDelete || (target.allowNull ? "SET NULL" : "CASCADE");
  81. this.options.onUpdate = this.options.onUpdate || "CASCADE";
  82. }
  83. Helpers.addForeignKeyConstraints(newAttributes[this.foreignKey], this.source, this.target, this.options, this.sourceKeyField);
  84. Utils.mergeDefaults(this.target.rawAttributes, newAttributes);
  85. this.target.refreshAttributes();
  86. this.identifierField = this.target.rawAttributes[this.foreignKey].field || this.foreignKey;
  87. Helpers.checkNamingCollision(this);
  88. return this;
  89. }
  90. mixin(obj) {
  91. const methods = ["get", "set", "create"];
  92. Helpers.mixinMethods(this, obj, methods);
  93. }
  94. async get(instances, options) {
  95. const where = {};
  96. let Target = this.target;
  97. let instance;
  98. options = Utils.cloneDeep(options);
  99. if (Object.prototype.hasOwnProperty.call(options, "scope")) {
  100. if (!options.scope) {
  101. Target = Target.unscoped();
  102. } else {
  103. Target = Target.scope(options.scope);
  104. }
  105. }
  106. if (Object.prototype.hasOwnProperty.call(options, "schema")) {
  107. Target = Target.schema(options.schema, options.schemaDelimiter);
  108. }
  109. if (!Array.isArray(instances)) {
  110. instance = instances;
  111. instances = void 0;
  112. }
  113. if (instances) {
  114. where[this.foreignKey] = {
  115. [Op.in]: instances.map((_instance) => _instance.get(this.sourceKey))
  116. };
  117. } else {
  118. where[this.foreignKey] = instance.get(this.sourceKey);
  119. }
  120. if (this.scope) {
  121. Object.assign(where, this.scope);
  122. }
  123. options.where = options.where ? { [Op.and]: [where, options.where] } : where;
  124. if (instances) {
  125. const results = await Target.findAll(options);
  126. const result = {};
  127. for (const _instance of instances) {
  128. result[_instance.get(this.sourceKey, { raw: true })] = null;
  129. }
  130. for (const _instance of results) {
  131. result[_instance.get(this.foreignKey, { raw: true })] = _instance;
  132. }
  133. return result;
  134. }
  135. return Target.findOne(options);
  136. }
  137. async set(sourceInstance, associatedInstance, options) {
  138. options = __spreadProps(__spreadValues({}, options), { scope: false });
  139. const oldInstance = await sourceInstance[this.accessors.get](options);
  140. const alreadyAssociated = oldInstance && associatedInstance && this.target.primaryKeyAttributes.every((attribute) => oldInstance.get(attribute, { raw: true }) === (associatedInstance.get ? associatedInstance.get(attribute, { raw: true }) : associatedInstance));
  141. if (oldInstance && !alreadyAssociated) {
  142. oldInstance[this.foreignKey] = null;
  143. await oldInstance.save(__spreadProps(__spreadValues({}, options), {
  144. fields: [this.foreignKey],
  145. allowNull: [this.foreignKey],
  146. association: true
  147. }));
  148. }
  149. if (associatedInstance && !alreadyAssociated) {
  150. if (!(associatedInstance instanceof this.target)) {
  151. const tmpInstance = {};
  152. tmpInstance[this.target.primaryKeyAttribute] = associatedInstance;
  153. associatedInstance = this.target.build(tmpInstance, {
  154. isNewRecord: false
  155. });
  156. }
  157. Object.assign(associatedInstance, this.scope);
  158. associatedInstance.set(this.foreignKey, sourceInstance.get(this.sourceKeyAttribute));
  159. return associatedInstance.save(options);
  160. }
  161. return null;
  162. }
  163. async create(sourceInstance, values, options) {
  164. values = values || {};
  165. options = options || {};
  166. if (this.scope) {
  167. for (const attribute of Object.keys(this.scope)) {
  168. values[attribute] = this.scope[attribute];
  169. if (options.fields) {
  170. options.fields.push(attribute);
  171. }
  172. }
  173. }
  174. values[this.foreignKey] = sourceInstance.get(this.sourceKeyAttribute);
  175. if (options.fields) {
  176. options.fields.push(this.foreignKey);
  177. }
  178. return await this.target.create(values, options);
  179. }
  180. verifyAssociationAlias(alias) {
  181. if (typeof alias === "string") {
  182. return this.as === alias;
  183. }
  184. if (alias && alias.singular) {
  185. return this.as === alias.singular;
  186. }
  187. return !this.isAliased;
  188. }
  189. }
  190. module.exports = HasOne;
  191. //# sourceMappingURL=has-one.js.map