yinzerflow 0.1.9 β 0.1.11
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/README.md +211 -290
- package/example/bun.lock +866 -0
- package/example/hooks/authentication.middleware.ts +77 -0
- package/example/index.ts +60 -0
- package/example/package.json +61 -0
- package/example/routes/authentication.routes.ts +243 -0
- package/example/routes/content-types.ts +176 -0
- package/example/tsconfig.json +32 -0
- package/index.d.ts +239 -108
- package/index.js +23 -1223
- package/index.js.map +25 -17
- package/package.json +16 -15
package/README.md
CHANGED
|
@@ -1,375 +1,296 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
7. [Starting the Server](#starting-the-server)
|
|
21
|
-
8. [Request Handling Flow](#request-handling-flow)
|
|
22
|
-
9. [Error Handling](#error-handling)
|
|
23
|
-
10. [Examples](#examples)
|
|
24
|
-
11. [Contribution](#contribution)
|
|
25
|
-
12. [Conclusion](#conclusion)
|
|
26
|
-
|
|
27
|
-
## Overview
|
|
28
|
-
|
|
29
|
-
YinzerFlow is a lightweight HTTP server framework built for Node.js, designed with TypeScript in mind. It leverages TypeScript's powerful type system to provide enhanced type safety and autocompletion, making it easier for developers to build robust web applications. With YinzerFlow, you can enjoy a flexible routing system, middleware support, and a straightforward interface to handle incoming requests and responsesβall while benefiting from TypeScript's clear typing and error-checking capabilities. This combination allows for a smoother development experience, reducing runtime errors and improving code maintainability.
|
|
30
|
-
|
|
31
|
-
```typescript
|
|
32
|
-
import { YinzerFlow } from 'yinzerflow';
|
|
33
|
-
|
|
34
|
-
export const app = new YinzerFlow({
|
|
35
|
-
port: 5000,
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
app.post('/example-route', (ctx) => {
|
|
39
|
-
const { body } = ctx.request;
|
|
40
|
-
return { message: 'Hello, world!' };
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
app.listen();
|
|
44
|
-
```
|
|
1
|
+
# YinzerFlow
|
|
2
|
+
|
|
3
|
+
<div align="center">
|
|
4
|
+
<h3>A lightweight, modular HTTP server framework for Node.js</h3>
|
|
5
|
+
<p>Built with TypeScript. Zero dependencies. Blazing fast.</p>
|
|
6
|
+
</div>
|
|
7
|
+
|
|
8
|
+
## Features
|
|
9
|
+
|
|
10
|
+
- π **Lightweight & Fast**: Built from scratch with performance in mind
|
|
11
|
+
- π§© **Modular Architecture**: Easily extensible with a clean component structure
|
|
12
|
+
- π **Type-Safe**: Full TypeScript support with comprehensive type definitions
|
|
13
|
+
- π§ͺ **Well-Tested**: Extensive test coverage for reliability
|
|
14
|
+
- π¦ **Zero Dependencies**: No bloated node_modules folder
|
|
15
|
+
- πͺ **Request Lifecycle Hooks**: Powerful hooks system for request processing (formerly middleware)
|
|
16
|
+
- π£οΈ **Route Groups**: Organize routes with prefixes and shared hooks
|
|
17
|
+
- π **Event-Based Architecture**: Subscribe to framework events for advanced customization
|
|
18
|
+
- π **Content Type Handling**: Built-in support for JSON, XML, multipart forms, and more
|
|
19
|
+
- π **Connection Management**: Robust connection tracking with statistics and graceful shutdown
|
|
45
20
|
|
|
46
21
|
## Installation
|
|
47
22
|
|
|
48
|
-
To get started with YinzerFlow, simply install it using your preferred package manager. YinzerFlow is available via npm, as well as other popular package managers such as Bun, Yarn, and pnpm. Follow the instructions below based on the package manager you are using:
|
|
49
|
-
|
|
50
|
-
### Using npm
|
|
51
|
-
|
|
52
|
-
If you are using npm, run the following command in your terminal:
|
|
53
|
-
|
|
54
23
|
```bash
|
|
55
24
|
npm install yinzerflow
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
For those who prefer Bun, you can add YinzerFlow to your project with the following command:
|
|
61
|
-
|
|
62
|
-
```bash
|
|
25
|
+
# or
|
|
26
|
+
yarn add yinzerflow
|
|
27
|
+
# or
|
|
63
28
|
bun add yinzerflow
|
|
64
29
|
```
|
|
65
30
|
|
|
66
|
-
|
|
31
|
+
## Quick Start
|
|
67
32
|
|
|
68
|
-
|
|
33
|
+
### JavaScript
|
|
69
34
|
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
```
|
|
35
|
+
```javascript
|
|
36
|
+
const { YinzerFlow } = require('yinzerflow');
|
|
73
37
|
|
|
74
|
-
|
|
38
|
+
const app = new YinzerFlow({ port: 3000 });
|
|
75
39
|
|
|
76
|
-
|
|
40
|
+
app.get('/hello', ({ request }) => {
|
|
41
|
+
return { message: 'Hello, World!' };
|
|
42
|
+
});
|
|
77
43
|
|
|
78
|
-
|
|
79
|
-
|
|
44
|
+
app.listen();
|
|
45
|
+
console.log('Server running on http://localhost:3000');
|
|
80
46
|
```
|
|
81
47
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
### Importing YinzerFlow
|
|
48
|
+
### TypeScript
|
|
85
49
|
|
|
86
50
|
```typescript
|
|
87
51
|
import { YinzerFlow } from 'yinzerflow';
|
|
88
|
-
```
|
|
89
52
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
```typescript
|
|
93
|
-
const app = new YinzerFlow({ port: 5000 });
|
|
94
|
-
```
|
|
53
|
+
const app = new YinzerFlow({ port: 3000 });
|
|
95
54
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
55
|
+
app.get('/hello', ({ request }) => {
|
|
56
|
+
return { message: 'Hello, World!' };
|
|
57
|
+
});
|
|
99
58
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
'/example',
|
|
103
|
-
({ request, response }) => {
|
|
104
|
-
return { message: 'Hello, world!' };
|
|
105
|
-
},
|
|
106
|
-
{
|
|
107
|
-
beforeHandler: ({ request, response }) => {
|
|
108
|
-
// Logic before the main handler
|
|
109
|
-
},
|
|
110
|
-
afterHandler: ({ request, response }) => {
|
|
111
|
-
// Logic after the main handler
|
|
112
|
-
},
|
|
113
|
-
},
|
|
114
|
-
);
|
|
59
|
+
app.listen();
|
|
60
|
+
console.log('Server running on http://localhost:3000');
|
|
115
61
|
```
|
|
116
62
|
|
|
117
|
-
|
|
118
|
-
The before handler is a good place to perform operations such as authentication, validation, or any pre-processing logic before the main handler is executed.
|
|
63
|
+
## Core Concepts
|
|
119
64
|
|
|
120
|
-
|
|
121
|
-
The after handler can be used for post-processing tasks like logging, modifying the response, or cleaning up resources after the main handler has completed.
|
|
122
|
-
|
|
123
|
-
### Additional Route Methods and Parameters
|
|
124
|
-
|
|
125
|
-
YinzerFlow supports various HTTP methods such as `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, and `OPTIONS`. You can use these methods to define routes for specific HTTP requests.
|
|
65
|
+
### Routing
|
|
126
66
|
|
|
127
67
|
```typescript
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
app.
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
app.
|
|
138
|
-
|
|
68
|
+
// Basic routes
|
|
69
|
+
app.get('/users', getAllUsersHandler);
|
|
70
|
+
app.post('/users', createUserHandler);
|
|
71
|
+
app.get('/users/:id', getUserByIdHandler);
|
|
72
|
+
app.put('/users/:id', updateUserHandler);
|
|
73
|
+
app.delete('/users/:id', deleteUserHandler);
|
|
74
|
+
|
|
75
|
+
// Route groups
|
|
76
|
+
app.group('/api/v1', [
|
|
77
|
+
app.get('/products', getProductsHandler),
|
|
78
|
+
app.post('/products', createProductHandler)
|
|
79
|
+
], {
|
|
80
|
+
beforeGroup: authenticationHook
|
|
139
81
|
});
|
|
140
82
|
```
|
|
141
83
|
|
|
142
|
-
|
|
84
|
+
### Request Lifecycle Hooks
|
|
143
85
|
|
|
144
86
|
```typescript
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
// Route handler logic
|
|
87
|
+
// Global hook for all requests
|
|
88
|
+
app.beforeAll(({ request }) => {
|
|
89
|
+
console.log(`Request received: ${request.method} ${request.path}`);
|
|
149
90
|
});
|
|
150
|
-
```
|
|
151
91
|
|
|
152
|
-
|
|
92
|
+
// Path-specific hooks
|
|
93
|
+
app.beforeAll(
|
|
94
|
+
({ request, response }) => {
|
|
95
|
+
const token = request.headers['authorization'];
|
|
96
|
+
if (!token) {
|
|
97
|
+
response.setStatus(401);
|
|
98
|
+
return { error: 'Authentication required' };
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
{ paths: ['/admin/*', '/profile/*'] }
|
|
102
|
+
);
|
|
153
103
|
|
|
154
|
-
|
|
155
|
-
app.
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
});
|
|
104
|
+
// Exclude specific paths
|
|
105
|
+
app.beforeAll(
|
|
106
|
+
authHook,
|
|
107
|
+
{ paths: 'allButExcluded', excluded: ['/login', '/register'] }
|
|
108
|
+
);
|
|
160
109
|
```
|
|
161
110
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
You can group routes using the `group` method. This is useful for applying middleware to multiple routes at once or for organizing related routes.
|
|
111
|
+
### Content Type Handling
|
|
165
112
|
|
|
166
113
|
```typescript
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
114
|
+
// Automatically parses JSON requests
|
|
115
|
+
app.post('/api/json', ({ request, response }) => {
|
|
116
|
+
if (!isJsonData(request.body)) {
|
|
117
|
+
response.setStatus(400);
|
|
118
|
+
return { error: 'Expected JSON data' };
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const { name, email } = request.body;
|
|
122
|
+
return { success: true, data: { name, email } };
|
|
174
123
|
});
|
|
175
|
-
```
|
|
176
124
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
});
|
|
191
|
-
},
|
|
192
|
-
);
|
|
125
|
+
// Handle file uploads
|
|
126
|
+
app.post('/api/upload', ({ request, response }) => {
|
|
127
|
+
if (!isMultipartFormData(request.body)) {
|
|
128
|
+
response.setStatus(400);
|
|
129
|
+
return { error: 'Expected multipart form data' };
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const { fields, files } = request.body;
|
|
133
|
+
return {
|
|
134
|
+
success: true,
|
|
135
|
+
message: `Received ${Object.keys(files).length} files`
|
|
136
|
+
};
|
|
137
|
+
});
|
|
193
138
|
```
|
|
194
139
|
|
|
195
|
-
|
|
140
|
+
### Connection Management
|
|
196
141
|
|
|
197
|
-
|
|
142
|
+
YinzerFlow provides a robust connection management system that allows you to track, monitor, and gracefully handle server connections:
|
|
198
143
|
|
|
199
144
|
```typescript
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
success: true,
|
|
203
|
-
message: 'Hello, world!',
|
|
204
|
-
};
|
|
205
|
-
});
|
|
206
|
-
```
|
|
145
|
+
import { YinzerFlow } from 'yinzerflow';
|
|
146
|
+
import { ConnectionEvent } from 'yinzerflow/constants/connection';
|
|
207
147
|
|
|
208
|
-
|
|
148
|
+
const app = new YinzerFlow({ port: 3000 });
|
|
209
149
|
|
|
210
|
-
|
|
211
|
-
app.
|
|
212
|
-
|
|
213
|
-
return 'Hello, world!';
|
|
150
|
+
// Subscribe to connection events
|
|
151
|
+
app.connectionManager.on(ConnectionEvent.CONNECTION_ADDED, (socket) => {
|
|
152
|
+
console.log('New connection established');
|
|
214
153
|
});
|
|
215
|
-
```
|
|
216
154
|
|
|
217
|
-
|
|
155
|
+
app.connectionManager.on(ConnectionEvent.CONNECTION_ERROR, (socket, error) => {
|
|
156
|
+
console.error('Connection error:', error);
|
|
157
|
+
});
|
|
218
158
|
|
|
219
|
-
|
|
220
|
-
app.get('/
|
|
159
|
+
// Get connection statistics
|
|
160
|
+
app.get('/admin/stats', ({ request }) => {
|
|
161
|
+
const stats = app.connectionManager.getStats();
|
|
221
162
|
return {
|
|
222
|
-
|
|
223
|
-
|
|
163
|
+
activeConnections: stats.activeConnections,
|
|
164
|
+
totalConnections: stats.totalConnections,
|
|
165
|
+
connectionErrors: stats.connectionErrors,
|
|
166
|
+
uptime: stats.uptime
|
|
224
167
|
};
|
|
225
168
|
});
|
|
226
|
-
```
|
|
227
|
-
|
|
228
|
-
In this example, the response status is set to `201`, and the response body is a string. The response headers are set to `text/plain` by default in this case.
|
|
229
|
-
|
|
230
|
-
### Changing or Adding Headers
|
|
231
|
-
|
|
232
|
-
You can also add or remove headers using the `response` object:
|
|
233
169
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
170
|
+
// Graceful shutdown example
|
|
171
|
+
process.on('SIGTERM', async () => {
|
|
172
|
+
console.log('SIGTERM received, shutting down gracefully');
|
|
173
|
+
|
|
174
|
+
// Give connections 5 seconds to finish before force closing
|
|
175
|
+
await app.connectionManager.closeAllConnections(5000);
|
|
176
|
+
await app.close();
|
|
177
|
+
|
|
178
|
+
console.log('Server shut down gracefully');
|
|
179
|
+
process.exit(0);
|
|
239
180
|
});
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
## Route Validation (Coming Soon)
|
|
243
|
-
|
|
244
|
-
You can validate routes using the `validate` method. This method takes a schema object and validates the request body, query parameters, or route parameters against it.
|
|
245
181
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
'/example-route',
|
|
249
|
-
({ request }) => {
|
|
250
|
-
const { body } = request;
|
|
251
|
-
const { name, age } = body;
|
|
252
|
-
// Route handler logic
|
|
253
|
-
},
|
|
254
|
-
{
|
|
255
|
-
validate: {
|
|
256
|
-
body: {
|
|
257
|
-
email: { type: 'email', required: true },
|
|
258
|
-
name: { type: 'string', required: true },
|
|
259
|
-
dateOfBirth: { type: 'date' },
|
|
260
|
-
age: { type: 'number', min: 18 },
|
|
261
|
-
},
|
|
262
|
-
},
|
|
263
|
-
},
|
|
264
|
-
);
|
|
182
|
+
app.listen();
|
|
183
|
+
console.log('Server running on http://localhost:3000');
|
|
265
184
|
```
|
|
266
185
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
YinzerFlow supports middleware that can be applied globally or to specific routes. Middleware can manipulate the request and also return a response. This is useful for tasks such as authentication and throttling.
|
|
270
|
-
|
|
271
|
-
### Global Middleware
|
|
272
|
-
|
|
273
|
-
To apply middleware before all routes:
|
|
274
|
-
|
|
275
|
-
```typescript
|
|
276
|
-
app.beforeAll(({ request, response }) => {
|
|
277
|
-
// middleware logic
|
|
278
|
-
});
|
|
279
|
-
```
|
|
186
|
+
#### ConnectionManager API
|
|
280
187
|
|
|
281
|
-
|
|
188
|
+
The `ConnectionManager` class provides the following methods and properties:
|
|
282
189
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
(
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
},
|
|
292
|
-
);
|
|
293
|
-
```
|
|
190
|
+
- **Methods**:
|
|
191
|
+
- `setServer(server: Server)`: Associates the connection manager with a server instance
|
|
192
|
+
- `addConnection(socket: Socket)`: Registers a new socket connection for tracking
|
|
193
|
+
- `removeConnection(socket: Socket)`: Removes a socket from tracking when it closes
|
|
194
|
+
- `getStats()`: Returns statistics about connections (`IConnectionStats`)
|
|
195
|
+
- `closeAllConnections(gracePeriod?: number)`: Gracefully closes all active connections
|
|
196
|
+
- `on(event: ConnectionEvent, listener: Function)`: Subscribes to connection events
|
|
197
|
+
- `off(event: ConnectionEvent, listener: Function)`: Unsubscribes from connection events
|
|
294
198
|
|
|
295
|
-
|
|
199
|
+
- **Events**:
|
|
200
|
+
- `CONNECTION_ADDED`: Fired when a new connection is established
|
|
201
|
+
- `CONNECTION_REMOVED`: Fired when a connection is closed
|
|
202
|
+
- `CONNECTION_ERROR`: Fired when a connection encounters an error
|
|
203
|
+
- `ALL_CONNECTIONS_CLOSED`: Fired when all connections have been closed
|
|
204
|
+
- `SERVER_LISTENING`: Fired when the server starts listening
|
|
205
|
+
- `SERVER_CLOSED`: Fired when the server is closed
|
|
296
206
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
{
|
|
303
|
-
paths: 'allButExcluded',
|
|
304
|
-
excluded: ['/login', '/register'],
|
|
305
|
-
},
|
|
306
|
-
);
|
|
307
|
-
```
|
|
207
|
+
- **Statistics**:
|
|
208
|
+
- `activeConnections`: Number of currently active connections
|
|
209
|
+
- `totalConnections`: Total number of connections since server start
|
|
210
|
+
- `connectionErrors`: Number of connection errors encountered
|
|
211
|
+
- `uptime`: Server uptime in milliseconds
|
|
308
212
|
|
|
309
|
-
|
|
213
|
+
#### Graceful Shutdown Pattern
|
|
310
214
|
|
|
311
|
-
|
|
215
|
+
For production applications, implementing a graceful shutdown pattern is recommended:
|
|
312
216
|
|
|
313
217
|
```typescript
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
});
|
|
218
|
+
// Graceful shutdown handler
|
|
219
|
+
const gracefulShutdown = async (signal: string) => {
|
|
220
|
+
console.log(`${signal} received, starting graceful shutdown`);
|
|
221
|
+
|
|
222
|
+
// Step 1: Stop accepting new connections (optional)
|
|
223
|
+
server.close();
|
|
224
|
+
|
|
225
|
+
// Step 2: Allow existing connections to finish (with timeout)
|
|
226
|
+
console.log('Closing remaining connections...');
|
|
227
|
+
await app.connectionManager.closeAllConnections(10000); // 10 second grace period
|
|
228
|
+
|
|
229
|
+
// Step 3: Close the server completely
|
|
230
|
+
console.log('Shutting down server...');
|
|
231
|
+
await app.close();
|
|
232
|
+
|
|
233
|
+
console.log('Shutdown complete');
|
|
234
|
+
process.exit(0);
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
// Register shutdown handlers
|
|
238
|
+
process.on('SIGTERM', () => gracefulShutdown('SIGTERM'));
|
|
239
|
+
process.on('SIGINT', () => gracefulShutdown('SIGINT'));
|
|
317
240
|
```
|
|
318
241
|
|
|
319
|
-
|
|
242
|
+
This pattern ensures that your server can handle restarts and deployments without dropping active connections.
|
|
320
243
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
```typescript
|
|
324
|
-
app.listen();
|
|
325
|
-
```
|
|
244
|
+
## Examples
|
|
326
245
|
|
|
327
|
-
|
|
246
|
+
Check out the [examples](/example) directory for more detailed usage examples:
|
|
328
247
|
|
|
329
|
-
|
|
248
|
+
- [JavaScript Example](/example/javascript) - Basic server implementation in JavaScript
|
|
249
|
+
- [TypeScript Example](/example/typescript) - Type-safe server implementation in TypeScript
|
|
330
250
|
|
|
331
|
-
|
|
332
|
-
2. Route validation
|
|
333
|
-
3. Global middleware
|
|
334
|
-
4. Before group middleware
|
|
335
|
-
5. Before route middleware
|
|
336
|
-
6. Route handler
|
|
337
|
-
7. After route middleware
|
|
338
|
-
8. Response sent
|
|
251
|
+
## Documentation
|
|
339
252
|
|
|
340
|
-
|
|
253
|
+
For detailed documentation, see the [docs](/docs) directory:
|
|
341
254
|
|
|
342
|
-
|
|
255
|
+
- [Getting Started](/docs/README.md) - Overview and quick start guide
|
|
256
|
+
- [Routing System](/docs/routing.md) - Comprehensive guide to the routing system
|
|
257
|
+
- [Request Lifecycle Hooks](/docs/hooks.md) - In-depth documentation of the hooks system
|
|
258
|
+
- [Content Type Handling](/docs/content-types.md) - Working with different content types
|
|
259
|
+
- [Error Handling](/docs/error-handling.md) - Guide to handling errors at different levels
|
|
260
|
+
- [Testing Guide](/TESTING.md) - Comprehensive guide to testing the framework
|
|
343
261
|
|
|
344
|
-
|
|
345
|
-
2. **Simplified Debugging**: Built-in logging capabilities make identifying and fixing errors easier.
|
|
346
|
-
3. **Improved Reliability**: Effectively catching and managing errors prevents unexpected crashes, ensuring smoother operation.
|
|
262
|
+
## Project Structure
|
|
347
263
|
|
|
348
|
-
|
|
264
|
+
```
|
|
265
|
+
yinzerflow/
|
|
266
|
+
βββ app/ # Source code
|
|
267
|
+
βββ docs/ # Documentation
|
|
268
|
+
βββ example/ # Usage examples
|
|
269
|
+
β βββ javascript/ # JavaScript example
|
|
270
|
+
β βββ typescript/ # TypeScript example
|
|
271
|
+
βββ package.json # Package configuration
|
|
272
|
+
βββ TESTING.md # Testing documentation
|
|
273
|
+
βββ README.md # This file
|
|
274
|
+
```
|
|
349
275
|
|
|
350
|
-
|
|
276
|
+
## Contributing
|
|
351
277
|
|
|
352
|
-
|
|
278
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
353
279
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
response.setStatus(<THttpStatusCode>HttpStatusCode.TOO_MANY_REQUESTS);
|
|
360
|
-
return { success: false, message: 'Internal server error' };
|
|
361
|
-
},
|
|
362
|
-
});
|
|
363
|
-
```
|
|
280
|
+
1. Fork the repository
|
|
281
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
282
|
+
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
|
283
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
284
|
+
5. Open a Pull Request
|
|
364
285
|
|
|
365
|
-
##
|
|
286
|
+
## License
|
|
366
287
|
|
|
367
|
-
|
|
288
|
+
This project is licensed under the MIT License - see the LICENSE file for details.
|
|
368
289
|
|
|
369
|
-
##
|
|
290
|
+
## Why "YinzerFlow"?
|
|
370
291
|
|
|
371
|
-
|
|
292
|
+
"Yinzer" is a term for a native or inhabitant of the city of Pittsburgh, Pennsylvania. The name combines the local Pittsburgh dialect with "flow" to represent the smooth flow of HTTP requests through the framework.
|
|
372
293
|
|
|
373
|
-
|
|
294
|
+
---
|
|
374
295
|
|
|
375
|
-
|
|
296
|
+
Built with β€οΈ in Pittsburgh
|