A repository lives in the data layer. That is the short and simple answer.
it's doing the work of an adapter(just adapting the fetch logic format of MongoDatabase to another format easier to use)
Using that definition of an adapter, arguably all classes in a well-abstracted codebase act as adapters.
Every class inherently couples ("adapts") its internal implementation to its public interface. In classes where the workload is not complex, it's possible to end up with a counterintuitively disproportionate amount of the effort being spent on the adaptation and not any other "real" logic.
That is perfectly fine, and is very common in codebases with proper layer separation. Not every layer is used to its fullest extent in every single one of its implementations.
For example, a data layer may have some complex queries that have meat on their bones; but at the same time most codebases also tend to contain very basic CRUD operations that don't require much logic to execute. Fetching an entity by its identifier, which is your example, is such a case of "trivial logic".
This is further compounded by Typescript allowing you to return any object of any type, as long as it fulfills the interface requirements. This is different in more strongly typed languages (e.g. C#) where your object needs to be of a specific class that explicitly implements the given interface.
In the case of C#, you tend to spend more effort on actually mapping from one object to another. Typescript bypasses this by dynamically checking the structure of the object directly (as opposed to C# which checks the structure of the type of the object), which leads to not needing to worry about the specific type of the objects.
As an aside, and probably biased because I'm a C# dev:
I'm not a big fan of this Typescript behavior. I prefer explicitly requiring that your entity type implements the given interface, because without doing so you have two separate definitions (the interface and the entity) which happen to be structurally similar, but it's very easy to make these go out of sync by adjusting one and not the other.
The benefit of explicitly marking the entity type as implementing the interface is that it becomes more obvious that you've adjusted one and forgot the other; which IMHO prevents silly bugs.
In short, because you are dealing with a trivial CRUD operation, coupled with the fact that Typescript almost entirely negates the need to remap your entity; leaves your class with little to do other than return the entity.
This does not mean the repository is superfluous. Its existence is justified in that it properly abstracts the responsibility of fetching the hero data from your mongo database. Trivial as it may be today, it may become more complex tomorrow. The repository is there to ensure that when and if this gets to be more complex, you are only required to make changes to the repository implementation and not your domain logic directly.
Some examples of such changes may include:
- Changing your underlying database provider
- Changing your underlying data entity structure (e.g. storing the data across multiple tables), without wanting to change your domain entity structure itself.
It's very common to want to do away with mostly passthrough layers in an attempt to be more efficient, but this is the most common trap that leads to bad practice and inflexible codebases.
You should instead judge the value of an abstraction by its responsibility, and not by the size of its implementation. The repository has a valid role to play in your codebase, even though that role is tiny at the moment.