@avleon/core 0.0.46 → 0.0.48

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.
Files changed (142) hide show
  1. package/License +21 -21
  2. package/README.md +666 -666
  3. package/dist/chunk-9hOWP6kD.cjs +64 -0
  4. package/dist/chunk-DORXReHP.js +37 -0
  5. package/dist/index-BxIMWhgy.d.ts +1284 -0
  6. package/dist/index-DPn7qtzq.d.cts +1283 -0
  7. package/dist/index.cjs +3194 -0
  8. package/dist/index.cjs.map +1 -0
  9. package/dist/index.js +3022 -79
  10. package/dist/index.js.map +1 -0
  11. package/dist/lib-Bk8hUm06.cjs +7847 -0
  12. package/dist/lib-Bk8hUm06.cjs.map +1 -0
  13. package/dist/lib-CvDxBMkR.js +7843 -0
  14. package/dist/lib-CvDxBMkR.js.map +1 -0
  15. package/package.json +41 -103
  16. package/dist/application.test.d.ts +0 -1
  17. package/dist/application.test.js +0 -15
  18. package/dist/authentication.d.ts +0 -13
  19. package/dist/authentication.js +0 -16
  20. package/dist/cache.d.ts +0 -12
  21. package/dist/cache.js +0 -78
  22. package/dist/cache.test.d.ts +0 -1
  23. package/dist/cache.test.js +0 -36
  24. package/dist/collection.d.ts +0 -43
  25. package/dist/collection.js +0 -231
  26. package/dist/collection.test.d.ts +0 -1
  27. package/dist/collection.test.js +0 -59
  28. package/dist/config.d.ts +0 -18
  29. package/dist/config.js +0 -58
  30. package/dist/config.test.d.ts +0 -1
  31. package/dist/config.test.js +0 -40
  32. package/dist/constants.d.ts +0 -1
  33. package/dist/constants.js +0 -4
  34. package/dist/container.d.ts +0 -30
  35. package/dist/container.js +0 -55
  36. package/dist/controller.d.ts +0 -50
  37. package/dist/controller.js +0 -71
  38. package/dist/controller.test.d.ts +0 -1
  39. package/dist/controller.test.js +0 -97
  40. package/dist/core/application.d.ts +0 -74
  41. package/dist/core/application.js +0 -424
  42. package/dist/core/router.d.ts +0 -44
  43. package/dist/core/router.js +0 -520
  44. package/dist/core/testing.d.ts +0 -21
  45. package/dist/core/testing.js +0 -104
  46. package/dist/core/types.d.ts +0 -67
  47. package/dist/core/types.js +0 -2
  48. package/dist/decorators.d.ts +0 -15
  49. package/dist/decorators.js +0 -41
  50. package/dist/environment-variables.d.ts +0 -49
  51. package/dist/environment-variables.js +0 -130
  52. package/dist/environment-variables.test.d.ts +0 -1
  53. package/dist/environment-variables.test.js +0 -70
  54. package/dist/event-dispatcher.d.ts +0 -22
  55. package/dist/event-dispatcher.js +0 -97
  56. package/dist/event-subscriber.d.ts +0 -14
  57. package/dist/event-subscriber.js +0 -87
  58. package/dist/exceptions/http-exceptions.d.ts +0 -50
  59. package/dist/exceptions/http-exceptions.js +0 -85
  60. package/dist/exceptions/index.d.ts +0 -1
  61. package/dist/exceptions/index.js +0 -17
  62. package/dist/exceptions/system-exception.d.ts +0 -22
  63. package/dist/exceptions/system-exception.js +0 -26
  64. package/dist/file-storage.d.ts +0 -69
  65. package/dist/file-storage.js +0 -323
  66. package/dist/file-storage.test.d.ts +0 -1
  67. package/dist/file-storage.test.js +0 -117
  68. package/dist/helpers.d.ts +0 -11
  69. package/dist/helpers.js +0 -27
  70. package/dist/helpers.test.d.ts +0 -1
  71. package/dist/helpers.test.js +0 -95
  72. package/dist/index.d.ts +0 -57
  73. package/dist/interfaces/avleon-application.d.ts +0 -75
  74. package/dist/interfaces/avleon-application.js +0 -2
  75. package/dist/kenx-provider.d.ts +0 -7
  76. package/dist/kenx-provider.js +0 -44
  77. package/dist/kenx-provider.test.d.ts +0 -1
  78. package/dist/kenx-provider.test.js +0 -36
  79. package/dist/logger.d.ts +0 -12
  80. package/dist/logger.js +0 -87
  81. package/dist/logger.test.d.ts +0 -1
  82. package/dist/logger.test.js +0 -42
  83. package/dist/map-types.d.ts +0 -17
  84. package/dist/map-types.js +0 -89
  85. package/dist/middleware.d.ts +0 -34
  86. package/dist/middleware.js +0 -73
  87. package/dist/middleware.test.d.ts +0 -1
  88. package/dist/middleware.test.js +0 -121
  89. package/dist/multipart.d.ts +0 -17
  90. package/dist/multipart.js +0 -70
  91. package/dist/multipart.test.d.ts +0 -1
  92. package/dist/multipart.test.js +0 -87
  93. package/dist/openapi.d.ts +0 -410
  94. package/dist/openapi.js +0 -59
  95. package/dist/openapi.test.d.ts +0 -1
  96. package/dist/openapi.test.js +0 -111
  97. package/dist/params.d.ts +0 -17
  98. package/dist/params.js +0 -64
  99. package/dist/params.test.d.ts +0 -1
  100. package/dist/params.test.js +0 -83
  101. package/dist/queue.d.ts +0 -29
  102. package/dist/queue.js +0 -84
  103. package/dist/response.d.ts +0 -16
  104. package/dist/response.js +0 -56
  105. package/dist/results.d.ts +0 -20
  106. package/dist/results.js +0 -32
  107. package/dist/route-methods.d.ts +0 -25
  108. package/dist/route-methods.js +0 -60
  109. package/dist/route-methods.test.d.ts +0 -1
  110. package/dist/route-methods.test.js +0 -129
  111. package/dist/swagger-schema.d.ts +0 -37
  112. package/dist/swagger-schema.js +0 -454
  113. package/dist/swagger-schema.test.d.ts +0 -1
  114. package/dist/swagger-schema.test.js +0 -125
  115. package/dist/types/app-builder.interface.d.ts +0 -15
  116. package/dist/types/app-builder.interface.js +0 -8
  117. package/dist/types/application.interface.d.ts +0 -8
  118. package/dist/types/application.interface.js +0 -2
  119. package/dist/utils/common-utils.d.ts +0 -17
  120. package/dist/utils/common-utils.js +0 -108
  121. package/dist/utils/di-utils.d.ts +0 -1
  122. package/dist/utils/di-utils.js +0 -22
  123. package/dist/utils/hash.d.ts +0 -2
  124. package/dist/utils/hash.js +0 -11
  125. package/dist/utils/index.d.ts +0 -2
  126. package/dist/utils/index.js +0 -18
  127. package/dist/utils/object-utils.d.ts +0 -11
  128. package/dist/utils/object-utils.js +0 -198
  129. package/dist/utils/optional-require.d.ts +0 -8
  130. package/dist/utils/optional-require.js +0 -70
  131. package/dist/utils/validation-utils.d.ts +0 -13
  132. package/dist/utils/validation-utils.js +0 -119
  133. package/dist/validation.d.ts +0 -39
  134. package/dist/validation.js +0 -108
  135. package/dist/validation.test.d.ts +0 -1
  136. package/dist/validation.test.js +0 -61
  137. package/dist/validator-extend.d.ts +0 -7
  138. package/dist/validator-extend.js +0 -28
  139. package/dist/websocket.d.ts +0 -10
  140. package/dist/websocket.js +0 -21
  141. package/dist/websocket.test.d.ts +0 -1
  142. package/dist/websocket.test.js +0 -27
@@ -1,85 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.HttpExceptions = exports.ForbiddenException = exports.UnauthorizedException = exports.NotFoundException = exports.InternalErrorException = exports.ValidationErrorException = exports.BadRequestException = exports.BaseHttpException = void 0;
4
- /**
5
- * @copyright 2024
6
- * @author Tareq Hossain
7
- * @email xtrinsic96@gmail.com
8
- * @url https://github.com/xtareq
9
- */
10
- class BaseHttpException extends Error {
11
- constructor(message) {
12
- const stringMessage = typeof message === "string" ? message : JSON.stringify(message);
13
- super(stringMessage);
14
- this.code = 500;
15
- this.name = "HttpException";
16
- this.payload = typeof message === "string" ? { message } : message;
17
- }
18
- isCustomException() {
19
- return true;
20
- }
21
- }
22
- exports.BaseHttpException = BaseHttpException;
23
- class BadRequestException extends BaseHttpException {
24
- constructor(message) {
25
- super(message);
26
- this.name = "BadRequest";
27
- this.code = 400;
28
- }
29
- }
30
- exports.BadRequestException = BadRequestException;
31
- class ValidationErrorException extends BadRequestException {
32
- constructor() {
33
- super(...arguments);
34
- this.name = "ValidationError";
35
- }
36
- }
37
- exports.ValidationErrorException = ValidationErrorException;
38
- class InternalErrorException extends BaseHttpException {
39
- constructor(message = "Something going wrong") {
40
- super(message);
41
- this.name = "InternalError";
42
- this.code = 500;
43
- }
44
- }
45
- exports.InternalErrorException = InternalErrorException;
46
- class NotFoundException extends BaseHttpException {
47
- constructor(message) {
48
- super(message);
49
- this.name = "NotFound";
50
- this.code = 404;
51
- }
52
- }
53
- exports.NotFoundException = NotFoundException;
54
- class UnauthorizedException extends BaseHttpException {
55
- constructor(message) {
56
- super(message);
57
- this.name = "Unauthorized";
58
- this.code = 401;
59
- }
60
- }
61
- exports.UnauthorizedException = UnauthorizedException;
62
- class ForbiddenException extends BaseHttpException {
63
- constructor(message) {
64
- super(message);
65
- this.name = "Forbidden";
66
- this.code = 403;
67
- }
68
- }
69
- exports.ForbiddenException = ForbiddenException;
70
- // export type HttpExceptions = {
71
- // NotFound: (message: any) => NotFoundException,
72
- // ValidationError: (message: any) =>ValidationErrorException,
73
- // BadRequest: (message: any) => BadRequestException,
74
- // Unauthorized: (message: any) => UnauthorizedException,
75
- // Forbidden: (message: any) => ForbiddenException,
76
- // InternalError: (message: any) => InternalErrorException
77
- // }
78
- exports.HttpExceptions = {
79
- notFound: (message = "") => new NotFoundException(message),
80
- validationError: (message = "") => new ValidationErrorException(message),
81
- badRequest: (message = "") => new BadRequestException(message),
82
- unauthorized: (message = "") => new UnauthorizedException(message),
83
- forbidden: (message = "") => new ForbiddenException(message),
84
- internalError: (message = "") => new InternalErrorException(message),
85
- };
@@ -1 +0,0 @@
1
- export * from "./http-exceptions";
@@ -1,17 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
- };
16
- Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./http-exceptions"), exports);
@@ -1,22 +0,0 @@
1
- /**
2
- * @copyright 2024
3
- * @author Tareq Hossain
4
- * @email xtrinsic96@gmail.com
5
- * @url https://github.com/xtareq
6
- */
7
- export interface IRouteDuplicateErr {
8
- path: string;
9
- mpath: string;
10
- method: string;
11
- controller: string;
12
- inverseController?: string;
13
- }
14
- export declare class SystemUseError extends Error {
15
- constructor(message: string);
16
- }
17
- export declare class DuplicateRouteException extends Error {
18
- constructor(params: IRouteDuplicateErr);
19
- }
20
- export declare class EnvironmentVariableNotFound extends Error {
21
- constructor(key: string);
22
- }
@@ -1,26 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.EnvironmentVariableNotFound = exports.DuplicateRouteException = exports.SystemUseError = void 0;
4
- class SystemUseError extends Error {
5
- constructor(message) {
6
- super(message);
7
- }
8
- }
9
- exports.SystemUseError = SystemUseError;
10
- class DuplicateRouteException extends Error {
11
- constructor(params) {
12
- let sameController = params.controller == params.inverseController;
13
- let message = `Duplicate route found for method ${params.method.toUpperCase()}:${params.path == "" ? "'/'" : params.path} `;
14
- message += sameController
15
- ? `in ${params.controller}`
16
- : `both in ${params.controller} and ${params.inverseController}`;
17
- super(message);
18
- }
19
- }
20
- exports.DuplicateRouteException = DuplicateRouteException;
21
- class EnvironmentVariableNotFound extends Error {
22
- constructor(key) {
23
- super(`${key} not found in environment variables.`);
24
- }
25
- }
26
- exports.EnvironmentVariableNotFound = EnvironmentVariableNotFound;
@@ -1,69 +0,0 @@
1
- import fs, { PathLike } from "fs";
2
- import { MultipartFile } from "./multipart";
3
- interface TransformOptions {
4
- resize?: {
5
- width: number;
6
- height: number;
7
- };
8
- format?: "jpeg" | "png" | "webp" | "avif";
9
- quality?: number;
10
- }
11
- export interface FileStorageInterface {
12
- transform(options: TransformOptions): FileStorage;
13
- save(file: MultipartFile, options?: SaveOptionsSingle): Promise<MultipartFile>;
14
- saveAll(files: MultipartFile[], options?: SaveOptions): Promise<MultipartFile[]>;
15
- remove(filepath: string): 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 {
25
- private transformOptions;
26
- private readonly baseDir;
27
- private readonly maxFileSize;
28
- constructor();
29
- /**
30
- * Set transformation options for the next save operation
31
- */
32
- transform(options: TransformOptions): FileStorage;
33
- getUploadFile(fliePath: string): Promise<Buffer<ArrayBufferLike>>;
34
- download(filepath: PathLike): Promise<{
35
- download: boolean;
36
- stream: fs.ReadStream;
37
- filename: string;
38
- }>;
39
- downloadAs(filepath: PathLike, filename: string): Promise<{
40
- download: boolean;
41
- stream: fs.ReadStream;
42
- filename: string;
43
- }>;
44
- /**
45
- * Save a single file with optional transformations
46
- */
47
- save(f: MultipartFile, options?: SaveOptionsSingle): Promise<any>;
48
- /**
49
- * Save multiple files
50
- */
51
- saveAll(files: MultipartFile[], options?: SaveOptions): Promise<any[]>;
52
- /**
53
- * Remove a file from storage
54
- */
55
- remove(filepath: string): Promise<void>;
56
- /**
57
- * Process image with transformations using sharp
58
- */
59
- private processImage;
60
- /**
61
- * Helper methods
62
- */
63
- private isFileExists;
64
- private ensureDirectoryExists;
65
- private removeFileSync;
66
- private isImageFile;
67
- private validateFilename;
68
- }
69
- export {};
@@ -1,323 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
19
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
20
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
21
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
22
- return c > 3 && r && Object.defineProperty(target, key, r), r;
23
- };
24
- var __importStar = (this && this.__importStar) || (function () {
25
- var ownKeys = function(o) {
26
- ownKeys = Object.getOwnPropertyNames || function (o) {
27
- var ar = [];
28
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
- return ar;
30
- };
31
- return ownKeys(o);
32
- };
33
- return function (mod) {
34
- if (mod && mod.__esModule) return mod;
35
- var result = {};
36
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
- __setModuleDefault(result, mod);
38
- return result;
39
- };
40
- })();
41
- var __metadata = (this && this.__metadata) || function (k, v) {
42
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
43
- };
44
- var __importDefault = (this && this.__importDefault) || function (mod) {
45
- return (mod && mod.__esModule) ? mod : { "default": mod };
46
- };
47
- Object.defineProperty(exports, "__esModule", { value: true });
48
- exports.FileStorage = void 0;
49
- const fs_1 = __importStar(require("fs"));
50
- const path_1 = __importDefault(require("path"));
51
- const promises_1 = require("stream/promises");
52
- const decorators_1 = require("./decorators");
53
- const system_exception_1 = require("./exceptions/system-exception");
54
- const http_exceptions_1 = require("./exceptions/http-exceptions");
55
- let FileStorage = class FileStorage {
56
- constructor() {
57
- this.transformOptions = null;
58
- this.maxFileSize = 50 * 1024 * 1024; // 50MB default
59
- this.baseDir = path_1.default.join(process.cwd(), "public");
60
- this.ensureDirectoryExists(this.baseDir);
61
- }
62
- /**
63
- * Set transformation options for the next save operation
64
- */
65
- transform(options) {
66
- this.transformOptions = options;
67
- return this;
68
- }
69
- async getUploadFile(fliePath) {
70
- const f = await fs_1.default.promises.readFile(path_1.default.join(this.baseDir, fliePath));
71
- return f;
72
- }
73
- async download(filepath) {
74
- const filename = filepath
75
- .toString()
76
- .split(/[\/\\]/)
77
- .pop() || "file";
78
- const s = (0, fs_1.createReadStream)(filepath);
79
- return {
80
- download: true,
81
- stream: s,
82
- filename,
83
- };
84
- }
85
- async downloadAs(filepath, filename) {
86
- const s = (0, fs_1.createReadStream)(filepath);
87
- return {
88
- download: true,
89
- stream: s,
90
- filename,
91
- };
92
- }
93
- /**
94
- * Save a single file with optional transformations
95
- */
96
- async save(f, options) {
97
- var _a;
98
- const opts = {
99
- overwrite: (_a = options === null || options === void 0 ? void 0 : options.overwrite) !== null && _a !== void 0 ? _a : true,
100
- to: options === null || options === void 0 ? void 0 : options.to,
101
- saveAs: options === null || options === void 0 ? void 0 : options.saveAs,
102
- };
103
- if (f.type !== "file") {
104
- throw new system_exception_1.SystemUseError("Invalid file type");
105
- }
106
- try {
107
- const filename = opts.saveAs || f.filename;
108
- this.validateFilename(filename);
109
- const uploadDir = opts.to
110
- ? path_1.default.join(this.baseDir, opts.to)
111
- : this.baseDir;
112
- const fullPath = path_1.default.join(uploadDir, filename);
113
- if (!fullPath.startsWith(this.baseDir)) {
114
- throw new system_exception_1.SystemUseError("Invalid file path");
115
- }
116
- // Check if file exists
117
- if (!opts.overwrite && this.isFileExists(fullPath)) {
118
- throw new system_exception_1.SystemUseError("File already exists");
119
- }
120
- await this.ensureDirectoryExists(uploadDir);
121
- let sourceStream;
122
- const savedFile = f;
123
- if (savedFile.filepath && !f.file) {
124
- sourceStream = fs_1.default.createReadStream(savedFile.filepath);
125
- }
126
- else if (f.file) {
127
- sourceStream = f.file;
128
- }
129
- else {
130
- throw new system_exception_1.SystemUseError("No file stream or filepath available");
131
- }
132
- if (this.transformOptions && this.isImageFile(filename)) {
133
- await this.processImage(sourceStream, fullPath);
134
- }
135
- else {
136
- await (0, promises_1.pipeline)(sourceStream, fs_1.default.createWriteStream(fullPath));
137
- }
138
- if (savedFile.filepath && fs_1.default.existsSync(savedFile.filepath)) {
139
- this.removeFileSync(savedFile.filepath);
140
- }
141
- if (opts.saveAs) {
142
- f.filename = opts.saveAs;
143
- }
144
- return {
145
- uploadPath: (options === null || options === void 0 ? void 0 : options.to) ? '/uploads/' + options.to + "/" + f.filename : '/uploads/' + f.filename,
146
- staticPath: (options === null || options === void 0 ? void 0 : options.to) ? '/static/' + options.to + "/" + f.filename : '/static/' + f.filename
147
- };
148
- }
149
- catch (err) {
150
- if (err instanceof system_exception_1.SystemUseError ||
151
- err instanceof http_exceptions_1.InternalErrorException) {
152
- throw err;
153
- }
154
- console.error("File save error:", err);
155
- throw new system_exception_1.SystemUseError("Failed to upload file");
156
- }
157
- }
158
- /**
159
- * Save multiple files
160
- */
161
- async saveAll(files, options) {
162
- var _a;
163
- if (!files || files.length === 0) {
164
- return [];
165
- }
166
- const opts = {
167
- overwrite: (_a = options === null || options === void 0 ? void 0 : options.overwrite) !== null && _a !== void 0 ? _a : true,
168
- to: options === null || options === void 0 ? void 0 : options.to,
169
- };
170
- const uploadDir = opts.to ? path_1.default.join(this.baseDir, opts.to) : this.baseDir;
171
- await this.ensureDirectoryExists(uploadDir);
172
- const results = [];
173
- for (const f of files) {
174
- try {
175
- this.validateFilename(f.filename);
176
- const fullPath = path_1.default.join(uploadDir, f.filename);
177
- if (!fullPath.startsWith(this.baseDir)) {
178
- throw new system_exception_1.SystemUseError(`Invalid file path for ${f.filename}`);
179
- }
180
- if (!opts.overwrite && this.isFileExists(fullPath)) {
181
- throw new system_exception_1.SystemUseError(`File ${f.filename} already exists`);
182
- }
183
- if (f.file) {
184
- if (this.transformOptions && this.isImageFile(f.filename)) {
185
- await this.processImage(f.file, fullPath);
186
- }
187
- else {
188
- await (0, promises_1.pipeline)(f.file, fs_1.default.createWriteStream(fullPath));
189
- }
190
- }
191
- else {
192
- const fp = f;
193
- if (!fp.filepath) {
194
- throw new system_exception_1.SystemUseError(`No filepath for ${f.filename}`);
195
- }
196
- if (this.transformOptions && this.isImageFile(f.filename)) {
197
- await this.processImage(fs_1.default.createReadStream(fp.filepath), fullPath);
198
- }
199
- else {
200
- await (0, promises_1.pipeline)(fs_1.default.createReadStream(fp.filepath), fs_1.default.createWriteStream(fullPath));
201
- }
202
- this.removeFileSync(fp.filepath);
203
- }
204
- results.push({
205
- uploadPath: (options === null || options === void 0 ? void 0 : options.to) ? '/uploads/' + options.to + "/" + f.filename : '/uploads/' + f.filename,
206
- staticPath: (options === null || options === void 0 ? void 0 : options.to) ? '/static/' + options.to + "/" + f.filename : '/static/' + f.filename
207
- });
208
- }
209
- catch (error) {
210
- console.error(`Failed to save file ${f.filename}:`, error);
211
- throw new system_exception_1.SystemUseError(`Failed to upload file ${f.filename}`);
212
- }
213
- }
214
- return results;
215
- }
216
- /**
217
- * Remove a file from storage
218
- */
219
- async remove(filepath) {
220
- const fullPath = path_1.default.join(this.baseDir, filepath);
221
- // Security check
222
- if (!fullPath.startsWith(this.baseDir)) {
223
- throw new system_exception_1.SystemUseError("Invalid file path");
224
- }
225
- if (!this.isFileExists(fullPath)) {
226
- throw new system_exception_1.SystemUseError("File doesn't exist");
227
- }
228
- try {
229
- fs_1.default.unlinkSync(fullPath);
230
- }
231
- catch (error) {
232
- console.error("File removal error:", error);
233
- throw new system_exception_1.SystemUseError("Failed to remove file");
234
- }
235
- }
236
- /**
237
- * Process image with transformations using sharp
238
- */
239
- async processImage(fileStream, outputPath) {
240
- var _a, _b;
241
- try {
242
- const sharp = await Promise.resolve().then(() => __importStar(require("sharp")));
243
- let sharpPipeline = sharp.default();
244
- if ((_a = this.transformOptions) === null || _a === void 0 ? void 0 : _a.resize) {
245
- sharpPipeline = sharpPipeline.resize(this.transformOptions.resize.width, this.transformOptions.resize.height, { fit: "inside", withoutEnlargement: true });
246
- }
247
- if ((_b = this.transformOptions) === null || _b === void 0 ? void 0 : _b.format) {
248
- const quality = this.transformOptions.quality || 80;
249
- switch (this.transformOptions.format) {
250
- case "jpeg":
251
- sharpPipeline = sharpPipeline.jpeg({ quality });
252
- break;
253
- case "png":
254
- sharpPipeline = sharpPipeline.png({ quality });
255
- break;
256
- case "webp":
257
- sharpPipeline = sharpPipeline.webp({ quality });
258
- break;
259
- case "avif":
260
- sharpPipeline = sharpPipeline.avif({ quality });
261
- break;
262
- }
263
- }
264
- await (0, promises_1.pipeline)(fileStream, sharpPipeline, fs_1.default.createWriteStream(outputPath));
265
- }
266
- catch (error) {
267
- if (error.code === "MODULE_NOT_FOUND" &&
268
- error.message.includes("sharp")) {
269
- throw new http_exceptions_1.InternalErrorException("sharp module not found. Please install sharp to use image transformations.");
270
- }
271
- console.error("Image processing failed:", error);
272
- throw new http_exceptions_1.InternalErrorException("Image processing failed");
273
- }
274
- finally {
275
- this.transformOptions = null;
276
- }
277
- }
278
- /**
279
- * Helper methods
280
- */
281
- isFileExists(fpath) {
282
- return fs_1.default.existsSync(fpath);
283
- }
284
- async ensureDirectoryExists(dirPath) {
285
- if (!fs_1.default.existsSync(dirPath)) {
286
- fs_1.default.mkdirSync(dirPath, { recursive: true });
287
- }
288
- }
289
- removeFileSync(filepath) {
290
- try {
291
- if (fs_1.default.existsSync(filepath)) {
292
- fs_1.default.unlinkSync(filepath);
293
- }
294
- }
295
- catch (error) {
296
- console.error("Failed to remove temp file:", error);
297
- }
298
- }
299
- isImageFile(filename) {
300
- const ext = path_1.default.extname(filename).toLowerCase();
301
- return [".jpg", ".jpeg", ".png", ".webp", ".avif", ".gif", ".bmp"].includes(ext);
302
- }
303
- validateFilename(filename) {
304
- if (!filename || filename.trim() === "") {
305
- throw new system_exception_1.SystemUseError("Invalid filename");
306
- }
307
- // Check for path traversal attempts
308
- if (filename.includes("..") ||
309
- filename.includes("/") ||
310
- filename.includes("\\")) {
311
- throw new system_exception_1.SystemUseError("Invalid filename: path traversal detected");
312
- }
313
- // Check for null bytes
314
- if (filename.includes("\0")) {
315
- throw new system_exception_1.SystemUseError("Invalid filename: null byte detected");
316
- }
317
- }
318
- };
319
- exports.FileStorage = FileStorage;
320
- exports.FileStorage = FileStorage = __decorate([
321
- decorators_1.AppService,
322
- __metadata("design:paramtypes", [])
323
- ], FileStorage);
@@ -1 +0,0 @@
1
- export {};
@@ -1,117 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const fs_1 = __importDefault(require("fs"));
7
- const stream_1 = require("stream");
8
- const file_storage_1 = require("./file-storage");
9
- const system_exception_1 = require("./exceptions/system-exception");
10
- const promises_1 = require("stream/promises");
11
- jest.mock("fs");
12
- jest.mock("stream/promises", () => ({
13
- pipeline: jest.fn((...args) => Promise.resolve()),
14
- }));
15
- const mockFs = fs_1.default;
16
- describe("FileStorage", () => {
17
- let fileStorage;
18
- const testFile = {
19
- type: "file",
20
- filename: "test.txt",
21
- file: new stream_1.Readable({ read() { } }),
22
- };
23
- beforeEach(() => {
24
- jest.clearAllMocks();
25
- fileStorage = new file_storage_1.FileStorage();
26
- mockFs.existsSync.mockReturnValue(false);
27
- mockFs.createWriteStream.mockReturnValue({});
28
- mockFs.createReadStream.mockReturnValue({});
29
- mockFs.unlinkSync.mockImplementation(() => { });
30
- mockFs.mkdirSync.mockImplementation(() => undefined);
31
- });
32
- describe("save", () => {
33
- it("should save a file successfully", async () => {
34
- await expect(fileStorage.save(testFile)).resolves.toEqual({
35
- uploadPath: "/uploads/test.txt",
36
- staticPath: "/static/test.txt",
37
- });
38
- });
39
- it("should throw SystemUseError if file exists and overwrite is false", async () => {
40
- mockFs.existsSync.mockReturnValue(true);
41
- await expect(fileStorage.save(testFile, { overwrite: false })).rejects.toThrow(system_exception_1.SystemUseError);
42
- });
43
- it("should throw SystemUseError on pipeline error", async () => {
44
- promises_1.pipeline.mockImplementationOnce(() => {
45
- throw new Error("Pipeline failed");
46
- });
47
- await expect(fileStorage.save(testFile)).rejects.toThrow(system_exception_1.SystemUseError);
48
- });
49
- });
50
- describe("remove", () => {
51
- it("should remove a file successfully", async () => {
52
- mockFs.existsSync.mockReturnValue(true);
53
- await expect(fileStorage.remove("test.txt")).resolves.toBeUndefined();
54
- expect(mockFs.unlinkSync).toHaveBeenCalled();
55
- });
56
- it("should throw SystemUseError if file does not exist", async () => {
57
- mockFs.existsSync.mockReturnValue(false);
58
- await expect(fileStorage.remove("test.txt")).rejects.toThrow(system_exception_1.SystemUseError);
59
- });
60
- });
61
- describe("saveAll", () => {
62
- it("should save multiple files successfully", async () => {
63
- const files = [
64
- { ...testFile, filename: "a.txt" },
65
- { ...testFile, filename: "b.txt" },
66
- ];
67
- await expect(fileStorage.saveAll(files)).resolves.toEqual([
68
- {
69
- uploadPath: "/uploads/a.txt",
70
- staticPath: "/static/a.txt",
71
- },
72
- {
73
- uploadPath: "/uploads/b.txt",
74
- staticPath: "/static/b.txt",
75
- },
76
- ]);
77
- });
78
- it("should throw SystemUseError on error", async () => {
79
- promises_1.pipeline.mockImplementationOnce(() => {
80
- throw new Error("Pipeline failed");
81
- });
82
- await expect(fileStorage.saveAll([testFile])).rejects.toThrow(system_exception_1.SystemUseError);
83
- });
84
- });
85
- describe("transform", () => {
86
- it("should set transform options and return itself", () => {
87
- const options = { resize: { width: 100, height: 100 }, format: "jpeg" };
88
- const result = fileStorage.transform(options);
89
- expect(result).toBe(fileStorage);
90
- // @ts-ignore
91
- expect(fileStorage.transformOptions).toEqual(options);
92
- });
93
- });
94
- // describe("processImage", () => {
95
- // it("should throw InternalErrorException if sharp is not installed", async () => {
96
- // jest.resetModules();
97
- // const fileStorage = new (require("./file-storage").FileStorage)();
98
- // fileStorage.transform({ format: "jpeg" });
99
- // await expect(
100
- // fileStorage["processImage"](new Readable({ read() {} }), "output.jpg"),
101
- // ).rejects.toThrow(InternalErrorException);
102
- // });
103
- // });
104
- describe("ensureDirectoryExists", () => {
105
- it("should create directory if not exists", async () => {
106
- mockFs.existsSync.mockReturnValue(false);
107
- await fileStorage["ensureDirectoryExists"]("public/test.txt");
108
- expect(mockFs.mkdirSync).toHaveBeenCalled();
109
- });
110
- it("should not create directory if exists", async () => {
111
- mockFs.mkdirSync.mockClear();
112
- mockFs.existsSync.mockReturnValue(true);
113
- await fileStorage["ensureDirectoryExists"]("public/test.txt");
114
- expect(mockFs.mkdirSync).not.toHaveBeenCalled();
115
- });
116
- });
117
- });
package/dist/helpers.d.ts DELETED
@@ -1,11 +0,0 @@
1
- /**
2
- * @copyright 2024
3
- * @author Tareq Hossain
4
- * @email xtrinsic96@gmail.com
5
- * @url https://github.com/xtareq
6
- */
7
- export * from "./utils/common-utils";
8
- export * from "./utils/object-utils";
9
- export * from "./utils/validation-utils";
10
- export * from "./utils/di-utils";
11
- export * from "./validation";