electron-injector 1.0.3 → 1.1.0

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/README.md CHANGED
@@ -27,7 +27,7 @@ Nace de la necesidad de crear aplicaciones de escritorio multiplataforma donde n
27
27
 
28
28
  ## 📦 Instalación
29
29
  ```bash
30
- npm install electron-injector rxjs
30
+ npm install electron-injector rxjs class-validator class-transformer
31
31
  ```
32
32
 
33
33
  > **Nota:**
@@ -48,34 +48,39 @@ import { Application } from 'electron-injector';
48
48
  import { UserController } from './controllers/user.controller';
49
49
  import { AuthGuard } from './guards/auth.guard';
50
50
  import { UserService } from './services/user.service';
51
+ import { DtoFilter } from './filters/dto.filter';
51
52
 
52
- async function bootstrap() {
53
- const electronApp = new Application({
54
- providers: [
55
- UserService,
56
- AuthGuard,
57
- ],
58
- controllers: [
59
- UserController,
60
- ],
61
- });
62
-
63
- await app.whenReady();
64
-
53
+ function createWindow() {
65
54
  const mainWindow = new BrowserWindow({
66
- width: 800,
67
- height: 600,
55
+ width: 900,
56
+ height: 670,
57
+ autoHideMenuBar: true,
58
+ ...(process.platform === 'linux' ? { icon } : {}),
68
59
  webPreferences: {
69
- nodeIntegration: false,
70
- contextIsolation: true,
71
- preload: path.join(__dirname, 'preload.js'),
72
- },
73
- });
74
-
75
- mainWindow.loadFile('index.html');
60
+ preload: join(__dirname, '../preload/index.js'),
61
+ sandbox: false
62
+ }
63
+ })
64
+
65
+ if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
66
+ mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL'])
67
+ } else {
68
+ mainWindow.loadFile(join(__dirname, '../renderer/index.html'))
69
+ }
76
70
  }
77
71
 
78
- bootstrap().catch(console.error);
72
+ app.whenReady().then(() {
73
+ const application = Application.create({
74
+ providers: [UserService, AuthGuard],
75
+ controllers: [UserController]
76
+ })
77
+
78
+ application.useGlobalFilters(DtoFilter)
79
+
80
+ application.bootstrap()
81
+
82
+ createWindow()
83
+ })
79
84
  ```
80
85
 
81
86
  ## 2. Creando un servicio
@@ -221,7 +226,7 @@ onMessage(@Payload() data: any) {
221
226
 
222
227
  ` @Payload() `
223
228
 
224
- Inyecta el payload recibido desde el renderer.
229
+ Inyecta el payload recibido desde el renderer. Si defines como tipo una clase decorada con class-validator, esto realiza la validación automática.
225
230
  ```ts
226
231
  @OnInvoke('update')
227
232
  async update(@Payload() data: any) {
package/dist/index.cjs CHANGED
@@ -32,14 +32,23 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
32
32
  var index_exports = {};
33
33
  __export(index_exports, {
34
34
  Application: () => Application,
35
+ Catch: () => Catch,
36
+ CircularDependency: () => CircularDependency,
35
37
  Controller: () => Controller,
38
+ ControllerIsNotValid: () => ControllerIsNotValid,
36
39
  Ctx: () => Ctx,
40
+ DataValidationError: () => DataValidationError,
41
+ ElectronInjectorError: () => ElectronInjectorError,
37
42
  Event: () => Event,
38
43
  ExecutionContext: () => ExecutionContext,
44
+ ForbiddenAccessError: () => ForbiddenAccessError,
39
45
  Injectable: () => Injectable,
46
+ IsNotExceptionFilter: () => IsNotExceptionFilter,
40
47
  OnInvoke: () => OnInvoke,
41
48
  OnSend: () => OnSend,
42
49
  Payload: () => Payload,
50
+ ProviderIsNotInjectable: () => ProviderIsNotInjectable,
51
+ ProviderNotFound: () => ProviderNotFound,
43
52
  Reflector: () => Reflector,
44
53
  SetMetadata: () => SetMetadata,
45
54
  UseGuards: () => UseGuards,
@@ -68,6 +77,14 @@ var ProviderNotFound = class extends ElectronInjectorError {
68
77
  super(`Provider '${providerName}' not found`);
69
78
  }
70
79
  };
80
+ var IsNotExceptionFilter = class extends ElectronInjectorError {
81
+ static {
82
+ __name(this, "IsNotExceptionFilter");
83
+ }
84
+ constructor(filterName) {
85
+ super(`Class ${filterName} is not a filter. Please ensure it is decorated with @Catch(...filters)`);
86
+ }
87
+ };
71
88
  var CircularDependency = class extends ElectronInjectorError {
72
89
  static {
73
90
  __name(this, "CircularDependency");
@@ -92,6 +109,26 @@ var ControllerIsNotValid = class extends ElectronInjectorError {
92
109
  super(`Controller '${controllerName}' is not valid. Please ensure it is decorated with @Controller()`);
93
110
  }
94
111
  };
112
+ var DataValidationError = class {
113
+ static {
114
+ __name(this, "DataValidationError");
115
+ }
116
+ messages;
117
+ constructor(validationError) {
118
+ this.messages = validationError.constraints;
119
+ }
120
+ get Messages() {
121
+ return this.messages;
122
+ }
123
+ };
124
+ var ForbiddenAccessError = class extends ElectronInjectorError {
125
+ static {
126
+ __name(this, "ForbiddenAccessError");
127
+ }
128
+ constructor(path, guardName) {
129
+ super(`Can not access to "${path}" path, by the gaurd "${guardName}"`);
130
+ }
131
+ };
95
132
 
96
133
  // src/keys.ts
97
134
  var CONTROLLER = Symbol("electron-di:controller");
@@ -99,6 +136,7 @@ var INJECTABLE = Symbol("electron-di:injectable");
99
136
  var HANDLER = Symbol("electron-di:handler");
100
137
  var PARAM = Symbol("electron-di:param");
101
138
  var GUARD = Symbol("electron-di:guard");
139
+ var FILTER = Symbol("electron-di:filter");
102
140
 
103
141
  // src/utilities.ts
104
142
  var Reflector = class {
@@ -225,19 +263,33 @@ var DEV_LOGGER = devLogger;
225
263
 
226
264
  // src/application.ts
227
265
  var import_electron = require("electron");
266
+ var import_class_validator = require("class-validator");
267
+ var import_class_transformer = require("class-transformer");
228
268
  var Application = class _Application {
229
269
  static {
230
270
  __name(this, "Application");
231
271
  }
232
272
  configOptions;
273
+ validationOptions;
233
274
  container = new Container();
234
- static create(configOptions) {
235
- return new _Application(configOptions);
275
+ filters = /* @__PURE__ */ new Map();
276
+ static create(configOptions, validationOptions = {}) {
277
+ return new _Application(configOptions, validationOptions);
278
+ }
279
+ useGlobalFilters(...filters) {
280
+ for (const filter of filters) {
281
+ const exceptionsClasses = Reflect.getMetadata(FILTER, filter);
282
+ if (!exceptionsClasses) throw new IsNotExceptionFilter(filter.name);
283
+ exceptionsClasses.forEach((excls) => {
284
+ this.filters.set(excls, filter);
285
+ this.container.addProvider(filter);
286
+ });
287
+ }
236
288
  }
237
- constructor(configOptions) {
289
+ constructor(configOptions, validationOptions) {
238
290
  this.configOptions = configOptions;
291
+ this.validationOptions = validationOptions;
239
292
  this.loadProviders();
240
- this.loadControllers();
241
293
  }
242
294
  loadProviders() {
243
295
  for (const provider of this.configOptions.providers || []) {
@@ -245,7 +297,7 @@ var Application = class _Application {
245
297
  DEV_LOGGER(`Provider ${typeof provider == "object" ? provider.provided.name : provider.name} loaded`);
246
298
  }
247
299
  }
248
- loadControllers() {
300
+ bootstrap() {
249
301
  for (const controller of this.configOptions.controllers || []) {
250
302
  const controllerPrefix = this.getControllerPrefix(controller);
251
303
  const controllerDependencies = this.getControllerDependencies(controller);
@@ -261,11 +313,28 @@ var Application = class _Application {
261
313
  const handlerCallback = /* @__PURE__ */ __name(async (event, data) => {
262
314
  const executionContext = new ExecutionContext(controller, controllerInstance[controllerMethod], data, event);
263
315
  for (const guard of guards) {
264
- const response = await this.guardExecute(guard, executionContext);
265
- if (!response) return false;
316
+ try {
317
+ const response = await this.guardExecute(guard, executionContext);
318
+ if (!response) return {
319
+ success: false,
320
+ error: new ForbiddenAccessError(path, guard.constructor.prototype.name)
321
+ };
322
+ } catch (e) {
323
+ return await this.useFilter(e, executionContext);
324
+ }
325
+ }
326
+ let params = [];
327
+ try {
328
+ params = await this.getParams(controllerInstance, controllerMethod, executionContext);
329
+ } catch (e) {
330
+ return await this.useFilter(e, executionContext);
331
+ }
332
+ let controllerResult = void 0;
333
+ try {
334
+ controllerResult = await this.controllerExecute(controllerInstance, controllerInstance[controllerMethod], params);
335
+ } catch (e) {
336
+ return await this.useFilter(e, executionContext);
266
337
  }
267
- const params = this.getParams(controllerInstance, controllerMethod, executionContext);
268
- const controllerResult = await this.controllerExecute(controllerInstance, controllerInstance[controllerMethod], params);
269
338
  return controllerResult;
270
339
  }, "handlerCallback");
271
340
  if (handlerMetadata.type === "invoke") {
@@ -276,15 +345,24 @@ var Application = class _Application {
276
345
  }
277
346
  }
278
347
  }
279
- getParams(target, propertyKey, executionContext) {
348
+ async getParams(target, propertyKey, executionContext) {
280
349
  const params = Reflect.getMetadata(PARAM, target, propertyKey);
281
350
  if (!params) return [];
282
- return params.map((param) => {
351
+ return await Promise.all(params.map(async (param, index) => {
283
352
  if (param === "ctx") return executionContext;
284
353
  if (param === "event") return executionContext.event;
285
- if (param === "payload") return executionContext.payload;
354
+ if (param === "payload") {
355
+ const validationClass = Reflect.getMetadata("design:paramtypes", target, propertyKey)[index];
356
+ const metadata = (0, import_class_validator.getMetadataStorage)().getTargetValidationMetadatas(validationClass, null, false, false);
357
+ if (typeof validationClass == "function" && metadata.length) {
358
+ const validatorObjectInstance = (0, import_class_transformer.plainToInstance)(validationClass, executionContext.payload);
359
+ const errors = await (0, import_class_validator.validate)(validatorObjectInstance, this.validationOptions);
360
+ if (errors.length) throw new DataValidationError(errors[0]);
361
+ }
362
+ return executionContext.payload;
363
+ }
286
364
  return void 0;
287
- });
365
+ }));
288
366
  }
289
367
  buildPath(controllerPrefix, methodPath) {
290
368
  const prefix = controllerPrefix.trim();
@@ -295,39 +373,48 @@ var Application = class _Application {
295
373
  return "";
296
374
  }
297
375
  async guardExecute(guard, executionContext) {
298
- try {
299
- const guardResult = guard.canActivate(executionContext);
300
- if (guardResult instanceof import_rxjs.Observable) {
301
- const result = await (0, import_rxjs.lastValueFrom)(guardResult.pipe((0, import_rxjs.first)()));
302
- if (!result) return false;
303
- } else if (guardResult instanceof Promise) {
304
- const result = await guardResult;
305
- if (!result) return false;
306
- } else {
307
- if (!guardResult) return false;
308
- }
309
- return true;
310
- } catch (error) {
311
- PROD_LOGGER(error);
312
- return false;
376
+ const guardResult = guard.canActivate(executionContext);
377
+ if (guardResult instanceof import_rxjs.Observable) {
378
+ const result = await (0, import_rxjs.lastValueFrom)(guardResult.pipe((0, import_rxjs.first)()));
379
+ if (!result) return false;
380
+ } else if (guardResult instanceof Promise) {
381
+ const result = await guardResult;
382
+ if (!result) return false;
383
+ } else {
384
+ if (!guardResult) return false;
313
385
  }
386
+ return true;
314
387
  }
315
388
  async controllerExecute(context, target, params) {
316
- try {
317
- const boundedTarget = target.bind(context);
318
- let controllerResult = boundedTarget(...params);
319
- while (controllerResult instanceof import_rxjs.Observable || controllerResult instanceof Promise) {
320
- if (controllerResult instanceof import_rxjs.Observable) {
321
- controllerResult = await (0, import_rxjs.lastValueFrom)(controllerResult);
322
- } else if (controllerResult instanceof Promise) {
323
- controllerResult = await controllerResult;
324
- }
389
+ const boundedTarget = target.bind(context);
390
+ let controllerResult = boundedTarget(...params);
391
+ while (controllerResult instanceof import_rxjs.Observable || controllerResult instanceof Promise) {
392
+ if (controllerResult instanceof import_rxjs.Observable) {
393
+ controllerResult = await (0, import_rxjs.lastValueFrom)(controllerResult);
394
+ } else if (controllerResult instanceof Promise) {
395
+ controllerResult = await controllerResult;
325
396
  }
326
- return controllerResult;
327
- } catch (error) {
328
- PROD_LOGGER(error.message ?? error);
329
- return void 0;
330
397
  }
398
+ return controllerResult;
399
+ }
400
+ async useFilter(error, executionContext) {
401
+ PROD_LOGGER(error);
402
+ for (const [cls, fltr] of this.filters) {
403
+ if (!(error instanceof cls)) continue;
404
+ const filterInstance = this.container.resolve(fltr);
405
+ const response = filterInstance.catch(error, executionContext);
406
+ if (response instanceof Promise) {
407
+ return await response;
408
+ }
409
+ if (response instanceof import_rxjs.Observable) {
410
+ return await (0, import_rxjs.lastValueFrom)(response);
411
+ }
412
+ return response;
413
+ }
414
+ return {
415
+ success: false,
416
+ error
417
+ };
331
418
  }
332
419
  getHandlerMetadata(target) {
333
420
  const handlerMetadata = Reflect.getMetadata(HANDLER, target);
@@ -431,17 +518,37 @@ function SetMetadata(key, value) {
431
518
  };
432
519
  }
433
520
  __name(SetMetadata, "SetMetadata");
521
+ function Catch(...filters) {
522
+ return function(target) {
523
+ const prevFilters = Reflect.getMetadata(FILTER, target) || [];
524
+ Reflect.defineMetadata(INJECTABLE, "singleton", target);
525
+ Reflect.defineMetadata(FILTER, [
526
+ ...prevFilters,
527
+ ...filters
528
+ ], target);
529
+ };
530
+ }
531
+ __name(Catch, "Catch");
434
532
  // Annotate the CommonJS export names for ESM import in node:
435
533
  0 && (module.exports = {
436
534
  Application,
535
+ Catch,
536
+ CircularDependency,
437
537
  Controller,
538
+ ControllerIsNotValid,
438
539
  Ctx,
540
+ DataValidationError,
541
+ ElectronInjectorError,
439
542
  Event,
440
543
  ExecutionContext,
544
+ ForbiddenAccessError,
441
545
  Injectable,
546
+ IsNotExceptionFilter,
442
547
  OnInvoke,
443
548
  OnSend,
444
549
  Payload,
550
+ ProviderIsNotInjectable,
551
+ ProviderNotFound,
445
552
  Reflector,
446
553
  SetMetadata,
447
554
  UseGuards,
package/dist/index.d.cts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { Observable } from 'rxjs';
2
2
  import { IpcMainEvent, IpcMainInvokeEvent } from 'electron';
3
+ import { ValidatorOptions, ValidationError } from 'class-validator';
3
4
 
4
5
  declare class Reflector {
5
6
  get<T = any>(key: any, target: any): T;
@@ -30,6 +31,9 @@ type Provider = Class | {
30
31
  interface CanActivate {
31
32
  canActivate: (context: ExecutionContext) => boolean | Promise<boolean> | Observable<boolean>;
32
33
  }
34
+ interface ExceptionFilter {
35
+ catch: (e: any, context: ExecutionContext) => any;
36
+ }
33
37
  interface ConfigOptions {
34
38
  providers?: Provider[];
35
39
  controllers?: Class[];
@@ -37,15 +41,19 @@ interface ConfigOptions {
37
41
 
38
42
  declare class Application {
39
43
  private configOptions;
44
+ private validationOptions;
40
45
  private container;
41
- static create(configOptions: ConfigOptions): Application;
42
- constructor(configOptions: ConfigOptions);
46
+ private filters;
47
+ static create(configOptions: ConfigOptions, validationOptions?: ValidatorOptions): Application;
48
+ useGlobalFilters(...filters: Class<ExceptionFilter>[]): void;
49
+ constructor(configOptions: ConfigOptions, validationOptions: ValidatorOptions);
43
50
  private loadProviders;
44
- private loadControllers;
51
+ bootstrap(): void;
45
52
  private getParams;
46
53
  private buildPath;
47
54
  private guardExecute;
48
55
  private controllerExecute;
56
+ private useFilter;
49
57
  private getHandlerMetadata;
50
58
  private getGuards;
51
59
  private getControllerPrefix;
@@ -61,5 +69,35 @@ declare function Event(): ParameterDecorator;
61
69
  declare function Ctx(): ParameterDecorator;
62
70
  declare function UseGuards(...guards: Class<CanActivate>[]): (_target: Object, _property?: string | symbol, descriptor?: PropertyDescriptor) => void;
63
71
  declare function SetMetadata(key: any, value: any): (target: Object, propertyKey?: string | symbol, descriptor?: PropertyDescriptor) => void;
72
+ declare function Catch(...filters: Class[]): (target: Object) => void;
73
+
74
+ declare class ElectronInjectorError extends Error {
75
+ constructor(message: string);
76
+ }
77
+ declare class ProviderNotFound extends ElectronInjectorError {
78
+ constructor(providerName: string);
79
+ }
80
+ declare class IsNotExceptionFilter extends ElectronInjectorError {
81
+ constructor(filterName: string);
82
+ }
83
+ declare class CircularDependency extends ElectronInjectorError {
84
+ constructor(providerName: string);
85
+ }
86
+ declare class ProviderIsNotInjectable extends ElectronInjectorError {
87
+ constructor(providerName: string);
88
+ }
89
+ declare class ControllerIsNotValid extends ElectronInjectorError {
90
+ constructor(controllerName: string);
91
+ }
92
+ declare class DataValidationError {
93
+ private messages;
94
+ constructor(validationError: ValidationError);
95
+ get Messages(): {
96
+ [type: string]: string;
97
+ } | undefined;
98
+ }
99
+ declare class ForbiddenAccessError extends ElectronInjectorError {
100
+ constructor(path: string, guardName: string);
101
+ }
64
102
 
65
- export { Application, type CanActivate, type ConfigOptions, Controller, Ctx, Event, ExecutionContext, Injectable, type InjectableType, OnInvoke, OnSend, Payload, Reflector, SetMetadata, UseGuards, applyDecorators };
103
+ export { Application, type CanActivate, Catch, CircularDependency, type ConfigOptions, Controller, ControllerIsNotValid, Ctx, DataValidationError, ElectronInjectorError, Event, type ExceptionFilter, ExecutionContext, ForbiddenAccessError, Injectable, type InjectableType, IsNotExceptionFilter, OnInvoke, OnSend, Payload, ProviderIsNotInjectable, ProviderNotFound, Reflector, SetMetadata, UseGuards, applyDecorators };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { Observable } from 'rxjs';
2
2
  import { IpcMainEvent, IpcMainInvokeEvent } from 'electron';
3
+ import { ValidatorOptions, ValidationError } from 'class-validator';
3
4
 
4
5
  declare class Reflector {
5
6
  get<T = any>(key: any, target: any): T;
@@ -30,6 +31,9 @@ type Provider = Class | {
30
31
  interface CanActivate {
31
32
  canActivate: (context: ExecutionContext) => boolean | Promise<boolean> | Observable<boolean>;
32
33
  }
34
+ interface ExceptionFilter {
35
+ catch: (e: any, context: ExecutionContext) => any;
36
+ }
33
37
  interface ConfigOptions {
34
38
  providers?: Provider[];
35
39
  controllers?: Class[];
@@ -37,15 +41,19 @@ interface ConfigOptions {
37
41
 
38
42
  declare class Application {
39
43
  private configOptions;
44
+ private validationOptions;
40
45
  private container;
41
- static create(configOptions: ConfigOptions): Application;
42
- constructor(configOptions: ConfigOptions);
46
+ private filters;
47
+ static create(configOptions: ConfigOptions, validationOptions?: ValidatorOptions): Application;
48
+ useGlobalFilters(...filters: Class<ExceptionFilter>[]): void;
49
+ constructor(configOptions: ConfigOptions, validationOptions: ValidatorOptions);
43
50
  private loadProviders;
44
- private loadControllers;
51
+ bootstrap(): void;
45
52
  private getParams;
46
53
  private buildPath;
47
54
  private guardExecute;
48
55
  private controllerExecute;
56
+ private useFilter;
49
57
  private getHandlerMetadata;
50
58
  private getGuards;
51
59
  private getControllerPrefix;
@@ -61,5 +69,35 @@ declare function Event(): ParameterDecorator;
61
69
  declare function Ctx(): ParameterDecorator;
62
70
  declare function UseGuards(...guards: Class<CanActivate>[]): (_target: Object, _property?: string | symbol, descriptor?: PropertyDescriptor) => void;
63
71
  declare function SetMetadata(key: any, value: any): (target: Object, propertyKey?: string | symbol, descriptor?: PropertyDescriptor) => void;
72
+ declare function Catch(...filters: Class[]): (target: Object) => void;
73
+
74
+ declare class ElectronInjectorError extends Error {
75
+ constructor(message: string);
76
+ }
77
+ declare class ProviderNotFound extends ElectronInjectorError {
78
+ constructor(providerName: string);
79
+ }
80
+ declare class IsNotExceptionFilter extends ElectronInjectorError {
81
+ constructor(filterName: string);
82
+ }
83
+ declare class CircularDependency extends ElectronInjectorError {
84
+ constructor(providerName: string);
85
+ }
86
+ declare class ProviderIsNotInjectable extends ElectronInjectorError {
87
+ constructor(providerName: string);
88
+ }
89
+ declare class ControllerIsNotValid extends ElectronInjectorError {
90
+ constructor(controllerName: string);
91
+ }
92
+ declare class DataValidationError {
93
+ private messages;
94
+ constructor(validationError: ValidationError);
95
+ get Messages(): {
96
+ [type: string]: string;
97
+ } | undefined;
98
+ }
99
+ declare class ForbiddenAccessError extends ElectronInjectorError {
100
+ constructor(path: string, guardName: string);
101
+ }
64
102
 
65
- export { Application, type CanActivate, type ConfigOptions, Controller, Ctx, Event, ExecutionContext, Injectable, type InjectableType, OnInvoke, OnSend, Payload, Reflector, SetMetadata, UseGuards, applyDecorators };
103
+ export { Application, type CanActivate, Catch, CircularDependency, type ConfigOptions, Controller, ControllerIsNotValid, Ctx, DataValidationError, ElectronInjectorError, Event, type ExceptionFilter, ExecutionContext, ForbiddenAccessError, Injectable, type InjectableType, IsNotExceptionFilter, OnInvoke, OnSend, Payload, ProviderIsNotInjectable, ProviderNotFound, Reflector, SetMetadata, UseGuards, applyDecorators };
package/dist/index.js CHANGED
@@ -24,6 +24,14 @@ var ProviderNotFound = class extends ElectronInjectorError {
24
24
  super(`Provider '${providerName}' not found`);
25
25
  }
26
26
  };
27
+ var IsNotExceptionFilter = class extends ElectronInjectorError {
28
+ static {
29
+ __name(this, "IsNotExceptionFilter");
30
+ }
31
+ constructor(filterName) {
32
+ super(`Class ${filterName} is not a filter. Please ensure it is decorated with @Catch(...filters)`);
33
+ }
34
+ };
27
35
  var CircularDependency = class extends ElectronInjectorError {
28
36
  static {
29
37
  __name(this, "CircularDependency");
@@ -48,6 +56,26 @@ var ControllerIsNotValid = class extends ElectronInjectorError {
48
56
  super(`Controller '${controllerName}' is not valid. Please ensure it is decorated with @Controller()`);
49
57
  }
50
58
  };
59
+ var DataValidationError = class {
60
+ static {
61
+ __name(this, "DataValidationError");
62
+ }
63
+ messages;
64
+ constructor(validationError) {
65
+ this.messages = validationError.constraints;
66
+ }
67
+ get Messages() {
68
+ return this.messages;
69
+ }
70
+ };
71
+ var ForbiddenAccessError = class extends ElectronInjectorError {
72
+ static {
73
+ __name(this, "ForbiddenAccessError");
74
+ }
75
+ constructor(path, guardName) {
76
+ super(`Can not access to "${path}" path, by the gaurd "${guardName}"`);
77
+ }
78
+ };
51
79
 
52
80
  // src/keys.ts
53
81
  var CONTROLLER = Symbol("electron-di:controller");
@@ -55,6 +83,7 @@ var INJECTABLE = Symbol("electron-di:injectable");
55
83
  var HANDLER = Symbol("electron-di:handler");
56
84
  var PARAM = Symbol("electron-di:param");
57
85
  var GUARD = Symbol("electron-di:guard");
86
+ var FILTER = Symbol("electron-di:filter");
58
87
 
59
88
  // src/utilities.ts
60
89
  var Reflector = class {
@@ -181,19 +210,33 @@ var DEV_LOGGER = devLogger;
181
210
 
182
211
  // src/application.ts
183
212
  import { ipcMain } from "electron";
213
+ import { getMetadataStorage, validate } from "class-validator";
214
+ import { plainToInstance } from "class-transformer";
184
215
  var Application = class _Application {
185
216
  static {
186
217
  __name(this, "Application");
187
218
  }
188
219
  configOptions;
220
+ validationOptions;
189
221
  container = new Container();
190
- static create(configOptions) {
191
- return new _Application(configOptions);
222
+ filters = /* @__PURE__ */ new Map();
223
+ static create(configOptions, validationOptions = {}) {
224
+ return new _Application(configOptions, validationOptions);
225
+ }
226
+ useGlobalFilters(...filters) {
227
+ for (const filter of filters) {
228
+ const exceptionsClasses = Reflect.getMetadata(FILTER, filter);
229
+ if (!exceptionsClasses) throw new IsNotExceptionFilter(filter.name);
230
+ exceptionsClasses.forEach((excls) => {
231
+ this.filters.set(excls, filter);
232
+ this.container.addProvider(filter);
233
+ });
234
+ }
192
235
  }
193
- constructor(configOptions) {
236
+ constructor(configOptions, validationOptions) {
194
237
  this.configOptions = configOptions;
238
+ this.validationOptions = validationOptions;
195
239
  this.loadProviders();
196
- this.loadControllers();
197
240
  }
198
241
  loadProviders() {
199
242
  for (const provider of this.configOptions.providers || []) {
@@ -201,7 +244,7 @@ var Application = class _Application {
201
244
  DEV_LOGGER(`Provider ${typeof provider == "object" ? provider.provided.name : provider.name} loaded`);
202
245
  }
203
246
  }
204
- loadControllers() {
247
+ bootstrap() {
205
248
  for (const controller of this.configOptions.controllers || []) {
206
249
  const controllerPrefix = this.getControllerPrefix(controller);
207
250
  const controllerDependencies = this.getControllerDependencies(controller);
@@ -217,11 +260,28 @@ var Application = class _Application {
217
260
  const handlerCallback = /* @__PURE__ */ __name(async (event, data) => {
218
261
  const executionContext = new ExecutionContext(controller, controllerInstance[controllerMethod], data, event);
219
262
  for (const guard of guards) {
220
- const response = await this.guardExecute(guard, executionContext);
221
- if (!response) return false;
263
+ try {
264
+ const response = await this.guardExecute(guard, executionContext);
265
+ if (!response) return {
266
+ success: false,
267
+ error: new ForbiddenAccessError(path, guard.constructor.prototype.name)
268
+ };
269
+ } catch (e) {
270
+ return await this.useFilter(e, executionContext);
271
+ }
272
+ }
273
+ let params = [];
274
+ try {
275
+ params = await this.getParams(controllerInstance, controllerMethod, executionContext);
276
+ } catch (e) {
277
+ return await this.useFilter(e, executionContext);
278
+ }
279
+ let controllerResult = void 0;
280
+ try {
281
+ controllerResult = await this.controllerExecute(controllerInstance, controllerInstance[controllerMethod], params);
282
+ } catch (e) {
283
+ return await this.useFilter(e, executionContext);
222
284
  }
223
- const params = this.getParams(controllerInstance, controllerMethod, executionContext);
224
- const controllerResult = await this.controllerExecute(controllerInstance, controllerInstance[controllerMethod], params);
225
285
  return controllerResult;
226
286
  }, "handlerCallback");
227
287
  if (handlerMetadata.type === "invoke") {
@@ -232,15 +292,24 @@ var Application = class _Application {
232
292
  }
233
293
  }
234
294
  }
235
- getParams(target, propertyKey, executionContext) {
295
+ async getParams(target, propertyKey, executionContext) {
236
296
  const params = Reflect.getMetadata(PARAM, target, propertyKey);
237
297
  if (!params) return [];
238
- return params.map((param) => {
298
+ return await Promise.all(params.map(async (param, index) => {
239
299
  if (param === "ctx") return executionContext;
240
300
  if (param === "event") return executionContext.event;
241
- if (param === "payload") return executionContext.payload;
301
+ if (param === "payload") {
302
+ const validationClass = Reflect.getMetadata("design:paramtypes", target, propertyKey)[index];
303
+ const metadata = getMetadataStorage().getTargetValidationMetadatas(validationClass, null, false, false);
304
+ if (typeof validationClass == "function" && metadata.length) {
305
+ const validatorObjectInstance = plainToInstance(validationClass, executionContext.payload);
306
+ const errors = await validate(validatorObjectInstance, this.validationOptions);
307
+ if (errors.length) throw new DataValidationError(errors[0]);
308
+ }
309
+ return executionContext.payload;
310
+ }
242
311
  return void 0;
243
- });
312
+ }));
244
313
  }
245
314
  buildPath(controllerPrefix, methodPath) {
246
315
  const prefix = controllerPrefix.trim();
@@ -251,39 +320,48 @@ var Application = class _Application {
251
320
  return "";
252
321
  }
253
322
  async guardExecute(guard, executionContext) {
254
- try {
255
- const guardResult = guard.canActivate(executionContext);
256
- if (guardResult instanceof Observable) {
257
- const result = await lastValueFrom(guardResult.pipe(first()));
258
- if (!result) return false;
259
- } else if (guardResult instanceof Promise) {
260
- const result = await guardResult;
261
- if (!result) return false;
262
- } else {
263
- if (!guardResult) return false;
264
- }
265
- return true;
266
- } catch (error) {
267
- PROD_LOGGER(error);
268
- return false;
323
+ const guardResult = guard.canActivate(executionContext);
324
+ if (guardResult instanceof Observable) {
325
+ const result = await lastValueFrom(guardResult.pipe(first()));
326
+ if (!result) return false;
327
+ } else if (guardResult instanceof Promise) {
328
+ const result = await guardResult;
329
+ if (!result) return false;
330
+ } else {
331
+ if (!guardResult) return false;
269
332
  }
333
+ return true;
270
334
  }
271
335
  async controllerExecute(context, target, params) {
272
- try {
273
- const boundedTarget = target.bind(context);
274
- let controllerResult = boundedTarget(...params);
275
- while (controllerResult instanceof Observable || controllerResult instanceof Promise) {
276
- if (controllerResult instanceof Observable) {
277
- controllerResult = await lastValueFrom(controllerResult);
278
- } else if (controllerResult instanceof Promise) {
279
- controllerResult = await controllerResult;
280
- }
336
+ const boundedTarget = target.bind(context);
337
+ let controllerResult = boundedTarget(...params);
338
+ while (controllerResult instanceof Observable || controllerResult instanceof Promise) {
339
+ if (controllerResult instanceof Observable) {
340
+ controllerResult = await lastValueFrom(controllerResult);
341
+ } else if (controllerResult instanceof Promise) {
342
+ controllerResult = await controllerResult;
281
343
  }
282
- return controllerResult;
283
- } catch (error) {
284
- PROD_LOGGER(error.message ?? error);
285
- return void 0;
286
344
  }
345
+ return controllerResult;
346
+ }
347
+ async useFilter(error, executionContext) {
348
+ PROD_LOGGER(error);
349
+ for (const [cls, fltr] of this.filters) {
350
+ if (!(error instanceof cls)) continue;
351
+ const filterInstance = this.container.resolve(fltr);
352
+ const response = filterInstance.catch(error, executionContext);
353
+ if (response instanceof Promise) {
354
+ return await response;
355
+ }
356
+ if (response instanceof Observable) {
357
+ return await lastValueFrom(response);
358
+ }
359
+ return response;
360
+ }
361
+ return {
362
+ success: false,
363
+ error
364
+ };
287
365
  }
288
366
  getHandlerMetadata(target) {
289
367
  const handlerMetadata = Reflect.getMetadata(HANDLER, target);
@@ -387,16 +465,36 @@ function SetMetadata(key, value) {
387
465
  };
388
466
  }
389
467
  __name(SetMetadata, "SetMetadata");
468
+ function Catch(...filters) {
469
+ return function(target) {
470
+ const prevFilters = Reflect.getMetadata(FILTER, target) || [];
471
+ Reflect.defineMetadata(INJECTABLE, "singleton", target);
472
+ Reflect.defineMetadata(FILTER, [
473
+ ...prevFilters,
474
+ ...filters
475
+ ], target);
476
+ };
477
+ }
478
+ __name(Catch, "Catch");
390
479
  export {
391
480
  Application,
481
+ Catch,
482
+ CircularDependency,
392
483
  Controller,
484
+ ControllerIsNotValid,
393
485
  Ctx,
486
+ DataValidationError,
487
+ ElectronInjectorError,
394
488
  Event,
395
489
  ExecutionContext,
490
+ ForbiddenAccessError,
396
491
  Injectable,
492
+ IsNotExceptionFilter,
397
493
  OnInvoke,
398
494
  OnSend,
399
495
  Payload,
496
+ ProviderIsNotInjectable,
497
+ ProviderNotFound,
400
498
  Reflector,
401
499
  SetMetadata,
402
500
  UseGuards,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "electron-injector",
3
- "version": "1.0.3",
3
+ "version": "1.1.0",
4
4
  "description": "Biblioteca para el desarrollo de aplicaciones con electron que proporciona una arquitectura robusta con inyección e inversion de dependencias.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -37,6 +37,8 @@
37
37
  "@swc/core": "^1.15.3",
38
38
  "@types/debug": "^4.1.12",
39
39
  "@types/node": "^24.10.1",
40
+ "class-transformer": "^0.5.1",
41
+ "class-validator": "^0.14.3",
40
42
  "electron": "^39.2.4",
41
43
  "eslint": "^9.39.1",
42
44
  "eslint-config-prettier": "^10.1.8",
@@ -49,6 +51,8 @@
49
51
  "typescript-eslint": "^8.48.0"
50
52
  },
51
53
  "peerDependencies": {
54
+ "class-transformer": "^0.5.1",
55
+ "class-validator": "^0.14.3",
52
56
  "electron": "^39.2.4",
53
57
  "rxjs": "^7.8.2"
54
58
  },