electron-injector 1.0.2 → 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,
@@ -52,15 +61,15 @@ var import_reflect_metadata = require("reflect-metadata");
52
61
  var import_rxjs = require("rxjs");
53
62
 
54
63
  // src/errors.ts
55
- var ElectronDiError = class extends Error {
64
+ var ElectronInjectorError = class extends Error {
56
65
  static {
57
- __name(this, "ElectronDiError");
66
+ __name(this, "ElectronInjectorError");
58
67
  }
59
68
  constructor(message) {
60
69
  super(message);
61
70
  }
62
71
  };
63
- var ProviderNotFound = class extends ElectronDiError {
72
+ var ProviderNotFound = class extends ElectronInjectorError {
64
73
  static {
65
74
  __name(this, "ProviderNotFound");
66
75
  }
@@ -68,7 +77,15 @@ var ProviderNotFound = class extends ElectronDiError {
68
77
  super(`Provider '${providerName}' not found`);
69
78
  }
70
79
  };
71
- var CircularDependency = class extends ElectronDiError {
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
+ };
88
+ var CircularDependency = class extends ElectronInjectorError {
72
89
  static {
73
90
  __name(this, "CircularDependency");
74
91
  }
@@ -76,7 +93,7 @@ var CircularDependency = class extends ElectronDiError {
76
93
  super(`Circular dependency detected for provider '${providerName}'`);
77
94
  }
78
95
  };
79
- var ProviderIsNotInjectable = class extends ElectronDiError {
96
+ var ProviderIsNotInjectable = class extends ElectronInjectorError {
80
97
  static {
81
98
  __name(this, "ProviderIsNotInjectable");
82
99
  }
@@ -84,7 +101,7 @@ var ProviderIsNotInjectable = class extends ElectronDiError {
84
101
  super(`Provider '${providerName}' is not injectable. Please ensure it is decorated with @Injectable()`);
85
102
  }
86
103
  };
87
- var ControllerIsNotValid = class extends ElectronDiError {
104
+ var ControllerIsNotValid = class extends ElectronInjectorError {
88
105
  static {
89
106
  __name(this, "ControllerIsNotValid");
90
107
  }
@@ -92,6 +109,26 @@ var ControllerIsNotValid = class extends ElectronDiError {
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,16 +263,33 @@ var DEV_LOGGER = devLogger;
225
263
 
226
264
  // src/application.ts
227
265
  var import_electron = require("electron");
228
- var Application = class {
266
+ var import_class_validator = require("class-validator");
267
+ var import_class_transformer = require("class-transformer");
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
- constructor(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
+ }
288
+ }
289
+ constructor(configOptions, validationOptions) {
235
290
  this.configOptions = configOptions;
291
+ this.validationOptions = validationOptions;
236
292
  this.loadProviders();
237
- this.loadControllers();
238
293
  }
239
294
  loadProviders() {
240
295
  for (const provider of this.configOptions.providers || []) {
@@ -242,7 +297,7 @@ var Application = class {
242
297
  DEV_LOGGER(`Provider ${typeof provider == "object" ? provider.provided.name : provider.name} loaded`);
243
298
  }
244
299
  }
245
- loadControllers() {
300
+ bootstrap() {
246
301
  for (const controller of this.configOptions.controllers || []) {
247
302
  const controllerPrefix = this.getControllerPrefix(controller);
248
303
  const controllerDependencies = this.getControllerDependencies(controller);
@@ -258,11 +313,28 @@ var Application = class {
258
313
  const handlerCallback = /* @__PURE__ */ __name(async (event, data) => {
259
314
  const executionContext = new ExecutionContext(controller, controllerInstance[controllerMethod], data, event);
260
315
  for (const guard of guards) {
261
- const response = await this.guardExecute(guard, executionContext);
262
- 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);
263
337
  }
264
- const params = this.getParams(controllerInstance, controllerMethod, executionContext);
265
- const controllerResult = await this.controllerExecute(controllerInstance, controllerInstance[controllerMethod], params);
266
338
  return controllerResult;
267
339
  }, "handlerCallback");
268
340
  if (handlerMetadata.type === "invoke") {
@@ -273,15 +345,24 @@ var Application = class {
273
345
  }
274
346
  }
275
347
  }
276
- getParams(target, propertyKey, executionContext) {
348
+ async getParams(target, propertyKey, executionContext) {
277
349
  const params = Reflect.getMetadata(PARAM, target, propertyKey);
278
350
  if (!params) return [];
279
- return params.map((param) => {
351
+ return await Promise.all(params.map(async (param, index) => {
280
352
  if (param === "ctx") return executionContext;
281
353
  if (param === "event") return executionContext.event;
282
- 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
+ }
283
364
  return void 0;
284
- });
365
+ }));
285
366
  }
286
367
  buildPath(controllerPrefix, methodPath) {
287
368
  const prefix = controllerPrefix.trim();
@@ -292,39 +373,48 @@ var Application = class {
292
373
  return "";
293
374
  }
294
375
  async guardExecute(guard, executionContext) {
295
- try {
296
- const guardResult = guard.canActivate(executionContext);
297
- if (guardResult instanceof import_rxjs.Observable) {
298
- const result = await (0, import_rxjs.lastValueFrom)(guardResult.pipe((0, import_rxjs.first)()));
299
- if (!result) return false;
300
- } else if (guardResult instanceof Promise) {
301
- const result = await guardResult;
302
- if (!result) return false;
303
- } else {
304
- if (!guardResult) return false;
305
- }
306
- return true;
307
- } catch (error) {
308
- PROD_LOGGER(error);
309
- 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;
310
385
  }
386
+ return true;
311
387
  }
312
388
  async controllerExecute(context, target, params) {
313
- try {
314
- const boundedTarget = target.bind(context);
315
- let controllerResult = boundedTarget(...params);
316
- while (controllerResult instanceof import_rxjs.Observable || controllerResult instanceof Promise) {
317
- if (controllerResult instanceof import_rxjs.Observable) {
318
- controllerResult = await (0, import_rxjs.lastValueFrom)(controllerResult);
319
- } else if (controllerResult instanceof Promise) {
320
- controllerResult = await controllerResult;
321
- }
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;
322
396
  }
323
- return controllerResult;
324
- } catch (error) {
325
- PROD_LOGGER(error.message ?? error);
326
- return void 0;
327
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
+ };
328
418
  }
329
419
  getHandlerMetadata(target) {
330
420
  const handlerMetadata = Reflect.getMetadata(HANDLER, target);
@@ -428,17 +518,37 @@ function SetMetadata(key, value) {
428
518
  };
429
519
  }
430
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");
431
532
  // Annotate the CommonJS export names for ESM import in node:
432
533
  0 && (module.exports = {
433
534
  Application,
535
+ Catch,
536
+ CircularDependency,
434
537
  Controller,
538
+ ControllerIsNotValid,
435
539
  Ctx,
540
+ DataValidationError,
541
+ ElectronInjectorError,
436
542
  Event,
437
543
  ExecutionContext,
544
+ ForbiddenAccessError,
438
545
  Injectable,
546
+ IsNotExceptionFilter,
439
547
  OnInvoke,
440
548
  OnSend,
441
549
  Payload,
550
+ ProviderIsNotInjectable,
551
+ ProviderNotFound,
442
552
  Reflector,
443
553
  SetMetadata,
444
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,14 +41,19 @@ interface ConfigOptions {
37
41
 
38
42
  declare class Application {
39
43
  private configOptions;
44
+ private validationOptions;
40
45
  private container;
41
- 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);
42
50
  private loadProviders;
43
- private loadControllers;
51
+ bootstrap(): void;
44
52
  private getParams;
45
53
  private buildPath;
46
54
  private guardExecute;
47
55
  private controllerExecute;
56
+ private useFilter;
48
57
  private getHandlerMetadata;
49
58
  private getGuards;
50
59
  private getControllerPrefix;
@@ -60,5 +69,35 @@ declare function Event(): ParameterDecorator;
60
69
  declare function Ctx(): ParameterDecorator;
61
70
  declare function UseGuards(...guards: Class<CanActivate>[]): (_target: Object, _property?: string | symbol, descriptor?: PropertyDescriptor) => void;
62
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
+ }
63
102
 
64
- 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,14 +41,19 @@ interface ConfigOptions {
37
41
 
38
42
  declare class Application {
39
43
  private configOptions;
44
+ private validationOptions;
40
45
  private container;
41
- 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);
42
50
  private loadProviders;
43
- private loadControllers;
51
+ bootstrap(): void;
44
52
  private getParams;
45
53
  private buildPath;
46
54
  private guardExecute;
47
55
  private controllerExecute;
56
+ private useFilter;
48
57
  private getHandlerMetadata;
49
58
  private getGuards;
50
59
  private getControllerPrefix;
@@ -60,5 +69,35 @@ declare function Event(): ParameterDecorator;
60
69
  declare function Ctx(): ParameterDecorator;
61
70
  declare function UseGuards(...guards: Class<CanActivate>[]): (_target: Object, _property?: string | symbol, descriptor?: PropertyDescriptor) => void;
62
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
+ }
63
102
 
64
- 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
@@ -8,15 +8,15 @@ import "reflect-metadata";
8
8
  import { first, lastValueFrom, Observable } from "rxjs";
9
9
 
10
10
  // src/errors.ts
11
- var ElectronDiError = class extends Error {
11
+ var ElectronInjectorError = class extends Error {
12
12
  static {
13
- __name(this, "ElectronDiError");
13
+ __name(this, "ElectronInjectorError");
14
14
  }
15
15
  constructor(message) {
16
16
  super(message);
17
17
  }
18
18
  };
19
- var ProviderNotFound = class extends ElectronDiError {
19
+ var ProviderNotFound = class extends ElectronInjectorError {
20
20
  static {
21
21
  __name(this, "ProviderNotFound");
22
22
  }
@@ -24,7 +24,15 @@ var ProviderNotFound = class extends ElectronDiError {
24
24
  super(`Provider '${providerName}' not found`);
25
25
  }
26
26
  };
27
- var CircularDependency = class extends ElectronDiError {
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
+ };
35
+ var CircularDependency = class extends ElectronInjectorError {
28
36
  static {
29
37
  __name(this, "CircularDependency");
30
38
  }
@@ -32,7 +40,7 @@ var CircularDependency = class extends ElectronDiError {
32
40
  super(`Circular dependency detected for provider '${providerName}'`);
33
41
  }
34
42
  };
35
- var ProviderIsNotInjectable = class extends ElectronDiError {
43
+ var ProviderIsNotInjectable = class extends ElectronInjectorError {
36
44
  static {
37
45
  __name(this, "ProviderIsNotInjectable");
38
46
  }
@@ -40,7 +48,7 @@ var ProviderIsNotInjectable = class extends ElectronDiError {
40
48
  super(`Provider '${providerName}' is not injectable. Please ensure it is decorated with @Injectable()`);
41
49
  }
42
50
  };
43
- var ControllerIsNotValid = class extends ElectronDiError {
51
+ var ControllerIsNotValid = class extends ElectronInjectorError {
44
52
  static {
45
53
  __name(this, "ControllerIsNotValid");
46
54
  }
@@ -48,6 +56,26 @@ var ControllerIsNotValid = class extends ElectronDiError {
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,16 +210,33 @@ var DEV_LOGGER = devLogger;
181
210
 
182
211
  // src/application.ts
183
212
  import { ipcMain } from "electron";
184
- var Application = class {
213
+ import { getMetadataStorage, validate } from "class-validator";
214
+ import { plainToInstance } from "class-transformer";
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
- constructor(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
+ }
235
+ }
236
+ constructor(configOptions, validationOptions) {
191
237
  this.configOptions = configOptions;
238
+ this.validationOptions = validationOptions;
192
239
  this.loadProviders();
193
- this.loadControllers();
194
240
  }
195
241
  loadProviders() {
196
242
  for (const provider of this.configOptions.providers || []) {
@@ -198,7 +244,7 @@ var Application = class {
198
244
  DEV_LOGGER(`Provider ${typeof provider == "object" ? provider.provided.name : provider.name} loaded`);
199
245
  }
200
246
  }
201
- loadControllers() {
247
+ bootstrap() {
202
248
  for (const controller of this.configOptions.controllers || []) {
203
249
  const controllerPrefix = this.getControllerPrefix(controller);
204
250
  const controllerDependencies = this.getControllerDependencies(controller);
@@ -214,11 +260,28 @@ var Application = class {
214
260
  const handlerCallback = /* @__PURE__ */ __name(async (event, data) => {
215
261
  const executionContext = new ExecutionContext(controller, controllerInstance[controllerMethod], data, event);
216
262
  for (const guard of guards) {
217
- const response = await this.guardExecute(guard, executionContext);
218
- 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);
219
284
  }
220
- const params = this.getParams(controllerInstance, controllerMethod, executionContext);
221
- const controllerResult = await this.controllerExecute(controllerInstance, controllerInstance[controllerMethod], params);
222
285
  return controllerResult;
223
286
  }, "handlerCallback");
224
287
  if (handlerMetadata.type === "invoke") {
@@ -229,15 +292,24 @@ var Application = class {
229
292
  }
230
293
  }
231
294
  }
232
- getParams(target, propertyKey, executionContext) {
295
+ async getParams(target, propertyKey, executionContext) {
233
296
  const params = Reflect.getMetadata(PARAM, target, propertyKey);
234
297
  if (!params) return [];
235
- return params.map((param) => {
298
+ return await Promise.all(params.map(async (param, index) => {
236
299
  if (param === "ctx") return executionContext;
237
300
  if (param === "event") return executionContext.event;
238
- 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
+ }
239
311
  return void 0;
240
- });
312
+ }));
241
313
  }
242
314
  buildPath(controllerPrefix, methodPath) {
243
315
  const prefix = controllerPrefix.trim();
@@ -248,39 +320,48 @@ var Application = class {
248
320
  return "";
249
321
  }
250
322
  async guardExecute(guard, executionContext) {
251
- try {
252
- const guardResult = guard.canActivate(executionContext);
253
- if (guardResult instanceof Observable) {
254
- const result = await lastValueFrom(guardResult.pipe(first()));
255
- if (!result) return false;
256
- } else if (guardResult instanceof Promise) {
257
- const result = await guardResult;
258
- if (!result) return false;
259
- } else {
260
- if (!guardResult) return false;
261
- }
262
- return true;
263
- } catch (error) {
264
- PROD_LOGGER(error);
265
- 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;
266
332
  }
333
+ return true;
267
334
  }
268
335
  async controllerExecute(context, target, params) {
269
- try {
270
- const boundedTarget = target.bind(context);
271
- let controllerResult = boundedTarget(...params);
272
- while (controllerResult instanceof Observable || controllerResult instanceof Promise) {
273
- if (controllerResult instanceof Observable) {
274
- controllerResult = await lastValueFrom(controllerResult);
275
- } else if (controllerResult instanceof Promise) {
276
- controllerResult = await controllerResult;
277
- }
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;
278
343
  }
279
- return controllerResult;
280
- } catch (error) {
281
- PROD_LOGGER(error.message ?? error);
282
- return void 0;
283
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
+ };
284
365
  }
285
366
  getHandlerMetadata(target) {
286
367
  const handlerMetadata = Reflect.getMetadata(HANDLER, target);
@@ -384,16 +465,36 @@ function SetMetadata(key, value) {
384
465
  };
385
466
  }
386
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");
387
479
  export {
388
480
  Application,
481
+ Catch,
482
+ CircularDependency,
389
483
  Controller,
484
+ ControllerIsNotValid,
390
485
  Ctx,
486
+ DataValidationError,
487
+ ElectronInjectorError,
391
488
  Event,
392
489
  ExecutionContext,
490
+ ForbiddenAccessError,
393
491
  Injectable,
492
+ IsNotExceptionFilter,
394
493
  OnInvoke,
395
494
  OnSend,
396
495
  Payload,
496
+ ProviderIsNotInjectable,
497
+ ProviderNotFound,
397
498
  Reflector,
398
499
  SetMetadata,
399
500
  UseGuards,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "electron-injector",
3
- "version": "1.0.2",
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
  },