TriPSs / nestjs-query

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

Relation fields in TypeOrm Embedded Entities are always null #255

Closed IvanKudryavskyReq closed 5 months ago

IvanKudryavskyReq commented 5 months ago

Describe the bug If some enity has an Embedded field that has a ManyToOne relationship, the responses will return null (User -> Address (embedded) -> State (ManyToOne))

Have you read the Contributing Guidelines?

Yes

To Reproduce Steps to reproduce the behavior:

  1. Create Entities: state.entity.ts
    
    import { Column, Entity, PrimaryGeneratedColumn, Index } from 'typeorm';

@Entity() export class State { @PrimaryGeneratedColumn() id: number;

@Column({ length: 50, unique: true }) @Index() name: string; }


address.ts:

import { ManyToOne } from 'typeorm'; import { State } from './state.entity';

export class Address { @ManyToOne(() => State, { cascade: ['remove'] }) state: State; }

user.entity.ts:

import { Entity, Column, PrimaryGeneratedColumn, ManyToOne } from 'typeorm'; import { Address } from './address.entity'; import { State } from './state.entity';

@Entity() export class User { @PrimaryGeneratedColumn('uuid') id: string;

@Column(() => Address) address?: Address;

@ManyToOne(() => State, { cascade: ['remove'] }) state: State; }

2. Create responses
state.response.ts

import { Field, Int, ObjectType } from '@nestjs/graphql'; import { FilterableField, IDField } from '@ptc-org/nestjs-query-graphql';

@ObjectType('State') export class StateResponse { @IDField(() => Int) id: number;

@Field() @FilterableField() name: string; }

address.response.ts

import { ObjectType } from '@nestjs/graphql'; import { StateResponse } from './state.response'; import { Relation } from '@ptc-org/nestjs-query-graphql';

@ObjectType('Address') @Relation('state', () => StateResponse) export class AddressResponse { }

user.response.ts

import { Field, GraphQLISODateTime, ID, ObjectType } from '@nestjs/graphql'; import { AddressResponse } from './address.response'; import { Address } from './address'; import { FilterableField, IDField, PagingStrategies, QueryOptions, Relation } from '@ptc-org/nestjs-query-graphql'; import { StateResponse } from './state.response';

@ObjectType('User') @QueryOptions({ pagingStrategy: PagingStrategies.OFFSET, enableTotalCount: true, }) @Relation('state', () => StateResponse) export class UserResponse { @IDField(() => ID) id: string;

@Field((type) => AddressResponse, { nullable: true }) address?: Address; }

3. Create data in DB
4. Execute query:

query User($userId: ID!) { user(id: $userId) { address { state { name } } state { id name shortName } } }

5. Result:

{ "data": { "user": { "address": { "state": null }, "state": { "id": 5, "name": "California", } } } }


in user.state - has state information, in user.address.state - null

**Expected behavior**
It is expected that the address.state field will have an object with fields

**Screenshots**
![image](https://github.com/TriPSs/nestjs-query/assets/42865530/d4f5fa61-7048-4ef1-9998-9ade880fa6e2)
![image](https://github.com/TriPSs/nestjs-query/assets/42865530/d777fd7b-c54b-4e04-b34e-a28160965848)

**Desktop (please complete the following information):**
 - Node Version - v20.12.1
 - Nestjs-query Version: 6.1.0
 - DB: postgres:16.2-alpine3.19
TriPSs commented 5 months ago

Could you try to update User to:

@Entity()
export class User {
  @PrimaryGeneratedColumn('uuid')
  id: string;

  @Column(() => Address)
  address?: Address;

  @ManyToOne(() => State, { cascade: ['remove'] })
  state: State;

  // Add this
  @Column()
  stateId: string
}
IvanKudryavskyReq commented 5 months ago

I added

@Column()
stateId: string

in user.entity.ts - no change In address.ts - no change either

The response looks the same as in the last screenshot

TriPSs commented 5 months ago

Then please create a example repo or add it as a test case to the examples.

IvanKudryavskyReq commented 5 months ago

Done: https://github.com/IvanKudryavskyReq/nestjs-query-issue-255 Added startup instructions to README.md

TriPSs commented 5 months ago

I see, did not know this was possible:

@Entity()
export class User {
  @Column(() => Address)
  address?: Address;
}

But in the repo you gave the ManyToOne was inside Address, so adding the following in address.ts will fill the stateId field inside:

  @Column()
  stateId: string;

This package does not handle the case you have here, every "object" in the main should be a relation if you want to go deeper. Since the field addressStateId is added to the root one you could keep address as is but add that field to the entity and then add the relation from user -> state to the user type.

TriPSs commented 5 months ago

Closing this, if still an issue you can re-open the ticket.