vrack2-core 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/.eslintrc.js +6 -0
  2. package/LICENSE +177 -0
  3. package/README.md +6 -0
  4. package/docs/RU-README.md +6 -0
  5. package/lib/Container.d.ts +30 -0
  6. package/lib/Container.js +236 -0
  7. package/lib/DeviceManager.d.ts +32 -0
  8. package/lib/DeviceManager.js +143 -0
  9. package/lib/IServiceStructure.d.ts +5 -0
  10. package/lib/IServiceStructure.js +2 -0
  11. package/lib/IStructureDevice.d.ts +7 -0
  12. package/lib/IStructureDevice.js +2 -0
  13. package/lib/ImportManager.d.ts +15 -0
  14. package/lib/ImportManager.js +145 -0
  15. package/lib/MainProcess.d.ts +9 -0
  16. package/lib/MainProcess.js +28 -0
  17. package/lib/Utility.d.ts +21 -0
  18. package/lib/Utility.js +48 -0
  19. package/lib/actions/Action.d.ts +4 -0
  20. package/lib/actions/Action.js +16 -0
  21. package/lib/actions/BasicAction.d.ts +15 -0
  22. package/lib/actions/BasicAction.js +44 -0
  23. package/lib/actions/GlobalAction.d.ts +4 -0
  24. package/lib/actions/GlobalAction.js +17 -0
  25. package/lib/actions/IAction.d.ts +11 -0
  26. package/lib/actions/IAction.js +2 -0
  27. package/lib/actions/ILocalAction.d.ts +11 -0
  28. package/lib/actions/ILocalAction.js +2 -0
  29. package/lib/errors/CoreError.d.ts +53 -0
  30. package/lib/errors/CoreError.js +81 -0
  31. package/lib/errors/ErrorManager.d.ts +47 -0
  32. package/lib/errors/ErrorManager.js +84 -0
  33. package/lib/index.d.ts +19 -0
  34. package/lib/index.js +55 -0
  35. package/lib/ports/BasicPort.d.ts +11 -0
  36. package/lib/ports/BasicPort.js +49 -0
  37. package/lib/ports/ILocalPort.d.ts +10 -0
  38. package/lib/ports/ILocalPort.js +2 -0
  39. package/lib/ports/IPort.d.ts +10 -0
  40. package/lib/ports/IPort.js +2 -0
  41. package/lib/ports/Port.d.ts +6 -0
  42. package/lib/ports/Port.js +20 -0
  43. package/lib/ports/ReturnPort.d.ts +6 -0
  44. package/lib/ports/ReturnPort.js +21 -0
  45. package/lib/ports/StandartPort.d.ts +4 -0
  46. package/lib/ports/StandartPort.js +17 -0
  47. package/lib/service/Device.d.ts +175 -0
  48. package/lib/service/Device.js +191 -0
  49. package/lib/service/DeviceConnect.d.ts +21 -0
  50. package/lib/service/DeviceConnect.js +32 -0
  51. package/lib/service/DevicePort.d.ts +24 -0
  52. package/lib/service/DevicePort.js +41 -0
  53. package/lib/service/IDeviceEvent.d.ts +5 -0
  54. package/lib/service/IDeviceEvent.js +2 -0
  55. package/lib/test.d.ts +1 -0
  56. package/lib/test.js +58 -0
  57. package/lib/validator/IValidationProblem.d.ts +8 -0
  58. package/lib/validator/IValidationProblem.js +2 -0
  59. package/lib/validator/IValidationRule.d.ts +9 -0
  60. package/lib/validator/IValidationRule.js +2 -0
  61. package/lib/validator/IValidationSubrule.d.ts +4 -0
  62. package/lib/validator/IValidationSubrule.js +2 -0
  63. package/lib/validator/Rule.d.ts +12 -0
  64. package/lib/validator/Rule.js +30 -0
  65. package/lib/validator/Validator.d.ts +14 -0
  66. package/lib/validator/Validator.js +57 -0
  67. package/lib/validator/types/ArrayType.d.ts +14 -0
  68. package/lib/validator/types/ArrayType.js +58 -0
  69. package/lib/validator/types/BasicType.d.ts +18 -0
  70. package/lib/validator/types/BasicType.js +54 -0
  71. package/lib/validator/types/NumberType.d.ts +19 -0
  72. package/lib/validator/types/NumberType.js +66 -0
  73. package/lib/validator/types/ObjectType.d.ts +18 -0
  74. package/lib/validator/types/ObjectType.js +51 -0
  75. package/lib/validator/types/StringType.d.ts +19 -0
  76. package/lib/validator/types/StringType.js +63 -0
  77. package/package.json +26 -0
  78. package/src/Container.ts +237 -0
  79. package/src/DeviceManager.ts +124 -0
  80. package/src/IServiceStructure.ts +6 -0
  81. package/src/IStructureDevice.ts +5 -0
  82. package/src/ImportManager.ts +112 -0
  83. package/src/MainProcess.ts +18 -0
  84. package/src/Utility.ts +44 -0
  85. package/src/actions/Action.ts +12 -0
  86. package/src/actions/BasicAction.ts +54 -0
  87. package/src/actions/GlobalAction.ts +14 -0
  88. package/src/actions/IAction.ts +8 -0
  89. package/src/actions/ILocalAction.ts +8 -0
  90. package/src/errors/CoreError.ts +87 -0
  91. package/src/errors/ErrorManager.ts +93 -0
  92. package/src/index.ts +30 -0
  93. package/src/ports/BasicPort.ts +53 -0
  94. package/src/ports/ILocalPort.ts +12 -0
  95. package/src/ports/IPort.ts +12 -0
  96. package/src/ports/Port.ts +17 -0
  97. package/src/ports/ReturnPort.ts +19 -0
  98. package/src/ports/StandartPort.ts +13 -0
  99. package/src/service/Device.ts +225 -0
  100. package/src/service/DeviceConnect.ts +36 -0
  101. package/src/service/DevicePort.ts +46 -0
  102. package/src/service/IDeviceEvent.ts +5 -0
  103. package/src/test.ts +82 -0
  104. package/src/validator/IValidationProblem.ts +9 -0
  105. package/src/validator/IValidationRule.ts +10 -0
  106. package/src/validator/IValidationSubrule.ts +5 -0
  107. package/src/validator/Rule.ts +30 -0
  108. package/src/validator/Validator.ts +67 -0
  109. package/src/validator/types/ArrayType.ts +67 -0
  110. package/src/validator/types/BasicType.ts +61 -0
  111. package/src/validator/types/NumberType.ts +86 -0
  112. package/src/validator/types/ObjectType.ts +58 -0
  113. package/src/validator/types/StringType.ts +79 -0
  114. package/tsconfig.json +103 -0
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright © 2022 Boris Bobylev. All rights reserved.
4
+ * Licensed under the Apache License, Version 2.0
5
+ */
6
+ var __importDefault = (this && this.__importDefault) || function (mod) {
7
+ return (mod && mod.__esModule) ? mod : { "default": mod };
8
+ };
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ const ErrorManager_1 = __importDefault(require("../../errors/ErrorManager"));
11
+ class BasicType {
12
+ constructor() {
13
+ this.rule = {
14
+ type: '',
15
+ require: false,
16
+ default: undefined,
17
+ rules: [],
18
+ example: undefined,
19
+ description: ''
20
+ };
21
+ }
22
+ require() {
23
+ this.rule.require = true;
24
+ return this;
25
+ }
26
+ example(ex) {
27
+ this.rule.example = ex;
28
+ return this;
29
+ }
30
+ description(desc) {
31
+ this.rule.description = desc;
32
+ return this;
33
+ }
34
+ export() {
35
+ return this.rule;
36
+ }
37
+ static validate(obj, key, rule) {
38
+ BasicType.checkDefault(obj, key, rule);
39
+ BasicType.checkRequire(obj, key, rule);
40
+ return true;
41
+ }
42
+ static checkDefault(obj, key, rule) {
43
+ if (rule.default === undefined)
44
+ return;
45
+ if (obj[key] === undefined)
46
+ obj[key] = rule.default;
47
+ }
48
+ static checkRequire(obj, key, rule) {
49
+ if (obj[key] === undefined)
50
+ throw ErrorManager_1.default.make('VR_ERROR_REQUAERED', { key });
51
+ }
52
+ }
53
+ exports.default = BasicType;
54
+ ErrorManager_1.default.register('Validator', 'Jwg5Mr1NqaSj', 'VR_ERROR_REQUAERED', 'A value is required', {});
@@ -0,0 +1,19 @@
1
+ import BasicType from "./BasicType";
2
+ import IValidationRule from "../IValidationRule";
3
+ import IValidationSubrule from "../IValidationSubrule";
4
+ export default class NumberType extends BasicType {
5
+ constructor();
6
+ default(def: number): this;
7
+ integer(): this;
8
+ max(max: number): this;
9
+ min(min: number): this;
10
+ static validate(obj: {
11
+ [key: string]: any;
12
+ }, key: string, rule: IValidationRule): boolean;
13
+ protected static checkMax(obj: {
14
+ [key: string]: any;
15
+ }, key: string, sub: IValidationSubrule): void;
16
+ protected static checkMin(obj: {
17
+ [key: string]: any;
18
+ }, key: string, sub: IValidationSubrule): void;
19
+ }
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright © 2022 Boris Bobylev. All rights reserved.
4
+ * Licensed under the Apache License, Version 2.0
5
+ */
6
+ var __importDefault = (this && this.__importDefault) || function (mod) {
7
+ return (mod && mod.__esModule) ? mod : { "default": mod };
8
+ };
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ const BasicType_1 = __importDefault(require("./BasicType"));
11
+ const ErrorManager_1 = __importDefault(require("../../errors/ErrorManager"));
12
+ class NumberType extends BasicType_1.default {
13
+ constructor() {
14
+ super();
15
+ this.rule.type = 'number';
16
+ }
17
+ default(def) {
18
+ this.rule.default = def;
19
+ return this;
20
+ }
21
+ integer() {
22
+ this.rule.rules.push({ name: 'integer', args: {} });
23
+ return this;
24
+ }
25
+ max(max) {
26
+ this.rule.rules.push({ name: 'max', args: max });
27
+ return this;
28
+ }
29
+ min(min) {
30
+ this.rule.rules.push({ name: 'max', args: min });
31
+ return this;
32
+ }
33
+ static validate(obj, key, rule) {
34
+ BasicType_1.default.validate(obj, key, rule);
35
+ if (typeof obj[key] !== 'number')
36
+ throw ErrorManager_1.default.make('VR_IS_NOT_NUMBER', { key });
37
+ if (!Number.isInteger(obj[key]))
38
+ throw ErrorManager_1.default.make('VR_NUMBER_INTEGER', {});
39
+ for (const subrule of rule.rules) {
40
+ switch (subrule.name) {
41
+ case 'max':
42
+ NumberType.checkMax(obj, key, subrule);
43
+ break;
44
+ case 'min':
45
+ NumberType.checkMin(obj, key, subrule);
46
+ break;
47
+ }
48
+ }
49
+ return true;
50
+ }
51
+ static checkMax(obj, key, sub) {
52
+ const val = obj[key];
53
+ if (val.length > sub.args)
54
+ throw ErrorManager_1.default.make('VR_NUMBER_MAX', { limit: sub.args });
55
+ }
56
+ static checkMin(obj, key, sub) {
57
+ const val = obj[key];
58
+ if (val.length < sub.args)
59
+ throw ErrorManager_1.default.make('VR_NUMBER_MIN', { limit: sub.args });
60
+ }
61
+ }
62
+ exports.default = NumberType;
63
+ ErrorManager_1.default.register('Validator', 'pn7B9po1UGRp', 'VR_IS_NOT_NUMBER', 'Value must be a number', {});
64
+ ErrorManager_1.default.register('Validator', 'fiUqanqqFlnt', 'VR_NUMBER_INTEGER', 'Value must be a integer', {});
65
+ ErrorManager_1.default.register('Validator', 'ZFSMAes0qdzC', 'VR_NUMBER_MAX', 'Number out of limit', {});
66
+ ErrorManager_1.default.register('Validator', 'B3zqsPub40HH', 'VR_NUMBER_MIN', 'Number out of limit', {});
@@ -0,0 +1,18 @@
1
+ import BasicType from "./BasicType";
2
+ import IValidationRule from "../IValidationRule";
3
+ import IValidationSubrule from "../IValidationSubrule";
4
+ export default class ObjectType extends BasicType {
5
+ constructor();
6
+ fields(obj: {
7
+ [key: string]: BasicType;
8
+ }): number;
9
+ static validate(obj: {
10
+ [key: string]: any;
11
+ }, key: string, rule: IValidationRule): boolean;
12
+ /**
13
+ * Validate object fields
14
+ */
15
+ protected static subValidate(obj: {
16
+ [key: string]: any;
17
+ }, key: string, sub: IValidationSubrule): void;
18
+ }
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright © 2022 Boris Bobylev. All rights reserved.
4
+ * Licensed under the Apache License, Version 2.0
5
+ */
6
+ var __importDefault = (this && this.__importDefault) || function (mod) {
7
+ return (mod && mod.__esModule) ? mod : { "default": mod };
8
+ };
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ const BasicType_1 = __importDefault(require("./BasicType"));
11
+ const ErrorManager_1 = __importDefault(require("../../errors/ErrorManager"));
12
+ const Validator_1 = __importDefault(require("../Validator"));
13
+ const CoreError_1 = __importDefault(require("../../errors/CoreError"));
14
+ class ObjectType extends BasicType_1.default {
15
+ constructor() {
16
+ super();
17
+ this.rule.type = 'object';
18
+ }
19
+ fields(obj) {
20
+ return this.rule.rules.push({ name: 'fields', args: obj });
21
+ }
22
+ static validate(obj, key, rule) {
23
+ BasicType_1.default.validate(obj, key, rule);
24
+ if (typeof obj[key] !== 'object')
25
+ throw ErrorManager_1.default.make('VR_IS_NOT_OBJECT', {});
26
+ for (const subrule of rule.rules) {
27
+ switch (subrule.name) {
28
+ case 'fields':
29
+ ObjectType.subValidate(obj, key, subrule);
30
+ break;
31
+ }
32
+ }
33
+ return true;
34
+ }
35
+ /**
36
+ * Validate object fields
37
+ */
38
+ static subValidate(obj, key, sub) {
39
+ try {
40
+ Validator_1.default.validate(sub.args, obj[key]);
41
+ }
42
+ catch (error) {
43
+ if (error instanceof CoreError_1.default) {
44
+ throw ErrorManager_1.default.make('VR_ERROR_OBJECT_FIELDS', { key }).add(error);
45
+ }
46
+ }
47
+ }
48
+ }
49
+ exports.default = ObjectType;
50
+ ErrorManager_1.default.register('Validator', 'zOPzOab9oLum', 'VR_IS_NOT_OBJECT', 'Value must be a object', {});
51
+ ErrorManager_1.default.register('Validator', 'p7qSfRGixV0M', 'VR_ERROR_OBJECT_FIELDS', 'Error of validation of fields inside the object', {});
@@ -0,0 +1,19 @@
1
+ import BasicType from "./BasicType";
2
+ import IValidationRule from "../IValidationRule";
3
+ import IValidationSubrule from "../IValidationSubrule";
4
+ export default class StringType extends BasicType {
5
+ constructor();
6
+ example(ex: string): this;
7
+ default(def: string): this;
8
+ maxLength(max: number): this;
9
+ minLength(min: number): this;
10
+ static validate(obj: {
11
+ [key: string]: any;
12
+ }, key: string, rule: IValidationRule): boolean;
13
+ protected static checkMaxLength(obj: {
14
+ [key: string]: any;
15
+ }, key: string, sub: IValidationSubrule): void;
16
+ protected static checkMinLength(obj: {
17
+ [key: string]: any;
18
+ }, key: string, sub: IValidationSubrule): void;
19
+ }
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright © 2022 Boris Bobylev. All rights reserved.
4
+ * Licensed under the Apache License, Version 2.0
5
+ */
6
+ var __importDefault = (this && this.__importDefault) || function (mod) {
7
+ return (mod && mod.__esModule) ? mod : { "default": mod };
8
+ };
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ const BasicType_1 = __importDefault(require("./BasicType"));
11
+ const ErrorManager_1 = __importDefault(require("../../errors/ErrorManager"));
12
+ class StringType extends BasicType_1.default {
13
+ constructor() {
14
+ super();
15
+ this.rule.type = 'string';
16
+ }
17
+ example(ex) {
18
+ this.rule.example = ex;
19
+ return this;
20
+ }
21
+ default(def) {
22
+ this.rule.default = def;
23
+ return this;
24
+ }
25
+ maxLength(max) {
26
+ this.rule.rules.push({ name: 'maxLength', args: max });
27
+ return this;
28
+ }
29
+ minLength(min) {
30
+ this.rule.rules.push({ name: 'minLength', args: min });
31
+ return this;
32
+ }
33
+ static validate(obj, key, rule) {
34
+ BasicType_1.default.validate(obj, key, rule);
35
+ if (typeof obj[key] !== 'string')
36
+ throw ErrorManager_1.default.make('VR_IS_NOT_STRING', { key });
37
+ for (const subrule of rule.rules) {
38
+ switch (subrule.name) {
39
+ case 'maxLength':
40
+ StringType.checkMaxLength(obj, key, subrule);
41
+ break;
42
+ case 'minLength':
43
+ StringType.checkMinLength(obj, key, subrule);
44
+ break;
45
+ }
46
+ }
47
+ return true;
48
+ }
49
+ static checkMaxLength(obj, key, sub) {
50
+ const val = obj[key];
51
+ if (val.length >= sub.args)
52
+ throw ErrorManager_1.default.make('VR_STRING_MAX_LENGTH', { limit: sub.args, key });
53
+ }
54
+ static checkMinLength(obj, key, sub) {
55
+ const val = obj[key];
56
+ if (val.length <= sub.args)
57
+ throw ErrorManager_1.default.make('VR_STRING_MIN_LENGTH', { limit: sub.args, key });
58
+ }
59
+ }
60
+ exports.default = StringType;
61
+ ErrorManager_1.default.register('Validator', 'klmjxHyQrWuH', 'VR_IS_NOT_STRING', 'Value must be a string', {});
62
+ ErrorManager_1.default.register('Validator', 'BL5lxR4BinkA', 'VR_STRING_MAX_LENGTH', 'The maximum string length is limited', {});
63
+ ErrorManager_1.default.register('Validator', 'KsijTdsbd2YN', 'VR_STRING_MIN_LENGTH', 'The minimum string length is limited', {});
package/package.json ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "vrack2-core",
3
+ "version": "0.0.1",
4
+ "description": "VRack2 core utils",
5
+ "main": "./lib/index",
6
+ "scripts": {
7
+ "test": "node ./lib/test.js"
8
+ },
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://gitlab.com/vrack/core-utils.git"
12
+ },
13
+ "author": "Boris Bobylev",
14
+ "license": "MIT",
15
+ "bugs": {
16
+ "url": "https://gitlab.com/vrack/core-utils/issues"
17
+ },
18
+ "homepage": "https://gitlab.com/vrack/core-utils#readme",
19
+ "devDependencies": {
20
+ "@types/node": "^18.11.17",
21
+ "@typescript-eslint/eslint-plugin": "^5.45.0",
22
+ "@typescript-eslint/parser": "^5.45.0",
23
+ "eslint": "^8.29.0",
24
+ "typescript": "^4.9.3"
25
+ }
26
+ }
@@ -0,0 +1,237 @@
1
+ import EventEmitter from "events";
2
+ import DeviceManager from "./DeviceManager";
3
+
4
+ import ErrorManager from "./errors/ErrorManager";
5
+ import IServiceStructure from "./IServiceStructure";
6
+ import IStructureDevice from "./IStructureDevice";
7
+ import Device from "./service/Device";
8
+ import Rule from "./validator/Rule";
9
+ import CoreError from "./errors/CoreError";
10
+ import Validator from "./validator/Validator";
11
+ import BasicAction from "./actions/BasicAction";
12
+ import ImportManager from "./ImportManager";
13
+ import DevicePort from "./service/DevicePort";
14
+
15
+ import IPort from "./ports/IPort";
16
+ import DeviceConnect from "./service/DeviceConnect";
17
+
18
+
19
+ ErrorManager.register('Container', 'FBDRkSAWnlcc', 'CTR_ERROR_INIT_DEVICE', 'Device initialization error', {
20
+ deviceConfig: Rule.object().description('Device configuration')
21
+ })
22
+
23
+ ErrorManager.register('Container', '96UX24PTyFU7', 'CTR_ERROR_INIT_CONNECTION', 'Connection initialization error', {
24
+ connection: Rule.string().description('Connection string')
25
+ })
26
+
27
+
28
+ ErrorManager.register('Container', '0HVa3cO1E2vB', 'CTR_INCORRECT_DEVICE_ID', 'Incorrect device id', {})
29
+ ErrorManager.register('Container', 'uF62e07wloS9', 'CTR_DEVICE_DUBLICATE', 'Device id is dublicated', {})
30
+ ErrorManager.register('Container', '2RZznI3JDNUW', 'CTR_ERROR_PREPARE_OPTIONS', 'An error occurred while preparing options', {
31
+ message: Rule.string().description('Exception error string')
32
+ })
33
+ ErrorManager.register('Container', 'NDW2oD7mFxqB', 'CTR_DEVICE_ACTION_NF', 'Action on device not found', {
34
+ action: Rule.string().description('Action name'),
35
+ method: Rule.string().description('Method name')
36
+ })
37
+ ErrorManager.register('Container', 'jkIpU1p4z5uz', 'CTR_INCORRECT_DYNAMIC_PN', 'Incorrect dynamic port name', {
38
+ port: Rule.string().description('Incorrect port name')
39
+ })
40
+ ErrorManager.register('Container', 'e8m8dUVVOEU7', 'CTR_INCORRECT_PN', 'Incorrect port name', {
41
+ port: Rule.string().description('Incorrect port name')
42
+ })
43
+ ErrorManager.register('Container', 'qPevPU6SRJ18', 'CTR_INPUT_HANDLER_NF', 'Port input handler not found', {
44
+ port: Rule.string().description('Port name for handler'),
45
+ handler: Rule.string().description('Handler name')
46
+ })
47
+ ErrorManager.register('Container', 'Kp74OuVGNU0u', 'CTR_CONNECTION_INCORRECT', 'Incorrect connection format', {
48
+ connection: Rule.string().description('Connection string'),
49
+ error: Rule.string().description('String of error problem'),
50
+ })
51
+ ErrorManager.register('Container', 'eMrJEISxvali', 'CTR_CONNECTION_DEVICE_NF', 'Connection device not found', {
52
+ connection: Rule.string().description('Connection string'),
53
+ device: Rule.string().description('Device name not found')
54
+ })
55
+ ErrorManager.register('Container', 'CwFj1G47H45E', 'CTR_CONNECTION_PORT_NF', 'Connection port not found', {
56
+ connection: Rule.string().description('Connection string'),
57
+ port: Rule.string().description('Port name not found')
58
+ })
59
+
60
+ export default class Container extends EventEmitter {
61
+ protected config: IServiceStructure
62
+ protected DeviceManager: DeviceManager
63
+ protected devices: { [key: string]: Device } = {}
64
+ protected deviceActions: { [key: string]: { [key: string]: BasicAction } }
65
+
66
+ constructor(config: IServiceStructure, dm: DeviceManager) {
67
+ super()
68
+ this.config = config
69
+ this.DeviceManager = dm
70
+ this.deviceActions = {}
71
+ }
72
+
73
+ async run() {
74
+
75
+ for (const device of this.config.devices) {
76
+ try {
77
+ await this.initDevice(device)
78
+ } catch (error) {
79
+ const ner = ErrorManager.make('CTR_ERROR_INIT_DEVICE', { deviceConfig: device })
80
+ if (error instanceof CoreError) ner.add(error)
81
+ throw ner
82
+ }
83
+ }
84
+
85
+ for (const conn of this.config.connections) {
86
+ try {
87
+ await this.initConnection(conn)
88
+ } catch (error) {
89
+ const ner = ErrorManager.make('CTR_ERROR_INIT_CONNECTION', { connection: conn })
90
+ if (error instanceof CoreError) ner.add(error)
91
+ throw ner
92
+ }
93
+ }
94
+
95
+ for (const key in this.devices) this.devices[key].process()
96
+ for (const key in this.devices) await this.devices[key].processPromise()
97
+
98
+
99
+ // const cs = await this.DeviceManager.get('vrack.Master')
100
+ // const cse = new cs()
101
+ // console.log(cse)
102
+ // cse.run()
103
+ }
104
+
105
+
106
+ protected async initDevice(dconf: IStructureDevice) {
107
+ const cs = await this.DeviceManager.get(dconf.type)
108
+ //
109
+ if (dconf.id === undefined || !dconf.id || typeof dconf.id !== 'string') {
110
+ throw ErrorManager.make('CTR_INCORRECT_DEVICE_ID')
111
+ }
112
+ // Device id is dublicated
113
+ if (dconf.id in this.devices) throw ErrorManager.make('CTR_DEVICE_DUBLICATE')
114
+ const dev = new cs(dconf.id, dconf.type, this) as Device
115
+ this.devices[dconf.id] = dev
116
+ // Fill options
117
+ for (const key in dconf.options) dev.options[key] = dconf.options[key]
118
+
119
+ // try prepare options
120
+ try {
121
+ dev.prepareOptions()
122
+ } catch (error) {
123
+ let message = ''
124
+ if (error instanceof Error) message = error.toString()
125
+ const ner = ErrorManager.make('CTR_ERROR_PREPARE_OPTIONS', { message })
126
+ if (error instanceof CoreError) ner.add(error)
127
+ throw ner
128
+ }
129
+
130
+ const rules = dev.checkOptions()
131
+ // Validating
132
+ Validator.validate(rules, dev.options)
133
+
134
+ dev.preProcess()
135
+
136
+ // Check actions
137
+ this.deviceActions[dev.id] = dev.actions()
138
+ for (const action in this.deviceActions[dev.id]) {
139
+ const method = ImportManager.camelize('action.' + action)
140
+ if (!(method in dev)) throw ErrorManager.make('CTR_DEVICE_ACTION_NF', { action, method })
141
+ }
142
+
143
+
144
+ // make ports
145
+ // prepare ports
146
+
147
+ // make inputPorts
148
+ const iPorts = dev.inputs()
149
+ for (const key in iPorts) {
150
+ const exp = iPorts[key].export()
151
+ const pList = this.getPortList(key, exp)
152
+ for (const subkey in pList) {
153
+ this.checkPortName(subkey)
154
+ const handler = ImportManager.camelize('input.' + subkey) as keyof Device
155
+ this.checkInputHandler(subkey, handler , dev)
156
+ const ndp = new DevicePort(subkey, pList[subkey])
157
+ dev.ports.input[subkey] = ndp
158
+ if (handler in dev) ndp.push = dev[handler].bind(dev)
159
+ }
160
+ }
161
+
162
+ const oPorts = dev.outputs()
163
+ for (const key in oPorts) {
164
+ const exp = oPorts[key].export()
165
+ const pList = this.getPortList(key, exp)
166
+ for (const subkey in pList) {
167
+ this.checkPortName(subkey)
168
+ const ndp = new DevicePort(subkey, pList[subkey])
169
+ dev.ports.output[subkey] = ndp
170
+ }
171
+ }
172
+ }
173
+
174
+ protected checkInputHandler(port: string, handler:string, device: Device) {
175
+ if (!(handler in device)) throw ErrorManager.make('CTR_INPUT_HANDLER_NF', { port, handler })
176
+ }
177
+
178
+ protected async initConnection(conn: string) {
179
+ const cc = this.toConnection(conn)
180
+ if (!(cc.outputDevice in this.devices)) throw ErrorManager.make('CTR_CONNECTION_DEVICE_NF', { connection: conn, device: cc.outputDevice })
181
+ if (!(cc.outputPort in this.devices[cc.outputDevice].ports.output)) throw ErrorManager.make('CTR_CONNECTION_PORT_NF', { connection: conn, port: cc.outputPort })
182
+
183
+ if (!(cc.inputDevice in this.devices)) throw ErrorManager.make('CTR_CONNECTION_DEVICE_NF', { connection: conn, device: cc.inputDevice })
184
+ if (!(cc.inputPort in this.devices[cc.inputDevice].ports.input)) throw ErrorManager.make('CTR_CONNECTION_PORT_NF', { connection: conn, port: cc.inputPort })
185
+ const outPort =this.devices[cc.outputDevice].ports.output[cc.outputPort]
186
+ const inPort = this.devices[cc.inputDevice].ports.input[cc.inputPort]
187
+ new DeviceConnect(outPort, inPort)
188
+ }
189
+
190
+ private toConnection(con: string) {
191
+ const act = con.split('->')
192
+ if (act.length !== 2) throw ErrorManager.make('CTR_CONNECTION_INCORRECT', { connection: con, error: "Syntax connection error, syntax have -> beetwen device" })
193
+
194
+ const outputDeviceActs = act[0].split('.')
195
+ const inputDeviceActs = act[1].split('.')
196
+
197
+ if (outputDeviceActs.length > 3 || inputDeviceActs.length > 3) throw ErrorManager.make('CTR_CONNECTION_INCORRECT', { connection: con, error: "Syntax connection error, syntax have more 3 actets on side" })
198
+ if (outputDeviceActs.length < 2 || inputDeviceActs.length < 2) throw ErrorManager.make('CTR_CONNECTION_INCORRECT', { connection: con, error: "Syntax connection error, syntax have less 2 actets on side" })
199
+
200
+ let outputDevice = outputDeviceActs.shift()?.trim()
201
+ const outputPort = outputDeviceActs.join('.').trim()
202
+ let inputDevice = inputDeviceActs.shift()?.trim()
203
+ const inputPort = inputDeviceActs.join('.').trim()
204
+
205
+ if (outputDevice === undefined) outputDevice = ''
206
+ if (inputDevice === undefined) inputDevice = ''
207
+
208
+ const result: { [key: string]: string } = {
209
+ outputDevice, outputPort, inputDevice, inputPort
210
+ }
211
+ return result
212
+ }
213
+
214
+ protected checkPortName(port: string) {
215
+ if (!port.match(/[a-zA-Z0-9.]/)) throw ErrorManager.make('CTR_INCORRECT_PN', { port })
216
+ }
217
+
218
+ protected getPortList(name: string, iPort: IPort) {
219
+ const result: { [key: string]: IPort } = {}
220
+ if (!iPort.dynamic) {
221
+ result[name] = iPort
222
+ return result
223
+ }
224
+
225
+ if (!name.match(/%d/)) throw ErrorManager.make('CTR_INCORRECT_DYNAMIC_PN', { port: name })
226
+
227
+ for (let i = 1; i <= iPort.count; i++) {
228
+ const nIPort = Object.assign({}, iPort)
229
+ nIPort.count = 0
230
+ nIPort.dynamic = false
231
+ const nname = name.replace(/%d/, i + '')
232
+ result[nname] = nIPort
233
+ }
234
+
235
+ return result
236
+ }
237
+ }
@@ -0,0 +1,124 @@
1
+ import path from 'path'
2
+ import fs from 'fs'
3
+ import ErrorManager from './errors/ErrorManager'
4
+ import Rule from './validator/Rule'
5
+
6
+ interface IDeviceGroup {
7
+ name: string,
8
+ dir: string,
9
+ devices: Array<any>,
10
+ deviceList: Array<string>,
11
+ errors: Array<string>,
12
+ description: string
13
+ }
14
+
15
+ interface IDeviceInGroup{
16
+ name: string,
17
+ errors: Array<string>
18
+ }
19
+
20
+ ErrorManager.register('DeviceManager', 'S5dBTBKTnVbF', 'DM_DEVICE_NOT_FOUND','Device not found', {
21
+ device: Rule.string().require().description('Device request name')
22
+ })
23
+
24
+ export default class DeviceManager {
25
+
26
+ dir = './devices'
27
+ systemDir: string
28
+
29
+ devices = new Map<string, string>()
30
+ deviceList: Array<IDeviceGroup> = []
31
+ constructor(systemDir: string, dir: string) {
32
+ this.systemDir = systemDir
33
+ this.dir = dir
34
+ }
35
+
36
+
37
+ updateList() {
38
+ this.deviceList = this.devicesList()
39
+ for (const dgroup of this.deviceList) {
40
+ dgroup.devices = []
41
+ for (const device of dgroup.deviceList) {
42
+ const ndevice : IDeviceInGroup = { name: device, errors: [] }
43
+ dgroup.devices.push(ndevice)
44
+ const devicePath = path.join(this.systemDir, this.dir, dgroup.name, device + '.js')
45
+ if (!fs.existsSync(devicePath)) { ndevice.errors.push('File of device not found'); continue }
46
+ }
47
+ }
48
+ return this.deviceList
49
+ }
50
+
51
+ devicesList() {
52
+ const result: Array<IDeviceGroup> = []
53
+ const files = fs.readdirSync(path.join(this.systemDir, this.dir))
54
+ const dirs = this.getOnlyDirs(files)
55
+ dirs.sort()
56
+ for (const ddir of dirs) {
57
+ const group: IDeviceGroup = {
58
+ name: ddir,
59
+ dir: this.dir,
60
+ devices: [],
61
+ deviceList: [],
62
+ errors: [],
63
+ description: ''
64
+ }
65
+ result.push(group)
66
+ const listPath = path.join(this.systemDir, this.dir, ddir, 'list.json')
67
+
68
+ if (!fs.existsSync(listPath)) {
69
+ group.errors.push(listPath + ' ignored - list.json not found');
70
+ continue
71
+ }
72
+
73
+ // @todo Исправить на SAFE
74
+ const list: Array<string> = JSON.parse(fs.readFileSync(listPath).toString('utf-8'))
75
+ if (!list || !Array.isArray(list)) {
76
+ group.errors.push(listPath + ' ignored - list.json incorrect');
77
+ continue
78
+ }
79
+
80
+ for (const listKey in list) {
81
+ const reqPath = path.join(this.systemDir, this.dir, ddir, list[listKey])
82
+ const devicePath = reqPath + '.js'
83
+ if (fs.existsSync(devicePath)) {
84
+ if (!this.devices.has(ddir + '.' + list[listKey])) this.devices.set(ddir + '.' + list[listKey], reqPath)
85
+ else console.log(devicePath + ' ignored - device not found')
86
+ }
87
+ }
88
+ list.sort()
89
+
90
+ group.deviceList = list
91
+ }
92
+ return result
93
+ }
94
+
95
+ /**
96
+ * Return class of device
97
+ *
98
+ * Requires special device string of path
99
+ * example "vrack.System" where "vrack" is vendor and "System" is device class
100
+ * @param {string} device Device path string
101
+ */
102
+ async get(device:string){
103
+ const p: string | undefined = this.devices.get(device)
104
+ if (typeof p ==='string') {
105
+ const deviceClass = await import(p)
106
+ if (deviceClass.default) return deviceClass.default
107
+ }
108
+ throw ErrorManager.make('DM_DEVICE_NOT_FOUND', { device })
109
+ }
110
+
111
+ /**
112
+ *
113
+ *
114
+ *
115
+ */
116
+ private getOnlyDirs(files: Array<string>) {
117
+ const result: Array<string> = []
118
+ for (const i in files) {
119
+ if (fs.statSync(path.join(this.systemDir, this.dir, files[i])).isDirectory()) result.push(files[i])
120
+ }
121
+ result.sort()
122
+ return result
123
+ }
124
+ }