UNPKG

typed-wx-api

Version:
1,224 lines 110 kB
"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 assert = require("assert"); const _ = require("lodash"); const Dottie = require("dottie"); const Utils = require("./utils"); const { logger } = require("./utils/logger"); const BelongsTo = require("./associations/belongs-to"); const BelongsToMany = require("./associations/belongs-to-many"); const InstanceValidator = require("./instance-validator"); const QueryTypes = require("./query-types"); const sequelizeErrors = require("./errors"); const Association = require("./associations/base"); const HasMany = require("./associations/has-many"); const DataTypes = require("./data-types"); const Hooks = require("./hooks"); const associationsMixin = require("./associations/mixin"); const Op = require("./operators"); const { noDoubleNestedGroup } = require("./utils/deprecations"); const validQueryKeywords = /* @__PURE__ */ new Set([ "where", "attributes", "paranoid", "include", "order", "limit", "offset", "transaction", "lock", "raw", "logging", "benchmark", "having", "searchPath", "rejectOnEmpty", "plain", "scope", "group", "through", "defaults", "distinct", "primary", "exception", "type", "hooks", "force", "name" ]); const nonCascadingOptions = ["include", "attributes", "originalAttributes", "order", "where", "limit", "offset", "plain", "group", "having"]; class Model { static get queryInterface() { return this.sequelize.getQueryInterface(); } static get queryGenerator() { return this.queryInterface.queryGenerator; } get sequelize() { return this.constructor.sequelize; } constructor(values = {}, options = {}) { if (!this.constructor._overwrittenAttributesChecked) { this.constructor._overwrittenAttributesChecked = true; setTimeout(() => { const overwrittenAttributes = []; for (const key of Object.keys(this.constructor._attributeManipulation)) { if (Object.prototype.hasOwnProperty.call(this, key)) { overwrittenAttributes.push(key); } } if (overwrittenAttributes.length > 0) { logger.warn(`Model ${JSON.stringify(this.constructor.name)} is declaring public class fields for attribute(s): ${overwrittenAttributes.map((attr) => JSON.stringify(attr)).join(", ")}. These class fields are shadowing Sequelize's attribute getters & setters. See https://sequelize.org/main/manual/model-basics.html#caveat-with-public-class-fields`); } }, 0); } options = __spreadValues({ isNewRecord: true, _schema: this.constructor._schema, _schemaDelimiter: this.constructor._schemaDelimiter }, options); if (options.attributes) { options.attributes = options.attributes.map((attribute) => Array.isArray(attribute) ? attribute[1] : attribute); } if (!options.includeValidated) { this.constructor._conformIncludes(options, this.constructor); if (options.include) { this.constructor._expandIncludeAll(options); this.constructor._validateIncludedElements(options); } } this.dataValues = {}; this._previousDataValues = {}; this.uniqno = 1; this._changed = /* @__PURE__ */ new Set(); this._options = options; this.isNewRecord = options.isNewRecord; this._initValues(values, options); } _initValues(values, options) { let defaults; let key; values = __spreadValues({}, values); if (options.isNewRecord) { defaults = {}; if (this.constructor._hasDefaultValues) { defaults = _.mapValues(this.constructor._defaultValues, (valueFn) => { const value = valueFn(); return value && value instanceof Utils.SequelizeMethod ? value : _.cloneDeep(value); }); } if (this.constructor.primaryKeyAttributes.length) { this.constructor.primaryKeyAttributes.forEach((primaryKeyAttribute) => { if (!Object.prototype.hasOwnProperty.call(defaults, primaryKeyAttribute)) { defaults[primaryKeyAttribute] = null; } }); } if (this.constructor._timestampAttributes.createdAt && defaults[this.constructor._timestampAttributes.createdAt]) { this.dataValues[this.constructor._timestampAttributes.createdAt] = Utils.toDefaultValue(defaults[this.constructor._timestampAttributes.createdAt], this.sequelize.options.dialect); delete defaults[this.constructor._timestampAttributes.createdAt]; } if (this.constructor._timestampAttributes.updatedAt && defaults[this.constructor._timestampAttributes.updatedAt]) { this.dataValues[this.constructor._timestampAttributes.updatedAt] = Utils.toDefaultValue(defaults[this.constructor._timestampAttributes.updatedAt], this.sequelize.options.dialect); delete defaults[this.constructor._timestampAttributes.updatedAt]; } if (this.constructor._timestampAttributes.deletedAt && defaults[this.constructor._timestampAttributes.deletedAt]) { this.dataValues[this.constructor._timestampAttributes.deletedAt] = Utils.toDefaultValue(defaults[this.constructor._timestampAttributes.deletedAt], this.sequelize.options.dialect); delete defaults[this.constructor._timestampAttributes.deletedAt]; } for (key in defaults) { if (values[key] === void 0) { this.set(key, Utils.toDefaultValue(defaults[key], this.sequelize.options.dialect), { raw: true }); delete values[key]; } } } this.set(values, options); } static _paranoidClause(model, options = {}) { if (options.include) { for (const include of options.include) { this._paranoidClause(include.model, include); } } if (_.get(options, "groupedLimit.on.options.paranoid")) { const throughModel = _.get(options, "groupedLimit.on.through.model"); if (throughModel) { options.groupedLimit.through = this._paranoidClause(throughModel, options.groupedLimit.through); } } if (!model.options.timestamps || !model.options.paranoid || options.paranoid === false) { return options; } const deletedAtCol = model._timestampAttributes.deletedAt; const deletedAtAttribute = model.rawAttributes[deletedAtCol]; const deletedAtObject = {}; let deletedAtDefaultValue = Object.prototype.hasOwnProperty.call(deletedAtAttribute, "defaultValue") ? deletedAtAttribute.defaultValue : null; deletedAtDefaultValue = deletedAtDefaultValue || { [Op.eq]: null }; deletedAtObject[deletedAtAttribute.field || deletedAtCol] = deletedAtDefaultValue; if (Utils.isWhereEmpty(options.where)) { options.where = deletedAtObject; } else { options.where = { [Op.and]: [deletedAtObject, options.where] }; } return options; } static _addDefaultAttributes() { const tail = {}; let head = {}; if (!_.some(this.rawAttributes, "primaryKey")) { if ("id" in this.rawAttributes) { throw new Error(`A column called 'id' was added to the attributes of '${this.tableName}' but not marked with 'primaryKey: true'`); } head = { id: { type: new DataTypes.INTEGER(), allowNull: false, primaryKey: true, autoIncrement: true, _autoGenerated: true } }; } if (this._timestampAttributes.createdAt) { tail[this._timestampAttributes.createdAt] = { type: DataTypes.DATE, allowNull: false, _autoGenerated: true }; } if (this._timestampAttributes.updatedAt) { tail[this._timestampAttributes.updatedAt] = { type: DataTypes.DATE, allowNull: false, _autoGenerated: true }; } if (this._timestampAttributes.deletedAt) { tail[this._timestampAttributes.deletedAt] = { type: DataTypes.DATE, _autoGenerated: true }; } if (this._versionAttribute) { tail[this._versionAttribute] = { type: DataTypes.INTEGER, allowNull: false, defaultValue: 0, _autoGenerated: true }; } const newRawAttributes = __spreadValues(__spreadValues({}, head), this.rawAttributes); _.each(tail, (value, attr) => { if (newRawAttributes[attr] === void 0) { newRawAttributes[attr] = value; } }); this.rawAttributes = newRawAttributes; if (!Object.keys(this.primaryKeys).length) { this.primaryKeys.id = this.rawAttributes.id; } } static getAttributes() { return this.rawAttributes; } static _findAutoIncrementAttribute() { this.autoIncrementAttribute = null; for (const name in this.rawAttributes) { if (Object.prototype.hasOwnProperty.call(this.rawAttributes, name)) { const definition = this.rawAttributes[name]; if (definition && definition.autoIncrement) { if (this.autoIncrementAttribute) { throw new Error("Invalid Instance definition. Only one autoincrement field allowed."); } this.autoIncrementAttribute = name; } } } } static _conformIncludes(options, self) { if (!options.include) return; if (!Array.isArray(options.include)) { options.include = [options.include]; } else if (!options.include.length) { delete options.include; return; } options.include = options.include.map((include) => this._conformInclude(include, self)); } static _transformStringAssociation(include, self) { if (self && typeof include === "string") { if (!Object.prototype.hasOwnProperty.call(self.associations, include)) { throw new Error(`Association with alias "${include}" does not exist on ${self.name}`); } return self.associations[include]; } return include; } static _conformInclude(include, self) { if (include) { let model; if (include._pseudo) return include; include = this._transformStringAssociation(include, self); if (include instanceof Association) { if (self && include.target.name === self.name) { model = include.source; } else { model = include.target; } return { model, association: include, as: include.as }; } if (include.prototype && include.prototype instanceof Model) { return { model: include }; } if (_.isPlainObject(include)) { if (include.association) { include.association = this._transformStringAssociation(include.association, self); if (self && include.association.target.name === self.name) { model = include.association.source; } else { model = include.association.target; } if (!include.model) include.model = model; if (!include.as) include.as = include.association.as; this._conformIncludes(include, model); return include; } if (include.model) { this._conformIncludes(include, include.model); return include; } if (include.all) { this._conformIncludes(include); return include; } } } throw new Error("Include unexpected. Element has to be either a Model, an Association or an object."); } static _expandIncludeAllElement(includes, include) { let all = include.all; delete include.all; if (all !== true) { if (!Array.isArray(all)) { all = [all]; } const validTypes = { BelongsTo: true, HasOne: true, HasMany: true, One: ["BelongsTo", "HasOne"], Has: ["HasOne", "HasMany"], Many: ["HasMany"] }; for (let i = 0; i < all.length; i++) { const type = all[i]; if (type === "All") { all = true; break; } const types = validTypes[type]; if (!types) { throw new sequelizeErrors.EagerLoadingError(`include all '${type}' is not valid - must be BelongsTo, HasOne, HasMany, One, Has, Many or All`); } if (types !== true) { all.splice(i, 1); i--; for (let j = 0; j < types.length; j++) { if (!all.includes(types[j])) { all.unshift(types[j]); i++; } } } } } const nested = include.nested; if (nested) { delete include.nested; if (!include.include) { include.include = []; } else if (!Array.isArray(include.include)) { include.include = [include.include]; } } const used = []; (function addAllIncludes(parent, includes2) { _.forEach(parent.associations, (association) => { if (all !== true && !all.includes(association.associationType)) { return; } const model = association.target; const as = association.options.as; const predicate = { model }; if (as) { predicate.as = as; } if (_.some(includes2, predicate)) { return; } if (nested && used.includes(model)) { return; } used.push(parent); const thisInclude = Utils.cloneDeep(include); thisInclude.model = model; if (as) { thisInclude.as = as; } includes2.push(thisInclude); if (nested) { addAllIncludes(model, thisInclude.include); if (thisInclude.include.length === 0) delete thisInclude.include; } }); used.pop(); })(this, includes); } static _validateIncludedElements(options, tableNames) { if (!options.model) options.model = this; tableNames = tableNames || {}; options.includeNames = []; options.includeMap = {}; options.hasSingleAssociation = false; options.hasMultiAssociation = false; if (!options.parent) { options.topModel = options.model; options.topLimit = options.limit; } options.include = options.include.map((include) => { include = this._conformInclude(include); include.parent = options; include.topLimit = options.topLimit; this._validateIncludedElement.call(options.model, include, tableNames, options); if (include.duplicating === void 0) { include.duplicating = include.association.isMultiAssociation; } include.hasDuplicating = include.hasDuplicating || include.duplicating; include.hasRequired = include.hasRequired || include.required; options.hasDuplicating = options.hasDuplicating || include.hasDuplicating; options.hasRequired = options.hasRequired || include.required; options.hasWhere = options.hasWhere || include.hasWhere || !!include.where; return include; }); for (const include of options.include) { include.hasParentWhere = options.hasParentWhere || !!options.where; include.hasParentRequired = options.hasParentRequired || !!options.required; if (include.subQuery !== false && options.hasDuplicating && options.topLimit) { if (include.duplicating) { include.subQuery = include.subQuery || false; include.subQueryFilter = include.hasRequired; } else { include.subQuery = include.hasRequired; include.subQueryFilter = false; } } else { include.subQuery = include.subQuery || false; if (include.duplicating) { include.subQueryFilter = include.subQuery; } else { include.subQueryFilter = false; include.subQuery = include.subQuery || include.hasParentRequired && include.hasRequired && !include.separate; } } options.includeMap[include.as] = include; options.includeNames.push(include.as); if (options.topModel === options.model && options.subQuery === void 0 && options.topLimit) { if (include.subQuery) { options.subQuery = include.subQuery; } else if (include.hasDuplicating) { options.subQuery = true; } } options.hasIncludeWhere = options.hasIncludeWhere || include.hasIncludeWhere || !!include.where; options.hasIncludeRequired = options.hasIncludeRequired || include.hasIncludeRequired || !!include.required; if (include.association.isMultiAssociation || include.hasMultiAssociation) { options.hasMultiAssociation = true; } if (include.association.isSingleAssociation || include.hasSingleAssociation) { options.hasSingleAssociation = true; } } if (options.topModel === options.model && options.subQuery === void 0) { options.subQuery = false; } return options; } static _validateIncludedElement(include, tableNames, options) { tableNames[include.model.getTableName()] = true; if (include.attributes && !options.raw) { include.model._expandAttributes(include); include.originalAttributes = include.model._injectDependentVirtualAttributes(include.attributes); include = Utils.mapFinderOptions(include, include.model); if (include.attributes.length) { _.each(include.model.primaryKeys, (attr, key) => { if (!include.attributes.some((includeAttr) => { if (attr.field !== key) { return Array.isArray(includeAttr) && includeAttr[0] === attr.field && includeAttr[1] === key; } return includeAttr === key; })) { include.attributes.unshift(key); } }); } } else { include = Utils.mapFinderOptions(include, include.model); } if (include._pseudo) { if (!include.attributes) { include.attributes = Object.keys(include.model.tableAttributes); } return Utils.mapFinderOptions(include, include.model); } const association = include.association || this._getIncludedAssociation(include.model, include.as); include.association = association; include.as = association.as; if (include.association.through && Object(include.association.through.model) === include.association.through.model) { if (!include.include) include.include = []; const through = include.association.through; include.through = _.defaults(include.through || {}, { model: through.model, as: through.model.name, association: { isSingleAssociation: true }, _pseudo: true, parent: include }); if (through.scope) { include.through.where = include.through.where ? { [Op.and]: [include.through.where, through.scope] } : through.scope; } include.include.push(include.through); tableNames[through.tableName] = true; } let model; if (include.model.scoped === true) { model = include.model; } else { model = include.association.target.name === include.model.name ? include.association.target : include.association.source; } model._injectScope(include); if (!include.attributes) { include.attributes = Object.keys(include.model.tableAttributes); } include = Utils.mapFinderOptions(include, include.model); if (include.required === void 0) { include.required = !!include.where; } if (include.association.scope) { include.where = include.where ? { [Op.and]: [include.where, include.association.scope] } : include.association.scope; } if (include.limit && include.separate === void 0) { include.separate = true; } if (include.separate === true) { if (!(include.association instanceof HasMany)) { throw new Error("Only HasMany associations support include.separate"); } include.duplicating = false; if (options.attributes && options.attributes.length && !_.flattenDepth(options.attributes, 2).includes(association.sourceKey)) { options.attributes.push(association.sourceKey); } if (include.attributes && include.attributes.length && !_.flattenDepth(include.attributes, 2).includes(association.foreignKey)) { include.attributes.push(association.foreignKey); } } if (Object.prototype.hasOwnProperty.call(include, "include")) { this._validateIncludedElements.call(include.model, include, tableNames); } return include; } static _getIncludedAssociation(targetModel, targetAlias) { const associations = this.getAssociations(targetModel); let association = null; if (associations.length === 0) { throw new sequelizeErrors.EagerLoadingError(`${targetModel.name} is not associated to ${this.name}!`); } if (associations.length === 1) { association = this.getAssociationForAlias(targetModel, targetAlias); if (association) { return association; } if (targetAlias) { const existingAliases = this.getAssociations(targetModel).map((association2) => association2.as); throw new sequelizeErrors.EagerLoadingError(`${targetModel.name} is associated to ${this.name} using an alias. You've included an alias (${targetAlias}), but it does not match the alias(es) defined in your association (${existingAliases.join(", ")}).`); } throw new sequelizeErrors.EagerLoadingError(`${targetModel.name} is associated to ${this.name} using an alias. You must use the 'as' keyword to specify the alias within your include statement.`); } association = this.getAssociationForAlias(targetModel, targetAlias); if (!association) { throw new sequelizeErrors.EagerLoadingError(`${targetModel.name} is associated to ${this.name} multiple times. To identify the correct association, you must use the 'as' keyword to specify the alias of the association you want to include.`); } return association; } static _expandIncludeAll(options) { const includes = options.include; if (!includes) { return; } for (let index = 0; index < includes.length; index++) { const include = includes[index]; if (include.all) { includes.splice(index, 1); index--; this._expandIncludeAllElement(includes, include); } } includes.forEach((include) => { this._expandIncludeAll.call(include.model, include); }); } static _conformIndex(index) { if (!index.fields) { throw new Error('Missing "fields" property for index definition'); } index = _.defaults(index, { type: "", parser: null }); if (index.type && index.type.toLowerCase() === "unique") { index.unique = true; delete index.type; } return index; } static _uniqIncludes(options) { if (!options.include) return; options.include = _(options.include).groupBy((include) => `${include.model && include.model.name}-${include.as}`).map((includes) => this._assignOptions(...includes)).value(); } static _baseMerge(...args) { _.assignWith(...args); this._conformIncludes(args[0], this); this._uniqIncludes(args[0]); return args[0]; } static _mergeFunction(objValue, srcValue, key) { if (Array.isArray(objValue) && Array.isArray(srcValue)) { return _.union(objValue, srcValue); } if (["where", "having"].includes(key)) { if (this.options && this.options.whereMergeStrategy === "and") { return combineWheresWithAnd(objValue, srcValue); } if (srcValue instanceof Utils.SequelizeMethod) { srcValue = { [Op.and]: srcValue }; } if (_.isPlainObject(objValue) && _.isPlainObject(srcValue)) { return Object.assign(objValue, srcValue); } } else if (key === "attributes" && _.isPlainObject(objValue) && _.isPlainObject(srcValue)) { return _.assignWith(objValue, srcValue, (objValue2, srcValue2) => { if (Array.isArray(objValue2) && Array.isArray(srcValue2)) { return _.union(objValue2, srcValue2); } }); } if (srcValue) { return Utils.cloneDeep(srcValue, true); } return srcValue === void 0 ? objValue : srcValue; } static _assignOptions(...args) { return this._baseMerge(...args, this._mergeFunction.bind(this)); } static _defaultsOptions(target, opts) { return this._baseMerge(target, opts, (srcValue, objValue, key) => { return this._mergeFunction(objValue, srcValue, key); }); } static init(attributes, options = {}) { if (!options.sequelize) { throw new Error("No Sequelize instance passed"); } this.sequelize = options.sequelize; const globalOptions = this.sequelize.options; options = Utils.merge(_.cloneDeep(globalOptions.define), options); if (!options.modelName) { options.modelName = this.name; } options = Utils.merge({ name: { plural: Utils.pluralize(options.modelName), singular: Utils.singularize(options.modelName) }, indexes: [], omitNull: globalOptions.omitNull, schema: globalOptions.schema }, options); this.sequelize.runHooks("beforeDefine", attributes, options); if (options.modelName !== this.name) { Object.defineProperty(this, "name", { value: options.modelName }); } delete options.modelName; this.options = __spreadValues({ timestamps: true, validate: {}, freezeTableName: false, underscored: false, paranoid: false, rejectOnEmpty: false, whereCollection: null, schema: null, schemaDelimiter: "", defaultScope: {}, scopes: {}, indexes: [], whereMergeStrategy: "overwrite" }, options); if (this.sequelize.isDefined(this.name)) { this.sequelize.modelManager.removeModel(this.sequelize.modelManager.getModel(this.name)); } this.associations = {}; this._setupHooks(options.hooks); this.underscored = this.options.underscored; if (!this.options.tableName) { this.tableName = this.options.freezeTableName ? this.name : Utils.underscoredIf(Utils.pluralize(this.name), this.underscored); } else { this.tableName = this.options.tableName; } this._schema = this.options.schema; this._schemaDelimiter = this.options.schemaDelimiter; _.each(options.validate, (validator, validatorType) => { if (Object.prototype.hasOwnProperty.call(attributes, validatorType)) { throw new Error(`A model validator function must not have the same name as a field. Model: ${this.name}, field/validation name: ${validatorType}`); } if (typeof validator !== "function") { throw new Error(`Members of the validate option must be functions. Model: ${this.name}, error with validate member ${validatorType}`); } }); if (!_.includes(["and", "overwrite"], this.options && this.options.whereMergeStrategy)) { throw new Error(`Invalid value ${this.options && this.options.whereMergeStrategy} for whereMergeStrategy. Allowed values are 'and' and 'overwrite'.`); } this.rawAttributes = _.mapValues(attributes, (attribute, name) => { attribute = this.sequelize.normalizeAttribute(attribute); if (attribute.type === void 0) { throw new Error(`Unrecognized datatype for attribute "${this.name}.${name}"`); } if (attribute.allowNull !== false && _.get(attribute, "validate.notNull")) { throw new Error(`Invalid definition for "${this.name}.${name}", "notNull" validator is only allowed with "allowNull:false"`); } if (_.get(attribute, "references.model.prototype") instanceof Model) { attribute.references.model = attribute.references.model.getTableName(); } return attribute; }); const tableName = this.getTableName(); this._indexes = this.options.indexes.map((index) => Utils.nameIndex(this._conformIndex(index), tableName)); this.primaryKeys = {}; this._readOnlyAttributes = /* @__PURE__ */ new Set(); this._timestampAttributes = {}; if (this.options.timestamps) { for (const key of ["createdAt", "updatedAt", "deletedAt"]) { if (!["undefined", "string", "boolean"].includes(typeof this.options[key])) { throw new Error(`Value for "${key}" option must be a string or a boolean, got ${typeof this.options[key]}`); } if (this.options[key] === "") { throw new Error(`Value for "${key}" option cannot be an empty string`); } } if (this.options.createdAt !== false) { this._timestampAttributes.createdAt = typeof this.options.createdAt === "string" ? this.options.createdAt : "createdAt"; this._readOnlyAttributes.add(this._timestampAttributes.createdAt); } if (this.options.updatedAt !== false) { this._timestampAttributes.updatedAt = typeof this.options.updatedAt === "string" ? this.options.updatedAt : "updatedAt"; this._readOnlyAttributes.add(this._timestampAttributes.updatedAt); } if (this.options.paranoid && this.options.deletedAt !== false) { this._timestampAttributes.deletedAt = typeof this.options.deletedAt === "string" ? this.options.deletedAt : "deletedAt"; this._readOnlyAttributes.add(this._timestampAttributes.deletedAt); } } if (this.options.version) { this._versionAttribute = typeof this.options.version === "string" ? this.options.version : "version"; this._readOnlyAttributes.add(this._versionAttribute); } this._hasReadOnlyAttributes = this._readOnlyAttributes.size > 0; this._addDefaultAttributes(); this.refreshAttributes(); this._findAutoIncrementAttribute(); this._scope = this.options.defaultScope; this._scopeNames = ["defaultScope"]; this.sequelize.modelManager.addModel(this); this.sequelize.runHooks("afterDefine", this); return this; } static refreshAttributes() { const attributeManipulation = {}; this.prototype._customGetters = {}; this.prototype._customSetters = {}; ["get", "set"].forEach((type) => { const opt = `${type}terMethods`; const funcs = __spreadValues({}, this.options[opt]); const _custom = type === "get" ? this.prototype._customGetters : this.prototype._customSetters; _.each(funcs, (method, attribute) => { _custom[attribute] = method; if (type === "get") { funcs[attribute] = function() { return this.get(attribute); }; } if (type === "set") { funcs[attribute] = function(value) { return this.set(attribute, value); }; } }); _.each(this.rawAttributes, (options, attribute) => { if (Object.prototype.hasOwnProperty.call(options, type)) { _custom[attribute] = options[type]; } if (type === "get") { funcs[attribute] = function() { return this.get(attribute); }; } if (type === "set") { funcs[attribute] = function(value) { return this.set(attribute, value); }; } }); _.each(funcs, (fct, name) => { if (!attributeManipulation[name]) { attributeManipulation[name] = { configurable: true }; } attributeManipulation[name][type] = fct; }); }); this._dataTypeChanges = {}; this._dataTypeSanitizers = {}; this._hasBooleanAttributes = false; this._hasDateAttributes = false; this._jsonAttributes = /* @__PURE__ */ new Set(); this._virtualAttributes = /* @__PURE__ */ new Set(); this._defaultValues = {}; this.prototype.validators = {}; this.fieldRawAttributesMap = {}; this.primaryKeys = {}; this.uniqueKeys = {}; _.each(this.rawAttributes, (definition, name) => { definition.type = this.sequelize.normalizeDataType(definition.type); definition.Model = this; definition.fieldName = name; definition._modelAttribute = true; if (definition.field === void 0) { definition.field = Utils.underscoredIf(name, this.underscored); } if (definition.primaryKey === true) { this.primaryKeys[name] = definition; } this.fieldRawAttributesMap[definition.field] = definition; if (definition.type._sanitize) { this._dataTypeSanitizers[name] = definition.type._sanitize; } if (definition.type._isChanged) { this._dataTypeChanges[name] = definition.type._isChanged; } if (definition.type instanceof DataTypes.BOOLEAN) { this._hasBooleanAttributes = true; } else if (definition.type instanceof DataTypes.DATE || definition.type instanceof DataTypes.DATEONLY) { this._hasDateAttributes = true; } else if (definition.type instanceof DataTypes.JSON) { this._jsonAttributes.add(name); } else if (definition.type instanceof DataTypes.VIRTUAL) { this._virtualAttributes.add(name); } if (Object.prototype.hasOwnProperty.call(definition, "defaultValue")) { this._defaultValues[name] = () => Utils.toDefaultValue(definition.defaultValue, this.sequelize.options.dialect); } if (Object.prototype.hasOwnProperty.call(definition, "unique") && definition.unique) { let idxName; if (typeof definition.unique === "object" && Object.prototype.hasOwnProperty.call(definition.unique, "name")) { idxName = definition.unique.name; } else if (typeof definition.unique === "string") { idxName = definition.unique; } else { idxName = `${this.tableName}_${name}_unique`; } const idx = this.uniqueKeys[idxName] || { fields: [] }; idx.fields.push(definition.field); idx.msg = idx.msg || definition.unique.msg || null; idx.name = idxName || false; idx.column = name; idx.customIndex = definition.unique !== true; this.uniqueKeys[idxName] = idx; } if (Object.prototype.hasOwnProperty.call(definition, "validate")) { this.prototype.validators[name] = definition.validate; } if (definition.index === true && definition.type instanceof DataTypes.JSONB) { this._indexes.push(Utils.nameIndex(this._conformIndex({ fields: [definition.field || name], using: "gin" }), this.getTableName())); delete definition.index; } }); this.fieldAttributeMap = _.reduce(this.fieldRawAttributesMap, (map, value, key) => { if (key !== value.fieldName) { map[key] = value.fieldName; } return map; }, {}); this._hasJsonAttributes = !!this._jsonAttributes.size; this._hasVirtualAttributes = !!this._virtualAttributes.size; this._hasDefaultValues = !_.isEmpty(this._defaultValues); this.tableAttributes = _.omitBy(this.rawAttributes, (_a, key) => this._virtualAttributes.has(key)); this.prototype._hasCustomGetters = Object.keys(this.prototype._customGetters).length; this.prototype._hasCustomSetters = Object.keys(this.prototype._customSetters).length; for (const key of Object.keys(attributeManipulation)) { if (Object.prototype.hasOwnProperty.call(Model.prototype, key)) { this.sequelize.log(`Not overriding built-in method from model attribute: ${key}`); continue; } Object.defineProperty(this.prototype, key, attributeManipulation[key]); } this.prototype.rawAttributes = this.rawAttributes; this.prototype._isAttribute = (key) => Object.prototype.hasOwnProperty.call(this.prototype.rawAttributes, key); this.primaryKeyAttributes = Object.keys(this.primaryKeys); this.primaryKeyAttribute = this.primaryKeyAttributes[0]; if (this.primaryKeyAttribute) { this.primaryKeyField = this.rawAttributes[this.primaryKeyAttribute].field || this.primaryKeyAttribute; } this._hasPrimaryKeys = this.primaryKeyAttributes.length > 0; this._isPrimaryKey = (key) => this.primaryKeyAttributes.includes(key); this._attributeManipulation = attributeManipulation; } static removeAttribute(attribute) { delete this.rawAttributes[attribute]; this.refreshAttributes(); } static async sync(options) { options = __spreadValues(__spreadValues({}, this.options), options); options.hooks = options.hooks === void 0 ? true : !!options.hooks; const attributes = this.tableAttributes; const rawAttributes = this.fieldRawAttributesMap; if (options.hooks) { await this.runHooks("beforeSync", options); } const tableName = this.getTableName(options); let tableExists; if (options.force) { await this.drop(options); tableExists = false; } else { tableExists = await this.queryInterface.tableExists(tableName, options); } if (!tableExists) { await this.queryInterface.createTable(tableName, attributes, options, this); } else { await this.queryInterface.ensureEnums(tableName, attributes, options, this); } if (tableExists && options.alter) { const tableInfos = await Promise.all([ this.queryInterface.describeTable(tableName, options), this.queryInterface.getForeignKeyReferencesForTable(tableName, options) ]); const columns = tableInfos[0]; const foreignKeyReferences = tableInfos[1]; const removedConstraints = {}; for (const columnName in attributes) { if (!Object.prototype.hasOwnProperty.call(attributes, columnName)) continue; if (!columns[columnName] && !columns[attributes[columnName].field]) { await this.queryInterface.addColumn(tableName, attributes[columnName].field || columnName, attributes[columnName], options); } } if (options.alter === true || typeof options.alter === "object" && options.alter.drop !== false) { for (const columnName in columns) { if (!Object.prototype.hasOwnProperty.call(columns, columnName)) continue; const currentAttribute = rawAttributes[columnName]; if (!currentAttribute) { await this.queryInterface.removeColumn(tableName, columnName, options); continue; } if (currentAttribute.primaryKey) continue; const references = currentAttribute.references; if (currentAttribute.references) { const database = this.sequelize.config.database; const schema = this.sequelize.config.schema; for (const foreignKeyReference of foreignKeyReferences) { const constraintName = foreignKeyReference.constraintName; if (!!constraintName && foreignKeyReference.tableCatalog === database && (schema ? foreignKeyReference.tableSchema === schema : true) && foreignKeyReference.referencedTableName === references.model && foreignKeyReference.referencedColumnName === references.key && (schema ? foreignKeyReference.referencedTableSchema === schema : true) && !removedConstraints[constraintName]) { await this.queryInterface.removeConstraint(tableName, constraintName, options); removedConstraints[constraintName] = true; } } } await this.queryInterface.changeColumn(tableName, columnName, currentAttribute, options); } } } const existingIndexes = await this.queryInterface.showIndex(tableName, options); const missingIndexes = this._indexes.filter((item1) => !existingIndexes.some((item2) => item1.name === item2.name)).sort((index1, index2) => { if (this.sequelize.options.dialect === "postgres") { if (index1.concurrently === true) return 1; if (index2.concurrently === true) return -1; } return 0; }); for (const index of missingIndexes) { await this.queryInterface.addIndex(tableName, __spreadValues(__spreadValues({}, options), index)); } if (options.hooks) { await this.runHooks("afterSync", options); } return this; } static async drop(options) { return await this.queryInterface.dropTable(this.getTableName(options), options); } static async dropSchema(schema) { return await this.queryInterface.dropSchema(schema); } static schema(schema, options) { const clone = class extends this { }; Object.defineProperty(clone, "name", { value: this.name }); clone._schema = schema; if (options) { if (typeof options === "string") { clone._schemaDelimiter = options; } else if (options.schemaDelimiter) { clone._schemaDelimiter = options.schemaDelimiter; } } return clone; } static getTableName() { return this.queryGenerator.addSchema(this); } static unscoped() { return this.scope(); } static addScope(name, scope, options) { options = __spreadValues({ override: false }, options); if ((name === "defaultScope" && Object.keys(this.options.defaultScope).length > 0 || name in this.options.scopes) && options.override === false) { throw new Error(`The scope ${name} already exists. Pass { override: true } as options to silence this error`); } if (name === "defaultScope") { this.options.defaultScope = this._scope = scope; } else { this.options.scopes[name] = scope; } } static scope(option) { const self = class extends this { }; let scope; let scopeName; Object.defineProperty(self, "name", { value: this.name }); self._scope = {}; self._scopeNames = []; self.scoped = true; if (!option) { return self; } const options = _.flatten(arguments); for (const option2 of options) { scope = null; scopeName = null; if (_.isPlainObject(option2)) { if (option2.method) { if (Array.isArray(option2.method) && !!self.options.scopes[option2.method[0]]) { scopeName = option2.method[0]; scope = self.options.scopes[scopeName].apply(self, option2.method.slice(1)); } else if (self.options.scopes[option2.method]) { scopeName = option2.method; scope = self.options.scopes[scopeName].apply(self); } } else { scope = option2; } } else if (option2 === "defaultScope" && _.isPlainObject(self.options.defaultScope)) { scope = self.options.defaultScope; } else { scopeName = option2; scope = self.options.scopes[scopeName]; if (typeof scope === "function") { scope = scope(); } } if (scope) { this._conformIncludes(scope, this); this._assignOptions(self._scope, Utils.cloneDeep(scope)); self._scopeNames.push(scopeName ? scopeName : "defaultScope"); } else { throw new sequelizeErrors.SequelizeScopeError(`Invalid scope ${scopeName} called.`); } } return self; } static async findAll(options) { if (options !== void 0 && !_.isPlainObject(options)) { throw new sequelizeErrors.QueryError("The argument passed to findAll must be an options object, use findByPk if you wish to pass a single primary key value"); } if (options !== void 0 && options.attributes) { if (!Array.isArray(options.attributes) && !_.isPlainObject(options.attributes)) { throw new sequelizeErrors.QueryError("The attributes option must be an array of column names or an object"); } } this.warnOnInvalidOptions(options, Object.keys(this.rawAttributes)); const tableNames = {}; tableNames[this.getTableName(options)] = true; options = Utils.cloneDeep(options); _.defaults(options, { hooks: true }); options.rejectOnEmpty = Object.prototype.hasOwnProperty.call(options, "rejectOnEmpty") ? options.rejectOnEmpty : this.options.rejectOnEmpty; this._injectScope(options); if (options.hooks) { await this.runHooks("beforeFind", options); } this._conformIncludes(options, this); this._expandAttributes(options); this._expandIncludeAll(options); if (options.hooks) { await this.runHooks("beforeFindAfterExpandIncludeAll", options); } options.originalAttributes = this._injectDependentVirtualAttributes(options.attributes); if (options.include) { options.hasJoin = true; this._validateIncludedElements(options, tableNames); if (options.attributes && !options.raw && this.primaryKeyAttribute && !options.attributes.includes(this.primaryKeyAttribute) && (!options.group || !options.hasSingleAssociation || options.hasMultiAssociation)) { options.attributes = [this.primaryKeyAttribute].concat(options.attributes); } } if (!options.attributes) { options.attributes = Object.keys(this.rawAttributes); options.originalAttributes = this._injectDependentVirtualAttributes(options.attributes); } this.options.whereCollection = options.where || null; Utils.mapFinderOptions(options, this); options = this._paranoidClause(this, options); if (options.hooks) { await this.runHooks("beforeFindAfterOptions", options); } const selectOptions = __spreadProps(__spreadValues({}, options), { tableNames: Object.keys(tableNames) }); const results = await this.queryInterface.select(this, this.getTableName(selectOptions), selectOptions); if (options.hooks) { await this.runHooks("afterFind", results, options); } if (_.isEmpty(results) && options.rejectOnEmpty) { if (typeof options.rejectOnEmpty === "function") { throw new options.rejectOnEmpty(); } if (typeof options.rejectOnEmpty === "object") { throw options.rejectOnEmpty; } throw new sequelizeErrors.EmptyResultError(); } return await Model._findSeparate(results, options); } static warnOnInvalidOptions(options, validColumnNames) { if (!_.isPlainObject(options)) { return; } const unrecognizedOptions = Object.keys(options).filter((k) => !validQueryKeywords.has(k)); const unexpectedModelAttributes = _.intersection(unrecognizedOptions, validColumnNames); if (!options.where && unexpectedModelAttributes.length > 0) { logger.warn(`Model attributes (${unexpectedModelAttributes.join(", ")}) passed into finder method options of model ${this.name}, but the options.where object is empty. Did you forget to use options.where?`); } } static _injectDependentVirtualAttributes(attributes) { if (!this._hasVirtualAttributes) return attributes; if (!attributes || !Array.isArray(attributes)) return attributes; for (const attribute of attributes) { if (this._virtualAttributes.has(attribute) && this.rawAttributes[attribute].type.fields) { attributes = attributes.concat(this.rawAttributes[attribute].type.fields); } } attributes = _.uniq(attributes); return attributes; } static async _findSeparate(results, options) { if (!options.include || options.raw || !results) return results; const original = results; if (options.plain) results = [results]; if (!results.length) return original; await Promise.all(options.include.map(async (include) => { if (!include.separate) { return await Model._findSeparate(results.reduce((memo, result) => { let associations = result.get(include.association.as); if (!associations) return memo; if (!Array.isArray(associations)) associations = [associations]; for (let i = 0, len = associations.length; i !== len; ++i) { memo.push(associations[i]); } return memo; }, []), __spreadProps(__spreadValues({}, _.omit(options, "include", "attributes", "order", "where", "limit", "offset", "plain", "scope")), { include: include.include || [] })); } const map = await include.association.get(results, __spreadValues(__spreadValues({}, _.omit(options, nonCascadingOptions)), _.omit(include, ["parent", "association", "as", "originalAttributes"]))); for (const result of results) { result.set(include.association.as, map[result.get(include.association.sourceKey)], { raw: true }); } })); return original; } static async findByPk(param, options) { if ([null, void 0].includes(param)) { return null; } options = Utils.cloneDeep(options) || {}; if (typeof param === "number" || typeof param === "bigint" || typeof param === "string" || Buffer.isBuffer(param)) { options.where = { [this.primaryKeyAttribute]: param }; } else { throw new Error(`Argument passed to findByPk is invalid: ${param}`); } return await this.findOne(options); } static async findOne(options) { if (options !== void 0 && !_.isPlainObject(options)) { throw new Error("The argument passed to findOne must be an options object, use findByPk if you wish to pass a single primary key value"); } options = Utils.cloneDeep(options); if (options.limit === void 0) { const uniqueSingleColumns = _.chain(this.uniqueKeys).values().filter((c) => c.fields.length === 1).map("column").value(); if (!options.where || !_.some(options.where, (value, key) => (key === this.primaryKeyAttribu