@forklaunch/hyper-express 0.2.9 → 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 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((_req, res, err) => {
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 swaggerPath = `/api/${process.env.VERSION ?? "v1"}${process.env.DOCS_PATH ?? "/docs"}`;
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
- const result = originalJson.call(this, data);
180
- return result;
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((_req, res, err) => {
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 swaggerPath = `/api/${process.env.VERSION ?? "v1"}${process.env.DOCS_PATH ?? "/docs"}`;
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
- const result = originalJson.call(this, data);
152
- return result;
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.2.9",
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.3",
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.18.3",
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
37
  "@forklaunch/common": "0.2.1",
37
- "@forklaunch/core": "0.3.6",
38
+ "@forklaunch/core": "0.4.0",
38
39
  "@forklaunch/validator": "0.4.4"
39
40
  },
40
41
  "devDependencies": {
41
- "@eslint/js": "^9.20.0",
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.7",
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.1",
50
- "ts-jest": "^29.2.5",
50
+ "prettier": "^3.5.2",
51
+ "ts-jest": "^29.2.6",
51
52
  "ts-node": "^10.9.2",
52
- "tsup": "^8.3.6",
53
- "tsx": "^4.19.2",
54
- "typescript": "^5.7.3",
55
- "typescript-eslint": "^8.24.0"
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",