@b9g/http-errors 0.1.1 → 0.1.3

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 (2) hide show
  1. package/README.md +314 -0
  2. package/package.json +2 -2
package/README.md ADDED
@@ -0,0 +1,314 @@
1
+ # @b9g/http-errors
2
+
3
+ Standard HTTP error responses with proper status codes and web platform Response objects.
4
+
5
+ ## Features
6
+
7
+ - **Standard HTTP Errors**: Pre-defined error classes for common HTTP status codes
8
+ - **Web Platform Response**: Returns proper Response objects, not thrown exceptions
9
+ - **Consistent API**: Uniform interface across all error types
10
+ - **TypeScript Support**: Full type definitions for all error classes
11
+ - **Lightweight**: Minimal dependencies, works everywhere
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ npm install @b9g/http-errors
17
+ ```
18
+
19
+ ## Quick Start
20
+
21
+ ```javascript
22
+ import {
23
+ NotFound,
24
+ BadRequest,
25
+ Unauthorized,
26
+ InternalServerError
27
+ } from '@b9g/http-errors';
28
+
29
+ // Create error responses
30
+ const notFound = NotFound('Page not found');
31
+ const badRequest = BadRequest('Invalid input data');
32
+ const unauthorized = Unauthorized('Authentication required');
33
+ const serverError = InternalServerError('Database connection failed');
34
+
35
+ // All return Response objects
36
+ console.log(notFound instanceof Response); // true
37
+ console.log(notFound.status); // 404
38
+ ```
39
+
40
+ ## Available Error Classes
41
+
42
+ ### Client Errors (4xx)
43
+
44
+ ```javascript
45
+ import {
46
+ BadRequest, // 400
47
+ Unauthorized, // 401
48
+ PaymentRequired, // 402
49
+ Forbidden, // 403
50
+ NotFound, // 404
51
+ MethodNotAllowed, // 405
52
+ NotAcceptable, // 406
53
+ RequestTimeout, // 408
54
+ Conflict, // 409
55
+ Gone, // 410
56
+ LengthRequired, // 411
57
+ PreconditionFailed, // 412
58
+ PayloadTooLarge, // 413
59
+ URITooLong, // 414
60
+ UnsupportedMediaType, // 415
61
+ RangeNotSatisfiable, // 416
62
+ ExpectationFailed, // 417
63
+ ImATeapot, // 418
64
+ UnprocessableEntity, // 422
65
+ TooManyRequests, // 429
66
+ } from '@b9g/http-errors';
67
+ ```
68
+
69
+ ### Server Errors (5xx)
70
+
71
+ ```javascript
72
+ import {
73
+ InternalServerError, // 500
74
+ NotImplemented, // 501
75
+ BadGateway, // 502
76
+ ServiceUnavailable, // 503
77
+ GatewayTimeout, // 504
78
+ HTTPVersionNotSupported, // 505
79
+ } from '@b9g/http-errors';
80
+ ```
81
+
82
+ ## Usage Examples
83
+
84
+ ### Basic Error Responses
85
+
86
+ ```javascript
87
+ import { NotFound, BadRequest } from '@b9g/http-errors';
88
+
89
+ // Simple message
90
+ const error1 = NotFound('User not found');
91
+
92
+ // With additional details
93
+ const error2 = BadRequest('Invalid email format', {
94
+ field: 'email',
95
+ code: 'INVALID_FORMAT'
96
+ });
97
+ ```
98
+
99
+ ### Router Integration
100
+
101
+ ```javascript
102
+ import { Router } from '@b9g/router';
103
+ import { NotFound, BadRequest, Unauthorized } from '@b9g/http-errors';
104
+
105
+ const router = new Router();
106
+
107
+ router.get('/users/:id', async (request, context) => {
108
+ const { id } = context.params;
109
+
110
+ // Validate input
111
+ if (!id || isNaN(Number(id))) {
112
+ return BadRequest('Invalid user ID');
113
+ }
114
+
115
+ // Check authentication
116
+ if (!request.headers.get('authorization')) {
117
+ return Unauthorized('Authentication required');
118
+ }
119
+
120
+ // Find user
121
+ const user = await db.users.find(id);
122
+ if (!user) {
123
+ return NotFound('User not found');
124
+ }
125
+
126
+ return Response.json(user);
127
+ });
128
+ ```
129
+
130
+ ### Middleware Error Handling
131
+
132
+ ```javascript
133
+ router.use(async (request, context, next) => {
134
+ try {
135
+ return await next();
136
+ } catch (error) {
137
+ console.error('Request failed:', error);
138
+ return InternalServerError('Something went wrong');
139
+ }
140
+ });
141
+ ```
142
+
143
+ ### Custom Error Details
144
+
145
+ ```javascript
146
+ import { BadRequest, Conflict } from '@b9g/http-errors';
147
+
148
+ // With error code
149
+ const validationError = BadRequest('Validation failed', {
150
+ code: 'VALIDATION_ERROR',
151
+ fields: ['email', 'password']
152
+ });
153
+
154
+ // With retry information
155
+ const rateLimitError = TooManyRequests('Rate limit exceeded', {
156
+ retryAfter: 60,
157
+ limit: 100,
158
+ window: 3600
159
+ });
160
+
161
+ // With conflict details
162
+ const duplicateError = Conflict('Email already exists', {
163
+ field: 'email',
164
+ value: 'user@example.com'
165
+ });
166
+ ```
167
+
168
+ ## API Reference
169
+
170
+ ### Error Functions
171
+
172
+ All error functions follow the same signature:
173
+
174
+ ```typescript
175
+ function ErrorName(message?: string, details?: any): Response
176
+ ```
177
+
178
+ #### Parameters
179
+
180
+ - `message` (optional): Human-readable error message
181
+ - `details` (optional): Additional error details (serialized as JSON)
182
+
183
+ #### Returns
184
+
185
+ Returns a `Response` object with:
186
+ - Appropriate HTTP status code
187
+ - `Content-Type: application/json`
188
+ - JSON body containing error information
189
+
190
+ ### Response Format
191
+
192
+ ```javascript
193
+ {
194
+ "error": {
195
+ "type": "NotFound",
196
+ "message": "User not found",
197
+ "status": 404,
198
+ "details": {
199
+ // Any additional details provided
200
+ }
201
+ }
202
+ }
203
+ ```
204
+
205
+ ## TypeScript Support
206
+
207
+ Full TypeScript definitions included:
208
+
209
+ ```typescript
210
+ import type { ErrorResponse } from '@b9g/http-errors';
211
+
212
+ function handleError(): ErrorResponse {
213
+ return NotFound('Resource not found');
214
+ }
215
+
216
+ // ErrorResponse extends Response
217
+ const response: Response = handleError();
218
+ ```
219
+
220
+ ## Integration Examples
221
+
222
+ ### API Error Handling
223
+
224
+ ```javascript
225
+ import {
226
+ BadRequest,
227
+ NotFound,
228
+ Conflict,
229
+ InternalServerError
230
+ } from '@b9g/http-errors';
231
+
232
+ router.post('/api/users', async (request) => {
233
+ try {
234
+ const data = await request.json();
235
+
236
+ // Validation
237
+ if (!data.email) {
238
+ return BadRequest('Email is required');
239
+ }
240
+
241
+ // Check for existing user
242
+ const existing = await db.users.findByEmail(data.email);
243
+ if (existing) {
244
+ return Conflict('Email already registered');
245
+ }
246
+
247
+ // Create user
248
+ const user = await db.users.create(data);
249
+ return Response.json(user, { status: 201 });
250
+
251
+ } catch (error) {
252
+ return InternalServerError('Failed to create user');
253
+ }
254
+ });
255
+ ```
256
+
257
+ ### Auth Middleware
258
+
259
+ ```javascript
260
+ import { Unauthorized, Forbidden } from '@b9g/http-errors';
261
+
262
+ const authMiddleware = async (request, context, next) => {
263
+ const token = request.headers.get('authorization');
264
+
265
+ if (!token) {
266
+ return Unauthorized('Authentication required');
267
+ }
268
+
269
+ try {
270
+ const user = await verifyToken(token);
271
+ context.user = user;
272
+ return await next();
273
+ } catch (error) {
274
+ return Forbidden('Invalid or expired token');
275
+ }
276
+ };
277
+
278
+ router.use('/api/admin/*', authMiddleware);
279
+ ```
280
+
281
+ ### Input Validation
282
+
283
+ ```javascript
284
+ import { BadRequest } from '@b9g/http-errors';
285
+
286
+ function validateUser(data) {
287
+ const errors = [];
288
+
289
+ if (!data.email) errors.push('email is required');
290
+ if (!data.password) errors.push('password is required');
291
+ if (data.password && data.password.length < 8) {
292
+ errors.push('password must be at least 8 characters');
293
+ }
294
+
295
+ if (errors.length > 0) {
296
+ return BadRequest('Validation failed', { errors });
297
+ }
298
+
299
+ return null; // Valid
300
+ }
301
+
302
+ router.post('/register', async (request) => {
303
+ const data = await request.json();
304
+
305
+ const validationError = validateUser(data);
306
+ if (validationError) return validationError;
307
+
308
+ // Process valid data...
309
+ });
310
+ ```
311
+
312
+ ## License
313
+
314
+ MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@b9g/http-errors",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "HTTP error classes for web applications",
5
5
  "keywords": [
6
6
  "http",
@@ -10,7 +10,7 @@
10
10
  ],
11
11
  "dependencies": {},
12
12
  "devDependencies": {
13
- "@b9g/libuild": "^0.1.10",
13
+ "@b9g/libuild": "^0.1.11",
14
14
  "bun-types": "latest"
15
15
  },
16
16
  "type": "module",