mathematic-inc / ts-japi

A highly-modular (typescript-friendly)-framework agnostic library for serializing data to the JSON:API specification
Apache License 2.0
202 stars 15 forks source link

[BUG] Bidirectional relationship leads to an infinity loop #58

Closed rogeraraujo90 closed 7 months ago

rogeraraujo90 commented 1 year ago

Describe the bug*

When creating a bi-directional relationship with the Relator class the result is an infinity loop

To Reproduce*

I have a class called Label which has a "parent" property of the Label type. My serializer looks like this:

import { Relator, Serializer } from "ts-japi";
import AppSerializer from "@config/server/serializers/AppSerializer";
import Label from "@models/Label";

export default class LabelSerializer extends AppSerializer {
  serializer: Serializer;

  constructor() {
    super();

    const LabelParentRelator = new Relator<Label, Label>(
      async ({ parent }) => parent,
      new LabelSerializer().serializer
    );

    this.serializer = new Serializer("label", {
      relators: [LabelParentRelator],
    });
  }
}

When I call labelSerializer.serializer.serialize(label) the result is:

RangeError: Maximum call stack size exceeded

The error is expected because of the constructor call, so I think we don't support bi-directional relationships or there is other API that is not documented to accomplish that.

Expected behavior*

I was expecting to see a serialized label with:

"relationships": {
  "parent": {
    "data": [
      {
        "type": "label",
        "id": <id>
      }
    ]
  }
}

Platform*

Additional context

{{Add any other context about the problem here.}}

* means required.

egmacke commented 1 year ago

@rogeraraujo90 apologies for the extremely late response. In case you're still having this issue (or for future readers of this issue) I believe the issue is as you indicate, that the LabelSerializer for the child relationship is being created each time the constructor is called.

Unless there's something very custom that you're trying to achieve (that's not given in the context of this ticket) I think the easiest solution for you is to simply define a static instance of the LabelSerializer which can then be used in the relator without needing to invoke the constructor which results in your infinite loop.

Hope that helps - if not then please provide some more context and I'll see how I can help

egmacke commented 7 months ago

Closing as stale and not an issue with the library