@avleon/core 0.0.19 → 0.0.24

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 (72) hide show
  1. package/README.md +559 -2
  2. package/dist/application.d.ts +26 -0
  3. package/dist/application.js +50 -0
  4. package/dist/collection.js +3 -2
  5. package/dist/container.d.ts +1 -0
  6. package/dist/container.js +2 -1
  7. package/dist/environment-variables.js +1 -1
  8. package/dist/file-storage.js +0 -128
  9. package/dist/helpers.d.ts +2 -0
  10. package/dist/helpers.js +41 -4
  11. package/dist/icore.d.ts +68 -26
  12. package/dist/icore.js +235 -212
  13. package/dist/index.d.ts +2 -2
  14. package/dist/index.js +4 -2
  15. package/dist/middleware.js +0 -8
  16. package/dist/multipart.js +4 -1
  17. package/dist/openapi.d.ts +37 -37
  18. package/dist/params.js +2 -2
  19. package/dist/response.js +6 -2
  20. package/dist/route-methods.js +1 -1
  21. package/dist/swagger-schema.js +4 -1
  22. package/dist/testing.js +5 -2
  23. package/dist/utils/index.d.ts +2 -0
  24. package/dist/utils/index.js +18 -0
  25. package/dist/utils/optional-require.d.ts +8 -0
  26. package/dist/utils/optional-require.js +70 -0
  27. package/dist/validation.d.ts +4 -1
  28. package/dist/validation.js +10 -5
  29. package/package.json +19 -11
  30. package/src/application.ts +96 -0
  31. package/src/authentication.ts +16 -0
  32. package/src/collection.ts +254 -0
  33. package/src/config.ts +39 -0
  34. package/src/constants.ts +1 -0
  35. package/src/container.ts +54 -0
  36. package/src/controller.ts +128 -0
  37. package/src/decorators.ts +27 -0
  38. package/src/environment-variables.ts +46 -0
  39. package/src/exceptions/http-exceptions.ts +86 -0
  40. package/src/exceptions/index.ts +1 -0
  41. package/src/exceptions/system-exception.ts +34 -0
  42. package/src/file-storage.ts +206 -0
  43. package/src/helpers.ts +328 -0
  44. package/src/icore.ts +1064 -0
  45. package/src/index.ts +30 -0
  46. package/src/logger.ts +72 -0
  47. package/src/map-types.ts +159 -0
  48. package/src/middleware.ts +98 -0
  49. package/src/multipart.ts +116 -0
  50. package/src/openapi.ts +372 -0
  51. package/src/params.ts +111 -0
  52. package/src/queue.ts +126 -0
  53. package/src/response.ts +117 -0
  54. package/src/results.ts +30 -0
  55. package/src/route-methods.ts +186 -0
  56. package/src/swagger-schema.ts +213 -0
  57. package/src/testing.ts +220 -0
  58. package/src/types/app-builder.interface.ts +19 -0
  59. package/src/types/application.interface.ts +9 -0
  60. package/src/utils/hash.ts +5 -0
  61. package/src/utils/index.ts +2 -0
  62. package/src/utils/optional-require.ts +50 -0
  63. package/src/validation.ts +156 -0
  64. package/src/validator-extend.ts +25 -0
  65. package/dist/classToOpenapi.d.ts +0 -0
  66. package/dist/classToOpenapi.js +0 -1
  67. package/dist/render.d.ts +0 -1
  68. package/dist/render.js +0 -8
  69. package/jest.config.ts +0 -9
  70. package/tsconfig.json +0 -25
  71. /package/dist/{security.d.ts → utils/hash.d.ts} +0 -0
  72. /package/dist/{security.js → utils/hash.js} +0 -0
@@ -112,134 +112,6 @@ let FileStorage = class FileStorage {
112
112
  throw new system_exception_1.SystemUseError("Can't upload file");
113
113
  }
114
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.");
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
- }
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
- */
243
115
  async processImage(fileStream, outputPath) {
244
116
  var _a, _b;
245
117
  try {
package/dist/helpers.d.ts CHANGED
@@ -29,4 +29,6 @@ type ValidationError = {
29
29
  errors: any;
30
30
  };
31
31
  export declare function validateRequestBody(target: Constructor, value: object, options?: "object" | "array"): ValidationError;
32
+ export declare function pick<T extends object>(obj: T, paths: string[]): Partial<T>;
33
+ export declare function exclude<T extends object>(obj: T | T[], paths: string[]): Partial<T> | Partial<T>[];
32
34
  export {};
package/dist/helpers.js CHANGED
@@ -19,6 +19,8 @@ exports.jsonToInstance = jsonToInstance;
19
19
  exports.transformObjectByInstanceToObject = transformObjectByInstanceToObject;
20
20
  exports.validateObjectByInstance = validateObjectByInstance;
21
21
  exports.validateRequestBody = validateRequestBody;
22
+ exports.pick = pick;
23
+ exports.exclude = exclude;
22
24
  /**
23
25
  * @copyright 2024
24
26
  * @author Tareq Hossain
@@ -42,19 +44,15 @@ function inject(cls) {
42
44
  }
43
45
  }
44
46
  function isConstructor(func) {
45
- // Check if the func is a function
46
47
  if (typeof func !== "function") {
47
48
  return false;
48
49
  }
49
- // Check if it's an arrow function or a built-in JavaScript function
50
50
  if (func === Function.prototype.bind || func instanceof RegExp) {
51
51
  return false;
52
52
  }
53
- // Check if it has a `prototype` property
54
53
  if (func.prototype && typeof func.prototype === "object") {
55
54
  return true;
56
55
  }
57
- // If it's not a constructor, check if it can be called with the new keyword
58
56
  try {
59
57
  const instance = new func();
60
58
  return typeof instance === "object";
@@ -253,3 +251,42 @@ function validateRequestBody(target, value, options = "array") {
253
251
  : error.map((x) => ({ path: x.property, constraints: x.constraints }));
254
252
  return { count: error.length, errors };
255
253
  }
254
+ function pick(obj, paths) {
255
+ const result = {};
256
+ for (const path of paths) {
257
+ const keys = path.split(".");
258
+ let source = obj;
259
+ let target = result;
260
+ for (let i = 0; i < keys.length; i++) {
261
+ const key = keys[i];
262
+ if (!(key in source))
263
+ break;
264
+ if (i === keys.length - 1) {
265
+ target[key] = source[key];
266
+ }
267
+ else {
268
+ source = source[key];
269
+ target[key] = target[key] || {};
270
+ target = target[key];
271
+ }
272
+ }
273
+ }
274
+ return result;
275
+ }
276
+ function exclude(obj, paths) {
277
+ if (Array.isArray(obj)) {
278
+ return obj.map((item) => exclude(item, paths));
279
+ }
280
+ const clone = structuredClone(obj); // Or use lodash.cloneDeep
281
+ for (const path of paths) {
282
+ const keys = path.split(".");
283
+ let target = clone;
284
+ for (let i = 0; i < keys.length - 1; i++) {
285
+ if (!(keys[i] in target))
286
+ break;
287
+ target = target[keys[i]];
288
+ }
289
+ target === null || target === void 0 ? true : delete target[keys[keys.length - 1]];
290
+ }
291
+ return clone;
292
+ }
package/dist/icore.d.ts CHANGED
@@ -87,6 +87,7 @@ export interface AvleonTestAppliction {
87
87
  export interface IAvleonApplication {
88
88
  isDevelopment(): boolean;
89
89
  useCors(corsOptions?: FastifyCorsOptions): void;
90
+ useDataSource<T extends IConfig<R>, R = ReturnType<InstanceType<Constructable<T>>["config"]>>(ConfigClass: Constructable<T>, modifyConfig?: (config: R) => R): void;
90
91
  useOpenApi<T extends IConfig<R>, R = ReturnType<InstanceType<Constructable<T>>["config"]>>(ConfigClass: Constructable<T>, modifyConfig?: (config: R) => R): void;
91
92
  useSwagger(options: OpenApiUiOptions): Promise<void>;
92
93
  useMultipart(options: MultipartOptions): void;
@@ -102,7 +103,7 @@ export interface IAvleonApplication {
102
103
  run(port?: number): Promise<void>;
103
104
  getTestApp(): TestApplication;
104
105
  }
105
- export declare class AvleonApplication implements IAvleonApplication {
106
+ export declare class AvleonApplication {
106
107
  private static instance;
107
108
  private static buildOptions;
108
109
  private app;
@@ -118,21 +119,75 @@ export declare class AvleonApplication implements IAvleonApplication {
118
119
  private authorizeMiddleware?;
119
120
  private appConfig;
120
121
  private dataSource?;
122
+ private isMapFeatures;
121
123
  private metaCache;
122
124
  private multipartOptions;
123
125
  private constructor();
124
126
  private isTest;
127
+ static getApp(): AvleonApplication;
125
128
  static getInternalApp(buildOptions: any): AvleonApplication;
126
129
  isDevelopment(): boolean;
127
130
  private initSwagger;
128
131
  useCors(corsOptions?: FastifyCorsOptions): void;
129
132
  useOpenApi<T extends IConfig<R>, R = ReturnType<InstanceType<Constructable<T>>["config"]>>(ConfigClass: Constructable<T>, modifyConfig?: (config: R) => R): void;
130
133
  /**
131
- * @deprecated
132
- * Will remove in next major version
134
+ * Registers the fastify-multipart plugin with the Fastify instance.
135
+ * This enables handling of multipart/form-data requests, typically used for file uploads.
136
+ *
137
+ * @param {MultipartOptions} options - Options to configure the fastify-multipart plugin.
138
+ * @param {FastifyInstance} this.app - The Fastify instance to register the plugin with.
139
+ * @property {MultipartOptions} this.multipartOptions - Stores the provided multipart options.
140
+ * @see {@link https://github.com/fastify/fastify-multipart} for more details on available options.
133
141
  */
134
- useSwagger(options: OpenApiUiOptions): Promise<void>;
135
142
  useMultipart(options: MultipartOptions): void;
143
+ /**
144
+ * Configures and initializes a TypeORM DataSource based on the provided configuration class.
145
+ * It retrieves the configuration from the application's configuration service and allows for optional modification.
146
+ * The initialized DataSource is then stored and registered within a dependency injection container.
147
+ *
148
+ * @template T - A generic type extending the `IConfig` interface, representing the configuration class.
149
+ * @template R - A generic type representing the return type of the configuration method of the `ConfigClass`.
150
+ * @param {Constructable<T>} ConfigClass - The constructor of the configuration class to be used for creating the DataSource.
151
+ * @param {(config: R) => R} [modifyConfig] - An optional function that takes the initial configuration and returns a modified configuration.
152
+ * @returns {void}
153
+ * @property {DataSourceOptions} this.dataSourceOptions - Stores the final DataSource options after potential modification.
154
+ * @property {DataSource} this.dataSource - Stores the initialized TypeORM DataSource instance.
155
+ * @see {@link https://typeorm.io/} for more information about TypeORM.
156
+ */
157
+ useDataSource<T extends IConfig<R>, R = ReturnType<InstanceType<Constructable<T>>["config"]>>(ConfigClass: Constructable<T>, modifyConfig?: (config: R) => R): void;
158
+ /**
159
+ * Registers an array of middleware classes to be executed before request handlers.
160
+ * It retrieves instances of the middleware classes from the dependency injection container
161
+ * and adds them as 'preHandler' hooks to the Fastify application.
162
+ *
163
+ * @template T - A generic type extending the `AppMiddleware` interface, representing the middleware class.
164
+ * @param {Constructor<T>[]} mclasses - An array of middleware class constructors to be registered.
165
+ * @returns {void}
166
+ * @property {Map<string, T>} this.middlewares - Stores the registered middleware instances, keyed by their class names.
167
+ * @see {@link https://www.fastify.io/docs/latest/Reference/Hooks/#prehandler} for more information about Fastify preHandler hooks.
168
+ */
169
+ useMiddlewares<T extends AppMiddleware>(mclasses: Constructor<T>[]): void;
170
+ /**
171
+ * Registers a middleware constructor to be used for authorization purposes.
172
+ * The specific implementation and usage of this middleware will depend on the application's authorization logic.
173
+ *
174
+ * @template T - A generic type representing the constructor of the authorization middleware.
175
+ * @param {Constructor<T>} middleware - The constructor of the middleware to be used for authorization.
176
+ * @returns {void}
177
+ * @property {any} this.authorizeMiddleware - Stores the constructor of the authorization middleware.
178
+ */
179
+ useAuthoriztion<T extends any>(middleware: Constructor<T>): void;
180
+ /**
181
+ * Registers the `@fastify/static` plugin to serve static files.
182
+ * It configures the root directory and URL prefix for serving static assets.
183
+ *
184
+ * @param {StaticFileOptions} [options={ path: undefined, prefix: undefined }] - Optional configuration for serving static files.
185
+ * @param {string} [options.path] - The absolute path to the static files directory. Defaults to 'process.cwd()/public'.
186
+ * @param {string} [options.prefix] - The URL prefix for serving static files. Defaults to '/static/'.
187
+ * @returns {void}
188
+ * @see {@link https://github.com/fastify/fastify-static} for more details on available options.
189
+ */
190
+ useStaticFiles(options?: StaticFileOptions): void;
136
191
  private handleMiddlewares;
137
192
  private executeMiddlewares;
138
193
  /**
@@ -157,34 +212,33 @@ export declare class AvleonApplication implements IAvleonApplication {
157
212
  private _processMeta;
158
213
  autoControllers(): Promise<void>;
159
214
  mapControllers(controllers: Function[]): void;
215
+ mapFeature(): void;
160
216
  private _mapControllers;
161
217
  mapControllersAuto(): void;
162
218
  handleRoute(args: any): Promise<void>;
163
219
  private mapFn;
164
- useMiddlewares<T extends AppMiddleware>(mclasses: Constructor<T>[]): void;
165
- useAuthoriztion<T extends any>(middleware: Constructor<T>): void;
166
220
  private _handleError;
167
221
  mapRoute<T extends (...args: any[]) => any>(method: "get" | "post" | "put" | "delete", path: string | undefined, fn: T): Promise<void>;
168
222
  private _routeHandler;
169
223
  mapGet<T extends (...args: any[]) => any>(path: string | undefined, fn: T): {
170
224
  useMiddleware: <M extends AppMiddleware>(middlewares: Constructor<AppMiddleware>[]) => /*elided*/ any;
171
- useSwagger: (options: OpenApiOptions) => /*elided*/ any;
225
+ useOpenApi: (options: OpenApiOptions) => /*elided*/ any;
172
226
  };
173
227
  mapPost<T extends (...args: any[]) => any>(path: string | undefined, fn: T): {
174
228
  useMiddleware: <M extends AppMiddleware>(middlewares: Constructor<AppMiddleware>[]) => /*elided*/ any;
175
- useSwagger: (options: OpenApiOptions) => /*elided*/ any;
229
+ useOpenApi: (options: OpenApiOptions) => /*elided*/ any;
176
230
  };
177
231
  mapPut<T extends (...args: any[]) => any>(path: string | undefined, fn: T): {
178
232
  useMiddleware: <M extends AppMiddleware>(middlewares: Constructor<AppMiddleware>[]) => /*elided*/ any;
179
- useSwagger: (options: OpenApiOptions) => /*elided*/ any;
233
+ useOpenApi: (options: OpenApiOptions) => /*elided*/ any;
180
234
  };
181
235
  mapDelete<T extends (...args: any[]) => any>(path: string | undefined, fn: T): {
182
236
  useMiddleware: <M extends AppMiddleware>(middlewares: Constructor<AppMiddleware>[]) => /*elided*/ any;
183
- useSwagger: (options: OpenApiOptions) => /*elided*/ any;
237
+ useOpenApi: (options: OpenApiOptions) => /*elided*/ any;
184
238
  };
185
- useStaticFiles(options?: StaticFileOptions): void;
239
+ private _mapFeatures;
186
240
  initializeDatabase(): Promise<void>;
187
- run(port?: number): Promise<void>;
241
+ run(port?: number, fn?: CallableFunction): Promise<void>;
188
242
  getTestApp(buildOptions?: any): TestApplication;
189
243
  }
190
244
  export type Application = typeof AvleonApplication;
@@ -210,19 +264,7 @@ export declare class TestBuilder {
210
264
  build(app: IAvleonApplication): TestApplication;
211
265
  fromApplication(app: IAvleonApplication): TestApplication;
212
266
  }
213
- export declare class Builder implements IAppBuilder {
214
- private static instance;
215
- private alreadyBuilt;
216
- private database;
217
- private dataSource?;
218
- private multipartOptions;
219
- private dataSourceOptions?;
220
- private testBuilder;
221
- private appConfig;
222
- private constructor();
223
- static createAppBuilder(): Builder;
224
- registerPlugin<T extends Function, S extends {}>(plugin: T, options: S): Promise<void>;
225
- addDataSource<T extends IConfig<R>, R = ReturnType<InstanceType<Constructable<T>>["config"]>>(ConfigClass: Constructable<T>, modifyConfig?: (config: R) => R): void;
226
- build<T extends IAvleonApplication>(): T;
267
+ export declare class Builder {
268
+ static createApplication(): AvleonApplication;
227
269
  }
228
270
  export {};