Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 16 additions & 16 deletions docs/patterns/macro.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ head:
import Tab from '../components/fern/tab.vue'
</script>

Macro is similar to a function that have a control over the lifecycle event, schema, context with full type safety.
Macro is similar to a function that has control over the lifecycle event, schema, and context with full type safety.

Once defined, it will be available in hook and can be activated by adding the property.
Once defined, it will be available in the hook and can be activated by adding the property.

```typescript twoslash
import { Elysia } from 'elysia'
Expand All @@ -48,7 +48,7 @@ Accessing the path should log **"Elysia"** as the results.
## Property shorthand
Starting from Elysia 1.2.10, each property in the macro object can be a function or an object.

If the property is an object, it will be translated to a function that accept a boolean parameter, and will be executed if the parameter is true.
If the property is an object, it will be translated to a function that accepts a boolean parameter and will be executed if the parameter is true.
```typescript
import { Elysia } from 'elysia'

Expand Down Expand Up @@ -79,11 +79,11 @@ export const auth = new Elysia()

**macro** has the same API as hook.

In previous example, we create a **hi** macro accepting a **string**.
In the previous example, we created a **hi** macro accepting a **string**.

We then assigned **hi** to **"Elysia"**, the value was then sent back to the **hi** function, and then the function added a new event to **beforeHandle** stack.

Which is an equivalent of pushing function to **beforeHandle** as the following:
Which is an equivalent of pushing the function to **beforeHandle** as follows:

```typescript
import { Elysia } from 'elysia'
Expand All @@ -96,7 +96,7 @@ const app = new Elysia()
})
```

**macro** shine when a logic is more complex than accepting a new function, for example creating an authorization layer for each route.
**macro** shine when a logic is more complex than accepting a new function, for example, creating an authorization layer for each route.

```typescript twoslash
// @filename: auth.ts
Expand Down Expand Up @@ -134,7 +134,7 @@ Macro can also register a new property to the context, allowing us to access the

The field can accept anything ranging from string to function, allowing us to create a custom life cycle event.

**macro** will be executed in order from top-to-bottom according to definition in hook, ensure that the stack is handled in the correct order.
**macro** will be executed in order from top-to-bottom according to the definition in the hook, ensuring that the stack is handled in the correct order.

## Resolve

Expand All @@ -159,14 +159,14 @@ new Elysia()

In the example above, we add a new property **user** to the context by returning an object with a **resolve** function.

Here's an example that macro resolve could be useful:
- perform authentication and add user to the context
Here's an example where macro resolve could be useful:
- perform authentication and add the user to the context
- run an additional database query and add data to the context
- add a new property to the context


### Macro extension with resolve
Due to TypeScript limitation, macro that extends other macro cannot infer type into **resolve** function.
Due to TypeScript's limitation, a macro that extends other macro cannot infer type into **resolve** function.

We provide a named single macro as a workaround to this limitation.

Expand All @@ -187,7 +187,7 @@ new Elysia()
```

## Schema
You can define a custom schema for your macro, to make sure that the route using the macro is passing the correct type.
You can define a custom schema for your macro to make sure that the route using the macro is passing the correct type.

```typescript twoslash
import { Elysia, t } from 'elysia'
Expand All @@ -212,12 +212,12 @@ new Elysia()

Macro with schema will automatically validate and infer type to ensure type safety, and it can co-exist with existing schema as well.

You can also stack multiple schema from different macro, or even from Standard Validator and it will work together seamlessly.
You can also stack multiple schemas from different macros, or even from the Standard Validator, and it will work together seamlessly.

### Schema with lifecycle in the same macro
Similar to [Macro extension with resolve](#macro-extension-with-resolve),

Macro schema also support type inference for **lifecycle within the same macro** **BUT** only with named single macro due to TypeScript limitation.
Macro schema also supports type inference for **lifecycle within the same macro** **BUT** only with a named single macro due to TypeScript limitation.

```typescript twoslash
import { Elysia, t } from 'elysia'
Expand All @@ -233,9 +233,9 @@ new Elysia()
})
```

If you want to use lifecycle type inference within the same macro, you might want to use a named single macro instead of multiple stacked macro
If you want to use lifecycle type inference within the same macro, you might want to use a named single macro instead of multiple stacked macros

> Not to confused with using macro schema to infer type into route's lifecycle event. That works just fine this limitation only apply to using lifecycle within the same macro.
> Not to be confused with using macro schema to infer type into the route's lifecycle event. That works just fine. This limitation only applies to using lifecycle within the same macro.

## Extension
Macro can extends other macro, allowing you to build upon existing one.
Expand Down Expand Up @@ -296,6 +296,6 @@ new Elysia()
```


However, if you evert accidentally create a circular dependency, Elysia have a limit stack of 16 to prevent infinite loop in both runtime and type inference.
However, if you ever accidentally create a circular dependency, Elysia has a limited stack of 16 to prevent an infinite loop in both runtime and type inference.

If the route already has OpenAPI detail, it will merge the detail together but prefers the route detail over macro detail.