vector-framework 1.1.1 → 1.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.
Files changed (98) hide show
  1. package/README.md +87 -635
  2. package/dist/auth/protected.d.ts.map +1 -1
  3. package/dist/auth/protected.js.map +1 -1
  4. package/dist/cache/manager.d.ts.map +1 -1
  5. package/dist/cache/manager.js +2 -7
  6. package/dist/cache/manager.js.map +1 -1
  7. package/dist/cli/index.js +17 -62
  8. package/dist/cli/index.js.map +1 -1
  9. package/dist/cli/option-resolution.d.ts +4 -0
  10. package/dist/cli/option-resolution.d.ts.map +1 -0
  11. package/dist/cli/option-resolution.js +28 -0
  12. package/dist/cli/option-resolution.js.map +1 -0
  13. package/dist/cli.js +2721 -617
  14. package/dist/constants/index.d.ts +3 -0
  15. package/dist/constants/index.d.ts.map +1 -1
  16. package/dist/constants/index.js +6 -0
  17. package/dist/constants/index.js.map +1 -1
  18. package/dist/core/config-loader.d.ts.map +1 -1
  19. package/dist/core/config-loader.js +2 -0
  20. package/dist/core/config-loader.js.map +1 -1
  21. package/dist/core/router.d.ts +41 -17
  22. package/dist/core/router.d.ts.map +1 -1
  23. package/dist/core/router.js +432 -153
  24. package/dist/core/router.js.map +1 -1
  25. package/dist/core/server.d.ts +14 -1
  26. package/dist/core/server.d.ts.map +1 -1
  27. package/dist/core/server.js +250 -30
  28. package/dist/core/server.js.map +1 -1
  29. package/dist/core/vector.d.ts +4 -3
  30. package/dist/core/vector.d.ts.map +1 -1
  31. package/dist/core/vector.js +21 -12
  32. package/dist/core/vector.js.map +1 -1
  33. package/dist/dev/route-generator.d.ts.map +1 -1
  34. package/dist/dev/route-generator.js.map +1 -1
  35. package/dist/dev/route-scanner.d.ts.map +1 -1
  36. package/dist/dev/route-scanner.js +1 -5
  37. package/dist/dev/route-scanner.js.map +1 -1
  38. package/dist/http.d.ts +14 -14
  39. package/dist/http.d.ts.map +1 -1
  40. package/dist/http.js +34 -41
  41. package/dist/http.js.map +1 -1
  42. package/dist/index.js +1314 -8
  43. package/dist/index.mjs +1314 -8
  44. package/dist/middleware/manager.d.ts.map +1 -1
  45. package/dist/middleware/manager.js +4 -0
  46. package/dist/middleware/manager.js.map +1 -1
  47. package/dist/openapi/docs-ui.d.ts +2 -0
  48. package/dist/openapi/docs-ui.d.ts.map +1 -0
  49. package/dist/openapi/docs-ui.js +1313 -0
  50. package/dist/openapi/docs-ui.js.map +1 -0
  51. package/dist/openapi/generator.d.ts +12 -0
  52. package/dist/openapi/generator.d.ts.map +1 -0
  53. package/dist/openapi/generator.js +273 -0
  54. package/dist/openapi/generator.js.map +1 -0
  55. package/dist/types/index.d.ts +70 -11
  56. package/dist/types/index.d.ts.map +1 -1
  57. package/dist/types/standard-schema.d.ts +118 -0
  58. package/dist/types/standard-schema.d.ts.map +1 -0
  59. package/dist/types/standard-schema.js +2 -0
  60. package/dist/types/standard-schema.js.map +1 -0
  61. package/dist/utils/cors.d.ts +13 -0
  62. package/dist/utils/cors.d.ts.map +1 -0
  63. package/dist/utils/cors.js +89 -0
  64. package/dist/utils/cors.js.map +1 -0
  65. package/dist/utils/path.d.ts +6 -0
  66. package/dist/utils/path.d.ts.map +1 -1
  67. package/dist/utils/path.js +5 -0
  68. package/dist/utils/path.js.map +1 -1
  69. package/dist/utils/schema-validation.d.ts +31 -0
  70. package/dist/utils/schema-validation.d.ts.map +1 -0
  71. package/dist/utils/schema-validation.js +77 -0
  72. package/dist/utils/schema-validation.js.map +1 -0
  73. package/dist/utils/validation.d.ts.map +1 -1
  74. package/dist/utils/validation.js +1 -0
  75. package/dist/utils/validation.js.map +1 -1
  76. package/package.json +13 -12
  77. package/src/auth/protected.ts +3 -13
  78. package/src/cache/manager.ts +4 -18
  79. package/src/cli/index.ts +19 -75
  80. package/src/cli/option-resolution.ts +40 -0
  81. package/src/constants/index.ts +7 -0
  82. package/src/core/config-loader.ts +3 -3
  83. package/src/core/router.ts +502 -156
  84. package/src/core/server.ts +327 -32
  85. package/src/core/vector.ts +49 -29
  86. package/src/dev/route-generator.ts +1 -3
  87. package/src/dev/route-scanner.ts +2 -9
  88. package/src/http.ts +85 -125
  89. package/src/middleware/manager.ts +4 -0
  90. package/src/openapi/assets/tailwindcdn.js +83 -0
  91. package/src/openapi/docs-ui.ts +1317 -0
  92. package/src/openapi/generator.ts +359 -0
  93. package/src/types/index.ts +104 -17
  94. package/src/types/standard-schema.ts +147 -0
  95. package/src/utils/cors.ts +101 -0
  96. package/src/utils/path.ts +6 -0
  97. package/src/utils/schema-validation.ts +123 -0
  98. package/src/utils/validation.ts +1 -0
package/README.md CHANGED
@@ -1,706 +1,158 @@
1
- # Vector Framework
1
+ # vector
2
+ <img width="1640" height="664" alt="vector-bw-banner" src="https://github.com/user-attachments/assets/afeb8c6e-0729-4fea-9054-7972f8af9365" />
2
3
 
3
- **Blazing fast, secure, and developer-friendly API framework for Bun**
4
+ Blazing fast, secure, and developer-friendly API framework for Bun.
4
5
 
5
- - **100,000+ requests/second** - Optimized for extreme performance
6
- - **Single dependency** - Only itty-router, minimizing security risks
7
- - **Zero build step** - Native TypeScript execution with Bun
8
- - **Encore-like DX** - Declarative, type-safe APIs you'll love
6
+ Vector is a Bun-first framework for building HTTP APIs with declarative route files, strong TypeScript inference, and zero runtime dependencies.
9
7
 
10
- ## Quick Start
8
+ - **Zero Dependencies**: No runtime routing dependency
9
+ - **Bun Native**: TypeScript-first workflow with the Bun runtime
10
+ - **Type Safe**: Typed request/auth/context with schema-driven validation
11
+ - **Built In**: Middleware, auth hooks, caching, CORS, OpenAPI generation
11
12
 
12
- ### Installation
13
+ ## Installation
13
14
 
14
15
  ```bash
15
16
  bun add vector-framework
16
17
  ```
17
18
 
18
- ### 1. Configure Your App
19
+ Requirements:
20
+
21
+ - Bun `>= 1.0.0`
19
22
 
20
- Create `vector.config.ts` in your project root:
23
+ ## Quick Start
21
24
 
22
- ```typescript
23
- // vector.config.ts
25
+ ### 1. Create `vector.config.ts`
26
+
27
+ ```ts
24
28
  import type { VectorConfigSchema } from "vector-framework";
25
29
 
26
30
  const config: VectorConfigSchema = {
27
- // Server configuration
28
31
  port: 3000,
29
32
  hostname: "localhost",
30
33
  development: process.env.NODE_ENV !== "production",
31
- routesDir: "./routes", // Auto-discovers routes here
32
-
33
- // CORS configuration
34
- cors: {
35
- origin: "*",
36
- credentials: true,
37
- allowHeaders: ["Content-Type", "Authorization"],
38
- allowMethods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
39
- },
40
-
41
- // Authentication handler
42
- auth: async (request) => {
43
- const token = request.headers.get("Authorization")?.replace("Bearer ", "");
44
- if (token === "valid-token") {
45
- return { id: "user-123", email: "user@example.com" };
46
- }
47
- throw new Error("Invalid token");
48
- },
49
-
50
- // Optional: Cache handler (Redis example)
51
- cache: async (key, factory, ttl) => {
52
- // Your caching logic here
53
- const cached = await redis.get(key);
54
- if (cached) return JSON.parse(cached);
55
-
56
- const value = await factory();
57
- await redis.setex(key, ttl, JSON.stringify(value));
58
- return value;
34
+ routesDir: "./routes",
35
+ defaults: {
36
+ route: {
37
+ expose: true,
38
+ auth: false,
39
+ },
59
40
  },
60
-
61
- // Optional: Middleware
62
- before: [
63
- async (request) => {
64
- console.log(`${request.method} ${request.url}`);
65
- return request;
66
- }
67
- ],
68
- after: [
69
- async (response, request) => {
70
- const duration = Date.now() - (request.startTime || Date.now());
71
- response.headers.set("X-Response-Time", `${duration}ms`);
72
- return response;
73
- }
74
- ],
75
41
  };
76
42
 
77
43
  export default config;
78
44
  ```
79
45
 
80
- ### 2. Create Your First Route
46
+ ### 2. Create a route file
81
47
 
82
- ```typescript
48
+ ```ts
83
49
  // routes/hello.ts
84
50
  import { route } from "vector-framework";
85
51
 
86
- // Simple public endpoint
87
52
  export const hello = route(
88
- {
89
- method: "GET",
90
- path: "/hello/:name",
91
- expose: true, // Public endpoint (default: true)
92
- },
93
- async (req) => {
94
- return { message: `Hello ${req.params.name}!` };
95
- }
96
- );
97
-
98
- // Protected endpoint - uses auth from config
99
- export const getProfile = route(
100
- {
101
- method: "GET",
102
- path: "/profile",
103
- auth: true, // Requires authentication
104
- expose: true,
105
- },
53
+ { method: "GET", path: "/hello/:name", expose: true },
106
54
  async (req) => {
107
- return {
108
- user: req.authUser, // Typed from your auth handler
109
- timestamp: new Date(),
110
- };
111
- }
112
- );
113
-
114
- // Cached endpoint
115
- export const getUsers = route(
116
- {
117
- method: "GET",
118
- path: "/users",
119
- cache: 300, // Cache for 5 minutes
120
- expose: true,
55
+ return { message: `Hello ${req.params.name}` };
121
56
  },
122
- async () => {
123
- // Expensive operation, will be cached
124
- const users = await db.users.findMany();
125
- return { users };
126
- }
127
57
  );
128
58
  ```
129
59
 
130
- ### 3. Start Your Server
60
+ ### 3. Run the server
131
61
 
132
62
  ```bash
133
- # Development mode with hot reload
134
63
  bun vector dev
135
-
136
- # Production mode
137
- bun vector start
138
-
139
- # With custom options
140
- bun vector dev --port 4000 --routes ./api
141
- ```
142
-
143
- That's it! Your API is running at `http://localhost:3000` 🎉
144
-
145
- ## TypeScript Type Safety
146
-
147
- Vector provides full type safety with customizable types. Define your types in the config and use them in routes:
148
-
149
- ```typescript
150
- // vector.config.ts
151
- import type { VectorConfigSchema, VectorTypes } from "vector-framework";
152
-
153
- // Define your custom user type
154
- interface MyUser {
155
- id: string;
156
- email: string;
157
- role: "admin" | "user";
158
- permissions: string[];
159
- }
160
-
161
- // Extend Vector types
162
- interface MyAppTypes extends VectorTypes {
163
- auth: MyUser;
164
- }
165
-
166
- // Use in config with type parameter
167
- const config: VectorConfigSchema<MyAppTypes> = {
168
- port: 3000,
169
-
170
- // Auth handler returns your custom type
171
- auth: async (request): Promise<MyUser> => {
172
- // Your auth logic
173
- return {
174
- id: "user-123",
175
- email: "user@example.com",
176
- role: "admin",
177
- permissions: ["read", "write"],
178
- };
179
- },
180
- };
181
-
182
- export default config;
183
- export type { MyAppTypes }; // Export for use in routes
184
- ```
185
-
186
- ```typescript
187
- // routes/admin.ts
188
- import { route, APIError } from "vector-framework";
189
- import type { MyAppTypes } from "../vector.config";
190
-
191
- // Use type parameter to get fully typed request
192
- export const adminOnly = route<MyAppTypes>(
193
- {
194
- method: "GET",
195
- path: "/admin/data",
196
- auth: true,
197
- expose: true,
198
- },
199
- async (req) => {
200
- // req.authUser is now typed as MyUser
201
- if (req.authUser?.role !== "admin") {
202
- throw APIError.forbidden("Admin access required");
203
- }
204
-
205
- // TypeScript knows these properties exist
206
- return {
207
- user: req.authUser.email,
208
- permissions: req.authUser.permissions,
209
- };
210
- }
211
- );
212
- ```
213
-
214
- ## Core Features
215
-
216
- ### Route Options
217
-
218
- ```typescript
219
- interface RouteOptions {
220
- method: string; // HTTP method (GET, POST, etc.)
221
- path: string; // Route path with params (/users/:id)
222
- expose?: boolean; // Make route accessible (default: true)
223
- auth?: boolean; // Require authentication
224
- cache?: number | { // Cache configuration
225
- ttl: number; // Time to live in seconds
226
- key?: string; // Custom cache key
227
- };
228
- rawRequest?: boolean; // Skip body parsing
229
- rawResponse?: boolean; // Return raw response
230
- responseContentType?: string; // Response content type
231
- }
232
- ```
233
-
234
- ### Request Object
235
-
236
- Every route handler receives a typed request object:
237
-
238
- ```typescript
239
- export const example = route(
240
- { method: "POST", path: "/example/:id" },
241
- async (req) => {
242
- // All available request properties:
243
- req.params.id; // URL parameters
244
- req.query.search; // Query parameters
245
- req.headers; // Request headers
246
- req.cookies; // Parsed cookies
247
- req.content; // Parsed body (JSON/form data)
248
- req.authUser; // Authenticated user (when auth: true)
249
- req.context; // Request context
250
- req.metadata; // Route metadata
251
- }
252
- );
253
64
  ```
254
65
 
255
- ### Error Handling
256
-
257
- Vector provides comprehensive error responses. Requests with a malformed URL are automatically rejected with a `400 Bad Request` before reaching your handler. Unhandled exceptions in handlers return a `500 Internal Server Error`.
66
+ Your API will be available at `http://localhost:3000`.
258
67
 
259
- ```typescript
260
- import { APIError } from "vector-framework";
68
+ ## Production Start
261
69
 
262
- export const example = route(
263
- { method: "GET", path: "/data/:id" },
264
- async (req) => {
265
- // Client errors (4xx)
266
- if (!req.params.id) {
267
- throw APIError.badRequest("ID is required");
268
- }
269
-
270
- const data = await findData(req.params.id);
271
- if (!data) {
272
- throw APIError.notFound("Data not found");
273
- }
274
-
275
- if (!canAccess(req.authUser, data)) {
276
- throw APIError.forbidden("Access denied");
277
- }
278
-
279
- // Rate limiting
280
- if (await isRateLimited(req)) {
281
- throw APIError.tooManyRequests("Please wait before trying again");
282
- }
283
-
284
- // Server errors (5xx)
285
- try {
286
- return await processData(data);
287
- } catch (error) {
288
- throw APIError.internalServerError("Processing failed");
289
- }
290
- }
291
- );
70
+ ```bash
71
+ bun vector start --config ./vector.config.ts --routes ./routes --port 8080 --host 0.0.0.0
292
72
  ```
293
73
 
294
- ## Configuration Reference
74
+ Notes:
295
75
 
296
- ### VectorConfigSchema
76
+ - `start` uses the same config and route options as `dev`.
77
+ - `start` sets `NODE_ENV=production`.
78
+ - File watching is only enabled for `dev`.
297
79
 
298
- ```typescript
299
- interface VectorConfigSchema {
300
- // Server
301
- port?: number; // Server port (default: 3000)
302
- hostname?: string; // Server hostname (default: localhost)
303
- reusePort?: boolean; // Reuse port (default: true)
304
- development?: boolean; // Development mode
305
- routesDir?: string; // Routes directory (default: ./routes)
306
- routeExcludePatterns?: string[]; // Patterns to exclude from route scanning
307
- idleTimeout?: number; // Idle timeout in seconds
80
+ ## Optional: Validation + OpenAPI
308
81
 
309
- // CORS
310
- cors?: CorsOptions | boolean;
311
-
312
- // Handlers
313
- auth?: ProtectedHandler; // Authentication handler
314
- cache?: CacheHandler; // Cache handler
315
-
316
- // Middleware
317
- before?: BeforeMiddleware[]; // Pre-request middleware
318
- after?: AfterMiddleware[]; // Post-response middleware
319
- }
82
+ ```bash
83
+ bun add -d zod
320
84
  ```
321
85
 
322
- ### Example: Full Configuration
86
+ Vector is not tied to Zod. It supports any validation library that implements the
87
+ `StandardSchemaV1` interface (`~standard` v1).
323
88
 
324
- ```typescript
325
- // vector.config.ts
326
- import type { VectorConfigSchema } from "vector-framework";
327
- import { verifyJWT } from "./lib/auth";
328
- import { redis } from "./lib/redis";
89
+ Common compatible choices include:
329
90
 
330
- const config: VectorConfigSchema = {
331
- port: process.env.PORT || 3000,
332
- hostname: "0.0.0.0",
333
- development: process.env.NODE_ENV !== "production",
334
- routesDir: "./api/routes",
335
- routeExcludePatterns: ["*.test.ts", "*.spec.ts"], // Optional: custom exclusions
336
- idleTimeout: 60,
337
-
338
- cors: {
339
- origin: ["https://example.com", "https://app.example.com"],
340
- credentials: true,
341
- allowHeaders: ["Content-Type", "Authorization", "X-Request-ID"],
342
- allowMethods: ["GET", "POST", "PUT", "DELETE"],
343
- maxAge: 86400,
344
- },
91
+ - Zod (v4+)
92
+ - Valibot
93
+ - ArkType
345
94
 
346
- auth: async (request) => {
347
- const token = request.headers.get("Authorization")?.replace("Bearer ", "");
348
- if (!token) throw new Error("No token provided");
95
+ For OpenAPI schema conversion, your library also needs `StandardJSONSchemaV1`
96
+ (`~standard.jsonSchema.input/output`). If those converters are missing, runtime
97
+ validation still works, but schema conversion is skipped.
349
98
 
350
- const user = await verifyJWT(token);
351
- if (!user) throw new Error("Invalid token");
99
+ ```ts
100
+ import { route } from "vector-framework";
101
+ import { z } from "zod";
352
102
 
353
- return user;
354
- },
103
+ const CreateUserInput = z.object({
104
+ body: z.object({
105
+ email: z.string().email(),
106
+ name: z.string().min(1),
107
+ }),
108
+ });
355
109
 
356
- cache: async (key, factory, ttl) => {
357
- const cached = await redis.get(key);
358
- if (cached) return JSON.parse(cached);
110
+ const CreateUserSchema = { input: CreateUserInput };
359
111
 
360
- const value = await factory();
361
- await redis.setex(key, ttl, JSON.stringify(value));
362
- return value;
112
+ export const createUser = route(
113
+ { method: "POST", path: "/users", expose: true, schema: CreateUserSchema },
114
+ async (req) => {
115
+ return { created: true, email: req.content.email };
363
116
  },
364
-
365
- before: [
366
- // Logging middleware
367
- async (request) => {
368
- request.startTime = Date.now();
369
- console.log(`[${new Date().toISOString()}] ${request.method} ${request.url}`);
370
- return request;
371
- },
372
-
373
- // Request ID middleware
374
- async (request) => {
375
- request.id = crypto.randomUUID();
376
- return request;
377
- },
378
- ],
379
-
380
- after: [
381
- // Response time header
382
- async (response, request) => {
383
- const duration = Date.now() - (request.startTime || Date.now());
384
- response.headers.set("X-Response-Time", `${duration}ms`);
385
- return response;
386
- },
387
-
388
- // Security headers
389
- async (response) => {
390
- response.headers.set("X-Content-Type-Options", "nosniff");
391
- response.headers.set("X-Frame-Options", "DENY");
392
- return response;
393
- },
394
- ],
395
- };
396
-
397
- export default config;
398
- ```
399
-
400
- ## CLI Commands
401
-
402
- ```bash
403
- # Development server with hot reload
404
- bun vector dev
405
-
406
- # Production server
407
- bun vector start
408
-
409
- # Build for production
410
- bun vector build
411
-
412
- # Command options
413
- bun vector dev --port 4000 # Custom port
414
- bun vector dev --host 0.0.0.0 # Custom host
415
- bun vector dev --routes ./api # Custom routes directory
416
- bun vector dev --config ./custom.config.ts # Custom config file
417
- ```
418
-
419
- ## Project Structure
420
-
421
- ```
422
- my-app/
423
- ├── vector.config.ts # Framework configuration
424
- ├── routes/ # Auto-discovered routes
425
- │ ├── users.ts # /users endpoints
426
- │ ├── posts.ts # /posts endpoints
427
- │ ├── users.test.ts # Test file (automatically excluded)
428
- │ └── admin/ # Nested routes
429
- │ └── stats.ts # /admin/stats endpoints
430
- ├── lib/ # Your libraries
431
- │ ├── auth.ts
432
- │ ├── db.ts
433
- │ └── redis.ts
434
- └── package.json
435
- ```
436
-
437
- ## Route Discovery
438
-
439
- Vector automatically discovers and loads route files from your `routesDir` (default: `./routes`). By default, the following file patterns are excluded from route scanning:
440
-
441
- - `*.test.ts`, `*.test.js`, `*.test.tsx`, `*.test.jsx` - Test files
442
- - `*.spec.ts`, `*.spec.js`, `*.spec.tsx`, `*.spec.jsx` - Spec files
443
- - `*.tests.ts`, `*.tests.js` - Test suite files
444
- - `**/__tests__/**` - Test directories
445
- - `*.interface.ts`, `*.type.ts` - Type definition files
446
- - `*.d.ts` - TypeScript declaration files
447
-
448
- You can customize the exclusion patterns using the `routeExcludePatterns` configuration option. Both single-segment (`*`) and multi-segment (`**`) glob patterns are supported:
449
-
450
- ```typescript
451
- // vector.config.ts
452
- const config: VectorConfigSchema = {
453
- routesDir: "./routes",
454
- // Custom exclusion patterns (overrides defaults)
455
- routeExcludePatterns: [
456
- "*.test.ts",
457
- "*.spec.ts",
458
- "*.mock.ts",
459
- "**/__tests__/**", // Exclude any nested __tests__ directory
460
- "_*.ts", // Exclude files starting with underscore
461
- ],
462
- };
117
+ );
463
118
  ```
464
119
 
465
- ## Performance
466
-
467
- Vector achieves exceptional performance through:
468
-
469
- - **Bun Runtime**: Native TypeScript execution without transpilation
470
- - **Minimal Dependencies**: Only itty-router (3KB) as dependency
471
- - **Optimized Routing**: Efficient regex-based route matching
472
- - **Smart Caching**: Built-in response caching with configurable TTL
120
+ Enable OpenAPI in `vector.config.ts`:
473
121
 
474
- Benchmarks show Vector handling **100,000+ requests/second** on standard hardware.
475
-
476
- ## Why Vector?
477
-
478
- ### For Encore Users
479
- Love Encore's declarative API design but need more flexibility? Vector provides the same developer experience with the freedom to deploy anywhere Bun runs.
480
-
481
- ### For Express/Fastify Users
482
- Tired of middleware chains and verbose configurations? Vector's declarative approach makes APIs cleaner and more maintainable.
483
-
484
- ### For New Projects
485
- Starting fresh? Vector gives you production-ready features from day one with minimal configuration.
486
-
487
- ## Error Reference
488
-
489
- Vector provides comprehensive error responses for all HTTP status codes. All errors return a consistent format:
490
-
491
- ```json
492
- {
493
- "error": true,
494
- "message": "Error message",
495
- "statusCode": 400,
496
- "timestamp": "2025-01-01T00:00:00.000Z"
122
+ ```ts
123
+ openapi: {
124
+ enabled: true,
125
+ path: '/openapi.json',
126
+ docs: false,
497
127
  }
498
128
  ```
499
129
 
500
- ### Client Errors (4xx)
501
-
502
- ```typescript
503
- import { APIError } from "vector-framework";
504
-
505
- // 400 Bad Request
506
- APIError.badRequest("Invalid input data");
507
-
508
- // 401 Unauthorized
509
- APIError.unauthorized("Authentication required");
510
-
511
- // 402 Payment Required
512
- APIError.paymentRequired("Subscription expired");
513
-
514
- // 403 Forbidden
515
- APIError.forbidden("Access denied");
516
-
517
- // 404 Not Found
518
- APIError.notFound("Resource not found");
519
-
520
- // 405 Method Not Allowed
521
- APIError.methodNotAllowed("POST not allowed on this endpoint");
522
-
523
- // 406 Not Acceptable
524
- APIError.notAcceptable("Cannot produce requested content type");
525
-
526
- // 408 Request Timeout
527
- APIError.requestTimeout("Request took too long");
528
-
529
- // 409 Conflict
530
- APIError.conflict("Resource already exists");
531
-
532
- // 410 Gone
533
- APIError.gone("Resource permanently deleted");
534
-
535
- // 411 Length Required
536
- APIError.lengthRequired("Content-Length header required");
537
-
538
- // 412 Precondition Failed
539
- APIError.preconditionFailed("ETag mismatch");
540
-
541
- // 413 Payload Too Large
542
- APIError.payloadTooLarge("Request body exceeds limit");
543
-
544
- // 414 URI Too Long
545
- APIError.uriTooLong("URL exceeds maximum length");
546
-
547
- // 415 Unsupported Media Type
548
- APIError.unsupportedMediaType("Content-Type not supported");
549
-
550
- // 416 Range Not Satisfiable
551
- APIError.rangeNotSatisfiable("Requested range cannot be satisfied");
552
-
553
- // 417 Expectation Failed
554
- APIError.expectationFailed("Expect header requirements not met");
555
-
556
- // 418 I'm a Teapot
557
- APIError.imATeapot("I refuse to brew coffee");
558
-
559
- // 421 Misdirected Request
560
- APIError.misdirectedRequest("Request sent to wrong server");
561
-
562
- // 422 Unprocessable Entity
563
- APIError.unprocessableEntity("Validation failed");
564
-
565
- // 423 Locked
566
- APIError.locked("Resource is locked");
567
-
568
- // 424 Failed Dependency
569
- APIError.failedDependency("Dependent request failed");
570
-
571
- // 425 Too Early
572
- APIError.tooEarly("Request is too early");
573
-
574
- // 426 Upgrade Required
575
- APIError.upgradeRequired("Protocol upgrade required");
576
-
577
- // 428 Precondition Required
578
- APIError.preconditionRequired("Precondition headers required");
579
-
580
- // 429 Too Many Requests
581
- APIError.tooManyRequests("Rate limit exceeded");
582
-
583
- // 431 Request Header Fields Too Large
584
- APIError.requestHeaderFieldsTooLarge("Headers too large");
585
-
586
- // 451 Unavailable For Legal Reasons
587
- APIError.unavailableForLegalReasons("Content blocked for legal reasons");
588
- ```
589
-
590
- ### Server Errors (5xx)
591
-
592
- ```typescript
593
- // 500 Internal Server Error
594
- APIError.internalServerError("Something went wrong");
595
-
596
- // 501 Not Implemented
597
- APIError.notImplemented("Feature not yet available");
598
-
599
- // 502 Bad Gateway
600
- APIError.badGateway("Upstream server error");
601
-
602
- // 503 Service Unavailable
603
- APIError.serviceUnavailable("Service temporarily down");
604
-
605
- // 504 Gateway Timeout
606
- APIError.gatewayTimeout("Upstream server timeout");
607
-
608
- // 505 HTTP Version Not Supported
609
- APIError.httpVersionNotSupported("HTTP/3 not supported");
610
-
611
- // 506 Variant Also Negotiates
612
- APIError.variantAlsoNegotiates("Content negotiation error");
613
-
614
- // 507 Insufficient Storage
615
- APIError.insufficientStorage("Server storage full");
616
-
617
- // 508 Loop Detected
618
- APIError.loopDetected("Infinite loop detected");
619
-
620
- // 510 Not Extended
621
- APIError.notExtended("Extension required");
622
-
623
- // 511 Network Authentication Required
624
- APIError.networkAuthenticationRequired("Network login required");
625
- ```
626
-
627
- ### Convenience Aliases
628
-
629
- ```typescript
630
- // Alias for 422 Unprocessable Entity
631
- APIError.invalidArgument("Field 'email' is required");
632
-
633
- // Alias for 429 Too Many Requests
634
- APIError.rateLimitExceeded("Try again in 60 seconds");
635
-
636
- // Alias for 503 Service Unavailable
637
- APIError.maintenance("Scheduled maintenance in progress");
638
- ```
639
-
640
- ### Custom Errors
130
+ ## Documentation
641
131
 
642
- ```typescript
643
- // Create error with any status code
644
- APIError.custom(456, "Custom error message");
132
+ Start here for deeper guides:
645
133
 
646
- // With custom content type
647
- APIError.custom(400, "Invalid XML", "application/xml");
648
- ```
134
+ - [Docs Index](docs/README.md)
135
+ - [Configuration](docs/configuration.md)
136
+ - [Routing and Request API](docs/routing.md)
137
+ - [TypeScript Types](docs/typescript.md)
138
+ - [Schema Validation](docs/schema-validation.md)
139
+ - [OpenAPI and Docs UI](docs/openapi.md)
140
+ - [CLI and Route Discovery](docs/cli-and-discovery.md)
141
+ - [Error Reference](docs/errors.md)
142
+ - [Migration Notes](docs/migration.md)
143
+ - [Performance Notes](docs/performance.md)
649
144
 
650
- ### Usage in Routes
145
+ ## Examples
651
146
 
652
- ```typescript
653
- export const example = route(
654
- { method: "POST", path: "/api/users" },
655
- async (req) => {
656
- // Validation errors
657
- if (!req.content?.email) {
658
- throw APIError.badRequest("Email is required");
659
- }
660
-
661
- if (!isValidEmail(req.content.email)) {
662
- throw APIError.unprocessableEntity("Invalid email format");
663
- }
664
-
665
- // Authentication errors
666
- if (!req.authUser) {
667
- throw APIError.unauthorized("Please login first");
668
- }
669
-
670
- if (req.authUser.role !== "admin") {
671
- throw APIError.forbidden("Admin access required");
672
- }
673
-
674
- // Resource errors
675
- const existingUser = await findUserByEmail(req.content.email);
676
- if (existingUser) {
677
- throw APIError.conflict("Email already registered");
678
- }
679
-
680
- // Rate limiting
681
- if (await checkRateLimit(req.authUser.id)) {
682
- throw APIError.tooManyRequests("Maximum 5 users per hour");
683
- }
684
-
685
- try {
686
- const user = await createUser(req.content);
687
- return { user };
688
- } catch (error) {
689
- // Database errors
690
- if (error.code === "STORAGE_FULL") {
691
- throw APIError.insufficientStorage("Database full");
692
- }
693
-
694
- // Generic server error
695
- throw APIError.internalServerError("Failed to create user");
696
- }
697
- }
698
- );
699
- ```
147
+ - [examples/routes/health.ts](examples/routes/health.ts)
148
+ - [examples/routes/events.ts](examples/routes/events.ts)
149
+ - [examples/routes/commerce.ts](examples/routes/commerce.ts)
150
+ - [tests/e2e/test-routes.ts](tests/e2e/test-routes.ts) (broader endpoint patterns)
151
+ - [tests/e2e/test-zod-routes.ts](tests/e2e/test-zod-routes.ts) (Zod + I/O validation flows)
700
152
 
701
153
  ## Contributing
702
154
 
703
- Contributions are welcome! Please feel free to submit a Pull Request.
155
+ Contributions are welcome. Open an issue or pull request.
704
156
 
705
157
  ## License
706
158