@deconz-community/ddf-validator 2.17.0 → 2.19.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.
@@ -1,62 +1,63 @@
1
1
  import { z as e } from "zod";
2
- const E = "2.17.0", y = {
2
+ const M = "2.19.0", O = {
3
3
  "devcap1.schema.json": [
4
- O,
5
- _,
6
- $,
7
- w,
8
- C
4
+ z,
5
+ P,
6
+ W,
7
+ L,
8
+ N,
9
+ Y
9
10
  ],
10
11
  "constants2.schema.json": [
11
- T
12
+ R
12
13
  ]
13
14
  };
14
- function O(t, a, u) {
15
- const o = typeof t.manufacturername == "string" && typeof t.modelid == "string";
16
- if (o)
15
+ function z(t, r, u) {
16
+ const i = typeof t.manufacturername == "string" && typeof t.modelid == "string";
17
+ if (i)
17
18
  return;
18
- const d = Array.isArray(t.manufacturername) && Array.isArray(t.modelid);
19
- if (d && t.manufacturername.length !== t.modelid.length) {
20
- a.addIssue({
19
+ const c = Array.isArray(t.manufacturername) && Array.isArray(t.modelid);
20
+ if (c && t.manufacturername.length !== t.modelid.length) {
21
+ r.addIssue({
21
22
  code: e.ZodIssueCode.invalid_intersection_types,
22
23
  message: "When 'manufacturername' and 'modelid' are both arrays they should be the same length",
23
24
  path: ["manufacturername", "modelid"]
24
25
  });
25
26
  return;
26
27
  }
27
- (o || d) === !1 && a.addIssue({
28
+ (i || c) === !1 && r.addIssue({
28
29
  code: e.ZodIssueCode.invalid_intersection_types,
29
30
  message: "Invalid properties 'manufacturername' and 'modelid' should have the same type",
30
31
  path: ["manufacturername", "modelid"]
31
32
  });
32
33
  }
33
- function _(t, a, u) {
34
+ function P(t, r, u) {
34
35
  if (!t.bindings)
35
36
  return;
36
- const o = (i) => `0x${(typeof i == "number" ? i : Number.parseInt(i, 16)).toString(16)}`, d = {};
37
- t.bindings.forEach((i) => {
38
- i.bind === "unicast" && i.report && i.report.forEach((l) => {
39
- l.max !== 65535 && (d[`${o(i["src.ep"])}.${o(i.cl)}.${o(l.at)}`] = l.max);
37
+ const i = (n) => `0x${(typeof n == "number" ? n : Number.parseInt(n, 16)).toString(16)}`, c = {};
38
+ t.bindings.forEach((n) => {
39
+ n.bind === "unicast" && n.report && n.report.forEach((d) => {
40
+ d.max !== 65535 && (c[`${i(n["src.ep"])}.${i(n.cl)}.${i(d.at)}`] = d.max);
40
41
  });
41
- }), t.subdevices.forEach((i, l) => {
42
- i.items.forEach((s, n) => {
43
- var c;
44
- if (s["refresh.interval"] && s.read && s.read.fn === "zcl") {
45
- const b = o(s.read.ep ?? ((c = i.fingerprint) == null ? void 0 : c.endpoint) ?? i.uuid[1]), h = Array.isArray(s.read.at) ? s.read.at : [s.read.at];
46
- for (let v = 0; v < h.length; v++) {
47
- const g = `${b}.${o(s.read.cl)}.${o(h[v])}`;
48
- d[g] !== void 0 && s["refresh.interval"] - 60 < d[g] && a.addIssue({
42
+ }), t.subdevices.forEach((n, d) => {
43
+ n.items.forEach((a, m) => {
44
+ var s;
45
+ if (a["refresh.interval"] && a.read && a.read.fn === "zcl:attr" && a.read.at) {
46
+ const o = i(a.read.ep ?? ((s = n.fingerprint) == null ? void 0 : s.endpoint) ?? n.uuid[1]), p = Array.isArray(a.read.at) ? a.read.at : [a.read.at];
47
+ for (let b = 0; b < p.length; b++) {
48
+ const h = `${o}.${i(a.read.cl)}.${i(p[b])}`;
49
+ c[h] !== void 0 && a["refresh.interval"] - 60 < c[h] && r.addIssue({
49
50
  code: e.ZodIssueCode.custom,
50
- message: `The refresh interval (${s["refresh.interval"]} - 60 = ${s["refresh.interval"] - 60}) should be greater than the binding max refresh value (${d[g]}) with a margin of 60 seconds`,
51
- path: ["subdevices", l, "items", n, "refresh.interval"]
51
+ message: `The refresh interval (${a["refresh.interval"]} - 60 = ${a["refresh.interval"] - 60}) should be greater than the binding max refresh value (${c[h]}) with a margin of 60 seconds`,
52
+ path: ["subdevices", d, "items", m, "refresh.interval"]
52
53
  });
53
54
  }
54
55
  }
55
56
  });
56
57
  });
57
58
  }
58
- function $(t, a, u) {
59
- const o = [
59
+ function W(t, r, u) {
60
+ const i = [
60
61
  /*
61
62
  {
62
63
  description: 'a device should always have basic attributes.',
@@ -146,88 +147,100 @@ function $(t, a, u) {
146
147
  }
147
148
  }
148
149
  }
149
- ], d = (i, l) => typeof i == "string" ? l(i) : Array.isArray(i) ? i.every((s) => d(s, l)) : "and" in i ? i.and.every((s) => d(s, l)) : "or" in i ? i.or.some((s) => d(s, l)) : !1;
150
- t.subdevices.forEach((i, l) => {
151
- const s = i.items.map((n) => n.name);
152
- o.forEach((n) => {
153
- (Object.keys(n.if).length === 0 || Object.entries(n.if).some(([c, b]) => {
154
- switch (c) {
150
+ ], c = (n, d) => typeof n == "string" ? d(n) : Array.isArray(n) ? n.every((a) => c(a, d)) : "and" in n ? n.and.every((a) => c(a, d)) : "or" in n ? n.or.some((a) => c(a, d)) : !1;
151
+ t.subdevices.forEach((n, d) => {
152
+ const a = n.items.map((m) => m.name);
153
+ i.forEach((m) => {
154
+ (Object.keys(m.if).length === 0 || Object.entries(m.if).some(([s, o]) => {
155
+ switch (s) {
155
156
  case "type":
156
- return d(b, (h) => h === i.type);
157
+ return c(o, (p) => p === n.type);
157
158
  case "item":
158
- return d(b, (h) => s.includes(h));
159
+ return c(o, (p) => a.includes(p));
159
160
  default:
160
161
  return !1;
161
162
  }
162
- })) && (d(n.need.item, (c) => s.includes(c)) || a.addIssue({
163
+ })) && (c(m.need.item, (s) => a.includes(s)) || r.addIssue({
163
164
  code: e.ZodIssueCode.custom,
164
- message: `The device is missing some items because ${n.description}`,
165
- path: ["subdevices", l, "items"]
165
+ message: `The device is missing some items because ${m.description}`,
166
+ path: ["subdevices", d, "items"]
166
167
  }));
167
168
  });
168
169
  });
169
170
  }
170
- function w(t, a, u) {
171
- const o = ["parse", "write"];
172
- t.subdevices.forEach((d, i) => {
173
- d.items.forEach((l, s) => {
174
- o.forEach((n) => {
175
- const c = l[n];
176
- c !== void 0 && (c.fn === void 0 || c.fn === "zcl" || c.fn === "zcl:attr" || c.fn === "zcl:cmd") && (c.eval === void 0 && c.script === void 0 && a.addIssue({
171
+ function L(t, r, u) {
172
+ const i = ["parse", "write"];
173
+ t.subdevices.forEach((c, n) => {
174
+ c.items.forEach((d, a) => {
175
+ i.forEach((m) => {
176
+ const s = d[m];
177
+ s !== void 0 && (s.fn === void 0 || s.fn === "zcl:attr" || s.fn === "zcl:cmd") && (s.eval === void 0 && s.script === void 0 && r.addIssue({
177
178
  code: e.ZodIssueCode.custom,
178
- message: `The '${n}' function is missing 'eval' or 'script' option.`,
179
- path: ["subdevices", i, "items", s, n]
180
- }), c.eval !== void 0 && c.script !== void 0 && a.addIssue({
179
+ message: `The '${m}' function is missing 'eval' or 'script' option.`,
180
+ path: ["subdevices", n, "items", a, m]
181
+ }), s.eval !== void 0 && s.script !== void 0 && r.addIssue({
181
182
  code: e.ZodIssueCode.custom,
182
- message: `The '${n}' function is having both 'eval' and 'script' option.`,
183
- path: ["subdevices", i, "items", s, n]
183
+ message: `The '${m}' function is having both 'eval' and 'script' option.`,
184
+ path: ["subdevices", n, "items", a, m]
184
185
  }));
185
186
  });
186
187
  });
187
188
  });
188
189
  }
189
- function T(t, a, u) {
190
- const o = I();
191
- Object.keys(t).forEach((d) => {
192
- if (!Object.keys(o.shape).includes(d)) {
193
- if (!["$MF_", "$TYPE_"].some((i) => d.startsWith(i))) {
194
- a.addIssue({
190
+ function R(t, r, u) {
191
+ const i = C();
192
+ Object.keys(t).forEach((c) => {
193
+ if (!Object.keys(i.shape).includes(c)) {
194
+ if (!["$MF_", "$TYPE_"].some((n) => c.startsWith(n))) {
195
+ r.addIssue({
195
196
  code: e.ZodIssueCode.custom,
196
197
  message: "The constant key should start with '$MF_' or '$TYPE_'",
197
- path: [d]
198
+ path: [c]
198
199
  });
199
200
  return;
200
201
  }
201
- typeof t[d] != "string" && a.addIssue({
202
+ typeof t[c] != "string" && r.addIssue({
202
203
  code: e.ZodIssueCode.custom,
203
204
  message: "The constant value should be a string",
204
- path: [d]
205
+ path: [c]
205
206
  });
206
207
  }
207
208
  });
208
209
  }
209
- function C(t, a, u) {
210
- t.subdevices.forEach((o, d) => {
211
- const i = u.subDevices[o.type];
212
- if (!i) {
213
- a.addIssue({
210
+ function N(t, r, u) {
211
+ t.subdevices.forEach((i, c) => {
212
+ const n = u.subDevices[i.type];
213
+ if (!n) {
214
+ r.addIssue({
214
215
  code: e.ZodIssueCode.custom,
215
- message: `The device is missing the device definition for the type "${o.type}"`,
216
- path: ["subdevices", d, "items"]
216
+ message: `The device is missing the device definition for the type "${i.type}"`,
217
+ path: ["subdevices", c, "items"]
217
218
  });
218
219
  return;
219
220
  }
220
- let l = i.items;
221
- i.items_optional && (l = l.filter((s) => !i.items_optional.includes(s))), l.forEach((s) => {
222
- o.items.find((n) => n.name === s) || a.addIssue({
221
+ let d = n.items;
222
+ n.items_optional && (d = d.filter((a) => !n.items_optional.includes(a))), d.forEach((a) => {
223
+ i.items.find((m) => m.name === a) || r.addIssue({
223
224
  code: e.ZodIssueCode.custom,
224
- message: `The device should have the item "${s}" because it is mandatory for devices of type "${o.type}"`,
225
- path: ["subdevices", d, "items"]
225
+ message: `The device should have the item "${a}" because it is mandatory for devices of type "${i.type}"`,
226
+ path: ["subdevices", c, "items"]
226
227
  });
227
228
  });
228
229
  });
229
230
  }
230
- function A(t) {
231
+ function Y(t, r, u) {
232
+ t.subdevices.forEach((i, c) => {
233
+ const n = i.items.map((d) => d.name);
234
+ i.items.forEach((d, a) => {
235
+ d.parse && d.parse.fn === "numtostr" && (n.includes(d.parse.srcitem) || r.addIssue({
236
+ code: e.ZodIssueCode.custom,
237
+ message: `The device should have the item "${d.parse.srcitem}" because it is used in the 'numtostr' function`,
238
+ path: ["subdevices", c, "items", a, "parse", "srcitem"]
239
+ }));
240
+ });
241
+ });
242
+ }
243
+ function B(t) {
231
244
  return e.strictObject({
232
245
  $schema: e.optional(e.string()),
233
246
  schema: e.literal("constants1.schema.json"),
@@ -235,100 +248,92 @@ function A(t) {
235
248
  "device-types": e.record(e.string().startsWith("$TYPE_"), e.string())
236
249
  });
237
250
  }
238
- function I(t) {
251
+ function C(t) {
239
252
  return e.object({
240
253
  $schema: e.optional(e.string()),
241
254
  schema: e.literal("constants2.schema.json")
242
255
  }).passthrough();
243
256
  }
244
- function M() {
257
+ function U() {
245
258
  return e.string().regex(
246
259
  // Regex for AAAA-MM-JJ
247
260
  /^(\d{4})-(?:(?:0[1-9])|(?:1[0-2]))-(?:(?:0[1-9])|(?:[12][0-9])|(?:3[01]))$/,
248
261
  "Invalid date value"
249
262
  );
250
263
  }
251
- function r(t = void 0) {
252
- const a = "Invalid hexadecimal value";
253
- return t === void 0 ? e.string().regex(/^0x[0-9a-fA-F]+$/, a) : e.string().regex(new RegExp(`^0x[0-9a-fA-F]{${t}}$`), a);
264
+ function l(t = void 0) {
265
+ const r = "Invalid hexadecimal value";
266
+ return t === void 0 ? e.string().regex(/^0x[0-9a-fA-F]+$/, r) : e.string().regex(new RegExp(`^0x[0-9a-fA-F]{${t}}$`), r);
254
267
  }
255
- function m() {
268
+ function g() {
256
269
  return e.union([
257
- r(2),
270
+ l(2),
258
271
  e.number().min(0).max(255)
259
272
  ]);
260
273
  }
261
- function S() {
274
+ function k() {
262
275
  return e.custom((t) => {
263
276
  if (!Array.isArray(t) || t.length % 2 !== 0)
264
277
  return !1;
265
- for (let a = 0; a < t.length; a += 2) {
266
- const u = t[a], o = t[a + 1];
267
- if (typeof u != "number" || typeof o != "string")
278
+ for (let r = 0; r < t.length; r += 2) {
279
+ const u = t[r], i = t[r + 1];
280
+ if (typeof u != "number" || typeof i != "string")
268
281
  return !1;
269
282
  }
270
283
  return !0;
271
284
  }, "The value must be an array with an even number of values and alternating between number and string.");
272
285
  }
273
- function j() {
286
+ function S() {
274
287
  return e.union([
275
288
  e.tuple([
276
289
  e.literal("$address.ext"),
277
- r(2)
290
+ l(2)
278
291
  ]),
279
292
  e.tuple([
280
293
  e.literal("$address.ext"),
281
- r(2),
282
- r(4)
294
+ l(2),
295
+ l(4)
283
296
  ])
284
297
  ]);
285
298
  }
286
- function f() {
299
+ function A() {
287
300
  return e.string();
288
301
  }
289
- function p() {
302
+ function F() {
290
303
  return e.string();
291
304
  }
292
- function J() {
305
+ const x = e.strictObject({
306
+ ep: e.optional(g()).describe("Endpoint, 255 means any endpoint, 0 means auto selected from subdevice."),
307
+ cl: l(4).describe("Cluster ID."),
308
+ at: e.optional(l(4).or(e.array(l(4)))).describe("Attribute ID."),
309
+ mf: e.optional(l(4)).describe("Manufacturer code, must be set to 0x0000 for non manufacturer specific commands."),
310
+ cmd: e.optional(l(2)).describe("Zigbee command."),
311
+ eval: e.optional(F()).describe("Javascript expression to transform the attribute value to the Item value."),
312
+ script: e.optional(A()).describe("Relative path of a Javascript .js file.")
313
+ }), f = {
314
+ read: x.extend({
315
+ fc: e.optional(l(2).or(e.number())).describe("Zigbee command frame control.")
316
+ }),
317
+ parse: x.extend({}),
318
+ write: x.extend({
319
+ "state.timeout": e.optional(e.number()),
320
+ "change.timeout": e.optional(e.number()),
321
+ dt: e.optional(l(2)).describe("Data type.")
322
+ })
323
+ };
324
+ function V() {
293
325
  return e.discriminatedUnion("fn", [
294
326
  e.strictObject({
295
327
  fn: e.literal("none")
296
328
  }),
297
- e.strictObject({
298
- fn: e.undefined().describe("Generic function to read ZCL attributes."),
299
- at: r(4).or(e.array(r(4))).describe("Attribute ID."),
300
- cl: r(4).describe("Cluster ID."),
301
- ep: e.optional(m()).describe("Endpoint, 255 means any endpoint, 0 means auto selected from subdevice."),
302
- mf: e.optional(r(4)).describe("Manufacturer code, must be set to 0x0000 for non manufacturer specific commands."),
303
- eval: e.optional(p()).describe("Javascript expression to transform the raw value.")
329
+ f.read.extend({
330
+ fn: e.undefined().describe("Generic function to read ZCL attributes.")
304
331
  }),
305
- e.strictObject({
306
- fn: e.literal("zcl").describe("Generic function to read ZCL attributes."),
307
- at: r(4).or(e.array(r(4))).describe("Attribute ID."),
308
- cl: r(4).describe("Cluster ID."),
309
- ep: e.optional(m()).describe("Endpoint, 255 means any endpoint, 0 means auto selected from subdevice."),
310
- mf: e.optional(r(4)).describe("Manufacturer code, must be set to 0x0000 for non manufacturer specific commands."),
311
- eval: e.optional(p()).describe("Javascript expression to transform the raw value."),
312
- script: e.optional(f()).describe("Relative path of a Javascript .js file.")
313
- }).describe("Deprecated"),
314
- e.strictObject({
315
- fn: e.literal("zcl:attr").describe("Generic function to parse ZCL values from read/report commands."),
316
- at: r(4).or(e.array(r(4))).describe("String hex value or array of string hex values."),
317
- cl: r(4).describe("Cluster ID."),
318
- ep: e.optional(m()).describe("Endpoint, 255 means any endpoint, 0 means auto selected from subdevice."),
319
- mf: e.optional(r(4)).describe("Manufacturer code, must be set to 0x0000 for non manufacturer specific commands."),
320
- eval: e.optional(p()).describe("Javascript expression to transform the attribute value to the Item value."),
321
- script: e.optional(f()).describe("Relative path of a Javascript .js file.")
332
+ f.read.extend({
333
+ fn: e.literal("zcl:attr").describe("Generic function to parse ZCL values from read/report commands.")
322
334
  }),
323
- e.strictObject({
324
- fn: e.literal("zcl:cmd").describe("Generic function to parse ZCL values from read/report commands."),
325
- cl: r(4).describe("Cluster ID."),
326
- ep: e.optional(m()).describe("Endpoint, 255 means any endpoint, 0 means auto selected from subdevice."),
327
- mf: e.optional(r(4)).describe("Manufacturer code, must be set to 0x0000 for non manufacturer specific commands."),
328
- cmd: e.optional(r(2)).describe("Zigbee command."),
329
- eval: e.optional(p()).describe("Javascript expression to transform the attribute value to the Item value."),
330
- fc: e.optional(r(2).or(e.number())).describe("Zigbee command frame control."),
331
- script: e.optional(f()).describe("Relative path of a Javascript .js file.")
335
+ f.read.extend({
336
+ fn: e.literal("zcl:cmd").describe("Generic function to parse ZCL values from read/report commands.")
332
337
  }),
333
338
  e.strictObject({
334
339
  fn: e.literal("tuya").describe("Generic function to read all Tuya datapoints. It has no parameters.")
@@ -337,47 +342,17 @@ function J() {
337
342
  message: "eval and script should not both be present"
338
343
  });
339
344
  }
340
- function Z() {
345
+ function q(t) {
341
346
  return e.discriminatedUnion("fn", [
342
- e.strictObject({
343
- fn: e.undefined().describe("Generic function to parse ZCL attributes and commands."),
344
- at: e.optional(r(4).or(e.array(r(4)))).describe("Attribute ID."),
345
- cl: r(4).describe("Cluster ID."),
346
- cppsrc: e.optional(e.string()),
347
- ep: e.optional(m()).describe("Endpoint, 255 means any endpoint, 0 means auto selected from subdevice."),
348
- cmd: e.optional(r(2)).describe("Zigbee command."),
349
- mf: e.optional(r(4)).describe("Manufacturer code, must be set to 0x0000 for non manufacturer specific commands."),
350
- eval: e.optional(p()).describe("Javascript expression to transform the raw value."),
351
- script: e.optional(f()).describe("Relative path of a Javascript .js file.")
347
+ f.parse.extend({
348
+ fn: e.undefined().describe("Generic function to read ZCL attributes."),
349
+ cppsrc: e.optional(e.string())
352
350
  }),
353
- e.strictObject({
354
- fn: e.literal("zcl").describe("Generic function to parse ZCL attributes and commands."),
355
- at: e.optional(r(4).or(e.array(r(4)))).describe("Attribute ID."),
356
- cl: r(4).describe("Cluster ID."),
357
- cppsrc: e.optional(e.string()),
358
- ep: e.optional(m()).describe("Endpoint, 255 means any endpoint, 0 means auto selected from subdevice."),
359
- cmd: e.optional(r(2)).describe("Zigbee command."),
360
- mf: e.optional(r(4)).describe("Manufacturer code, must be set to 0x0000 for non manufacturer specific commands."),
361
- eval: e.optional(p()).describe("Javascript expression to transform the raw value."),
362
- script: e.optional(f()).describe("Relative path of a Javascript .js file.")
363
- }).describe("Deprecated"),
364
- e.strictObject({
365
- fn: e.literal("zcl:attr").describe("Generic function to parse ZCL values from read/report commands."),
366
- at: r(4).or(e.array(r(4))).describe("String hex value or array of string hex values."),
367
- cl: r(4).describe("Cluster ID."),
368
- ep: e.optional(m()).describe("Endpoint, 255 means any endpoint, 0 means auto selected from subdevice."),
369
- mf: e.optional(r(4)).describe("Manufacturer code, must be set to 0x0000 for non manufacturer specific commands."),
370
- eval: e.optional(p()).describe("Javascript expression to transform the attribute value to the Item value."),
371
- script: e.optional(f()).describe("Relative path of a Javascript .js file.")
351
+ f.parse.extend({
352
+ fn: e.literal("zcl:attr").describe("Generic function to parse ZCL values from read/report commands.")
372
353
  }),
373
- e.strictObject({
374
- fn: e.literal("zcl:cmd").describe("Generic function to parse ZCL values from read/report commands."),
375
- cl: r(4).describe("Cluster ID."),
376
- ep: e.optional(m()).describe("Endpoint, 255 means any endpoint, 0 means auto selected from subdevice."),
377
- mf: e.optional(r(4)).describe("Manufacturer code, must be set to 0x0000 for non manufacturer specific commands."),
378
- cmd: e.optional(r(2)).describe("Zigbee command."),
379
- eval: e.optional(p()).describe("Javascript expression to transform the attribute value to the Item value."),
380
- script: e.optional(f()).describe("Relative path of a Javascript .js file.")
354
+ f.parse.extend({
355
+ fn: e.literal("zcl:cmd").describe("Generic function to parse ZCL values from read/report commands.")
381
356
  }),
382
357
  e.strictObject({
383
358
  fn: e.literal("ias:zonestatus").describe("Generic function to parse IAS ZONE status change notifications or zone status from read/report command."),
@@ -385,102 +360,65 @@ function Z() {
385
360
  }),
386
361
  e.strictObject({
387
362
  fn: e.literal("numtostr").describe("Generic function to to convert number to string."),
388
- // TODO use generic
389
- srcitem: e.enum(["state/airqualityppb", "state/pm2_5"]).describe("The source item holding the number."),
363
+ srcitem: e.enum(t.attributes, {
364
+ errorMap: (r, u) => r.code === "invalid_enum_value" ? { message: `Invalid enum value. Expected item from generic attributes definition, received '${r.received}'` } : { message: u.defaultError }
365
+ }).describe("The source item holding the number."),
390
366
  op: e.enum(["lt", "le", "eq", "gt", "ge"]).describe("Comparison operator (lt | le | eq | gt | ge)"),
391
- to: S().describe("Array of (num, string) mappings")
367
+ to: k().describe("Array of (num, string) mappings")
392
368
  }),
393
369
  e.strictObject({
394
370
  fn: e.literal("time").describe("Specialized function to parse time, local and last set time from read/report commands of the time cluster and auto-sync time if needed.")
395
371
  }),
396
- e.strictObject({
372
+ f.parse.pick({
373
+ ep: !0,
374
+ at: !0,
375
+ mf: !0,
376
+ eval: !0,
377
+ script: !0
378
+ }).extend({
397
379
  fn: e.literal("xiaomi:special").describe("Generic function to parse custom Xiaomi attributes and commands."),
398
- ep: e.optional(m()).describe("Endpoint, 255 means any endpoint, 0 means auto selected from subdevice."),
399
- mf: e.optional(r(4)).describe("Manufacturer code, must be set to 0x0000 for non manufacturer specific commands."),
400
- at: e.optional(r(4)).describe("Attribute ID. The attribute to parse, shall be 0xff01, 0xff02 or 0x00f7"),
401
- idx: r(2).describe("A 8-bit string hex value."),
402
- eval: e.optional(p()).describe("Javascript expression to transform the raw value."),
403
- script: e.optional(f()).describe("Relative path of a Javascript .js file.")
380
+ idx: l(2).describe("A 8-bit string hex value.")
404
381
  }),
405
- e.strictObject({
382
+ f.parse.pick({ eval: !0, script: !0 }).extend({
406
383
  fn: e.literal("tuya").describe("Generic function to parse Tuya data."),
407
- dpid: e.number().describe("Data point ID. 1-255 the datapoint ID."),
408
- eval: e.optional(p()).describe("Javascript expression to transform the raw value."),
409
- script: e.optional(f()).describe("Relative path of a Javascript .js file.")
384
+ dpid: e.number().describe("Data point ID. 1-255 the datapoint ID.")
410
385
  })
411
- ]).refine((t) => !("eval" in t && "script" in t), {
386
+ ]).refine((r) => !("eval" in r && "script" in r), {
412
387
  message: "eval and script should not both be present"
413
388
  });
414
389
  }
415
- function G() {
390
+ function H() {
416
391
  return e.discriminatedUnion("fn", [
417
392
  e.strictObject({
418
393
  fn: e.literal("none")
419
394
  }),
420
- e.strictObject({
421
- fn: e.undefined(),
422
- at: e.optional(r(4).or(e.array(r(4)))).describe("Attribute ID."),
423
- "state.timeout": e.optional(e.number()),
424
- "change.timeout": e.optional(e.number()),
425
- cl: r(4).describe("Cluster ID."),
426
- dt: r(2).describe("Data type."),
427
- ep: e.optional(m()).describe("Endpoint, 255 means any endpoint, 0 means auto selected from subdevice."),
428
- mf: e.optional(r(4)).describe("Manufacturer code, must be set to 0x0000 for non manufacturer specific commands."),
429
- eval: e.optional(p()).describe("Javascript expression to transform the raw value."),
430
- script: e.optional(f()).describe("Relative path of a Javascript .js file.")
395
+ f.write.extend({
396
+ fn: e.undefined().describe("Generic function to read ZCL attributes."),
397
+ cppsrc: e.optional(e.string())
431
398
  }),
432
- e.strictObject({
433
- fn: e.literal("zcl"),
434
- at: e.optional(r(4).or(e.array(r(4)))).describe("Attribute ID."),
435
- "state.timeout": e.optional(e.number()),
436
- "change.timeout": e.optional(e.number()),
437
- cl: r(4).describe("Cluster ID."),
438
- dt: r(2).describe("Data type."),
439
- ep: e.optional(m()).describe("Endpoint, 255 means any endpoint, 0 means auto selected from subdevice."),
440
- mf: e.optional(r(4)).describe("Manufacturer code, must be set to 0x0000 for non manufacturer specific commands."),
441
- eval: e.optional(p()).describe("Javascript expression to transform the raw value."),
442
- script: e.optional(f()).describe("Relative path of a Javascript .js file.")
443
- }).describe("Deprecated"),
444
- e.strictObject({
445
- fn: e.literal("zcl:attr").describe("Generic function to parse ZCL values from read/report commands."),
446
- at: r(4).or(e.array(r(4))).describe("String hex value or array of string hex values."),
447
- "state.timeout": e.optional(e.number()),
448
- "change.timeout": e.optional(e.number()),
449
- cl: r(4).describe("Cluster ID."),
450
- dt: r(2).describe("Data type."),
451
- ep: e.optional(m()).describe("Endpoint, 255 means any endpoint, 0 means auto selected from subdevice."),
452
- mf: e.optional(r(4)).describe("Manufacturer code, must be set to 0x0000 for non manufacturer specific commands."),
453
- eval: e.optional(p()).describe("Javascript expression to transform the attribute value to the Item value."),
454
- script: e.optional(f()).describe("Relative path of a Javascript .js file.")
399
+ f.write.extend({
400
+ fn: e.literal("zcl:attr").describe("Generic function to parse ZCL values from read/report commands.")
455
401
  }),
456
- e.strictObject({
457
- fn: e.literal("zcl:cmd").describe("Generic function to parse ZCL values from read/report commands."),
458
- cl: r(4).describe("Cluster ID."),
459
- ep: e.optional(m()).describe("Endpoint, 255 means any endpoint, 0 means auto selected from subdevice."),
460
- mf: e.optional(r(4)).describe("Manufacturer code, must be set to 0x0000 for non manufacturer specific commands."),
461
- cmd: e.optional(r(2)).describe("Zigbee command."),
462
- eval: e.optional(p()).describe("Javascript expression to transform the attribute value to the Item value."),
463
- script: e.optional(f()).describe("Relative path of a Javascript .js file.")
402
+ f.write.extend({
403
+ fn: e.literal("zcl:cmd").describe("Generic function to parse ZCL values from read/report commands.")
464
404
  }),
465
- e.strictObject({
405
+ f.write.pick({ eval: !0, script: !0 }).extend({
466
406
  fn: e.literal("tuya").describe("Generic function to write Tuya data."),
467
407
  dpid: e.number().describe("Data point ID. 1-255 the datapoint ID."),
468
- dt: r(2).describe("Data type."),
469
- eval: e.optional(p()).describe("Javascript expression to transform the raw value."),
470
- script: e.optional(f()).describe("Relative path of a Javascript .js file.")
408
+ dt: l(2).describe("Data type.")
471
409
  })
472
410
  ]).refine((t) => !("eval" in t && "script" in t), {
473
411
  message: "eval and script should not both be present"
474
412
  });
475
413
  }
476
- function D(t) {
414
+ function Z(t) {
477
415
  return e.strictObject({
478
416
  $schema: e.optional(e.string()),
479
417
  schema: e.literal("resourceitem1.schema.json"),
480
418
  id: e.string(),
481
419
  description: e.optional(e.string()).describe("Item description, better to do not use it."),
482
420
  comment: e.optional(e.string()).describe("TODO: What is this ? What the difference with description ?"),
483
- deprecated: e.optional(M()).describe("Date of deprecation, if the item is deprecated, it's better to use the new one."),
421
+ deprecated: e.optional(U()).describe("Date of deprecation, if the item is deprecated, it's better to use the new one."),
484
422
  datatype: e.optional(e.enum([
485
423
  "String",
486
424
  "Bool",
@@ -505,9 +443,9 @@ function D(t) {
505
443
  static: e.optional(e.union([e.string(), e.number(), e.boolean()])).describe("A static default value is fixed and can be not changed."),
506
444
  range: e.optional(e.tuple([e.number(), e.number()])).describe("Values range limit."),
507
445
  virtual: e.optional(e.boolean()).describe("TODO: What is this ?"),
508
- read: e.optional(J()).describe("Fonction used to read value."),
509
- parse: e.optional(Z()).describe("Fonction used to parse incoming values."),
510
- write: e.optional(G()).describe("Fonction used to write value."),
446
+ read: e.optional(V()).describe("Fonction used to read value."),
447
+ parse: e.optional(q(t)).describe("Fonction used to parse incoming values."),
448
+ write: e.optional(H()).describe("Fonction used to write value."),
511
449
  "refresh.interval": e.optional(e.number()).describe("Refresh interval used for read fonction, NEED to be superior at value used in binding part."),
512
450
  // TODO Validate this
513
451
  values: e.optional(e.unknown()).describe("TODO: What is this ?"),
@@ -515,7 +453,7 @@ function D(t) {
515
453
  default: e.optional(e.unknown()).describe("Defaut value.")
516
454
  });
517
455
  }
518
- function R(t) {
456
+ function J(t) {
519
457
  return e.strictObject({
520
458
  $schema: e.optional(e.string()),
521
459
  schema: e.literal("devcap1.schema.json"),
@@ -538,32 +476,32 @@ function R(t) {
538
476
  modelid: e.string().or(e.array(e.string())).describe("Model ID from Basic Cluster."),
539
477
  vendor: e.optional(e.string()).describe("Friendly name of the manufacturer."),
540
478
  comment: e.optional(e.string()),
541
- matchexpr: e.optional(p()).describe("Need to return true for the DDF be used."),
542
- path: e.optional(f()).describe("DDF path, useless, can be removed."),
479
+ matchexpr: e.optional(F()).describe("Need to return true for the DDF be used."),
480
+ path: e.optional(A()).describe("DDF path, useless, can be removed."),
543
481
  product: e.optional(e.string()).describe("Complements the model id to be shown in the UI."),
544
482
  sleeper: e.optional(e.boolean()).describe("Sleeping devices can only receive when awake."),
545
483
  supportsMgmtBind: e.optional(e.boolean()),
546
484
  status: e.enum(["Draft", "Bronze", "Silver", "Gold"]).describe("The code quality of the DDF file."),
547
- subdevices: e.array(F(t)).describe("Devices section."),
548
- bindings: e.optional(e.array(k())).describe("Bindings section.")
485
+ subdevices: e.array(X(t)).describe("Devices section."),
486
+ bindings: e.optional(e.array(Q())).describe("Bindings section.")
549
487
  });
550
488
  }
551
- function F(t) {
489
+ function X(t) {
552
490
  return e.strictObject({
553
491
  type: e.union([
554
492
  e.enum(Object.keys(t.deviceTypes), {
555
- errorMap: (a, u) => a.code === "invalid_enum_value" ? { message: `Invalid enum value. Expected type from generic attributes definition, received '${a.received}'` } : { message: u.defaultError }
493
+ errorMap: (r, u) => r.code === "invalid_enum_value" ? { message: `Invalid enum value. Expected type from generic attributes definition, received '${r.received}'` } : { message: u.defaultError }
556
494
  }),
557
495
  e.string().regex(/^(?!\$TYPE_).*/g, "The type start with $TYPE_ but is not present in constants.json")
558
496
  ]),
559
497
  restapi: e.enum(["/lights", "/sensors"]),
560
- uuid: j(),
498
+ uuid: S(),
561
499
  fingerprint: e.optional(e.strictObject({
562
- profile: r(4),
563
- device: r(4),
564
- endpoint: m(),
565
- in: e.optional(e.array(r(4))),
566
- out: e.optional(e.array(r(4)))
500
+ profile: l(4),
501
+ device: l(4),
502
+ endpoint: g(),
503
+ in: e.optional(e.array(l(4))),
504
+ out: e.optional(e.array(l(4)))
567
505
  })),
568
506
  meta: e.optional(e.strictObject({
569
507
  // TODO validate this
@@ -574,51 +512,51 @@ function F(t) {
574
512
  buttons: e.optional(e.any()),
575
513
  // TODO validate this
576
514
  buttonevents: e.optional(e.any()),
577
- items: e.array(z(t)),
515
+ items: e.array(K(t)),
578
516
  example: e.optional(e.unknown())
579
517
  });
580
518
  }
581
- function z(t) {
582
- return D().omit({
519
+ function K(t) {
520
+ return Z(t).omit({
583
521
  $schema: !0,
584
522
  schema: !0,
585
523
  id: !0
586
524
  }).extend({
587
525
  name: e.enum(t.attributes, {
588
- errorMap: (a, u) => a.code === "invalid_enum_value" ? { message: `Invalid enum value. Expected item from generic attributes definition, received '${a.received}'` } : { message: u.defaultError }
526
+ errorMap: (r, u) => r.code === "invalid_enum_value" ? { message: `Invalid enum value. Expected item from generic attributes definition, received '${r.received}'` } : { message: u.defaultError }
589
527
  }).describe("Item name.")
590
528
  });
591
529
  }
592
- function k(t) {
530
+ function Q(t) {
593
531
  return e.discriminatedUnion("bind", [
594
532
  e.strictObject({
595
533
  bind: e.literal("unicast"),
596
- "src.ep": m().describe("Source endpoint."),
597
- "dst.ep": e.optional(m()).describe("Destination endpoint, generaly 0x01."),
598
- cl: r(4).describe("Cluster."),
534
+ "src.ep": g().describe("Source endpoint."),
535
+ "dst.ep": e.optional(g()).describe("Destination endpoint, generaly 0x01."),
536
+ cl: l(4).describe("Cluster."),
599
537
  report: e.optional(e.array(
600
538
  e.strictObject({
601
- at: r(4),
602
- dt: r(2),
603
- mf: e.optional(r(4)),
539
+ at: l(4),
540
+ dt: l(2),
541
+ mf: e.optional(l(4)),
604
542
  min: e.number(),
605
543
  max: e.number(),
606
- change: e.optional(r().or(e.number()))
607
- }).refine((a) => a.min <= a.max, { message: "invalid report time, min should be smaller than max" })
544
+ change: e.optional(l().or(e.number()))
545
+ }).refine((r) => r.min <= r.max, { message: "invalid report time, min should be smaller than max" })
608
546
  ))
609
547
  }),
610
548
  e.strictObject({
611
549
  bind: e.literal("groupcast"),
612
- "src.ep": m().describe("Source endpoint."),
613
- cl: r(4).describe("Cluster."),
550
+ "src.ep": g().describe("Source endpoint."),
551
+ cl: l(4).describe("Cluster."),
614
552
  "config.group": e.number().min(0).max(255)
615
553
  })
616
554
  ]);
617
555
  }
618
- function L(t) {
619
- const a = e.array(
556
+ function ee(t) {
557
+ const r = e.array(
620
558
  e.enum(t.attributes, {
621
- errorMap: (u, o) => u.code === "invalid_enum_value" ? { message: `Invalid enum value. Expected item from generic attributes definition, received '${u.received}'` } : { message: o.defaultError }
559
+ errorMap: (u, i) => u.code === "invalid_enum_value" ? { message: `Invalid enum value. Expected item from generic attributes definition, received '${u.received}'` } : { message: i.defaultError }
622
560
  })
623
561
  );
624
562
  return e.strictObject({
@@ -626,88 +564,111 @@ function L(t) {
626
564
  schema: e.literal("subdevice1.schema.json"),
627
565
  type: e.union([
628
566
  e.enum(Object.keys(t.deviceTypes), {
629
- errorMap: (u, o) => u.code === "invalid_enum_value" ? { message: `Invalid enum value. Expected type from generic attributes definition, received '${u.received}'` } : { message: o.defaultError }
567
+ errorMap: (u, i) => u.code === "invalid_enum_value" ? { message: `Invalid enum value. Expected type from generic attributes definition, received '${u.received}'` } : { message: i.defaultError }
630
568
  }),
631
569
  e.string().regex(/^(?!\$TYPE_).*/g, "The type start with $TYPE_ but is not present in constants.json")
632
570
  ]),
633
571
  name: e.string(),
634
572
  restapi: e.enum(["/lights", "/sensors"]),
635
573
  order: e.number(),
636
- uuid: j(),
637
- items: a,
638
- items_optional: e.optional(a)
574
+ uuid: S(),
575
+ items: r,
576
+ items_optional: e.optional(r)
639
577
  });
640
578
  }
641
- function x(t) {
579
+ function D(t) {
642
580
  return e.discriminatedUnion("schema", [
643
- R(t),
644
- A(),
645
- I(),
646
- D(),
647
- L(t)
648
- ]).superRefine((a, u) => {
649
- switch (a.schema) {
581
+ J(t),
582
+ B(),
583
+ C(),
584
+ Z(t),
585
+ ee(t)
586
+ ]).superRefine((r, u) => {
587
+ switch (r.schema) {
650
588
  case "devcap1.schema.json":
651
- y[a.schema].map((o) => o(a, u, t));
589
+ O[r.schema].map((i) => i(r, u, t));
652
590
  break;
653
591
  case "constants2.schema.json":
654
- y[a.schema].map((o) => o(a, u, t));
592
+ O[r.schema].map((i) => i(r, u, t));
655
593
  break;
656
594
  }
657
595
  });
658
596
  }
659
- function P(t = {
597
+ function re(t = {
660
598
  attributes: [],
661
599
  manufacturers: {},
662
600
  deviceTypes: {},
663
601
  resources: {},
664
602
  subDevices: {}
665
603
  }) {
666
- let a = x(t);
604
+ let r = D(t);
667
605
  const u = () => {
668
- a = x(t);
669
- };
670
- return { generics: t, loadGeneric: (s) => {
671
- const n = a.parse(s);
672
- switch (n.schema) {
606
+ r = D(t);
607
+ }, i = (m) => [
608
+ "constants1.schema.json",
609
+ "constants2.schema.json",
610
+ "resourceitem1.schema.json",
611
+ "subdevice1.schema.json"
612
+ ].includes(m), c = (m) => m === "devcap1.schema.json", n = (m) => {
613
+ const s = r.parse(m);
614
+ switch (s.schema) {
673
615
  case "constants1.schema.json":
674
616
  t.manufacturers = {
675
617
  ...t.manufacturers,
676
- ...n.manufacturers
618
+ ...s.manufacturers
677
619
  }, t.deviceTypes = {
678
620
  ...t.deviceTypes,
679
- ...n["device-types"]
621
+ ...s["device-types"]
680
622
  };
681
623
  break;
682
624
  case "constants2.schema.json": {
683
- Object.keys(n).filter((c) => c.startsWith("$MF_")).forEach((c) => {
684
- t.manufacturers[c] = n[c];
685
- }), Object.keys(n).filter((c) => c.startsWith("$TYPE_")).forEach((c) => {
686
- t.deviceTypes[c] = n[c];
625
+ Object.keys(s).filter((o) => o.startsWith("$MF_")).forEach((o) => {
626
+ t.manufacturers[o] = s[o];
627
+ }), Object.keys(s).filter((o) => o.startsWith("$TYPE_")).forEach((o) => {
628
+ t.deviceTypes[o] = s[o];
687
629
  });
688
630
  break;
689
631
  }
690
632
  case "resourceitem1.schema.json": {
691
- if (t.attributes.includes(n.id))
692
- throw new Error(`Got duplicate resource item with attribute id '${n.id}'.`);
693
- const c = n, b = n.id;
694
- delete c.$schema, delete c.schema, delete c.id, t.resources[b] = c, t.attributes.push(b);
633
+ if (t.attributes.includes(s.id))
634
+ throw new Error(`Got duplicate resource item with attribute id '${s.id}'.`);
635
+ const o = s, p = s.id;
636
+ delete o.$schema, delete o.schema, delete o.id, t.resources[p] = o, t.attributes.push(p);
695
637
  break;
696
638
  }
697
639
  case "subdevice1.schema.json":
698
- t.subDevices[n.type] = n, t.subDevices[n.name] = n;
640
+ t.subDevices[s.type] = s, t.subDevices[s.name] = s;
699
641
  break;
700
642
  default:
701
- throw new Error(`Got invalid generic file, got data with schema '${n.schema}'.`);
643
+ throw new Error(`Got invalid generic file, got data with schema '${s.schema}'.`);
702
644
  }
703
645
  return u(), !0;
704
- }, validate: (s) => a.parse(s), getSchema: () => a, version: E, isGeneric: (s) => [
705
- "constants1.schema.json",
706
- "constants2.schema.json",
707
- "resourceitem1.schema.json",
708
- "subdevice1.schema.json"
709
- ].includes(s), isDDF: (s) => s === "devcap1.schema.json" };
646
+ }, d = (m) => r.parse(m);
647
+ return { generics: t, loadGeneric: n, validate: d, bulkValidate: (m, s, o = {}) => {
648
+ const p = (b, h) => {
649
+ var E, j, T;
650
+ let I = 0, _ = Number.POSITIVE_INFINITY, $ = b, v = [];
651
+ for ((E = o.onSectionStart) == null || E.call(o, h, b.length); v = [], (j = o.onSectionProgress) == null || j.call(o, h, 1, b.length), $.forEach((y) => {
652
+ var w;
653
+ (w = o.onSectionProgress) == null || w.call(o, h, I++, b.length);
654
+ try {
655
+ h === "generic" ? n(y.data) : h === "ddf" && d(y.data);
656
+ } catch (G) {
657
+ v.push({
658
+ ...y,
659
+ error: G
660
+ });
661
+ }
662
+ }), !(v.length === 0 || v.length >= _); )
663
+ I -= v.length, $ = v, _ = v.length;
664
+ return (T = o.onSectionEnd) == null || T.call(o, h, b.length, v), v;
665
+ };
666
+ return [
667
+ ...p(m, "generic"),
668
+ ...p(s, "ddf")
669
+ ];
670
+ }, getSchema: () => r, version: M, isGeneric: i, isDDF: c };
710
671
  }
711
672
  export {
712
- P as createValidator
673
+ re as createValidator
713
674
  };