@forklaunch/hyper-express 0.2.8 → 0.3.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/lib/index.d.mts +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.js +63 -10
- package/lib/index.mjs +66 -11
- package/package.json +13 -12
package/lib/index.d.mts
CHANGED
@@ -45,7 +45,7 @@ declare class Router<SV extends AnySchemaValidator, BasePath extends `/${string}
|
|
45
45
|
* @template ReqQuery - A type for the request query, defaulting to ParsedQs.
|
46
46
|
* @template LocalsObj - A type for local variables, defaulting to an empty object.
|
47
47
|
*/
|
48
|
-
interface Request<SV extends AnySchemaValidator, P extends ParamsDictionary, ReqBody extends Record<string, unknown>, ReqQuery extends ParsedQs, ReqHeaders extends Record<string, string>, LocalsObj extends Record<string, unknown>> extends ForklaunchRequest<SV, P, ReqBody, ReqQuery, ReqHeaders>, Omit<Request$1<LocalsObj>, 'method' | 'params' | 'query' | 'headers'> {
|
48
|
+
interface Request<SV extends AnySchemaValidator, P extends ParamsDictionary, ReqBody extends Record<string, unknown>, ReqQuery extends ParsedQs, ReqHeaders extends Record<string, string>, LocalsObj extends Record<string, unknown>> extends ForklaunchRequest<SV, P, ReqBody, ReqQuery, ReqHeaders>, Omit<Request$1<LocalsObj>, 'method' | 'params' | 'query' | 'headers' | 'path'> {
|
49
49
|
/** The request body */
|
50
50
|
body: ReqBody;
|
51
51
|
/** The request query parameters */
|
package/lib/index.d.ts
CHANGED
@@ -45,7 +45,7 @@ declare class Router<SV extends AnySchemaValidator, BasePath extends `/${string}
|
|
45
45
|
* @template ReqQuery - A type for the request query, defaulting to ParsedQs.
|
46
46
|
* @template LocalsObj - A type for local variables, defaulting to an empty object.
|
47
47
|
*/
|
48
|
-
interface Request<SV extends AnySchemaValidator, P extends ParamsDictionary, ReqBody extends Record<string, unknown>, ReqQuery extends ParsedQs, ReqHeaders extends Record<string, string>, LocalsObj extends Record<string, unknown>> extends ForklaunchRequest<SV, P, ReqBody, ReqQuery, ReqHeaders>, Omit<Request$1<LocalsObj>, 'method' | 'params' | 'query' | 'headers'> {
|
48
|
+
interface Request<SV extends AnySchemaValidator, P extends ParamsDictionary, ReqBody extends Record<string, unknown>, ReqQuery extends ParsedQs, ReqHeaders extends Record<string, string>, LocalsObj extends Record<string, unknown>> extends ForklaunchRequest<SV, P, ReqBody, ReqQuery, ReqHeaders>, Omit<Request$1<LocalsObj>, 'method' | 'params' | 'query' | 'headers' | 'path'> {
|
49
49
|
/** The request body */
|
50
50
|
body: ReqBody;
|
51
51
|
/** The request query parameters */
|
package/lib/index.js
CHANGED
@@ -44,7 +44,7 @@ var import_live_directory = __toESM(require("live-directory"));
|
|
44
44
|
var import_absolute_path = __toESM(require("swagger-ui-dist/absolute-path"));
|
45
45
|
var import_swagger_ui_express = __toESM(require("swagger-ui-express"));
|
46
46
|
function swaggerRedirect(path) {
|
47
|
-
return (req, res, next)
|
47
|
+
return function swaggerHosting(req, res, next) {
|
48
48
|
if (req.path === path) {
|
49
49
|
res.redirect(`${path}/`);
|
50
50
|
}
|
@@ -107,19 +107,47 @@ var Application = class extends import_http.ForklaunchExpressLikeApplication {
|
|
107
107
|
constructor(schemaValidator) {
|
108
108
|
super(schemaValidator, new import_hyper_express_fork.Server());
|
109
109
|
}
|
110
|
-
listen(arg0, arg1, arg2) {
|
110
|
+
async listen(arg0, arg1, arg2) {
|
111
111
|
if (typeof arg0 === "number") {
|
112
112
|
const port = arg0 || Number(process.env.PORT);
|
113
|
-
this.internal.set_error_handler((
|
113
|
+
this.internal.set_error_handler((req, res, err) => {
|
114
114
|
res.locals.errorMessage = err.message;
|
115
|
-
console.error(err);
|
116
115
|
res.status(
|
117
116
|
res.statusCode && res.statusCode >= 400 ? res.statusCode : 500
|
118
117
|
).send(`Internal server error:
|
119
118
|
|
120
119
|
${err.message}`);
|
120
|
+
(0, import_http.emitLoggerError)(
|
121
|
+
{
|
122
|
+
contractDetails: { name: "unknown" },
|
123
|
+
originalPath: req.path,
|
124
|
+
...req,
|
125
|
+
method: req.method,
|
126
|
+
path: req.path
|
127
|
+
},
|
128
|
+
{
|
129
|
+
statusCode: res.statusCode ?? 500
|
130
|
+
},
|
131
|
+
err.stack ?? err.message
|
132
|
+
);
|
121
133
|
});
|
122
|
-
const
|
134
|
+
const { apiReference } = await import("@scalar/express-api-reference");
|
135
|
+
this.internal.use(
|
136
|
+
`/api/${process.env.VERSION ?? "v1"}${process.env.DOCS_PATH ?? "/docs"}`,
|
137
|
+
apiReference({
|
138
|
+
spec: {
|
139
|
+
content: (0, import_http.generateSwaggerDocument)(
|
140
|
+
this.schemaValidator,
|
141
|
+
port,
|
142
|
+
this.routers
|
143
|
+
)
|
144
|
+
},
|
145
|
+
theme: "deepSpace",
|
146
|
+
layout: "modern"
|
147
|
+
})
|
148
|
+
);
|
149
|
+
const swaggerPath = `/api/${process.env.VERSION ?? "v1"}${// process.env.DOCS_PATH ?? '/docs'
|
150
|
+
"/swagger"}`;
|
123
151
|
this.internal.use(swaggerPath, swaggerRedirect(swaggerPath));
|
124
152
|
this.internal.get(
|
125
153
|
`${swaggerPath}/*`,
|
@@ -147,7 +175,6 @@ var import_hyper_express_fork2 = require("@forklaunch/hyper-express-fork");
|
|
147
175
|
|
148
176
|
// src/middleware/contentParse.middleware.ts
|
149
177
|
async function contentParse(req) {
|
150
|
-
console.debug("[MIDDLEWARE] contentParse started");
|
151
178
|
switch (req.headers["content-type"] && req.headers["content-type"].split(";")[0]) {
|
152
179
|
case "application/json":
|
153
180
|
req.body = await req.json();
|
@@ -161,6 +188,24 @@ async function contentParse(req) {
|
|
161
188
|
case "application/octet-stream":
|
162
189
|
req.body = await req.buffer();
|
163
190
|
break;
|
191
|
+
case "multipart/form-data":
|
192
|
+
req.body = {};
|
193
|
+
await req.multipart(async (field) => {
|
194
|
+
if (field.file) {
|
195
|
+
const fileBuffer = Buffer.from(
|
196
|
+
await field.file.stream.read(),
|
197
|
+
field.encoding
|
198
|
+
);
|
199
|
+
req.body[field.name] = {
|
200
|
+
buffer: fileBuffer,
|
201
|
+
name: field.file.name ?? field.name,
|
202
|
+
type: field.mime_type
|
203
|
+
};
|
204
|
+
} else {
|
205
|
+
req.body[field.name] = field.value;
|
206
|
+
}
|
207
|
+
});
|
208
|
+
break;
|
164
209
|
default:
|
165
210
|
req.body = await req.json();
|
166
211
|
break;
|
@@ -170,20 +215,29 @@ async function contentParse(req) {
|
|
170
215
|
// src/middleware/enrichResponseTransmission.middleware.ts
|
171
216
|
var import_http2 = require("@forklaunch/core/http");
|
172
217
|
function enrichResponseTransmission(req, res, next) {
|
173
|
-
console.debug("[MIDDLEWARE] enrichResponseTransmission");
|
174
218
|
const originalSend = res.send;
|
175
219
|
const originalJson = res.json;
|
176
220
|
const originalSetHeader = res.setHeader;
|
177
221
|
res.json = function(data) {
|
178
222
|
res.bodyData = data;
|
179
|
-
|
180
|
-
|
223
|
+
res.statusCode = res._status_code;
|
224
|
+
(0, import_http2.recordMetric)(req, res);
|
225
|
+
(0, import_http2.enrichExpressLikeSend)(
|
226
|
+
this,
|
227
|
+
req,
|
228
|
+
res,
|
229
|
+
originalJson,
|
230
|
+
data,
|
231
|
+
!res.cors && (res._cork && !res._corked || !res._cork)
|
232
|
+
);
|
233
|
+
return data;
|
181
234
|
};
|
182
235
|
res.send = function(data) {
|
183
236
|
if (!res.bodyData) {
|
184
237
|
res.bodyData = data;
|
185
238
|
res.statusCode = res._status_code;
|
186
239
|
}
|
240
|
+
(0, import_http2.recordMetric)(req, res);
|
187
241
|
return (0, import_http2.enrichExpressLikeSend)(
|
188
242
|
this,
|
189
243
|
req,
|
@@ -209,7 +263,6 @@ function enrichResponseTransmission(req, res, next) {
|
|
209
263
|
|
210
264
|
// src/middleware/polyfillGetHeaders.middleware.ts
|
211
265
|
function polyfillGetHeaders(_req, res, next) {
|
212
|
-
console.debug("[MIDDLEWARE] polyfillGetHeaders started");
|
213
266
|
res.getHeaders = () => {
|
214
267
|
return res._headers;
|
215
268
|
};
|
package/lib/index.mjs
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
// src/hyperExpressApplication.ts
|
2
2
|
import {
|
3
|
+
emitLoggerError,
|
3
4
|
ForklaunchExpressLikeApplication,
|
4
5
|
generateSwaggerDocument
|
5
6
|
} from "@forklaunch/core/http";
|
@@ -10,7 +11,7 @@ import LiveDirectory from "live-directory";
|
|
10
11
|
import getAbsoluteSwaggerFsPath from "swagger-ui-dist/absolute-path";
|
11
12
|
import swaggerUi from "swagger-ui-express";
|
12
13
|
function swaggerRedirect(path) {
|
13
|
-
return (req, res, next)
|
14
|
+
return function swaggerHosting(req, res, next) {
|
14
15
|
if (req.path === path) {
|
15
16
|
res.redirect(`${path}/`);
|
16
17
|
}
|
@@ -73,19 +74,47 @@ var Application = class extends ForklaunchExpressLikeApplication {
|
|
73
74
|
constructor(schemaValidator) {
|
74
75
|
super(schemaValidator, new Server());
|
75
76
|
}
|
76
|
-
listen(arg0, arg1, arg2) {
|
77
|
+
async listen(arg0, arg1, arg2) {
|
77
78
|
if (typeof arg0 === "number") {
|
78
79
|
const port = arg0 || Number(process.env.PORT);
|
79
|
-
this.internal.set_error_handler((
|
80
|
+
this.internal.set_error_handler((req, res, err) => {
|
80
81
|
res.locals.errorMessage = err.message;
|
81
|
-
console.error(err);
|
82
82
|
res.status(
|
83
83
|
res.statusCode && res.statusCode >= 400 ? res.statusCode : 500
|
84
84
|
).send(`Internal server error:
|
85
85
|
|
86
86
|
${err.message}`);
|
87
|
+
emitLoggerError(
|
88
|
+
{
|
89
|
+
contractDetails: { name: "unknown" },
|
90
|
+
originalPath: req.path,
|
91
|
+
...req,
|
92
|
+
method: req.method,
|
93
|
+
path: req.path
|
94
|
+
},
|
95
|
+
{
|
96
|
+
statusCode: res.statusCode ?? 500
|
97
|
+
},
|
98
|
+
err.stack ?? err.message
|
99
|
+
);
|
87
100
|
});
|
88
|
-
const
|
101
|
+
const { apiReference } = await import("@scalar/express-api-reference");
|
102
|
+
this.internal.use(
|
103
|
+
`/api/${process.env.VERSION ?? "v1"}${process.env.DOCS_PATH ?? "/docs"}`,
|
104
|
+
apiReference({
|
105
|
+
spec: {
|
106
|
+
content: generateSwaggerDocument(
|
107
|
+
this.schemaValidator,
|
108
|
+
port,
|
109
|
+
this.routers
|
110
|
+
)
|
111
|
+
},
|
112
|
+
theme: "deepSpace",
|
113
|
+
layout: "modern"
|
114
|
+
})
|
115
|
+
);
|
116
|
+
const swaggerPath = `/api/${process.env.VERSION ?? "v1"}${// process.env.DOCS_PATH ?? '/docs'
|
117
|
+
"/swagger"}`;
|
89
118
|
this.internal.use(swaggerPath, swaggerRedirect(swaggerPath));
|
90
119
|
this.internal.get(
|
91
120
|
`${swaggerPath}/*`,
|
@@ -117,7 +146,6 @@ import {
|
|
117
146
|
|
118
147
|
// src/middleware/contentParse.middleware.ts
|
119
148
|
async function contentParse(req) {
|
120
|
-
console.debug("[MIDDLEWARE] contentParse started");
|
121
149
|
switch (req.headers["content-type"] && req.headers["content-type"].split(";")[0]) {
|
122
150
|
case "application/json":
|
123
151
|
req.body = await req.json();
|
@@ -131,6 +159,24 @@ async function contentParse(req) {
|
|
131
159
|
case "application/octet-stream":
|
132
160
|
req.body = await req.buffer();
|
133
161
|
break;
|
162
|
+
case "multipart/form-data":
|
163
|
+
req.body = {};
|
164
|
+
await req.multipart(async (field) => {
|
165
|
+
if (field.file) {
|
166
|
+
const fileBuffer = Buffer.from(
|
167
|
+
await field.file.stream.read(),
|
168
|
+
field.encoding
|
169
|
+
);
|
170
|
+
req.body[field.name] = {
|
171
|
+
buffer: fileBuffer,
|
172
|
+
name: field.file.name ?? field.name,
|
173
|
+
type: field.mime_type
|
174
|
+
};
|
175
|
+
} else {
|
176
|
+
req.body[field.name] = field.value;
|
177
|
+
}
|
178
|
+
});
|
179
|
+
break;
|
134
180
|
default:
|
135
181
|
req.body = await req.json();
|
136
182
|
break;
|
@@ -139,23 +185,33 @@ async function contentParse(req) {
|
|
139
185
|
|
140
186
|
// src/middleware/enrichResponseTransmission.middleware.ts
|
141
187
|
import {
|
142
|
-
enrichExpressLikeSend
|
188
|
+
enrichExpressLikeSend,
|
189
|
+
recordMetric
|
143
190
|
} from "@forklaunch/core/http";
|
144
191
|
function enrichResponseTransmission(req, res, next) {
|
145
|
-
console.debug("[MIDDLEWARE] enrichResponseTransmission");
|
146
192
|
const originalSend = res.send;
|
147
193
|
const originalJson = res.json;
|
148
194
|
const originalSetHeader = res.setHeader;
|
149
195
|
res.json = function(data) {
|
150
196
|
res.bodyData = data;
|
151
|
-
|
152
|
-
|
197
|
+
res.statusCode = res._status_code;
|
198
|
+
recordMetric(req, res);
|
199
|
+
enrichExpressLikeSend(
|
200
|
+
this,
|
201
|
+
req,
|
202
|
+
res,
|
203
|
+
originalJson,
|
204
|
+
data,
|
205
|
+
!res.cors && (res._cork && !res._corked || !res._cork)
|
206
|
+
);
|
207
|
+
return data;
|
153
208
|
};
|
154
209
|
res.send = function(data) {
|
155
210
|
if (!res.bodyData) {
|
156
211
|
res.bodyData = data;
|
157
212
|
res.statusCode = res._status_code;
|
158
213
|
}
|
214
|
+
recordMetric(req, res);
|
159
215
|
return enrichExpressLikeSend(
|
160
216
|
this,
|
161
217
|
req,
|
@@ -181,7 +237,6 @@ function enrichResponseTransmission(req, res, next) {
|
|
181
237
|
|
182
238
|
// src/middleware/polyfillGetHeaders.middleware.ts
|
183
239
|
function polyfillGetHeaders(_req, res, next) {
|
184
|
-
console.debug("[MIDDLEWARE] polyfillGetHeaders started");
|
185
240
|
res.getHeaders = () => {
|
186
241
|
return res._headers;
|
187
242
|
};
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@forklaunch/hyper-express",
|
3
|
-
"version": "0.
|
3
|
+
"version": "0.3.0",
|
4
4
|
"description": "Forklaunch framework for hyper-express.",
|
5
5
|
"homepage": "https://github.com/forklaunch/forklaunch-js#readme",
|
6
6
|
"bugs": {
|
@@ -25,34 +25,35 @@
|
|
25
25
|
"lib/**"
|
26
26
|
],
|
27
27
|
"dependencies": {
|
28
|
-
"@forklaunch/hyper-express-fork": "6.17.
|
28
|
+
"@forklaunch/hyper-express-fork": "^6.17.30",
|
29
|
+
"@scalar/express-api-reference": "^0.4.186",
|
29
30
|
"cors": "^2.8.5",
|
30
31
|
"live-directory": "^3.0.3",
|
31
32
|
"openapi3-ts": "^4.4.0",
|
32
33
|
"qs": "^6.14.0",
|
33
|
-
"swagger-ui-dist": "^5.
|
34
|
+
"swagger-ui-dist": "^5.20.0",
|
34
35
|
"swagger-ui-express": "^5.0.1",
|
35
36
|
"uWebSockets.js": "github:uNetworking/uWebSockets.js#v20.44.0",
|
36
|
-
"@forklaunch/core": "0.3.6",
|
37
37
|
"@forklaunch/common": "0.2.1",
|
38
|
+
"@forklaunch/core": "0.4.0",
|
38
39
|
"@forklaunch/validator": "0.4.4"
|
39
40
|
},
|
40
41
|
"devDependencies": {
|
41
|
-
"@eslint/js": "^9.
|
42
|
+
"@eslint/js": "^9.21.0",
|
42
43
|
"@types/cors": "^2.8.17",
|
43
44
|
"@types/jest": "^29.5.14",
|
44
45
|
"@types/qs": "^6.9.18",
|
45
46
|
"@types/swagger-ui-dist": "^3.30.5",
|
46
|
-
"@types/swagger-ui-express": "^4.1.
|
47
|
+
"@types/swagger-ui-express": "^4.1.8",
|
47
48
|
"jest": "^29.7.0",
|
48
49
|
"kill-port-process": "^3.2.1",
|
49
|
-
"prettier": "^3.5.
|
50
|
-
"ts-jest": "^29.2.
|
50
|
+
"prettier": "^3.5.2",
|
51
|
+
"ts-jest": "^29.2.6",
|
51
52
|
"ts-node": "^10.9.2",
|
52
|
-
"tsup": "^8.
|
53
|
-
"tsx": "^4.19.
|
54
|
-
"typescript": "^5.
|
55
|
-
"typescript-eslint": "^8.
|
53
|
+
"tsup": "^8.4.0",
|
54
|
+
"tsx": "^4.19.3",
|
55
|
+
"typescript": "^5.8.2",
|
56
|
+
"typescript-eslint": "^8.25.0"
|
56
57
|
},
|
57
58
|
"scripts": {
|
58
59
|
"build": "tsc --noEmit && tsup index.ts --format cjs,esm --no-splitting --dts --tsconfig tsconfig.json --out-dir lib --clean",
|