Skip to content

Commit ce18ac1

Browse files
committed
🎉 feat: patterns
1 parent 5032463 commit ce18ac1

File tree

7 files changed

+125
-63
lines changed

7 files changed

+125
-63
lines changed

docs/.vitepress/config.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,39 @@ export default defineConfig({
207207
}
208208
]
209209
},
210+
{
211+
text: '🧭 Patterns',
212+
items: [
213+
{
214+
text: 'Cookie',
215+
link: '/patterns/cookie'
216+
},
217+
{
218+
text: 'Cookie Signature',
219+
link: '/patterns/cookie-signature'
220+
},
221+
{
222+
text: 'Web Socket',
223+
link: '/patterns/cookie'
224+
},
225+
{
226+
text: 'Documentation',
227+
link: '/patterns/creating-documentation'
228+
},
229+
{
230+
text: 'Trace',
231+
link: '/patterns/trace'
232+
},
233+
{
234+
text: 'Mount',
235+
link: '/patterns/mount'
236+
},
237+
{
238+
text: 'Lazy Loading Module',
239+
link: '/patterns/lazy-loading-module'
240+
}
241+
]
242+
},
210243
{
211244
text: 'Getting Started',
212245
items: [

docs/new/essential/context.md

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ new Elysia()
150150
The object offers a less repetitive API for setting multiple values.
151151

152152
### Remap
153-
Remap is a function reassignment.
153+
Remap is a function reassignment.
154154

155155
Allowing us to create a new value from existing value like renaming or removing a property.
156156

@@ -180,6 +180,41 @@ However, it's important to note that Elysia doesn't offer reactivity from this a
180180
Using remap, Elysia will treat a returned object as a new property, removing any property that is missing from the object.
181181
:::
182182
183+
## Affix
184+
The provide a smoother experience, some plugins might have a lot of property value which can be overwhelming to remap one-by-one.
185+
186+
The **Affix** function which consists of **prefix** and **suffix**, allowing us to remap all property of an instance.
187+
188+
```ts
189+
const setup = new Elysia({ name: 'setup' })
190+
.decorate({
191+
argon: 'a',
192+
boron: 'b',
193+
carbon: 'c'
194+
})
195+
196+
const app = new Elysia()
197+
.use(
198+
setup
199+
.prefix('decorator', 'setup')
200+
)
201+
.get('/', ({ setupCarbon }) => setupCarbon)
202+
```
203+
204+
Allowing us to bulk remap a property of the plugin effortlessly, preventing the name collision of the plugin.
205+
206+
By default, **affix** will handle both runtime, type-level code automatically, remapping the property to camelCase as naming convention.
207+
208+
In some condition, you can also remap `all` property of the plugin:
209+
```ts
210+
const app = new Elysia()
211+
.use(
212+
setup
213+
.prefix('all', 'setup')
214+
)
215+
.get('/', ({ setupCarbon }) => setupCarbon)
216+
```
217+
183218
## Reference and value
184219
To mutate the state, it's recommended to use `reference` to mutate rather than using an actual value.
185220

docs/new/validation/elysia-type.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ This is useful when an incoming value is a numeric string for example path param
2424
Numeric accepts the same attribute as [Numeric Instance](https://json-schema.org/draft/2020-12/json-schema-validation#name-validation-keywords-for-num)
2525

2626
## File
27-
A singular file. Often useful for HTTP body validation.
27+
A singular file. Often useful for **file upload** validation.
2828

2929
```typescript
3030
t.File()

docs/new/validation/reference-model.md

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ const app = new Elysia()
3939
})
4040
```
4141

42-
We can refactor them by declaring the model as a variable, and reuse them.
42+
We can refactor the code by extract the model as a variable, and reference them.
4343
```typescript
4444
import { Elysia, t } from 'elysia'
4545

@@ -56,9 +56,7 @@ const app = new Elysia()
5656
})
5757
```
5858

59-
This method of separation the concerns is an effective approach for maintaining clean code.
60-
61-
You might find yourself reusing multiple models with different controllers as the app gets more complex.
59+
This method of separation the concerns is an effective approach but we might find ourself reusing multiple models with different controllers as the app gets more complex.
6260

6361
We can resolve that by creating a "reference model"  allowing us to name the model and use auto-completion to reference it directly in `schema` by registering the models with `model`.
6462

@@ -126,9 +124,9 @@ export const authModel = new Elysia()
126124
```
127125

128126
## Naming Convention
129-
Duplicated model names will cause Elysia to throw an error. To prevent declaring duplicate model names, you can use the following naming convention.
127+
Duplicated model names will cause Elysia to throw an error. To prevent declaring duplicate model names, we can use the following naming convention.
130128

131-
Let's say that you have all models stored at `models/<name>.ts`, you can declare the prefix of the model as a namespace.
129+
Let's say that we have all models stored at `models/<name>.ts`, and declare the prefix of the model as a namespace.
132130

133131
```typescript
134132
// admin.model.ts

docs/patterns/cookie.md

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,21 +31,20 @@ app.get('/', ({ cookie: { name } }) => {
3131
})
3232
```
3333

34-
By default, Reactive Cookie can encode/decode type of object automatically. So if you like to set the cookie as an object, it will just work.
34+
By default, Reactive Cookie can encode/decode type of object automatically allowing us to treat cookie as an object without worrying about the encoding/decoding. **It just works**.
3535

3636
## Reactivity
37-
Elysia cookie is reactive, based on approach like signal.
37+
The Elysia cookie is reactive. This means that when you change the cookie value, the cookie will be updated automatically based on approach like signal.
3838

39-
Elysia cookie can sync the value of cookie, and set-headers automatically, providing a single source of truth for handling cookie.
39+
A single source of truth for handling cookies is provided by Elysia cookies, which have the ability to automatically set headers and sync cookie values.
4040

41-
If you don't set the new value for the cookie, the `Set-Cookie` header will not be send to keep the same cookie value, so you don't have to worry about the performance.
41+
Since cookies are Proxy-dependent objects by default, the extract value can never be **undefined**; instead, it will always be a value of `Cookie<unknown>`, which can be obtained by invoking the **.value** property.
4242

43-
By default, cookie is an object that rely on Proxy, so the extract value can never be **undefined**, it will always be a value of `Cookie<unknown>`, which you can retrieve its value by calling **.value** property.
44-
45-
If you iterate over the cookie jar, the value will be only iterated over an existing cookie value, so you can treat it as a normal object.
43+
We can treat the cookie jar as a regular object, iteration over it will only iterate over an already-existing cookie value.
4644

4745
## Cookie Attribute
4846
To use Cookie attribute, you can either use one of the following:
47+
4948
1. Setting the property directly
5049
2. Using `set` or `add` to update cookie property.
5150

docs/patterns/lazy-loading-module.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ head:
1515
---
1616

1717
# Lazy-Loading Module
18-
Modules are eagerly loaded by default.
18+
Modules are eagerly loaded by default.
1919

2020
Elysia loads all modules then registers and indexes all of them before starting the server. This enforces that all the modules have loaded before it starts accepting requests.
2121

@@ -53,7 +53,7 @@ const app = new Elysia()
5353

5454
Elysia static plugin is also a deferred module, as it loads files and registers files path asynchronously.
5555

56-
To ensure module registration before the server starts, you can use `await` on the deferred module.
56+
To ensure module registration before the server starts, we can use `await` on the deferred module.
5757

5858
```typescript
5959
// index.ts
@@ -78,7 +78,7 @@ const app = new Elysia()
7878
Using module lazy-loading is recommended when the module is computationally heavy and/or blocking.
7979

8080
## Testing
81-
In a test environment, you can use `await app.modules` to wait for deferred and lazy-loading modules.
81+
In a test environment, we can use `await app.modules` to wait for deferred and lazy-loading modules.
8282

8383
```typescript
8484
import { Elysia } from 'elysia'

docs/patterns/websocket.md

Lines changed: 42 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,17 @@ head:
1616

1717
# WebSocket
1818

19-
Elysia WebSocket extends Bun's WebSocket which uses [uWebSocket](https://github.com/uNetworking/uWebSockets) under the hood.
19+
WebSocket is a realtime protocol for communication between your client and server.
2020

21-
To use websocket, just call `ws()`:
21+
Unlike HTTP where our client repeatedly asking the website for information and waiting for a reply each time, WebSocket sets up a direct line where our client and server can send messages back and forth directly, making the conversation quicker and smoother without having to start over each message.
22+
23+
SocketIO is a popular library for WebSocket, but it is not the only one. Elysia uses [uWebSocket] [uWebSocket](https://github.com/uNetworking/uWebSockets) which Bun use under the hood with the same API.
24+
25+
To use websocket, simply call `Elysia.ws()`:
2226
```typescript
2327
import { Elysia } from 'elysia'
2428

25-
const app = new Elysia()
29+
new Elysia()
2630
.ws('/ws', {
2731
message(ws, message) {
2832
ws.send(message)
@@ -31,7 +35,39 @@ const app = new Elysia()
3135
.listen(8080)
3236
```
3337

34-
Like a normal route, WebSockets also accepts a **schema** object to strictly type and validate requests.
38+
## WebSocket message validation:
39+
40+
Same as normal route, WebSockets also accepts a **schema** object to strictly type and validate requests.
41+
42+
```typescript
43+
import { Elysia, t } from 'elysia'
44+
45+
const app = new Elysia()
46+
.ws('/ws', {
47+
// validate incoming message
48+
body: t.Object({
49+
message: t.String()
50+
}),
51+
message(ws, { message }) {
52+
ws.send({
53+
message,
54+
time: Date.now()
55+
})
56+
}
57+
})
58+
.listen(8080)
59+
```
60+
61+
WebSocket schema can validate the following:
62+
63+
- message - An incoming message.
64+
- query - query string or URL parameters.
65+
- params - Path parameters.
66+
- header - Request's headers.
67+
- cookie - Request's cookie
68+
- response - Value returned from handler
69+
70+
By default Elysia will parse incoming stringified JSON message as Object for validation.
3571

3672
## Configuration
3773
You can set Elysia constructor to set the Web Socket value.
@@ -43,9 +79,9 @@ new Elysia({
4379
})
4480
```
4581

46-
Elysia's WebSocket implementation extends Bun's WebSocket configuration so if you wish to configure the websocket you can refer to [Bun's WebSocket documentation](https://bun.sh/docs/api/websockets) to learn more about this.
82+
Elysia's WebSocket implementation extends Bun's WebSocket configuration, please refers to [Bun's WebSocket documentation](https://bun.sh/docs/api/websockets) for more information.
4783

48-
Below is a config that extends from [Bun WebSocket](https://bun.sh/docs/api/websockets#create-a-websocket-server)
84+
The following are a brief configuration from [Bun WebSocket](https://bun.sh/docs/api/websockets#create-a-websocket-server)
4985

5086
### perMessageDeflate
5187

@@ -114,20 +150,6 @@ WebSocketHandler extends config from [config](#config).
114150

115151
Below is a config which is accepted by `ws`.
116152

117-
## schema
118-
119-
Validatation for an incoming WebSocket request.
120-
121-
- headers: validate headers before upgrade to WebSocket
122-
- params: validate path paramters
123-
- query: validate query parameters
124-
- body: validate websocket message
125-
- response: validate websocket response
126-
127-
::: tip
128-
It's recommended to use query parameters instead of path parameters in WebSocket, as parsing path parameters is expensive and sometime unrealiable for multiple data with long value.
129-
:::
130-
131153
## open
132154

133155
Callback function for new websocket connection.
@@ -214,28 +236,3 @@ Like `transform`, but execute before validation of WebSocket message
214236
## header
215237

216238
Additional headers to add before upgrade connection to WebSocket.
217-
218-
## WebSocket message validation:
219-
220-
Validate incoming WebSocket message.
221-
222-
By default Elysia will parse incoming stringified JSON message as Object for validation.
223-
224-
```typescript
225-
import { Elysia, t } from 'elysia'
226-
227-
const app = new Elysia()
228-
.ws('/ws', {
229-
// validate incoming message
230-
body: t.Object({
231-
message: t.String()
232-
}),
233-
message(ws, { message }) {
234-
ws.send({
235-
message,
236-
time: Date.now()
237-
})
238-
}
239-
})
240-
.listen(8080)
241-
```

0 commit comments

Comments
 (0)