@avleon/core 0.0.12 → 0.0.13
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/file-storage.d.ts +22 -5
- package/dist/file-storage.js +203 -55
- package/dist/icore.d.ts +7 -1
- package/dist/icore.js +44 -8
- package/dist/multipart.d.ts +3 -3
- package/dist/multipart.js +7 -2
- package/dist/response.d.ts +11 -2
- package/dist/response.js +46 -6
- package/package.json +51 -53
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/icore.d.ts
CHANGED
|
@@ -41,6 +41,12 @@ export interface ParamMetaOptions {
|
|
|
41
41
|
validatorClass: boolean;
|
|
42
42
|
type: "route:param" | "route:query" | "route:body" | "route:header" | "route:user" | "route:file" | "route:files";
|
|
43
43
|
}
|
|
44
|
+
export interface ParamMetaFilesOptions {
|
|
45
|
+
index: number;
|
|
46
|
+
type: "route:files";
|
|
47
|
+
files: MultipartFile[];
|
|
48
|
+
fieldName: string;
|
|
49
|
+
}
|
|
44
50
|
export interface MethodParamMeta {
|
|
45
51
|
params: ParamMetaOptions[];
|
|
46
52
|
query: ParamMetaOptions[];
|
|
@@ -49,7 +55,7 @@ export interface MethodParamMeta {
|
|
|
49
55
|
currentUser: ParamMetaOptions[];
|
|
50
56
|
swagger?: OpenApiUiOptions;
|
|
51
57
|
file?: any[];
|
|
52
|
-
files?:
|
|
58
|
+
files?: ParamMetaFilesOptions[];
|
|
53
59
|
}
|
|
54
60
|
type StaticFileOptions = {
|
|
55
61
|
path?: PathLike;
|
package/dist/icore.js
CHANGED
|
@@ -193,7 +193,6 @@ class AvleonApplication {
|
|
|
193
193
|
return;
|
|
194
194
|
const prototype = Object.getPrototypeOf(ctrl);
|
|
195
195
|
const methods = Object.getOwnPropertyNames(prototype).filter((name) => name !== "constructor");
|
|
196
|
-
let classMiddlewares = [];
|
|
197
196
|
const tag = ctrl.constructor.name.replace("Controller", "");
|
|
198
197
|
const swaggerControllerMeta = Reflect.getMetadata("controller:openapi", ctrl.constructor) || {};
|
|
199
198
|
const authClsMeata = Reflect.getMetadata(container_1.AUTHORIZATION_META_KEY, ctrl.constructor) || { authorize: false, options: undefined };
|
|
@@ -279,7 +278,7 @@ class AvleonApplication {
|
|
|
279
278
|
* @returns
|
|
280
279
|
*/
|
|
281
280
|
async _mapArgs(req, meta) {
|
|
282
|
-
var _a, e_2, _b, _c;
|
|
281
|
+
var _a, e_2, _b, _c, _d, e_3, _e, _f;
|
|
283
282
|
if (!req.hasOwnProperty("_argsCache")) {
|
|
284
283
|
Object.defineProperty(req, "_argsCache", {
|
|
285
284
|
value: new Map(),
|
|
@@ -293,15 +292,15 @@ class AvleonApplication {
|
|
|
293
292
|
}
|
|
294
293
|
const args = meta.params.map((p) => req.params[p.key] || null);
|
|
295
294
|
meta.query.forEach((q) => (args[q.index] = q.key === "all" ? req.query : req.query[q.key]));
|
|
296
|
-
meta.body.forEach((body) => (args[body.index] = req.body));
|
|
295
|
+
meta.body.forEach((body) => (args[body.index] = Object.assign(Object.assign({}, req.body), req.formData)));
|
|
297
296
|
meta.currentUser.forEach((user) => (args[user.index] = req.user));
|
|
298
297
|
meta.headers.forEach((header) => (args[header.index] =
|
|
299
298
|
header.key === "all" ? req.headers : req.headers[header.key]));
|
|
300
299
|
if (meta.file) {
|
|
301
300
|
try {
|
|
302
|
-
for (var
|
|
303
|
-
_c =
|
|
304
|
-
|
|
301
|
+
for (var _g = true, _h = __asyncValues(meta.file), _j; _j = await _h.next(), _a = _j.done, !_a; _g = true) {
|
|
302
|
+
_c = _j.value;
|
|
303
|
+
_g = false;
|
|
305
304
|
let f = _c;
|
|
306
305
|
args[f.index] = await req.file();
|
|
307
306
|
}
|
|
@@ -309,11 +308,48 @@ class AvleonApplication {
|
|
|
309
308
|
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
310
309
|
finally {
|
|
311
310
|
try {
|
|
312
|
-
if (!
|
|
311
|
+
if (!_g && !_a && (_b = _h.return)) await _b.call(_h);
|
|
313
312
|
}
|
|
314
313
|
finally { if (e_2) throw e_2.error; }
|
|
315
314
|
}
|
|
316
315
|
}
|
|
316
|
+
if (meta.files) {
|
|
317
|
+
const files = await req.saveRequestFiles();
|
|
318
|
+
if (!files || files.length === 0) {
|
|
319
|
+
throw new exceptions_1.BadRequestException({ error: "No files uploaded" });
|
|
320
|
+
}
|
|
321
|
+
const fileInfo = files.map((file) => ({
|
|
322
|
+
type: file.type,
|
|
323
|
+
filepath: file.filepath,
|
|
324
|
+
fieldname: file.fieldname,
|
|
325
|
+
filename: file.filename,
|
|
326
|
+
encoding: file.encoding,
|
|
327
|
+
mimetype: file.mimetype,
|
|
328
|
+
fields: file.fields,
|
|
329
|
+
}));
|
|
330
|
+
try {
|
|
331
|
+
for (var _k = true, _l = __asyncValues(meta.files), _m; _m = await _l.next(), _d = _m.done, !_d; _k = true) {
|
|
332
|
+
_f = _m.value;
|
|
333
|
+
_k = false;
|
|
334
|
+
let f = _f;
|
|
335
|
+
const findex = fileInfo.findIndex((x) => x.fieldname == f.fieldName);
|
|
336
|
+
if (f.fieldName != "all" && findex == -1) {
|
|
337
|
+
throw new exceptions_1.BadRequestException(`${f.fieldName} doesn't exists in request files tree.`);
|
|
338
|
+
}
|
|
339
|
+
args[f.index] =
|
|
340
|
+
f.fieldName == "all"
|
|
341
|
+
? fileInfo
|
|
342
|
+
: fileInfo.filter((x) => x.fieldname == f.fieldName);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
catch (e_3_1) { e_3 = { error: e_3_1 }; }
|
|
346
|
+
finally {
|
|
347
|
+
try {
|
|
348
|
+
if (!_k && !_d && (_e = _l.return)) await _e.call(_l);
|
|
349
|
+
}
|
|
350
|
+
finally { if (e_3) throw e_3.error; }
|
|
351
|
+
}
|
|
352
|
+
}
|
|
317
353
|
cache.set(cacheKey, args);
|
|
318
354
|
return args;
|
|
319
355
|
}
|
|
@@ -579,7 +615,7 @@ class TestBuilder {
|
|
|
579
615
|
}
|
|
580
616
|
async getTestApplication(options) {
|
|
581
617
|
const app = AvleonApplication.getInternalApp({
|
|
582
|
-
dataSourceOptions: this.dataSourceOptions
|
|
618
|
+
dataSourceOptions: this.dataSourceOptions,
|
|
583
619
|
});
|
|
584
620
|
app.mapControllers([...options.controllers]);
|
|
585
621
|
const fa = await app.getTestApp();
|
package/dist/multipart.d.ts
CHANGED
|
@@ -4,14 +4,14 @@
|
|
|
4
4
|
* @email xtrinsic96@gmail.com
|
|
5
5
|
* @url https://github.com/xtareq
|
|
6
6
|
*/
|
|
7
|
-
import { MultipartFile as FsM } from "@fastify/multipart";
|
|
7
|
+
import { MultipartFile as FsM, SavedMultipartFile } from "@fastify/multipart";
|
|
8
8
|
import { IRequest } from "./icore";
|
|
9
9
|
export declare function UploadFile(fieldName: string): (target: any, propertyKey: string | symbol, parameterIndex: number) => void;
|
|
10
|
-
export declare function UploadFiles(fieldName
|
|
10
|
+
export declare function UploadFiles(fieldName?: string): (target: any, propertyKey: string | symbol, parameterIndex: number) => void;
|
|
11
11
|
type Foptions = {
|
|
12
12
|
saveAs?: string;
|
|
13
13
|
dest?: true;
|
|
14
14
|
};
|
|
15
|
-
export type MultipartFile = FsM;
|
|
15
|
+
export type MultipartFile = FsM | SavedMultipartFile;
|
|
16
16
|
export declare function UploadFileFromRequest(req: IRequest, options?: Foptions): Promise<FsM | undefined>;
|
|
17
17
|
export {};
|
package/dist/multipart.js
CHANGED
|
@@ -33,7 +33,10 @@ function UploadFiles(fieldName) {
|
|
|
33
33
|
Reflect.defineMetadata(container_1.REQUEST_BODY_FILES_KEY, [], target, propertyKey);
|
|
34
34
|
}
|
|
35
35
|
const existingMetadata = Reflect.getMetadata(container_1.REQUEST_BODY_FILES_KEY, target, propertyKey);
|
|
36
|
-
existingMetadata.push({
|
|
36
|
+
existingMetadata.push({
|
|
37
|
+
fieldName: fieldName ? fieldName : "all",
|
|
38
|
+
index: parameterIndex,
|
|
39
|
+
});
|
|
37
40
|
Reflect.defineMetadata(container_1.REQUEST_BODY_FILES_KEY, existingMetadata, target, propertyKey);
|
|
38
41
|
};
|
|
39
42
|
}
|
|
@@ -43,7 +46,9 @@ function UploadFileFromRequest(req, options) {
|
|
|
43
46
|
let fname = f.filename;
|
|
44
47
|
if (options) {
|
|
45
48
|
if (options.dest) {
|
|
46
|
-
fname = options.saveAs
|
|
49
|
+
fname = options.saveAs
|
|
50
|
+
? options.dest + "/" + options.saveAs
|
|
51
|
+
: options.dest + "/" + f.filename;
|
|
47
52
|
}
|
|
48
53
|
else {
|
|
49
54
|
fname = path_1.default.join(process.cwd(), `public/${options.saveAs ? options.saveAs : f.filename}`);
|
package/dist/response.d.ts
CHANGED
|
@@ -11,6 +11,15 @@ export interface IHttpResponse<T extends any> {
|
|
|
11
11
|
data: T | null;
|
|
12
12
|
}
|
|
13
13
|
export declare class HttpResponse {
|
|
14
|
-
static Ok<T>(obj: any, s?: ClassConstructor<T>):
|
|
15
|
-
static
|
|
14
|
+
static Ok<T>(obj: any, s?: ClassConstructor<T>): IHttpResponse<T>;
|
|
15
|
+
static Created<T>(obj: any, s?: ClassConstructor<T>): IHttpResponse<T>;
|
|
16
|
+
static NoContent(): IHttpResponse<null>;
|
|
17
|
+
static BadRequest(message: string, data?: any): IHttpResponse<any>;
|
|
18
|
+
static Unauthorized(message: string, data?: any): IHttpResponse<any>;
|
|
19
|
+
static Forbidden(message: string, data?: any): IHttpResponse<any>;
|
|
20
|
+
static NotFound(message: string, data?: any): IHttpResponse<any>;
|
|
21
|
+
static InternalServerError(message?: string, data?: any): IHttpResponse<any>;
|
|
22
|
+
static Conflict(message: string, data?: any): IHttpResponse<any>;
|
|
23
|
+
static UnprocessableEntity(message: string, data?: any): IHttpResponse<any>;
|
|
24
|
+
static TooManyRequests(message: string, data?: any): IHttpResponse<any>;
|
|
16
25
|
}
|
package/dist/response.js
CHANGED
|
@@ -22,16 +22,56 @@ class HttpResponse {
|
|
|
22
22
|
static Ok(obj, s) {
|
|
23
23
|
if (s) {
|
|
24
24
|
const isPaginated = obj === null || obj === void 0 ? void 0 : obj.hasOwnProperty("total");
|
|
25
|
-
|
|
26
|
-
const transformedData = (0, class_transformer_1.plainToInstance)(s,
|
|
25
|
+
const dataToTransform = isPaginated ? obj.data : obj;
|
|
26
|
+
const transformedData = (0, class_transformer_1.plainToInstance)(s, dataToTransform, {
|
|
27
27
|
enableImplicitConversion: true,
|
|
28
|
-
excludeExtraneousValues: true,
|
|
28
|
+
excludeExtraneousValues: true,
|
|
29
29
|
});
|
|
30
|
-
|
|
31
|
-
? Object.assign(Object.assign({}, obj), { data: (0, class_transformer_1.instanceToPlain)(transformedData) }) : { data: (0, class_transformer_1.instanceToPlain)(transformedData) }
|
|
30
|
+
const transformedResult = isPaginated
|
|
31
|
+
? Object.assign(Object.assign({}, obj), { data: (0, class_transformer_1.instanceToPlain)(transformedData) }) : { data: (0, class_transformer_1.instanceToPlain)(transformedData) };
|
|
32
|
+
return Object.assign({ message: "success" }, transformedResult);
|
|
32
33
|
}
|
|
33
34
|
return { message: "success", data: obj };
|
|
34
35
|
}
|
|
35
|
-
static
|
|
36
|
+
static Created(obj, s) {
|
|
37
|
+
if (s) {
|
|
38
|
+
const transformedData = (0, class_transformer_1.plainToInstance)(s, obj, {
|
|
39
|
+
enableImplicitConversion: true,
|
|
40
|
+
excludeExtraneousValues: true,
|
|
41
|
+
});
|
|
42
|
+
return {
|
|
43
|
+
message: "created",
|
|
44
|
+
data: (0, class_transformer_1.instanceToPlain)(transformedData),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
return { message: "created", data: obj };
|
|
48
|
+
}
|
|
49
|
+
static NoContent() {
|
|
50
|
+
return { message: "no content", data: null };
|
|
51
|
+
}
|
|
52
|
+
static BadRequest(message, data = null) {
|
|
53
|
+
return { message: message, data: data };
|
|
54
|
+
}
|
|
55
|
+
static Unauthorized(message, data = null) {
|
|
56
|
+
return { message: message, data: data };
|
|
57
|
+
}
|
|
58
|
+
static Forbidden(message, data = null) {
|
|
59
|
+
return { message: message, data: data };
|
|
60
|
+
}
|
|
61
|
+
static NotFound(message, data = null) {
|
|
62
|
+
return { message: message, data: data };
|
|
63
|
+
}
|
|
64
|
+
static InternalServerError(message = "Internal server error", data = null) {
|
|
65
|
+
return { message: message, data: data };
|
|
66
|
+
}
|
|
67
|
+
static Conflict(message, data = null) {
|
|
68
|
+
return { message: message, data: data };
|
|
69
|
+
}
|
|
70
|
+
static UnprocessableEntity(message, data = null) {
|
|
71
|
+
return { message: message, data: data };
|
|
72
|
+
}
|
|
73
|
+
static TooManyRequests(message, data = null) {
|
|
74
|
+
return { message: message, data: data };
|
|
75
|
+
}
|
|
36
76
|
}
|
|
37
77
|
exports.HttpResponse = HttpResponse;
|
package/package.json
CHANGED
|
@@ -1,54 +1,52 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@avleon/core",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"main": "./dist/index.js",
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
"@fastify/
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
"url": "git+https://github.com/avleonjs/avleon-core"
|
|
53
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@avleon/core",
|
|
3
|
+
"version": "0.0.13",
|
|
4
|
+
"main": "./dist/index.js",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"build": "rimraf dist && tsc",
|
|
7
|
+
"watch": "tsc-watch",
|
|
8
|
+
"test": "jest",
|
|
9
|
+
"test:watch": "jest --watch"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [],
|
|
12
|
+
"author": "Tareq Hossain",
|
|
13
|
+
"license": "ISC",
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"@types/jest": "^29.5.14",
|
|
16
|
+
"class-transformer": "^0.5.1",
|
|
17
|
+
"class-validator": "^0.14.1",
|
|
18
|
+
"jest": "^29.7.0",
|
|
19
|
+
"nodemon": "^3.1.7",
|
|
20
|
+
"sharp": "^0.33.5",
|
|
21
|
+
"ts-jest": "^29.2.5",
|
|
22
|
+
"ts-node": "^10.9.2",
|
|
23
|
+
"tsc-watch": "^6.2.1",
|
|
24
|
+
"typeorm": "^0.3.20",
|
|
25
|
+
"typescript": "^5.7.2"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@fastify/cors": "^11.0.0",
|
|
29
|
+
"@fastify/multipart": "^9.0.3",
|
|
30
|
+
"@fastify/static": "^8.1.1",
|
|
31
|
+
"@fastify/swagger": "^9.4.0",
|
|
32
|
+
"@fastify/swagger-ui": "^5.1.0",
|
|
33
|
+
"bcryptjs": "^3.0.2",
|
|
34
|
+
"dotenv": "^16.4.7",
|
|
35
|
+
"fastify": "^5.1.0",
|
|
36
|
+
"reflect-metadata": "^0.2.2",
|
|
37
|
+
"typedi": "^0.10.0"
|
|
38
|
+
},
|
|
39
|
+
"peerDependencies": {
|
|
40
|
+
"typeorm": "^0.3.20",
|
|
41
|
+
"class-transformer": "^0.5.1",
|
|
42
|
+
"class-validator": "^0.14.1"
|
|
43
|
+
},
|
|
44
|
+
"directories": {
|
|
45
|
+
"test": "tests"
|
|
46
|
+
},
|
|
47
|
+
"description": "avleon core",
|
|
48
|
+
"repository": {
|
|
49
|
+
"type": "git",
|
|
50
|
+
"url": "git+https://github.com/avleonjs/avleon-core"
|
|
51
|
+
}
|
|
54
52
|
}
|