elysiajs / elysia

Ergonomic Framework for Humans
https://elysiajs.com
MIT License
9.09k stars 193 forks source link

Decorates are replacing each other #673

Closed vitorpldev closed 3 weeks ago

vitorpldev commented 1 month ago

What version of Elysia.JS is running?

1.0.23

What platform is your computer?

Linux 6.5.0-35-generic x86_64 x86_64

What steps can reproduce the bug?

Captura de tela de 2024-06-09 23-59-08

I ended up putting the controllers for each route into groups, the user and url controllers both have the /create route. For some reason, when I call /user/create, Elysia is running the service from the /url/create route

What is the expected behavior?

No response

What do you see instead?

No response

Additional information

No response

vitorpldev commented 1 month ago

I've been trying to find out the cause of this for some time, from the tests I've done, apparently the decorates I've been using on different controllers are replacing each other.

code

For some reason in the controllers function when I say to group the urlController after the userController, the decorate that the userController uses (userService) is being deleted and replaced by the decorate of the urlController (urlService). When I call the /user/create route, the result is that services.user.create is not a defined function

bogeychan commented 4 weeks ago

@vitorpldev, can you please post code snippets in text form? checkout Creating and highlighting code blocks

vitorpldev commented 4 weeks ago

Okay, the code I gave as an example is this:

import Elysia, { t } from "elysia";

const user_decorator = (application: Elysia) => {
  return application.decorate({
    services: {
      find: (name: string) => `The name of user is ${name}`,
    },
  });
};

const url_decorator = (application: Elysia) => {
  return application.decorate({
    services: {
      find: (url: string) => `The url is ${url}`,
    },
  });
};

const user_controller = (application: Elysia) => {
  return application.use(user_decorator).get(
    "/",
    ({ query, services }) => {
      return new Response(services.find(query.value), { status: 200 });
    },
    {
      query: t.Object({ value: t.String() }),
    }
  );
};

const url_controller = (application: Elysia) => {
  return application.use(url_decorator).get(
    "/",
    ({ query, services }) => {
      return new Response(services.find(query.value), { status: 200 });
    },
    {
      query: t.Object({ value: t.String() }),
    }
  );
};

const controller = (application: Elysia) => {
  return application
    .group("/user", (user) => {
      return user.use(user_controller);
    })
    .group("/url", (url) => {
      return url.use(url_controller);
    });
};

const app = new Elysia().use(controller);

app.listen({ hostname: "localhost", port: 3030 }, (server) => {
  console.log(`Server is running at ${server.url}`);
});

If in this code I make a request for GET for http://localhost:3030/user/ passing the value "Elysia" in the query, the expected would be "The name of user is Elysia", but the result is "The url is Elysia". This is because the way in controllers I am grouping the url_controller after the user_controller, the decorate of the url_controller is replacing the decorate of the user_controller

nxht commented 3 weeks ago

@vitorpldev Both user_decorator and url_decorator is decorating same services, I think it's expected to get overridden.

You can either

vitorpldev commented 3 weeks ago

Perfect, thank you my friend.