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.
@@ -1,266 +0,0 @@
1
- # Error Handling in YinzerFlow
2
-
3
- YinzerFlow provides a flexible and robust error handling system that allows you to gracefully handle errors in your application. This document explains the core concepts, features, and best practices for error handling.
4
-
5
- ## Core Concepts
6
-
7
- Error handling in YinzerFlow occurs at multiple levels:
8
-
9
- 1. **Route and Hook Level**: Explicit error handling in your route handlers and hooks
10
- 2. **Global Error Handler**: A centralized error handler for unhandled errors
11
- 3. **Framework Level**: Built-in error handling for framework-level errors
12
-
13
- ## Route and Hook Level Error Handling
14
-
15
- The most direct way to handle errors is within your route handlers and hooks using try/catch blocks:
16
-
17
- ```typescript
18
- app.get('/users/:id', async ({ request, response }) => {
19
- try {
20
- const user = await getUserById(request.params.id);
21
- if (!user) {
22
- response.setStatus(404);
23
- return { error: 'User not found' };
24
- }
25
- return user;
26
- } catch (error) {
27
- console.error('Failed to retrieve user:', error);
28
- response.setStatus(500);
29
- return { error: 'Failed to retrieve user' };
30
- }
31
- });
32
- ```
33
-
34
- This approach gives you fine-grained control over error handling for specific routes.
35
-
36
- ### Setting Status Codes
37
-
38
- When an error occurs, you should set an appropriate HTTP status code using the `response.setStatus()` method:
39
-
40
- ```typescript
41
- response.setStatus(400); // Bad Request
42
- response.setStatus(401); // Unauthorized
43
- response.setStatus(403); // Forbidden
44
- response.setStatus(404); // Not Found
45
- response.setStatus(500); // Internal Server Error
46
- ```
47
-
48
- ### Returning Error Responses
49
-
50
- After setting the status code, return an object with an error message:
51
-
52
- ```typescript
53
- return { error: 'Resource not found' };
54
- ```
55
-
56
- You can include additional information in the error response:
57
-
58
- ```typescript
59
- return {
60
- error: 'Validation failed',
61
- details: [
62
- { field: 'email', message: 'Invalid email format' },
63
- { field: 'password', message: 'Password too short' }
64
- ]
65
- };
66
- ```
67
-
68
- ## Global Error Handler
69
-
70
- YinzerFlow provides a global error handler that catches unhandled errors in your application. By default, it:
71
-
72
- 1. Logs the error to the console
73
- 2. Sets the response status to 500 (Internal Server Error)
74
- 3. Returns a JSON object with an error message
75
-
76
- ### Default Error Handler
77
-
78
- The default error handler is implemented as follows:
79
-
80
- ```typescript
81
- private readonly _defaultErrorHandler: TErrorFunction = ({ response }, error): unknown => {
82
- console.error('Unhandled error:', error);
83
- response.setStatus(HttpStatusCode.INTERNAL_SERVER_ERROR);
84
- return { error: 'Internal Server Error' };
85
- };
86
- ```
87
-
88
- ### Custom Error Handler
89
-
90
- You can provide your own error handler when initializing YinzerFlow:
91
-
92
- ```typescript
93
- const app = new YinzerFlow({
94
- port: 3000,
95
- errorHandler: ({ response }, error) => {
96
- console.error('Custom error handler:', error);
97
- response.setStatus(500);
98
-
99
- // In development, include the stack trace
100
- if (process.env.NODE_ENV === 'development') {
101
- return {
102
- error: error.message,
103
- stack: error.stack,
104
- timestamp: new Date().toISOString()
105
- };
106
- }
107
-
108
- // In production, return a generic message
109
- return {
110
- error: 'An unexpected error occurred',
111
- timestamp: new Date().toISOString()
112
- };
113
- }
114
- });
115
- ```
116
-
117
- ## Framework Level Error Handling
118
-
119
- YinzerFlow handles framework-level errors automatically, such as:
120
-
121
- - Invalid route paths
122
- - Malformed request bodies
123
- - Unsupported content types
124
-
125
- These errors are handled internally and appropriate responses are sent to the client.
126
-
127
- ## Best Practices
128
-
129
- ### Use Specific Status Codes
130
-
131
- Use the most specific HTTP status code for each error situation:
132
-
133
- ```typescript
134
- // Authentication error
135
- response.setStatus(401);
136
- return { error: 'Authentication required' };
137
-
138
- // Authorization error
139
- response.setStatus(403);
140
- return { error: 'Permission denied' };
141
-
142
- // Resource not found
143
- response.setStatus(404);
144
- return { error: 'User not found' };
145
-
146
- // Validation error
147
- response.setStatus(400);
148
- return { error: 'Invalid input' };
149
-
150
- // Server error
151
- response.setStatus(500);
152
- return { error: 'Internal server error' };
153
- ```
154
-
155
- ### Provide Helpful Error Messages
156
-
157
- Error messages should be clear and actionable:
158
-
159
- ```typescript
160
- // Good
161
- return { error: 'Email format is invalid' };
162
-
163
- // Better
164
- return {
165
- error: 'Validation failed',
166
- details: [
167
- { field: 'email', message: 'Email must be a valid email address' }
168
- ]
169
- };
170
-
171
- // Avoid
172
- return { error: 'Error occurred' };
173
- ```
174
-
175
- ### Log Errors Appropriately
176
-
177
- Log errors with sufficient context for debugging:
178
-
179
- ```typescript
180
- try {
181
- // Operation that might fail
182
- } catch (error) {
183
- console.error(`Failed to process order ${orderId}:`, error);
184
- response.setStatus(500);
185
- return { error: 'Failed to process order' };
186
- }
187
- ```
188
-
189
- ### Handle Async Errors
190
-
191
- Always use try/catch blocks with async operations:
192
-
193
- ```typescript
194
- app.get('/data', async ({ response }) => {
195
- try {
196
- const data = await fetchDataFromDatabase();
197
- return data;
198
- } catch (error) {
199
- console.error('Database error:', error);
200
- response.setStatus(500);
201
- return { error: 'Failed to fetch data' };
202
- }
203
- });
204
- ```
205
-
206
- ## Common Error Scenarios
207
-
208
- ### Authentication Errors
209
-
210
- ```typescript
211
- app.beforeAll(({ request, response }) => {
212
- const token = request.headers.authorization?.split(' ')[1];
213
- if (!token) {
214
- response.setStatus(401);
215
- return { error: 'Authentication required' };
216
- }
217
-
218
- try {
219
- const user = verifyToken(token);
220
- request.state.user = user;
221
- } catch (error) {
222
- response.setStatus(401);
223
- return { error: 'Invalid token' };
224
- }
225
- });
226
- ```
227
-
228
- ### Validation Errors
229
-
230
- ```typescript
231
- app.post('/users', ({ request, response }) => {
232
- const { name, email, password } = request.body;
233
- const errors = [];
234
-
235
- if (!name) errors.push({ field: 'name', message: 'Name is required' });
236
- if (!email) errors.push({ field: 'email', message: 'Email is required' });
237
- if (!password) errors.push({ field: 'password', message: 'Password is required' });
238
-
239
- if (errors.length > 0) {
240
- response.setStatus(400);
241
- return { error: 'Validation failed', details: errors };
242
- }
243
-
244
- // Process valid data...
245
- return { success: true };
246
- });
247
- ```
248
-
249
- ### Not Found Errors
250
-
251
- ```typescript
252
- app.get('/users/:id', ({ request, response }) => {
253
- const user = findUserById(request.params.id);
254
-
255
- if (!user) {
256
- response.setStatus(404);
257
- return { error: 'User not found' };
258
- }
259
-
260
- return user;
261
- });
262
- ```
263
-
264
- ## Conclusion
265
-
266
- Effective error handling is crucial for building robust and user-friendly applications. YinzerFlow provides a flexible error handling system that allows you to handle errors at multiple levels, from route-specific handling to global error management. By following the best practices outlined in this document, you can ensure that your application gracefully handles errors and provides helpful feedback to users.
@@ -1,276 +0,0 @@
1
- # File Parsers
2
-
3
- YinzerFlow provides robust support for parsing various file formats in HTTP requests and responses. This document explains the core concepts, features, and best practices for working with different file formats.
4
-
5
- ## Core Concepts
6
-
7
- In web applications, files can be uploaded in various formats, such as YAML, CSV, and more. YinzerFlow automatically detects and parses these formats based on the file extension and content type, making it easy to work with different types of files.
8
-
9
- ### Parser Configuration
10
-
11
- YinzerFlow allows you to configure how files are parsed through the `parserOptions` in your server configuration. You can control whether files should be automatically parsed:
12
-
13
- ```typescript
14
- const app = new YinzerFlow({
15
- port: 5000,
16
- parserOptions: {
17
- yaml: {
18
- raw: true,
19
- },
20
- json: {
21
- raw: true,
22
- }
23
- },
24
- // Other options...
25
- });
26
- ```
27
-
28
- #### Raw Mode
29
-
30
- Setting `raw: true` in the parser options disables automatic parsing of files. This is useful when:
31
-
32
- - You want to handle the parsing yourself
33
- - You're dealing with binary files that don't need parsing
34
- - You need to implement custom parsing logic
35
- - You want to improve performance by avoiding unnecessary parsing
36
-
37
- When raw mode is enabled, file contents will be provided as Buffer objects or strings, depending on the file type.
38
-
39
- ### Type Safety
40
-
41
- YinzerFlow provides TypeScript interfaces and type guards for each supported file format, allowing you to work with file contents in a type-safe manner.
42
-
43
- ## Supported File Formats
44
-
45
- YinzerFlow supports the following file formats out of the box:
46
-
47
- | Format | MIME Type | Type Interface | Type Guard | Description |
48
- |--------|-----------|----------------|------------|-------------|
49
- | YAML | `text/yaml`, `application/x-yaml` | `TYamlData` | `isYamlData` | YAML data with support for complex structures |
50
- | CSV (Coming Soon) | `text/csv` | `TCsvData` | `isCsvData` | CSV data with headers and rows |
51
- | JSON (Coming Soon) | `application/json` | `TJsonData` | `isJsonData` | JSON data as a generic object |
52
-
53
- ## Working with File Parsers
54
-
55
- There are two main approaches to working with parsed file contents in YinzerFlow:
56
-
57
- ### Approach 1: Type Casting (Simple but Less Safe)
58
-
59
- This approach uses TypeScript's type assertion to specify the expected file format:
60
-
61
- ```typescript
62
- import { TYamlData } from 'yinzerflow/types/parsers/fileParsers/Yaml';
63
-
64
- app.post('/upload', ({ request }) => {
65
- // Use type assertion - simple but no runtime validation
66
- const fileContent = request.file.content as TYamlData;
67
-
68
- // Access the parsed data directly
69
- const config = fileContent;
70
-
71
- // Process the data...
72
- return { success: true };
73
- });
74
- ```
75
-
76
- **When to use this approach:**
77
- - When you're certain about the file format (e.g., an internal API with controlled clients)
78
- - When performance is critical and you want to avoid runtime type checking
79
- - In simple applications where type safety is less important
80
-
81
- ### Approach 2: Type Guards (Safer and Recommended)
82
-
83
- This approach uses runtime type checking for better safety:
84
-
85
- ```typescript
86
- import { isYamlData } from 'yinzerflow/types/parsers/fileParsers/Yaml';
87
-
88
- app.post('/upload', ({ request, response }) => {
89
- // Runtime type checking
90
- if (!isYamlData(request.file.content)) {
91
- response.setStatus(400);
92
- return { error: 'Expected YAML file' };
93
- }
94
-
95
- // TypeScript knows request.file.content is TYamlData here
96
- const config = request.file.content;
97
-
98
- // Process the data...
99
- return { success: true };
100
- });
101
- ```
102
-
103
- **When to use this approach:**
104
- - When handling files from external clients
105
- - When an endpoint might receive different file formats
106
- - When you want to provide clear error messages for invalid files
107
- - In most production applications (recommended approach)
108
-
109
- ### Approach 3: Manual Parsing (When Raw Mode is Enabled)
110
-
111
- When you've configured YinzerFlow with `raw: true` in the parser options, you'll need to manually parse file contents:
112
-
113
- ```typescript
114
- // Your own custom parser
115
- import { parseYaml } from 'custom/parser';
116
-
117
- app.post('/upload', ({ request, response }) => {
118
- // Get the raw file content (as Buffer or string)
119
- const rawContent = request.file.content;
120
-
121
- try {
122
- // Manually parse the content
123
- const parsedContent = parseYaml(rawContent.toString());
124
-
125
- // Process the parsed content
126
- // ...
127
-
128
- return { success: true };
129
- } catch (error) {
130
- response.setStatus(400);
131
- return { error: 'Failed to parse YAML file' };
132
- }
133
- });
134
- ```
135
-
136
- **When to use this approach:**
137
- - When you've disabled automatic parsing with `raw: true`
138
- - When you need custom parsing logic
139
- - When you want to handle parsing errors in a specific way
140
- - When working with binary files or non-standard formats
141
-
142
- ## Detailed File Format Examples
143
-
144
- ### YAML Files
145
-
146
- YAML is commonly used for configuration files and structured data:
147
-
148
- ```typescript
149
- import { isYamlData } from 'yinzerflow/types/parsers/fileParsers/Yaml';
150
-
151
- app.post('/api/config', ({ request, response }) => {
152
- if (!isYamlData(request.file.content)) {
153
- response.setStatus(400);
154
- return { error: 'Expected YAML file' };
155
- }
156
-
157
- // Validate required fields
158
- const config = request.file.content;
159
- if (!config.version || !config.settings) {
160
- response.setStatus(400);
161
- return { error: 'Invalid YAML structure' };
162
- }
163
-
164
- // Process the configuration
165
- const processedConfig = {
166
- version: config.version,
167
- settings: config.settings,
168
- processedAt: new Date().toISOString()
169
- };
170
-
171
- // Save the configuration (example)
172
- saveConfig(processedConfig);
173
-
174
- response.setStatus(201);
175
- return processedConfig;
176
- });
177
- ```
178
-
179
- #### Type Definition
180
-
181
- ```typescript
182
- // The YAML data type
183
- type TYamlData = Array<TYamlData> | boolean | number | string | { [key: string]: TYamlData } | null;
184
-
185
- // Type guard for YAML data
186
- const isYamlData = (content: unknown): content is TYamlData => {
187
- // Implementation details...
188
- };
189
- ```
190
-
191
- ### CSV Files (Coming Soon)
192
-
193
- CSV files are commonly used for data import/export:
194
-
195
- ### JSON Files (Coming Soon)
196
-
197
- JSON files are commonly used for structured data:
198
-
199
- ## Best Practices
200
-
201
- ### 1. Always Validate File Contents
202
-
203
- Always validate the file format and structure, especially for public APIs:
204
-
205
- ```typescript
206
- app.post('/api/import', ({ request, response }) => {
207
- // Validate file format
208
- if (!isYamlData(request.file.content)) {
209
- response.setStatus(400);
210
- return { error: 'Expected YAML file' };
211
- }
212
-
213
- // Validate required structure
214
- const data = request.file.content;
215
- if (!data || typeof data !== 'object') {
216
- response.setStatus(400);
217
- return { error: 'Invalid YAML structure' };
218
- }
219
-
220
- // Validate specific fields
221
- const { name, version } = data;
222
- if (!name || !version) {
223
- response.setStatus(400);
224
- return { error: 'Missing required fields' };
225
- }
226
-
227
- // Process the data...
228
- });
229
- ```
230
-
231
- ### 2. Use Type Guards for Public APIs
232
-
233
- Always use type guards when handling files from external sources:
234
-
235
- ```typescript
236
- app.post('/api/upload', ({ request, response }) => {
237
- // Check file type
238
- if (!request.file.contentType.startsWith('text/yaml')) {
239
- response.setStatus(415);
240
- return { error: 'Unsupported file type' };
241
- }
242
-
243
- // Validate file content
244
- if (!isYamlData(request.file.content)) {
245
- response.setStatus(400);
246
- return { error: 'Invalid YAML format' };
247
- }
248
-
249
- // Process the file...
250
- });
251
- ```
252
-
253
- ### 3. Handle Large Files Efficiently
254
-
255
- When dealing with large files, consider using streams and processing data in chunks:
256
-
257
- ```typescript
258
- app.post('/api/import', async ({ request, response }) => {
259
- if (!isYamlData(request.file.content)) {
260
- response.setStatus(400);
261
- return { error: 'Expected YAML file' };
262
- }
263
-
264
- // Process large files in chunks
265
- const chunkSize = 1000;
266
- const data = request.file.content;
267
-
268
- for (let i = 0; i < data.length; i += chunkSize) {
269
- const chunk = data.slice(i, i + chunkSize);
270
- await processChunk(chunk);
271
- }
272
-
273
- return { success: true };
274
- });
275
- ```
276
-