loopbackio / loopbackio/loopback-next

HasManyRepository should implement EntityCrudRepository?

Open
#5,025 6 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

feature Relations
Dominant language
TypeScript
Stars
5.1k
Forks
1.1k
Avg merge
2d 21h
Merged PRs (30d)
27

Description

Suggestion

The HasManyRepository is missing the *ById, exists and count methods. They would prove to be very handy...

Use Cases

Currently we have to forge the where clause to target entities by ID when working on a relation. This is error prone and more work than it should be.

For the *ById methods:

While routes like GET /project/12/milestone/3 could definitely be narrowed down to /milestone/3
Relation can be used in a multi-tenant architecture like so in a controller:

    this.tenantRepository.milestones(currentUserProfile.tenantId);

To find a milestone, making sure we return it only if it is owned by the current tenant:

async findById(
    @inject(SecurityBindings.USER) currentUserProfile: SscUserProfile,
    @param.path.number('id') id: number,
    @param.filter(CrmContact, {exclude: 'where'})
    filter?: FilterExcludingWhere<CrmContact>,
  ): Promise<CrmContact> {
    filter = filter || {};
    filter.limit = 1;
    const newFilter = Object.assign({}, filter, {where: {id}});
    return (await this.tenantRepository.milestones(currentUserProfile.tenantId).find(newFilter))[0];
  }

This gets cumbersome even if there's better ways to build the where filter like using constraints (?).

For the count method

Another use case if for the count method. We cannot efficiently use the relation to count as we need to use find for it! A worker could be to use the right repository and constrain it to the relation key...

// ... the Where filter should be modified not just thown away but meh
   return this.mileStoneRepository.count({tenantId:currentUserProfile.tenantId});
//or
   const newFilter = {where,fields:{id:true}}; //include the least fields possible.
   return (await this.tenantRepository.milestones(currentUserProfile.tenantId).find(newFilter)).length;

Examples

return this.tenantRepository.milestones(currentUserProfile.tenantId).findById(id);
return this.tenantRepository.milestones(currentUserProfile.tenantId).count(where);

Acceptance criteria

  • implement count, exists and *ById for hasManyRepository
  • implement exists and *ById for hasOneRepository

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by locating the HasManyRepository and HasOneRepository implementations and the EntityCrudRepository interface. Trace how relation-scoped queries are currently handled, then use the repository tests covering these classes to verify count, exists, and *ById behavior for both relation types.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
backend-api-design
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.