@flightdev/http 0.0.4
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/LICENSE +21 -0
- package/README.md +580 -0
- package/dist/adapters/bun.d.ts +39 -0
- package/dist/adapters/bun.js +29 -0
- package/dist/adapters/bun.js.map +1 -0
- package/dist/adapters/deno.d.ts +36 -0
- package/dist/adapters/deno.js +28 -0
- package/dist/adapters/deno.js.map +1 -0
- package/dist/adapters/node.d.ts +34 -0
- package/dist/adapters/node.js +89 -0
- package/dist/adapters/node.js.map +1 -0
- package/dist/index.d.ts +116 -0
- package/dist/index.js +377 -0
- package/dist/index.js.map +1 -0
- package/dist/types-CtqOEBIR.d.ts +88 -0
- package/package.json +57 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024-2026 Flight Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,580 @@
|
|
|
1
|
+
# @flight-framework/http
|
|
2
|
+
|
|
3
|
+
HTTP server for Flight Framework. Built on Web Standard APIs with radix-tree routing for maximum performance. Runs on Node.js, Bun, and Deno.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Features](#features)
|
|
8
|
+
- [Installation](#installation)
|
|
9
|
+
- [Quick Start](#quick-start)
|
|
10
|
+
- [Routing](#routing)
|
|
11
|
+
- [Route Parameters](#route-parameters)
|
|
12
|
+
- [Middleware](#middleware)
|
|
13
|
+
- [Context API](#context-api)
|
|
14
|
+
- [Request Handling](#request-handling)
|
|
15
|
+
- [Response Helpers](#response-helpers)
|
|
16
|
+
- [Error Handling](#error-handling)
|
|
17
|
+
- [Sub-Routers](#sub-routers)
|
|
18
|
+
- [Runtime Adapters](#runtime-adapters)
|
|
19
|
+
- [Static Files](#static-files)
|
|
20
|
+
- [CORS](#cors)
|
|
21
|
+
- [API Reference](#api-reference)
|
|
22
|
+
- [License](#license)
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Features
|
|
27
|
+
|
|
28
|
+
- Radix-tree routing for fast path matching
|
|
29
|
+
- Native Request/Response APIs (Web Standard)
|
|
30
|
+
- Multi-runtime support: Node.js, Bun, Deno
|
|
31
|
+
- Middleware with async/await
|
|
32
|
+
- Type-safe route parameters
|
|
33
|
+
- Built-in helpers for JSON, HTML, redirects
|
|
34
|
+
- Zero external runtime dependencies
|
|
35
|
+
- Full TypeScript support
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Installation
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npm install @flight-framework/http
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Quick Start
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
import { createServer } from '@flight-framework/http';
|
|
51
|
+
import { serve } from '@flight-framework/http/node';
|
|
52
|
+
|
|
53
|
+
const app = createServer();
|
|
54
|
+
|
|
55
|
+
app.get('/', (c) => c.json({ message: 'Hello Flight!' }));
|
|
56
|
+
|
|
57
|
+
app.get('/users/:id', (c) => {
|
|
58
|
+
return c.json({ userId: c.params.id });
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
app.post('/users', async (c) => {
|
|
62
|
+
const body = await c.req.json();
|
|
63
|
+
return c.json({ created: true, user: body }, 201);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
serve(app, { port: 3000 });
|
|
67
|
+
console.log('Server running at http://localhost:3000');
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## Routing
|
|
73
|
+
|
|
74
|
+
Register routes using HTTP method helpers:
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
app.get('/path', handler); // GET
|
|
78
|
+
app.post('/path', handler); // POST
|
|
79
|
+
app.put('/path', handler); // PUT
|
|
80
|
+
app.patch('/path', handler); // PATCH
|
|
81
|
+
app.delete('/path', handler); // DELETE
|
|
82
|
+
app.options('/path', handler); // OPTIONS
|
|
83
|
+
app.head('/path', handler); // HEAD
|
|
84
|
+
|
|
85
|
+
// All methods
|
|
86
|
+
app.all('/path', handler);
|
|
87
|
+
|
|
88
|
+
// Multiple methods
|
|
89
|
+
app.on(['GET', 'POST'], '/path', handler);
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Route Patterns
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
// Static path
|
|
96
|
+
app.get('/about', handler);
|
|
97
|
+
|
|
98
|
+
// Single parameter
|
|
99
|
+
app.get('/users/:id', handler);
|
|
100
|
+
|
|
101
|
+
// Multiple parameters
|
|
102
|
+
app.get('/posts/:year/:month/:slug', handler);
|
|
103
|
+
|
|
104
|
+
// Optional parameter
|
|
105
|
+
app.get('/files/:path?', handler);
|
|
106
|
+
|
|
107
|
+
// Wildcard (catch-all)
|
|
108
|
+
app.get('/assets/*', handler);
|
|
109
|
+
|
|
110
|
+
// Named wildcard
|
|
111
|
+
app.get('/docs/:path*', handler);
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Route Parameters
|
|
117
|
+
|
|
118
|
+
Access route parameters from the context:
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
// Route: /users/:id/posts/:postId
|
|
122
|
+
app.get('/users/:id/posts/:postId', (c) => {
|
|
123
|
+
const { id, postId } = c.params;
|
|
124
|
+
return c.json({ userId: id, postId });
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
// Wildcard parameters
|
|
128
|
+
// Route: /files/*
|
|
129
|
+
// Request: /files/images/photo.jpg
|
|
130
|
+
app.get('/files/*', (c) => {
|
|
131
|
+
const path = c.params['*']; // "images/photo.jpg"
|
|
132
|
+
return c.text(`File: ${path}`);
|
|
133
|
+
});
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Type-Safe Parameters
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
import type { Context } from '@flight-framework/http';
|
|
140
|
+
|
|
141
|
+
interface UserParams {
|
|
142
|
+
id: string;
|
|
143
|
+
postId: string;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
app.get('/users/:id/posts/:postId', (c: Context<UserParams>) => {
|
|
147
|
+
c.params.id; // string (typed)
|
|
148
|
+
c.params.postId; // string (typed)
|
|
149
|
+
});
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## Middleware
|
|
155
|
+
|
|
156
|
+
Middleware functions run before route handlers:
|
|
157
|
+
|
|
158
|
+
```typescript
|
|
159
|
+
// Global middleware (runs on all routes)
|
|
160
|
+
app.use(async (c, next) => {
|
|
161
|
+
const start = performance.now();
|
|
162
|
+
const response = await next();
|
|
163
|
+
const duration = performance.now() - start;
|
|
164
|
+
console.log(`${c.req.method} ${c.req.url} - ${duration.toFixed(2)}ms`);
|
|
165
|
+
return response;
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
// Path-specific middleware
|
|
169
|
+
app.use('/api/*', async (c, next) => {
|
|
170
|
+
// Only runs on /api/* routes
|
|
171
|
+
return next();
|
|
172
|
+
});
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Authentication Middleware
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
const authMiddleware = async (c, next) => {
|
|
179
|
+
const token = c.header('Authorization')?.replace('Bearer ', '');
|
|
180
|
+
|
|
181
|
+
if (!token) {
|
|
182
|
+
return c.json({ error: 'Unauthorized' }, 401);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const user = await verifyToken(token);
|
|
186
|
+
if (!user) {
|
|
187
|
+
return c.json({ error: 'Invalid token' }, 401);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Store user in context for later use
|
|
191
|
+
c.set('user', user);
|
|
192
|
+
return next();
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
// Apply to specific routes
|
|
196
|
+
app.use('/api/*', authMiddleware);
|
|
197
|
+
|
|
198
|
+
// Access in route handler
|
|
199
|
+
app.get('/api/profile', (c) => {
|
|
200
|
+
const user = c.get('user');
|
|
201
|
+
return c.json(user);
|
|
202
|
+
});
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### Middleware Chain
|
|
206
|
+
|
|
207
|
+
Multiple middleware functions run in order:
|
|
208
|
+
|
|
209
|
+
```typescript
|
|
210
|
+
app.get('/protected',
|
|
211
|
+
authMiddleware,
|
|
212
|
+
rateLimitMiddleware,
|
|
213
|
+
validationMiddleware,
|
|
214
|
+
(c) => {
|
|
215
|
+
return c.json({ data: 'secret' });
|
|
216
|
+
}
|
|
217
|
+
);
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## Context API
|
|
223
|
+
|
|
224
|
+
The context object provides access to request data and response helpers:
|
|
225
|
+
|
|
226
|
+
```typescript
|
|
227
|
+
app.get('/demo', (c) => {
|
|
228
|
+
// Request object (Web Standard)
|
|
229
|
+
c.req; // Request
|
|
230
|
+
c.req.method; // "GET"
|
|
231
|
+
c.req.url; // Full URL
|
|
232
|
+
|
|
233
|
+
// Route parameters
|
|
234
|
+
c.params; // { id: "123" }
|
|
235
|
+
c.params.id; // "123"
|
|
236
|
+
|
|
237
|
+
// Query parameters
|
|
238
|
+
c.query('page'); // "1" or undefined
|
|
239
|
+
c.query('page', '1'); // "1" (with default)
|
|
240
|
+
c.queries('tags'); // ["a", "b"] (array)
|
|
241
|
+
|
|
242
|
+
// Headers
|
|
243
|
+
c.header('Content-Type'); // "application/json"
|
|
244
|
+
c.header('X-Custom'); // Custom header value
|
|
245
|
+
|
|
246
|
+
// Cookies
|
|
247
|
+
c.cookie('session'); // Cookie value
|
|
248
|
+
|
|
249
|
+
// Context storage
|
|
250
|
+
c.set('key', 'value'); // Store value
|
|
251
|
+
c.get('key'); // Retrieve value
|
|
252
|
+
|
|
253
|
+
return c.json({ ok: true });
|
|
254
|
+
});
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
## Request Handling
|
|
260
|
+
|
|
261
|
+
### JSON Body
|
|
262
|
+
|
|
263
|
+
```typescript
|
|
264
|
+
app.post('/api/users', async (c) => {
|
|
265
|
+
const body = await c.req.json();
|
|
266
|
+
// body is parsed JSON
|
|
267
|
+
return c.json({ received: body });
|
|
268
|
+
});
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
### Form Data
|
|
272
|
+
|
|
273
|
+
```typescript
|
|
274
|
+
app.post('/upload', async (c) => {
|
|
275
|
+
const form = await c.req.formData();
|
|
276
|
+
const name = form.get('name');
|
|
277
|
+
const file = form.get('file'); // File object
|
|
278
|
+
|
|
279
|
+
return c.json({ name, fileName: file?.name });
|
|
280
|
+
});
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
### Raw Text
|
|
284
|
+
|
|
285
|
+
```typescript
|
|
286
|
+
app.post('/webhook', async (c) => {
|
|
287
|
+
const text = await c.req.text();
|
|
288
|
+
return c.text(`Received: ${text}`);
|
|
289
|
+
});
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
### Raw Binary
|
|
293
|
+
|
|
294
|
+
```typescript
|
|
295
|
+
app.post('/binary', async (c) => {
|
|
296
|
+
const buffer = await c.req.arrayBuffer();
|
|
297
|
+
return c.json({ bytes: buffer.byteLength });
|
|
298
|
+
});
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
---
|
|
302
|
+
|
|
303
|
+
## Response Helpers
|
|
304
|
+
|
|
305
|
+
```typescript
|
|
306
|
+
// JSON response
|
|
307
|
+
c.json({ data: 'value' });
|
|
308
|
+
c.json({ created: true }, 201);
|
|
309
|
+
c.json({ error: 'Not found' }, 404);
|
|
310
|
+
|
|
311
|
+
// Text response
|
|
312
|
+
c.text('Hello, World!');
|
|
313
|
+
c.text('Created', 201);
|
|
314
|
+
|
|
315
|
+
// HTML response
|
|
316
|
+
c.html('<h1>Hello</h1>');
|
|
317
|
+
c.html('<!DOCTYPE html>...', 200);
|
|
318
|
+
|
|
319
|
+
// Redirect
|
|
320
|
+
c.redirect('/new-location');
|
|
321
|
+
c.redirect('/login', 302); // Temporary (default)
|
|
322
|
+
c.redirect('/moved', 301); // Permanent
|
|
323
|
+
|
|
324
|
+
// No Content
|
|
325
|
+
c.body(null, 204);
|
|
326
|
+
|
|
327
|
+
// Custom response
|
|
328
|
+
return new Response(body, {
|
|
329
|
+
status: 200,
|
|
330
|
+
headers: { 'X-Custom': 'value' },
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
// Set response headers
|
|
334
|
+
c.header('X-Request-Id', requestId);
|
|
335
|
+
c.header('Cache-Control', 'max-age=3600');
|
|
336
|
+
|
|
337
|
+
// Set cookies
|
|
338
|
+
c.cookie('session', token, {
|
|
339
|
+
httpOnly: true,
|
|
340
|
+
secure: true,
|
|
341
|
+
sameSite: 'Strict',
|
|
342
|
+
maxAge: 60 * 60 * 24, // 1 day
|
|
343
|
+
});
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
---
|
|
347
|
+
|
|
348
|
+
## Error Handling
|
|
349
|
+
|
|
350
|
+
### Global Error Handler
|
|
351
|
+
|
|
352
|
+
```typescript
|
|
353
|
+
app.onError((error, c) => {
|
|
354
|
+
console.error('Error:', error);
|
|
355
|
+
|
|
356
|
+
if (error instanceof ValidationError) {
|
|
357
|
+
return c.json({ error: error.message }, 400);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
return c.json({ error: 'Internal Server Error' }, 500);
|
|
361
|
+
});
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
### 404 Not Found
|
|
365
|
+
|
|
366
|
+
```typescript
|
|
367
|
+
app.notFound((c) => {
|
|
368
|
+
return c.json({
|
|
369
|
+
error: 'Not Found',
|
|
370
|
+
path: new URL(c.req.url).pathname,
|
|
371
|
+
}, 404);
|
|
372
|
+
});
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
### Throwing Errors
|
|
376
|
+
|
|
377
|
+
```typescript
|
|
378
|
+
import { HTTPException } from '@flight-framework/http';
|
|
379
|
+
|
|
380
|
+
app.get('/protected', (c) => {
|
|
381
|
+
if (!c.get('user')) {
|
|
382
|
+
throw new HTTPException(401, 'Unauthorized');
|
|
383
|
+
}
|
|
384
|
+
return c.json({ secret: 'data' });
|
|
385
|
+
});
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
---
|
|
389
|
+
|
|
390
|
+
## Sub-Routers
|
|
391
|
+
|
|
392
|
+
Organize routes into modules:
|
|
393
|
+
|
|
394
|
+
```typescript
|
|
395
|
+
// routes/users.ts
|
|
396
|
+
import { createServer } from '@flight-framework/http';
|
|
397
|
+
|
|
398
|
+
export const users = createServer();
|
|
399
|
+
|
|
400
|
+
users.get('/', (c) => c.json({ users: [] }));
|
|
401
|
+
users.get('/:id', (c) => c.json({ id: c.params.id }));
|
|
402
|
+
users.post('/', (c) => c.json({ created: true }));
|
|
403
|
+
|
|
404
|
+
// main.ts
|
|
405
|
+
import { createServer } from '@flight-framework/http';
|
|
406
|
+
import { users } from './routes/users';
|
|
407
|
+
|
|
408
|
+
const app = createServer();
|
|
409
|
+
|
|
410
|
+
// Mount sub-router
|
|
411
|
+
app.route('/api/users', users);
|
|
412
|
+
|
|
413
|
+
// Routes:
|
|
414
|
+
// GET /api/users
|
|
415
|
+
// GET /api/users/:id
|
|
416
|
+
// POST /api/users
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
---
|
|
420
|
+
|
|
421
|
+
## Runtime Adapters
|
|
422
|
+
|
|
423
|
+
### Node.js
|
|
424
|
+
|
|
425
|
+
```typescript
|
|
426
|
+
import { createServer } from '@flight-framework/http';
|
|
427
|
+
import { serve } from '@flight-framework/http/node';
|
|
428
|
+
|
|
429
|
+
const app = createServer();
|
|
430
|
+
|
|
431
|
+
serve(app, {
|
|
432
|
+
port: 3000,
|
|
433
|
+
hostname: '0.0.0.0',
|
|
434
|
+
});
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
### Bun
|
|
438
|
+
|
|
439
|
+
```typescript
|
|
440
|
+
import { createServer } from '@flight-framework/http';
|
|
441
|
+
import { serve } from '@flight-framework/http/bun';
|
|
442
|
+
|
|
443
|
+
const app = createServer();
|
|
444
|
+
|
|
445
|
+
serve(app, { port: 3000 });
|
|
446
|
+
|
|
447
|
+
// Or use Bun's native API
|
|
448
|
+
Bun.serve({
|
|
449
|
+
port: 3000,
|
|
450
|
+
fetch: app.fetch,
|
|
451
|
+
});
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
### Deno
|
|
455
|
+
|
|
456
|
+
```typescript
|
|
457
|
+
import { createServer } from '@flight-framework/http';
|
|
458
|
+
import { serve } from '@flight-framework/http/deno';
|
|
459
|
+
|
|
460
|
+
const app = createServer();
|
|
461
|
+
|
|
462
|
+
serve(app, { port: 3000 });
|
|
463
|
+
|
|
464
|
+
// Or use Deno's native API
|
|
465
|
+
Deno.serve({ port: 3000 }, app.fetch);
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
### Cloudflare Workers
|
|
469
|
+
|
|
470
|
+
```typescript
|
|
471
|
+
import { createServer } from '@flight-framework/http';
|
|
472
|
+
|
|
473
|
+
const app = createServer();
|
|
474
|
+
|
|
475
|
+
// ... define routes
|
|
476
|
+
|
|
477
|
+
export default {
|
|
478
|
+
fetch: app.fetch,
|
|
479
|
+
};
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
---
|
|
483
|
+
|
|
484
|
+
## Static Files
|
|
485
|
+
|
|
486
|
+
Serve static files from a directory:
|
|
487
|
+
|
|
488
|
+
```typescript
|
|
489
|
+
import { serveStatic } from '@flight-framework/http/static';
|
|
490
|
+
|
|
491
|
+
// Serve from 'public' directory
|
|
492
|
+
app.use('/static/*', serveStatic({ root: './public' }));
|
|
493
|
+
|
|
494
|
+
// With options
|
|
495
|
+
app.use('/assets/*', serveStatic({
|
|
496
|
+
root: './assets',
|
|
497
|
+
maxAge: 60 * 60 * 24, // 1 day cache
|
|
498
|
+
index: 'index.html',
|
|
499
|
+
}));
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
---
|
|
503
|
+
|
|
504
|
+
## CORS
|
|
505
|
+
|
|
506
|
+
Enable Cross-Origin Resource Sharing:
|
|
507
|
+
|
|
508
|
+
```typescript
|
|
509
|
+
import { cors } from '@flight-framework/http/cors';
|
|
510
|
+
|
|
511
|
+
// Allow all origins
|
|
512
|
+
app.use(cors());
|
|
513
|
+
|
|
514
|
+
// Specific origins
|
|
515
|
+
app.use(cors({
|
|
516
|
+
origin: 'https://example.com',
|
|
517
|
+
methods: ['GET', 'POST', 'PUT', 'DELETE'],
|
|
518
|
+
headers: ['Content-Type', 'Authorization'],
|
|
519
|
+
credentials: true,
|
|
520
|
+
maxAge: 86400,
|
|
521
|
+
}));
|
|
522
|
+
|
|
523
|
+
// Dynamic origin
|
|
524
|
+
app.use(cors({
|
|
525
|
+
origin: (origin) => {
|
|
526
|
+
return origin.endsWith('.example.com');
|
|
527
|
+
},
|
|
528
|
+
}));
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
---
|
|
532
|
+
|
|
533
|
+
## API Reference
|
|
534
|
+
|
|
535
|
+
### createServer(options?)
|
|
536
|
+
|
|
537
|
+
Create a new Flight HTTP server.
|
|
538
|
+
|
|
539
|
+
| Option | Type | Default | Description |
|
|
540
|
+
|--------|------|---------|-------------|
|
|
541
|
+
| `strict` | `boolean` | `true` | Strict routing (trailing slash matters) |
|
|
542
|
+
| `getPath` | `function` | - | Custom path extraction |
|
|
543
|
+
|
|
544
|
+
### Context Methods
|
|
545
|
+
|
|
546
|
+
| Method | Description |
|
|
547
|
+
|--------|-------------|
|
|
548
|
+
| `c.req` | Web Standard Request object |
|
|
549
|
+
| `c.params` | Route parameters |
|
|
550
|
+
| `c.query(name, default?)` | Get query parameter |
|
|
551
|
+
| `c.queries(name)` | Get all values for query param |
|
|
552
|
+
| `c.header(name)` | Get request header |
|
|
553
|
+
| `c.cookie(name)` | Get cookie value |
|
|
554
|
+
| `c.set(key, value)` | Store value in context |
|
|
555
|
+
| `c.get(key)` | Retrieve value from context |
|
|
556
|
+
| `c.json(data, status?)` | JSON response |
|
|
557
|
+
| `c.text(text, status?)` | Text response |
|
|
558
|
+
| `c.html(html, status?)` | HTML response |
|
|
559
|
+
| `c.redirect(url, status?)` | Redirect response |
|
|
560
|
+
| `c.body(body, status?)` | Raw body response |
|
|
561
|
+
|
|
562
|
+
### App Methods
|
|
563
|
+
|
|
564
|
+
| Method | Description |
|
|
565
|
+
|--------|-------------|
|
|
566
|
+
| `app.get/post/put/delete/patch(path, ...handlers)` | Register route |
|
|
567
|
+
| `app.all(path, ...handlers)` | All HTTP methods |
|
|
568
|
+
| `app.on(methods[], path, ...handlers)` | Specific methods |
|
|
569
|
+
| `app.use(...middleware)` | Add middleware |
|
|
570
|
+
| `app.use(path, ...middleware)` | Path-specific middleware |
|
|
571
|
+
| `app.route(path, subRouter)` | Mount sub-router |
|
|
572
|
+
| `app.notFound(handler)` | Custom 404 handler |
|
|
573
|
+
| `app.onError(handler)` | Custom error handler |
|
|
574
|
+
| `app.fetch(request)` | Handle request (Web Standard) |
|
|
575
|
+
|
|
576
|
+
---
|
|
577
|
+
|
|
578
|
+
## License
|
|
579
|
+
|
|
580
|
+
MIT
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { E as Env, F as FlightHttpServer } from '../types-CtqOEBIR.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @flightdev/http - Bun Adapter
|
|
5
|
+
*
|
|
6
|
+
* Allows running Flight HTTP server on Bun runtime.
|
|
7
|
+
* Bun natively supports Web Standard Request/Response.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
interface BunServer {
|
|
11
|
+
stop: () => void;
|
|
12
|
+
port: number;
|
|
13
|
+
hostname: string;
|
|
14
|
+
}
|
|
15
|
+
interface ServeOptions {
|
|
16
|
+
port?: number;
|
|
17
|
+
hostname?: string;
|
|
18
|
+
onListen?: (info: {
|
|
19
|
+
port: number;
|
|
20
|
+
hostname: string;
|
|
21
|
+
}) => void;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Start a Bun server with the Flight app
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```typescript
|
|
28
|
+
* import { createServer } from '@flightdev/http';
|
|
29
|
+
* import { serve } from '@flightdev/http/bun';
|
|
30
|
+
*
|
|
31
|
+
* const app = createServer();
|
|
32
|
+
* app.get('/', (c) => c.json({ hello: 'world' }));
|
|
33
|
+
*
|
|
34
|
+
* serve(app, { port: 3000 });
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
declare function serve<E extends Env = Env>(app: FlightHttpServer<E>, options?: ServeOptions): BunServer;
|
|
38
|
+
|
|
39
|
+
export { FlightHttpServer, type ServeOptions, serve };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// src/adapters/bun.ts
|
|
2
|
+
function serve(app, options = {}) {
|
|
3
|
+
const {
|
|
4
|
+
port = 3e3,
|
|
5
|
+
hostname = "0.0.0.0",
|
|
6
|
+
onListen
|
|
7
|
+
} = options;
|
|
8
|
+
const server = Bun.serve({
|
|
9
|
+
port,
|
|
10
|
+
hostname,
|
|
11
|
+
fetch: (request) => app.fetch(request)
|
|
12
|
+
});
|
|
13
|
+
const info = { port: server.port, hostname: server.hostname };
|
|
14
|
+
if (onListen) {
|
|
15
|
+
onListen(info);
|
|
16
|
+
} else {
|
|
17
|
+
console.log(`
|
|
18
|
+
\u2708\uFE0F Flight HTTP Server (Bun) running!
|
|
19
|
+
|
|
20
|
+
\u279C Local: http://localhost:${info.port}/
|
|
21
|
+
\u279C Network: http://${info.hostname}:${info.port}/
|
|
22
|
+
`);
|
|
23
|
+
}
|
|
24
|
+
return server;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export { serve };
|
|
28
|
+
//# sourceMappingURL=bun.js.map
|
|
29
|
+
//# sourceMappingURL=bun.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/adapters/bun.ts"],"names":[],"mappings":";AAsDO,SAAS,KAAA,CACZ,GAAA,EACA,OAAA,GAAwB,EAAC,EAChB;AACT,EAAA,MAAM;AAAA,IACF,IAAA,GAAO,GAAA;AAAA,IACP,QAAA,GAAW,SAAA;AAAA,IACX;AAAA,GACJ,GAAI,OAAA;AAEJ,EAAA,MAAM,MAAA,GAAS,IAAI,KAAA,CAAM;AAAA,IACrB,IAAA;AAAA,IACA,QAAA;AAAA,IACA,KAAA,EAAO,CAAC,OAAA,KAAY,GAAA,CAAI,MAAM,OAAO;AAAA,GACxC,CAAA;AAED,EAAA,MAAM,OAAO,EAAE,IAAA,EAAM,OAAO,IAAA,EAAM,QAAA,EAAU,OAAO,QAAA,EAAS;AAE5D,EAAA,IAAI,QAAA,EAAU;AACV,IAAA,QAAA,CAAS,IAAI,CAAA;AAAA,EACjB,CAAA,MAAO;AACH,IAAA,OAAA,CAAQ,GAAA,CAAI;AAAA;AAAA;AAAA,oCAAA,EAGa,KAAK,IAAI,CAAA;AAAA,0BAAA,EACnB,IAAA,CAAK,QAAQ,CAAA,CAAA,EAAI,IAAA,CAAK,IAAI,CAAA;AAAA,CAChD,CAAA;AAAA,EACG;AAEA,EAAA,OAAO,MAAA;AACX","file":"bun.js","sourcesContent":["/**\r\n * @flightdev/http - Bun Adapter\r\n * \r\n * Allows running Flight HTTP server on Bun runtime.\r\n * Bun natively supports Web Standard Request/Response.\r\n */\r\n\r\nimport type { FlightHttpServer, Env } from '../types.js';\r\n\r\n// ============================================================================\r\n// Bun Server Types\r\n// ============================================================================\r\n\r\ninterface BunServeOptions {\r\n port?: number;\r\n hostname?: string;\r\n fetch: (request: Request) => Response | Promise<Response>;\r\n}\r\n\r\ninterface BunServer {\r\n stop: () => void;\r\n port: number;\r\n hostname: string;\r\n}\r\n\r\n// We don't import Bun types directly to avoid build issues\r\ndeclare const Bun: {\r\n serve: (options: BunServeOptions) => BunServer;\r\n};\r\n\r\n// ============================================================================\r\n// serve() Function\r\n// ============================================================================\r\n\r\nexport interface ServeOptions {\r\n port?: number;\r\n hostname?: string;\r\n onListen?: (info: { port: number; hostname: string }) => void;\r\n}\r\n\r\n/**\r\n * Start a Bun server with the Flight app\r\n * \r\n * @example\r\n * ```typescript\r\n * import { createServer } from '@flightdev/http';\r\n * import { serve } from '@flightdev/http/bun';\r\n * \r\n * const app = createServer();\r\n * app.get('/', (c) => c.json({ hello: 'world' }));\r\n * \r\n * serve(app, { port: 3000 });\r\n * ```\r\n */\r\nexport function serve<E extends Env = Env>(\r\n app: FlightHttpServer<E>,\r\n options: ServeOptions = {}\r\n): BunServer {\r\n const {\r\n port = 3000,\r\n hostname = '0.0.0.0',\r\n onListen,\r\n } = options;\r\n\r\n const server = Bun.serve({\r\n port,\r\n hostname,\r\n fetch: (request) => app.fetch(request),\r\n });\r\n\r\n const info = { port: server.port, hostname: server.hostname };\r\n\r\n if (onListen) {\r\n onListen(info);\r\n } else {\r\n console.log(`\r\n ✈️ Flight HTTP Server (Bun) running!\r\n \r\n ➜ Local: http://localhost:${info.port}/\r\n ➜ Network: http://${info.hostname}:${info.port}/\r\n`);\r\n }\r\n\r\n return server;\r\n}\r\n\r\n// Re-export useful types\r\nexport type { FlightHttpServer } from '../types.js';\r\n"]}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { E as Env, F as FlightHttpServer } from '../types-CtqOEBIR.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @flightdev/http - Deno Adapter
|
|
5
|
+
*
|
|
6
|
+
* Allows running Flight HTTP server on Deno runtime.
|
|
7
|
+
* Deno natively supports Web Standard Request/Response.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
interface ServeOptions {
|
|
11
|
+
port?: number;
|
|
12
|
+
hostname?: string;
|
|
13
|
+
onListen?: (info: {
|
|
14
|
+
port: number;
|
|
15
|
+
hostname: string;
|
|
16
|
+
}) => void;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Start a Deno server with the Flight app
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* import { createServer } from '@flightdev/http';
|
|
24
|
+
* import { serve } from '@flightdev/http/deno';
|
|
25
|
+
*
|
|
26
|
+
* const app = createServer();
|
|
27
|
+
* app.get('/', (c) => c.json({ hello: 'world' }));
|
|
28
|
+
*
|
|
29
|
+
* serve(app, { port: 3000 });
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
declare function serve<E extends Env = Env>(app: FlightHttpServer<E>, options?: ServeOptions): {
|
|
33
|
+
shutdown: () => Promise<void>;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export { FlightHttpServer, type ServeOptions, serve };
|