zigbee-herdsman 5.0.3 → 6.0.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.
Files changed (79) hide show
  1. package/.github/dependabot.yml +3 -0
  2. package/.github/workflows/ci.yml +1 -0
  3. package/.release-please-manifest.json +1 -1
  4. package/CHANGELOG.md +26 -0
  5. package/biome.json +1 -1
  6. package/dist/adapter/deconz/adapter/deconzAdapter.js +1 -1
  7. package/dist/adapter/deconz/adapter/deconzAdapter.js.map +1 -1
  8. package/dist/adapter/ember/ezsp/buffalo.d.ts +0 -2
  9. package/dist/adapter/ember/ezsp/buffalo.d.ts.map +1 -1
  10. package/dist/adapter/ember/ezsp/buffalo.js +0 -4
  11. package/dist/adapter/ember/ezsp/buffalo.js.map +1 -1
  12. package/dist/adapter/ember/uart/ash.d.ts.map +1 -1
  13. package/dist/adapter/ember/uart/ash.js +0 -2
  14. package/dist/adapter/ember/uart/ash.js.map +1 -1
  15. package/dist/buffalo/buffalo.d.ts +5 -0
  16. package/dist/buffalo/buffalo.d.ts.map +1 -1
  17. package/dist/buffalo/buffalo.js +7 -0
  18. package/dist/buffalo/buffalo.js.map +1 -1
  19. package/dist/controller/controller.d.ts.map +1 -1
  20. package/dist/controller/controller.js +1 -1
  21. package/dist/controller/controller.js.map +1 -1
  22. package/dist/controller/events.d.ts +1 -0
  23. package/dist/controller/events.d.ts.map +1 -1
  24. package/dist/controller/tstype.d.ts +17 -0
  25. package/dist/controller/tstype.d.ts.map +1 -1
  26. package/dist/zspec/zcl/buffaloZcl.d.ts +32 -17
  27. package/dist/zspec/zcl/buffaloZcl.d.ts.map +1 -1
  28. package/dist/zspec/zcl/buffaloZcl.js +257 -121
  29. package/dist/zspec/zcl/buffaloZcl.js.map +1 -1
  30. package/dist/zspec/zcl/definition/cluster.d.ts.map +1 -1
  31. package/dist/zspec/zcl/definition/cluster.js +154 -24
  32. package/dist/zspec/zcl/definition/cluster.js.map +1 -1
  33. package/dist/zspec/zcl/definition/clusters-typegen.d.ts +2 -0
  34. package/dist/zspec/zcl/definition/clusters-typegen.d.ts.map +1 -0
  35. package/dist/zspec/zcl/definition/clusters-typegen.js +300 -0
  36. package/dist/zspec/zcl/definition/clusters-typegen.js.map +1 -0
  37. package/dist/zspec/zcl/definition/clusters-types.d.ts +7205 -0
  38. package/dist/zspec/zcl/definition/clusters-types.d.ts.map +1 -0
  39. package/dist/zspec/zcl/definition/clusters-types.js +3 -0
  40. package/dist/zspec/zcl/definition/clusters-types.js.map +1 -0
  41. package/dist/zspec/zcl/definition/enums.d.ts +4 -6
  42. package/dist/zspec/zcl/definition/enums.d.ts.map +1 -1
  43. package/dist/zspec/zcl/definition/enums.js +3 -5
  44. package/dist/zspec/zcl/definition/enums.js.map +1 -1
  45. package/dist/zspec/zcl/definition/foundation.d.ts.map +1 -1
  46. package/dist/zspec/zcl/definition/foundation.js +43 -15
  47. package/dist/zspec/zcl/definition/foundation.js.map +1 -1
  48. package/dist/zspec/zcl/definition/tstype.d.ts +105 -11
  49. package/dist/zspec/zcl/definition/tstype.d.ts.map +1 -1
  50. package/dist/zspec/zcl/zclFrame.d.ts.map +1 -1
  51. package/dist/zspec/zcl/zclFrame.js +32 -20
  52. package/dist/zspec/zcl/zclFrame.js.map +1 -1
  53. package/dist/zspec/zdo/buffaloZdo.d.ts +0 -6
  54. package/dist/zspec/zdo/buffaloZdo.d.ts.map +1 -1
  55. package/dist/zspec/zdo/buffaloZdo.js +0 -8
  56. package/dist/zspec/zdo/buffaloZdo.js.map +1 -1
  57. package/package.json +3 -3
  58. package/src/adapter/deconz/adapter/deconzAdapter.ts +1 -1
  59. package/src/adapter/ember/ezsp/buffalo.ts +0 -5
  60. package/src/adapter/ember/uart/ash.ts +0 -2
  61. package/src/buffalo/buffalo.ts +8 -0
  62. package/src/controller/controller.ts +2 -1
  63. package/src/controller/events.ts +1 -0
  64. package/src/controller/greenPower.ts +4 -4
  65. package/src/controller/tstype.ts +17 -16
  66. package/src/zspec/zcl/buffaloZcl.ts +323 -238
  67. package/src/zspec/zcl/definition/cluster.ts +154 -24
  68. package/src/zspec/zcl/definition/clusters-typegen.ts +511 -0
  69. package/src/zspec/zcl/definition/clusters-types.ts +7282 -0
  70. package/src/zspec/zcl/definition/enums.ts +3 -5
  71. package/src/zspec/zcl/definition/foundation.ts +43 -15
  72. package/src/zspec/zcl/definition/tstype.ts +118 -7
  73. package/src/zspec/zcl/zclFrame.ts +37 -19
  74. package/src/zspec/zdo/buffaloZdo.ts +0 -9
  75. package/test/controller.test.ts +65 -803
  76. package/test/greenpower.test.ts +0 -12
  77. package/test/zcl.test.ts +13 -11
  78. package/test/zspec/zcl/buffalo.test.ts +216 -74
  79. package/test/zspec/zcl/frame.test.ts +62 -28
@@ -0,0 +1,511 @@
1
+ /* v8 ignore start */
2
+ /**
3
+ * How to run:
4
+ * ```bash
5
+ * npm i -g ts-node
6
+ * ts-node ./src/zspec/zcl/definition/clusters-typegen.ts && pnpm run check:w
7
+ * ```
8
+ * or with compiled:
9
+ * ```bash
10
+ * pnpm run prepack
11
+ * node ./dist/zspec/zcl/definition/clusters-typegen.js && pnpm run check:w
12
+ * ```
13
+ */
14
+ import {writeFileSync} from "node:fs";
15
+ import ts from "typescript";
16
+ import {isFoundationDiscoverRsp} from "../utils";
17
+ import {Clusters} from "./cluster";
18
+ import {BuffaloZclDataType, DataType} from "./enums";
19
+ import {Foundation, type FoundationCommandName, type FoundationDefinition} from "./foundation";
20
+ import {ManufacturerCode} from "./manufacturerCode";
21
+ import type {AttributeDefinition, ClusterName, CommandDefinition} from "./tstype";
22
+
23
+ const FILENAME = "clusters-types.ts";
24
+
25
+ const file = ts.createSourceFile(FILENAME, "", ts.ScriptTarget.ES2022, false, ts.ScriptKind.TS);
26
+ const printer = ts.createPrinter({newLine: ts.NewLineKind.LineFeed});
27
+
28
+ const emptyObject = ts.factory.createTypeReferenceNode("Record", [
29
+ ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword),
30
+ ts.factory.createKeywordTypeNode(ts.SyntaxKind.NeverKeyword),
31
+ ]);
32
+
33
+ const namedImports = ts.factory.createImportDeclaration(
34
+ undefined,
35
+ ts.factory.createImportClause(
36
+ true,
37
+ undefined,
38
+ ts.factory.createNamedImports([
39
+ // sorted by name
40
+ ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier("ExtensionFieldSet")),
41
+ ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier("Gpd")),
42
+ ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier("GpdAttributeReport")),
43
+ ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier("GpdChannelRequest")),
44
+ ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier("MiboxerZone")),
45
+ ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier("Struct")),
46
+ ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier("StructuredSelector")),
47
+ ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier("ThermoTransition")),
48
+ ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier("TuyaDataPointValue")),
49
+ // ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier("ZclDate")), // XXX: currently unused
50
+ // ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier("ZclTimeOfDay")), // XXX: currently unused
51
+ ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier("ZoneInfo")),
52
+ ]),
53
+ ),
54
+ ts.factory.createStringLiteral("./tstype"),
55
+ undefined,
56
+ );
57
+
58
+ const getTypeFromDataType = (dataType: DataType | BuffaloZclDataType): ts.TypeNode => {
59
+ switch (dataType) {
60
+ case DataType.NO_DATA:
61
+ case DataType.UNKNOWN: {
62
+ return ts.factory.createKeywordTypeNode(ts.SyntaxKind.NeverKeyword);
63
+ }
64
+ case DataType.OCTET_STR:
65
+ case DataType.LONG_OCTET_STR:
66
+ case DataType.SEC_KEY: {
67
+ return ts.factory.createTypeReferenceNode("Buffer");
68
+ }
69
+ case DataType.CHAR_STR:
70
+ case DataType.LONG_CHAR_STR:
71
+ case DataType.IEEE_ADDR: {
72
+ return ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword);
73
+ }
74
+ case DataType.ARRAY:
75
+ case DataType.SET:
76
+ case DataType.BAG: {
77
+ return ts.factory.createArrayTypeNode(ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword));
78
+ }
79
+ case DataType.STRUCT: {
80
+ return ts.factory.createTypeReferenceNode("Struct");
81
+ }
82
+ case DataType.TOD: {
83
+ return ts.factory.createTypeReferenceNode("ZclTimeOfDay");
84
+ }
85
+ case DataType.DATE: {
86
+ return ts.factory.createTypeReferenceNode("ZclDate");
87
+ }
88
+ case BuffaloZclDataType.USE_DATA_TYPE: {
89
+ return ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword);
90
+ }
91
+ case BuffaloZclDataType.LIST_UINT8:
92
+ case BuffaloZclDataType.LIST_UINT16:
93
+ case BuffaloZclDataType.LIST_UINT24:
94
+ case BuffaloZclDataType.LIST_UINT32: {
95
+ return ts.factory.createArrayTypeNode(ts.factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword));
96
+ }
97
+ case BuffaloZclDataType.LIST_ZONEINFO: {
98
+ return ts.factory.createArrayTypeNode(ts.factory.createTypeReferenceNode("ZoneInfo"));
99
+ }
100
+ case BuffaloZclDataType.EXTENSION_FIELD_SETS: {
101
+ return ts.factory.createArrayTypeNode(ts.factory.createTypeReferenceNode("ExtensionFieldSet"));
102
+ }
103
+ case BuffaloZclDataType.LIST_THERMO_TRANSITIONS: {
104
+ return ts.factory.createArrayTypeNode(ts.factory.createTypeReferenceNode("ThermoTransition"));
105
+ }
106
+ case BuffaloZclDataType.BUFFER: {
107
+ return ts.factory.createTypeReferenceNode("Buffer");
108
+ }
109
+ case BuffaloZclDataType.GPD_FRAME: {
110
+ return ts.factory.createUnionTypeNode([
111
+ ts.factory.createTypeReferenceNode("Gpd"),
112
+ ts.factory.createTypeReferenceNode("GpdChannelRequest"),
113
+ ts.factory.createTypeReferenceNode("GpdAttributeReport"),
114
+ ts.factory.createTypeLiteralNode([
115
+ ts.factory.createPropertySignature(undefined, "raw", undefined, ts.factory.createTypeReferenceNode("Buffer")),
116
+ ]),
117
+ ts.factory.createTypeReferenceNode("Record<string, never>"),
118
+ ]);
119
+ }
120
+ case BuffaloZclDataType.STRUCTURED_SELECTOR: {
121
+ return ts.factory.createTypeReferenceNode("StructuredSelector");
122
+ }
123
+ case BuffaloZclDataType.LIST_TUYA_DATAPOINT_VALUES: {
124
+ return ts.factory.createArrayTypeNode(ts.factory.createTypeReferenceNode("TuyaDataPointValue"));
125
+ }
126
+ case BuffaloZclDataType.LIST_MIBOXER_ZONES: {
127
+ return ts.factory.createArrayTypeNode(ts.factory.createTypeReferenceNode("MiboxerZone"));
128
+ }
129
+ default: {
130
+ return ts.factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword);
131
+ }
132
+ }
133
+ };
134
+
135
+ const addAttributes = (attributes: Readonly<Record<string, Readonly<AttributeDefinition>>>): ts.TypeNode => {
136
+ const elements: ts.PropertySignature[] = [];
137
+
138
+ for (const attributeName in attributes) {
139
+ const attribute = attributes[attributeName];
140
+
141
+ const element = ts.factory.createPropertySignature(
142
+ undefined,
143
+ attributeName,
144
+ // always optional if manuf-specific
145
+ attribute.manufacturerCode ? ts.factory.createToken(ts.SyntaxKind.QuestionToken) : undefined,
146
+ getTypeFromDataType(attribute.type),
147
+ );
148
+
149
+ elements.push(element);
150
+
151
+ let comment = `* ID: ${attribute.ID} | Type: ${DataType[attribute.type] ?? BuffaloZclDataType[attribute.type]} `;
152
+
153
+ if (attribute.manufacturerCode !== undefined) {
154
+ comment += `| Specific to manufacturer: ${ManufacturerCode[attribute.manufacturerCode]} (${attribute.manufacturerCode}) `;
155
+ }
156
+
157
+ ts.addSyntheticLeadingComment(element, ts.SyntaxKind.MultiLineCommentTrivia, comment, true);
158
+ }
159
+
160
+ return elements.length > 0 ? ts.factory.createTypeLiteralNode(elements) : emptyObject;
161
+ };
162
+
163
+ const addCommands = (commands: Readonly<Record<string, Readonly<CommandDefinition>>>): ts.TypeNode => {
164
+ const elements: ts.PropertySignature[] = [];
165
+
166
+ for (const commandName in commands) {
167
+ const command = commands[commandName];
168
+ const cmdElements: ts.PropertySignature[] = [];
169
+
170
+ for (const parameter of command.parameters) {
171
+ // @ts-expect-error bad typing?
172
+ const existing = cmdElements.find((element) => element.name.escapedText === parameter.name);
173
+ const paramType = getTypeFromDataType(parameter.type);
174
+
175
+ if (!existing) {
176
+ const cmdElement = ts.factory.createPropertySignature(
177
+ undefined,
178
+ parameter.name,
179
+ parameter.conditions ? ts.factory.createToken(ts.SyntaxKind.QuestionToken) : undefined,
180
+ paramType,
181
+ );
182
+
183
+ cmdElements.push(cmdElement);
184
+ ts.addSyntheticLeadingComment(
185
+ cmdElement,
186
+ ts.SyntaxKind.MultiLineCommentTrivia,
187
+ `* Type: ${DataType[parameter.type] ?? BuffaloZclDataType[parameter.type]} `,
188
+ true,
189
+ );
190
+ } else if (
191
+ // @ts-expect-error bad typing?
192
+ existing.type?.typeName?.escapedText &&
193
+ // @ts-expect-error bad typing?
194
+ paramType.typeName?.escapedText &&
195
+ // @ts-expect-error bad typing?
196
+ existing.type.typeName.escapedText !== paramType.typeName.escapedText
197
+ ) {
198
+ // XXX: not currently used, untested
199
+ ts.factory.updatePropertySignature(
200
+ existing,
201
+ existing.modifiers,
202
+ existing.name,
203
+ existing.questionToken,
204
+ ts.factory.createUnionTypeNode([existing.type, paramType]),
205
+ );
206
+ } else if (!parameter.conditions) {
207
+ throw new Error(`Two or more cluster command parameters have identical name without conditions. ${JSON.stringify(parameter)}`);
208
+ }
209
+ }
210
+
211
+ const element = ts.factory.createPropertySignature(
212
+ undefined,
213
+ commandName,
214
+ undefined,
215
+ cmdElements.length > 0 ? ts.factory.createTypeLiteralNode(cmdElements) : emptyObject,
216
+ );
217
+
218
+ elements.push(element);
219
+
220
+ let comment = `* ID: ${command.ID} `;
221
+
222
+ if (command.response !== undefined) {
223
+ comment += `| Response ID: ${command.response} `;
224
+ }
225
+
226
+ ts.addSyntheticLeadingComment(element, ts.SyntaxKind.MultiLineCommentTrivia, comment, true);
227
+ }
228
+
229
+ return elements.length > 0 ? ts.factory.createTypeLiteralNode(elements) : ts.factory.createKeywordTypeNode(ts.SyntaxKind.NeverKeyword);
230
+ };
231
+
232
+ const clusterElements: ts.TypeElement[] = [];
233
+
234
+ for (const clusterName in Clusters) {
235
+ const cluster = Clusters[clusterName as ClusterName];
236
+
237
+ const attributesProp = ts.factory.createPropertySignature(undefined, "attributes", undefined, addAttributes(cluster.attributes));
238
+ const commandsProp = ts.factory.createPropertySignature(undefined, "commands", undefined, addCommands(cluster.commands));
239
+ const commandResponsesProp = ts.factory.createPropertySignature(undefined, "commandResponses", undefined, addCommands(cluster.commandsResponse));
240
+
241
+ clusterElements.push(
242
+ ts.factory.createPropertySignature(
243
+ undefined,
244
+ clusterName,
245
+ undefined,
246
+ ts.factory.createTypeLiteralNode([attributesProp, commandsProp, commandResponsesProp]),
247
+ ),
248
+ );
249
+ }
250
+
251
+ const clustersDecl = ts.factory.createInterfaceDeclaration(
252
+ [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)],
253
+ "TClusters",
254
+ undefined,
255
+ undefined,
256
+ clusterElements,
257
+ );
258
+
259
+ const addParameters = (foundation: Readonly<FoundationDefinition>): ts.TypeNode => {
260
+ const elements: ts.PropertySignature[] = [];
261
+
262
+ for (const parameter of foundation.parameters) {
263
+ const element = ts.factory.createPropertySignature(
264
+ undefined,
265
+ parameter.name,
266
+ parameter.conditions ? ts.factory.createToken(ts.SyntaxKind.QuestionToken) : undefined,
267
+ getTypeFromDataType(parameter.type),
268
+ );
269
+
270
+ elements.push(element);
271
+
272
+ ts.addSyntheticLeadingComment(
273
+ element,
274
+ ts.SyntaxKind.MultiLineCommentTrivia,
275
+ `* Type: ${DataType[parameter.type] ?? BuffaloZclDataType[parameter.type]} `,
276
+ true,
277
+ );
278
+ }
279
+
280
+ if (elements.length === 0) {
281
+ return emptyObject;
282
+ }
283
+
284
+ switch (foundation.parseStrategy) {
285
+ case "repetitive": {
286
+ return ts.factory.createArrayTypeNode(ts.factory.createTypeLiteralNode(elements));
287
+ }
288
+ case "flat": {
289
+ return ts.factory.createTypeLiteralNode(elements);
290
+ }
291
+ case "oneof": {
292
+ if (isFoundationDiscoverRsp(foundation.ID)) {
293
+ const discComplete = ts.factory.createPropertySignature(
294
+ undefined,
295
+ "discComplete",
296
+ undefined,
297
+ ts.factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword),
298
+ );
299
+
300
+ ts.addSyntheticLeadingComment(discComplete, ts.SyntaxKind.MultiLineCommentTrivia, `* Type: ${DataType[DataType.UINT8]} `, true);
301
+
302
+ return ts.factory.createTypeLiteralNode([
303
+ discComplete,
304
+ ts.factory.createPropertySignature(
305
+ undefined,
306
+ "attrInfos",
307
+ undefined,
308
+ ts.factory.createArrayTypeNode(ts.factory.createTypeLiteralNode(elements)),
309
+ ),
310
+ ]);
311
+ }
312
+ }
313
+ }
314
+
315
+ throw new Error(`Unknown command strategy for ${JSON.stringify(foundation)}`);
316
+ };
317
+
318
+ const foundationElements: ts.TypeElement[] = [];
319
+ const foundationRepetitiveElements: ts.TypeNode[] = [];
320
+ const foundationFlatElements: ts.TypeNode[] = [];
321
+ const foundationOneOfElements: ts.TypeNode[] = [];
322
+
323
+ for (const foundationName in Foundation) {
324
+ const foundation = Foundation[foundationName as FoundationCommandName];
325
+ const element = ts.factory.createPropertySignature(undefined, foundationName, undefined, addParameters(foundation));
326
+
327
+ foundationElements.push(element);
328
+ ts.addSyntheticLeadingComment(element, ts.SyntaxKind.MultiLineCommentTrivia, `* ID: ${foundation.ID} `, true);
329
+
330
+ const stratNode = ts.factory.createTypeReferenceNode(`"${foundationName}"`);
331
+
332
+ switch (foundation.parseStrategy) {
333
+ case "repetitive": {
334
+ foundationRepetitiveElements.push(stratNode);
335
+ break;
336
+ }
337
+ case "flat": {
338
+ foundationFlatElements.push(stratNode);
339
+ break;
340
+ }
341
+ case "oneof": {
342
+ foundationOneOfElements.push(stratNode);
343
+ break;
344
+ }
345
+ }
346
+ }
347
+
348
+ const foundationDecl = ts.factory.createInterfaceDeclaration(
349
+ [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)],
350
+ "TFoundation",
351
+ undefined,
352
+ undefined,
353
+ foundationElements,
354
+ );
355
+
356
+ const foundationRepetitiveDecl = ts.factory.createTypeAliasDeclaration(
357
+ [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)],
358
+ "TFoundationRepetitive",
359
+ undefined,
360
+ ts.factory.createUnionTypeNode(foundationRepetitiveElements),
361
+ );
362
+ const foundationFlatDecl = ts.factory.createTypeAliasDeclaration(
363
+ [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)],
364
+ "TFoundationFlat",
365
+ undefined,
366
+ ts.factory.createUnionTypeNode(foundationFlatElements),
367
+ );
368
+ const foundationOneOfDecl = ts.factory.createTypeAliasDeclaration(
369
+ [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)],
370
+ "TFoundationOneOf",
371
+ undefined,
372
+ ts.factory.createUnionTypeNode(foundationOneOfElements),
373
+ );
374
+ const clDecl = ts.factory.createTypeParameterDeclaration(
375
+ undefined,
376
+ "Cl",
377
+ ts.factory.createUnionTypeNode([
378
+ ts.factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword),
379
+ ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword),
380
+ ]),
381
+ );
382
+ const coDecl = ts.factory.createTypeParameterDeclaration(
383
+ undefined,
384
+ "Co",
385
+ ts.factory.createUnionTypeNode([
386
+ ts.factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword),
387
+ ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword),
388
+ ]),
389
+ );
390
+ const clusterGenericPayloadDecl = ts.factory.createTypeAliasDeclaration(
391
+ [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)],
392
+ "TClusterGenericPayload",
393
+ undefined,
394
+ ts.factory.createTypeReferenceNode("Record<string, unknown>"),
395
+ );
396
+ const clusterAttributeKeysDecl = ts.factory.createTypeAliasDeclaration(
397
+ [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)],
398
+ "TClusterAttributeKeys",
399
+ [clDecl],
400
+ ts.factory.createTypeReferenceNode(
401
+ `Cl extends keyof ${clustersDecl.name.escapedText} ? (keyof ${clustersDecl.name.escapedText}[Cl]["attributes"])[] : (string | number)[];`,
402
+ ),
403
+ );
404
+ const clusterAttributesDecl = ts.factory.createTypeAliasDeclaration(
405
+ [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)],
406
+ "TClusterAttributes",
407
+ [clDecl],
408
+ ts.factory.createTypeReferenceNode(
409
+ `Cl extends keyof ${clustersDecl.name.escapedText} ? ${clustersDecl.name.escapedText}[Cl]["attributes"] : ${clusterGenericPayloadDecl.name.escapedText}`,
410
+ ),
411
+ );
412
+ const partialClusterAttributesDecl = ts.factory.createTypeAliasDeclaration(
413
+ [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)],
414
+ "TPartialClusterAttributes",
415
+ [clDecl],
416
+ ts.factory.createTypeReferenceNode(
417
+ `Cl extends keyof ${clustersDecl.name.escapedText} ? Partial<${clustersDecl.name.escapedText}[Cl]["attributes"]> : ${clusterGenericPayloadDecl.name.escapedText}`,
418
+ ),
419
+ );
420
+ const clusterCommandPayloadDecl = ts.factory.createTypeAliasDeclaration(
421
+ [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)],
422
+ "TClusterCommandPayload",
423
+ [clDecl, coDecl],
424
+ ts.factory.createTypeReferenceNode(
425
+ `Cl extends keyof ${clustersDecl.name.escapedText} ? Co extends keyof ${clustersDecl.name.escapedText}[Cl]["commands"] ? ${clustersDecl.name.escapedText}[Cl]["commands"][Co] : ${clusterGenericPayloadDecl.name.escapedText} : ${clusterGenericPayloadDecl.name.escapedText};`,
426
+ ),
427
+ );
428
+ const clusterCommandResponsePayloadDecl = ts.factory.createTypeAliasDeclaration(
429
+ [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)],
430
+ "TClusterCommandResponsePayload",
431
+ [clDecl, coDecl],
432
+ ts.factory.createTypeReferenceNode(
433
+ `Cl extends keyof ${clustersDecl.name.escapedText} ? Co extends keyof ${clustersDecl.name.escapedText}[Cl]["commandResponses"] ? ${clustersDecl.name.escapedText}[Cl]["commandResponses"][Co] : ${clusterGenericPayloadDecl.name.escapedText} : ${clusterGenericPayloadDecl.name.escapedText};`,
434
+ ),
435
+ );
436
+ const clusterPayloadDecl = ts.factory.createTypeAliasDeclaration(
437
+ [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)],
438
+ "TClusterPayload",
439
+ [clDecl, coDecl],
440
+ ts.factory.createTypeReferenceNode(
441
+ `Cl extends keyof ${clustersDecl.name.escapedText} ? ${clustersDecl.name.escapedText}[Cl]["commands"] extends never ? ${clustersDecl.name.escapedText}[Cl]["commandResponses"] extends never ? never : Co extends keyof ${clustersDecl.name.escapedText}[Cl]["commandResponses"] ? ${clustersDecl.name.escapedText}[Cl]["commandResponses"][Co] : ${clusterGenericPayloadDecl.name.escapedText} : Co extends keyof ${clustersDecl.name.escapedText}[Cl]["commands"] ? ${clustersDecl.name.escapedText}[Cl]["commands"][Co] : Co extends keyof ${clustersDecl.name.escapedText}[Cl]["commandResponses"] ? ${clustersDecl.name.escapedText}[Cl]["commandResponses"][Co] : ${clusterGenericPayloadDecl.name.escapedText} : ${clusterGenericPayloadDecl.name.escapedText};`,
442
+ ),
443
+ );
444
+ const foundationGenericPayloadDecl = ts.factory.createTypeAliasDeclaration(
445
+ [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)],
446
+ "TFoundationGenericPayload",
447
+ undefined,
448
+ ts.factory.createTypeReferenceNode(`${foundationDecl.name.escapedText}[keyof ${foundationDecl.name.escapedText}]`),
449
+ );
450
+ const foundationRepetitivePayloadDecl = ts.factory.createTypeAliasDeclaration(
451
+ [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)],
452
+ "TFoundationRepetitivePayload",
453
+ undefined,
454
+ ts.factory.createTypeReferenceNode(`${foundationDecl.name.escapedText}[${foundationRepetitiveDecl.name.escapedText}]`),
455
+ );
456
+ const foundationFlatPayloadDecl = ts.factory.createTypeAliasDeclaration(
457
+ [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)],
458
+ "TFoundationFlatPayload",
459
+ undefined,
460
+ ts.factory.createTypeReferenceNode(`${foundationDecl.name.escapedText}[${foundationFlatDecl.name.escapedText}]`),
461
+ );
462
+ const foundationOneOfPayloadDecl = ts.factory.createTypeAliasDeclaration(
463
+ [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)],
464
+ "TFoundationOneOfPayload",
465
+ undefined,
466
+ ts.factory.createTypeReferenceNode(`${foundationDecl.name.escapedText}[${foundationOneOfDecl.name.escapedText}]`),
467
+ );
468
+ const foundationPayloadDecl = ts.factory.createTypeAliasDeclaration(
469
+ [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)],
470
+ "TFoundationPayload",
471
+ [coDecl],
472
+ ts.factory.createTypeReferenceNode(
473
+ `Co extends keyof ${foundationDecl.name.escapedText} ? ${foundationDecl.name.escapedText}[Co] : ${foundationGenericPayloadDecl.name.escapedText}`,
474
+ ),
475
+ );
476
+
477
+ const result = `${printer.printNode(ts.EmitHint.Unspecified, namedImports, file)}
478
+
479
+ ${printer.printNode(ts.EmitHint.Unspecified, clustersDecl, file)}
480
+
481
+ ${printer.printNode(ts.EmitHint.Unspecified, foundationDecl, file)}
482
+
483
+ ${printer.printNode(ts.EmitHint.Unspecified, foundationRepetitiveDecl, file)}
484
+ ${printer.printNode(ts.EmitHint.Unspecified, foundationFlatDecl, file)}
485
+ ${printer.printNode(ts.EmitHint.Unspecified, foundationOneOfDecl, file)}
486
+
487
+ // Clusters
488
+ ${printer.printNode(ts.EmitHint.Unspecified, clusterGenericPayloadDecl, file)}
489
+
490
+ ${printer.printNode(ts.EmitHint.Unspecified, clusterAttributeKeysDecl, file)}
491
+
492
+ ${printer.printNode(ts.EmitHint.Unspecified, clusterAttributesDecl, file)}
493
+
494
+ ${printer.printNode(ts.EmitHint.Unspecified, partialClusterAttributesDecl, file)}
495
+
496
+ ${printer.printNode(ts.EmitHint.Unspecified, clusterCommandPayloadDecl, file)}
497
+
498
+ ${printer.printNode(ts.EmitHint.Unspecified, clusterCommandResponsePayloadDecl, file)}
499
+
500
+ ${printer.printNode(ts.EmitHint.Unspecified, clusterPayloadDecl, file)}
501
+
502
+ // Foundation
503
+ ${printer.printNode(ts.EmitHint.Unspecified, foundationGenericPayloadDecl, file)}
504
+ ${printer.printNode(ts.EmitHint.Unspecified, foundationRepetitivePayloadDecl, file)}
505
+ ${printer.printNode(ts.EmitHint.Unspecified, foundationFlatPayloadDecl, file)}
506
+ ${printer.printNode(ts.EmitHint.Unspecified, foundationOneOfPayloadDecl, file)}
507
+
508
+ ${printer.printNode(ts.EmitHint.Unspecified, foundationPayloadDecl, file)}
509
+ `;
510
+
511
+ writeFileSync(`./src/zspec/zcl/definition/${FILENAME}`, result, {encoding: "utf8"});