@abejarano/ts-express-server 1.5.3 → 1.7.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 +14 -2
- package/dist/BootstrapServer.d.ts +13 -6
- package/dist/BootstrapServer.js +30 -23
- package/dist/BootstrapStandardServer.d.ts +2 -1
- package/dist/BootstrapStandardServer.js +6 -4
- package/dist/abstract/ServerModule.d.ts +2 -2
- package/dist/abstract/ServerService.d.ts +2 -2
- package/dist/abstract/ServerTypes.d.ts +64 -0
- package/dist/abstract/ServerTypes.js +8 -0
- package/dist/abstract/index.d.ts +1 -0
- package/dist/abstract/index.js +1 -0
- package/dist/adapters/BunAdapter.d.ts +18 -0
- package/dist/adapters/BunAdapter.js +741 -0
- package/dist/adapters/ExpressAdapter.d.ts +8 -0
- package/dist/adapters/ExpressAdapter.js +40 -0
- package/dist/adapters/index.d.ts +2 -0
- package/dist/adapters/index.js +18 -0
- package/dist/createRouter.d.ts +2 -0
- package/dist/createRouter.js +12 -0
- package/dist/decorators/Controller.d.ts +1 -1
- package/dist/decorators/Controller.js +4 -1
- package/dist/decorators/DecoratorGuards.d.ts +1 -0
- package/dist/decorators/DecoratorGuards.js +14 -0
- package/dist/decorators/Handlers.d.ts +5 -5
- package/dist/decorators/Handlers.js +5 -1
- package/dist/decorators/Use.d.ts +2 -2
- package/dist/decorators/Use.js +5 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.js +2 -0
- package/dist/modules/ControllersModule.d.ts +2 -2
- package/dist/modules/ControllersModule.js +14 -8
- package/dist/modules/CorsModule.d.ts +2 -2
- package/dist/modules/CorsModule.js +66 -2
- package/dist/modules/FileUploadModule.d.ts +4 -4
- package/dist/modules/FileUploadModule.js +43 -6
- package/dist/modules/RateLimitModule.d.ts +4 -4
- package/dist/modules/RateLimitModule.js +48 -7
- package/dist/modules/RequestContextModule.d.ts +2 -9
- package/dist/modules/RequestContextModule.js +53 -4
- package/dist/modules/RoutesModule.d.ts +4 -4
- package/dist/modules/RoutesModule.js +12 -3
- package/dist/modules/SecurityModule.d.ts +4 -4
- package/dist/modules/SecurityModule.js +43 -6
- package/dist/testing/createDecoratedTestApp.d.ts +3 -3
- package/dist/testing/createDecoratedTestApp.js +8 -4
- package/package.json +1 -1
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ServerAdapter, ServerApp, ServerInstance, ServerRouter, ServerRuntime } from "../abstract/ServerTypes";
|
|
2
|
+
export declare class ExpressAdapter implements ServerAdapter {
|
|
3
|
+
runtime: ServerRuntime;
|
|
4
|
+
createApp(): ServerApp;
|
|
5
|
+
createRouter(): ServerRouter;
|
|
6
|
+
configure(app: ServerApp, port: number): void;
|
|
7
|
+
listen(app: ServerApp, port: number, onListen: () => void): ServerInstance;
|
|
8
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ExpressAdapter = void 0;
|
|
4
|
+
const ServerTypes_1 = require("../abstract/ServerTypes");
|
|
5
|
+
let expressModule = null;
|
|
6
|
+
const getExpressModule = () => {
|
|
7
|
+
if (!expressModule) {
|
|
8
|
+
expressModule = require("express");
|
|
9
|
+
}
|
|
10
|
+
return expressModule;
|
|
11
|
+
};
|
|
12
|
+
class ExpressAdapter {
|
|
13
|
+
constructor() {
|
|
14
|
+
this.runtime = ServerTypes_1.ServerRuntime.Express;
|
|
15
|
+
}
|
|
16
|
+
createApp() {
|
|
17
|
+
const express = getExpressModule();
|
|
18
|
+
return express();
|
|
19
|
+
}
|
|
20
|
+
createRouter() {
|
|
21
|
+
const express = getExpressModule();
|
|
22
|
+
return express.Router();
|
|
23
|
+
}
|
|
24
|
+
configure(app, port) {
|
|
25
|
+
const expressApp = app;
|
|
26
|
+
const express = getExpressModule();
|
|
27
|
+
const bodyParser = require("body-parser");
|
|
28
|
+
const cookieParser = require("cookie-parser");
|
|
29
|
+
expressApp.use(express.json());
|
|
30
|
+
expressApp.use(bodyParser.urlencoded({ extended: true }));
|
|
31
|
+
expressApp.use(cookieParser());
|
|
32
|
+
expressApp.set("port", port);
|
|
33
|
+
expressApp.set("trust proxy", 1);
|
|
34
|
+
}
|
|
35
|
+
listen(app, port, onListen) {
|
|
36
|
+
const expressApp = app;
|
|
37
|
+
return expressApp.listen(port, onListen);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
exports.ExpressAdapter = ExpressAdapter;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./BunAdapter"), exports);
|
|
18
|
+
__exportStar(require("./ExpressAdapter"), exports);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createRouter = void 0;
|
|
4
|
+
const abstract_1 = require("./abstract");
|
|
5
|
+
const adapters_1 = require("./adapters");
|
|
6
|
+
const createRouter = (runtime = abstract_1.ServerRuntime.Express) => {
|
|
7
|
+
if (runtime === abstract_1.ServerRuntime.Bun) {
|
|
8
|
+
return new adapters_1.BunAdapter().createRouter();
|
|
9
|
+
}
|
|
10
|
+
return new adapters_1.ExpressAdapter().createRouter();
|
|
11
|
+
};
|
|
12
|
+
exports.createRouter = createRouter;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import "reflect-metadata";
|
|
2
|
-
export declare function Controller(basePath: string): (
|
|
2
|
+
export declare function Controller(basePath: string): (...args: any[]) => void;
|
|
@@ -2,9 +2,12 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Controller = Controller;
|
|
4
4
|
const MetadataKeys_1 = require("./MetadataKeys");
|
|
5
|
+
const DecoratorGuards_1 = require("./DecoratorGuards");
|
|
5
6
|
require("reflect-metadata");
|
|
6
7
|
function Controller(basePath) {
|
|
7
|
-
return function (
|
|
8
|
+
return function (...args) {
|
|
9
|
+
(0, DecoratorGuards_1.assertLegacyDecorator)(args, "@Controller");
|
|
10
|
+
const target = args[0];
|
|
8
11
|
Reflect.defineMetadata(MetadataKeys_1.MetadataKeys.BASE_PATH, basePath, target);
|
|
9
12
|
};
|
|
10
13
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function assertLegacyDecorator(args: any[], decoratorName: string): void;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.assertLegacyDecorator = assertLegacyDecorator;
|
|
4
|
+
function assertLegacyDecorator(args, decoratorName) {
|
|
5
|
+
const context = args[1];
|
|
6
|
+
if (args.length === 2 &&
|
|
7
|
+
context &&
|
|
8
|
+
typeof context === "object" &&
|
|
9
|
+
"kind" in context) {
|
|
10
|
+
throw new Error(`[ts-express-server] ${decoratorName} is not compatible with ` +
|
|
11
|
+
`standard TypeScript decorators. Enable "experimentalDecorators": true ` +
|
|
12
|
+
`in your tsconfig and ensure your files are included by that config.`);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -11,8 +11,8 @@ export interface IRouter {
|
|
|
11
11
|
path: string;
|
|
12
12
|
handlerName: string | symbol;
|
|
13
13
|
}
|
|
14
|
-
export declare const Get: (path: string) => (
|
|
15
|
-
export declare const Post: (path: string) => (
|
|
16
|
-
export declare const Put: (path: string) => (
|
|
17
|
-
export declare const Delete: (path: string) => (
|
|
18
|
-
export declare const Patch: (path: string) => (
|
|
14
|
+
export declare const Get: (path: string) => (...args: any[]) => void;
|
|
15
|
+
export declare const Post: (path: string) => (...args: any[]) => void;
|
|
16
|
+
export declare const Put: (path: string) => (...args: any[]) => void;
|
|
17
|
+
export declare const Delete: (path: string) => (...args: any[]) => void;
|
|
18
|
+
export declare const Patch: (path: string) => (...args: any[]) => void;
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Patch = exports.Delete = exports.Put = exports.Post = exports.Get = exports.Methods = void 0;
|
|
4
4
|
const MetadataKeys_1 = require("./MetadataKeys");
|
|
5
|
+
const DecoratorGuards_1 = require("./DecoratorGuards");
|
|
5
6
|
require("reflect-metadata");
|
|
6
7
|
var Methods;
|
|
7
8
|
(function (Methods) {
|
|
@@ -13,7 +14,10 @@ var Methods;
|
|
|
13
14
|
})(Methods || (exports.Methods = Methods = {}));
|
|
14
15
|
function methodDecorator(method) {
|
|
15
16
|
return function (path) {
|
|
16
|
-
return function (
|
|
17
|
+
return function (...args) {
|
|
18
|
+
(0, DecoratorGuards_1.assertLegacyDecorator)(args, `@${method.toUpperCase()}`);
|
|
19
|
+
const target = args[0];
|
|
20
|
+
const key = args[1];
|
|
17
21
|
const routers = Reflect.getMetadata(MetadataKeys_1.MetadataKeys.ROUTERS, target) || [];
|
|
18
22
|
routers.push({
|
|
19
23
|
method,
|
package/dist/decorators/Use.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ServerHandler } from "../abstract";
|
|
2
2
|
import "reflect-metadata";
|
|
3
|
-
export declare function Use(middleware:
|
|
3
|
+
export declare function Use(middleware: ServerHandler | ServerHandler[]): (...args: any[]) => void;
|
package/dist/decorators/Use.js
CHANGED
|
@@ -2,9 +2,13 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Use = Use;
|
|
4
4
|
const MetadataKeys_1 = require("./MetadataKeys");
|
|
5
|
+
const DecoratorGuards_1 = require("./DecoratorGuards");
|
|
5
6
|
require("reflect-metadata");
|
|
6
7
|
function Use(middleware) {
|
|
7
|
-
return function (
|
|
8
|
+
return function (...args) {
|
|
9
|
+
(0, DecoratorGuards_1.assertLegacyDecorator)(args, "@Use");
|
|
10
|
+
const target = args[0];
|
|
11
|
+
const key = args[1];
|
|
8
12
|
const newMiddlewares = Array.isArray(middleware)
|
|
9
13
|
? middleware
|
|
10
14
|
: [middleware];
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import "reflect-metadata";
|
|
2
2
|
export { BootstrapServer } from "./BootstrapServer";
|
|
3
|
+
export type { BootstrapServerOptions } from "./BootstrapServer";
|
|
3
4
|
export { BootstrapStandardServer } from "./BootstrapStandardServer";
|
|
4
5
|
export type { BootstrapStandardServerOptions } from "./BootstrapStandardServer";
|
|
6
|
+
export * from "./adapters";
|
|
7
|
+
export * from "./createRouter";
|
|
5
8
|
export * from "./modules";
|
|
6
9
|
export * from "./abstract";
|
|
7
10
|
export * from "./decorators";
|
package/dist/index.js
CHANGED
|
@@ -20,6 +20,8 @@ var BootstrapServer_1 = require("./BootstrapServer");
|
|
|
20
20
|
Object.defineProperty(exports, "BootstrapServer", { enumerable: true, get: function () { return BootstrapServer_1.BootstrapServer; } });
|
|
21
21
|
var BootstrapStandardServer_1 = require("./BootstrapStandardServer");
|
|
22
22
|
Object.defineProperty(exports, "BootstrapStandardServer", { enumerable: true, get: function () { return BootstrapStandardServer_1.BootstrapStandardServer; } });
|
|
23
|
+
__exportStar(require("./adapters"), exports);
|
|
24
|
+
__exportStar(require("./createRouter"), exports);
|
|
23
25
|
__exportStar(require("./modules"), exports);
|
|
24
26
|
__exportStar(require("./abstract"), exports);
|
|
25
27
|
__exportStar(require("./decorators"), exports);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Express } from "express";
|
|
2
1
|
import { BaseServerModule } from "../abstract";
|
|
2
|
+
import { ServerApp, ServerContext } from "../abstract";
|
|
3
3
|
import "reflect-metadata";
|
|
4
4
|
export declare class ControllersModule extends BaseServerModule {
|
|
5
5
|
private controllers;
|
|
@@ -7,5 +7,5 @@ export declare class ControllersModule extends BaseServerModule {
|
|
|
7
7
|
priority: number;
|
|
8
8
|
constructor(controllers: Function[]);
|
|
9
9
|
getModuleName(): string;
|
|
10
|
-
init(app:
|
|
10
|
+
init(app: ServerApp, context?: ServerContext): void;
|
|
11
11
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ControllersModule = void 0;
|
|
4
|
-
const express_1 = require("express");
|
|
5
4
|
const abstract_1 = require("../abstract");
|
|
5
|
+
const adapters_1 = require("../adapters");
|
|
6
6
|
const MetadataKeys_1 = require("../decorators/MetadataKeys");
|
|
7
7
|
const Parameters_1 = require("../decorators/Parameters");
|
|
8
8
|
require("reflect-metadata");
|
|
@@ -16,16 +16,16 @@ class ControllersModule extends abstract_1.BaseServerModule {
|
|
|
16
16
|
getModuleName() {
|
|
17
17
|
return this.name;
|
|
18
18
|
}
|
|
19
|
-
init(app) {
|
|
19
|
+
init(app, context) {
|
|
20
20
|
this.controllers.forEach((ControllerClass) => {
|
|
21
21
|
const basePath = Reflect.getMetadata(MetadataKeys_1.MetadataKeys.BASE_PATH, ControllerClass);
|
|
22
22
|
const classMiddlewares = Reflect.getMetadata(MetadataKeys_1.MetadataKeys.MIDDLEWARE, ControllerClass) || [];
|
|
23
|
-
const routers = Reflect.getMetadata(MetadataKeys_1.MetadataKeys.ROUTERS, ControllerClass.prototype) ||
|
|
24
|
-
[];
|
|
23
|
+
const routers = Reflect.getMetadata(MetadataKeys_1.MetadataKeys.ROUTERS, ControllerClass.prototype) || [];
|
|
25
24
|
if (!basePath) {
|
|
26
25
|
return;
|
|
27
26
|
}
|
|
28
|
-
const
|
|
27
|
+
const adapter = context?.adapter ?? new adapters_1.ExpressAdapter();
|
|
28
|
+
const router = adapter.createRouter();
|
|
29
29
|
// Create a single controller instance per controller class (singleton pattern)
|
|
30
30
|
const controllerInstance = new ControllerClass();
|
|
31
31
|
// Apply class-level middlewares
|
|
@@ -36,7 +36,8 @@ class ControllersModule extends abstract_1.BaseServerModule {
|
|
|
36
36
|
const routeHandler = ControllerClass.prototype[handlerName];
|
|
37
37
|
const routeMiddlewares = Reflect.getMetadata(MetadataKeys_1.MetadataKeys.MIDDLEWARE, ControllerClass.prototype, handlerName) || [];
|
|
38
38
|
const parameterMetadata = Reflect.getMetadata(MetadataKeys_1.MetadataKeys.PARAMETERS, ControllerClass.prototype, handlerName) || [];
|
|
39
|
-
router[method](
|
|
39
|
+
const routerMethod = router[method]?.bind(router);
|
|
40
|
+
routerMethod(path, ...routeMiddlewares, async (req, res, next) => {
|
|
40
41
|
if (parameterMetadata.length === 0) {
|
|
41
42
|
try {
|
|
42
43
|
const result = routeHandler.call(controllerInstance, req, res, next);
|
|
@@ -54,8 +55,13 @@ class ControllersModule extends abstract_1.BaseServerModule {
|
|
|
54
55
|
parameterMetadata.forEach((param) => {
|
|
55
56
|
switch (param.type) {
|
|
56
57
|
case Parameters_1.ParameterType.BODY:
|
|
57
|
-
|
|
58
|
-
|
|
58
|
+
if (param.data) {
|
|
59
|
+
const body = req.body;
|
|
60
|
+
args[param.index] = body ? body[param.data] : undefined;
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
args[param.index] = req.body;
|
|
64
|
+
}
|
|
59
65
|
break;
|
|
60
66
|
case Parameters_1.ParameterType.PARAM:
|
|
61
67
|
args[param.index] = param.data
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Express } from "express";
|
|
2
1
|
import { BaseServerModule } from "../abstract";
|
|
2
|
+
import { ServerApp, ServerContext } from "../abstract";
|
|
3
3
|
import cors from "cors";
|
|
4
4
|
export declare class CorsModule extends BaseServerModule {
|
|
5
5
|
name: string;
|
|
@@ -7,5 +7,5 @@ export declare class CorsModule extends BaseServerModule {
|
|
|
7
7
|
private corsOptions;
|
|
8
8
|
constructor(corsOptions?: cors.CorsOptions);
|
|
9
9
|
getModuleName(): string;
|
|
10
|
-
init(app:
|
|
10
|
+
init(app: ServerApp, context?: ServerContext): void;
|
|
11
11
|
}
|
|
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.CorsModule = void 0;
|
|
7
7
|
const abstract_1 = require("../abstract");
|
|
8
|
+
const abstract_2 = require("../abstract");
|
|
8
9
|
const cors_1 = __importDefault(require("cors"));
|
|
9
10
|
class CorsModule extends abstract_1.BaseServerModule {
|
|
10
11
|
constructor(corsOptions) {
|
|
@@ -20,8 +21,71 @@ class CorsModule extends abstract_1.BaseServerModule {
|
|
|
20
21
|
getModuleName() {
|
|
21
22
|
return this.name;
|
|
22
23
|
}
|
|
23
|
-
init(app) {
|
|
24
|
-
|
|
24
|
+
init(app, context) {
|
|
25
|
+
const runtime = context?.runtime ?? abstract_2.ServerRuntime.Express;
|
|
26
|
+
if (runtime === abstract_2.ServerRuntime.Express) {
|
|
27
|
+
app.use((0, cors_1.default)(this.corsOptions));
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
app.use(createCorsMiddleware(this.corsOptions));
|
|
25
31
|
}
|
|
26
32
|
}
|
|
27
33
|
exports.CorsModule = CorsModule;
|
|
34
|
+
const createCorsMiddleware = (options) => {
|
|
35
|
+
return (req, res, next) => {
|
|
36
|
+
const originHeader = String(req.headers?.origin || "");
|
|
37
|
+
const allowOrigin = resolveOrigin(options.origin, originHeader);
|
|
38
|
+
if (allowOrigin) {
|
|
39
|
+
res.set("access-control-allow-origin", allowOrigin);
|
|
40
|
+
}
|
|
41
|
+
if (options.credentials) {
|
|
42
|
+
res.set("access-control-allow-credentials", "true");
|
|
43
|
+
}
|
|
44
|
+
if (options.methods) {
|
|
45
|
+
res.set("access-control-allow-methods", Array.isArray(options.methods) ? options.methods.join(",") : options.methods);
|
|
46
|
+
}
|
|
47
|
+
if (options.allowedHeaders) {
|
|
48
|
+
res.set("access-control-allow-headers", Array.isArray(options.allowedHeaders)
|
|
49
|
+
? options.allowedHeaders.join(",")
|
|
50
|
+
: options.allowedHeaders);
|
|
51
|
+
}
|
|
52
|
+
if (options.maxAge !== undefined) {
|
|
53
|
+
res.set("access-control-max-age", String(options.maxAge));
|
|
54
|
+
}
|
|
55
|
+
if (req.method === "OPTIONS") {
|
|
56
|
+
res.status(204).end();
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
next();
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
const resolveOrigin = (originOption, requestOrigin) => {
|
|
63
|
+
if (!originOption || originOption === "*") {
|
|
64
|
+
return "*";
|
|
65
|
+
}
|
|
66
|
+
if (originOption === true) {
|
|
67
|
+
return requestOrigin || "*";
|
|
68
|
+
}
|
|
69
|
+
if (typeof originOption === "string") {
|
|
70
|
+
return originOption;
|
|
71
|
+
}
|
|
72
|
+
if (Array.isArray(originOption)) {
|
|
73
|
+
return originOption.includes(requestOrigin) ? requestOrigin : undefined;
|
|
74
|
+
}
|
|
75
|
+
if (typeof originOption === "function") {
|
|
76
|
+
let resolved;
|
|
77
|
+
originOption(requestOrigin, (err, value) => {
|
|
78
|
+
if (err) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
if (value === true) {
|
|
82
|
+
resolved = requestOrigin || "*";
|
|
83
|
+
}
|
|
84
|
+
else if (typeof value === "string") {
|
|
85
|
+
resolved = value;
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
return resolved;
|
|
89
|
+
}
|
|
90
|
+
return undefined;
|
|
91
|
+
};
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { Express } from "express";
|
|
2
|
-
import fileUpload from "express-fileupload";
|
|
3
1
|
import { BaseServerModule } from "../abstract";
|
|
2
|
+
import { ServerApp, ServerContext } from "../abstract";
|
|
3
|
+
import type { Options as FileUploadOptions } from "express-fileupload";
|
|
4
4
|
export declare class FileUploadModule extends BaseServerModule {
|
|
5
5
|
name: string;
|
|
6
6
|
priority: number;
|
|
7
7
|
private fileUploadOptions;
|
|
8
|
-
constructor(fileUploadOptions?:
|
|
8
|
+
constructor(fileUploadOptions?: FileUploadOptions);
|
|
9
9
|
getModuleName(): string;
|
|
10
|
-
init(app:
|
|
10
|
+
init(app: ServerApp, context?: ServerContext): void;
|
|
11
11
|
}
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.FileUploadModule = void 0;
|
|
7
|
-
const express_fileupload_1 = __importDefault(require("express-fileupload"));
|
|
8
4
|
const abstract_1 = require("../abstract");
|
|
5
|
+
const abstract_2 = require("../abstract");
|
|
9
6
|
class FileUploadModule extends abstract_1.BaseServerModule {
|
|
10
7
|
constructor(fileUploadOptions) {
|
|
11
8
|
super();
|
|
@@ -20,8 +17,48 @@ class FileUploadModule extends abstract_1.BaseServerModule {
|
|
|
20
17
|
getModuleName() {
|
|
21
18
|
return this.name;
|
|
22
19
|
}
|
|
23
|
-
init(app) {
|
|
24
|
-
|
|
20
|
+
init(app, context) {
|
|
21
|
+
const runtime = context?.runtime ?? abstract_2.ServerRuntime.Express;
|
|
22
|
+
if (runtime === abstract_2.ServerRuntime.Express) {
|
|
23
|
+
const fileUpload = require("express-fileupload");
|
|
24
|
+
app.use(fileUpload(this.fileUploadOptions));
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
app.use(createBunFileUploadMiddleware());
|
|
25
28
|
}
|
|
26
29
|
}
|
|
27
30
|
exports.FileUploadModule = FileUploadModule;
|
|
31
|
+
const createBunFileUploadMiddleware = () => {
|
|
32
|
+
return async (req, _res, next) => {
|
|
33
|
+
if (!req.raw || req.files) {
|
|
34
|
+
return next();
|
|
35
|
+
}
|
|
36
|
+
const contentType = String(req.headers?.["content-type"] || "");
|
|
37
|
+
if (!contentType.includes("multipart/form-data")) {
|
|
38
|
+
return next();
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
41
|
+
const formData = await req.raw.formData();
|
|
42
|
+
const files = {};
|
|
43
|
+
const body = {};
|
|
44
|
+
formData.forEach((value, key) => {
|
|
45
|
+
if (value instanceof File) {
|
|
46
|
+
files[key] = value;
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
body[key] = value;
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
if (Object.keys(files).length) {
|
|
53
|
+
req.files = files;
|
|
54
|
+
}
|
|
55
|
+
if (Object.keys(body).length && req.body === undefined) {
|
|
56
|
+
req.body = body;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
// Ignore malformed multipart payloads.
|
|
61
|
+
}
|
|
62
|
+
next();
|
|
63
|
+
};
|
|
64
|
+
};
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { Express } from "express";
|
|
2
1
|
import { BaseServerModule } from "../abstract";
|
|
3
|
-
import
|
|
2
|
+
import { ServerApp, ServerContext } from "../abstract";
|
|
3
|
+
import type { Options as RateLimitOptions } from "express-rate-limit";
|
|
4
4
|
export declare class RateLimitModule extends BaseServerModule {
|
|
5
5
|
name: string;
|
|
6
6
|
priority: number;
|
|
7
7
|
private limiterOptions;
|
|
8
|
-
constructor(limiterOptions?:
|
|
8
|
+
constructor(limiterOptions?: Partial<RateLimitOptions>);
|
|
9
9
|
getModuleName(): string;
|
|
10
|
-
init(app:
|
|
10
|
+
init(app: ServerApp, context?: ServerContext): void;
|
|
11
11
|
}
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.RateLimitModule = void 0;
|
|
7
4
|
const abstract_1 = require("../abstract");
|
|
8
|
-
const
|
|
5
|
+
const abstract_2 = require("../abstract");
|
|
9
6
|
class RateLimitModule extends abstract_1.BaseServerModule {
|
|
10
7
|
constructor(limiterOptions) {
|
|
11
8
|
super();
|
|
@@ -21,9 +18,53 @@ class RateLimitModule extends abstract_1.BaseServerModule {
|
|
|
21
18
|
getModuleName() {
|
|
22
19
|
return this.name;
|
|
23
20
|
}
|
|
24
|
-
init(app) {
|
|
25
|
-
const
|
|
26
|
-
|
|
21
|
+
init(app, context) {
|
|
22
|
+
const runtime = context?.runtime ?? abstract_2.ServerRuntime.Express;
|
|
23
|
+
if (runtime === abstract_2.ServerRuntime.Express) {
|
|
24
|
+
const rateLimitModule = require("express-rate-limit");
|
|
25
|
+
const rateLimit = rateLimitModule.default ?? rateLimitModule;
|
|
26
|
+
const limiter = rateLimit(this.limiterOptions);
|
|
27
|
+
app.use(limiter);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
app.use(createRateLimitMiddleware(this.limiterOptions));
|
|
27
31
|
}
|
|
28
32
|
}
|
|
29
33
|
exports.RateLimitModule = RateLimitModule;
|
|
34
|
+
const createRateLimitMiddleware = (options) => {
|
|
35
|
+
const windowMsOption = options?.windowMs;
|
|
36
|
+
const windowMs = typeof windowMsOption === "number" ? windowMsOption : 8 * 60 * 1000;
|
|
37
|
+
const legacyMax = options?.max;
|
|
38
|
+
const limitOption = options?.limit ?? legacyMax;
|
|
39
|
+
const limit = typeof limitOption === "number" ? limitOption : 100;
|
|
40
|
+
const hits = new Map();
|
|
41
|
+
return (req, res, next) => {
|
|
42
|
+
const key = req.ip || String(req.headers?.["x-forwarded-for"] || "unknown");
|
|
43
|
+
const now = Date.now();
|
|
44
|
+
const existing = hits.get(key);
|
|
45
|
+
if (!existing || existing.expiresAt <= now) {
|
|
46
|
+
hits.set(key, { count: 1, expiresAt: now + windowMs });
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
existing.count += 1;
|
|
50
|
+
}
|
|
51
|
+
const current = hits.get(key);
|
|
52
|
+
const remaining = Math.max(0, limit - current.count);
|
|
53
|
+
if (options?.standardHeaders) {
|
|
54
|
+
res.set("ratelimit-limit", String(limit));
|
|
55
|
+
res.set("ratelimit-remaining", String(remaining));
|
|
56
|
+
res.set("ratelimit-reset", String(Math.ceil(current.expiresAt / 1000)));
|
|
57
|
+
}
|
|
58
|
+
if (current.count > limit) {
|
|
59
|
+
const message = typeof options?.message === "string" ||
|
|
60
|
+
(typeof options?.message === "object" && options?.message)
|
|
61
|
+
? options.message
|
|
62
|
+
: undefined;
|
|
63
|
+
res.status(429).json(message || {
|
|
64
|
+
message: "Too many requests, please try again later.",
|
|
65
|
+
});
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
next();
|
|
69
|
+
};
|
|
70
|
+
};
|
|
@@ -1,16 +1,9 @@
|
|
|
1
|
-
import { Express } from "express";
|
|
2
1
|
import { BaseServerModule } from "../abstract";
|
|
3
|
-
|
|
4
|
-
namespace Express {
|
|
5
|
-
interface Request {
|
|
6
|
-
requestId?: string;
|
|
7
|
-
}
|
|
8
|
-
}
|
|
9
|
-
}
|
|
2
|
+
import { ServerApp, ServerContext } from "../abstract";
|
|
10
3
|
export declare class RequestContextModule extends BaseServerModule {
|
|
11
4
|
name: string;
|
|
12
5
|
priority: number;
|
|
13
|
-
init(app:
|
|
6
|
+
init(app: ServerApp, _context?: ServerContext): void;
|
|
14
7
|
getModuleName(): string;
|
|
15
8
|
}
|
|
16
9
|
interface Context {
|
|
@@ -1,7 +1,39 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
36
|
exports.RequestContext = exports.RequestContextModule = void 0;
|
|
4
|
-
const uuid_1 = require("uuid");
|
|
5
37
|
const abstract_1 = require("../abstract");
|
|
6
38
|
const async_hooks_1 = require("async_hooks");
|
|
7
39
|
class RequestContextModule extends abstract_1.BaseServerModule {
|
|
@@ -10,12 +42,13 @@ class RequestContextModule extends abstract_1.BaseServerModule {
|
|
|
10
42
|
this.name = "RequestContext";
|
|
11
43
|
this.priority = -50;
|
|
12
44
|
}
|
|
13
|
-
init(app) {
|
|
14
|
-
const requestContextMiddleware = (req,
|
|
45
|
+
init(app, _context) {
|
|
46
|
+
const requestContextMiddleware = async (req, _res, next) => {
|
|
15
47
|
const incomingRequestId = req.headers["x-request-id"];
|
|
16
48
|
const requestId = (Array.isArray(incomingRequestId)
|
|
17
49
|
? incomingRequestId[0]
|
|
18
|
-
: incomingRequestId) || (
|
|
50
|
+
: incomingRequestId) || (await createRequestId());
|
|
51
|
+
req.requestId = requestId;
|
|
19
52
|
RequestContext.run({ requestId }, () => {
|
|
20
53
|
next();
|
|
21
54
|
});
|
|
@@ -43,3 +76,19 @@ class RequestContext {
|
|
|
43
76
|
}
|
|
44
77
|
exports.RequestContext = RequestContext;
|
|
45
78
|
RequestContext.storage = new async_hooks_1.AsyncLocalStorage();
|
|
79
|
+
const createRequestId = async () => {
|
|
80
|
+
const cryptoObj = globalThis.crypto;
|
|
81
|
+
if (cryptoObj?.randomUUID) {
|
|
82
|
+
return cryptoObj.randomUUID();
|
|
83
|
+
}
|
|
84
|
+
try {
|
|
85
|
+
const uuidModule = (await Promise.resolve().then(() => __importStar(require("uuid"))));
|
|
86
|
+
if (uuidModule.v4) {
|
|
87
|
+
return uuidModule.v4();
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
// Ignore and fallback.
|
|
92
|
+
}
|
|
93
|
+
return `${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
|
94
|
+
};
|