Skip to content

Commit 8aab745

Browse files
🔧 fix: typos and missing imports (#180)
* docs(introduction): fix typos * docs(at-a-glance): fix typo * docs(essential): fix typos * chore: update bun.lockb * docs(essential): fix scope imports + onAfterHandle typo * docs(essential): update schema.md imports * docs(essential): update life-cycle.md imports * fix: undo required code formatting * fix: undo required code formatting * fix: revert bun.lockb --------- Co-authored-by: bogeychan <[email protected]>
1 parent b66a449 commit 8aab745

File tree

8 files changed

+150
-115
lines changed

8 files changed

+150
-115
lines changed

‎bun.lockb

100755100644
File mode changed.

‎docs/at-glance.md

Lines changed: 38 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,25 @@
11
---
22
title: At glance - ElysiaJS
33
head:
4-
- - meta
5-
- property: 'og:title'
6-
content: At glance - ElysiaJS
4+
- - meta
5+
- property: 'og:title'
6+
content: At glance - ElysiaJS
77

8-
- - meta
9-
- name: 'description'
10-
content: Designed with ergonomic design, extensive support for TypeScript, modern JavaScript API, optimized for Bun. Offers a unique experience unified type, and end-to-end type safety while maintaining excellent performance.
8+
- - meta
9+
- name: 'description'
10+
content: Designed with ergonomic design, extensive support for TypeScript, modern JavaScript API, optimized for Bun. Offers a unique experience unified type, and end-to-end type safety while maintaining excellent performance.
1111

12-
- - meta
13-
- property: 'og:description'
14-
content: Designed with ergonomic design, extensive support for TypeScript, modern JavaScript API, optimized for Bun. Offers a unique experience unified type, and end-to-end type safety while maintaining excellent performance.
12+
- - meta
13+
- property: 'og:description'
14+
content: Designed with ergonomic design, extensive support for TypeScript, modern JavaScript API, optimized for Bun. Offers a unique experience unified type, and end-to-end type safety while maintaining excellent performance.
1515
---
1616

1717
# At glance
18+
1819
Elysia is designed with familiar API from Express and Fastify with extensive support for TypeScript, modern JavaScript API, and optimized for Bun.
1920

2021
Here's a simple hello world in Elysia.
22+
2123
```typescript
2224
import { Elysia } from 'elysia'
2325

@@ -29,34 +31,37 @@ new Elysia()
2931
Navigate to [localhost:3000](http://localhost:3000/) and it should show 'Hello Elysia' as a result.
3032

3133
## Performance
34+
3235
Building on Bun and extensive optimization like Static Code Analysis allows Elysia to generate optimized code on the fly.
3336

3437
Elysia can outperform most of the web frameworks available today<a href="#ref-1"><sup>[1]</sup></a>, and even match the performance of Golang and Rust framework<a href="#ref-2"><sup>[2]</sup></a>.
3538

36-
| Framework | Runtime | Average | Plain Text | Dynamic Parameters | JSON Body |
37-
| ----------------- | -------- | ----------- | ---------- | ------------------ | ---------- |
38-
| Elysia | bun | 275,063.507 | 326,868.9 | 261,729.3 | 236,592.32 |
39-
| Bun | bun | 273,634.127 | 322,071.07 | 251,679.46 | 247,151.85 |
40-
| Hono | bun | 257,532.08 | 320,757.07 | 233,769.22 | 218,069.95 |
41-
| Web Standard | bun | 242,838.703 | 288,692.76 | 226,591.45 | 213,231.9 |
42-
| Hyper Express | node | 242,045.913 | 354,697.63 | 277,109.51 | 94,330.6 |
43-
| h3 | node | 112,677.263 | 137,556.49 | 101,431.5 | 99,043.8 |
44-
| Fastify | node | 64,145.95 | 74,631.46 | 66,235.48 | 51,570.91 |
45-
| Koa | node | 38,696.13 | 44,741.88 | 39,790.11 | 31,556.4 |
46-
| Hapi | node | 28,170.763 | 42,780.44 | 15,350.06 | 26,381.79 |
47-
| Adonis | node | 23,367.073 | 22,673.54 | 21,442.97 | 25,984.71 |
48-
| Express | node | 16,301.823 | 17,974.35 | 17,090.62 | 13,840.5 |
49-
| Nest | node | 14,978.863 | 16,926.01 | 15,507.62 | 12,502.96 |
39+
| Framework | Runtime | Average | Plain Text | Dynamic Parameters | JSON Body |
40+
| ------------- | ------- | ----------- | ---------- | ------------------ | ---------- |
41+
| Elysia | bun | 275,063.507 | 326,868.9 | 261,729.3 | 236,592.32 |
42+
| Bun | bun | 273,634.127 | 322,071.07 | 251,679.46 | 247,151.85 |
43+
| Hono | bun | 257,532.08 | 320,757.07 | 233,769.22 | 218,069.95 |
44+
| Web Standard | bun | 242,838.703 | 288,692.76 | 226,591.45 | 213,231.9 |
45+
| Hyper Express | node | 242,045.913 | 354,697.63 | 277,109.51 | 94,330.6 |
46+
| h3 | node | 112,677.263 | 137,556.49 | 101,431.5 | 99,043.8 |
47+
| Fastify | node | 64,145.95 | 74,631.46 | 66,235.48 | 51,570.91 |
48+
| Koa | node | 38,696.13 | 44,741.88 | 39,790.11 | 31,556.4 |
49+
| Hapi | node | 28,170.763 | 42,780.44 | 15,350.06 | 26,381.79 |
50+
| Adonis | node | 23,367.073 | 22,673.54 | 21,442.97 | 25,984.71 |
51+
| Express | node | 16,301.823 | 17,974.35 | 17,090.62 | 13,840.5 |
52+
| Nest | node | 14,978.863 | 16,926.01 | 15,507.62 | 12,502.96 |
5053

5154
## TypeScript
55+
5256
Elysia is built with a complex type system trying to infer every possible detail from simple path parameters to full-blown recursive instance deep merge to provide you the most out of TypeScript.
5357

5458
Take a look at this example:
59+
5560
```typescript
5661
import { Elysia } from 'elysia'
5762

5863
new Elysia()
59-
.get('/id/:id', ({ params: { id }}) => id)
64+
.get('/id/:id', ({ params: { id } }) => id)
6065
.listen(3000)
6166
```
6267

@@ -67,14 +72,16 @@ In most framework, you need to provide a generic type to the **id** parameter wh
6772
Elysia's goal is to help you write less TypeScript and focus more on Business logic. Let the complex type be handled by the framework.
6873

6974
## Unified Type
75+
7076
To take a step further, Elysia provide **Elysia.t**, a schema builder to validate type and value in both runtime and compile-time to create a single source of truth for your data-type. Elysia refers this term as **Unified Type**.
7177

7278
Let's modify the previous code to accept only a numeric value instead of a string.
79+
7380
```typescript
7481
import { Elysia, t } from 'elysia'
7582

7683
new Elysia()
77-
.get('/id/:id', ({ params: { id }}) => id, {
84+
.get('/id/:id', ({ params: { id } }) => id, {
7885
params: t.Object({
7986
id: t.Numeric()
8087
})
@@ -87,6 +94,7 @@ This code ensures that our path parameter **id**, will always be a numeric strin
8794
With Elysia schema builder, we can ensure type safety like a strong-typed language with a single source of truth.
8895

8996
## Standard
97+
9098
Elysia adopts many standards by default, like OpenAPI, and WinterCG compliance, allowing you to integrate with most of the industry standard tools or at least easily integrate with tools you are familiar with.
9199

92100
For instance, as Elysia adopts OpenAPI by default, generating a documentation with Swagger is as easy as adding a one-liner:
@@ -97,7 +105,7 @@ import { swagger } from '@elysiajs/swagger'
97105

98106
new Elysia()
99107
.use(swagger())
100-
.get('/id/:id', ({ params: { id }}) => id, {
108+
.get('/id/:id', ({ params: { id } }) => id, {
101109
params: t.Object({
102110
id: t.Numeric()
103111
})
@@ -108,6 +116,7 @@ new Elysia()
108116
With the Swagger plugin, you can seamlessly generate a Swagger page without additional code or specific config and share it with your team effortlessly.
109117

110118
## End-to-end Type Safety
119+
111120
With Elysia, type safety is not only limited to server-side only.
112121

113122
With Elysia, you can synchronize your type with your frontend team automatically like tRPC, with Elysia's client library, "Eden".
@@ -118,7 +127,7 @@ import { swagger } from '@elysiajs/swagger'
118127

119128
const app = new Elysia()
120129
.use(swagger())
121-
.get('/id/:id', ({ params: { id }}) => id, {
130+
.get('/id/:id', ({ params: { id } }) => id, {
122131
params: t.Object({
123132
id: t.Numeric()
124133
})
@@ -129,6 +138,7 @@ export type App = typeof app
129138
```
130139
131140
And on your client side:
141+
132142
```typescript
133143
// client.ts
134144
import { edenTreaty } from '@elysiajs/eden'
@@ -145,6 +155,7 @@ With Eden, you can use the existing Elysia type to query Elysia server **without
145155
Elysia is not only about helping you to create a confident backend but for all that is beautiful in this world.
146156

147157
---
158+
148159
<small id="ref-1">1. Measure in requests/second. The benchmark for parsing query, path parameter and set response header on Debian 11, Intel i7-13700K tested on Bun 0.7.2 on 6 Aug 2023. See the benchmark condition [here](https://github.com/SaltyAom/bun-http-framework-benchmark/tree/c7e26fe3f1bfee7ffbd721dbade10ad72a0a14ab#results).</small>
149160

150161
<small id="ref-2">2. Based on [TechEmpower Benchmark round 22](https://www.techempower.com/benchmarks/#section=data-r22&hw=ph&test=composite).</small>

‎docs/essential/context.md

Lines changed: 59 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,39 @@
11
---
22
title: Handler - ElysiaJS
33
head:
4-
- - meta
5-
- property: 'og:title'
6-
content: Handler - ElysiaJS
4+
- - meta
5+
- property: 'og:title'
6+
content: Handler - ElysiaJS
77

8-
- - meta
9-
- name: 'description'
10-
content: Context is information about each request from the client, unique to each request with a global mutable store. Context can be customized using state, decorate and derive.
8+
- - meta
9+
- name: 'description'
10+
content: Context is information about each request from the client, unique to each request with a global mutable store. Context can be customized using state, decorate and derive.
1111

12-
- - meta
13-
- property: 'og:description'
14-
content: Context is information about each request from the client, unique to each request with a global mutable store. Context can be customized using state, decorate and derive.
12+
- - meta
13+
- property: 'og:description'
14+
content: Context is information about each request from the client, unique to each request with a global mutable store. Context can be customized using state, decorate and derive.
1515
---
1616

1717
# Context
18-
Context is information of each request passed to [route handler](/essential/handler).
19-
20-
Context is unique for each request, and is not shared except it's a `store` property which is a global mutable state object, (aka state).
21-
22-
Elysia context is consists of:
23-
- **path** - Pathname of the request
24-
- **body** - [HTTP message](https://developer.mozilla.org/en-US/docs/Web/HTTP/Messages), form or file upload.
25-
- **query** - [Query String](https://en.wikipedia.org/wiki/Query_string), include additional parameters for search query as JavaScript Object. (Query is extract from a value after pathname starting from '?' question mark sign)
26-
- **params** - Elysia's path parameters parsed as JavaScript object
27-
- **headers** - [HTTP Header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers), additional information about the request like User-Agent, Content-Type, Cache Hint.
28-
- **request** - [Web Standard Request](https://developer.mozilla.org/en-US/docs/Web/API/Request)
29-
- **store** - A global mutable store for Elysia instance
30-
- **cookie** - A global mutable signal store for interacting with Cookie (including get/set)
31-
- **set** - Property to apply to Response:
32-
- **status** - [HTTP status](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status), default to 200 if not set.
33-
- **headers** - Response headers
34-
- **redirect** - Response as a path to redirect to
18+
19+
Context is information of each request passed to a [route handler](/essential/handler).
20+
21+
Context is unique for each request, and is not shared unless it's a `store` property which is a global mutable state object, (aka state).
22+
23+
Elysia context consists of:
24+
25+
- **path** - Pathname of the request
26+
- **body** - [HTTP message](https://developer.mozilla.org/en-US/docs/Web/HTTP/Messages), form or file upload.
27+
- **query** - [Query String](https://en.wikipedia.org/wiki/Query_string), include additional parameters for search query as JavaScript Object. (Query is extracted from a value after pathname starting from '?' question mark sign)
28+
- **params** - Elysia's path parameters parsed as JavaScript object
29+
- **headers** - [HTTP Header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers), additional information about the request like User-Agent, Content-Type, Cache Hint.
30+
- **request** - [Web Standard Request](https://developer.mozilla.org/en-US/docs/Web/API/Request)
31+
- **store** - A global mutable store for Elysia instance
32+
- **cookie** - A global mutable signal store for interacting with Cookie (including get/set)
33+
- **set** - Property to apply to Response:
34+
- **status** - [HTTP status](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status), defaults to 200 if not set.
35+
- **headers** - Response headers
36+
- **redirect** - Response as a path to redirect to
3537

3638
## Extending context
3739

@@ -40,17 +42,19 @@ Because Elysia only provides essential information about the Request, you can cu
4042
Extraction of a user ID or another frequently used function related to the request, for example, into Context itself.
4143

4244
You can extend Elysia's context by using:
43-
- **state** - Create a global mutable state into **Context.store**
44-
- **decorate** - Add additional function or property assigned to **Context**
45-
- **derive** - Add additional property based on existing property or request which is uniquely assigned to every request.
45+
46+
- **state** - Create a global mutable state into **Context.store**
47+
- **decorate** - Add additional function or property assigned to **Context**
48+
- **derive** - Add additional property based on existing property or request which is uniquely assigned to every request.
4649

4750
The following APIs add extra functionality to the Context.
4851

4952
::: tip
50-
It's recommended to assign property related to request and response, or frequently used function to Context for separation of concern.
53+
It's recommended to assign properties related to request and response, or frequently used functions to Context for separation of concerns.
5154
:::
5255

5356
## Store
57+
5458
**State** is a global mutable object shared across the Elysia app.
5559

5660
If you are familiar with frontend libraries like React, Vue, or Svelte, there's a concept of Global State Management, which is also partially implemented in Elysia via state and store.
@@ -60,6 +64,7 @@ If you are familiar with frontend libraries like React, Vue, or Svelte, there's
6064
**state** is a function to assign an initial value to **store**, which could be mutated later.
6165

6266
To assign value to `store`, you can use **Elysia.state**:
67+
6368
```typescript
6469
import { Elysia } from 'elysia'
6570

@@ -71,6 +76,7 @@ new Elysia()
7176
Once you call **state**, value will be added to **store** property, and can be later used after in handler.
7277

7378
Beware that you cannot use state value before being assigned.
79+
7480
```typescript
7581
import { Elysia } from 'elysia'
7682

@@ -83,12 +89,13 @@ new Elysia()
8389
```
8490

8591
::: tip
86-
Elysia registers state value into the store automatically without explicit type or additional TypeScript generic is needed.
92+
Elysia registers state values into the store automatically without explicit type or additional TypeScript generic needed.
8793

8894
This is the magic of the Elysia-type system that does this automatically.
8995
:::
9096

9197
## Decorate
98+
9299
Like **store**, **decorate** assigns an additional property to **Context** directly.
93100

94101
The only difference is that the value should be read-only and not reassigned later.
@@ -109,6 +116,7 @@ new Elysia()
109116
```
110117

111118
## Derive
119+
112120
Like `decorate`, you can assign an additional property to **Context** directly.
113121

114122
But instead of setting the property before the server is started. **derive** assigns a property when each request happens. Allowing us to extract a piece of information into a property instead.
@@ -129,17 +137,20 @@ new Elysia()
129137

130138
Because **derive** is assigned once a new request starts, **derive** can access Request properties like **headers**, **query**, **body** where **store**, and **decorate** can't.
131139

132-
Unlike **state**, and **decorate**. Properties which assigned by **derive** is unique and not shared with another request.
140+
Unlike **state**, and **decorate**. Properties that are assigned by **derive** are unique and not shared with another request.
133141

134142
## Pattern
143+
135144
**state**, **decorate** offers a similar APIs pattern for assigning property to Context as the following:
136-
- key-value
137-
- object
138-
- remap
145+
146+
- key-value
147+
- object
148+
- remap
139149

140150
Where **derive** can be only used with **remap** because it depends on existing value.
141151

142152
### key-value
153+
143154
You can use **state**, and **decorate** to assign a value using a key-value pattern.
144155

145156
```typescript
@@ -153,22 +164,23 @@ new Elysia()
153164
This pattern is great for readability for setting a single property.
154165

155166
### Object
167+
156168
Assigning multiple properties is better contained in an object for a single assignment.
157169

158170
```typescript
159171
import { Elysia } from 'elysia'
160172

161-
new Elysia()
162-
.decorate({
163-
logger: new Logger(),
164-
trace: new Trace(),
165-
telemetry: new Telemetry()
166-
})
173+
new Elysia().decorate({
174+
logger: new Logger(),
175+
trace: new Trace(),
176+
telemetry: new Telemetry()
177+
})
167178
```
168179

169180
The object offers a less repetitive API for setting multiple values.
170181

171182
### Remap
183+
172184
Remap is a function reassignment.
173185

174186
Allowing us to create a new value from existing value like renaming or removing a property.
@@ -200,6 +212,7 @@ Using remap, Elysia will treat a returned object as a new property, removing any
200212
:::
201213

202214
## Affix
215+
203216
To provide a smoother experience, some plugins might have a lot of property value which can be overwhelming to remap one-by-one.
204217

205218
The **Affix** function which consists of **prefix** and **suffix**, allowing us to remap all property of an instance.
@@ -225,21 +238,21 @@ Allowing us to bulk remap a property of the plugin effortlessly, preventing the
225238
By default, **affix** will handle both runtime, type-level code automatically, remapping the property to camelCase as naming convention.
226239

227240
In some condition, you can also remap `all` property of the plugin:
241+
228242
```ts
229243
const app = new Elysia()
230-
.use(
231-
setup
232-
.prefix('all', 'setup')
233-
)
244+
.use(setup.prefix('all', 'setup'))
234245
.get('/', ({ setupCarbon }) => setupCarbon)
235246
```
236247

237248
## Reference and value
249+
238250
To mutate the state, it's recommended to use **reference** to mutate rather than using an actual value.
239251

240252
When accessing the property from JavaScript, if you define a primitive value from an object property as a new value, the reference is lost, the value is treated as new separate value instead.
241253

242254
For example:
255+
243256
```typescript
244257
const store = {
245258
counter: 0
@@ -252,6 +265,7 @@ console.log(store.counter) // ✅ 1
252265
We can use **store.counter** to access and mutate the property.
253266

254267
However, if we define a counter as a new value
268+
255269
```typescript
256270
const store = {
257271
counter: 0

0 commit comments

Comments
 (0)