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 +30 -25
- package/dist/index.cjs +156 -46
- package/dist/index.d.cts +42 -3
- package/dist/index.d.ts +42 -3
- package/dist/index.js +147 -46
- package/package.json +5 -1
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
|
-
|
|
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:
|
|
67
|
-
height:
|
|
55
|
+
width: 900,
|
|
56
|
+
height: 670,
|
|
57
|
+
autoHideMenuBar: true,
|
|
58
|
+
...(process.platform === 'linux' ? { icon } : {}),
|
|
68
59
|
webPreferences: {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
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
|
-
|
|
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
|
|
64
|
+
var ElectronInjectorError = class extends Error {
|
|
56
65
|
static {
|
|
57
|
-
__name(this, "
|
|
66
|
+
__name(this, "ElectronInjectorError");
|
|
58
67
|
}
|
|
59
68
|
constructor(message) {
|
|
60
69
|
super(message);
|
|
61
70
|
}
|
|
62
71
|
};
|
|
63
|
-
var ProviderNotFound = class extends
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
262
|
-
|
|
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")
|
|
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
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
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
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
11
|
+
var ElectronInjectorError = class extends Error {
|
|
12
12
|
static {
|
|
13
|
-
__name(this, "
|
|
13
|
+
__name(this, "ElectronInjectorError");
|
|
14
14
|
}
|
|
15
15
|
constructor(message) {
|
|
16
16
|
super(message);
|
|
17
17
|
}
|
|
18
18
|
};
|
|
19
|
-
var ProviderNotFound = class extends
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
218
|
-
|
|
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")
|
|
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
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
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
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
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
|
|
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
|
},
|