moost 0.6.6 → 0.6.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,213 +0,0 @@
1
- # Pipes & Resolvers — moost
2
-
3
- > Pipe pipeline for argument resolution, `@Pipe`, `@Resolve`, validation/transformation stages, and the argument resolution lifecycle.
4
-
5
- ## Concepts
6
-
7
- Pipes process method arguments before the handler executes. They run in a defined priority pipeline:
8
-
9
- ```
10
- BEFORE_RESOLVE → RESOLVE → AFTER_RESOLVE → BEFORE_TRANSFORM → TRANSFORM → AFTER_TRANSFORM → BEFORE_VALIDATE → VALIDATE → AFTER_VALIDATE
11
- ```
12
-
13
- Each stage can modify the argument value. The most commonly used stages:
14
- - **RESOLVE** — Fetch the initial value (from request, context, DI, etc.)
15
- - **TRANSFORM** — Convert types, parse data
16
- - **VALIDATE** — Check constraints, throw on invalid data
17
-
18
- ### Pipe Scope
19
-
20
- Pipes can be registered at three levels:
21
- 1. **Global** — `app.pipe(myPipe)` — applies to all handlers
22
- 2. **Class** — `@Pipe(myPipe)` on controller class — applies to all methods
23
- 3. **Method/Parameter** — `@Pipe(myPipe)` on method or parameter — applies to that specific target
24
-
25
- Pipes are merged and sorted by priority across all levels.
26
-
27
- ## API Reference
28
-
29
- ### `@Resolve(fn, name?)`
30
-
31
- The most common pipe — resolves a parameter value from the event context. Used to create parameter decorators.
32
-
33
- ```ts
34
- import { Resolve } from 'moost'
35
-
36
- // Simple resolver
37
- function MyParam() {
38
- return Resolve(() => useMyContext().value, 'my-param')
39
- }
40
-
41
- // Usage
42
- @Get('test')
43
- handler(@MyParam() value: string) { }
44
- ```
45
-
46
- `@Resolve()` registers a pipe at the `RESOLVE` stage. The function runs inside the event context and can use any composables.
47
-
48
- ### `@Param(name?: string)`
49
-
50
- Built-in resolver for route parameters (from Wooks router).
51
-
52
- ```ts
53
- @Get('users/:id')
54
- getUser(@Param('id') id: string) { }
55
-
56
- @Get('users/:id/posts/:postId')
57
- getPost(@Params() params: { id: string; postId: string }) { }
58
- ```
59
-
60
- ### `@Pipe(pipe)`
61
-
62
- Registers a pipe at class, method, or parameter level.
63
-
64
- ```ts
65
- import { Pipe } from 'moost'
66
-
67
- // Class-level pipe
68
- @Pipe(validationPipe)
69
- @Controller()
70
- class MyController { }
71
-
72
- // Method-level pipe
73
- @Pipe(transformPipe)
74
- @Get('data')
75
- getData() { }
76
- ```
77
-
78
- ### Pipe Definition (TPipeData)
79
-
80
- ```ts
81
- interface TPipeData {
82
- priority: TPipePriority // Stage in the pipeline
83
- pipe: TPipeFunction // The pipe function
84
- }
85
-
86
- type TPipeFunction = (
87
- value: unknown, // Current parameter value
88
- metas: TPipeMetas, // Metadata about the parameter
89
- level: 'PARAM' | 'METHOD' // Whether this is a parameter or return value pipe
90
- ) => unknown | Promise<unknown>
91
- ```
92
-
93
- ### `TPipePriority` stages
94
-
95
- ```ts
96
- enum TPipePriority {
97
- BEFORE_RESOLVE = 0,
98
- RESOLVE = 10,
99
- AFTER_RESOLVE = 20,
100
- BEFORE_TRANSFORM = 30,
101
- TRANSFORM = 40,
102
- AFTER_TRANSFORM = 50,
103
- BEFORE_VALIDATE = 60,
104
- VALIDATE = 70,
105
- AFTER_VALIDATE = 80,
106
- }
107
- ```
108
-
109
- ### `TPipeMetas` (context passed to pipe functions)
110
-
111
- ```ts
112
- interface TPipeMetas {
113
- classMeta: TMoostMetadata // Controller class metadata
114
- methodMeta: TMoostMetadata // Handler method metadata
115
- paramMeta: TMoostParamsMetadata // Parameter metadata (type, inject, paramSource, etc.)
116
- type: TClassConstructor // Controller class constructor
117
- key: string | symbol // Method name
118
- index: number // Parameter index
119
- targetMeta: TMoostParamsMetadata
120
- instantiate: <T>(cls: TClassConstructor<T>) => Promise<T> | T // DI helper
121
- }
122
- ```
123
-
124
- ## Common Patterns
125
-
126
- ### Pattern: Custom Parameter Decorator with Resolve
127
-
128
- ```ts
129
- import { Resolve } from 'moost'
130
- import { useRequest } from '@wooksjs/event-http'
131
-
132
- function ClientIp(): ParameterDecorator {
133
- return Resolve(() => {
134
- const { raw } = useRequest()
135
- return raw.socket.remoteAddress
136
- }, 'client-ip')
137
- }
138
- ```
139
-
140
- ### Pattern: Validation Pipe
141
-
142
- ```ts
143
- import { Pipe, TPipePriority } from 'moost'
144
-
145
- const zodValidation: TPipeData = {
146
- priority: TPipePriority.VALIDATE,
147
- pipe(value, metas) {
148
- const schema = metas.paramMeta.zodSchema
149
- if (schema) {
150
- return schema.parse(value) // Throws ZodError on invalid
151
- }
152
- return value
153
- },
154
- }
155
-
156
- @Pipe(zodValidation)
157
- @Controller()
158
- class ValidatedController { }
159
- ```
160
-
161
- ### Pattern: Type Transformation Pipe
162
-
163
- ```ts
164
- const autoTransform: TPipeData = {
165
- priority: TPipePriority.TRANSFORM,
166
- pipe(value, metas) {
167
- const targetType = metas.paramMeta.type
168
- if (targetType === Number && typeof value === 'string') {
169
- return Number(value)
170
- }
171
- if (targetType === Boolean && typeof value === 'string') {
172
- return value === 'true'
173
- }
174
- return value
175
- },
176
- }
177
- ```
178
-
179
- ## Integration
180
-
181
- ### With Adapters
182
-
183
- Argument resolution is provided to adapters via `opts.resolveArgs` in `bindHandler()`. Pass it through to `defineMoostEventHandler()` — pipes run automatically during the "Arguments:resolve" phase of the handler lifecycle.
184
-
185
- ### With the Handler Lifecycle
186
-
187
- ```
188
- defineMoostEventHandler execution:
189
- 1. Scope + logger setup
190
- 2. Controller instance resolution
191
- 3. Interceptor before phase
192
- 4. ──► Argument resolution (pipes run here) ◄──
193
- 5. Handler method execution with resolved args
194
- 6. Interceptor after phase
195
- 7. Cleanup
196
- ```
197
-
198
- If argument resolution throws (e.g., validation failure), the handler is skipped and the error flows to interceptor error handlers.
199
-
200
- ## Best Practices
201
-
202
- - Use `@Resolve()` for parameter injection — it's the standard pattern across all adapters
203
- - Register validation pipes at class level to apply consistently
204
- - Keep pipe functions pure — avoid side effects during argument resolution
205
- - Use `TPipePriority.VALIDATE` for validation and `TPipePriority.TRANSFORM` for type coercion
206
- - The `instantiate` helper in `TPipeMetas` resolves classes via DI — use it for pipe dependencies
207
-
208
- ## Gotchas
209
-
210
- - Pipes run in strict priority order — if two pipes have the same priority, class-level runs before method-level, which runs before parameter-level
211
- - `@Resolve()` replaces the parameter value entirely — the initial value is `undefined` before the RESOLVE stage
212
- - Async pipes are supported — if any pipe returns a Promise, the entire argument array is awaited via `Promise.all()`
213
- - The `paramMeta.type` field comes from TypeScript's `emitDecoratorMetadata` — it's the design-time type, not a runtime validator