CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-sequelize

Promise-based Node.js ORM tool for Postgres, MySQL, MariaDB, SQLite, Microsoft SQL Server, Amazon Redshift and Snowflake's Data Cloud with solid transaction support, relations, eager and lazy loading, read replication and more

Pending
Overview
Eval results
Files

associations.mddocs/

Associations

Model relationship definitions and operations including one-to-one, one-to-many, and many-to-many associations with eager loading.

Capabilities

BelongsTo Association

Defines a belongs-to relationship where the current model has a foreign key pointing to the target model.

/**
 * Define belongs-to association
 * @param target - Target model class
 * @param options - Association options
 * @returns BelongsTo association instance
 */
static belongsTo(target: ModelCtor, options?: BelongsToOptions): BelongsTo;

interface BelongsToOptions {
  /** Foreign key column name */
  foreignKey?: string | ForeignKeyOptions;
  /** Target key (usually primary key) */
  targetKey?: string;
  /** Association alias */
  as?: string;
  /** Association scope */
  scope?: AssociationScope;
  /** Include hooks */
  hooks?: boolean;
  /** On update action */
  onUpdate?: string;
  /** On delete action */
  onDelete?: string;
  /** Constraint options */
  constraints?: boolean;
}

interface ForeignKeyOptions {
  /** Column name */
  name?: string;
  /** Allow null values */
  allowNull?: boolean;
}

Usage Examples:

// Basic belongs-to
class Post extends Model {}
class User extends Model {}

Post.belongsTo(User);  // Creates userId foreign key on Post

// With custom foreign key
Post.belongsTo(User, {
  foreignKey: 'authorId',
  as: 'author'
});

// With constraints
Post.belongsTo(User, {
  foreignKey: {
    name: 'userId',
    allowNull: false
  },
  onDelete: 'CASCADE',
  onUpdate: 'CASCADE'
});

// Usage in queries
const post = await Post.findOne({
  include: [{ model: User, as: 'author' }]
});

// Instance methods (automatically created)
const post = await Post.findByPk(1);
const user = await post.getUser();     // or getAuthor() if aliased
await post.setUser(newUser);
const newUser = await post.createUser({ name: 'John' });

HasOne Association

Defines a has-one relationship where the target model has a foreign key pointing to the current model.

/**
 * Define has-one association
 * @param target - Target model class
 * @param options - Association options
 * @returns HasOne association instance
 */
static hasOne(target: ModelCtor, options?: HasOneOptions): HasOne;

interface HasOneOptions {
  /** Foreign key column name on target */
  foreignKey?: string | ForeignKeyOptions;
  /** Source key (usually primary key) */
  sourceKey?: string;
  /** Association alias */
  as?: string;
  /** Association scope */
  scope?: AssociationScope;
  /** Include hooks */
  hooks?: boolean;
  /** On update action */
  onUpdate?: string;
  /** On delete action */
  onDelete?: string;
  /** Constraint options */
  constraints?: boolean;
}

Usage Examples:

// Basic has-one
class User extends Model {}
class Profile extends Model {}

User.hasOne(Profile);  // Creates userId foreign key on Profile

// With options
User.hasOne(Profile, {
  foreignKey: 'ownerId',
  as: 'userProfile',
  onDelete: 'CASCADE'
});

// Usage in queries
const user = await User.findOne({
  include: [Profile]  // or { model: Profile, as: 'userProfile' }
});

// Instance methods
const user = await User.findByPk(1);
const profile = await user.getProfile();
await user.setProfile(newProfile);
const profile = await user.createProfile({ bio: 'Hello' });

HasMany Association

Defines a has-many relationship where the target model has a foreign key pointing to the current model.

/**
 * Define has-many association  
 * @param target - Target model class
 * @param options - Association options
 * @returns HasMany association instance
 */
static hasMany(target: ModelCtor, options?: HasManyOptions): HasMany;

interface HasManyOptions {
  /** Foreign key column name on target */
  foreignKey?: string | ForeignKeyOptions;
  /** Source key (usually primary key) */
  sourceKey?: string;
  /** Association alias */
  as?: string;
  /** Association scope */
  scope?: AssociationScope;
  /** Include hooks */
  hooks?: boolean;
  /** On update action */
  onUpdate?: string;
  /** On delete action */
  onDelete?: string;
  /** Constraint options */
  constraints?: boolean;
}

Usage Examples:

// Basic has-many
class User extends Model {}
class Post extends Model {}

User.hasMany(Post);  // Creates userId foreign key on Post

// With options
User.hasMany(Post, {
  foreignKey: 'authorId',
  as: 'articles',
  scope: { status: 'published' }
});

// Usage in queries
const user = await User.findOne({
  include: [{ 
    model: Post, 
    as: 'articles',
    where: { status: 'published' }
  }]
});

// Instance methods
const user = await User.findByPk(1);
const posts = await user.getPosts();           // or getArticles()
await user.setPosts([post1, post2]);
await user.addPost(newPost);
await user.addPosts([post1, post2]);
await user.removePost(post);
await user.removePosts([post1, post2]);
const newPost = await user.createPost({ title: 'Hello' });
const hasPost = await user.hasPost(post);
const postCount = await user.countPosts();

BelongsToMany Association

Defines a many-to-many relationship through a junction table.

/**
 * Define belongs-to-many association
 * @param target - Target model class  
 * @param options - Association options
 * @returns BelongsToMany association instance
 */
static belongsToMany(target: ModelCtor, options: BelongsToManyOptions): BelongsToMany;

interface BelongsToManyOptions {
  /** Junction table name or model */
  through: string | ModelCtor | ThroughOptions;
  /** Foreign key for source model */
  foreignKey?: string | ForeignKeyOptions;
  /** Foreign key for target model */
  otherKey?: string | ForeignKeyOptions;
  /** Source key (usually primary key) */
  sourceKey?: string;
  /** Target key (usually primary key) */
  targetKey?: string;
  /** Association alias */
  as?: string;
  /** Association scope */
  scope?: AssociationScope;
  /** Include hooks */
  hooks?: boolean;
  /** Constraint options */
  constraints?: boolean;
}

interface ThroughOptions {
  /** Junction model */
  model: ModelCtor;
  /** Unique constraint on junction */
  unique?: boolean;
  /** Additional attributes on junction */
  scope?: any;
}

Usage Examples:

// Basic many-to-many
class User extends Model {}
class Role extends Model {}

User.belongsToMany(Role, { through: 'UserRoles' });
Role.belongsToMany(User, { through: 'UserRoles' });

// With custom keys
User.belongsToMany(Role, {
  through: 'UserRoles',
  foreignKey: 'userId',
  otherKey: 'roleId',
  as: 'permissions'
});

// With junction model
class UserRole extends Model {}
UserRole.init({
  userId: DataTypes.INTEGER,
  roleId: DataTypes.INTEGER,
  assignedAt: DataTypes.DATE,
  assignedBy: DataTypes.INTEGER
});

User.belongsToMany(Role, {
  through: UserRole,
  foreignKey: 'userId',
  otherKey: 'roleId'
});

// Usage in queries
const user = await User.findOne({
  include: [{
    model: Role,
    through: { attributes: ['assignedAt'] }  // Include junction attributes
  }]
});

// Instance methods
const user = await User.findByPk(1);
const roles = await user.getRoles();
await user.setRoles([role1, role2]);
await user.addRole(newRole);
await user.addRoles([role1, role2]);
await user.removeRole(role);
await user.removeRoles([role1, role2]);

// With junction attributes
await user.addRole(role, { through: { assignedBy: adminId } });

Eager Loading

Loading associated models along with the main query.

interface IncludeOptions {
  /** Model to include */
  model: ModelCtor;
  /** Association alias */
  as?: string;
  /** Include attributes */
  attributes?: FindAttributeOptions;
  /** WHERE clause for included model */
  where?: WhereOptions;
  /** Required join (INNER vs LEFT JOIN) */
  required?: boolean;
  /** Include paranoid records */
  paranoid?: boolean;
  /** Nested includes */
  include?: IncludeOptions | IncludeOptions[];
  /** Separate queries for has-many */
  separate?: boolean;
  /** Limit included records */
  limit?: number;
  /** Through table options (for belongsToMany) */
  through?: ThroughOptions;
  /** Duplicate records handling */
  duplicating?: boolean;
}

type Includeable = ModelCtor | IncludeOptions;

Usage Examples:

// Basic include
const users = await User.findAll({
  include: [Post]
});

// Include with alias
const users = await User.findAll({
  include: [{ model: Post, as: 'articles' }]
});

// Include with conditions
const users = await User.findAll({
  include: [{
    model: Post,
    where: { status: 'published' },
    required: true  // INNER JOIN instead of LEFT JOIN
  }]
});

// Nested includes
const posts = await Post.findAll({
  include: [{
    model: User,
    include: [Profile]
  }]
});

// Many-to-many with junction attributes
const users = await User.findAll({
  include: [{
    model: Role,
    through: {
      attributes: ['assignedAt', 'assignedBy']
    }
  }]
});

// Separate queries for performance
const users = await User.findAll({
  include: [{
    model: Post,
    separate: true,  // Run separate query
    limit: 5
  }]
});

Association Scopes

Define scopes that are automatically applied to associations.

interface AssociationScope {
  [key: string]: any;
}

Usage Example:

// Define association with scope
User.hasMany(Post, {
  as: 'publishedPosts',
  scope: {
    status: 'published'
  }
});

// Scope is automatically applied
const user = await User.findByPk(1);
const publishedPosts = await user.getPublishedPosts();
// Only returns posts where status = 'published'

Advanced Association Patterns

Complex association setups and patterns.

// Self-referencing associations
User.hasMany(User, { as: 'Children', foreignKey: 'parentId' });
User.belongsTo(User, { as: 'Parent', foreignKey: 'parentId' });

// Multiple associations between same models
User.hasMany(Post, { as: 'AuthoredPosts', foreignKey: 'authorId' });
User.hasMany(Post, { as: 'EditedPosts', foreignKey: 'editorId' });

// Polymorphic associations (manual setup)
class Comment extends Model {}
Comment.belongsTo(Post, { foreignKey: 'commentableId', constraints: false, scope: { commentableType: 'post' } });
Comment.belongsTo(User, { foreignKey: 'commentableId', constraints: false, scope: { commentableType: 'user' } });

Usage Examples:

// Self-referencing
const manager = await User.findOne({
  include: [{ model: User, as: 'Children' }]
});

// Multiple associations
const user = await User.findOne({
  include: [
    { model: Post, as: 'AuthoredPosts' },
    { model: Post, as: 'EditedPosts' }
  ]
});

// Polymorphic
const comments = await Comment.findAll({
  include: [
    { model: Post, where: { commentableType: 'post' } },
    { model: User, where: { commentableType: 'user' } }
  ]
});

Install with Tessl CLI

npx tessl i tessl/npm-sequelize

docs

associations.md

data-types.md

database-connection.md

error-handling.md

hooks.md

index.md

model-definition.md

query-operators.md

querying.md

transactions.md

tile.json