express-resforge 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/CHANGELOG.md +27 -0
- package/LICENSE +21 -0
- package/README.md +309 -0
- package/dist/constants/defaultMessages.d.ts +5 -0
- package/dist/constants/defaultMessages.js +29 -0
- package/dist/constants/httpStatus.d.ts +28 -0
- package/dist/constants/httpStatus.js +33 -0
- package/dist/constants/responseCodes.d.ts +22 -0
- package/dist/constants/responseCodes.js +25 -0
- package/dist/core/context.d.ts +36 -0
- package/dist/core/context.js +45 -0
- package/dist/core/formatter.d.ts +7 -0
- package/dist/core/formatter.js +17 -0
- package/dist/core/pluginManager.d.ts +27 -0
- package/dist/core/pluginManager.js +37 -0
- package/dist/core/responseBuilder.d.ts +32 -0
- package/dist/core/responseBuilder.js +107 -0
- package/dist/core/responseFactory.d.ts +12 -0
- package/dist/core/responseFactory.js +52 -0
- package/dist/formatter/axiosFormatter.d.ts +8 -0
- package/dist/formatter/axiosFormatter.js +12 -0
- package/dist/formatter/firebaseFormatter.d.ts +6 -0
- package/dist/formatter/firebaseFormatter.js +19 -0
- package/dist/formatter/joiFormatter.d.ts +8 -0
- package/dist/formatter/joiFormatter.js +26 -0
- package/dist/formatter/mongooseFormatter.d.ts +2 -0
- package/dist/formatter/mongooseFormatter.js +20 -0
- package/dist/formatter/prismaFormatter.d.ts +15 -0
- package/dist/formatter/prismaFormatter.js +49 -0
- package/dist/formatter/zodFormatter.d.ts +9 -0
- package/dist/formatter/zodFormatter.js +27 -0
- package/dist/helpers/cache.d.ts +2 -0
- package/dist/helpers/cache.js +6 -0
- package/dist/helpers/cookies.d.ts +2 -0
- package/dist/helpers/cookies.js +6 -0
- package/dist/helpers/download.d.ts +2 -0
- package/dist/helpers/download.js +6 -0
- package/dist/helpers/errors.d.ts +10 -0
- package/dist/helpers/errors.js +21 -0
- package/dist/helpers/headers.d.ts +2 -0
- package/dist/helpers/headers.js +7 -0
- package/dist/helpers/health.d.ts +2 -0
- package/dist/helpers/health.js +10 -0
- package/dist/helpers/meta.d.ts +2 -0
- package/dist/helpers/meta.js +11 -0
- package/dist/helpers/pagination.d.ts +9 -0
- package/dist/helpers/pagination.js +14 -0
- package/dist/helpers/redirect.d.ts +2 -0
- package/dist/helpers/redirect.js +6 -0
- package/dist/helpers/success.d.ts +3 -0
- package/dist/helpers/success.js +7 -0
- package/dist/helpers/validation.d.ts +2 -0
- package/dist/helpers/validation.js +6 -0
- package/dist/index.d.ts +90 -0
- package/dist/index.js +74 -0
- package/dist/middleware/errorHandler.d.ts +9 -0
- package/dist/middleware/errorHandler.js +90 -0
- package/dist/middleware/requestId.d.ts +16 -0
- package/dist/middleware/requestId.js +18 -0
- package/dist/middleware/requestTimer.d.ts +6 -0
- package/dist/middleware/requestTimer.js +26 -0
- package/dist/middleware/responseMiddleware.d.ts +7 -0
- package/dist/middleware/responseMiddleware.js +93 -0
- package/dist/plugins/pluginAPI.d.ts +7 -0
- package/dist/plugins/pluginAPI.js +12 -0
- package/dist/types/config.d.ts +52 -0
- package/dist/types/config.js +22 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.js +19 -0
- package/dist/types/plugin.d.ts +11 -0
- package/dist/types/plugin.js +2 -0
- package/dist/types/responses.d.ts +72 -0
- package/dist/types/responses.js +6 -0
- package/dist/utils/cleanObject.d.ts +11 -0
- package/dist/utils/cleanObject.js +26 -0
- package/dist/utils/deepMerge.d.ts +12 -0
- package/dist/utils/deepMerge.js +43 -0
- package/dist/utils/helpers.d.ts +4 -0
- package/dist/utils/helpers.js +15 -0
- package/dist/utils/time.d.ts +4 -0
- package/dist/utils/time.js +11 -0
- package/dist/utils/uuid.d.ts +9 -0
- package/dist/utils/uuid.js +24 -0
- package/dist/version.d.ts +4 -0
- package/dist/version.js +7 -0
- package/package.json +68 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## [1.0.0] - 2026-07-13
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- **Core Orchestration:** Initialized global `apiKit` gateway tracking configuration framework supporting unified response structures.
|
|
14
|
+
- **Fluent Builder System:** Added `ResponseBuilder` supporting fluent chaining methods for metadata payloads, business response codes, cookies, and HTTP headers.
|
|
15
|
+
- **Asynchronous Resiliency:** Implemented `apiKit.async()` higher-order function wrappers to intercept unhandled asynchronous promise rejections across application routes.
|
|
16
|
+
- **Context Isolation Engine:** Integrated low-overhead `AsyncLocalStorage` via `context.ts` to manage unique correlation transaction IDs and tracking timers across requests.
|
|
17
|
+
- **Ecosystem Validation Adapters:** Added out-of-the-box data normalization error formatters for third-party libraries: `Zod`, `Joi`, `Mongoose`, `Prisma`, `Axios`, and `Firebase`.
|
|
18
|
+
- **Comprehensive Testing Infrastructure:** Built out integration test runners (`tests/integration/apiKit.test.ts`) and targeted optimization paths (`tests/unit/formatters.test.ts`, `tests/unit/coverageHitter.test.ts`).
|
|
19
|
+
- **SWC Compilation Pipeline:** Migrated test execution layer to `@swc/jest` to reduce runtime processing latency (~0.45s execution benchmarks).
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
- **HTTP Node Lifecycle Crash:** Patched response timing calculation bugs in `requestTimer.ts` by safely overriding the native `res.end` pointer to bind headers before network streams freeze (resolving "Cannot set headers after they are sent to the client" errors).
|
|
23
|
+
- **TypeScript Type Safety Mismatch:** Resolved dynamic compiler inference properties blocks during deep objects merging by wrapping the `deepMerge` validation tests into explicit target typings.
|
|
24
|
+
|
|
25
|
+
### Safety
|
|
26
|
+
- **Prototype Pollution Shielding:** Hardened `deepMerge.ts` utility configurations to completely block malicious object property injections via `__proto__` and `constructor` access routes.
|
|
27
|
+
- **Information Leak Sanitization:** Implemented stack trace masking filters across production execution mode states inside the global boundary error catcher framework.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Dream Mythic Studio
|
|
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,309 @@
|
|
|
1
|
+
|
|
2
|
+
# express-resforge
|
|
3
|
+
|
|
4
|
+
[](https://www.npmjs.com/package/express-resforge)
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
[](https://github.com/vaibhavdhake123/express-resforge)
|
|
7
|
+
|
|
8
|
+
An enterprise-quality, zero-dependency engine designed to standardize API response envelopes, orchestrate asynchronous error pipelines, format third-party library errors, and trace high-precision performance metrics across Express microservices.
|
|
9
|
+
|
|
10
|
+
Compatible out-of-the-box with **Express v4**, **Express v5**, **ESM**, and **CommonJS** targets running on Node.js 18+.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## 🏗️ Core Architecture Flow
|
|
15
|
+
|
|
16
|
+
When an HTTP request enters your application, `express-resforge` handles the lifecycle safely without causing memory overhead or thread-blocking issues:
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
[Incoming Request]
|
|
22
|
+
│
|
|
23
|
+
▼
|
|
24
|
+
┌────────────────────────────────┐
|
|
25
|
+
│ apiKit.requestId() & timer() │ ──► Allocates transaction UUIDs & high-precision tracking
|
|
26
|
+
└────────────────────────────────┘
|
|
27
|
+
│
|
|
28
|
+
▼
|
|
29
|
+
┌────────────────────────────────┐
|
|
30
|
+
│ apiKit.middleware() │ ──► Dynamically injects semantic shortcuts onto `res`
|
|
31
|
+
└────────────────────────────────┘
|
|
32
|
+
│
|
|
33
|
+
▼
|
|
34
|
+
┌────────────────────────────────┐
|
|
35
|
+
│ App Business Controllers │ ──► Run workflows through fluent builders (e.g., `res.success()`)
|
|
36
|
+
└────────────────────────────────┘
|
|
37
|
+
│
|
|
38
|
+
▼
|
|
39
|
+
┌────────────────────────────────┐
|
|
40
|
+
│ Plugin Interceptors │ ──► Append global telemetry/metadata on the fly
|
|
41
|
+
└────────────────────────────────┘
|
|
42
|
+
│
|
|
43
|
+
▼
|
|
44
|
+
┌────────────────────────────────┐
|
|
45
|
+
│ apiKit.errorHandler() │ ──► Catches runtime failures & masks internal stack traces
|
|
46
|
+
└────────────────────────────────┘
|
|
47
|
+
│
|
|
48
|
+
▼
|
|
49
|
+
[Outbound Standardized JSON]
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## 🛠️ Installation
|
|
56
|
+
|
|
57
|
+
Install the package via npm:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
npm install express-resforge
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## 🚀 Quick Start Guide
|
|
67
|
+
|
|
68
|
+
### 1. Initialize Global Middlewares
|
|
69
|
+
|
|
70
|
+
Mount the `express-resforge` middleware core engine at the top of your Express application definition stack:
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
import express from 'express';
|
|
74
|
+
import { apiKit } from 'express-resforge';
|
|
75
|
+
|
|
76
|
+
const app = express();
|
|
77
|
+
app.use(express.json());
|
|
78
|
+
|
|
79
|
+
// 1. Mount isolated request lifecycle tracing systems
|
|
80
|
+
app.use(apiKit.requestId());
|
|
81
|
+
app.use(apiKit.requestTimer());
|
|
82
|
+
|
|
83
|
+
// 2. Initialize global configuration middleware
|
|
84
|
+
app.use(apiKit.middleware({
|
|
85
|
+
apiVersion: 'v1.0.0',
|
|
86
|
+
errors: {
|
|
87
|
+
exposeStack: process.env.NODE_ENV === 'development',
|
|
88
|
+
sanitizeServerErrors: true
|
|
89
|
+
}
|
|
90
|
+
}));
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### 2. Implement Standard Route Handlers
|
|
95
|
+
|
|
96
|
+
Eliminate boilerplate blocks using the native, higher-order asynchronous wrapper `apiKit.async()` combined with semantic response triggers:
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
// Traditional clean controller pattern
|
|
100
|
+
app.get('/api/users/:id', apiKit.async(async (req, res) => {
|
|
101
|
+
const user = await database.find(req.params.id);
|
|
102
|
+
|
|
103
|
+
if (!user) {
|
|
104
|
+
return res.notFound({ message: 'Target user profile does not exist.' }).send();
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return res.success(user).message('Profile loaded successfully.').send();
|
|
108
|
+
}));
|
|
109
|
+
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### 3. Advanced Fluent Chaining Builder Mechanics
|
|
113
|
+
|
|
114
|
+
You can cleanly string together custom statuses, business workflow tracking codes, HTTP headers, and secure cookie properties in a single statement:
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
app.post('/api/auth/login', apiKit.async(async (req, res) => {
|
|
118
|
+
const session = await authEngine.authenticate(req.body);
|
|
119
|
+
|
|
120
|
+
return res.created(session)
|
|
121
|
+
.message('Authentication transaction finalized.')
|
|
122
|
+
.code('AUTH_PROCESSED_SUCCESSFULLY')
|
|
123
|
+
.header('X-Auth-Token', session.token)
|
|
124
|
+
.cookie('sid', session.id, { httpOnly: true, secure: true })
|
|
125
|
+
.send();
|
|
126
|
+
}));
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### 4. Automatic Automated Pagination Calculation
|
|
131
|
+
|
|
132
|
+
Pass raw list inputs along with pagination parameters. `express-resforge` automatically calculates bounding limits, total pages, and boolean indicators:
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
app.get('/api/products', apiKit.async(async (req, res) => {
|
|
136
|
+
const products = await database.fetchBatch({ offset: 10, limit: 10 });
|
|
137
|
+
|
|
138
|
+
// Generates complete totalPages, hasNextPage, and hasPrevPage blocks natively
|
|
139
|
+
return res.paginate(products, { page: 2, limit: 10, total: 45 })
|
|
140
|
+
.message('Paginated product inventory batch loaded.')
|
|
141
|
+
.send();
|
|
142
|
+
}));
|
|
143
|
+
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### 5. Mount the Catch-All Resilient Error Boundary
|
|
147
|
+
|
|
148
|
+
Place the global exception boundary tracker at the final exit boundary of your route stack to intercept uncaught failures:
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
// Always register the error orchestrator after all active operational routes
|
|
152
|
+
app.use(apiKit.errorHandler());
|
|
153
|
+
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## 🔌 Global Plugin System Interceptors
|
|
159
|
+
|
|
160
|
+
You can hook into the payload formatting engine globally to inject custom tags, regional cloud location traces, or real-time tracking hashes right before the data hits the network stream:
|
|
161
|
+
|
|
162
|
+
```typescript
|
|
163
|
+
import { apiKit } from 'express-resforge';
|
|
164
|
+
|
|
165
|
+
apiKit.use((payload, req, res) => {
|
|
166
|
+
// Inject microservice cloud node location tags safely
|
|
167
|
+
payload.meta.serverCluster = "aws-us-east-1-prod-node";
|
|
168
|
+
return payload;
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## 💎 Ecosystem Error Formatters Matrix
|
|
176
|
+
|
|
177
|
+
Convert diverse validation exceptions from third-party ecosystems into uniform validation shapes. You can parse anomalies explicitly or let the error handler format them automatically:
|
|
178
|
+
|
|
179
|
+
```typescript
|
|
180
|
+
import { apiKit } from 'express-resforge';
|
|
181
|
+
|
|
182
|
+
app.post('/api/register', (req, res) => {
|
|
183
|
+
const validation = myZodSchema.safeParse(req.body);
|
|
184
|
+
|
|
185
|
+
if (!validation.success) {
|
|
186
|
+
// Standardizes Zod internal diagnostics into a flat ValidationErrorItem array
|
|
187
|
+
const cleanErrors = apiKit.formatters.zod(validation.error);
|
|
188
|
+
return res.unprocessable({ errors: cleanErrors }).send();
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
res.created(validation.data).send();
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Supported out-of-the-box engines include:
|
|
197
|
+
|
|
198
|
+
* `apiKit.formatters.zod(error)`
|
|
199
|
+
* `apiKit.formatters.joi(error)`
|
|
200
|
+
* `apiKit.formatters.prisma(error)`
|
|
201
|
+
* `apiKit.formatters.mongoose(error)`
|
|
202
|
+
* `apiKit.formatters.axios(error)`
|
|
203
|
+
* `apiKit.formatters.firebase(error)`
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## 📊 Standard Response Schema Envelope
|
|
208
|
+
|
|
209
|
+
Every payload delivered down the wire matches this production schema model:
|
|
210
|
+
|
|
211
|
+
### Standard Success Response Output
|
|
212
|
+
|
|
213
|
+
```json
|
|
214
|
+
{
|
|
215
|
+
"success": true,
|
|
216
|
+
"statusCode": 200,
|
|
217
|
+
"responseCode": "SUCCESS",
|
|
218
|
+
"message": "Profile loaded successfully.",
|
|
219
|
+
"data": {
|
|
220
|
+
"profileId": 42
|
|
221
|
+
},
|
|
222
|
+
"meta": {
|
|
223
|
+
"requestId": "e30e9d6d-2c81-4b13-be8e-73cb1a4d8d1f",
|
|
224
|
+
"timestamp": "2026-07-13T07:07:00.000Z",
|
|
225
|
+
"executionTimeMs": 1.42,
|
|
226
|
+
"apiVersion": "v1.0.0",
|
|
227
|
+
"serverCluster": "aws-us-east-1-prod-node"
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### Standard Paginated Response Output
|
|
234
|
+
|
|
235
|
+
```json
|
|
236
|
+
{
|
|
237
|
+
"success": true,
|
|
238
|
+
"statusCode": 200,
|
|
239
|
+
"responseCode": "SUCCESS",
|
|
240
|
+
"message": "Paginated product inventory batch loaded.",
|
|
241
|
+
"data": [{ "id": 101 }, { "id": 102 }],
|
|
242
|
+
"pagination": {
|
|
243
|
+
"page": 2,
|
|
244
|
+
"limit": 10,
|
|
245
|
+
"totalElements": 45,
|
|
246
|
+
"totalPages": 5,
|
|
247
|
+
"hasNextPage": true,
|
|
248
|
+
"hasPrevPage": true
|
|
249
|
+
},
|
|
250
|
+
"meta": {
|
|
251
|
+
"requestId": "fa925bc0-80d4-4ce6-a6de-12e09b30c511",
|
|
252
|
+
"timestamp": "2026-07-13T07:07:05.000Z",
|
|
253
|
+
"executionTimeMs": 2.10,
|
|
254
|
+
"apiVersion": "v1.0.0"
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
## 📋 API Helper Reference Matrix
|
|
263
|
+
|
|
264
|
+
| Response Helper Method | Status Code | Default Internal System Code |
|
|
265
|
+
| --- | --- | --- |
|
|
266
|
+
| `res.success(data, options)` | `200` | `SUCCESS` |
|
|
267
|
+
| `res.created(data, options)` | `201` | `CREATED` |
|
|
268
|
+
| `res.accepted(data, options)` | `202` | `ACCEPTED` |
|
|
269
|
+
| `res.deleted(options)` | `200` | `DELETED` |
|
|
270
|
+
| `res.noContent()` | `204` | *Empty Body Response* |
|
|
271
|
+
| `res.badRequest(options)` | `400` | `BAD_REQUEST` |
|
|
272
|
+
| `res.unauthorized(options)` | `401` | `UNAUTHORIZED` |
|
|
273
|
+
| `res.forbidden(options)` | `403` | `FORBIDDEN` |
|
|
274
|
+
| `res.notFound(options)` | `404` | `RESOURCE_NOT_FOUND` |
|
|
275
|
+
| `res.conflict(options)` | `409` | `RESOURCE_CONFLICT` |
|
|
276
|
+
| `res.unprocessable(options)` | `422` | `VALIDATION_FAILED` |
|
|
277
|
+
| `res.tooManyRequests(options)` | `429` | `RATE_LIMIT_EXCEEDED` |
|
|
278
|
+
| `res.serverError(options)` | `500` | `INTERNAL_SERVER_ERROR` |
|
|
279
|
+
|
|
280
|
+
---
|
|
281
|
+
|
|
282
|
+
## 🛡️ Security Best Practices Enforced
|
|
283
|
+
|
|
284
|
+
* **Prototype Pollution Immunity:** Internal utility methods run isolated loop boundaries that filter out malicious object injection hashes via key hooks like `__proto__` or `constructor`.
|
|
285
|
+
* **Leak Protection Sanitation:** When production settings are active, system level exception dumps (database driver timeouts, runtime faults) are cleanly scrubbed out. The client gets a clear error reference code without revealing system details.
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
## 📄 License
|
|
290
|
+
|
|
291
|
+
Distributed under the MIT License. See `LICENSE` for more information.
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
295
|
+
## 👥 Maintained By
|
|
296
|
+
|
|
297
|
+
**Dream Mythic Studio**
|
|
298
|
+
Founded and maintained by **Vaibhav Dhake**.
|
|
299
|
+
|
|
300
|
+
- **Founder & Lead Developer:** Vaibhav Dhake
|
|
301
|
+
- **Studio:** Dream Mythic Studio
|
|
302
|
+
- **GitHub:** https://github.com/vaibhavdhake123
|
|
303
|
+
|
|
304
|
+
For bug reports, feature requests, discussions, or contributions, please open an issue or submit a pull request on the official repository:
|
|
305
|
+
|
|
306
|
+
**Repository:** https://github.com/vaibhavdhake123/express-resforge
|
|
307
|
+
|
|
308
|
+
Built with ❤️ by **Dream Mythic Studio**.
|
|
309
|
+
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DefaultMessages = void 0;
|
|
4
|
+
const httpStatus_1 = require("./httpStatus");
|
|
5
|
+
/**
|
|
6
|
+
* @fileoverview Fallback natural language message strings tied directly to HTTP states.
|
|
7
|
+
* Sealed at runtime to protect consistency across endpoint distributions.
|
|
8
|
+
*/
|
|
9
|
+
exports.DefaultMessages = {
|
|
10
|
+
// 2xx Success States
|
|
11
|
+
[httpStatus_1.HttpStatus.OK]: 'Operation completed successfully.',
|
|
12
|
+
[httpStatus_1.HttpStatus.CREATED]: 'Resource was successfully created.',
|
|
13
|
+
[httpStatus_1.HttpStatus.ACCEPTED]: 'Request accepted and is processing asynchronously.',
|
|
14
|
+
[httpStatus_1.HttpStatus.NO_CONTENT]: 'Request processed successfully with empty content.',
|
|
15
|
+
// 4xx Client Error States
|
|
16
|
+
[httpStatus_1.HttpStatus.BAD_REQUEST]: 'The request payload is invalid or malformed.',
|
|
17
|
+
[httpStatus_1.HttpStatus.UNAUTHORIZED]: 'Authentication is required to access this resource.',
|
|
18
|
+
[httpStatus_1.HttpStatus.FORBIDDEN]: 'You do not possess the necessary privileges for this resource.',
|
|
19
|
+
[httpStatus_1.HttpStatus.NOT_FOUND]: 'The requested resource could not be found.',
|
|
20
|
+
[httpStatus_1.HttpStatus.CONFLICT]: 'A state conflict occurred while processing the resource.',
|
|
21
|
+
[httpStatus_1.HttpStatus.UNPROCESSABLE_ENTITY]: 'Validation failed for the submitted parameters.',
|
|
22
|
+
[httpStatus_1.HttpStatus.TOO_MANY_REQUESTS]: 'Rate limit exceeded. Please try again later.',
|
|
23
|
+
// 5xx Server Error States
|
|
24
|
+
[httpStatus_1.HttpStatus.INTERNAL_SERVER_ERROR]: 'An unexpected internal server error occurred.',
|
|
25
|
+
[httpStatus_1.HttpStatus.NOT_IMPLEMENTED]: 'The requested endpoint capability is not implemented.',
|
|
26
|
+
[httpStatus_1.HttpStatus.SERVICE_UNAVAILABLE]: 'The server is temporarily down or overloaded.',
|
|
27
|
+
};
|
|
28
|
+
// Lock down the object at runtime to prevent accidental mutation drift
|
|
29
|
+
Object.freeze(exports.DefaultMessages);
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview RFC-compliant HTTP Status Codes mapped as immutable constant bindings.
|
|
3
|
+
* Optimized via Object.freeze to eliminate runtime mutation risks.
|
|
4
|
+
*/
|
|
5
|
+
export declare const HttpStatus: {
|
|
6
|
+
readonly OK: 200;
|
|
7
|
+
readonly CREATED: 201;
|
|
8
|
+
readonly ACCEPTED: 202;
|
|
9
|
+
readonly NO_CONTENT: 204;
|
|
10
|
+
readonly MOVED_PERMANENTLY: 301;
|
|
11
|
+
readonly FOUND: 302;
|
|
12
|
+
readonly NOT_MODIFIED: 304;
|
|
13
|
+
readonly BAD_REQUEST: 400;
|
|
14
|
+
readonly UNAUTHORIZED: 401;
|
|
15
|
+
readonly FORBIDDEN: 403;
|
|
16
|
+
readonly NOT_FOUND: 404;
|
|
17
|
+
readonly METHOD_NOT_ALLOWED: 405;
|
|
18
|
+
readonly CONFLICT: 409;
|
|
19
|
+
readonly UNPROCESSABLE_ENTITY: 422;
|
|
20
|
+
readonly TOO_MANY_REQUESTS: 429;
|
|
21
|
+
readonly INTERNAL_SERVER_ERROR: 500;
|
|
22
|
+
readonly NOT_IMPLEMENTED: 501;
|
|
23
|
+
readonly SERVICE_UNAVAILABLE: 503;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Type-safe representation extracted from the immutable HttpStatus dictionary.
|
|
27
|
+
*/
|
|
28
|
+
export type HttpStatusType = typeof HttpStatus[keyof typeof HttpStatus];
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview RFC-compliant HTTP Status Codes mapped as immutable constant bindings.
|
|
4
|
+
* Optimized via Object.freeze to eliminate runtime mutation risks.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.HttpStatus = void 0;
|
|
8
|
+
exports.HttpStatus = {
|
|
9
|
+
// 2xx Success
|
|
10
|
+
OK: 200,
|
|
11
|
+
CREATED: 201,
|
|
12
|
+
ACCEPTED: 202,
|
|
13
|
+
NO_CONTENT: 204,
|
|
14
|
+
// 3xx Redirection
|
|
15
|
+
MOVED_PERMANENTLY: 301,
|
|
16
|
+
FOUND: 302,
|
|
17
|
+
NOT_MODIFIED: 304,
|
|
18
|
+
// 4xx Client Errors
|
|
19
|
+
BAD_REQUEST: 400,
|
|
20
|
+
UNAUTHORIZED: 401,
|
|
21
|
+
FORBIDDEN: 403,
|
|
22
|
+
NOT_FOUND: 404,
|
|
23
|
+
METHOD_NOT_ALLOWED: 405,
|
|
24
|
+
CONFLICT: 409,
|
|
25
|
+
UNPROCESSABLE_ENTITY: 422,
|
|
26
|
+
TOO_MANY_REQUESTS: 429,
|
|
27
|
+
// 5xx Server Errors
|
|
28
|
+
INTERNAL_SERVER_ERROR: 500,
|
|
29
|
+
NOT_IMPLEMENTED: 501,
|
|
30
|
+
SERVICE_UNAVAILABLE: 503,
|
|
31
|
+
};
|
|
32
|
+
// Lock down the object at runtime to prevent accidental engineering drift or pollution
|
|
33
|
+
Object.freeze(exports.HttpStatus);
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Unique enterprise-standard alpha string identifiers for runtime states.
|
|
3
|
+
* Sealed at compile-time and runtime to protect tracking consistency.
|
|
4
|
+
*/
|
|
5
|
+
export declare const ResponseCodes: {
|
|
6
|
+
readonly SUCCESS: "SUCCESS";
|
|
7
|
+
readonly CREATED: "CREATED";
|
|
8
|
+
readonly ACCEPTED: "ACCEPTED";
|
|
9
|
+
readonly DELETED: "DELETED";
|
|
10
|
+
readonly NO_CONTENT: "NO_CONTENT";
|
|
11
|
+
readonly BAD_REQUEST: "BAD_REQUEST";
|
|
12
|
+
readonly UNAUTHORIZED: "UNAUTHORIZED";
|
|
13
|
+
readonly FORBIDDEN: "FORBIDDEN";
|
|
14
|
+
readonly NOT_FOUND: "RESOURCE_NOT_FOUND";
|
|
15
|
+
readonly CONFLICT: "RESOURCE_CONFLICT";
|
|
16
|
+
readonly UNPROCESSABLE: "VALIDATION_FAILED";
|
|
17
|
+
readonly TOO_MANY_REQUESTS: "RATE_LIMIT_EXCEEDED";
|
|
18
|
+
readonly SERVER_ERROR: "INTERNAL_SERVER_ERROR";
|
|
19
|
+
readonly NOT_IMPLEMENTED: "NOT_IMPLEMENTED";
|
|
20
|
+
readonly SERVICE_UNAVAILABLE: "SERVICE_UNAVAILABLE";
|
|
21
|
+
};
|
|
22
|
+
export type ResponseCodeType = typeof ResponseCodes[keyof typeof ResponseCodes];
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview Unique enterprise-standard alpha string identifiers for runtime states.
|
|
4
|
+
* Sealed at compile-time and runtime to protect tracking consistency.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.ResponseCodes = void 0;
|
|
8
|
+
exports.ResponseCodes = {
|
|
9
|
+
SUCCESS: "SUCCESS",
|
|
10
|
+
CREATED: "CREATED",
|
|
11
|
+
ACCEPTED: "ACCEPTED",
|
|
12
|
+
DELETED: "DELETED",
|
|
13
|
+
NO_CONTENT: "NO_CONTENT",
|
|
14
|
+
BAD_REQUEST: "BAD_REQUEST",
|
|
15
|
+
UNAUTHORIZED: "UNAUTHORIZED",
|
|
16
|
+
FORBIDDEN: "FORBIDDEN",
|
|
17
|
+
NOT_FOUND: "RESOURCE_NOT_FOUND",
|
|
18
|
+
CONFLICT: "RESOURCE_CONFLICT",
|
|
19
|
+
UNPROCESSABLE: "VALIDATION_FAILED",
|
|
20
|
+
TOO_MANY_REQUESTS: "RATE_LIMIT_EXCEEDED",
|
|
21
|
+
SERVER_ERROR: "INTERNAL_SERVER_ERROR",
|
|
22
|
+
NOT_IMPLEMENTED: "NOT_IMPLEMENTED",
|
|
23
|
+
SERVICE_UNAVAILABLE: "SERVICE_UNAVAILABLE",
|
|
24
|
+
};
|
|
25
|
+
Object.freeze(exports.ResponseCodes);
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Isolation store tracking scoped transaction states using AsyncLocalStorage.
|
|
3
|
+
*/
|
|
4
|
+
export interface RequestStoreContext {
|
|
5
|
+
requestId: string;
|
|
6
|
+
startTime: [number, number];
|
|
7
|
+
timestamp: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Encapsulated storage wrapper enforcing strict access limits on request variables.
|
|
11
|
+
*/
|
|
12
|
+
declare class RequestContextManager {
|
|
13
|
+
private readonly storage;
|
|
14
|
+
/**
|
|
15
|
+
* Wraps an execution thread pipeline inside a persistent scoped contextual tracking space.
|
|
16
|
+
* @param context Pre-populated execution variables for the tracking boundary.
|
|
17
|
+
* @param next Next async execution block to process inside isolation.
|
|
18
|
+
*/
|
|
19
|
+
run<R>(context: RequestStoreContext, next: () => R): R;
|
|
20
|
+
/**
|
|
21
|
+
* Fetches the current request's active execution context safely.
|
|
22
|
+
* Returns undefined if accessed outside an active express execution line.
|
|
23
|
+
*/
|
|
24
|
+
getStore(): RequestStoreContext | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* Programmatically retrieves the active request ID.
|
|
27
|
+
* Returns a clean empty string if no tracking frame is active.
|
|
28
|
+
*/
|
|
29
|
+
getRequestId(): string;
|
|
30
|
+
/**
|
|
31
|
+
* Computes high-precision microsecond differential calculations tracking current duration bounds.
|
|
32
|
+
*/
|
|
33
|
+
getExecutionTimeMs(): number;
|
|
34
|
+
}
|
|
35
|
+
export declare const requestContext: RequestContextManager;
|
|
36
|
+
export {};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.requestContext = void 0;
|
|
4
|
+
const node_async_hooks_1 = require("node:async_hooks");
|
|
5
|
+
/**
|
|
6
|
+
* Encapsulated storage wrapper enforcing strict access limits on request variables.
|
|
7
|
+
*/
|
|
8
|
+
class RequestContextManager {
|
|
9
|
+
storage = new node_async_hooks_1.AsyncLocalStorage();
|
|
10
|
+
/**
|
|
11
|
+
* Wraps an execution thread pipeline inside a persistent scoped contextual tracking space.
|
|
12
|
+
* @param context Pre-populated execution variables for the tracking boundary.
|
|
13
|
+
* @param next Next async execution block to process inside isolation.
|
|
14
|
+
*/
|
|
15
|
+
run(context, next) {
|
|
16
|
+
return this.storage.run(context, next);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Fetches the current request's active execution context safely.
|
|
20
|
+
* Returns undefined if accessed outside an active express execution line.
|
|
21
|
+
*/
|
|
22
|
+
getStore() {
|
|
23
|
+
return this.storage.getStore();
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Programmatically retrieves the active request ID.
|
|
27
|
+
* Returns a clean empty string if no tracking frame is active.
|
|
28
|
+
*/
|
|
29
|
+
getRequestId() {
|
|
30
|
+
return this.storage.getStore()?.requestId ?? '';
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Computes high-precision microsecond differential calculations tracking current duration bounds.
|
|
34
|
+
*/
|
|
35
|
+
getExecutionTimeMs() {
|
|
36
|
+
const store = this.storage.getStore();
|
|
37
|
+
if (!store)
|
|
38
|
+
return 0;
|
|
39
|
+
const diff = process.hrtime(store.startTime);
|
|
40
|
+
// Convert [seconds, nanoseconds] directly to highly readable float milliseconds
|
|
41
|
+
const ms = (diff[0] * 1000) + (diff[1] / 1000000);
|
|
42
|
+
return Math.round(ms * 100) / 100; // Constrain decimal drift to two accurate fraction spaces
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
exports.requestContext = new RequestContextManager();
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ValidationErrorItem } from '../types/responses';
|
|
2
|
+
export declare class CentralFormatter {
|
|
3
|
+
/**
|
|
4
|
+
* Safe execution wrapper that maps custom library errors using specified formatter rules.
|
|
5
|
+
*/
|
|
6
|
+
static format(formatterFn: (err: any) => ValidationErrorItem[], error: any): ValidationErrorItem[];
|
|
7
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CentralFormatter = void 0;
|
|
4
|
+
class CentralFormatter {
|
|
5
|
+
/**
|
|
6
|
+
* Safe execution wrapper that maps custom library errors using specified formatter rules.
|
|
7
|
+
*/
|
|
8
|
+
static format(formatterFn, error) {
|
|
9
|
+
try {
|
|
10
|
+
return formatterFn(error);
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return [{ field: 'unknown', message: 'An unparseable validation fault occurred.' }];
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
exports.CentralFormatter = CentralFormatter;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { StandardApiResponse } from '../types/responses';
|
|
2
|
+
/**
|
|
3
|
+
* Signature function blueprint for all custom response interceptor plugins.
|
|
4
|
+
*/
|
|
5
|
+
export type ApiKitPlugin = (payload: StandardApiResponse<any>, req: any, res: any) => StandardApiResponse<any>;
|
|
6
|
+
/**
|
|
7
|
+
* Orchestration engine managing registration and execution lifecycle of custom plugins.
|
|
8
|
+
*/
|
|
9
|
+
export declare class PluginManager {
|
|
10
|
+
private readonly plugins;
|
|
11
|
+
/**
|
|
12
|
+
* Registers a global plugin hook into the internal pipeline.
|
|
13
|
+
* @param plugin The execution interceptor function block.
|
|
14
|
+
*/
|
|
15
|
+
use(plugin: ApiKitPlugin): void;
|
|
16
|
+
/**
|
|
17
|
+
* Executes all registered plugins sequentially over the payload using a flat loop
|
|
18
|
+
* to guarantee zero-allocation performance overhead.
|
|
19
|
+
*
|
|
20
|
+
* @param payload The generated standard API response object.
|
|
21
|
+
* @param req The raw incoming Express request context.
|
|
22
|
+
* @param res The raw active Express response context.
|
|
23
|
+
* @returns The fully decorated or mutated API payload structure.
|
|
24
|
+
*/
|
|
25
|
+
execute(payload: StandardApiResponse<any>, req: any, res: any): StandardApiResponse<any>;
|
|
26
|
+
}
|
|
27
|
+
export declare const globalPluginManager: PluginManager;
|