TriPSs / nestjs-query

Easy CRUD for GraphQL.
https://tripss.github.io/nestjs-query/
MIT License
157 stars 43 forks source link

Issue with SetRelations on one relationship, setRelations with empty array assigns all existing values #275

Open coupster74 opened 3 months ago

coupster74 commented 3 months ago

Describe the bug I have an issue where I have two relationships with an action where calling setRelations passing in [] when the entity is company results in ALL companies being associated with the action. Here is some code for reference:

@FilterableUnPagedRelation('issues', () => Issue, {
  nullable: true,
  update: { enabled: true },
  remove: { enabled: true },
})
@FilterableUnPagedRelation('companies', () => Company, {
  nullable: true,
  update: { enabled: true },
  remove: { enabled: true },
})

//... snip ...

  @ManyToMany(() => Company, (company) => company.actions)
  @JoinTable()
  companies: Company[];

  @ManyToMany(() => Issue, (issue) => issue.actions)
  @JoinTable()
  issues: Issue[];

The code for these two relationships are identical within the action resolver (error handling simplified for example)

    if (action.issuesIds)
      try {
        result = await this.actionService.setRelations(
          'issues',
          id,
          action.issuesIds,
        );
      } catch (err) {
        console.log(err);
      }

    if (action.companiesIds)
      try {
        result = await this.actionService.setRelations(
          'companies',
          id,
          action.companiesIds,
        );
      } catch (err) {
        console.log(err);
      }

At first I thought it was an issue with the library, but it is working fine for relationships to other entities. Here is what I have managed to determine:

I'm at a loss as to next steps to troubleshoot and I have a massive code base so I'd like to not recreate if at all possible. Do you have any ideas on next steps you can recommend?

coupster74 commented 3 months ago

@TriPSs I have determined what is causing the issue, and I would think it is a bug.

the company object has a one to one relationship to portal prefeerences which is based on the company's id.

here is attribute on the company entity:

  @OneToOne(() => PortalCompanyPreference, {
    onDelete: 'CASCADE',
    createForeignKeyConstraints: false,
    nullable: true,
  })
  @JoinColumn({ name: 'id' })
  portalPreferences?: PortalCompanyPreference;

and here is portalPreferences (thinned out):

import { Entity, Column, PrimaryColumn } from 'typeorm';
import { Field, ID, ObjectType } from '@nestjs/graphql';
import { IDField, QueryOptions } from '@ptc-org/nestjs-query-graphql';
import { DEFAULT_QUERY_RESULTS } from '../config/constants';
import { GraphQLJSONObject } from 'graphql-type-json';

@Entity()
@ObjectType()
@QueryOptions({ defaultResultSize: DEFAULT_QUERY_RESULTS, maxResultsSize: -1 })
export class PortalCompanyPreference {
  @PrimaryColumn({ type: 'uuid' })
  @IDField(() => ID)
  companyId!: string;

  @Field(() => GraphQLJSONObject, { nullable: true })
  @Column({ nullable: true, type: 'jsonb' })
  preferences?: JSON;
}

if I remove portalPreferences from company, then the setRelations works fine.

the reason for the separate potential entity was the separation of domains, and very few companies have portal preferences. I was attempting to be smart and allowing the front end dev to save portal preferences with a companyId and they would start showing up on company queries.

This approach DOES work from all perspectives with the exception of setRelations call on a company attribute with an empty array. I would think this is a bug.. not sure where in the code it would be manifesting though.

TriPSs commented 3 months ago

interesting, could you create a repo with the issue? Then I can take a look to see what is happening.