Skip to content
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

Cannot access derive properties in macro #558

Closed
raggesilver opened this issue Mar 19, 2024 · 1 comment
Closed

Cannot access derive properties in macro #558

raggesilver opened this issue Mar 19, 2024 · 1 comment
Assignees
Labels
good first issue Good for newcomers

Comments

@raggesilver
Copy link

What version of Elysia.JS is running?

1.0.5

What platform is your computer?

Darwin 23.2.0 x86_64 i386

What steps can reproduce the bug?

export const example = new Elysia()
  .derive({ as: "scoped" }, async () => {
    return { myProp: 42 };
  })
  .macro(({ onBeforeHandle }) => ({
    public: (_?: boolean) => {
      onBeforeHandle(ctx => {
        ctx.myProp; // myProp is number | undefined, but it is always undefined in runtime
      });
    },
  }));

What is the expected behavior?

We should be able to access derived props in the same scope.

What do you see instead?

Props are typed as maybe undefined and are all undefined during runtime.

Additional information

No response

@raggesilver raggesilver added the bug Something isn't working label Mar 19, 2024
@SaltyAom SaltyAom added the good first issue Good for newcomers label Jun 6, 2024
@SaltyAom
Copy link
Member

SaltyAom commented Jun 6, 2024

Hi, this is an expected behavior

This happens because of the scoping mechanism.
macro is global and applies to all routes while derive is defined for a subset of routes.


This means derive properties apply to self and parent, but not a scope beyond that in contrast to a global macro.
On the scope beyond the parent scope, myProp will be undefined while in self and parent is not.

Macro is public and can apply to any route so macro has to consider both scenarios, both myProp with value (in scope) and not (goes beyond scope).

Consider this code:

const plugin = new Elysia()
	.derive({ as: 'scoped' }, () => {
		return { myProp: 42 }
	})
	.macro(({ onBeforeHandle }) => ({
		public(_?: boolean) {
			onBeforeHandle(({ myProp }) => {
				console.log(myProp)
			})
		}
	}))
	.get('/', 'hi', {
		'public': true
	})

plugin.handle(new Request("http://localhost"))

In this code, myProp will be 42 because derive is applied to self which includes /.

Screenshot 2567-06-06 at 12 21 33

However, in this code:

import { Elysia } from '../src'

const plugin = new Elysia()
	.derive({ as: 'scoped' }, () => {
		return { myProp: 42 }
	})
	.macro(({ onBeforeHandle }) => ({
		public(_?: boolean) {
			onBeforeHandle(({ myProp }) => {
				console.log(myProp)
			})
		}
	}))

const parent = new Elysia().use(plugin)

const main = new Elysia().use(parent).get('/', 'hi', {
	public: true
})

main.handle(new Request('http://localhost'))

In this code, myProp will be undefined because it goes out of (parent) scope.

Screenshot 2567-06-06 at 12 21 41

However, if you set derive scope to global, myProp would not be undefined because derive is applied globally on the same scope as macro.

Setting derive as scoped:
Screenshot 2567-06-06 at 12 14 13

Setting derive as global:
Screenshot 2567-06-06 at 12 14 20

So the current behavior is correct because myProp could be either 42 or undefined because derive is defined as scope or local.

I'm closing the issue because this is not a bug but an intended feature to help developers catch bugs but feel free to continue the discussion if something is not clear or if you have more questions.

Thank you.

@SaltyAom SaltyAom closed this as completed Jun 6, 2024
@SaltyAom SaltyAom removed the bug Something isn't working label Jun 6, 2024
@SaltyAom SaltyAom self-assigned this Jun 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
good first issue Good for newcomers
Projects
None yet
Development

No branches or pull requests

2 participants