@avleon/core 0.0.29 → 0.0.30
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/package.json +2 -3
- package/src/application.ts +0 -104
- package/src/authentication.ts +0 -16
- package/src/cache.ts +0 -91
- package/src/collection.test.ts +0 -71
- package/src/collection.ts +0 -344
- package/src/config.test.ts +0 -35
- package/src/config.ts +0 -85
- package/src/constants.ts +0 -1
- package/src/container.ts +0 -54
- package/src/controller.ts +0 -125
- package/src/decorators.ts +0 -27
- package/src/environment-variables.ts +0 -53
- package/src/event-dispatcher.ts +0 -100
- package/src/event-subscriber.ts +0 -79
- package/src/exceptions/http-exceptions.ts +0 -86
- package/src/exceptions/index.ts +0 -1
- package/src/exceptions/system-exception.ts +0 -35
- package/src/file-storage.ts +0 -206
- package/src/helpers.ts +0 -324
- package/src/icore.ts +0 -1106
- package/src/index.ts +0 -32
- package/src/interfaces/avleon-application.ts +0 -32
- package/src/logger.ts +0 -72
- package/src/map-types.ts +0 -159
- package/src/middleware.ts +0 -121
- package/src/multipart.ts +0 -116
- package/src/openapi.ts +0 -372
- package/src/params.ts +0 -111
- package/src/queue.ts +0 -126
- package/src/response.ts +0 -74
- package/src/results.ts +0 -30
- package/src/route-methods.ts +0 -186
- package/src/swagger-schema.ts +0 -213
- package/src/testing.ts +0 -220
- package/src/types/app-builder.interface.ts +0 -18
- package/src/types/application.interface.ts +0 -7
- package/src/utils/hash.ts +0 -8
- package/src/utils/index.ts +0 -2
- package/src/utils/optional-require.ts +0 -50
- package/src/validation.ts +0 -160
- package/src/validator-extend.ts +0 -25
- package/src/websocket.ts +0 -47
package/src/index.ts
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @copyright 2024
|
|
3
|
-
* @author Tareq Hossain
|
|
4
|
-
* @email xtrinsic96@gmail.com
|
|
5
|
-
* @url https://github.com/xtareq
|
|
6
|
-
*/
|
|
7
|
-
import * as sw from "./swagger-schema";
|
|
8
|
-
export * from "./icore";
|
|
9
|
-
export * from "./testing";
|
|
10
|
-
export { inject, validateRequestBody, pick, exclude } from "./helpers";
|
|
11
|
-
export * from "./decorators";
|
|
12
|
-
export * from "./middleware";
|
|
13
|
-
export * from "./config";
|
|
14
|
-
export * from "./openapi";
|
|
15
|
-
export * from "./map-types";
|
|
16
|
-
export * from "./response";
|
|
17
|
-
export * from "./exceptions";
|
|
18
|
-
export * from "./validator-extend";
|
|
19
|
-
export * from "./validation";
|
|
20
|
-
export * from "./environment-variables";
|
|
21
|
-
export * from "./collection";
|
|
22
|
-
export * from "./queue";
|
|
23
|
-
export * from "./utils/hash";
|
|
24
|
-
export * from "./multipart";
|
|
25
|
-
export * from "./file-storage";
|
|
26
|
-
export * from "./logger";
|
|
27
|
-
export * from "./event-dispatcher";
|
|
28
|
-
export { Subscribe, Private } from "./event-subscriber";
|
|
29
|
-
|
|
30
|
-
export const GetSchema = sw.generateSwaggerSchema;
|
|
31
|
-
|
|
32
|
-
export { default as AvleonContainer } from "./container";
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
interface AvleonApplication {
|
|
2
|
-
// all use
|
|
3
|
-
useCors: () => void;
|
|
4
|
-
/**
|
|
5
|
-
* function for register database
|
|
6
|
-
* @param options datasource options. options can be plain object or avleon config class
|
|
7
|
-
* */
|
|
8
|
-
useDatasource: () => void;
|
|
9
|
-
useMultipart: () => void;
|
|
10
|
-
useOpenApi: () => void;
|
|
11
|
-
useMiddlewares: () => void;
|
|
12
|
-
useAuthorization: () => void;
|
|
13
|
-
useSerialization: () => void;
|
|
14
|
-
useControllers: () => void;
|
|
15
|
-
useStaticFiles: () => void;
|
|
16
|
-
/**
|
|
17
|
-
* @experimental
|
|
18
|
-
* use https as defalut http protocol
|
|
19
|
-
* */
|
|
20
|
-
useHttps: () => void;
|
|
21
|
-
|
|
22
|
-
// all map
|
|
23
|
-
mapGet: () => void;
|
|
24
|
-
mapPost: () => void;
|
|
25
|
-
mapPut: () => void;
|
|
26
|
-
mapPatch: () => void;
|
|
27
|
-
mapOptions: () => void;
|
|
28
|
-
mapGroup: () => void;
|
|
29
|
-
// all others
|
|
30
|
-
// run
|
|
31
|
-
run: () => void;
|
|
32
|
-
}
|
package/src/logger.ts
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import pino from "pino";
|
|
2
|
-
import { AppService } from "./decorators";
|
|
3
|
-
|
|
4
|
-
@AppService
|
|
5
|
-
export class LoggerService {
|
|
6
|
-
private logger: pino.Logger;
|
|
7
|
-
|
|
8
|
-
constructor() {
|
|
9
|
-
this.logger = pino({
|
|
10
|
-
level: process.env.LOG_LEVEL || "info",
|
|
11
|
-
transport: {
|
|
12
|
-
target: "pino-pretty",
|
|
13
|
-
options: {
|
|
14
|
-
translateTime: "SYS:standard",
|
|
15
|
-
ignore: "pid,hostname",
|
|
16
|
-
},
|
|
17
|
-
},
|
|
18
|
-
});
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
getLogger(): pino.Logger {
|
|
22
|
-
return this.logger;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
info(message: string, obj?: any): void {
|
|
26
|
-
if (obj) {
|
|
27
|
-
this.logger.info(obj, message);
|
|
28
|
-
} else {
|
|
29
|
-
this.logger.info(message);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
error(message: string, obj?: any): void {
|
|
34
|
-
if (obj) {
|
|
35
|
-
this.logger.error(obj, message);
|
|
36
|
-
} else {
|
|
37
|
-
this.logger.error(message);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
warn(message: string, obj?: any): void {
|
|
42
|
-
if (obj) {
|
|
43
|
-
this.logger.warn(obj, message);
|
|
44
|
-
} else {
|
|
45
|
-
this.logger.warn(message);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
debug(message: string, obj?: any): void {
|
|
50
|
-
if (obj) {
|
|
51
|
-
this.logger.debug(obj, message);
|
|
52
|
-
} else {
|
|
53
|
-
this.logger.debug(message);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
fatal(message: string, obj?: any): void {
|
|
58
|
-
if (obj) {
|
|
59
|
-
this.logger.fatal(obj, message);
|
|
60
|
-
} else {
|
|
61
|
-
this.logger.fatal(message);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
trace(message: string, obj?: any): void {
|
|
66
|
-
if (obj) {
|
|
67
|
-
this.logger.trace(obj, message);
|
|
68
|
-
} else {
|
|
69
|
-
this.logger.trace(message);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
package/src/map-types.ts
DELETED
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @copyright 2024
|
|
3
|
-
* @author Tareq Hossain
|
|
4
|
-
* @email xtrinsic96@gmail.com
|
|
5
|
-
* @url https://github.com/xtareq
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
//
|
|
9
|
-
type Constructor<T = any> = new (...args: any[]) => T;
|
|
10
|
-
|
|
11
|
-
export function PartialType<T>(
|
|
12
|
-
BaseClass: Constructor<T>,
|
|
13
|
-
): Constructor<Partial<T>> {
|
|
14
|
-
const baseProperties: string[] = [];
|
|
15
|
-
let currentPrototype = BaseClass.prototype;
|
|
16
|
-
|
|
17
|
-
// Collect properties from the base class (including inherited ones)
|
|
18
|
-
while (currentPrototype && currentPrototype !== Object.prototype) {
|
|
19
|
-
const properties = Object.getOwnPropertyNames(currentPrototype).filter(
|
|
20
|
-
(prop) => prop !== "constructor", // Exclude the constructor
|
|
21
|
-
);
|
|
22
|
-
|
|
23
|
-
// Retrieve metadata for each property
|
|
24
|
-
properties.forEach((key) => {
|
|
25
|
-
// Check if the property has type metadata (design:type)
|
|
26
|
-
const designType = Reflect.getMetadata(
|
|
27
|
-
"design:type",
|
|
28
|
-
currentPrototype,
|
|
29
|
-
key,
|
|
30
|
-
);
|
|
31
|
-
if (designType) {
|
|
32
|
-
baseProperties.push(key);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// Retrieve validation metadata (class-validator)
|
|
36
|
-
const validationMetadata = Reflect.getMetadataKeys(currentPrototype, key);
|
|
37
|
-
validationMetadata.forEach((metadataKey) => {});
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
currentPrototype = Object.getPrototypeOf(currentPrototype); // Move up the prototype chain
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
class PartialClass {}
|
|
44
|
-
|
|
45
|
-
// Define properties as optional and copy metadata
|
|
46
|
-
baseProperties.forEach((key) => {
|
|
47
|
-
const propertyType = Reflect.getMetadata(
|
|
48
|
-
"design:type",
|
|
49
|
-
BaseClass.prototype,
|
|
50
|
-
key,
|
|
51
|
-
);
|
|
52
|
-
Reflect.defineMetadata(
|
|
53
|
-
"design:type",
|
|
54
|
-
propertyType,
|
|
55
|
-
PartialClass.prototype,
|
|
56
|
-
key,
|
|
57
|
-
);
|
|
58
|
-
|
|
59
|
-
// Propagate class-validator metadata to the new class
|
|
60
|
-
const validationMetadataKeys =
|
|
61
|
-
Reflect.getMetadataKeys(BaseClass.prototype, key) || [];
|
|
62
|
-
validationMetadataKeys.forEach((metadataKey) => {
|
|
63
|
-
const metadataValue = Reflect.getMetadata(
|
|
64
|
-
metadataKey,
|
|
65
|
-
BaseClass.prototype,
|
|
66
|
-
key,
|
|
67
|
-
);
|
|
68
|
-
Reflect.defineMetadata(
|
|
69
|
-
metadataKey,
|
|
70
|
-
metadataValue,
|
|
71
|
-
PartialClass.prototype,
|
|
72
|
-
key,
|
|
73
|
-
);
|
|
74
|
-
});
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
// Copy other metadata from the base class (non-property metadata)
|
|
78
|
-
Reflect.getMetadataKeys(BaseClass.prototype).forEach((key) => {
|
|
79
|
-
const metadataValue = Reflect.getMetadata(key, BaseClass.prototype);
|
|
80
|
-
Reflect.defineMetadata(key, metadataValue, PartialClass.prototype);
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
return PartialClass as Constructor<Partial<T>>;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Utility to pick specific properties from a class.
|
|
88
|
-
*/
|
|
89
|
-
export function PickType<T, K extends keyof T>(
|
|
90
|
-
BaseClass: Constructor<T>,
|
|
91
|
-
keys: K[],
|
|
92
|
-
): Constructor<Pick<T, K>> {
|
|
93
|
-
class PickClass {
|
|
94
|
-
constructor() {
|
|
95
|
-
(keys as string[]).forEach((key: string) => {
|
|
96
|
-
Reflect.defineMetadata(
|
|
97
|
-
"design:type",
|
|
98
|
-
Reflect.getMetadata("design:type", BaseClass.prototype, key),
|
|
99
|
-
this,
|
|
100
|
-
key,
|
|
101
|
-
);
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
Reflect.decorate([Reflect.metadata("design:properties", keys)], PickClass);
|
|
107
|
-
|
|
108
|
-
// Copy metadata from BaseClass to PickClass
|
|
109
|
-
Reflect.getMetadataKeys(BaseClass.prototype).forEach((key) => {
|
|
110
|
-
Reflect.defineMetadata(
|
|
111
|
-
key,
|
|
112
|
-
Reflect.getMetadata(key, BaseClass.prototype),
|
|
113
|
-
PickClass.prototype,
|
|
114
|
-
);
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
return PickClass as Constructor<Pick<T, K>>;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Utility to omit specific properties from a class.
|
|
122
|
-
*/
|
|
123
|
-
export function OmitType<T, K extends keyof T>(
|
|
124
|
-
BaseClass: Constructor<T>,
|
|
125
|
-
keys: K[],
|
|
126
|
-
): Constructor<Omit<T, K>> {
|
|
127
|
-
const allKeys = Reflect.getMetadata("design:properties", BaseClass) || [];
|
|
128
|
-
const omitKeys = new Set(keys);
|
|
129
|
-
const finalKeys = allKeys.filter((key: string) => !omitKeys.has(key as any));
|
|
130
|
-
|
|
131
|
-
class OmitClass {
|
|
132
|
-
constructor() {
|
|
133
|
-
finalKeys.forEach((key: string) => {
|
|
134
|
-
Reflect.defineMetadata(
|
|
135
|
-
"design:type",
|
|
136
|
-
Reflect.getMetadata("design:type", BaseClass.prototype, key),
|
|
137
|
-
this,
|
|
138
|
-
key,
|
|
139
|
-
);
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
Reflect.decorate(
|
|
145
|
-
[Reflect.metadata("design:properties", finalKeys)],
|
|
146
|
-
OmitClass,
|
|
147
|
-
);
|
|
148
|
-
|
|
149
|
-
// Copy metadata from BaseClass to OmitClass
|
|
150
|
-
Reflect.getMetadataKeys(BaseClass.prototype).forEach((key) => {
|
|
151
|
-
Reflect.defineMetadata(
|
|
152
|
-
key,
|
|
153
|
-
Reflect.getMetadata(key, BaseClass.prototype),
|
|
154
|
-
OmitClass.prototype,
|
|
155
|
-
);
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
return OmitClass as Constructor<Omit<T, K>>;
|
|
159
|
-
}
|
package/src/middleware.ts
DELETED
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @copyright 2024
|
|
3
|
-
* @author Tareq Hossain
|
|
4
|
-
* @email xtrinsic96@gmail.com
|
|
5
|
-
* @url https://github.com/xtareq
|
|
6
|
-
*/
|
|
7
|
-
import { Service } from "typedi";
|
|
8
|
-
import { IRequest, IResponse } from "./icore";
|
|
9
|
-
import {
|
|
10
|
-
HttpExceptionTypes as HttpException,
|
|
11
|
-
UnauthorizedException,
|
|
12
|
-
} from "./exceptions";
|
|
13
|
-
import Container, { AUTHORIZATION_META_KEY } from "./container";
|
|
14
|
-
|
|
15
|
-
export abstract class AvleonMiddleware {
|
|
16
|
-
abstract invoke(
|
|
17
|
-
req: IRequest,
|
|
18
|
-
res?: IResponse,
|
|
19
|
-
): Promise<IRequest | HttpException>;
|
|
20
|
-
}
|
|
21
|
-
export type AuthHandler = (
|
|
22
|
-
req: IRequest,
|
|
23
|
-
roles?: string[],
|
|
24
|
-
) => Promise<IRequest | HttpException>;
|
|
25
|
-
|
|
26
|
-
export type Constructor<T> = { new (...args: any[]): T };
|
|
27
|
-
|
|
28
|
-
export abstract class AuthorizeMiddleware {
|
|
29
|
-
abstract authorize(
|
|
30
|
-
roles: string[],
|
|
31
|
-
): (req: IRequest, res?: IResponse) => IRequest | Promise<IRequest>;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export type AuthReturnTypes = IRequest | Promise<IRequest>;
|
|
35
|
-
|
|
36
|
-
interface AuthorizeClass {
|
|
37
|
-
authorize(req: IRequest, options?: any): AuthReturnTypes;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export function AppAuthorization(target: {
|
|
41
|
-
new (...args: any[]): AuthorizeClass;
|
|
42
|
-
}) {
|
|
43
|
-
if (typeof target.prototype.authorize !== "function") {
|
|
44
|
-
throw new Error(
|
|
45
|
-
`Class "${target.name}" must implement an "authorize" method.`,
|
|
46
|
-
);
|
|
47
|
-
}
|
|
48
|
-
Service()(target);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// export function Authorized(target: Function): void;
|
|
52
|
-
export function Authorized(): ClassDecorator & MethodDecorator;
|
|
53
|
-
export function Authorized(options?: any): ClassDecorator & MethodDecorator;
|
|
54
|
-
export function Authorized(
|
|
55
|
-
options: any = {},
|
|
56
|
-
): MethodDecorator | ClassDecorator {
|
|
57
|
-
return function (
|
|
58
|
-
target: any,
|
|
59
|
-
propertyKey?: string | symbol,
|
|
60
|
-
descriptor?: PropertyDescriptor,
|
|
61
|
-
) {
|
|
62
|
-
if (propertyKey && descriptor) {
|
|
63
|
-
Reflect.defineMetadata(
|
|
64
|
-
AUTHORIZATION_META_KEY,
|
|
65
|
-
{ authorize: true, options },
|
|
66
|
-
target.constructor,
|
|
67
|
-
propertyKey,
|
|
68
|
-
);
|
|
69
|
-
} else {
|
|
70
|
-
Reflect.defineMetadata(
|
|
71
|
-
AUTHORIZATION_META_KEY,
|
|
72
|
-
{ authorize: true, options },
|
|
73
|
-
target,
|
|
74
|
-
);
|
|
75
|
-
}
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export function AppMiddleware(target: Constructor<AvleonMiddleware>) {
|
|
80
|
-
if (typeof target.prototype.invoke !== "function") {
|
|
81
|
-
throw new Error(
|
|
82
|
-
`Class "${target.name}" must implement an "invoke" method.`,
|
|
83
|
-
);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
Service()(target);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
export function UseMiddleware<
|
|
90
|
-
T extends AvleonMiddleware | (new (...args: any[]) => AvleonMiddleware),
|
|
91
|
-
>(options: T | T[]): MethodDecorator & ClassDecorator {
|
|
92
|
-
return function (
|
|
93
|
-
target: Object | Function,
|
|
94
|
-
propertyKey?: string | symbol,
|
|
95
|
-
descriptor?: PropertyDescriptor,
|
|
96
|
-
) {
|
|
97
|
-
const normalizeMiddleware = (middleware: any) =>
|
|
98
|
-
typeof middleware === "function" ? new middleware() : middleware;
|
|
99
|
-
const middlewareList = (Array.isArray(options) ? options : [options]).map(
|
|
100
|
-
normalizeMiddleware,
|
|
101
|
-
);
|
|
102
|
-
if (typeof target === "function" && !propertyKey) {
|
|
103
|
-
const existingMiddlewares =
|
|
104
|
-
Reflect.getMetadata("controller:middleware", target) || [];
|
|
105
|
-
Reflect.defineMetadata(
|
|
106
|
-
"controller:middleware",
|
|
107
|
-
[...existingMiddlewares, ...middlewareList],
|
|
108
|
-
target,
|
|
109
|
-
);
|
|
110
|
-
} else if (descriptor) {
|
|
111
|
-
const existingMiddlewares =
|
|
112
|
-
Reflect.getMetadata("route:middleware", target, propertyKey!) || [];
|
|
113
|
-
Reflect.defineMetadata(
|
|
114
|
-
"route:middleware",
|
|
115
|
-
[...existingMiddlewares, ...middlewareList],
|
|
116
|
-
target,
|
|
117
|
-
propertyKey!,
|
|
118
|
-
);
|
|
119
|
-
}
|
|
120
|
-
};
|
|
121
|
-
}
|
package/src/multipart.ts
DELETED
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @copyright 2024
|
|
3
|
-
* @author Tareq Hossain
|
|
4
|
-
* @email xtrinsic96@gmail.com
|
|
5
|
-
* @url https://github.com/xtareq
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import {
|
|
9
|
-
MultipartFile as FsM,
|
|
10
|
-
MultipartValue,
|
|
11
|
-
SavedMultipartFile,
|
|
12
|
-
} from "@fastify/multipart";
|
|
13
|
-
import { IRequest } from "./icore";
|
|
14
|
-
import fs from "fs";
|
|
15
|
-
import path from "path";
|
|
16
|
-
import { pipeline } from "stream/promises";
|
|
17
|
-
import { InternalErrorException } from "./exceptions";
|
|
18
|
-
import { REQUEST_BODY_FILE_KEY, REQUEST_BODY_FILES_KEY } from "./container";
|
|
19
|
-
|
|
20
|
-
export function UploadFile(fieldName: string) {
|
|
21
|
-
return function (
|
|
22
|
-
target: any,
|
|
23
|
-
propertyKey: string | symbol,
|
|
24
|
-
parameterIndex: number,
|
|
25
|
-
) {
|
|
26
|
-
if (!Reflect.hasMetadata(REQUEST_BODY_FILE_KEY, target, propertyKey)) {
|
|
27
|
-
Reflect.defineMetadata(REQUEST_BODY_FILE_KEY, [], target, propertyKey);
|
|
28
|
-
}
|
|
29
|
-
const existingMetadata = Reflect.getMetadata(
|
|
30
|
-
REQUEST_BODY_FILE_KEY,
|
|
31
|
-
target,
|
|
32
|
-
propertyKey,
|
|
33
|
-
) as {
|
|
34
|
-
fieldName: string;
|
|
35
|
-
index: number;
|
|
36
|
-
}[];
|
|
37
|
-
existingMetadata.push({ fieldName, index: parameterIndex });
|
|
38
|
-
Reflect.defineMetadata(
|
|
39
|
-
REQUEST_BODY_FILE_KEY,
|
|
40
|
-
existingMetadata,
|
|
41
|
-
target,
|
|
42
|
-
propertyKey,
|
|
43
|
-
);
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export function UploadFiles(fieldName?: string) {
|
|
48
|
-
return function (
|
|
49
|
-
target: any,
|
|
50
|
-
propertyKey: string | symbol,
|
|
51
|
-
parameterIndex: number,
|
|
52
|
-
) {
|
|
53
|
-
if (!Reflect.hasMetadata(REQUEST_BODY_FILES_KEY, target, propertyKey)) {
|
|
54
|
-
Reflect.defineMetadata(REQUEST_BODY_FILES_KEY, [], target, propertyKey);
|
|
55
|
-
}
|
|
56
|
-
const existingMetadata = Reflect.getMetadata(
|
|
57
|
-
REQUEST_BODY_FILES_KEY,
|
|
58
|
-
target,
|
|
59
|
-
propertyKey,
|
|
60
|
-
) as {
|
|
61
|
-
fieldName: string;
|
|
62
|
-
index: number;
|
|
63
|
-
}[];
|
|
64
|
-
existingMetadata.push({
|
|
65
|
-
fieldName: fieldName ? fieldName : "all",
|
|
66
|
-
index: parameterIndex,
|
|
67
|
-
});
|
|
68
|
-
Reflect.defineMetadata(
|
|
69
|
-
REQUEST_BODY_FILES_KEY,
|
|
70
|
-
existingMetadata,
|
|
71
|
-
target,
|
|
72
|
-
propertyKey,
|
|
73
|
-
);
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
type Foptions = {
|
|
78
|
-
saveAs?: string;
|
|
79
|
-
dest?: true;
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
export type MultipartFile = FsM | SavedMultipartFile;
|
|
83
|
-
export function UploadFileFromRequest(req: IRequest, options?: Foptions) {
|
|
84
|
-
return Promise.resolve(
|
|
85
|
-
req.file().then(async (f) => {
|
|
86
|
-
if (f && f.file) {
|
|
87
|
-
let fname = f.filename;
|
|
88
|
-
if (options) {
|
|
89
|
-
if (options.dest) {
|
|
90
|
-
fname = options.saveAs
|
|
91
|
-
? options.dest + "/" + options.saveAs
|
|
92
|
-
: options.dest + "/" + f.filename;
|
|
93
|
-
} else {
|
|
94
|
-
fname = path.join(
|
|
95
|
-
process.cwd(),
|
|
96
|
-
`public/${options.saveAs ? options.saveAs : f.filename}`,
|
|
97
|
-
);
|
|
98
|
-
}
|
|
99
|
-
} else {
|
|
100
|
-
fname = path.join(process.cwd(), `public/${f.filename}`);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
if (fs.existsSync(fname)) {
|
|
104
|
-
throw new InternalErrorException("File already exists.");
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
await pipeline(f.file!, fs.createWriteStream(fname));
|
|
108
|
-
|
|
109
|
-
return {
|
|
110
|
-
...f,
|
|
111
|
-
filename: options?.saveAs ? options.saveAs : f.filename,
|
|
112
|
-
} as MultipartFile;
|
|
113
|
-
}
|
|
114
|
-
}),
|
|
115
|
-
);
|
|
116
|
-
}
|