http-response-kit 1.0.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.
- package/LICENSE +21 -0
- package/README.md +272 -0
- package/dist/index.d.mts +564 -0
- package/dist/index.d.ts +564 -0
- package/dist/index.js +939 -0
- package/dist/index.mjs +895 -0
- package/package.json +49 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Matteo Teodori
|
|
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,272 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://raw.githubusercontent.com/matteo-teodori/http-response-kit/main/logo.png" alt="http-response-kit logo" width="300" />
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
> 🚀 A professional HTTP error and response formatting library for Node.js
|
|
6
|
+
|
|
7
|
+
[](https://www.typescriptlang.org/)
|
|
8
|
+
[](https://nodejs.org/)
|
|
9
|
+
[](https://opensource.org/licenses/MIT)
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
- ✅ **Complete HTTP Status Codes** - All 4xx and 5xx error codes + 1xx, 2xx, 3xx
|
|
14
|
+
- ✅ **TypeScript First** - Full type safety and IntelliSense support
|
|
15
|
+
- ✅ **Factory Methods** - Convenient `HttpError.notFound()`, `HttpError.badRequest()`, etc.
|
|
16
|
+
- ✅ **Customizable** - Override default messages, add metadata, configure globally
|
|
17
|
+
- ✅ **Zero Dependencies** - Lightweight and fast
|
|
18
|
+
- ✅ **ESM & CommonJS** - Works everywhere
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install http-response-kit
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Quick Start
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
import { HttpError, HttpResponse, configure } from 'http-response-kit';
|
|
30
|
+
|
|
31
|
+
// Throw HTTP errors
|
|
32
|
+
throw HttpError.notFound('User not found');
|
|
33
|
+
throw HttpError.badRequest('Invalid email format');
|
|
34
|
+
throw HttpError.unauthorized('Token expired');
|
|
35
|
+
|
|
36
|
+
// Or use status codes directly
|
|
37
|
+
throw new HttpError(404, { message: 'User not found' });
|
|
38
|
+
throw new HttpError(429, { message: 'Slow down!', retryAfter: 60 });
|
|
39
|
+
|
|
40
|
+
// Format success responses
|
|
41
|
+
const response = HttpResponse.success({
|
|
42
|
+
data: { id: 1, name: 'John' },
|
|
43
|
+
message: 'User retrieved successfully'
|
|
44
|
+
});
|
|
45
|
+
// { success: true, status_code: 200, data: {...}, message: '...' }
|
|
46
|
+
|
|
47
|
+
// Format error responses
|
|
48
|
+
const error = HttpError.notFound('User not found');
|
|
49
|
+
const errorResponse = HttpResponse.error(error);
|
|
50
|
+
// { success: false, status_code: 404, error: { type: 'not_found', ... } }
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Usage with Express
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
import express from 'express';
|
|
57
|
+
import { HttpError, HttpResponse, configure } from 'http-response-kit';
|
|
58
|
+
|
|
59
|
+
const app = express();
|
|
60
|
+
|
|
61
|
+
// Configure library
|
|
62
|
+
configure({
|
|
63
|
+
isDevelopment: process.env.NODE_ENV === 'development',
|
|
64
|
+
includeTimestamp: true,
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
// Your routes
|
|
68
|
+
app.get('/users/:id', async (req, res) => {
|
|
69
|
+
try {
|
|
70
|
+
const user = await findUser(req.params.id);
|
|
71
|
+
if (!user) {
|
|
72
|
+
throw HttpError.notFound('User not found');
|
|
73
|
+
}
|
|
74
|
+
res.json(HttpResponse.ok(user));
|
|
75
|
+
} catch (err) {
|
|
76
|
+
const error = HttpError.fromError(err);
|
|
77
|
+
res.status(error.code).json(HttpResponse.error(error));
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// Global error handler
|
|
82
|
+
app.use((err, req, res, next) => {
|
|
83
|
+
const error = HttpError.fromError(err);
|
|
84
|
+
res.status(error.code).json(HttpResponse.error(error));
|
|
85
|
+
});
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## API Reference
|
|
89
|
+
|
|
90
|
+
### HttpSuccessCode (1xx Informational)
|
|
91
|
+
|
|
92
|
+
| Enum | Code | Description |
|
|
93
|
+
|------|------|-------------|
|
|
94
|
+
| `CONTINUE` | 100 | Continue with request |
|
|
95
|
+
| `SWITCHING_PROTOCOLS` | 101 | Switching protocols |
|
|
96
|
+
| `PROCESSING` | 102 | Processing request |
|
|
97
|
+
| `EARLY_HINTS` | 103 | Early hints |
|
|
98
|
+
|
|
99
|
+
### HttpSuccessCode (2xx Success)
|
|
100
|
+
|
|
101
|
+
| Enum | Code | Description |
|
|
102
|
+
|------|------|-------------|
|
|
103
|
+
| `OK` | 200 | Request succeeded |
|
|
104
|
+
| `CREATED` | 201 | Resource created |
|
|
105
|
+
| `ACCEPTED` | 202 | Request accepted for processing |
|
|
106
|
+
| `NON_AUTHORITATIVE_INFORMATION` | 203 | Non-authoritative information |
|
|
107
|
+
| `NO_CONTENT` | 204 | No content to return |
|
|
108
|
+
| `RESET_CONTENT` | 205 | Reset content |
|
|
109
|
+
| `PARTIAL_CONTENT` | 206 | Partial content |
|
|
110
|
+
| `MULTI_STATUS` | 207 | Multi-status response |
|
|
111
|
+
| `ALREADY_REPORTED` | 208 | Already reported |
|
|
112
|
+
| `IM_USED` | 226 | IM used |
|
|
113
|
+
|
|
114
|
+
### HttpRedirectCode (3xx Redirect)
|
|
115
|
+
|
|
116
|
+
| Enum | Code | Description |
|
|
117
|
+
|------|------|-------------|
|
|
118
|
+
| `MULTIPLE_CHOICES` | 300 | Multiple choices available |
|
|
119
|
+
| `MOVED_PERMANENTLY` | 301 | Resource moved permanently |
|
|
120
|
+
| `FOUND` | 302 | Resource found at different URI |
|
|
121
|
+
| `SEE_OTHER` | 303 | See other resource |
|
|
122
|
+
| `NOT_MODIFIED` | 304 | Resource not modified |
|
|
123
|
+
| `USE_PROXY` | 305 | Use proxy |
|
|
124
|
+
| `TEMPORARY_REDIRECT` | 307 | Temporary redirect |
|
|
125
|
+
| `PERMANENT_REDIRECT` | 308 | Permanent redirect |
|
|
126
|
+
|
|
127
|
+
### HttpError
|
|
128
|
+
|
|
129
|
+
#### Factory Methods (4xx Client Errors)
|
|
130
|
+
|
|
131
|
+
| Method | Code | Description |
|
|
132
|
+
|--------|------|-------------|
|
|
133
|
+
| `HttpError.badRequest()` | 400 | Bad Request |
|
|
134
|
+
| `HttpError.unauthorized()` | 401 | Unauthorized |
|
|
135
|
+
| `HttpError.paymentRequired()` | 402 | Payment Required |
|
|
136
|
+
| `HttpError.forbidden()` | 403 | Forbidden |
|
|
137
|
+
| `HttpError.notFound()` | 404 | Not Found |
|
|
138
|
+
| `HttpError.methodNotAllowed()` | 405 | Method Not Allowed |
|
|
139
|
+
| `HttpError.notAcceptable()` | 406 | Not Acceptable |
|
|
140
|
+
| `HttpError.proxyAuthenticationRequired()` | 407 | Proxy Auth Required |
|
|
141
|
+
| `HttpError.requestTimeout()` | 408 | Request Timeout |
|
|
142
|
+
| `HttpError.conflict()` | 409 | Conflict |
|
|
143
|
+
| `HttpError.gone()` | 410 | Gone |
|
|
144
|
+
| `HttpError.lengthRequired()` | 411 | Length Required |
|
|
145
|
+
| `HttpError.preconditionFailed()` | 412 | Precondition Failed |
|
|
146
|
+
| `HttpError.payloadTooLarge()` | 413 | Payload Too Large |
|
|
147
|
+
| `HttpError.uriTooLong()` | 414 | URI Too Long |
|
|
148
|
+
| `HttpError.unsupportedMediaType()` | 415 | Unsupported Media Type |
|
|
149
|
+
| `HttpError.rangeNotSatisfiable()` | 416 | Range Not Satisfiable |
|
|
150
|
+
| `HttpError.expectationFailed()` | 417 | Expectation Failed |
|
|
151
|
+
| `HttpError.imATeapot()` | 418 | I'm a Teapot |
|
|
152
|
+
| `HttpError.misdirectedRequest()` | 421 | Misdirected Request |
|
|
153
|
+
| `HttpError.unprocessableEntity()` | 422 | Unprocessable Entity |
|
|
154
|
+
| `HttpError.locked()` | 423 | Locked |
|
|
155
|
+
| `HttpError.failedDependency()` | 424 | Failed Dependency |
|
|
156
|
+
| `HttpError.tooEarly()` | 425 | Too Early |
|
|
157
|
+
| `HttpError.upgradeRequired()` | 426 | Upgrade Required |
|
|
158
|
+
| `HttpError.preconditionRequired()` | 428 | Precondition Required |
|
|
159
|
+
| `HttpError.tooManyRequests()` | 429 | Too Many Requests |
|
|
160
|
+
| `HttpError.requestHeaderFieldsTooLarge()` | 431 | Header Fields Too Large |
|
|
161
|
+
| `HttpError.unavailableForLegalReasons()` | 451 | Unavailable For Legal Reasons |
|
|
162
|
+
|
|
163
|
+
#### Factory Methods (5xx Server Errors)
|
|
164
|
+
|
|
165
|
+
| Method | Code | Description |
|
|
166
|
+
|--------|------|-------------|
|
|
167
|
+
| `HttpError.internalServerError()` | 500 | Internal Server Error |
|
|
168
|
+
| `HttpError.notImplemented()` | 501 | Not Implemented |
|
|
169
|
+
| `HttpError.badGateway()` | 502 | Bad Gateway |
|
|
170
|
+
| `HttpError.serviceUnavailable()` | 503 | Service Unavailable |
|
|
171
|
+
| `HttpError.gatewayTimeout()` | 504 | Gateway Timeout |
|
|
172
|
+
| `HttpError.httpVersionNotSupported()` | 505 | HTTP Version Not Supported |
|
|
173
|
+
| `HttpError.variantAlsoNegotiates()` | 506 | Variant Also Negotiates |
|
|
174
|
+
| `HttpError.insufficientStorage()` | 507 | Insufficient Storage |
|
|
175
|
+
| `HttpError.loopDetected()` | 508 | Loop Detected |
|
|
176
|
+
| `HttpError.bandwidthLimitExceeded()` | 509 | Bandwidth Limit Exceeded |
|
|
177
|
+
| `HttpError.notExtended()` | 510 | Not Extended |
|
|
178
|
+
| `HttpError.networkAuthenticationRequired()` | 511 | Network Auth Required |
|
|
179
|
+
|
|
180
|
+
#### Utility Methods
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
// Convert any error to HttpError
|
|
184
|
+
const httpError = HttpError.fromError(unknownError);
|
|
185
|
+
|
|
186
|
+
// Check if error is HttpError
|
|
187
|
+
if (HttpError.isHttpError(error)) { ... }
|
|
188
|
+
|
|
189
|
+
// Check error category
|
|
190
|
+
error.isClientError(); // 4xx
|
|
191
|
+
error.isServerError(); // 5xx
|
|
192
|
+
|
|
193
|
+
// Add metadata
|
|
194
|
+
throw HttpError.badRequest('Validation failed', {
|
|
195
|
+
fields: ['email', 'password']
|
|
196
|
+
});
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### HttpResponse
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
// Success responses
|
|
203
|
+
HttpResponse.success({ data, message, statusCode, metadata });
|
|
204
|
+
HttpResponse.ok(data, message);
|
|
205
|
+
HttpResponse.created(data, message);
|
|
206
|
+
HttpResponse.accepted(data, message);
|
|
207
|
+
HttpResponse.noContent();
|
|
208
|
+
|
|
209
|
+
// Error responses
|
|
210
|
+
HttpResponse.error(httpError);
|
|
211
|
+
HttpResponse.fromError(anyError);
|
|
212
|
+
|
|
213
|
+
// Paginated responses
|
|
214
|
+
HttpResponse.paginated(items, {
|
|
215
|
+
page: 1,
|
|
216
|
+
limit: 10,
|
|
217
|
+
total: 100
|
|
218
|
+
});
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### Configuration
|
|
222
|
+
|
|
223
|
+
```typescript
|
|
224
|
+
import { configure } from 'http-response-kit';
|
|
225
|
+
|
|
226
|
+
configure({
|
|
227
|
+
// Enable stack traces in error responses
|
|
228
|
+
isDevelopment: true,
|
|
229
|
+
|
|
230
|
+
// Include timestamps in all responses
|
|
231
|
+
includeTimestamp: true,
|
|
232
|
+
|
|
233
|
+
// Custom default messages per status code
|
|
234
|
+
customMessages: {
|
|
235
|
+
404: 'Oops! This page went on vacation 🏝️',
|
|
236
|
+
500: 'Well, this is embarrassing... 🤖'
|
|
237
|
+
},
|
|
238
|
+
|
|
239
|
+
// Custom response transformer
|
|
240
|
+
responseTransformer: (response) => ({
|
|
241
|
+
...response,
|
|
242
|
+
api_version: 'v1'
|
|
243
|
+
})
|
|
244
|
+
});
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
## Status Code Enums
|
|
248
|
+
|
|
249
|
+
```typescript
|
|
250
|
+
import {
|
|
251
|
+
HttpSuccessCode,
|
|
252
|
+
HttpClientErrorCode,
|
|
253
|
+
HttpServerErrorCode,
|
|
254
|
+
HttpRedirectCode,
|
|
255
|
+
HttpInfoCode
|
|
256
|
+
} from 'http-response-kit';
|
|
257
|
+
|
|
258
|
+
// Use enums for type safety
|
|
259
|
+
HttpSuccessCode.OK // 200
|
|
260
|
+
HttpSuccessCode.CREATED // 201
|
|
261
|
+
HttpSuccessCode.NO_CONTENT // 204
|
|
262
|
+
HttpClientErrorCode.NOT_FOUND // 404
|
|
263
|
+
HttpServerErrorCode.INTERNAL_SERVER_ERROR // 500
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
## Changelog
|
|
267
|
+
|
|
268
|
+
See [CHANGELOG.md](CHANGELOG.md) for detailed release notes.
|
|
269
|
+
|
|
270
|
+
## License
|
|
271
|
+
|
|
272
|
+
MIT © [Matteo Teodori](https://github.com/matteo-teodori)
|