Skip to content

Add support for Repositories / Data Mapper #15389

@ephys

Description

@ephys

Issue Creation Checklist

  • I understand that my issue will be automatically closed if I don't fill in the requested information
  • I have read the contribution guidelines

Feature Description

Describe the feature you'd like to see implemented

This is a feature that would take a long time to implement with our current codebase, but our rewrite to TypeScript is the perfect opportunity to make sure our new design is compatible with a Repository Mode.

The goal of a repository mode would be to eliminate our current limitation that one model can only ever be associated to one Sequelize instance.
(to be 100% honest, that limitation would remain for classes that extend Model because they expose static DB methods, but we could have model classes that do not extend Model).

Here is an example:

// note that this doesn't extend Model
class User {
  @IntPrimaryKey
  declare id: number;
}

// Models are registered just like without repository mode
const sequelize1 = new Sequelize({
  models: [User],
});

// Error! The findAll static method does not exist.
User.findAll();

// You need to get the repository instead:
const userRepository1 = sequelize1.getRepository(User);
const users = userRepository1.findAll(); // success!

// The same model can be used in multiple Sequelize instances.
const sequelize2 = new Sequelize({
  models: [User],
});

const userRepository2 = sequelize2.getRepository(User);
const users = userRepository2.findAll(); // success!

Existing models with their static methods would continue to work just like before, but they cannot be used in multiple Sequelize instances:

class User extends Model {
  @IntPrimaryKey
  declare id: number;
}

// Models are registered just like without repository mode
const sequelize1 = new Sequelize({
  models: [User],
});

// This works!
User.findAll();

// This works too!
const userRepository1 = sequelize1.getRepository(User);
const users = userRepository1.findAll(); // success!

// Error: Model "User" already belongs to a different Sequelize instance. Models that extend the "Model" base class cannot be used in multiple Sequelize instances. You must use plain models and repositories instead.
const sequelize2 = new Sequelize({
  models: [User],
});

Describe why you would like this feature to be added to Sequelize

It would allow using the same models in multiple databases.

How would we implement this

We're migrating model.js to TypeScript, it's the perfect opportunity to move all of it to a new class called ModelRepository.

The Model class would be emptied, with only its public methods remaining. It would have an internal, private, ModelRepository instance, and its public methods would delegate to that ModelRepository.

Once model.js has been completely migrated to ModelRepository, we'll be able to add sequelize.getRepository(model), and register models that don't extend the base Model class.

Is this feature dialect-specific?

  • No. This feature is relevant to Sequelize as a whole.
  • Yes. This feature only applies to the following dialect(s):

Would you be willing to resolve this issue by submitting a Pull Request?

  • Yes, I have the time and I know how to start.
  • Yes, I have the time but I will need guidance.
  • No, I don't have the time, but my company or I are supporting Sequelize through donations on OpenCollective.
  • No, I don't have the time, and I understand that I will need to wait until someone from the community or maintainers is interested in implementing my feature.

Indicate your interest in the addition of this feature by adding the 👍 reaction. Comments such as "+1" will be removed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions