yinzerflow 0.1.18 → 0.2.0

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.
package/docs/hooks.md DELETED
@@ -1,289 +0,0 @@
1
- # Request Lifecycle Hooks
2
-
3
- YinzerFlow provides a powerful hooks system (traditionally called middleware in other frameworks) that allows you to intercept and modify requests and responses at various points in the request lifecycle. This document explains the core components, features, and best practices for using the hooks system.
4
-
5
- ## Core Concepts
6
-
7
- In YinzerFlow, hooks are functions that can be executed at different phases of the request lifecycle:
8
-
9
- 1. **Before All**: Executed before any route-specific hooks
10
- 2. **Before Group**: Executed for routes in a specific group
11
- 3. **Before Handler**: Executed before a specific route handler
12
- 4. **After Handler**: Executed after a specific route handler
13
-
14
- Each hook can:
15
- - Modify the request or response
16
- - End the request early by returning a response
17
- - Pass control to the next hook by returning nothing
18
-
19
- ## Core Components
20
-
21
- The hooks system consists of one main component:
22
-
23
- ### HooksManager (MiddlewareManager)
24
-
25
- The `MiddlewareManager` class (which we recommend thinking of as a "HooksManager") is responsible for registering and executing hooks at the appropriate points in the request lifecycle.
26
-
27
- ```typescript
28
- import { MiddlewareManager } from 'yinzerflow';
29
-
30
- const hooksManager = new MiddlewareManager();
31
- ```
32
-
33
- #### Key Features
34
-
35
- - **Path matching**: Hooks can be applied to specific paths or path patterns
36
- - **Path exclusion**: Hooks can be excluded from specific paths
37
- - **Event-based architecture**: Emits events when hooks are added or executed
38
- - **Error handling**: Comprehensive error handling with proper logging and propagation
39
-
40
- ## Registering Hooks
41
-
42
- ### Global Hooks
43
-
44
- Global hooks are executed for all requests:
45
-
46
- ```typescript
47
- app.beforeAll((ctx) => {
48
- console.log(`Request received: ${ctx.request.method} ${ctx.request.path}`);
49
- });
50
- ```
51
-
52
- ### Path-Specific Hooks
53
-
54
- Hooks can be applied to specific paths:
55
-
56
- ```typescript
57
- app.beforeAll(
58
- (ctx) => {
59
- // Verify API key
60
- const apiKey = ctx.request.headers['x-api-key'];
61
- if (!apiKey || !isValidApiKey(apiKey)) {
62
- ctx.response.setStatus(401);
63
- return { error: 'Invalid API key' };
64
- }
65
- },
66
- { paths: ['/api/users', '/api/products'] }
67
- );
68
- ```
69
-
70
- ### Path Pattern Hooks
71
-
72
- Hooks can be applied to path patterns using wildcards:
73
-
74
- ```typescript
75
- app.beforeAll(
76
- (ctx) => {
77
- // Verify API key for all API routes
78
- const apiKey = ctx.request.headers['x-api-key'];
79
- if (!apiKey || !isValidApiKey(apiKey)) {
80
- ctx.response.setStatus(401);
81
- return { error: 'Invalid API key' };
82
- }
83
- },
84
- { paths: ['/api/*'] }
85
- );
86
- ```
87
-
88
- ### Excluded Paths
89
-
90
- Hooks can be excluded from specific paths:
91
-
92
- ```typescript
93
- app.beforeAll(
94
- (ctx) => {
95
- // Log all requests except health checks
96
- console.log(`Request received: ${ctx.request.method} ${ctx.request.path}`);
97
- },
98
- { paths: 'allButExcluded', excluded: ['/health'] }
99
- );
100
- ```
101
-
102
- ## Route-Specific Hooks
103
-
104
- In addition to global hooks, you can also specify hooks for specific routes:
105
-
106
- ### Before Handler
107
-
108
- ```typescript
109
- app.get(
110
- '/users/:id',
111
- handleGetUser,
112
- {
113
- beforeHandler: (ctx) => {
114
- // Validate user ID
115
- const userId = ctx.request.params.id;
116
- if (!isValidUserId(userId)) {
117
- ctx.response.setStatus(400);
118
- return { error: 'Invalid user ID' };
119
- }
120
- }
121
- }
122
- );
123
- ```
124
-
125
- ### After Handler
126
-
127
- ```typescript
128
- app.get(
129
- '/users/:id',
130
- handleGetUser,
131
- {
132
- afterHandler: (ctx) => {
133
- // Log successful user retrieval
134
- console.log(`User retrieved: ${ctx.request.params.id}`);
135
- }
136
- }
137
- );
138
- ```
139
-
140
- ## Hook Execution Order
141
-
142
- Hooks are executed in the following order:
143
-
144
- 1. Global "Before All" hooks (registered with `app.beforeAll()`)
145
- 2. Group "Before Group" hooks (specified when registering route groups)
146
- 3. Route-specific "Before Handler" hooks (specified when registering routes)
147
- 4. Route handler
148
- 5. Route-specific "After Handler" hooks (specified when registering routes)
149
-
150
- If any hook returns a response, the request is short-circuited and that response is sent to the client.
151
-
152
- ## Response Handling and Error Management
153
-
154
- YinzerFlow provides flexible ways to handle responses and errors in your hooks and route handlers.
155
-
156
- ### Setting Status Codes
157
-
158
- You can set status codes directly using the response object in the context:
159
-
160
- ```typescript
161
- app.beforeAll((ctx) => {
162
- // Check if user is authenticated
163
- if (!isAuthenticated(ctx)) {
164
- ctx.response.setStatus(401); // Sets status to 401 Unauthorized
165
- return { message: 'Authentication required' };
166
- }
167
- });
168
- ```
169
-
170
- ### Returning Responses
171
-
172
- Hooks and route handlers can return responses in several ways:
173
-
174
- 1. **Return an object**: The object will be automatically converted to JSON
175
- ```typescript
176
- return { success: true, data: { id: 1, name: 'John' } };
177
- ```
178
-
179
- 2. **Return a primitive**: The value will be converted to a string
180
- ```typescript
181
- return 'Hello World';
182
- ```
183
-
184
- ### Error Handling
185
-
186
- For explicit error handling in hooks, use try/catch blocks:
187
-
188
- ```typescript
189
- app.beforeAll(async (ctx) => {
190
- try {
191
- const result = await someAsyncOperation();
192
- ctx.state.result = result;
193
- } catch (error) {
194
- console.error('Operation failed:', error);
195
- ctx.response.setStatus(500);
196
- return { error: 'Operation failed', message: error.message };
197
- }
198
- });
199
- ```
200
-
201
- YinzerFlow has a built-in error handling system that catches unhandled errors. For more details on error handling, refer to the [Error Handling](./error-handling.md) documentation.
202
-
203
- ## Advanced Features
204
-
205
- ### Hook Events
206
-
207
- The hooks system emits events when hooks are added or executed. You can listen for these events to perform additional actions:
208
-
209
- ```typescript
210
- import { HookManagerEvent } from 'yinzerflow/constants/hooks';
211
-
212
- app.hooks.on(HookManagerEvent.HOOK_EXECUTED, (info) => {
213
- console.log(`Hook executed: ${info.phase} for ${info.path}`);
214
- });
215
- ```
216
-
217
- ### Hook Removal
218
-
219
- You can remove all hooks using the `clear` method:
220
-
221
- ```typescript
222
- app.hooks.clear();
223
- ```
224
-
225
- ## Best Practices
226
-
227
- ### Keep Hooks Focused
228
-
229
- Each hook should have a single responsibility. For example, separate authentication, logging, and validation into different hooks.
230
-
231
- ```typescript
232
- // Good
233
- app.beforeAll(logRequest);
234
- app.beforeAll(authenticate);
235
- app.beforeAll(validateInput);
236
-
237
- // Avoid
238
- app.beforeAll((ctx) => {
239
- // Log request
240
- // Authenticate user
241
- // Validate input
242
- });
243
- ```
244
-
245
- ### Use Path Patterns Wisely
246
-
247
- Use path patterns to apply hooks to groups of routes:
248
-
249
- ```typescript
250
- // Apply authentication to all admin routes
251
- app.beforeAll(authenticate, { paths: ['/admin/*'] });
252
-
253
- // Apply rate limiting to all API routes
254
- app.beforeAll(rateLimiter, { paths: ['/api/*'] });
255
- ```
256
-
257
- ### Error Handling
258
-
259
- Implement proper error handling in your hooks:
260
-
261
- ```typescript
262
- app.beforeAll(async (ctx) => {
263
- try {
264
- // Perform some async operation
265
- await someAsyncOperation();
266
- } catch (error) {
267
- console.error('Hook error:', error);
268
- ctx.response.setStatus(500);
269
- return { error: 'An error occurred' };
270
- }
271
- });
272
- ```
273
-
274
- ### Performance Considerations
275
-
276
- - **Keep hooks lightweight**: Hooks are executed on every matching request, so keep them efficient
277
- - **Use path matching**: Apply hooks only to the paths that need them
278
- - **Cache expensive operations**: If a hook performs expensive operations, consider caching the results
279
-
280
- ## Common Use Cases
281
-
282
- - **Authentication**
283
- - **Logging**
284
- - **Rate Limiting**
285
-
286
- ## Conclusion
287
- # End of Selection
288
-
289
- The hooks system in YinzerFlow provides a flexible and powerful way to modify requests and responses at various points in the request lifecycle. By using hooks effectively, you can implement cross-cutting concerns like authentication, logging, and rate limiting in a clean and maintainable way.
package/docs/routing.md DELETED
@@ -1,204 +0,0 @@
1
- # Routing System
2
-
3
- The YinzerFlow routing system provides a flexible and efficient way to define and manage routes in your application. This document explains the core components, features, and best practices for using the routing system.
4
-
5
- ## Core Components
6
-
7
- The routing system consists of two main components:
8
-
9
- 1. **RouteRegistry**: Responsible for storing and managing routes
10
- 2. **RouteFinder**: Responsible for finding and matching routes based on requests
11
-
12
- ### RouteRegistry
13
-
14
- The `RouteRegistry` class manages the registration and storage of routes. It provides methods for adding, removing, and retrieving routes.
15
-
16
- ```typescript
17
- import { RouteRegistry } from 'yinzerflow';
18
-
19
- const registry = new RouteRegistry();
20
- ```
21
-
22
- #### Key Features
23
-
24
- - **Event-based architecture**: Emits events when routes are added, removed, or changed
25
- - **Path validation**: Validates route paths to ensure they follow proper formatting rules
26
- - **Route grouping**: Supports grouping routes with common prefixes
27
- - **Route removal**: Allows removing individual routes or clearing all routes
28
-
29
- ### RouteFinder
30
-
31
- The `RouteFinder` class handles route lookup and matching. It uses efficient algorithms to find the appropriate route for a given request.
32
-
33
- ```typescript
34
- import { RouteFinder } from 'yinzerflow';
35
-
36
- const finder = new RouteFinder(registry);
37
- ```
38
-
39
- #### Key Features
40
-
41
- - **Pattern route caching**: Caches pattern routes for faster lookup
42
- - **Path normalization**: Handles trailing slashes and path normalization
43
- - **Parameter extraction**: Extracts parameters from request paths
44
-
45
- ## Route Definition
46
-
47
- Routes in YinzerFlow are defined with a path, HTTP method, and handler function. You can also specify optional middleware functions to be executed before or after the main handler.
48
-
49
- ```typescript
50
- app.get('/users', handleGetUsers);
51
- app.post('/users', handleCreateUser);
52
- app.put('/users/:id', handleUpdateUser);
53
- app.delete('/users/:id', handleDeleteUser);
54
- app.patch('/users/:id', handlePartialUpdateUser);
55
- ```
56
-
57
- ### Route Parameters
58
-
59
- You can define route parameters by prefixing a path segment with a colon (`:`). These parameters will be extracted and made available in the request context.
60
-
61
- ```typescript
62
- app.get('/users/:id', (ctx) => {
63
- const userId = ctx.request.params.id;
64
- // ...
65
- });
66
- ```
67
-
68
- ### Route Groups
69
-
70
- You can group routes with a common prefix using the `group` method:
71
-
72
- ```typescript
73
- const apiRoutes = [
74
- app.get('/users', handleGetUsers),
75
- app.post('/users', handleCreateUser),
76
- ];
77
-
78
- app.group('/api', apiRoutes);
79
- ```
80
-
81
- This will register the routes as `/api/users` for GET and POST methods.
82
-
83
- ## Advanced Features
84
-
85
- ### Route Events
86
-
87
- The routing system emits events when routes are added, removed, or changed. You can listen for these events to perform additional actions:
88
-
89
- ```typescript
90
- import { RouteRegistryEvent } from 'yinzerflow/constants/route';
91
-
92
- app.routeRegistry.on(RouteRegistryEvent.ROUTE_ADDED, (route) => {
93
- console.log(`New route added: ${route.method} ${route.path}`);
94
- });
95
- ```
96
-
97
- ### Route Validation
98
-
99
- The routing system validates route paths to ensure they follow proper formatting rules:
100
-
101
- - Paths must start with a slash
102
- - Paths cannot have consecutive slashes
103
- - Path parameters must have names
104
-
105
- If a path doesn't meet these requirements, an error will be thrown:
106
-
107
- ```typescript
108
- try {
109
- app.get('invalid-path', handler); // Will throw an error
110
- } catch (error) {
111
- console.error(error.message); // "Route path must start with a slash: invalid-path"
112
- }
113
- ```
114
-
115
- ### Route Removal
116
-
117
- You can remove routes using the `removeRoute` method:
118
-
119
- ```typescript
120
- app.routeRegistry.removeRoute('GET', '/users/:id');
121
- ```
122
-
123
- Or clear all routes:
124
-
125
- ```typescript
126
- app.routeRegistry.clearRoutes();
127
- ```
128
-
129
- ## Best Practices
130
-
131
- ### Organizing Routes
132
-
133
- For larger applications, it's recommended to organize routes by feature or resource:
134
-
135
- ```typescript
136
- // users.routes.ts
137
- export function registerUserRoutes(app) {
138
- app.get('/users', handleGetUsers);
139
- app.post('/users', handleCreateUser);
140
- // ...
141
- }
142
-
143
- // main.ts
144
- registerUserRoutes(app);
145
- ```
146
-
147
- ### Route Naming Conventions
148
-
149
- Follow these conventions for route paths:
150
-
151
- - Use lowercase for paths
152
- - Use hyphens for multi-word resources (e.g., `/user-profiles`)
153
- - Use plural nouns for resource collections (e.g., `/users` instead of `/user`)
154
- - Use singular nouns with parameters for specific resources (e.g., `/users/:id`)
155
-
156
- ### Error Handling
157
-
158
- Implement proper error handling in your route handlers:
159
-
160
- ```typescript
161
- app.get('/users/:id', async (ctx) => {
162
- try {
163
- const user = await getUserById(ctx.request.params.id);
164
- if (!user) {
165
- ctx.response.setStatus(404);
166
- return { error: 'User not found' };
167
- }
168
- return user;
169
- } catch (error) {
170
- console.error('Failed to retrieve user:', error);
171
- ctx.response.setStatus(500);
172
- return { error: 'Failed to retrieve user' };
173
- }
174
- });
175
- ```
176
-
177
- For more details on error handling, refer to the [Error Handling](./error-handling.md) documentation.
178
-
179
- ## Performance Considerations
180
-
181
- The routing system is designed to be efficient, but here are some tips to maximize performance:
182
-
183
- - **Avoid excessive route parameters**: Each parameter adds overhead to route matching
184
- - **Use route groups**: Grouping routes with common prefixes improves organization and can slightly improve performance
185
- - **Order routes by specificity**: Place more specific routes before more general ones
186
-
187
- ## Debugging Routes
188
-
189
- You can get information about registered routes using these methods:
190
-
191
- ```typescript
192
- // Get all routes
193
- const routes = app.routeRegistry.getRoutes();
194
-
195
- // Check if a route exists
196
- const hasRoute = app.routeRegistry.hasRoute('GET', '/users/:id');
197
-
198
- // Get the number of registered routes
199
- const routeCount = app.routeRegistry.routeCount;
200
- ```
201
-
202
- ## Conclusion
203
-
204
- The YinzerFlow routing system provides a flexible and efficient way to define and manage routes in your application. By understanding its core components and features, you can build well-organized and performant web applications.