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.
- package/.eslintrc.js +6 -0
- package/LICENSE +177 -0
- package/README.md +6 -0
- package/docs/RU-README.md +6 -0
- package/lib/Container.d.ts +30 -0
- package/lib/Container.js +236 -0
- package/lib/DeviceManager.d.ts +32 -0
- package/lib/DeviceManager.js +143 -0
- package/lib/IServiceStructure.d.ts +5 -0
- package/lib/IServiceStructure.js +2 -0
- package/lib/IStructureDevice.d.ts +7 -0
- package/lib/IStructureDevice.js +2 -0
- package/lib/ImportManager.d.ts +15 -0
- package/lib/ImportManager.js +145 -0
- package/lib/MainProcess.d.ts +9 -0
- package/lib/MainProcess.js +28 -0
- package/lib/Utility.d.ts +21 -0
- package/lib/Utility.js +48 -0
- package/lib/actions/Action.d.ts +4 -0
- package/lib/actions/Action.js +16 -0
- package/lib/actions/BasicAction.d.ts +15 -0
- package/lib/actions/BasicAction.js +44 -0
- package/lib/actions/GlobalAction.d.ts +4 -0
- package/lib/actions/GlobalAction.js +17 -0
- package/lib/actions/IAction.d.ts +11 -0
- package/lib/actions/IAction.js +2 -0
- package/lib/actions/ILocalAction.d.ts +11 -0
- package/lib/actions/ILocalAction.js +2 -0
- package/lib/errors/CoreError.d.ts +53 -0
- package/lib/errors/CoreError.js +81 -0
- package/lib/errors/ErrorManager.d.ts +47 -0
- package/lib/errors/ErrorManager.js +84 -0
- package/lib/index.d.ts +19 -0
- package/lib/index.js +55 -0
- package/lib/ports/BasicPort.d.ts +11 -0
- package/lib/ports/BasicPort.js +49 -0
- package/lib/ports/ILocalPort.d.ts +10 -0
- package/lib/ports/ILocalPort.js +2 -0
- package/lib/ports/IPort.d.ts +10 -0
- package/lib/ports/IPort.js +2 -0
- package/lib/ports/Port.d.ts +6 -0
- package/lib/ports/Port.js +20 -0
- package/lib/ports/ReturnPort.d.ts +6 -0
- package/lib/ports/ReturnPort.js +21 -0
- package/lib/ports/StandartPort.d.ts +4 -0
- package/lib/ports/StandartPort.js +17 -0
- package/lib/service/Device.d.ts +175 -0
- package/lib/service/Device.js +191 -0
- package/lib/service/DeviceConnect.d.ts +21 -0
- package/lib/service/DeviceConnect.js +32 -0
- package/lib/service/DevicePort.d.ts +24 -0
- package/lib/service/DevicePort.js +41 -0
- package/lib/service/IDeviceEvent.d.ts +5 -0
- package/lib/service/IDeviceEvent.js +2 -0
- package/lib/test.d.ts +1 -0
- package/lib/test.js +58 -0
- package/lib/validator/IValidationProblem.d.ts +8 -0
- package/lib/validator/IValidationProblem.js +2 -0
- package/lib/validator/IValidationRule.d.ts +9 -0
- package/lib/validator/IValidationRule.js +2 -0
- package/lib/validator/IValidationSubrule.d.ts +4 -0
- package/lib/validator/IValidationSubrule.js +2 -0
- package/lib/validator/Rule.d.ts +12 -0
- package/lib/validator/Rule.js +30 -0
- package/lib/validator/Validator.d.ts +14 -0
- package/lib/validator/Validator.js +57 -0
- package/lib/validator/types/ArrayType.d.ts +14 -0
- package/lib/validator/types/ArrayType.js +58 -0
- package/lib/validator/types/BasicType.d.ts +18 -0
- package/lib/validator/types/BasicType.js +54 -0
- package/lib/validator/types/NumberType.d.ts +19 -0
- package/lib/validator/types/NumberType.js +66 -0
- package/lib/validator/types/ObjectType.d.ts +18 -0
- package/lib/validator/types/ObjectType.js +51 -0
- package/lib/validator/types/StringType.d.ts +19 -0
- package/lib/validator/types/StringType.js +63 -0
- package/package.json +26 -0
- package/src/Container.ts +237 -0
- package/src/DeviceManager.ts +124 -0
- package/src/IServiceStructure.ts +6 -0
- package/src/IStructureDevice.ts +5 -0
- package/src/ImportManager.ts +112 -0
- package/src/MainProcess.ts +18 -0
- package/src/Utility.ts +44 -0
- package/src/actions/Action.ts +12 -0
- package/src/actions/BasicAction.ts +54 -0
- package/src/actions/GlobalAction.ts +14 -0
- package/src/actions/IAction.ts +8 -0
- package/src/actions/ILocalAction.ts +8 -0
- package/src/errors/CoreError.ts +87 -0
- package/src/errors/ErrorManager.ts +93 -0
- package/src/index.ts +30 -0
- package/src/ports/BasicPort.ts +53 -0
- package/src/ports/ILocalPort.ts +12 -0
- package/src/ports/IPort.ts +12 -0
- package/src/ports/Port.ts +17 -0
- package/src/ports/ReturnPort.ts +19 -0
- package/src/ports/StandartPort.ts +13 -0
- package/src/service/Device.ts +225 -0
- package/src/service/DeviceConnect.ts +36 -0
- package/src/service/DevicePort.ts +46 -0
- package/src/service/IDeviceEvent.ts +5 -0
- package/src/test.ts +82 -0
- package/src/validator/IValidationProblem.ts +9 -0
- package/src/validator/IValidationRule.ts +10 -0
- package/src/validator/IValidationSubrule.ts +5 -0
- package/src/validator/Rule.ts +30 -0
- package/src/validator/Validator.ts +67 -0
- package/src/validator/types/ArrayType.ts +67 -0
- package/src/validator/types/BasicType.ts +61 -0
- package/src/validator/types/NumberType.ts +86 -0
- package/src/validator/types/ObjectType.ts +58 -0
- package/src/validator/types/StringType.ts +79 -0
- package/tsconfig.json +103 -0
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright © 2022 Boris Bobylev. All rights reserved.
|
|
3
|
+
* Licensed under the Apache License, Version 2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
// import DeviceError from "../errors/DeviceError";
|
|
8
|
+
// import Rule from "../validator/ValidatorRule";
|
|
9
|
+
import BasicType from "../validator/types/BasicType";
|
|
10
|
+
import Container from '../Container';
|
|
11
|
+
import BasicAction from "../actions/BasicAction";
|
|
12
|
+
import BasicPort from "../ports/BasicPort";
|
|
13
|
+
import DevicePort from "./DevicePort";
|
|
14
|
+
import IDeviceEvent from "./IDeviceEvent";
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Интерфейс списка исходящих портов устройства
|
|
19
|
+
// */
|
|
20
|
+
// export interface IDeviceOutputList {
|
|
21
|
+
// [index: string]: OutputPort;
|
|
22
|
+
// }
|
|
23
|
+
|
|
24
|
+
// /**
|
|
25
|
+
// * Интерфейс списка входящих портов устройства
|
|
26
|
+
// */
|
|
27
|
+
// export interface IDeviceInputList {
|
|
28
|
+
// [index: string]: InputPort;
|
|
29
|
+
// }
|
|
30
|
+
|
|
31
|
+
export enum EDeviceMessageTypes {
|
|
32
|
+
terminal = "terminal",
|
|
33
|
+
info = "info",
|
|
34
|
+
error = "error",
|
|
35
|
+
event = "event",
|
|
36
|
+
action = "action",
|
|
37
|
+
alert = "alert",
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
interface IDevicePorts {
|
|
41
|
+
input: {[key:string]: DevicePort}
|
|
42
|
+
output: {[key:string]: DevicePort}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export default class Device {
|
|
46
|
+
/** Идентификатор устройства */
|
|
47
|
+
id: string;
|
|
48
|
+
type: string;
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
ports: IDevicePorts
|
|
52
|
+
|
|
53
|
+
/** Экземпляр класса виртуальной стойки */
|
|
54
|
+
Container: Container;
|
|
55
|
+
|
|
56
|
+
/** Входящие (назначаемые сверху) параметры устройства */
|
|
57
|
+
options: {[key: string]: any} = {};
|
|
58
|
+
|
|
59
|
+
constructor(id: string, type: string, Container: Container){
|
|
60
|
+
this.id = id
|
|
61
|
+
this.type = type
|
|
62
|
+
this.Container = Container
|
|
63
|
+
this.ports = {
|
|
64
|
+
input: {},
|
|
65
|
+
output: {}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Short device description
|
|
71
|
+
*
|
|
72
|
+
* @return {string} Device description
|
|
73
|
+
* */
|
|
74
|
+
description(): string{
|
|
75
|
+
return ''
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Shares данные устройства (обновляемые данные)
|
|
80
|
+
* используется с методом `this.render`
|
|
81
|
+
*
|
|
82
|
+
* @see render()
|
|
83
|
+
* */
|
|
84
|
+
shares: any = {};
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
*
|
|
88
|
+
*/
|
|
89
|
+
storage: any = {}
|
|
90
|
+
|
|
91
|
+
/** Список Action-методов устройства */
|
|
92
|
+
actions() : { [key: string] : BasicAction} { return {} }
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Определение списка параметров устройства
|
|
96
|
+
*
|
|
97
|
+
* @returns {Array<Rule>}
|
|
98
|
+
* */
|
|
99
|
+
checkOptions(): {[key:string]: BasicType} { return {} }
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Prepare options
|
|
103
|
+
*
|
|
104
|
+
* this method call before validating options
|
|
105
|
+
*/
|
|
106
|
+
prepareOptions() { return }
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
inputs () : {[key:string]: BasicPort} { return {} }
|
|
110
|
+
outputs () : {[key:string]: BasicPort} { return {} }
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Метод является входной точкой для начала инициализации устройства
|
|
114
|
+
*
|
|
115
|
+
* Устройство пройдет только следующие этапы создания устройства:
|
|
116
|
+
*
|
|
117
|
+
* - Создания класса
|
|
118
|
+
* - Назначение праметров устройства
|
|
119
|
+
*
|
|
120
|
+
* Необходимо использовать для назначения функций вызова динамических портов
|
|
121
|
+
* устройства.
|
|
122
|
+
*/
|
|
123
|
+
preProcess() { return }
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Метод является входной точкой для начала работы устройства
|
|
127
|
+
*
|
|
128
|
+
* Устройство пройдет следующие этапы создания устройства:
|
|
129
|
+
*
|
|
130
|
+
* - Создания класса
|
|
131
|
+
* - Назначение праметров устройства
|
|
132
|
+
* - Создание портов
|
|
133
|
+
* - Назначение функций вызова
|
|
134
|
+
* - Создание соединений между устройствами
|
|
135
|
+
* - Линковка Shares устройства
|
|
136
|
+
*
|
|
137
|
+
* Необходимо использовать для осуществления начала основной работы устройства
|
|
138
|
+
* например, инициализация подключений, создание таймеров и тп.
|
|
139
|
+
*/
|
|
140
|
+
process() { return }
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* По аналогии с `process` но асинхронный, загрузчик будет ждать выполнения всех
|
|
144
|
+
* методов `processPromise` всех устройств.
|
|
145
|
+
*
|
|
146
|
+
* Используется, когда есть необходимость перед запуском стойки выполнить
|
|
147
|
+
* и дождаться выполнения асинхронного кода (инициализация некоторых файловых баз данных и тп)
|
|
148
|
+
*/
|
|
149
|
+
async processPromise() { return }
|
|
150
|
+
|
|
151
|
+
stop() { return }
|
|
152
|
+
|
|
153
|
+
async stopPromise() { return }
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Метод заменяется загрузчиком стойки, после чего, вызов этого метода приводит
|
|
157
|
+
* к постановке в очередь устройства на обновление данных `Shares`
|
|
158
|
+
*/
|
|
159
|
+
render() { return this.event('device.render', 'shares', this.shares) }
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Метод заменяется загрузчиком стойки, после чего, вызов этого метода приводит
|
|
163
|
+
* к сохранение в локальное файловое хранилище данных `Storage`
|
|
164
|
+
*/
|
|
165
|
+
save() { return this.event('device.save', 'storage', this.storage) }
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Метод заменяется загрузчиком стойки, после чего, вызов этого метода приводит
|
|
169
|
+
* к отправке сообщению об ошибке
|
|
170
|
+
*
|
|
171
|
+
* @param {string} data Сообщение об ошибке
|
|
172
|
+
* @param {any} trace Непосредственно объект ошибки, или объект который поможет разобратся в случившейся ситуации
|
|
173
|
+
*/
|
|
174
|
+
error(data: string, trace: any) { return this.event('device.error', data, trace) }
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Метод заменяется загрузчиком стойки, после чего, вызов этого метода приводит
|
|
178
|
+
* к отправке информационного сообщения
|
|
179
|
+
*
|
|
180
|
+
* @param {string} data Сообщение об ошибке
|
|
181
|
+
* @param {any} trace Дополнительная информация
|
|
182
|
+
*/
|
|
183
|
+
notify(data: string, trace: any) { return this.event('device.notify', data, trace) }
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Метод заменяется загрузчиком стойки, после чего, вызов этого метода приводит
|
|
187
|
+
* к отправке оповещения
|
|
188
|
+
*
|
|
189
|
+
* @param {string} data Сообщение об ошибке
|
|
190
|
+
* @param {any} trace Дополнительная информация
|
|
191
|
+
*/
|
|
192
|
+
alert(data: string, trace: any) { return this.event('device.alert', data, trace) }
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Метод заменяется загрузчиком стойки, после чего, вызов этого метода приводит
|
|
196
|
+
* к отправке отладочной информации
|
|
197
|
+
*
|
|
198
|
+
* @param {string} data Сообщение об ошибке
|
|
199
|
+
* @param {any} trace Дополнительная информация
|
|
200
|
+
*/
|
|
201
|
+
terminal(data: string, trace: any) { return this.event('device.terminal', data, trace) }
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Метод заменяется загрузчиком стойки, после чего, вызов этого метода приводит
|
|
205
|
+
* к отправке сообщения о событии
|
|
206
|
+
*
|
|
207
|
+
* @param {string} data Сообщение об ошибке
|
|
208
|
+
* @param {any} trace Дополнительная информация
|
|
209
|
+
*/
|
|
210
|
+
protected event(type:string, data: string, trace: any) {
|
|
211
|
+
const nEvent: IDeviceEvent = {id: this.id, data, trace}
|
|
212
|
+
return this.Container.emit(type, nEvent)
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Сообщает стойке, о том, что устройство не может дальше работать
|
|
217
|
+
* и произошла критическая ошибка
|
|
218
|
+
*
|
|
219
|
+
* Требует создание ошибки устройства DeviceError
|
|
220
|
+
*
|
|
221
|
+
*/
|
|
222
|
+
terminate(error: Error, action: string) {
|
|
223
|
+
return this.event('device.terminate', action, error)
|
|
224
|
+
}
|
|
225
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright © 2022 Boris Bobylev. All rights reserved.
|
|
3
|
+
* Licensed under the Apache License, Version 2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import DevicePort from "./DevicePort"
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Класс для соедиения портов устройств
|
|
10
|
+
*
|
|
11
|
+
*/
|
|
12
|
+
export default class {
|
|
13
|
+
outputLink: DevicePort
|
|
14
|
+
inputLink: DevicePort
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Инициализация соединения, требует 2 порта которые привязаны
|
|
18
|
+
* к устройствам
|
|
19
|
+
*
|
|
20
|
+
*/
|
|
21
|
+
constructor(output: DevicePort, input: DevicePort) {
|
|
22
|
+
this.outputLink = output
|
|
23
|
+
this.inputLink = input
|
|
24
|
+
this.outputLink.addConnection(this)
|
|
25
|
+
this.inputLink.addConnection(this)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Вызов входящего порта при вызове соединения
|
|
30
|
+
*
|
|
31
|
+
* @param {any} data Данные
|
|
32
|
+
*/
|
|
33
|
+
push(data: any): any {
|
|
34
|
+
return this.inputLink.push(data)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright © 2022 Boris Bobylev. All rights reserved.
|
|
3
|
+
* Licensed under the Apache License, Version 2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import IPort from "../ports/IPort"
|
|
7
|
+
import DeviceConnect from "./DeviceConnect"
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Класс для реализации порта устройства
|
|
11
|
+
* Порт может быть как входящий так и исходящий
|
|
12
|
+
*/
|
|
13
|
+
export default class DevicePort {
|
|
14
|
+
connected = false
|
|
15
|
+
connections: Array<DeviceConnect> = []
|
|
16
|
+
id: string
|
|
17
|
+
type: string
|
|
18
|
+
required: boolean
|
|
19
|
+
constructor(id: string, port: IPort) {
|
|
20
|
+
this.id = id
|
|
21
|
+
this.type = port.type
|
|
22
|
+
this.required = port.required
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Добавление связи в порт
|
|
27
|
+
*/
|
|
28
|
+
addConnection(connection: DeviceConnect) {
|
|
29
|
+
this.connected = true
|
|
30
|
+
this.connections.push(connection)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Вызов входящего порта при вызове соединения
|
|
35
|
+
*
|
|
36
|
+
* @param {any} data Данные
|
|
37
|
+
*/
|
|
38
|
+
push(data: any): any {
|
|
39
|
+
if (this.connected){
|
|
40
|
+
if (this.connections.length === 1) return this.connections[0].push(data)
|
|
41
|
+
for (const conn of this.connections){
|
|
42
|
+
conn.push(data)
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
package/src/test.ts
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// import Action from "./rack/Action";
|
|
2
|
+
// import Port from "./rack/Port";
|
|
3
|
+
// import Rule from "./validator/Rule";
|
|
4
|
+
|
|
5
|
+
import Rule from "./validator/Rule";
|
|
6
|
+
import Validator from "./validator/Validator";
|
|
7
|
+
|
|
8
|
+
Rule.array().require()
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
// class Device {
|
|
12
|
+
|
|
13
|
+
// options (){
|
|
14
|
+
// return {
|
|
15
|
+
// test: Rule.string().default('Default string').description('Test string'),
|
|
16
|
+
// list: Rule.Array().objects({
|
|
17
|
+
// name: Rule.string(),
|
|
18
|
+
// value: Rule.number()
|
|
19
|
+
// })
|
|
20
|
+
// }
|
|
21
|
+
// }
|
|
22
|
+
|
|
23
|
+
// outputs(){
|
|
24
|
+
// return {
|
|
25
|
+
// 'test.output%d': Port.standart().dynamic(5),
|
|
26
|
+
// }
|
|
27
|
+
// }
|
|
28
|
+
|
|
29
|
+
// inputs(){
|
|
30
|
+
// return {
|
|
31
|
+
// 'test.output%d': Port.return().dynamic(5),
|
|
32
|
+
// }
|
|
33
|
+
// }
|
|
34
|
+
|
|
35
|
+
// actions(){
|
|
36
|
+
// return {
|
|
37
|
+
// 'test.action': Action.global().rules({
|
|
38
|
+
// test: Rule.string().default('Default string').description('Test string'),
|
|
39
|
+
// }).description('Test action for call global')
|
|
40
|
+
// }
|
|
41
|
+
// }
|
|
42
|
+
|
|
43
|
+
// init(){
|
|
44
|
+
|
|
45
|
+
// }
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
// process(){
|
|
49
|
+
|
|
50
|
+
// }
|
|
51
|
+
|
|
52
|
+
// async processPromise(){
|
|
53
|
+
|
|
54
|
+
// }
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
// }
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
const rules = {
|
|
65
|
+
obj: Rule.object().require().description('Test validation object'),
|
|
66
|
+
str: Rule.string().require().minLength(5),
|
|
67
|
+
arr: Rule.array().require(),
|
|
68
|
+
num: Rule.number().require().integer().description('integer test')
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
const data = {
|
|
73
|
+
obj: {},
|
|
74
|
+
str: 'qwe4',
|
|
75
|
+
arr: [],
|
|
76
|
+
num: 1.23
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
Validator.validate(rules,data)
|
|
81
|
+
|
|
82
|
+
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright © 2022 Boris Bobylev. All rights reserved.
|
|
3
|
+
* Licensed under the Apache License, Version 2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import ArrayType from "./types/ArrayType";
|
|
7
|
+
import NumberType from "./types/NumberType";
|
|
8
|
+
import ObjectType from "./types/ObjectType";
|
|
9
|
+
import StringType from "./types/StringType";
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
*/
|
|
14
|
+
export default class Rule {
|
|
15
|
+
static number() {
|
|
16
|
+
return new NumberType()
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
static string(){
|
|
20
|
+
return new StringType()
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
static object(){
|
|
24
|
+
return new ObjectType()
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
static array (){
|
|
28
|
+
return new ArrayType()
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright © 2022 Boris Bobylev. All rights reserved.
|
|
3
|
+
* Licensed under the Apache License, Version 2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import ErrorManager from "../errors/ErrorManager";
|
|
7
|
+
|
|
8
|
+
import ArrayType from "./types/ArrayType";
|
|
9
|
+
import BasicType from "./types/BasicType";
|
|
10
|
+
import NumberType from "./types/NumberType";
|
|
11
|
+
import ObjectType from "./types/ObjectType";
|
|
12
|
+
import StringType from "./types/StringType";
|
|
13
|
+
|
|
14
|
+
import CoreError from "../errors/CoreError";
|
|
15
|
+
import IValidationProblem from './IValidationProblem';
|
|
16
|
+
import IValidationRule from "./IValidationRule";
|
|
17
|
+
|
|
18
|
+
ErrorManager.register(
|
|
19
|
+
'Validator', 'VXLeMLVnIXGf', 'VR_TYPE_NOT_EXISTS',
|
|
20
|
+
'Type not exists', {
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
ErrorManager.register(
|
|
24
|
+
'Validator', 'X1UP4P2HRHWd', 'VR_NOT_PASS',
|
|
25
|
+
'Validation error - data not pass', {
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
export default class Validator {
|
|
29
|
+
|
|
30
|
+
static validate(rules: {[key:string]: BasicType},data: {[key:string]: any}) : boolean {
|
|
31
|
+
const problems: Array<IValidationProblem> = []
|
|
32
|
+
for (const key of Object.keys(rules)){
|
|
33
|
+
const rule = rules[key]
|
|
34
|
+
const ruleRaw = rule.export()
|
|
35
|
+
const cs = Validator.getClass(ruleRaw.type)
|
|
36
|
+
try {
|
|
37
|
+
cs.validate(data, key, ruleRaw)
|
|
38
|
+
} catch (err){
|
|
39
|
+
if (err instanceof CoreError) problems.push(Validator.makeProblem(err, key, ruleRaw))
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
if (problems.length) Validator.makeError(problems)
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
private static makeError(eList: Array<IValidationProblem>){
|
|
47
|
+
throw ErrorManager.make('VR_NOT_PASS', {
|
|
48
|
+
problems: eList
|
|
49
|
+
})
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
protected static makeProblem(err: CoreError, key: string, rule: IValidationRule) : IValidationProblem {
|
|
53
|
+
return {
|
|
54
|
+
type: err.vShort, code: err.vCode, description: err.message, rule, arg: err.vAdd
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
private static getClass(cn : string){
|
|
59
|
+
switch (cn){
|
|
60
|
+
case 'string': return StringType
|
|
61
|
+
case 'number': return NumberType
|
|
62
|
+
case 'object': return ObjectType
|
|
63
|
+
case 'array': return ArrayType
|
|
64
|
+
}
|
|
65
|
+
throw ErrorManager.make('VR_TYPE_NOT_EXISTS', { type: cn })
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright © 2022 Boris Bobylev. All rights reserved.
|
|
3
|
+
* Licensed under the Apache License, Version 2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import IValidationRule from "../IValidationRule";
|
|
7
|
+
import BasicType from "./BasicType";
|
|
8
|
+
import ErrorManager from "../../errors/ErrorManager"
|
|
9
|
+
import IValidationSubrule from "../IValidationSubrule";
|
|
10
|
+
import Validator from "../Validator";
|
|
11
|
+
import CoreError from "../../errors/CoreError";
|
|
12
|
+
|
|
13
|
+
export default class ArrayType extends BasicType {
|
|
14
|
+
constructor() {
|
|
15
|
+
super()
|
|
16
|
+
this.rule.type = 'array'
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
default(def: Array<any>) {
|
|
20
|
+
this.rule.default = def
|
|
21
|
+
return this
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
content(t: BasicType) {
|
|
25
|
+
this.rule.rules.push({ name: 'contain', args: t })
|
|
26
|
+
return this
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
static validate(obj: { [key: string]: any; }, key: string, rule: IValidationRule): boolean {
|
|
30
|
+
BasicType.validate(obj, key, rule)
|
|
31
|
+
if (!Array.isArray(obj[key])) throw ErrorManager.make('VR_IS_NOT_ARRAY', {})
|
|
32
|
+
for (const subrule of rule.rules) {
|
|
33
|
+
switch (subrule.name) {
|
|
34
|
+
case 'fields':
|
|
35
|
+
ArrayType.checkContent(obj, key, subrule)
|
|
36
|
+
break
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return true
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
protected static checkContent(obj: { [key: string]: any }, key: string, sub: IValidationSubrule) {
|
|
43
|
+
const sw = { value: undefined }
|
|
44
|
+
const tr = { value: sub.args }
|
|
45
|
+
for (const index of obj[key]) {
|
|
46
|
+
sw.value = obj[key][index]
|
|
47
|
+
try {
|
|
48
|
+
Validator.validate(tr, sw)
|
|
49
|
+
} catch (error) {
|
|
50
|
+
if (error instanceof CoreError) {
|
|
51
|
+
throw ErrorManager.make('VR_ARRAY_CONTENT_ERROR', { index }).add(error)
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
ErrorManager.register(
|
|
60
|
+
'Validator', '3U9s3ZsTH6FA', 'VR_IS_NOT_ARRAY',
|
|
61
|
+
'Value must be a array', {
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
ErrorManager.register(
|
|
65
|
+
'Validator', 'Eg9cIXlxi1yP', 'VR_ARRAY_CONTENT_ERROR',
|
|
66
|
+
'Validation error inside the array data', {
|
|
67
|
+
})
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright © 2022 Boris Bobylev. All rights reserved.
|
|
3
|
+
* Licensed under the Apache License, Version 2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import ErrorManager from "../../errors/ErrorManager"
|
|
7
|
+
import IValidationRule from "../IValidationRule"
|
|
8
|
+
|
|
9
|
+
export default class BasicType {
|
|
10
|
+
protected rule: IValidationRule
|
|
11
|
+
|
|
12
|
+
constructor() {
|
|
13
|
+
this.rule = {
|
|
14
|
+
type: '',
|
|
15
|
+
require: false,
|
|
16
|
+
default: undefined,
|
|
17
|
+
rules: [],
|
|
18
|
+
example: undefined,
|
|
19
|
+
description: ''
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
require(){
|
|
24
|
+
this.rule.require = true
|
|
25
|
+
return this
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
example(ex: any){
|
|
29
|
+
this.rule.example = ex
|
|
30
|
+
return this
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
description(desc: string){
|
|
34
|
+
this.rule.description = desc
|
|
35
|
+
return this
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export() {
|
|
39
|
+
return this.rule
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
static validate(obj: {[key:string]: any}, key: string, rule: IValidationRule) :boolean {
|
|
43
|
+
BasicType.checkDefault(obj, key, rule)
|
|
44
|
+
BasicType.checkRequire(obj, key, rule)
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
protected static checkDefault(obj: {[key:string]: any}, key: string, rule: IValidationRule) {
|
|
49
|
+
if (rule.default === undefined) return
|
|
50
|
+
if (obj[key] === undefined) obj[key] = rule.default
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
protected static checkRequire(obj: {[key:string]: any}, key: string, rule: IValidationRule) {
|
|
54
|
+
if (obj[key] === undefined) throw ErrorManager.make('VR_ERROR_REQUAERED', { key })
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
ErrorManager.register(
|
|
59
|
+
'Validator', 'Jwg5Mr1NqaSj', 'VR_ERROR_REQUAERED',
|
|
60
|
+
'A value is required', {
|
|
61
|
+
})
|