Skip to content

Typescript generator: Handle resources with explicit id field #132

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

luca-nardelli
Copy link
Contributor

@luca-nardelli luca-nardelli commented May 21, 2019

Q A
Bug fix? yes
New feature? no
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets
License MIT
Doc PR

If any of our resources are identified using Doctrine's Identity Through Foreign Entities (https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/tutorials/composite-primary-keys.html#identity-through-foreign-entities) and they also declare a getter function to serialize their id in the id property of the response, then the standard template defined for the typescript interface does not work for them since it creates 2 members named id in the interface. This PR fixes it by removing id as a hard-coded field in the Handlebars template and by appending the id field to the list of fields to generate only if no property named id exists.

Code example:

Entity.php

/**
 * @ApiResource(
 *     normalizationContext={"groups"={"entityRead"}}
 * )
 * @ORM\Entity(repositoryClass="App\Repository\ProducerRepository")
 * @ORM\HasLifecycleCallbacks()
 */
class Entity
{
    /**
     * @ORM\Id()
     * @ORM\JoinColumn(name="id")
     * @ORM\OneToOne(targetEntity="App\Entity\AppUser", inversedBy="entity", cascade={"persist", "remove"})
     * @Groups({"entityRead","userRead"})
     * @var AppUser
     */
    private $user;
    
    /**
     * @return string|null
     * @Groups({"entityRead","userRead"})
     */
    public function getId(): ?string
    {
        return $this->user->getId();
    }

}

When this get serialized by the serializer, we get

{
  user: <user object serialized or IRI>,
  id: '<identifier>'
}

Without the getId() getter we would only have the user property in the response.

However, by adding this getId, I noticed that Api platform would add a new id field in the Hydra documentation (standard resources that have a true id property do not expose an id field in the documentation, I don't know why though), and this would in turn cause the client generator to generate an interface such as (imports omitted for brevity)

interface Entity {
  '@id'?: string;
  'id'?: string;
  'user': User;
  readonly 'id'?: string;
}

This makes the typescript compiler not happy as we have a re-definition of the id field.

So, maybe this could be solved on the PHP side by always specifying the id field in the documentation, but for the time being this solves the issue by selectively adding the id field only when it's not already declared on the resource.

@luca-nardelli
Copy link
Contributor Author

I've also added a test that handles a resource with an explicit id field.

@dunglas or @soyuka, let me know if you need a runnable example from the php side as well.

Copy link
Member

@soyuka soyuka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@dunglas dunglas merged commit 4f86a44 into api-platform:master Jun 7, 2019
@dunglas
Copy link
Member

dunglas commented Jun 7, 2019

Thanks @luca-nardelli

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants