ultimate-express 1.2.29 → 1.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/README.md CHANGED
@@ -16,7 +16,7 @@ To make sure µExpress matches behavior of Express in all cases, we run all test
16
16
 
17
17
  Similar projects based on uWebSockets:
18
18
 
19
- - `express` on Bun - since Bun uses uWS for its HTTP module, Express is about 2-3 times faster than on Node.js, but still slower than µExpress because it doesn't do uWS-specific optimizations.
19
+ - `express` on Bun - since Bun uses uWS for its HTTP module, Express is about 2-3 times faster than on Node.js, but still almost 2 times slower than µExpress because it doesn't do uWS-specific optimizations.
20
20
  - `hyper-express` - while having a similar API to Express, it's very far from being a drop-in replacement, and implements most of the functionality differently. This creates a lot of random quirks and issues, making the switch quite difficult. Built in middlewares are also very different, middlewares for Express are mostly not supported.
21
21
  - `uwebsockets-express` - this library is closer to being a drop-in replacement, but misses a lot of APIs, depends on Express by calling it's methods under the hood and doesn't try to optimize routing by using native uWS router.
22
22
 
@@ -61,6 +61,7 @@ Also tested on a [real-world application](https://nekoweb.org) with templates, s
61
61
  In a lot of cases, you can just replace `require("express")` with `require("ultimate-express")` and everything works the same. But there are some differences:
62
62
 
63
63
  - `case sensitive routing` is enabled by default.
64
+ - a new option `catch async errors` is added. If it's enabled, you don't need to use `express-async-errors` module.
64
65
  - request body is only read for POST, PUT and PATCH requests by default. You can add additional methods by setting `body methods` to array with uppercased methods.
65
66
  - For HTTPS, instead of doing this:
66
67
  ```js
@@ -301,9 +302,10 @@ Almost all middlewares that are compatible with Express are compatible with µEx
301
302
  - ✅ [express-subdomain](https://npmjs.com/package/express-subdomain)
302
303
  - ✅ [vhost](https://npmjs.com/package/vhost)
303
304
 
304
- Middlewares that are confirmed to not work:
305
+ Middlewares and modules that are confirmed to not work:
305
306
 
306
- - ❌ [compression](https://npmjs.com/package/compression) (doesn't error, but doesn't compress)
307
+ - ❌ [compression](https://npmjs.com/package/compression) - doesn't error, but doesn't compress
308
+ - ❌ [express-async-errors](https://npmjs.com/package/express-async-errors) - doesn't work, use `app.set('catch async errors', true)` instead.
307
309
 
308
310
  ## Tested view engines
309
311
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ultimate-express",
3
- "version": "1.2.29",
3
+ "version": "1.3.0",
4
4
  "description": "The Ultimate Express. Fastest http server with full Express compatibility, based on uWebSockets.",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -31,6 +31,7 @@
31
31
  "uwebsockets",
32
32
  "uws"
33
33
  ],
34
+ "types": "src/types.d.ts",
34
35
  "author": "dimden.dev",
35
36
  "license": "Apache-2.0",
36
37
  "bugs": {
@@ -38,6 +39,7 @@
38
39
  },
39
40
  "homepage": "https://github.com/dimdenGD/ultimate-express#readme",
40
41
  "dependencies": {
42
+ "@types/express": "^4.0.0",
41
43
  "accepts": "^1.3.8",
42
44
  "bytes": "^3.1.2",
43
45
  "cookie": "^0.6.0",
@@ -68,6 +70,7 @@
68
70
  "exit-hook": "^2.2.1",
69
71
  "express": "^4.19.2",
70
72
  "express-art-template": "^1.0.1",
73
+ "express-async-errors": "^3.1.1",
71
74
  "express-dot-engine": "^1.0.8",
72
75
  "express-fileupload": "^1.5.1",
73
76
  "express-handlebars": "^8.0.1",
@@ -159,12 +159,12 @@ class Application extends Router {
159
159
  }
160
160
 
161
161
  enable(key) {
162
- this.settings[key] = true;
162
+ this.set(key, true);
163
163
  return this;
164
164
  }
165
165
 
166
166
  disable(key) {
167
- this.settings[key] = false;
167
+ this.set(key, false);
168
168
  return this;
169
169
  }
170
170
 
package/src/response.js CHANGED
@@ -69,13 +69,12 @@ module.exports = class Response extends Writable {
69
69
  this._req = req;
70
70
  this._res = res;
71
71
  this.headersSent = false;
72
- this.aborted = false;
73
72
  this.app = app;
74
73
  this.locals = {};
74
+ this.finished = false;
75
75
  this.aborted = false;
76
76
  this.statusCode = 200;
77
77
  this.chunkedTransfer = true;
78
- this.finished = false;
79
78
  this.totalSize = 0;
80
79
  this.headers = {
81
80
  'connection': 'keep-alive',
@@ -96,7 +95,7 @@ module.exports = class Response extends Writable {
96
95
  });
97
96
  this.body = undefined;
98
97
  this.on('error', (err) => {
99
- if(this.aborted) {
98
+ if(this.finished) {
100
99
  return;
101
100
  }
102
101
  this._res.cork(() => {
@@ -121,6 +120,10 @@ module.exports = class Response extends Writable {
121
120
  err.code = 'ECONNABORTED';
122
121
  return this.destroy(err);
123
122
  }
123
+ if(this.finished) {
124
+ const err = new Error('Response already finished');
125
+ return this.destroy(err);
126
+ }
124
127
  this._res.cork(() => {
125
128
  if(!this.headersSent) {
126
129
  this.writeHead(this.statusCode);
@@ -149,7 +152,7 @@ module.exports = class Response extends Writable {
149
152
  if(!ok) {
150
153
  // wait until uWS is ready to accept more data
151
154
  this._res.onWritable((offset) => {
152
- if(this.aborted) {
155
+ if(this.finished) {
153
156
  return true;
154
157
  }
155
158
  const [ok, done] = this._res.tryEnd(chunk.slice(offset - lastOffset), this.totalSize);
@@ -221,7 +224,7 @@ module.exports = class Response extends Writable {
221
224
  if(this.finished) {
222
225
  return;
223
226
  }
224
-
227
+ this.writeHead(this.statusCode);
225
228
  this._res.cork(() => {
226
229
  if(!this.headersSent) {
227
230
  const etagFn = this.app.get('etag fn');
@@ -283,7 +286,6 @@ module.exports = class Response extends Writable {
283
286
  this.headers['content-type'] += '; charset=utf-8';
284
287
  }
285
288
  }
286
- this.writeHead(this.statusCode);
287
289
  return this.end(body);
288
290
  }
289
291
  sendFile(path, options = {}, callback) {
@@ -462,7 +464,7 @@ module.exports = class Response extends Writable {
462
464
  // serve smaller files using workers
463
465
  if(this.app.workers.length && stat.size < 768 * 1024 && !ranged) {
464
466
  this.app.readFileWithWorker(fullpath).then((data) => {
465
- if(this._res.aborted) {
467
+ if(this._res.finished) {
466
468
  return;
467
469
  }
468
470
  this.end(data);
@@ -730,7 +732,7 @@ module.exports = class Response extends Writable {
730
732
 
731
733
  function pipeStreamOverResponse(res, readStream, totalSize, callback) {
732
734
  readStream.on('data', (chunk) => {
733
- if(res.aborted) {
735
+ if(res.finished) {
734
736
  return readStream.destroy();
735
737
  }
736
738
  res._res.cork(() => {
@@ -756,7 +758,7 @@ function pipeStreamOverResponse(res, readStream, totalSize, callback) {
756
758
  res._res.abOffset = lastOffset;
757
759
 
758
760
  res._res.onWritable((offset) => {
759
- if(res.aborted) {
761
+ if(res.finished) {
760
762
  return true;
761
763
  }
762
764
  const [ok, done] = res._res.tryEnd(res._res.ab.slice(offset - res._res.abOffset), totalSize);
@@ -781,4 +783,4 @@ function pipeStreamOverResponse(res, readStream, totalSize, callback) {
781
783
  if(res.socketExists) res.socket.emit('error', e);
782
784
  }
783
785
  });
784
- }
786
+ }
package/src/router.js CHANGED
@@ -248,6 +248,7 @@ module.exports = class Router extends EventEmitter {
248
248
  const err = new Error('Connection closed');
249
249
  err.code = 'ECONNRESET';
250
250
  response.aborted = true;
251
+ response.finished = true;
251
252
  response.socket.emit('error', err);
252
253
  });
253
254
 
@@ -484,7 +485,12 @@ module.exports = class Router extends EventEmitter {
484
485
  const out = callback(req, res, next);
485
486
  if(out instanceof Promise) {
486
487
  out.catch(err => {
487
- throw err;
488
+ if(this.get("catch async errors")) {
489
+ this._handleError(err, req, res);
490
+ return resolve(true);
491
+ } else {
492
+ throw err;
493
+ }
488
494
  });
489
495
  }
490
496
  } catch(err) {
package/src/types.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ declare module 'ultimate-express' {
2
+ import express from '@types/express';
3
+ export = express;
4
+ }