@expressots/adapter-express 1.7.0 → 1.8.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/CHANGELOG.md +22 -0
- package/lib/cjs/adapter-express/express-utils/decorators.js +92 -5
- package/lib/cjs/adapter-express/express-utils/inversify-express-server.js +13 -3
- package/lib/cjs/adapter-express/express-utils/resolver-multer.js +33 -0
- package/lib/cjs/types/adapter-express/express-utils/decorators.d.ts +49 -1
- package/lib/cjs/types/adapter-express/express-utils/interfaces.d.ts +4 -1
- package/lib/cjs/types/adapter-express/express-utils/inversify-express-server.d.ts +2 -1
- package/lib/cjs/types/adapter-express/express-utils/resolver-multer.d.ts +7 -0
- package/lib/package.json +2 -2
- package/package.json +2 -2
package/lib/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
|
|
2
2
|
|
|
3
|
+
## [1.8.0](https://github.com/expressots/adapter-express/compare/1.7.0...1.8.0) (2024-08-13)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* add expressots middleware in decorators ([055ead9](https://github.com/expressots/adapter-express/commit/055ead94334dd5ea735ddf04a16a322d56d566cc))
|
|
9
|
+
* add FileUpload decorator ([a4f62b1](https://github.com/expressots/adapter-express/commit/a4f62b1cd377625c55218069599a7a262493e3f5))
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
### Bug Fixes
|
|
13
|
+
|
|
14
|
+
* adjust error msgs and package resolver ([34a0fcd](https://github.com/expressots/adapter-express/commit/34a0fcde6e637130e328733f48130408fa881a67))
|
|
15
|
+
* adjust isExpressoMiddleware function param types ([edc0888](https://github.com/expressots/adapter-express/commit/edc0888489df4c9f33a5b97af0820ce8f90904e9))
|
|
16
|
+
* return message ([32d656e](https://github.com/expressots/adapter-express/commit/32d656ec2b05a807599e428c9bd0389849c2165d))
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
### Code Refactoring
|
|
20
|
+
|
|
21
|
+
* bump expresso core deps & remove husky deprecated code ([a9b243f](https://github.com/expressots/adapter-express/commit/a9b243fd35b877c839da2871401574cf30db808e))
|
|
22
|
+
* httpMethod to Method decorator ([5e853a0](https://github.com/expressots/adapter-express/commit/5e853a04358430e9e6f658bf0d0b68b7e2708a24))
|
|
23
|
+
* remove unnecessary comments ([72c4a15](https://github.com/expressots/adapter-express/commit/72c4a157055fffdfbaad19a69ea124ca0eb7fa13))
|
|
24
|
+
|
|
3
25
|
## [1.7.0](https://github.com/expressots/adapter-express/compare/1.6.0...1.7.0) (2024-07-23)
|
|
4
26
|
|
|
5
27
|
|
|
@@ -10,13 +10,16 @@ exports.Put = Put;
|
|
|
10
10
|
exports.Patch = Patch;
|
|
11
11
|
exports.Head = Head;
|
|
12
12
|
exports.Delete = Delete;
|
|
13
|
-
exports.
|
|
13
|
+
exports.Method = Method;
|
|
14
14
|
exports.params = params;
|
|
15
15
|
exports.Render = Render;
|
|
16
16
|
exports.getRenderMetadata = getRenderMetadata;
|
|
17
|
+
exports.FileUpload = FileUpload;
|
|
17
18
|
require("reflect-metadata");
|
|
18
19
|
const inversify_1 = require("inversify");
|
|
19
20
|
const constants_1 = require("./constants");
|
|
21
|
+
const resolver_multer_1 = require("./resolver-multer");
|
|
22
|
+
const core_1 = require("@expressots/core");
|
|
20
23
|
exports.injectHttpContext = (0, inversify_1.inject)(constants_1.TYPE.HttpContext);
|
|
21
24
|
/**
|
|
22
25
|
* Controller decorator to define a new controller
|
|
@@ -83,7 +86,7 @@ function Http(code) {
|
|
|
83
86
|
* @param middleware array of middleware to be applied to all routes defined in path logic
|
|
84
87
|
*/
|
|
85
88
|
function All(path, ...middleware) {
|
|
86
|
-
return
|
|
89
|
+
return Method("all", path, ...middleware);
|
|
87
90
|
}
|
|
88
91
|
/**
|
|
89
92
|
* Decorator to allow GET HTTP method
|
|
@@ -99,7 +102,7 @@ function Get(path, ...middleware) {
|
|
|
99
102
|
* @param middleware array of middleware to be applied to the route
|
|
100
103
|
*/
|
|
101
104
|
function Post(path, ...middleware) {
|
|
102
|
-
return
|
|
105
|
+
return Method("post", path, ...middleware);
|
|
103
106
|
}
|
|
104
107
|
/**
|
|
105
108
|
* Decorator to allow PUT HTTP method
|
|
@@ -123,7 +126,7 @@ function Patch(path, ...middleware) {
|
|
|
123
126
|
* @param middleware array of middleware to be applied to the route
|
|
124
127
|
*/
|
|
125
128
|
function Head(path, ...middleware) {
|
|
126
|
-
return
|
|
129
|
+
return Method("head", path, ...middleware);
|
|
127
130
|
}
|
|
128
131
|
/**
|
|
129
132
|
* Decorator to allow DELETE HTTP method
|
|
@@ -189,7 +192,7 @@ function enhancedHttpMethod(method, path, ...middleware) {
|
|
|
189
192
|
* @param path route path
|
|
190
193
|
* @param middleware array of middleware to be applied to the route
|
|
191
194
|
*/
|
|
192
|
-
function
|
|
195
|
+
function Method(method, path, ...middleware) {
|
|
193
196
|
return (target, key) => {
|
|
194
197
|
const metadata = {
|
|
195
198
|
key,
|
|
@@ -336,3 +339,87 @@ function convertToType(value, type) {
|
|
|
336
339
|
}
|
|
337
340
|
return value;
|
|
338
341
|
}
|
|
342
|
+
/**
|
|
343
|
+
* File upload decorator to handle file uploads
|
|
344
|
+
* @param options
|
|
345
|
+
* @param multerOptions
|
|
346
|
+
* @default { none: true }
|
|
347
|
+
* @returns MethodDecorator
|
|
348
|
+
*/
|
|
349
|
+
function FileUpload(options, multerOptions) {
|
|
350
|
+
const multer = (0, resolver_multer_1.packageResolver)("multer");
|
|
351
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
352
|
+
let upload;
|
|
353
|
+
let method = "none";
|
|
354
|
+
if (multer) {
|
|
355
|
+
if (options === undefined) {
|
|
356
|
+
options = { none: true };
|
|
357
|
+
}
|
|
358
|
+
upload = multer(multerOptions);
|
|
359
|
+
method = inferMulterMethod(options);
|
|
360
|
+
}
|
|
361
|
+
return function (target, propertyKey, descriptor) {
|
|
362
|
+
const originalMethod = descriptor.value;
|
|
363
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
364
|
+
descriptor.value = function (...args) {
|
|
365
|
+
const req = args[0];
|
|
366
|
+
const res = args[1];
|
|
367
|
+
// const next = args[2] as NextFunction;
|
|
368
|
+
const multerMiddleware = getMulterMiddleware(upload, options, method);
|
|
369
|
+
multerMiddleware(req, res, (err) => {
|
|
370
|
+
if (err) {
|
|
371
|
+
return res.status(400).json({ error: err.message });
|
|
372
|
+
}
|
|
373
|
+
return originalMethod.apply(this, args);
|
|
374
|
+
});
|
|
375
|
+
};
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* Infer the multer method to use based on the provided options
|
|
380
|
+
* @param options
|
|
381
|
+
* @returns
|
|
382
|
+
*/
|
|
383
|
+
function inferMulterMethod(options) {
|
|
384
|
+
const report = new core_1.Report();
|
|
385
|
+
if (options.none)
|
|
386
|
+
return "none";
|
|
387
|
+
if (options.any)
|
|
388
|
+
return "any";
|
|
389
|
+
if (Array.isArray(options))
|
|
390
|
+
return "fields";
|
|
391
|
+
if (options.fieldName && options.maxCount !== undefined)
|
|
392
|
+
return "array";
|
|
393
|
+
if (options.fieldName)
|
|
394
|
+
return "single";
|
|
395
|
+
throw report.error("Invalid options provided for FileUpload.", core_1.StatusCode.InternalServerError, "multer-decorator");
|
|
396
|
+
}
|
|
397
|
+
/**
|
|
398
|
+
* Get the multer middleware based on the method
|
|
399
|
+
* @param upload
|
|
400
|
+
* @param options
|
|
401
|
+
* @param method
|
|
402
|
+
* @returns
|
|
403
|
+
*/
|
|
404
|
+
function getMulterMiddleware(upload, options, method) {
|
|
405
|
+
const report = new core_1.Report();
|
|
406
|
+
switch (method) {
|
|
407
|
+
case "single":
|
|
408
|
+
return upload.single(options.fieldName);
|
|
409
|
+
case "array":
|
|
410
|
+
return upload.array(options.fieldName, options.maxCount);
|
|
411
|
+
case "fields": {
|
|
412
|
+
const fieldsOptions = options.map((opt) => ({
|
|
413
|
+
name: opt.fieldName,
|
|
414
|
+
maxCount: opt.maxCount,
|
|
415
|
+
}));
|
|
416
|
+
return upload.fields(fieldsOptions);
|
|
417
|
+
}
|
|
418
|
+
case "none":
|
|
419
|
+
return upload.none();
|
|
420
|
+
case "any":
|
|
421
|
+
return upload.any();
|
|
422
|
+
default:
|
|
423
|
+
throw report.error(`Unsupported Multer method: ${method}`, core_1.StatusCode.InternalServerError, "multer-decorator");
|
|
424
|
+
}
|
|
425
|
+
}
|
|
@@ -126,22 +126,32 @@ class InversifyExpressServer {
|
|
|
126
126
|
const methodMetadata = (0, utils_1.getControllerMethodMetadata)(controller.constructor);
|
|
127
127
|
const parameterMetadata = (0, utils_1.getControllerParameterMetadata)(controller.constructor);
|
|
128
128
|
if (controllerMetadata && methodMetadata) {
|
|
129
|
-
const controllerMiddleware = this.
|
|
129
|
+
const controllerMiddleware = this.resolveMiddleware(...controllerMetadata.middleware);
|
|
130
130
|
methodMetadata.forEach((metadata) => {
|
|
131
131
|
let paramList = [];
|
|
132
132
|
if (parameterMetadata) {
|
|
133
133
|
paramList = parameterMetadata[metadata.key] || [];
|
|
134
134
|
}
|
|
135
135
|
const handler = this.handlerFactory(controllerMetadata.target.name, metadata.key, paramList);
|
|
136
|
-
const routeMiddleware = this.
|
|
136
|
+
const routeMiddleware = this.resolveMiddleware(...metadata.middleware);
|
|
137
137
|
this._router[metadata.method](`${controllerMetadata.path}${metadata.path}`, ...controllerMiddleware, ...routeMiddleware, handler);
|
|
138
138
|
});
|
|
139
139
|
}
|
|
140
140
|
});
|
|
141
141
|
this._app.use(this._routingConfig.rootPath, this._router);
|
|
142
142
|
}
|
|
143
|
-
|
|
143
|
+
isExpressoMiddleware(middlewareItem) {
|
|
144
|
+
return (typeof middlewareItem === "object" &&
|
|
145
|
+
"use" in middlewareItem &&
|
|
146
|
+
typeof middlewareItem.use === "function");
|
|
147
|
+
}
|
|
148
|
+
resolveMiddleware(...middleware) {
|
|
144
149
|
return middleware.map((middlewareItem) => {
|
|
150
|
+
if (this.isExpressoMiddleware(middlewareItem)) {
|
|
151
|
+
return (req, res, next) => {
|
|
152
|
+
middlewareItem.use(req, res, next);
|
|
153
|
+
};
|
|
154
|
+
}
|
|
145
155
|
if (!this._container.isBound(middlewareItem)) {
|
|
146
156
|
return middlewareItem;
|
|
147
157
|
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.packageResolver = packageResolver;
|
|
4
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
5
|
+
const core_1 = require("@expressots/core");
|
|
6
|
+
/**
|
|
7
|
+
* Resolve package from the current working directory.
|
|
8
|
+
* @param packageName
|
|
9
|
+
* @param options
|
|
10
|
+
* @returns
|
|
11
|
+
*/
|
|
12
|
+
function packageResolver(packageName) {
|
|
13
|
+
const logger = new core_1.Logger();
|
|
14
|
+
try {
|
|
15
|
+
const hasPackage = require.resolve(packageName, {
|
|
16
|
+
paths: [process.cwd()],
|
|
17
|
+
});
|
|
18
|
+
if (hasPackage) {
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
20
|
+
const packageResolved = require(hasPackage);
|
|
21
|
+
if (typeof packageResolved === "function") {
|
|
22
|
+
return packageResolved;
|
|
23
|
+
}
|
|
24
|
+
if (packageResolved.default && typeof packageResolved.default === "function") {
|
|
25
|
+
return packageResolved.default;
|
|
26
|
+
}
|
|
27
|
+
return packageResolved;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
logger.warn(`Package [${packageName}] not installed. Please install it using your package manager.`, "package-resolver");
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -70,7 +70,7 @@ export declare function Delete(path: string, ...middleware: Array<Middleware>):
|
|
|
70
70
|
* @param path route path
|
|
71
71
|
* @param middleware array of middleware to be applied to the route
|
|
72
72
|
*/
|
|
73
|
-
export declare function
|
|
73
|
+
export declare function Method(method: keyof typeof HTTP_VERBS_ENUM, path: string, ...middleware: Array<Middleware>): HandlerDecorator;
|
|
74
74
|
/**
|
|
75
75
|
* Parameter decorator to inject the request object
|
|
76
76
|
* @returns ParameterDecorator
|
|
@@ -132,3 +132,51 @@ export declare function getRenderMetadata(target: object, propertyKey: string |
|
|
|
132
132
|
template?: string;
|
|
133
133
|
defaultData?: Record<string, unknown>;
|
|
134
134
|
};
|
|
135
|
+
export interface StorageEngine {
|
|
136
|
+
_handleFile(req: unknown, file: MulterFile, callback: (error?: Error | null, info?: Partial<MulterFile>) => void): void;
|
|
137
|
+
_removeFile(req: unknown, file: MulterFile, callback: (error: Error | null) => void): void;
|
|
138
|
+
}
|
|
139
|
+
export interface MulterFile {
|
|
140
|
+
fieldname: string;
|
|
141
|
+
originalname: string;
|
|
142
|
+
encoding: string;
|
|
143
|
+
mimetype: string;
|
|
144
|
+
size: number;
|
|
145
|
+
destination?: string;
|
|
146
|
+
filename?: string;
|
|
147
|
+
path?: string;
|
|
148
|
+
buffer?: Buffer;
|
|
149
|
+
}
|
|
150
|
+
export interface MulterLimits {
|
|
151
|
+
fieldNameSize?: number;
|
|
152
|
+
fieldSize?: number;
|
|
153
|
+
fields?: number;
|
|
154
|
+
fileSize?: number;
|
|
155
|
+
files?: number;
|
|
156
|
+
parts?: number;
|
|
157
|
+
headerPairs?: number;
|
|
158
|
+
}
|
|
159
|
+
export interface MulterOptions {
|
|
160
|
+
dest?: string;
|
|
161
|
+
storage?: StorageEngine;
|
|
162
|
+
limits?: MulterLimits;
|
|
163
|
+
fileFilter?: FileFilter;
|
|
164
|
+
}
|
|
165
|
+
export type FileFilterCallback = (error: Error | null, acceptFile: boolean) => void;
|
|
166
|
+
export type FileFilter = (req: unknown, file: MulterFile, callback: FileFilterCallback) => void;
|
|
167
|
+
type FieldOptions = {
|
|
168
|
+
fieldName: string;
|
|
169
|
+
maxCount?: number;
|
|
170
|
+
};
|
|
171
|
+
/**
|
|
172
|
+
* File upload decorator to handle file uploads
|
|
173
|
+
* @param options
|
|
174
|
+
* @param multerOptions
|
|
175
|
+
* @default { none: true }
|
|
176
|
+
* @returns MethodDecorator
|
|
177
|
+
*/
|
|
178
|
+
export declare function FileUpload(options?: FieldOptions | Array<FieldOptions> | {
|
|
179
|
+
none?: boolean;
|
|
180
|
+
any?: boolean;
|
|
181
|
+
}, multerOptions?: MulterOptions): MethodDecorator;
|
|
182
|
+
export {};
|
|
@@ -12,7 +12,10 @@ interface ConstructorFunction<T = Record<string, unknown>> {
|
|
|
12
12
|
prototype: Prototype<T>;
|
|
13
13
|
}
|
|
14
14
|
export type DecoratorTarget<T = unknown> = ConstructorFunction<T> | Prototype<T>;
|
|
15
|
-
export
|
|
15
|
+
export interface IExpressoMiddleware {
|
|
16
|
+
use(req: Request, res: Response, next: NextFunction): Promise<void> | void;
|
|
17
|
+
}
|
|
18
|
+
export type Middleware = string | symbol | RequestHandler | IExpressoMiddleware;
|
|
16
19
|
export type ControllerHandler = (...params: Array<unknown>) => unknown;
|
|
17
20
|
export type BaseController = Record<string, ControllerHandler>;
|
|
18
21
|
export interface Controller {
|
|
@@ -46,7 +46,8 @@ export declare class InversifyExpressServer {
|
|
|
46
46
|
*/
|
|
47
47
|
build(): express.Application;
|
|
48
48
|
private registerControllers;
|
|
49
|
-
private
|
|
49
|
+
private isExpressoMiddleware;
|
|
50
|
+
private resolveMiddleware;
|
|
50
51
|
private copyHeadersTo;
|
|
51
52
|
private handleHttpResponseMessage;
|
|
52
53
|
private handlerFactory;
|
package/lib/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@expressots/adapter-express",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0",
|
|
4
4
|
"description": "Expressots - modern, fast, lightweight nodejs web framework (@adapter-express)",
|
|
5
5
|
"author": "",
|
|
6
6
|
"main": "./lib/cjs/index.js",
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
"@codecov/vite-plugin": "^0.0.1-beta.6",
|
|
76
76
|
"@commitlint/cli": "19.2.1",
|
|
77
77
|
"@commitlint/config-conventional": "19.2.2",
|
|
78
|
-
"@expressots/core": "2.
|
|
78
|
+
"@expressots/core": "2.16.0",
|
|
79
79
|
"@release-it/conventional-changelog": "8.0.1",
|
|
80
80
|
"@types/express": "4.17.21",
|
|
81
81
|
"@types/node": "20.14.10",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@expressots/adapter-express",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0",
|
|
4
4
|
"description": "Expressots - modern, fast, lightweight nodejs web framework (@adapter-express)",
|
|
5
5
|
"author": "",
|
|
6
6
|
"main": "./lib/cjs/index.js",
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
"@codecov/vite-plugin": "^0.0.1-beta.6",
|
|
76
76
|
"@commitlint/cli": "19.2.1",
|
|
77
77
|
"@commitlint/config-conventional": "19.2.2",
|
|
78
|
-
"@expressots/core": "2.
|
|
78
|
+
"@expressots/core": "2.16.0",
|
|
79
79
|
"@release-it/conventional-changelog": "8.0.1",
|
|
80
80
|
"@types/express": "4.17.21",
|
|
81
81
|
"@types/node": "20.14.10",
|