mirta 0.1.1 → 0.2.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/dist/index.d.mts +61 -9
- package/dist/index.mjs +56 -14
- package/package.json +4 -4
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { OnEvent } from '@mirta/basics';
|
|
2
2
|
export * from '@mirta/basics';
|
|
3
3
|
|
|
4
4
|
type DeviceType = 'wired' | 'virtual' | 'zigbee';
|
|
@@ -65,9 +65,9 @@ type StrictWhenSpecified<TObject, TKey extends keyof TObject, TReturn> = IsSpeci
|
|
|
65
65
|
* Устанавливает указанное свойство в readonly при выполнении указанного условия.
|
|
66
66
|
* @since 0.1.0
|
|
67
67
|
**/
|
|
68
|
-
type ReadonlyPropWhen<TObject, K extends keyof TObject, TCondition extends boolean | undefined> = TCondition extends true ? Omit<TObject, K> & {
|
|
68
|
+
type ReadonlyPropWhen<TObject, K extends keyof TObject, TCondition extends boolean | undefined> = TCondition extends true ? Expand<Omit<TObject, K> & {
|
|
69
69
|
+readonly [P in K]-?: TObject[P];
|
|
70
|
-
} : TObject;
|
|
70
|
+
}> : TObject;
|
|
71
71
|
/**
|
|
72
72
|
* Проверяет, что указанный тип объекта имеет хотя бы одно свойство заданного типа.
|
|
73
73
|
* Применяется для работы с дженериками.
|
|
@@ -86,14 +86,66 @@ type HasPropertyOfType<TObject extends object, TProperty> = {
|
|
|
86
86
|
[K in keyof TObject as TObject[K] extends TProperty ? K : never]: unknown;
|
|
87
87
|
} extends infer R ? {} extends R ? false : true : never;
|
|
88
88
|
|
|
89
|
+
/**
|
|
90
|
+
* Набор политик, управляющих доступностью смены значения контрола.
|
|
91
|
+
*
|
|
92
|
+
* @since 0.2.0
|
|
93
|
+
*
|
|
94
|
+
**/
|
|
95
|
+
declare enum ChangePolicies {
|
|
96
|
+
/**
|
|
97
|
+
* Политика по умолчанию.
|
|
98
|
+
*
|
|
99
|
+
* - Применяет {@link Public} к контролам типа `switch`, `pushbutton`, `range` и `rgb`;
|
|
100
|
+
*
|
|
101
|
+
* - Применяет {@link Script} к остальным типам контролов.
|
|
102
|
+
*
|
|
103
|
+
**/
|
|
104
|
+
Default = "default",
|
|
105
|
+
/**
|
|
106
|
+
* Установка значения возможна как скриптами wb-rules, так и сторонними службами.
|
|
107
|
+
*
|
|
108
|
+
* Применимо к контролам виртуальных устройств.
|
|
109
|
+
*
|
|
110
|
+
**/
|
|
111
|
+
Public = "public",
|
|
112
|
+
/**
|
|
113
|
+
* Установка значения возможна только скриптами wb-rules.
|
|
114
|
+
*
|
|
115
|
+
* Применимо к контролам виртуальных устройств.
|
|
116
|
+
*
|
|
117
|
+
**/
|
|
118
|
+
Script = "script",
|
|
119
|
+
/**
|
|
120
|
+
* Полный запрет записи, значение доступно только для чтения.
|
|
121
|
+
*
|
|
122
|
+
* Применимо к контролам реальных устройств.
|
|
123
|
+
*
|
|
124
|
+
**/
|
|
125
|
+
ReadOnly = "read-only"
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Определяет политику установки значений реальных устройств.
|
|
129
|
+
*
|
|
130
|
+
* @since 0.2.0
|
|
131
|
+
*
|
|
132
|
+
**/
|
|
133
|
+
type ChangePolicy = `${Exclude<ChangePolicies, ChangePolicies.Public | ChangePolicies.Script>}`;
|
|
134
|
+
/**
|
|
135
|
+
* Определяет политику установки значений контролов виртуальных устройств.
|
|
136
|
+
*
|
|
137
|
+
* @since 0.2.0
|
|
138
|
+
*
|
|
139
|
+
**/
|
|
140
|
+
type VirtualChangePolicy = `${Exclude<ChangePolicies, ChangePolicies.ReadOnly>}`;
|
|
89
141
|
type ValueEventHandler<TValue> = (newValue: TValue, oldValue: TValue) => void;
|
|
90
142
|
interface Control<TValue> {
|
|
91
143
|
/** Актуальное значение контрола. */
|
|
92
144
|
value: TValue;
|
|
93
145
|
/** Событие, происходящее когда поступило новое значение. */
|
|
94
|
-
|
|
146
|
+
onValueReceived: OnEvent<ValueEventHandler<TValue>>;
|
|
95
147
|
/** Событие, происходящее когда значение изменилось. */
|
|
96
|
-
|
|
148
|
+
onValueChanged: OnEvent<ValueEventHandler<TValue>>;
|
|
97
149
|
}
|
|
98
150
|
type MaybeReadonlyControl<TValue, TReadonly extends boolean | undefined> = ReadonlyPropWhen<Control<TValue>, 'value', TReadonly>;
|
|
99
151
|
|
|
@@ -117,8 +169,8 @@ type VirtualTypeMapper<K extends keyof WbRules.TypeMappings = keyof WbRules.Type
|
|
|
117
169
|
interface BaseControlDef {
|
|
118
170
|
/** Идентификатор контрола. Если не указан, используется название свойства. */
|
|
119
171
|
controlId?: string;
|
|
120
|
-
/**
|
|
121
|
-
|
|
172
|
+
/** Политика доступа на запись значения. */
|
|
173
|
+
changePolicy?: VirtualChangePolicy | ChangePolicy;
|
|
122
174
|
}
|
|
123
175
|
/**
|
|
124
176
|
* Определения основных контролов.
|
|
@@ -166,7 +218,7 @@ type StrictVirtualControls<TControls extends VirtualControls> = TControls & Virt
|
|
|
166
218
|
* при описании устройства в `defineDevice()`.
|
|
167
219
|
**/
|
|
168
220
|
type CreatedControls<TControls extends Controls | VirtualControls> = {
|
|
169
|
-
[K in keyof TControls]: Expand<MaybeReadonlyControl<StrictWhenSpecified<TControls[K], 'defaultValue', WbRules.TypeMappings[TControls[K]['type']]>, TControls[K]['
|
|
221
|
+
[K in keyof TControls]: Expand<MaybeReadonlyControl<StrictWhenSpecified<TControls[K], 'defaultValue', WbRules.TypeMappings[TControls[K]['type']]>, TControls[K]['changePolicy'] extends ChangePolicies.ReadOnly ? true : false>>;
|
|
170
222
|
};
|
|
171
223
|
/** Используется для извлечения типа значения из значения по умолчанию. */
|
|
172
224
|
type InferDefaultType<TProp> = [TProp] extends [{
|
|
@@ -431,5 +483,5 @@ declare function getControlSafe(context: DeviceContext, controlId: string): Cont
|
|
|
431
483
|
**/
|
|
432
484
|
declare function getControlSafe(deviceId: string, controlId: string, isReadyFunc: () => boolean): ControlSafe;
|
|
433
485
|
|
|
434
|
-
export { defineVirtualDevice, defineWiredDevice, defineZigbeeDevice, getControlSafe, getDeviceSafe };
|
|
486
|
+
export { ChangePolicies, defineVirtualDevice, defineWiredDevice, defineZigbeeDevice, getControlSafe, getDeviceSafe };
|
|
435
487
|
export type { ControlSafe, DeviceContext, DeviceType, PropType, TrackCallback };
|
package/dist/index.mjs
CHANGED
|
@@ -23,6 +23,45 @@ function getControlSafe(context, controlId, isReadyFunc = () => true) {
|
|
|
23
23
|
};
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
/**
|
|
27
|
+
* Набор политик, управляющих доступностью смены значения контрола.
|
|
28
|
+
*
|
|
29
|
+
* @since 0.2.0
|
|
30
|
+
*
|
|
31
|
+
**/
|
|
32
|
+
var ChangePolicies;
|
|
33
|
+
(function (ChangePolicies) {
|
|
34
|
+
/**
|
|
35
|
+
* Политика по умолчанию.
|
|
36
|
+
*
|
|
37
|
+
* - Применяет {@link Public} к контролам типа `switch`, `pushbutton`, `range` и `rgb`;
|
|
38
|
+
*
|
|
39
|
+
* - Применяет {@link Script} к остальным типам контролов.
|
|
40
|
+
*
|
|
41
|
+
**/
|
|
42
|
+
ChangePolicies["Default"] = "default";
|
|
43
|
+
/**
|
|
44
|
+
* Установка значения возможна как скриптами wb-rules, так и сторонними службами.
|
|
45
|
+
*
|
|
46
|
+
* Применимо к контролам виртуальных устройств.
|
|
47
|
+
*
|
|
48
|
+
**/
|
|
49
|
+
ChangePolicies["Public"] = "public";
|
|
50
|
+
/**
|
|
51
|
+
* Установка значения возможна только скриптами wb-rules.
|
|
52
|
+
*
|
|
53
|
+
* Применимо к контролам виртуальных устройств.
|
|
54
|
+
*
|
|
55
|
+
**/
|
|
56
|
+
ChangePolicies["Script"] = "script";
|
|
57
|
+
/**
|
|
58
|
+
* Полный запрет записи, значение доступно только для чтения.
|
|
59
|
+
*
|
|
60
|
+
* Применимо к контролам реальных устройств.
|
|
61
|
+
*
|
|
62
|
+
**/
|
|
63
|
+
ChangePolicies["ReadOnly"] = "read-only";
|
|
64
|
+
})(ChangePolicies || (ChangePolicies = {}));
|
|
26
65
|
const typeMappings = {
|
|
27
66
|
'text': 'string',
|
|
28
67
|
'value': 'number',
|
|
@@ -35,10 +74,11 @@ const typeMappings = {
|
|
|
35
74
|
/**
|
|
36
75
|
* Создаёт контрол устройства.
|
|
37
76
|
* @since 0.1.0
|
|
77
|
+
*
|
|
38
78
|
**/
|
|
39
79
|
function createControl(context, controlId, options) {
|
|
40
80
|
const { deviceType, deviceId } = context;
|
|
41
|
-
const { type,
|
|
81
|
+
const { type, changePolicy = ChangePolicies.Default } = options;
|
|
42
82
|
const defaultValue = 'defaultValue' in options
|
|
43
83
|
? options['defaultValue']
|
|
44
84
|
: void 0;
|
|
@@ -61,6 +101,7 @@ function createControl(context, controlId, options) {
|
|
|
61
101
|
* Устанавливает новое значение, если оно отличается от существующего.
|
|
62
102
|
* @param newValue Устанавливаемое значение.
|
|
63
103
|
* @param preventEmit Предотвращает отправку значения в устройство.
|
|
104
|
+
*
|
|
64
105
|
**/
|
|
65
106
|
function setValue(newValue, preventEmit = false) {
|
|
66
107
|
const oldValue = localValue;
|
|
@@ -102,16 +143,14 @@ function createControl(context, controlId, options) {
|
|
|
102
143
|
return localValue;
|
|
103
144
|
},
|
|
104
145
|
set value(newValue) {
|
|
105
|
-
if (
|
|
106
|
-
log.warning(`
|
|
146
|
+
if (changePolicy === ChangePolicies.ReadOnly) {
|
|
147
|
+
log.warning(`A new value of '${deviceId}/${controlId}' has been rejected: control is readonly.`);
|
|
107
148
|
return;
|
|
108
149
|
}
|
|
109
150
|
setValue(newValue);
|
|
110
151
|
},
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
valueChanged: valueChanged
|
|
114
|
-
.withoutRaise(),
|
|
152
|
+
onValueReceived: valueReceived.on,
|
|
153
|
+
onValueChanged: valueChanged.on,
|
|
115
154
|
};
|
|
116
155
|
}
|
|
117
156
|
|
|
@@ -141,6 +180,9 @@ function createContext(deviceType, deviceId, state) {
|
|
|
141
180
|
};
|
|
142
181
|
return context;
|
|
143
182
|
}
|
|
183
|
+
const extendWithReadonly = (changePolicy) => changePolicy && changePolicy !== ChangePolicies.Default
|
|
184
|
+
? { readonly: changePolicy === ChangePolicies.Script || changePolicy === ChangePolicies.ReadOnly }
|
|
185
|
+
: {};
|
|
144
186
|
function configureControls(deviceId, controls) {
|
|
145
187
|
const device = getDevice(deviceId);
|
|
146
188
|
if (!device)
|
|
@@ -154,8 +196,7 @@ function configureControls(deviceId, controls) {
|
|
|
154
196
|
device.removeControl(controlId);
|
|
155
197
|
device.addControl(controlId, assign({}, control, {
|
|
156
198
|
value: control.defaultValue,
|
|
157
|
-
|
|
158
|
-
}));
|
|
199
|
+
}, extendWithReadonly(control.changePolicy)));
|
|
159
200
|
});
|
|
160
201
|
}
|
|
161
202
|
function configureContext(type, deviceId, controls, title) {
|
|
@@ -182,9 +223,10 @@ function configureContext(type, deviceId, controls, title) {
|
|
|
182
223
|
if (type === 'virtual') {
|
|
183
224
|
const cells = {};
|
|
184
225
|
Object.keys(controls).forEach((key) => {
|
|
185
|
-
const
|
|
186
|
-
|
|
187
|
-
|
|
226
|
+
const control = controls[key];
|
|
227
|
+
const cell = assign({}, control, {
|
|
228
|
+
value: control['defaultValue'],
|
|
229
|
+
}, extendWithReadonly(control['changePolicy']));
|
|
188
230
|
cells[key] = cell;
|
|
189
231
|
});
|
|
190
232
|
global.defineVirtualDevice(deviceId, {
|
|
@@ -219,8 +261,8 @@ function createDevice(deviceType, deviceId, propDefs, props, options) {
|
|
|
219
261
|
const controlId = controlDef.controlId ?? key;
|
|
220
262
|
const control = createControl({ deviceType, deviceId, isReady: true }, controlId, {
|
|
221
263
|
type: controlDef.type,
|
|
264
|
+
changePolicy: controlDef.changePolicy ?? ChangePolicies.Default,
|
|
222
265
|
defaultValue: controlDef.defaultValue,
|
|
223
|
-
isReadonly: controlDef.isReadonly,
|
|
224
266
|
forceDefault: controlDef.forceDefault,
|
|
225
267
|
lazyInit: controlDef.lazyInit,
|
|
226
268
|
});
|
|
@@ -322,4 +364,4 @@ function getDeviceSafe(deviceId, isReadyFunc = () => true) {
|
|
|
322
364
|
};
|
|
323
365
|
}
|
|
324
366
|
|
|
325
|
-
export { defineVirtualDevice, defineWiredDevice, defineZigbeeDevice, getControlSafe, getDeviceSafe };
|
|
367
|
+
export { ChangePolicies, defineVirtualDevice, defineWiredDevice, defineZigbeeDevice, getControlSafe, getDeviceSafe };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mirta",
|
|
3
3
|
"description": "The powerful framework to write smart home automation scripts.",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.2.0",
|
|
5
5
|
"license": "Unlicense",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"mirta",
|
|
@@ -36,9 +36,9 @@
|
|
|
36
36
|
"url": "https://pay.cloudtips.ru/p/58512cca"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@mirta/
|
|
40
|
-
"@mirta/
|
|
41
|
-
"@mirta/
|
|
39
|
+
"@mirta/globals": "0.2.0",
|
|
40
|
+
"@mirta/basics": "0.2.0",
|
|
41
|
+
"@mirta/polyfills": "0.2.0"
|
|
42
42
|
},
|
|
43
43
|
"publishConfig": {
|
|
44
44
|
"access": "public"
|