UNPKG

@sequelize/core

Version:

Sequelize is a promise-based Node.js ORM tool for Postgres, MySQL, MariaDB, SQLite, Microsoft SQL Server, Amazon Redshift, Snowflake’s Data Cloud, Db2, and IBM i. It features solid transaction support, relations, eager and lazy loading, read replication a

249 lines (244 loc) 11.2 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var helpers_exports = {}; __export(helpers_exports, { AssociationSecret: () => AssociationSecret, assertAssociationModelIsDefined: () => assertAssociationModelIsDefined, assertAssociationUnique: () => assertAssociationUnique, checkNamingCollision: () => checkNamingCollision, defineAssociation: () => defineAssociation, getForwardedModel: () => getForwardedModel, isThroughOptions: () => isThroughOptions, mixinMethods: () => mixinMethods, normalizeBaseAssociationOptions: () => normalizeBaseAssociationOptions, normalizeForeignKeyOptions: () => normalizeForeignKeyOptions, normalizeInverseAssociation: () => normalizeInverseAssociation }); module.exports = __toCommonJS(helpers_exports); var import_isEqual = __toESM(require("lodash/isEqual")); var import_isPlainObject = __toESM(require("lodash/isPlainObject.js")); var import_lowerFirst = __toESM(require("lodash/lowerFirst")); var import_omit = __toESM(require("lodash/omit")); var import_node_assert = __toESM(require("node:assert")); var import_node_util = __toESM(require("node:util")); var import_errors = require("../errors/index.js"); var deprecations = __toESM(require("../utils/deprecations.js")); var import_model_utils = require("../utils/model-utils.js"); var import_object = require("../utils/object.js"); var import_string = require("../utils/string.js"); function checkNamingCollision(source, associationName) { if (Object.hasOwn(source.getAttributes(), associationName)) { throw new Error( `Naming collision between attribute '${associationName}' and association '${associationName}' on model ${source.name}. To remedy this, change the "as" options in your association definition` ); } } function mixinMethods(association, mixinTargetPrototype, methods, aliases) { for (const method of methods) { const targetMethodName = association.accessors[method]; if (Object.hasOwn(mixinTargetPrototype, targetMethodName)) { continue; } const realMethod = aliases?.[method] || method; Object.defineProperty(mixinTargetPrototype, targetMethodName, { enumerable: false, value(...params) { return association[realMethod](this, ...params); } }); } } const AssociationSecret = Symbol("AssociationConstructorPrivateKey"); function assertAssociationUnique(type, source, target, options, parent) { const as = options.as; const existingAssociation = source.associations[as]; if (!existingAssociation) { return; } const incompatibilityStatus = getAssociationsIncompatibilityStatus( existingAssociation, type, target, options ); if ((parent || existingAssociation.parentAssociation) && incompatibilityStatus == null) { return; } const existingRoot = existingAssociation.rootAssociation; if (!parent && existingRoot === existingAssociation) { throw new import_errors.AssociationError( `You have defined two associations with the same name "${as}" on the model "${source.name}". Use another alias using the "as" parameter.` ); } throw new import_errors.AssociationError( ` ${parent ? `The association "${parent.as}" needs to define` : `You are trying to define`} the ${type.name} association "${options.as}" from ${source.name} to ${target.name}, but that child association has already been defined as ${existingAssociation.associationType}, to ${target.name} by this call: ${existingRoot.source.name}.${(0, import_lowerFirst.default)(existingRoot.associationType)}(${existingRoot.target.name}, ${import_node_util.default.inspect(existingRoot.options)}) That association would be re-used if compatible, but it is incompatible because ${incompatibilityStatus === 0 /* DIFFERENT_TYPES */ ? `their types are different (${type.name} vs ${existingAssociation.associationType})` : incompatibilityStatus === 1 /* DIFFERENT_TARGETS */ ? `they target different models (${target.name} vs ${existingAssociation.target.name})` : `their options are not reconcilable: Options of the association to create: ${import_node_util.default.inspect((0, import_omit.default)(options, "inverse"), { sorted: true })} Options of the existing association: ${import_node_util.default.inspect((0, import_omit.default)(existingAssociation.options, "inverse"), { sorted: true })} `}`.trim() ); } var IncompatibilityStatus = /* @__PURE__ */ ((IncompatibilityStatus2) => { IncompatibilityStatus2[IncompatibilityStatus2["DIFFERENT_TYPES"] = 0] = "DIFFERENT_TYPES"; IncompatibilityStatus2[IncompatibilityStatus2["DIFFERENT_TARGETS"] = 1] = "DIFFERENT_TARGETS"; IncompatibilityStatus2[IncompatibilityStatus2["DIFFERENT_OPTIONS"] = 2] = "DIFFERENT_OPTIONS"; return IncompatibilityStatus2; })(IncompatibilityStatus || {}); function getAssociationsIncompatibilityStatus(existingAssociation, newAssociationType, newTarget, newOptions) { if (existingAssociation.associationType !== newAssociationType.name) { return 0 /* DIFFERENT_TYPES */; } if (!(0, import_model_utils.isSameInitialModel)(existingAssociation.target, newTarget)) { return 1 /* DIFFERENT_TARGETS */; } const opts1 = (0, import_omit.default)(existingAssociation.options, "inverse"); const opts2 = (0, import_omit.default)(newOptions, "inverse"); if (!(0, import_isEqual.default)(opts1, opts2)) { return 2 /* DIFFERENT_OPTIONS */; } return null; } function assertAssociationModelIsDefined(model) { if (!model.sequelize) { throw new Error( `Model ${model.name} must be defined (through Model.init or Sequelize#define) before calling one of its association declaration methods.` ); } } function defineAssociation(type, source, target, options, parent, normalizeOptions, construct) { if (!(0, import_model_utils.isModelStatic)(target)) { throw new Error( `${source.name}.${(0, import_lowerFirst.default)(type.name)} was called with ${import_node_util.default.inspect(target)} as the target model, but it is not a subclass of Sequelize's Model class` ); } assertAssociationModelIsDefined(source); assertAssociationModelIsDefined(target); const normalizedOptions = normalizeOptions(type, options, source, target); checkNamingCollision(source, normalizedOptions.as); assertAssociationUnique(type, source, target, normalizedOptions, parent); const sequelize = source.sequelize; Object.defineProperty(normalizedOptions, "sequelize", { configurable: true, get() { deprecations.movedSequelizeParam(); return sequelize; } }); if (normalizedOptions.hooks) { source.hooks.runSync("beforeAssociate", { source, target, type, sequelize }, normalizedOptions); } let association; try { association = source.associations[normalizedOptions.as] ?? construct(normalizedOptions); } catch (error) { throw new import_errors.AssociationError( parent ? `Association "${parent.as}" needs to create the ${type.name} association "${normalizedOptions.as}" from ${source.name} to ${target.name}, but it failed` : `Defining ${type.name} association "${normalizedOptions.as}" from ${source.name} to ${target.name} failed`, { cause: error } ); } if (normalizedOptions.hooks) { source.hooks.runSync( "afterAssociate", { source, target, type, association, sequelize }, normalizedOptions ); } checkNamingCollision(source, normalizedOptions.as); return association; } function normalizeInverseAssociation(inverse) { if (typeof inverse === "string") { return { as: inverse }; } return inverse; } function normalizeBaseAssociationOptions(associationType, options, source, target) { if ("onDelete" in options || "onUpdate" in options) { throw new Error( 'Options "onDelete" and "onUpdate" have been moved to "foreignKey.onDelete" and "foreignKey.onUpdate" (also available as "otherKey" in belongsToMany)' ); } if ("constraints" in options) { throw new Error('Option "constraints" has been renamed to "foreignKeyConstraints"'); } if ("foreignKeyConstraint" in options) { throw new Error( 'Option "foreignKeyConstraint" has been renamed to "foreignKeyConstraints" (with a "s" at the end)' ); } const isMultiAssociation = associationType.isMultiAssociation; let name; let as; if (options?.as) { if ((0, import_isPlainObject.default)(options.as)) { (0, import_node_assert.default)(typeof options.as === "object"); name = options.as; as = isMultiAssociation ? options.as.plural : options.as.singular; } else { (0, import_node_assert.default)(typeof options.as === "string"); as = options.as; name = { plural: isMultiAssociation ? options.as : (0, import_string.pluralize)(options.as), singular: isMultiAssociation ? (0, import_string.singularize)(options.as) : options.as }; } } else { as = (0, import_lowerFirst.default)(isMultiAssociation ? target.options.name.plural : target.options.name.singular); name = { plural: (0, import_lowerFirst.default)(target.options.name.plural), singular: (0, import_lowerFirst.default)(target.options.name.singular) }; } return (0, import_object.removeUndefined)({ ...options, foreignKey: normalizeForeignKeyOptions(options.foreignKey), hooks: options.hooks ?? false, as, name }); } function normalizeForeignKeyOptions(foreignKey) { return typeof foreignKey === "string" ? { name: foreignKey } : (0, import_object.removeUndefined)({ ...foreignKey, name: foreignKey?.name ?? foreignKey?.fieldName, fieldName: void 0 }); } function getForwardedModel(model, sequelize) { return typeof model === "function" && !(0, import_model_utils.isModelStatic)(model) ? model(sequelize) : model; } function isThroughOptions(val) { return (0, import_isPlainObject.default)(val) && "model" in val; } //# sourceMappingURL=helpers.js.map