@avleon/core 0.0.12 → 0.0.14
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/dist/classToOpenapi.d.ts +0 -0
- package/dist/classToOpenapi.js +1 -0
- package/dist/exceptions/http-exceptions.d.ts +0 -9
- package/dist/exceptions/http-exceptions.js +17 -9
- package/dist/file-storage.d.ts +22 -5
- package/dist/file-storage.js +203 -55
- package/dist/helpers.d.ts +2 -2
- package/dist/helpers.js +23 -17
- package/dist/icore.d.ts +28 -15
- package/dist/icore.js +87 -52
- package/dist/index.d.ts +3 -0
- package/dist/index.js +32 -7
- package/dist/logger.d.ts +12 -0
- package/dist/logger.js +87 -0
- package/dist/multipart.d.ts +3 -3
- package/dist/multipart.js +7 -2
- package/dist/params.js +4 -0
- package/dist/response.d.ts +13 -3
- package/dist/response.js +51 -9
- package/dist/swagger-schema.d.ts +0 -6
- package/dist/swagger-schema.js +102 -80
- package/package.json +5 -5
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
|
@@ -39,12 +39,3 @@ export declare class ForbiddenException extends BaseHttpException {
|
|
|
39
39
|
constructor(message: any);
|
|
40
40
|
}
|
|
41
41
|
export type HttpException = NotFoundException | BadRequestException | UnauthorizedException | InternalErrorException | ForbiddenException;
|
|
42
|
-
export type HttpExceptions = {
|
|
43
|
-
NotFound: (message: any) => NotFoundException;
|
|
44
|
-
ValidationError: (message: any) => ValidationErrorException;
|
|
45
|
-
BadRequest: (message: any) => BadRequestException;
|
|
46
|
-
Unauthorized: (message: any) => UnauthorizedException;
|
|
47
|
-
Forbidden: (message: any) => ForbiddenException;
|
|
48
|
-
InternalError: (message: any) => InternalErrorException;
|
|
49
|
-
};
|
|
50
|
-
export declare const httpExcepitoins: HttpExceptions;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.ForbiddenException = exports.UnauthorizedException = exports.NotFoundException = exports.InternalErrorException = exports.ValidationErrorException = exports.BadRequestException = exports.BaseHttpException = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* @copyright 2024
|
|
6
6
|
* @author Tareq Hossain
|
|
@@ -65,11 +65,19 @@ class ForbiddenException extends BaseHttpException {
|
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
67
|
exports.ForbiddenException = ForbiddenException;
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
68
|
+
// export type HttpExceptions = {
|
|
69
|
+
// NotFound: (message: any) => NotFoundException,
|
|
70
|
+
// ValidationError: (message: any) =>ValidationErrorException,
|
|
71
|
+
// BadRequest: (message: any) => BadRequestException,
|
|
72
|
+
// Unauthorized: (message: any) => UnauthorizedException,
|
|
73
|
+
// Forbidden: (message: any) => ForbiddenException,
|
|
74
|
+
// InternalError: (message: any) => InternalErrorException
|
|
75
|
+
// }
|
|
76
|
+
// export const httpExcepitoins: HttpExceptions = {
|
|
77
|
+
// NotFound:(message:any)=>new NotFoundException(message),
|
|
78
|
+
// ValidationError:(message:any)=>new ValidationErrorException(message),
|
|
79
|
+
// BadRequest:(message:any)=>new BadRequestException(message),
|
|
80
|
+
// Unauthorized:(message:any)=>new UnauthorizedException(message),
|
|
81
|
+
// Forbidden:(message:any)=>new ForbiddenException(message),
|
|
82
|
+
// InternalError: (message:any)=> new InternalErrorException(message)
|
|
83
|
+
// }
|
package/dist/file-storage.d.ts
CHANGED
|
@@ -1,17 +1,34 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { PathLike } from "fs";
|
|
2
|
+
import { MultipartFile } from "./multipart";
|
|
2
3
|
interface TransformOptions {
|
|
3
4
|
resize?: {
|
|
4
5
|
width: number;
|
|
5
6
|
height: number;
|
|
6
7
|
};
|
|
7
|
-
format?:
|
|
8
|
+
format?: "jpeg" | "png" | "webp" | "avif";
|
|
8
9
|
quality?: number;
|
|
9
10
|
}
|
|
10
|
-
export
|
|
11
|
+
export interface FileStorageInterface {
|
|
12
|
+
transform(options: TransformOptions): FileStorage;
|
|
13
|
+
save(file: MultipartFile, options?: SaveOptionsSingle): Promise<MultipartFile | undefined>;
|
|
14
|
+
saveAll(files: MultipartFile[], options?: SaveOptions): Promise<MultipartFile[] | undefined>;
|
|
15
|
+
remove(filepath: PathLike): Promise<void>;
|
|
16
|
+
}
|
|
17
|
+
export interface SaveOptions {
|
|
18
|
+
overwrite?: boolean;
|
|
19
|
+
to?: string;
|
|
20
|
+
}
|
|
21
|
+
export interface SaveOptionsSingle extends SaveOptions {
|
|
22
|
+
saveAs?: string;
|
|
23
|
+
}
|
|
24
|
+
export declare class FileStorage implements FileStorageInterface {
|
|
11
25
|
private transformOptions;
|
|
12
26
|
transform(options: TransformOptions): this;
|
|
13
|
-
|
|
14
|
-
|
|
27
|
+
private isFileExists;
|
|
28
|
+
save(f: MultipartFile, options?: SaveOptionsSingle): Promise<import("@fastify/multipart").MultipartFile | undefined>;
|
|
29
|
+
remove(filepath: PathLike): Promise<void>;
|
|
30
|
+
saveAll(files: MultipartFile[], options?: SaveOptions): Promise<MultipartFile[]>;
|
|
15
31
|
private processImage;
|
|
32
|
+
private ensureDirectoryExists;
|
|
16
33
|
}
|
|
17
34
|
export {};
|
package/dist/file-storage.js
CHANGED
|
@@ -48,7 +48,7 @@ const path_1 = __importDefault(require("path"));
|
|
|
48
48
|
const promises_1 = require("stream/promises");
|
|
49
49
|
const http_exceptions_1 = require("./exceptions/http-exceptions");
|
|
50
50
|
const decorators_1 = require("./decorators");
|
|
51
|
-
const
|
|
51
|
+
const system_exception_1 = require("./exceptions/system-exception");
|
|
52
52
|
let FileStorage = class FileStorage {
|
|
53
53
|
constructor() {
|
|
54
54
|
this.transformOptions = null;
|
|
@@ -57,77 +57,218 @@ let FileStorage = class FileStorage {
|
|
|
57
57
|
this.transformOptions = options;
|
|
58
58
|
return this;
|
|
59
59
|
}
|
|
60
|
+
isFileExists(fpath) {
|
|
61
|
+
return fs_1.default.existsSync(fpath);
|
|
62
|
+
}
|
|
60
63
|
async save(f, options) {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
|
|
64
|
+
let foptions = {
|
|
65
|
+
overwrite: options && options.overwrite ? options.overwrite : true,
|
|
66
|
+
};
|
|
67
|
+
try {
|
|
68
|
+
if (f.type == "file") {
|
|
69
|
+
const fname = path_1.default.join(process.cwd(), `public/${f.filename}`);
|
|
70
|
+
if (!foptions.overwrite && this.isFileExists(fname)) {
|
|
71
|
+
throw new system_exception_1.SystemUseError("File already exits.");
|
|
69
72
|
}
|
|
70
|
-
}
|
|
71
|
-
else {
|
|
72
|
-
fname = path_1.default.join(process.cwd(), `public/${f.filename}`);
|
|
73
|
-
}
|
|
74
|
-
if (fs_1.default.existsSync(fname) && !options.overwrite) {
|
|
75
|
-
throw new http_exceptions_1.InternalErrorException("File already exists.");
|
|
76
|
-
}
|
|
77
|
-
if (this.transformOptions) {
|
|
78
|
-
const tempFilePath = path_1.default.join(os_1.default.tmpdir(), `temp-${Date.now()}-${f.filename}`);
|
|
79
|
-
await (0, promises_1.pipeline)(f.file, fs_1.default.createWriteStream(tempFilePath));
|
|
80
|
-
await this.processImage(fs_1.default.createReadStream(tempFilePath), fname);
|
|
81
|
-
fs_1.default.unlinkSync(tempFilePath);
|
|
82
|
-
}
|
|
83
|
-
else {
|
|
84
73
|
await (0, promises_1.pipeline)(f.file, fs_1.default.createWriteStream(fname));
|
|
74
|
+
return f;
|
|
85
75
|
}
|
|
86
|
-
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
throw new system_exception_1.SystemUseError("Can't upload file");
|
|
87
79
|
}
|
|
88
80
|
}
|
|
89
|
-
async
|
|
90
|
-
if (
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
81
|
+
async remove(filepath) {
|
|
82
|
+
if (!this.isFileExists(path_1.default.join(process.cwd(), "public/" + filepath))) {
|
|
83
|
+
throw new system_exception_1.SystemUseError("File doesn't exists.");
|
|
84
|
+
}
|
|
85
|
+
return fs_1.default.unlinkSync(path_1.default.join(process.cwd(), "public/" + filepath));
|
|
86
|
+
}
|
|
87
|
+
async saveAll(files, options) {
|
|
88
|
+
try {
|
|
89
|
+
let foptions = {
|
|
90
|
+
overwrite: options && options.overwrite ? options.overwrite : true,
|
|
91
|
+
};
|
|
92
|
+
for (let f of files) {
|
|
93
|
+
let uploadPath = `public`;
|
|
94
|
+
if (options === null || options === void 0 ? void 0 : options.to) {
|
|
95
|
+
uploadPath = `public/${options.to}`;
|
|
96
|
+
}
|
|
97
|
+
const fname = path_1.default.join(process.cwd(), `${uploadPath}/${f.filename}`);
|
|
98
|
+
await this.ensureDirectoryExists(fname);
|
|
99
|
+
if (f.file) {
|
|
100
|
+
await (0, promises_1.pipeline)(f.file, fs_1.default.createWriteStream(fname));
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
const fp = f;
|
|
104
|
+
await (0, promises_1.pipeline)(fs_1.default.createReadStream(fp.filepath), fs_1.default.createWriteStream(fname));
|
|
105
|
+
fs_1.default.unlinkSync(fp.filepath);
|
|
106
|
+
}
|
|
106
107
|
}
|
|
107
|
-
return
|
|
108
|
+
return files;
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
console.error(error);
|
|
112
|
+
throw new system_exception_1.SystemUseError("Can't upload file");
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
/* private async saveSingleFile(
|
|
116
|
+
f: MultipartFile,
|
|
117
|
+
options: any
|
|
118
|
+
): Promise<MultipartFile | null> {
|
|
119
|
+
if (f && f.type == "file") {
|
|
120
|
+
let fname = f.filename;
|
|
121
|
+
if (options) {
|
|
122
|
+
if (options.dest) {
|
|
123
|
+
fname = options.saveAs
|
|
124
|
+
? options.dest + "/" + options.saveAs
|
|
125
|
+
: options.dest + "/" + f.filename;
|
|
126
|
+
} else {
|
|
127
|
+
fname = path.join(
|
|
128
|
+
process.cwd(),
|
|
129
|
+
`public/${options.saveAs ? options.saveAs : f.filename}`
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
} else {
|
|
133
|
+
fname = path.join(process.cwd(), `public/${f.filename}`);
|
|
134
|
+
}
|
|
135
|
+
await this.ensureDirectoryExists(fname); // Ensure directory exists
|
|
136
|
+
|
|
137
|
+
if (fs.existsSync(fname) && !options.overwrite) {
|
|
138
|
+
throw new InternalErrorException("File already exists.");
|
|
108
139
|
}
|
|
140
|
+
|
|
141
|
+
if (this.transformOptions) {
|
|
142
|
+
if (f.type == "file") {
|
|
143
|
+
const tempFilePath = path.join(
|
|
144
|
+
os.tmpdir(),
|
|
145
|
+
`temp-${Date.now()}-${f.filename}`
|
|
146
|
+
);
|
|
147
|
+
await pipeline(f.file!, fs.createWriteStream(tempFilePath));
|
|
148
|
+
await this.processImage(fs.createReadStream(tempFilePath), fname);
|
|
149
|
+
fs.unlinkSync(tempFilePath);
|
|
150
|
+
} else if (f.type == "fil") {
|
|
151
|
+
await this.processImage(fs.createReadStream(f.filepath), fname);
|
|
152
|
+
}
|
|
153
|
+
} else {
|
|
154
|
+
if (f.file) {
|
|
155
|
+
await pipeline(f.file!, fs.createWriteStream(fname));
|
|
156
|
+
} else if (f.filepath) {
|
|
157
|
+
fs.copyFileSync(f.filepath, fname);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return {
|
|
161
|
+
...f,
|
|
162
|
+
filename: options?.saveAs ? options.saveAs : f.filename,
|
|
163
|
+
} as MultipartFile;
|
|
164
|
+
}
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
async saveAs(
|
|
169
|
+
f: MultipartFile | MultipartFile[],
|
|
170
|
+
filename: string | string[],
|
|
171
|
+
options: any
|
|
172
|
+
) {
|
|
173
|
+
if (
|
|
174
|
+
Array.isArray(f) &&
|
|
175
|
+
Array.isArray(filename) &&
|
|
176
|
+
f.length === filename.length
|
|
177
|
+
) {
|
|
178
|
+
const savedFiles: MultipartFile[] = [];
|
|
179
|
+
for (let i = 0; i < f.length; i++) {
|
|
180
|
+
const savedFile = await this.saveSingleFileAs(
|
|
181
|
+
f[i],
|
|
182
|
+
filename[i],
|
|
183
|
+
options
|
|
184
|
+
);
|
|
185
|
+
if (savedFile) {
|
|
186
|
+
savedFiles.push(savedFile);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return savedFiles;
|
|
190
|
+
} else if (!Array.isArray(f) && !Array.isArray(filename)) {
|
|
191
|
+
return await this.saveSingleFileAs(f, filename as string, options);
|
|
192
|
+
} else {
|
|
193
|
+
throw new InternalErrorException(
|
|
194
|
+
"File and filename array lengths do not match."
|
|
195
|
+
);
|
|
196
|
+
}
|
|
109
197
|
}
|
|
198
|
+
|
|
199
|
+
private async saveSingleFileAs(
|
|
200
|
+
f: MultipartFile,
|
|
201
|
+
filename: string,
|
|
202
|
+
options: any
|
|
203
|
+
): Promise<MultipartFile | null> {
|
|
204
|
+
if (f) {
|
|
205
|
+
let fname = filename;
|
|
206
|
+
|
|
207
|
+
if (options && options.dest) {
|
|
208
|
+
fname = options.dest + "/" + filename;
|
|
209
|
+
} else {
|
|
210
|
+
fname = path.join(process.cwd(), `public/${filename}`);
|
|
211
|
+
}
|
|
212
|
+
await this.ensureDirectoryExists(fname);
|
|
213
|
+
|
|
214
|
+
if (fs.existsSync(fname) && !options.overwrite) {
|
|
215
|
+
throw new InternalErrorException("File already exists.");
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
if (this.transformOptions) {
|
|
219
|
+
if (f.file) {
|
|
220
|
+
const tempFilePath = path.join(
|
|
221
|
+
os.tmpdir(),
|
|
222
|
+
`temp-${Date.now()}-${f.filename}`
|
|
223
|
+
);
|
|
224
|
+
await pipeline(f.file!, fs.createWriteStream(tempFilePath));
|
|
225
|
+
await this.processImage(fs.createReadStream(tempFilePath), fname);
|
|
226
|
+
fs.unlinkSync(tempFilePath);
|
|
227
|
+
} else if (f.filepath) {
|
|
228
|
+
await this.processImage(fs.createReadStream(f.filepath), fname);
|
|
229
|
+
}
|
|
230
|
+
} else {
|
|
231
|
+
if (f.file) {
|
|
232
|
+
await pipeline(f.file!, fs.createWriteStream(fname));
|
|
233
|
+
} else if (f.filepath) {
|
|
234
|
+
fs.copyFileSync(f.filepath, fname);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
return { ...f, filename: filename } as MultipartFile;
|
|
239
|
+
}
|
|
240
|
+
return null;
|
|
241
|
+
}
|
|
242
|
+
*/
|
|
110
243
|
async processImage(fileStream, outputPath) {
|
|
111
244
|
var _a, _b;
|
|
112
245
|
try {
|
|
113
|
-
const sharp = await Promise.resolve().then(() => __importStar(require(
|
|
246
|
+
const sharp = await Promise.resolve().then(() => __importStar(require("sharp"))); // Lazy import sharp
|
|
114
247
|
let sharpPipeline = sharp.default();
|
|
115
248
|
if ((_a = this.transformOptions) === null || _a === void 0 ? void 0 : _a.resize) {
|
|
116
249
|
sharpPipeline = sharpPipeline.resize(this.transformOptions.resize.width, this.transformOptions.resize.height);
|
|
117
250
|
}
|
|
118
251
|
if ((_b = this.transformOptions) === null || _b === void 0 ? void 0 : _b.format) {
|
|
119
252
|
switch (this.transformOptions.format) {
|
|
120
|
-
case
|
|
121
|
-
sharpPipeline = sharpPipeline.jpeg({
|
|
253
|
+
case "jpeg":
|
|
254
|
+
sharpPipeline = sharpPipeline.jpeg({
|
|
255
|
+
quality: this.transformOptions.quality || 80,
|
|
256
|
+
});
|
|
122
257
|
break;
|
|
123
|
-
case
|
|
124
|
-
sharpPipeline = sharpPipeline.png({
|
|
258
|
+
case "png":
|
|
259
|
+
sharpPipeline = sharpPipeline.png({
|
|
260
|
+
quality: this.transformOptions.quality || 80,
|
|
261
|
+
});
|
|
125
262
|
break;
|
|
126
|
-
case
|
|
127
|
-
sharpPipeline = sharpPipeline.webp({
|
|
263
|
+
case "webp":
|
|
264
|
+
sharpPipeline = sharpPipeline.webp({
|
|
265
|
+
quality: this.transformOptions.quality || 80,
|
|
266
|
+
});
|
|
128
267
|
break;
|
|
129
|
-
case
|
|
130
|
-
sharpPipeline = sharpPipeline.avif({
|
|
268
|
+
case "avif":
|
|
269
|
+
sharpPipeline = sharpPipeline.avif({
|
|
270
|
+
quality: this.transformOptions.quality || 80,
|
|
271
|
+
});
|
|
131
272
|
break;
|
|
132
273
|
default:
|
|
133
274
|
break;
|
|
@@ -136,16 +277,23 @@ let FileStorage = class FileStorage {
|
|
|
136
277
|
await (0, promises_1.pipeline)(fileStream, sharpPipeline, fs_1.default.createWriteStream(outputPath));
|
|
137
278
|
}
|
|
138
279
|
catch (error) {
|
|
139
|
-
if (error.code ===
|
|
140
|
-
|
|
280
|
+
if (error.code === "MODULE_NOT_FOUND" &&
|
|
281
|
+
error.message.includes("sharp")) {
|
|
282
|
+
throw new http_exceptions_1.InternalErrorException("sharp module not found. Please install sharp to use image transformations.");
|
|
141
283
|
}
|
|
142
|
-
console.error(
|
|
143
|
-
throw new http_exceptions_1.InternalErrorException(
|
|
284
|
+
console.error("Image processing failed:", error);
|
|
285
|
+
throw new http_exceptions_1.InternalErrorException("Image processing failed.");
|
|
144
286
|
}
|
|
145
287
|
finally {
|
|
146
288
|
this.transformOptions = null; // Reset transform options after processing
|
|
147
289
|
}
|
|
148
290
|
}
|
|
291
|
+
async ensureDirectoryExists(filePath) {
|
|
292
|
+
const dir = path_1.default.dirname(filePath);
|
|
293
|
+
if (!fs_1.default.existsSync(dir)) {
|
|
294
|
+
fs_1.default.mkdirSync(dir, { recursive: true });
|
|
295
|
+
}
|
|
296
|
+
}
|
|
149
297
|
};
|
|
150
298
|
exports.FileStorage = FileStorage;
|
|
151
299
|
exports.FileStorage = FileStorage = __decorate([
|
package/dist/helpers.d.ts
CHANGED
|
@@ -23,10 +23,10 @@ export declare function jsonToJs(value: string): any;
|
|
|
23
23
|
export declare function jsonToInstance(value: string, instance: Constructor): any;
|
|
24
24
|
export declare function transformObjectByInstanceToObject(instance: Constructor, value: object): Record<string, any>;
|
|
25
25
|
export declare const isClassValidatorClass: (target: Constructor) => boolean;
|
|
26
|
-
export declare function validateObjectByInstance(target: Constructor, value?: object, options?:
|
|
26
|
+
export declare function validateObjectByInstance(target: Constructor, value?: object, options?: "object" | "array"): Promise<any>;
|
|
27
27
|
type ValidationError = {
|
|
28
28
|
count: number;
|
|
29
29
|
errors: any;
|
|
30
30
|
};
|
|
31
|
-
export declare function validateRequestBody(target: Constructor, value: object, options?:
|
|
31
|
+
export declare function validateRequestBody(target: Constructor, value: object, options?: "object" | "array"): ValidationError;
|
|
32
32
|
export {};
|
package/dist/helpers.js
CHANGED
|
@@ -43,7 +43,7 @@ function inject(cls) {
|
|
|
43
43
|
}
|
|
44
44
|
function isConstructor(func) {
|
|
45
45
|
// Check if the func is a function
|
|
46
|
-
if (typeof func !==
|
|
46
|
+
if (typeof func !== "function") {
|
|
47
47
|
return false;
|
|
48
48
|
}
|
|
49
49
|
// Check if it's an arrow function or a built-in JavaScript function
|
|
@@ -51,13 +51,13 @@ function isConstructor(func) {
|
|
|
51
51
|
return false;
|
|
52
52
|
}
|
|
53
53
|
// Check if it has a `prototype` property
|
|
54
|
-
if (func.prototype && typeof func.prototype ===
|
|
54
|
+
if (func.prototype && typeof func.prototype === "object") {
|
|
55
55
|
return true;
|
|
56
56
|
}
|
|
57
57
|
// If it's not a constructor, check if it can be called with the new keyword
|
|
58
58
|
try {
|
|
59
59
|
const instance = new func();
|
|
60
|
-
return typeof instance ===
|
|
60
|
+
return typeof instance === "object";
|
|
61
61
|
}
|
|
62
62
|
catch (e) {
|
|
63
63
|
return false;
|
|
@@ -83,8 +83,7 @@ function parsedPath(ipath) {
|
|
|
83
83
|
const isClassValidator = (target) => {
|
|
84
84
|
try {
|
|
85
85
|
const clsval = require("class-validator");
|
|
86
|
-
const result = (0, class_validator_1.getMetadataStorage)()
|
|
87
|
-
.getTargetValidationMetadatas(target, '', false, false);
|
|
86
|
+
const result = (0, class_validator_1.getMetadataStorage)().getTargetValidationMetadatas(target, "", false, false);
|
|
88
87
|
return result.length > 0;
|
|
89
88
|
}
|
|
90
89
|
catch (err) {
|
|
@@ -216,7 +215,7 @@ const isClassValidatorClass = (target) => {
|
|
|
216
215
|
}
|
|
217
216
|
};
|
|
218
217
|
exports.isClassValidatorClass = isClassValidatorClass;
|
|
219
|
-
async function validateObjectByInstance(target, value = {}, options =
|
|
218
|
+
async function validateObjectByInstance(target, value = {}, options = "array") {
|
|
220
219
|
try {
|
|
221
220
|
const { validateOrReject } = require("class-validator");
|
|
222
221
|
const { plainToInstance } = require("class-transformer");
|
|
@@ -224,11 +223,16 @@ async function validateObjectByInstance(target, value = {}, options = 'array') {
|
|
|
224
223
|
}
|
|
225
224
|
catch (error) {
|
|
226
225
|
if (typeof error == "object" && Array.isArray(error)) {
|
|
227
|
-
const errors = options ==
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
226
|
+
const errors = options == "object"
|
|
227
|
+
? error.reduce((acc, x) => {
|
|
228
|
+
//acc[x.property] = Object.values(x.constraints);
|
|
229
|
+
acc[x.property] = x.constraints;
|
|
230
|
+
return acc;
|
|
231
|
+
}, {})
|
|
232
|
+
: error.map((x) => ({
|
|
233
|
+
path: x.property,
|
|
234
|
+
constraints: x.constraints,
|
|
235
|
+
}));
|
|
232
236
|
return errors;
|
|
233
237
|
}
|
|
234
238
|
else {
|
|
@@ -236,14 +240,16 @@ async function validateObjectByInstance(target, value = {}, options = 'array') {
|
|
|
236
240
|
}
|
|
237
241
|
}
|
|
238
242
|
}
|
|
239
|
-
function validateRequestBody(target, value, options =
|
|
243
|
+
function validateRequestBody(target, value, options = "array") {
|
|
240
244
|
if (!(0, exports.isClassValidatorClass)(target))
|
|
241
245
|
return { count: 0, errors: {} };
|
|
242
246
|
const error = (0, class_validator_1.validateSync)((0, class_transformer_1.plainToInstance)(target, value ? value : {}));
|
|
243
|
-
const errors = options ==
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
247
|
+
const errors = options == "object"
|
|
248
|
+
? error.reduce((acc, x) => {
|
|
249
|
+
//acc[x.property] = Object.values(x.constraints);
|
|
250
|
+
acc[x.property] = x.constraints;
|
|
251
|
+
return acc;
|
|
252
|
+
}, {})
|
|
253
|
+
: error.map((x) => ({ path: x.property, constraints: x.constraints }));
|
|
248
254
|
return { count: error.length, errors };
|
|
249
255
|
}
|
package/dist/icore.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @email xtrinsic96@gmail.com
|
|
5
5
|
* @url https://github.com/xtareq
|
|
6
6
|
*/
|
|
7
|
-
import {
|
|
7
|
+
import { FastifyReply, FastifyRequest, HookHandlerDoneFunction, InjectOptions, LightMyRequestResponse } from "fastify";
|
|
8
8
|
import { Constructable } from "typedi";
|
|
9
9
|
import { Constructor } from "./helpers";
|
|
10
10
|
import { PathLike } from "fs";
|
|
@@ -27,9 +27,19 @@ export interface IRequest extends FastifyRequest {
|
|
|
27
27
|
headers: any;
|
|
28
28
|
user?: any;
|
|
29
29
|
}
|
|
30
|
+
export interface DoneFunction extends HookHandlerDoneFunction {
|
|
31
|
+
}
|
|
30
32
|
export interface IResponse extends FastifyReply {
|
|
31
33
|
}
|
|
32
|
-
export
|
|
34
|
+
export type TestResponseType = LightMyRequestResponse;
|
|
35
|
+
export type TestResponse = TestResponseType | Promise<TestResponseType>;
|
|
36
|
+
export interface TestApplication {
|
|
37
|
+
get: (url: string, options?: InjectOptions) => TestResponse;
|
|
38
|
+
post: (url: string, options?: InjectOptions) => TestResponse;
|
|
39
|
+
put: (url: string, options?: InjectOptions) => TestResponse;
|
|
40
|
+
patch: (url: string, options?: InjectOptions) => TestResponse;
|
|
41
|
+
delete: (url: string, options?: InjectOptions) => TestResponse;
|
|
42
|
+
options: (url: string, options?: InjectOptions) => TestResponse;
|
|
33
43
|
}
|
|
34
44
|
export interface ParamMetaOptions {
|
|
35
45
|
index: number;
|
|
@@ -39,8 +49,15 @@ export interface ParamMetaOptions {
|
|
|
39
49
|
validate: boolean;
|
|
40
50
|
dataType: any;
|
|
41
51
|
validatorClass: boolean;
|
|
52
|
+
schema?: any;
|
|
42
53
|
type: "route:param" | "route:query" | "route:body" | "route:header" | "route:user" | "route:file" | "route:files";
|
|
43
54
|
}
|
|
55
|
+
export interface ParamMetaFilesOptions {
|
|
56
|
+
index: number;
|
|
57
|
+
type: "route:files";
|
|
58
|
+
files: MultipartFile[];
|
|
59
|
+
fieldName: string;
|
|
60
|
+
}
|
|
44
61
|
export interface MethodParamMeta {
|
|
45
62
|
params: ParamMetaOptions[];
|
|
46
63
|
query: ParamMetaOptions[];
|
|
@@ -49,7 +66,7 @@ export interface MethodParamMeta {
|
|
|
49
66
|
currentUser: ParamMetaOptions[];
|
|
50
67
|
swagger?: OpenApiUiOptions;
|
|
51
68
|
file?: any[];
|
|
52
|
-
files?:
|
|
69
|
+
files?: ParamMetaFilesOptions[];
|
|
53
70
|
}
|
|
54
71
|
type StaticFileOptions = {
|
|
55
72
|
path?: PathLike;
|
|
@@ -58,7 +75,6 @@ type StaticFileOptions = {
|
|
|
58
75
|
type MultipartOptions = {
|
|
59
76
|
destination: PathLike;
|
|
60
77
|
} & FastifyMultipartOptions;
|
|
61
|
-
type AvleonApp = FastifyInstance;
|
|
62
78
|
export type TestAppOptions = {
|
|
63
79
|
controllers: Constructor[];
|
|
64
80
|
};
|
|
@@ -72,7 +88,7 @@ export interface IAvleonApplication {
|
|
|
72
88
|
useCors(corsOptions?: FastifyCorsOptions): void;
|
|
73
89
|
useOpenApi<T extends IConfig<R>, R = ReturnType<InstanceType<Constructable<T>>["config"]>>(ConfigClass: Constructable<T>, modifyConfig?: (config: R) => R): void;
|
|
74
90
|
useSwagger(options: OpenApiUiOptions): Promise<void>;
|
|
75
|
-
useMultipart(options: MultipartOptions):
|
|
91
|
+
useMultipart(options: MultipartOptions): void;
|
|
76
92
|
useMiddlewares<T extends AppMiddleware>(mclasses: Constructor<T>[]): void;
|
|
77
93
|
useAuthoriztion<T extends any>(middleware: Constructor<T>): void;
|
|
78
94
|
mapRoute<T extends (...args: any[]) => any>(method: "get" | "post" | "put" | "delete", path: string, fn: T): Promise<void>;
|
|
@@ -83,7 +99,7 @@ export interface IAvleonApplication {
|
|
|
83
99
|
mapControllers(controllers: any[]): any;
|
|
84
100
|
useStaticFiles(options?: StaticFileOptions): void;
|
|
85
101
|
run(port?: number): Promise<void>;
|
|
86
|
-
getTestApp():
|
|
102
|
+
getTestApp(): TestApplication;
|
|
87
103
|
}
|
|
88
104
|
declare class AvleonApplication implements IAvleonApplication {
|
|
89
105
|
private static instance;
|
|
@@ -114,7 +130,7 @@ declare class AvleonApplication implements IAvleonApplication {
|
|
|
114
130
|
* Will remove in next major version
|
|
115
131
|
*/
|
|
116
132
|
useSwagger(options: OpenApiUiOptions): Promise<void>;
|
|
117
|
-
useMultipart(options: MultipartOptions):
|
|
133
|
+
useMultipart(options: MultipartOptions): void;
|
|
118
134
|
private handleMiddlewares;
|
|
119
135
|
private executeMiddlewares;
|
|
120
136
|
/**
|
|
@@ -167,7 +183,7 @@ declare class AvleonApplication implements IAvleonApplication {
|
|
|
167
183
|
useStaticFiles(options?: StaticFileOptions): void;
|
|
168
184
|
initializeDatabase(): Promise<void>;
|
|
169
185
|
run(port?: number): Promise<void>;
|
|
170
|
-
getTestApp(buildOptions?: any):
|
|
186
|
+
getTestApp(buildOptions?: any): TestApplication;
|
|
171
187
|
}
|
|
172
188
|
export type Application = typeof AvleonApplication;
|
|
173
189
|
export interface ITestBuilder {
|
|
@@ -187,11 +203,11 @@ export declare class TestBuilder {
|
|
|
187
203
|
static createBuilder(): TestBuilder;
|
|
188
204
|
getController<T>(controller: Constructor<T>): T;
|
|
189
205
|
getService<T>(service: Constructor<T>): T;
|
|
190
|
-
getTestApplication(options: TestAppOptions):
|
|
191
|
-
build(app: IAvleonApplication):
|
|
192
|
-
fromApplication(app: IAvleonApplication):
|
|
206
|
+
getTestApplication(options: TestAppOptions): TestApplication;
|
|
207
|
+
build(app: IAvleonApplication): TestApplication;
|
|
208
|
+
fromApplication(app: IAvleonApplication): TestApplication;
|
|
193
209
|
}
|
|
194
|
-
export declare class Builder implements
|
|
210
|
+
export declare class Builder implements IAppBuilder {
|
|
195
211
|
private static instance;
|
|
196
212
|
private alreadyBuilt;
|
|
197
213
|
private database;
|
|
@@ -201,12 +217,9 @@ export declare class Builder implements ITestBuilder, IAppBuilder {
|
|
|
201
217
|
private testBuilder;
|
|
202
218
|
private appConfig;
|
|
203
219
|
private constructor();
|
|
204
|
-
getTestApplication(): AvleonTestAppliction;
|
|
205
220
|
static createAppBuilder(): Builder;
|
|
206
|
-
static creatTestAppBuilder(): ITestBuilder;
|
|
207
221
|
registerPlugin<T extends Function, S extends {}>(plugin: T, options: S): Promise<void>;
|
|
208
222
|
addDataSource<T extends IConfig<R>, R = ReturnType<InstanceType<Constructable<T>>["config"]>>(ConfigClass: Constructable<T>, modifyConfig?: (config: R) => R): void;
|
|
209
|
-
createTestApplication<T extends AvleonTestAppliction>(buildOptions?: any): any;
|
|
210
223
|
build<T extends IAvleonApplication>(): T;
|
|
211
224
|
}
|
|
212
225
|
export {};
|