@morojs/moro 1.8.5 → 1.8.7
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 +7 -6
- package/dist/core/http/http-server.d.ts +5 -3
- package/dist/core/http/http-server.js +38 -11
- package/dist/core/http/http-server.js.map +1 -1
- package/dist/core/http/http2-server.d.ts +1 -1
- package/dist/core/http/http2-server.js +23 -9
- package/dist/core/http/http2-server.js.map +1 -1
- package/dist/core/http/moro-engine-server.d.ts +24 -4
- package/dist/core/http/moro-engine-server.js +194 -42
- package/dist/core/http/moro-engine-server.js.map +1 -1
- package/dist/core/jobs/job-executor.d.ts +1 -0
- package/dist/core/jobs/job-executor.js +23 -1
- package/dist/core/jobs/job-executor.js.map +1 -1
- package/dist/core/middleware/built-in/auth/helpers.js +11 -1
- package/dist/core/middleware/built-in/auth/helpers.js.map +1 -1
- package/dist/core/pooling/object-pool-manager.js +14 -20
- package/dist/core/pooling/object-pool-manager.js.map +1 -1
- package/dist/core/routing/radix-tree.d.ts +1 -0
- package/dist/core/routing/radix-tree.js +6 -1
- package/dist/core/routing/radix-tree.js.map +1 -1
- package/dist/core/routing/unified-router.js +33 -25
- package/dist/core/routing/unified-router.js.map +1 -1
- package/dist/core/utilities/hooks.d.ts +2 -0
- package/dist/core/utilities/hooks.js +28 -2
- package/dist/core/utilities/hooks.js.map +1 -1
- package/dist/moro.js +12 -0
- package/dist/moro.js.map +1 -1
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
|
|
9
9
|
[](https://badge.fury.io/js/@morojs%2Fmoro)
|
|
10
10
|
[](https://opensource.org/licenses/MIT)
|
|
11
|
-
[](https://nodejs.org/)
|
|
12
12
|
|
|
13
|
-
[**Website**](https://morojs.com) • [**Documentation**](https://morojs.com/docs) • [**Quick Start**](https://morojs.com/docs/
|
|
13
|
+
[**Website**](https://morojs.com) • [**Documentation**](https://morojs.com/docs) • [**Quick Start**](https://morojs.com/docs/quick-start) • [**Discord**](https://morojs.com/discord)
|
|
14
14
|
|
|
15
15
|
</div>
|
|
16
16
|
|
|
@@ -18,12 +18,12 @@
|
|
|
18
18
|
|
|
19
19
|
## Why MoroJS?
|
|
20
20
|
|
|
21
|
-
Build high-performance APIs with intelligent routing
|
|
21
|
+
Build high-performance APIs with intelligent routing: declare what a route needs and MoroJS runs it in the optimal, security-first order every time — rate limiting sheds floods before auth, auth gates the cache. Middleware ordering stops being something you can get wrong. Deploy anywhere: Node.js, Vercel Edge, AWS Lambda, or Cloudflare Workers - same code, zero configuration.
|
|
22
22
|
|
|
23
23
|
**Key Features:**
|
|
24
24
|
|
|
25
25
|
- **Native C++ Engine** - ~102k req/s real-world through the full framework, 572k pipelined, on a single thread
|
|
26
|
-
- **Intelligent Routing** -
|
|
26
|
+
- **Intelligent Routing** - Declare auth, validation, rate limits and caching in any order; they always execute in the optimal, security-first one
|
|
27
27
|
- **Enterprise Auth** - Built-in Better Auth with OAuth & RBAC
|
|
28
28
|
- **Universal Validation** - Works with Zod, Joi, Yup, or Class Validator
|
|
29
29
|
- **Message Queues** - Production-ready queues (Bull, RabbitMQ, SQS, Kafka)
|
|
@@ -53,6 +53,7 @@ import { createApp, z } from '@morojs/moro';
|
|
|
53
53
|
const app = await createApp();
|
|
54
54
|
|
|
55
55
|
// Intelligent routing - order doesn't matter!
|
|
56
|
+
// (rate limit -> auth -> validation -> cache -> handler)
|
|
56
57
|
app
|
|
57
58
|
.post('/users')
|
|
58
59
|
.body(
|
|
@@ -196,7 +197,7 @@ Check out [working examples](https://github.com/Moro-JS/examples) for:
|
|
|
196
197
|
|
|
197
198
|
## Why Choose MoroJS?
|
|
198
199
|
|
|
199
|
-
**vs Express** - Intelligent middleware
|
|
200
|
+
**vs Express** - Intelligent security-first middleware pipeline eliminates ordering bugs and configuration complexity
|
|
200
201
|
|
|
201
202
|
**vs Fastify** - ~1.5x the throughput out of the box (Moro's native engine), plus multi-runtime deployment without adapters
|
|
202
203
|
|
|
@@ -216,6 +217,6 @@ MIT © [Moro Framework Team](https://morojs.com)
|
|
|
216
217
|
|
|
217
218
|
**Ready to build high-performance APIs?**
|
|
218
219
|
|
|
219
|
-
[Get Started](https://morojs.com/docs/
|
|
220
|
+
[Get Started](https://morojs.com/docs/quick-start) • [GitHub](https://github.com/Moro-JS/moro) • [npm](https://www.npmjs.com/package/@morojs/moro) • [Discord](https://morojs.com/discord)
|
|
220
221
|
|
|
221
222
|
</div>
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { Server } from 'http';
|
|
2
2
|
import type { HttpRuntimeLimits } from './utils/size.js';
|
|
3
3
|
import { HttpRequest, HttpResponse, HttpHandler, Middleware } from '../../types/http.js';
|
|
4
|
-
|
|
4
|
+
declare const http: typeof import("http");
|
|
5
|
+
export declare class MoroIncomingMessage extends http.IncomingMessage {
|
|
5
6
|
/** Bound on the per-server subclass prototype - no per-request write needed */
|
|
6
7
|
_server: MoroHttpServer;
|
|
7
8
|
params: Record<string, string>;
|
|
@@ -39,7 +40,7 @@ export declare class MoroIncomingMessage extends IncomingMessage {
|
|
|
39
40
|
accepts(types?: string | string[]): string | false;
|
|
40
41
|
acceptsLanguages(langs?: string | string[]): string | false;
|
|
41
42
|
}
|
|
42
|
-
export declare class MoroServerResponse extends ServerResponse {
|
|
43
|
+
export declare class MoroServerResponse extends http.ServerResponse {
|
|
43
44
|
/** Bound on the per-server subclass prototype - no per-request write needed */
|
|
44
45
|
_server: MoroHttpServer;
|
|
45
46
|
_locals: Record<string, any> | undefined;
|
|
@@ -256,3 +257,4 @@ export declare class MoroHttpServer {
|
|
|
256
257
|
};
|
|
257
258
|
};
|
|
258
259
|
}
|
|
260
|
+
export {};
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
import { IncomingMessage, ServerResponse, createServer } from 'http';
|
|
3
|
-
import { createServer as createHttpsServer } from 'https';
|
|
4
|
-
import * as zlib from 'zlib';
|
|
1
|
+
import { createRequire } from 'module';
|
|
5
2
|
import { promisify } from 'util';
|
|
6
3
|
import { randomUUID } from 'crypto';
|
|
7
4
|
import { createFrameworkLogger } from '../logger/index.js';
|
|
@@ -9,8 +6,35 @@ import { parseMultipart as parseMultipartBuffer, } from './utils/multipart-parse
|
|
|
9
6
|
import { parseRawQueryString } from './utils/query-parser.js';
|
|
10
7
|
import { PathMatcher } from '../routing/path-matcher.js';
|
|
11
8
|
import { ObjectPoolManager } from '../pooling/object-pool-manager.js';
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
// `node:https` and `node:zlib` are resolved on first use rather than at import
|
|
10
|
+
// time. This module is on every app's startup path, but plaintext HTTP apps
|
|
11
|
+
// never touch https (~1.9 MB RSS, it drags in tls) and uncompressed responses
|
|
12
|
+
// never touch zlib (~0.3 MB). Builtins are always synchronously requirable, so
|
|
13
|
+
// the secure-server and compression paths stay fully synchronous.
|
|
14
|
+
// Resolves Node builtins ONLY, so the base passed to createRequire is
|
|
15
|
+
// irrelevant - 'file:///' is used instead of import.meta.url so this file still
|
|
16
|
+
// compiles under the CJS transform Jest applies to the test suite.
|
|
17
|
+
const requireBuiltin = createRequire('file:///');
|
|
18
|
+
// `node:http` is pulled through createRequire rather than `import`. In an ESM
|
|
19
|
+
// package the two are NOT equivalent: building the ESM facade for node:http
|
|
20
|
+
// drags in http2, tls, zlib and worker_threads and costs ~10.4 MB RSS, while
|
|
21
|
+
// require('http') costs ~0.9 MB and pulls only net. Same objects, same
|
|
22
|
+
// semantics - measurably less memory. See also the lazy https/zlib below.
|
|
23
|
+
const http = requireBuiltin('http');
|
|
24
|
+
const createServer = http.createServer;
|
|
25
|
+
let gzipFn;
|
|
26
|
+
let deflateFn;
|
|
27
|
+
function compressors() {
|
|
28
|
+
if (!gzipFn) {
|
|
29
|
+
const zlib = requireBuiltin('zlib');
|
|
30
|
+
gzipFn = promisify(zlib.gzip);
|
|
31
|
+
deflateFn = promisify(zlib.deflate);
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
gzip: gzipFn,
|
|
35
|
+
deflate: deflateFn,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
14
38
|
const JSON_CONTENT_TYPE = 'application/json; charset=utf-8';
|
|
15
39
|
const STATUS_MESSAGES = {
|
|
16
40
|
200: 'OK',
|
|
@@ -83,7 +107,7 @@ function parseCookieHeader(cookieHeader) {
|
|
|
83
107
|
// the `_server` back-reference, so methods can reach server config (logger,
|
|
84
108
|
// compression settings) without any per-request allocation.
|
|
85
109
|
// ---------------------------------------------------------------------------
|
|
86
|
-
export class MoroIncomingMessage extends IncomingMessage {
|
|
110
|
+
export class MoroIncomingMessage extends http.IncomingMessage {
|
|
87
111
|
// Hot per-request fields (assigned in handleRequest; declared here for
|
|
88
112
|
// stable shape). Everything else lives behind the single `_lazy` slot -
|
|
89
113
|
// per-request construction pays 5 field initializations instead of 16.
|
|
@@ -327,7 +351,7 @@ export class MoroIncomingMessage extends IncomingMessage {
|
|
|
327
351
|
return false;
|
|
328
352
|
}
|
|
329
353
|
}
|
|
330
|
-
export class MoroServerResponse extends ServerResponse {
|
|
354
|
+
export class MoroServerResponse extends http.ServerResponse {
|
|
331
355
|
_locals = undefined;
|
|
332
356
|
get locals() {
|
|
333
357
|
let l = this._locals;
|
|
@@ -354,7 +378,8 @@ export class MoroServerResponse extends ServerResponse {
|
|
|
354
378
|
const acceptEncoding = this.req?.headers['accept-encoding'];
|
|
355
379
|
if (acceptEncoding && acceptEncoding.includes('gzip')) {
|
|
356
380
|
const buffer = Buffer.from(jsonString, 'utf8');
|
|
357
|
-
|
|
381
|
+
compressors()
|
|
382
|
+
.gzip(buffer)
|
|
358
383
|
.then(compressed => {
|
|
359
384
|
if (this.headersSent)
|
|
360
385
|
return;
|
|
@@ -385,7 +410,8 @@ export class MoroServerResponse extends ServerResponse {
|
|
|
385
410
|
}
|
|
386
411
|
else if (acceptEncoding && acceptEncoding.includes('deflate')) {
|
|
387
412
|
const buffer = Buffer.from(jsonString, 'utf8');
|
|
388
|
-
|
|
413
|
+
compressors()
|
|
414
|
+
.deflate(buffer)
|
|
389
415
|
.then(compressed => {
|
|
390
416
|
if (this.headersSent)
|
|
391
417
|
return;
|
|
@@ -935,7 +961,8 @@ export class MoroHttpServer {
|
|
|
935
961
|
if (options?.ssl) {
|
|
936
962
|
// In-process HTTPS. The https ServerOptions extends the http one, so the
|
|
937
963
|
// IncomingMessage/ServerResponse subclass injection carries over.
|
|
938
|
-
|
|
964
|
+
const https = requireBuiltin('https');
|
|
965
|
+
this.server = https.createServer({ ...serverOpts, ...options.ssl }, this.handleRequest.bind(this));
|
|
939
966
|
this.logger.info('HTTPS server created (in-process TLS)', 'HttpServer');
|
|
940
967
|
}
|
|
941
968
|
else {
|