vector-framework 1.0.0 → 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 (104) hide show
  1. package/README.md +87 -634
  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 +5 -2
  5. package/dist/cache/manager.d.ts.map +1 -1
  6. package/dist/cache/manager.js +21 -12
  7. package/dist/cache/manager.js.map +1 -1
  8. package/dist/cli/index.js +60 -126
  9. package/dist/cli/index.js.map +1 -1
  10. package/dist/cli/option-resolution.d.ts +4 -0
  11. package/dist/cli/option-resolution.d.ts.map +1 -0
  12. package/dist/cli/option-resolution.js +28 -0
  13. package/dist/cli/option-resolution.js.map +1 -0
  14. package/dist/cli.js +2774 -599
  15. package/dist/constants/index.d.ts +3 -0
  16. package/dist/constants/index.d.ts.map +1 -1
  17. package/dist/constants/index.js +6 -0
  18. package/dist/constants/index.js.map +1 -1
  19. package/dist/core/config-loader.d.ts +2 -2
  20. package/dist/core/config-loader.d.ts.map +1 -1
  21. package/dist/core/config-loader.js +18 -18
  22. package/dist/core/config-loader.js.map +1 -1
  23. package/dist/core/router.d.ts +41 -15
  24. package/dist/core/router.d.ts.map +1 -1
  25. package/dist/core/router.js +465 -150
  26. package/dist/core/router.js.map +1 -1
  27. package/dist/core/server.d.ts +17 -3
  28. package/dist/core/server.d.ts.map +1 -1
  29. package/dist/core/server.js +274 -33
  30. package/dist/core/server.js.map +1 -1
  31. package/dist/core/vector.d.ts +9 -8
  32. package/dist/core/vector.d.ts.map +1 -1
  33. package/dist/core/vector.js +40 -32
  34. package/dist/core/vector.js.map +1 -1
  35. package/dist/dev/route-generator.d.ts.map +1 -1
  36. package/dist/dev/route-generator.js.map +1 -1
  37. package/dist/dev/route-scanner.d.ts +1 -1
  38. package/dist/dev/route-scanner.d.ts.map +1 -1
  39. package/dist/dev/route-scanner.js +37 -43
  40. package/dist/dev/route-scanner.js.map +1 -1
  41. package/dist/http.d.ts +14 -14
  42. package/dist/http.d.ts.map +1 -1
  43. package/dist/http.js +84 -84
  44. package/dist/http.js.map +1 -1
  45. package/dist/index.d.ts +3 -3
  46. package/dist/index.js +1314 -8
  47. package/dist/index.mjs +1314 -8
  48. package/dist/middleware/manager.d.ts +1 -1
  49. package/dist/middleware/manager.d.ts.map +1 -1
  50. package/dist/middleware/manager.js +4 -0
  51. package/dist/middleware/manager.js.map +1 -1
  52. package/dist/openapi/docs-ui.d.ts +2 -0
  53. package/dist/openapi/docs-ui.d.ts.map +1 -0
  54. package/dist/openapi/docs-ui.js +1313 -0
  55. package/dist/openapi/docs-ui.js.map +1 -0
  56. package/dist/openapi/generator.d.ts +12 -0
  57. package/dist/openapi/generator.d.ts.map +1 -0
  58. package/dist/openapi/generator.js +273 -0
  59. package/dist/openapi/generator.js.map +1 -0
  60. package/dist/types/index.d.ts +70 -11
  61. package/dist/types/index.d.ts.map +1 -1
  62. package/dist/types/standard-schema.d.ts +118 -0
  63. package/dist/types/standard-schema.d.ts.map +1 -0
  64. package/dist/types/standard-schema.js +2 -0
  65. package/dist/types/standard-schema.js.map +1 -0
  66. package/dist/utils/cors.d.ts +13 -0
  67. package/dist/utils/cors.d.ts.map +1 -0
  68. package/dist/utils/cors.js +89 -0
  69. package/dist/utils/cors.js.map +1 -0
  70. package/dist/utils/path.d.ts +7 -0
  71. package/dist/utils/path.d.ts.map +1 -1
  72. package/dist/utils/path.js +14 -3
  73. package/dist/utils/path.js.map +1 -1
  74. package/dist/utils/schema-validation.d.ts +31 -0
  75. package/dist/utils/schema-validation.d.ts.map +1 -0
  76. package/dist/utils/schema-validation.js +77 -0
  77. package/dist/utils/schema-validation.js.map +1 -0
  78. package/dist/utils/validation.d.ts.map +1 -1
  79. package/dist/utils/validation.js +1 -0
  80. package/dist/utils/validation.js.map +1 -1
  81. package/package.json +24 -19
  82. package/src/auth/protected.ts +3 -13
  83. package/src/cache/manager.ts +25 -30
  84. package/src/cli/index.ts +62 -141
  85. package/src/cli/option-resolution.ts +40 -0
  86. package/src/constants/index.ts +7 -0
  87. package/src/core/config-loader.ts +20 -22
  88. package/src/core/router.ts +535 -155
  89. package/src/core/server.ts +354 -45
  90. package/src/core/vector.ts +71 -61
  91. package/src/dev/route-generator.ts +1 -3
  92. package/src/dev/route-scanner.ts +38 -51
  93. package/src/http.ts +117 -187
  94. package/src/index.ts +3 -3
  95. package/src/middleware/manager.ts +8 -11
  96. package/src/openapi/assets/tailwindcdn.js +83 -0
  97. package/src/openapi/docs-ui.ts +1317 -0
  98. package/src/openapi/generator.ts +359 -0
  99. package/src/types/index.ts +104 -17
  100. package/src/types/standard-schema.ts +147 -0
  101. package/src/utils/cors.ts +101 -0
  102. package/src/utils/path.ts +19 -4
  103. package/src/utils/schema-validation.ts +123 -0
  104. package/src/utils/validation.ts +1 -0
package/README.md CHANGED
@@ -1,705 +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
- - **70,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:
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:
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
- "_*.ts", // Exclude files starting with underscore
460
- ],
461
- };
117
+ );
462
118
  ```
463
119
 
464
- ## Performance
465
-
466
- Vector achieves exceptional performance through:
467
-
468
- - **Bun Runtime**: Native TypeScript execution without transpilation
469
- - **Minimal Dependencies**: Only itty-router (3KB) as dependency
470
- - **Optimized Routing**: Efficient regex-based route matching
471
- - **Smart Caching**: Built-in response caching with configurable TTL
120
+ Enable OpenAPI in `vector.config.ts`:
472
121
 
473
- Benchmarks show Vector handling **70,000+ requests/second** on standard hardware.
474
-
475
- ## Why Vector?
476
-
477
- ### For Encore Users
478
- Love Encore's declarative API design but need more flexibility? Vector provides the same developer experience with the freedom to deploy anywhere Bun runs.
479
-
480
- ### For Express/Fastify Users
481
- Tired of middleware chains and verbose configurations? Vector's declarative approach makes APIs cleaner and more maintainable.
482
-
483
- ### For New Projects
484
- Starting fresh? Vector gives you production-ready features from day one with minimal configuration.
485
-
486
- ## Error Reference
487
-
488
- Vector provides comprehensive error responses for all HTTP status codes. All errors return a consistent format:
489
-
490
- ```json
491
- {
492
- "error": true,
493
- "message": "Error message",
494
- "statusCode": 400,
495
- "timestamp": "2025-01-01T00:00:00.000Z"
122
+ ```ts
123
+ openapi: {
124
+ enabled: true,
125
+ path: '/openapi.json',
126
+ docs: false,
496
127
  }
497
128
  ```
498
129
 
499
- ### Client Errors (4xx)
500
-
501
- ```typescript
502
- import { APIError } from "vector-framework";
503
-
504
- // 400 Bad Request
505
- APIError.badRequest("Invalid input data");
506
-
507
- // 401 Unauthorized
508
- APIError.unauthorized("Authentication required");
509
-
510
- // 402 Payment Required
511
- APIError.paymentRequired("Subscription expired");
512
-
513
- // 403 Forbidden
514
- APIError.forbidden("Access denied");
515
-
516
- // 404 Not Found
517
- APIError.notFound("Resource not found");
518
-
519
- // 405 Method Not Allowed
520
- APIError.methodNotAllowed("POST not allowed on this endpoint");
521
-
522
- // 406 Not Acceptable
523
- APIError.notAcceptable("Cannot produce requested content type");
524
-
525
- // 408 Request Timeout
526
- APIError.requestTimeout("Request took too long");
527
-
528
- // 409 Conflict
529
- APIError.conflict("Resource already exists");
530
-
531
- // 410 Gone
532
- APIError.gone("Resource permanently deleted");
533
-
534
- // 411 Length Required
535
- APIError.lengthRequired("Content-Length header required");
536
-
537
- // 412 Precondition Failed
538
- APIError.preconditionFailed("ETag mismatch");
539
-
540
- // 413 Payload Too Large
541
- APIError.payloadTooLarge("Request body exceeds limit");
542
-
543
- // 414 URI Too Long
544
- APIError.uriTooLong("URL exceeds maximum length");
545
-
546
- // 415 Unsupported Media Type
547
- APIError.unsupportedMediaType("Content-Type not supported");
548
-
549
- // 416 Range Not Satisfiable
550
- APIError.rangeNotSatisfiable("Requested range cannot be satisfied");
551
-
552
- // 417 Expectation Failed
553
- APIError.expectationFailed("Expect header requirements not met");
554
-
555
- // 418 I'm a Teapot
556
- APIError.imATeapot("I refuse to brew coffee");
557
-
558
- // 421 Misdirected Request
559
- APIError.misdirectedRequest("Request sent to wrong server");
560
-
561
- // 422 Unprocessable Entity
562
- APIError.unprocessableEntity("Validation failed");
563
-
564
- // 423 Locked
565
- APIError.locked("Resource is locked");
566
-
567
- // 424 Failed Dependency
568
- APIError.failedDependency("Dependent request failed");
569
-
570
- // 425 Too Early
571
- APIError.tooEarly("Request is too early");
572
-
573
- // 426 Upgrade Required
574
- APIError.upgradeRequired("Protocol upgrade required");
575
-
576
- // 428 Precondition Required
577
- APIError.preconditionRequired("Precondition headers required");
578
-
579
- // 429 Too Many Requests
580
- APIError.tooManyRequests("Rate limit exceeded");
581
-
582
- // 431 Request Header Fields Too Large
583
- APIError.requestHeaderFieldsTooLarge("Headers too large");
584
-
585
- // 451 Unavailable For Legal Reasons
586
- APIError.unavailableForLegalReasons("Content blocked for legal reasons");
587
- ```
588
-
589
- ### Server Errors (5xx)
590
-
591
- ```typescript
592
- // 500 Internal Server Error
593
- APIError.internalServerError("Something went wrong");
594
-
595
- // 501 Not Implemented
596
- APIError.notImplemented("Feature not yet available");
597
-
598
- // 502 Bad Gateway
599
- APIError.badGateway("Upstream server error");
600
-
601
- // 503 Service Unavailable
602
- APIError.serviceUnavailable("Service temporarily down");
603
-
604
- // 504 Gateway Timeout
605
- APIError.gatewayTimeout("Upstream server timeout");
606
-
607
- // 505 HTTP Version Not Supported
608
- APIError.httpVersionNotSupported("HTTP/3 not supported");
609
-
610
- // 506 Variant Also Negotiates
611
- APIError.variantAlsoNegotiates("Content negotiation error");
612
-
613
- // 507 Insufficient Storage
614
- APIError.insufficientStorage("Server storage full");
615
-
616
- // 508 Loop Detected
617
- APIError.loopDetected("Infinite loop detected");
618
-
619
- // 510 Not Extended
620
- APIError.notExtended("Extension required");
621
-
622
- // 511 Network Authentication Required
623
- APIError.networkAuthenticationRequired("Network login required");
624
- ```
625
-
626
- ### Convenience Aliases
627
-
628
- ```typescript
629
- // Alias for 422 Unprocessable Entity
630
- APIError.invalidArgument("Field 'email' is required");
631
-
632
- // Alias for 429 Too Many Requests
633
- APIError.rateLimitExceeded("Try again in 60 seconds");
634
-
635
- // Alias for 503 Service Unavailable
636
- APIError.maintenance("Scheduled maintenance in progress");
637
- ```
638
-
639
- ### Custom Errors
130
+ ## Documentation
640
131
 
641
- ```typescript
642
- // Create error with any status code
643
- APIError.custom(456, "Custom error message");
132
+ Start here for deeper guides:
644
133
 
645
- // With custom content type
646
- APIError.custom(400, "Invalid XML", "application/xml");
647
- ```
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)
648
144
 
649
- ### Usage in Routes
145
+ ## Examples
650
146
 
651
- ```typescript
652
- export const example = route(
653
- { method: "POST", path: "/api/users" },
654
- async (req) => {
655
- // Validation errors
656
- if (!req.content?.email) {
657
- throw APIError.badRequest("Email is required");
658
- }
659
-
660
- if (!isValidEmail(req.content.email)) {
661
- throw APIError.unprocessableEntity("Invalid email format");
662
- }
663
-
664
- // Authentication errors
665
- if (!req.authUser) {
666
- throw APIError.unauthorized("Please login first");
667
- }
668
-
669
- if (req.authUser.role !== "admin") {
670
- throw APIError.forbidden("Admin access required");
671
- }
672
-
673
- // Resource errors
674
- const existingUser = await findUserByEmail(req.content.email);
675
- if (existingUser) {
676
- throw APIError.conflict("Email already registered");
677
- }
678
-
679
- // Rate limiting
680
- if (await checkRateLimit(req.authUser.id)) {
681
- throw APIError.tooManyRequests("Maximum 5 users per hour");
682
- }
683
-
684
- try {
685
- const user = await createUser(req.content);
686
- return { user };
687
- } catch (error) {
688
- // Database errors
689
- if (error.code === "STORAGE_FULL") {
690
- throw APIError.insufficientStorage("Database full");
691
- }
692
-
693
- // Generic server error
694
- throw APIError.internalServerError("Failed to create user");
695
- }
696
- }
697
- );
698
- ```
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)
699
152
 
700
153
  ## Contributing
701
154
 
702
- Contributions are welcome! Please feel free to submit a Pull Request.
155
+ Contributions are welcome. Open an issue or pull request.
703
156
 
704
157
  ## License
705
158