@matter/protocol 0.12.4-alpha.0-20250211-56b2c53a0 → 0.12.4-alpha.0-20250212-b2729c9eb

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 (236) hide show
  1. package/dist/cjs/action/Interactable.d.ts +36 -0
  2. package/dist/cjs/action/Interactable.d.ts.map +1 -0
  3. package/dist/cjs/action/Interactable.js +22 -0
  4. package/dist/cjs/action/Interactable.js.map +6 -0
  5. package/dist/cjs/action/Val.d.ts +94 -0
  6. package/dist/cjs/action/Val.d.ts.map +1 -0
  7. package/dist/cjs/action/Val.js +33 -0
  8. package/dist/cjs/action/Val.js.map +6 -0
  9. package/dist/cjs/action/errors.d.ts +69 -0
  10. package/dist/cjs/action/errors.d.ts.map +1 -0
  11. package/dist/cjs/action/errors.js +108 -0
  12. package/dist/cjs/action/errors.js.map +6 -0
  13. package/dist/cjs/action/index.d.ts +13 -0
  14. package/dist/cjs/action/index.d.ts.map +1 -0
  15. package/dist/cjs/action/index.js +30 -0
  16. package/dist/cjs/action/index.js.map +6 -0
  17. package/dist/cjs/action/protocols.d.ts +118 -0
  18. package/dist/cjs/action/protocols.d.ts.map +1 -0
  19. package/dist/cjs/action/protocols.js +22 -0
  20. package/dist/cjs/action/protocols.js.map +6 -0
  21. package/dist/cjs/action/request/Invoke.d.ts +35 -0
  22. package/dist/cjs/action/request/Invoke.d.ts.map +1 -0
  23. package/dist/cjs/action/request/Invoke.js +80 -0
  24. package/dist/cjs/action/request/Invoke.js.map +6 -0
  25. package/dist/cjs/action/request/MalformedRequestError.d.ts +14 -0
  26. package/dist/cjs/action/request/MalformedRequestError.d.ts.map +1 -0
  27. package/dist/cjs/action/request/MalformedRequestError.js +32 -0
  28. package/dist/cjs/action/request/MalformedRequestError.js.map +6 -0
  29. package/dist/cjs/action/request/Read.d.ts +141 -0
  30. package/dist/cjs/action/request/Read.d.ts.map +1 -0
  31. package/dist/cjs/action/request/Read.js +173 -0
  32. package/dist/cjs/action/request/Read.js.map +6 -0
  33. package/dist/cjs/action/request/Specifier.d.ts +82 -0
  34. package/dist/cjs/action/request/Specifier.d.ts.map +1 -0
  35. package/dist/cjs/action/request/Specifier.js +88 -0
  36. package/dist/cjs/action/request/Specifier.js.map +6 -0
  37. package/dist/cjs/action/request/Subscribe.d.ts +26 -0
  38. package/dist/cjs/action/request/Subscribe.d.ts.map +1 -0
  39. package/dist/cjs/action/request/Subscribe.js +50 -0
  40. package/dist/cjs/action/request/Subscribe.js.map +6 -0
  41. package/dist/cjs/action/request/Write.d.ts +10 -0
  42. package/dist/cjs/action/request/Write.d.ts.map +1 -0
  43. package/dist/cjs/action/request/Write.js +22 -0
  44. package/dist/cjs/action/request/Write.js.map +6 -0
  45. package/dist/cjs/action/request/index.d.ts +11 -0
  46. package/dist/cjs/action/request/index.d.ts.map +1 -0
  47. package/dist/cjs/action/request/index.js +28 -0
  48. package/dist/cjs/action/request/index.js.map +6 -0
  49. package/dist/cjs/action/response/InvokeResult.d.ts +15 -0
  50. package/dist/cjs/action/response/InvokeResult.d.ts.map +1 -0
  51. package/dist/cjs/action/response/InvokeResult.js +22 -0
  52. package/dist/cjs/action/response/InvokeResult.js.map +6 -0
  53. package/dist/cjs/action/response/ReadResult.d.ts +63 -0
  54. package/dist/cjs/action/response/ReadResult.d.ts.map +1 -0
  55. package/dist/cjs/action/response/ReadResult.js +22 -0
  56. package/dist/cjs/action/response/ReadResult.js.map +6 -0
  57. package/dist/cjs/action/response/SubscribeResult.d.ts +13 -0
  58. package/dist/cjs/action/response/SubscribeResult.d.ts.map +1 -0
  59. package/dist/cjs/action/response/SubscribeResult.js +22 -0
  60. package/dist/cjs/action/response/SubscribeResult.js.map +6 -0
  61. package/dist/cjs/action/response/WriteResult.d.ts +12 -0
  62. package/dist/cjs/action/response/WriteResult.d.ts.map +1 -0
  63. package/dist/cjs/action/response/WriteResult.js +22 -0
  64. package/dist/cjs/action/response/WriteResult.js.map +6 -0
  65. package/dist/cjs/action/response/index.d.ts +10 -0
  66. package/dist/cjs/action/response/index.d.ts.map +1 -0
  67. package/dist/cjs/action/response/index.js +27 -0
  68. package/dist/cjs/action/response/index.js.map +6 -0
  69. package/dist/cjs/action/server/AccessControl.d.ts +152 -0
  70. package/dist/cjs/action/server/AccessControl.d.ts.map +1 -0
  71. package/dist/cjs/action/server/AccessControl.js +287 -0
  72. package/dist/cjs/action/server/AccessControl.js.map +6 -0
  73. package/dist/cjs/action/server/AttributeResponse.d.ts +36 -0
  74. package/dist/cjs/action/server/AttributeResponse.d.ts.map +1 -0
  75. package/dist/cjs/action/server/AttributeResponse.js +352 -0
  76. package/dist/cjs/action/server/AttributeResponse.js.map +6 -0
  77. package/dist/cjs/action/server/ServerInteraction.d.ts +35 -0
  78. package/dist/cjs/action/server/ServerInteraction.d.ts.map +1 -0
  79. package/dist/cjs/action/server/ServerInteraction.js +52 -0
  80. package/dist/cjs/action/server/ServerInteraction.js.map +6 -0
  81. package/dist/cjs/action/server/index.d.ts +9 -0
  82. package/dist/cjs/action/server/index.d.ts.map +1 -0
  83. package/dist/cjs/action/server/index.js +26 -0
  84. package/dist/cjs/action/server/index.js.map +6 -0
  85. package/dist/cjs/index.d.ts +1 -0
  86. package/dist/cjs/index.d.ts.map +1 -1
  87. package/dist/cjs/index.js +1 -0
  88. package/dist/cjs/index.js.map +1 -1
  89. package/dist/cjs/interaction/AccessControlManager.d.ts +1 -1
  90. package/dist/cjs/interaction/AccessControlManager.d.ts.map +1 -1
  91. package/dist/cjs/interaction/AccessControlManager.js +2 -2
  92. package/dist/cjs/interaction/AccessControlManager.js.map +1 -1
  93. package/dist/cjs/interaction/AttributeDataEncoder.d.ts +1 -3
  94. package/dist/cjs/interaction/AttributeDataEncoder.d.ts.map +1 -1
  95. package/dist/cjs/interaction/InteractionMessenger.d.ts +5 -5
  96. package/dist/cjs/interaction/InteractionMessenger.d.ts.map +1 -1
  97. package/dist/cjs/interaction/InteractionServer.d.ts +1 -1
  98. package/dist/cjs/interaction/InteractionServer.d.ts.map +1 -1
  99. package/dist/cjs/interaction/InteractionServer.js +2 -2
  100. package/dist/cjs/interaction/InteractionServer.js.map +1 -1
  101. package/dist/cjs/interaction/ServerSubscription.d.ts +2 -2
  102. package/dist/cjs/interaction/ServerSubscription.d.ts.map +1 -1
  103. package/dist/cjs/interaction/ServerSubscription.js +0 -1
  104. package/dist/cjs/interaction/ServerSubscription.js.map +1 -1
  105. package/dist/cjs/mdns/MdnsScanner.d.ts +2 -2
  106. package/dist/esm/action/Interactable.d.ts +36 -0
  107. package/dist/esm/action/Interactable.d.ts.map +1 -0
  108. package/dist/esm/action/Interactable.js +6 -0
  109. package/dist/esm/action/Interactable.js.map +6 -0
  110. package/dist/esm/action/Val.d.ts +94 -0
  111. package/dist/esm/action/Val.d.ts.map +1 -0
  112. package/dist/esm/action/Val.js +13 -0
  113. package/dist/esm/action/Val.js.map +6 -0
  114. package/dist/esm/action/errors.d.ts +69 -0
  115. package/dist/esm/action/errors.d.ts.map +1 -0
  116. package/dist/esm/action/errors.js +88 -0
  117. package/dist/esm/action/errors.js.map +6 -0
  118. package/dist/esm/action/index.d.ts +13 -0
  119. package/dist/esm/action/index.d.ts.map +1 -0
  120. package/dist/esm/action/index.js +13 -0
  121. package/dist/esm/action/index.js.map +6 -0
  122. package/dist/esm/action/protocols.d.ts +118 -0
  123. package/dist/esm/action/protocols.d.ts.map +1 -0
  124. package/dist/esm/action/protocols.js +6 -0
  125. package/dist/esm/action/protocols.js.map +6 -0
  126. package/dist/esm/action/request/Invoke.d.ts +35 -0
  127. package/dist/esm/action/request/Invoke.d.ts.map +1 -0
  128. package/dist/esm/action/request/Invoke.js +60 -0
  129. package/dist/esm/action/request/Invoke.js.map +6 -0
  130. package/dist/esm/action/request/MalformedRequestError.d.ts +14 -0
  131. package/dist/esm/action/request/MalformedRequestError.d.ts.map +1 -0
  132. package/dist/esm/action/request/MalformedRequestError.js +12 -0
  133. package/dist/esm/action/request/MalformedRequestError.js.map +6 -0
  134. package/dist/esm/action/request/Read.d.ts +141 -0
  135. package/dist/esm/action/request/Read.d.ts.map +1 -0
  136. package/dist/esm/action/request/Read.js +153 -0
  137. package/dist/esm/action/request/Read.js.map +6 -0
  138. package/dist/esm/action/request/Specifier.d.ts +82 -0
  139. package/dist/esm/action/request/Specifier.d.ts.map +1 -0
  140. package/dist/esm/action/request/Specifier.js +68 -0
  141. package/dist/esm/action/request/Specifier.js.map +6 -0
  142. package/dist/esm/action/request/Subscribe.d.ts +26 -0
  143. package/dist/esm/action/request/Subscribe.d.ts.map +1 -0
  144. package/dist/esm/action/request/Subscribe.js +30 -0
  145. package/dist/esm/action/request/Subscribe.js.map +6 -0
  146. package/dist/esm/action/request/Write.d.ts +10 -0
  147. package/dist/esm/action/request/Write.d.ts.map +1 -0
  148. package/dist/esm/action/request/Write.js +6 -0
  149. package/dist/esm/action/request/Write.js.map +6 -0
  150. package/dist/esm/action/request/index.d.ts +11 -0
  151. package/dist/esm/action/request/index.d.ts.map +1 -0
  152. package/dist/esm/action/request/index.js +11 -0
  153. package/dist/esm/action/request/index.js.map +6 -0
  154. package/dist/esm/action/response/InvokeResult.d.ts +15 -0
  155. package/dist/esm/action/response/InvokeResult.d.ts.map +1 -0
  156. package/dist/esm/action/response/InvokeResult.js +6 -0
  157. package/dist/esm/action/response/InvokeResult.js.map +6 -0
  158. package/dist/esm/action/response/ReadResult.d.ts +63 -0
  159. package/dist/esm/action/response/ReadResult.d.ts.map +1 -0
  160. package/dist/esm/action/response/ReadResult.js +6 -0
  161. package/dist/esm/action/response/ReadResult.js.map +6 -0
  162. package/dist/esm/action/response/SubscribeResult.d.ts +13 -0
  163. package/dist/esm/action/response/SubscribeResult.d.ts.map +1 -0
  164. package/dist/esm/action/response/SubscribeResult.js +6 -0
  165. package/dist/esm/action/response/SubscribeResult.js.map +6 -0
  166. package/dist/esm/action/response/WriteResult.d.ts +12 -0
  167. package/dist/esm/action/response/WriteResult.d.ts.map +1 -0
  168. package/dist/esm/action/response/WriteResult.js +6 -0
  169. package/dist/esm/action/response/WriteResult.js.map +6 -0
  170. package/dist/esm/action/response/index.d.ts +10 -0
  171. package/dist/esm/action/response/index.d.ts.map +1 -0
  172. package/dist/esm/action/response/index.js +10 -0
  173. package/dist/esm/action/response/index.js.map +6 -0
  174. package/dist/esm/action/server/AccessControl.d.ts +152 -0
  175. package/dist/esm/action/server/AccessControl.d.ts.map +1 -0
  176. package/dist/esm/action/server/AccessControl.js +267 -0
  177. package/dist/esm/action/server/AccessControl.js.map +6 -0
  178. package/dist/esm/action/server/AttributeResponse.d.ts +36 -0
  179. package/dist/esm/action/server/AttributeResponse.d.ts.map +1 -0
  180. package/dist/esm/action/server/AttributeResponse.js +339 -0
  181. package/dist/esm/action/server/AttributeResponse.js.map +6 -0
  182. package/dist/esm/action/server/ServerInteraction.d.ts +35 -0
  183. package/dist/esm/action/server/ServerInteraction.d.ts.map +1 -0
  184. package/dist/esm/action/server/ServerInteraction.js +32 -0
  185. package/dist/esm/action/server/ServerInteraction.js.map +6 -0
  186. package/dist/esm/action/server/index.d.ts +9 -0
  187. package/dist/esm/action/server/index.d.ts.map +1 -0
  188. package/dist/esm/action/server/index.js +9 -0
  189. package/dist/esm/action/server/index.js.map +6 -0
  190. package/dist/esm/index.d.ts +1 -0
  191. package/dist/esm/index.d.ts.map +1 -1
  192. package/dist/esm/index.js +1 -0
  193. package/dist/esm/index.js.map +1 -1
  194. package/dist/esm/interaction/AccessControlManager.d.ts +1 -1
  195. package/dist/esm/interaction/AccessControlManager.d.ts.map +1 -1
  196. package/dist/esm/interaction/AccessControlManager.js +2 -2
  197. package/dist/esm/interaction/AccessControlManager.js.map +1 -1
  198. package/dist/esm/interaction/AttributeDataEncoder.d.ts +1 -3
  199. package/dist/esm/interaction/AttributeDataEncoder.d.ts.map +1 -1
  200. package/dist/esm/interaction/InteractionMessenger.d.ts +5 -5
  201. package/dist/esm/interaction/InteractionMessenger.d.ts.map +1 -1
  202. package/dist/esm/interaction/InteractionServer.d.ts +1 -1
  203. package/dist/esm/interaction/InteractionServer.d.ts.map +1 -1
  204. package/dist/esm/interaction/InteractionServer.js +2 -2
  205. package/dist/esm/interaction/InteractionServer.js.map +1 -1
  206. package/dist/esm/interaction/ServerSubscription.d.ts +2 -2
  207. package/dist/esm/interaction/ServerSubscription.d.ts.map +1 -1
  208. package/dist/esm/interaction/ServerSubscription.js +0 -1
  209. package/dist/esm/interaction/ServerSubscription.js.map +1 -1
  210. package/dist/esm/mdns/MdnsScanner.d.ts +2 -2
  211. package/package.json +6 -6
  212. package/src/action/Interactable.ts +40 -0
  213. package/src/action/Val.ts +111 -0
  214. package/src/action/errors.ts +119 -0
  215. package/src/action/index.ts +13 -0
  216. package/src/action/protocols.ts +134 -0
  217. package/src/action/request/Invoke.ts +93 -0
  218. package/src/action/request/MalformedRequestError.ts +14 -0
  219. package/src/action/request/Read.ts +356 -0
  220. package/src/action/request/Specifier.ts +146 -0
  221. package/src/action/request/Subscribe.ts +54 -0
  222. package/src/action/request/Write.ts +13 -0
  223. package/src/action/request/index.ts +11 -0
  224. package/src/action/response/InvokeResult.ts +17 -0
  225. package/src/action/response/ReadResult.ts +89 -0
  226. package/src/action/response/SubscribeResult.ts +14 -0
  227. package/src/action/response/WriteResult.ts +13 -0
  228. package/src/action/response/index.ts +10 -0
  229. package/src/action/server/AccessControl.ts +494 -0
  230. package/src/action/server/AttributeResponse.ts +413 -0
  231. package/src/action/server/ServerInteraction.ts +64 -0
  232. package/src/action/server/index.ts +9 -0
  233. package/src/index.ts +1 -0
  234. package/src/interaction/AccessControlManager.ts +3 -3
  235. package/src/interaction/InteractionServer.ts +2 -3
  236. package/src/interaction/ServerSubscription.ts +0 -2
@@ -0,0 +1,356 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022-2025 Matter.js Authors
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import { FALLBACK_INTERACTIONMODEL_REVISION } from "#session/Session.js";
8
+ import type {
9
+ AttributePath,
10
+ ClusterType,
11
+ DataVersionFilter,
12
+ EventFilter,
13
+ EventPath,
14
+ GlobalAttributes,
15
+ ReadRequest,
16
+ } from "#types";
17
+ import { camelize } from "@matter/general";
18
+ import { MalformedRequestError } from "./MalformedRequestError.js";
19
+ import { Specifier } from "./Specifier.js";
20
+
21
+ /**
22
+ * A read request formulated using Matter protocol semantics.
23
+ */
24
+ export interface Read extends ReadRequest {}
25
+
26
+ /**
27
+ * Formulate a read request using Matter numeric IDs.
28
+ */
29
+ export function Read(options: Read.Options): Read;
30
+
31
+ /**
32
+ * Formulate a read request with extended options and name-based IDs.
33
+ */
34
+ export function Read(options: Read.Options, ...selectors: Read.Selector[]): Read;
35
+
36
+ /**
37
+ * Formulate a read request with name-based IDs.
38
+ */
39
+ export function Read(...selectors: Read.Selector[]): Read;
40
+
41
+ export function Read(optionsOrSelector: Read.Options | Read.Selector, ...selectors: Read.Selector[]): Read {
42
+ let options;
43
+ if ("kind" in optionsOrSelector) {
44
+ selectors = [optionsOrSelector, ...selectors];
45
+ options = {};
46
+ } else {
47
+ options = optionsOrSelector;
48
+ }
49
+ let { attributes: attributeRequests, versionFilters, events: eventRequests, eventFilters } = options;
50
+
51
+ const result: Read = {
52
+ isFabricFiltered: options.fabricFilter ?? true,
53
+ interactionModelRevision: options.interactionModelRevision ?? FALLBACK_INTERACTIONMODEL_REVISION,
54
+ };
55
+
56
+ for (const selector of selectors) {
57
+ reifySelector(selector);
58
+ }
59
+
60
+ if (!attributeRequests?.length && !eventRequests?.length) {
61
+ throw new MalformedRequestError(`Read action designates no attributes or events`);
62
+ }
63
+
64
+ if (attributeRequests) {
65
+ result.attributeRequests = attributeRequests;
66
+ }
67
+
68
+ if (versionFilters) {
69
+ result.dataVersionFilters = versionFilters;
70
+ }
71
+
72
+ if (eventRequests) {
73
+ result.eventRequests = eventRequests;
74
+ }
75
+
76
+ if (eventFilters !== undefined) {
77
+ result.eventFilters = eventFilters;
78
+ }
79
+
80
+ return result;
81
+
82
+ function reifySelector(selector: Read.Selector) {
83
+ switch (selector.kind) {
84
+ case "attribute":
85
+ reifyAttributeSelector(selector);
86
+ break;
87
+
88
+ case "event":
89
+ reifyEventSelector(selector);
90
+ break;
91
+
92
+ default:
93
+ throw new MalformedRequestError(`Invalid selector kind "${(selector as Read.Selector).kind}"`);
94
+ }
95
+ }
96
+
97
+ /**
98
+ * Update "real" ReadRequest fields from our convenience attribute "selector".
99
+ */
100
+ function reifyAttributeSelector(selector: Read.AttributeSelector) {
101
+ const cluster = Specifier.clusterOf(selector);
102
+ const { endpoint } = selector;
103
+
104
+ // Install data version filter if the endpoint reports it has complete version information
105
+ if (typeof endpoint === "object" && endpoint?.versions && typeof cluster === "object" && cluster !== null) {
106
+ const version = endpoint.versions?.[camelize(cluster.name)];
107
+ if (version !== undefined) {
108
+ const filter = {
109
+ path: { endpointId: endpoint.number, clusterId: cluster.id },
110
+ dataVersion: version,
111
+ };
112
+ if (versionFilters === undefined) {
113
+ versionFilters = [filter];
114
+ } else if (
115
+ versionFilters.find(
116
+ ({ path: { endpointId, clusterId } }) =>
117
+ endpointId === endpoint.number && clusterId === cluster.id,
118
+ ) === undefined
119
+ ) {
120
+ versionFilters.push(filter);
121
+ }
122
+ }
123
+ }
124
+
125
+ // Configure base AttributePath
126
+ if (attributeRequests === undefined) {
127
+ attributeRequests = [];
128
+ }
129
+ const prototype: AttributePath = {};
130
+ if (endpoint !== undefined) {
131
+ prototype.endpointId = Specifier.endpointIdOf(selector);
132
+ }
133
+ if (cluster !== undefined) {
134
+ prototype.clusterId = cluster.id;
135
+ }
136
+
137
+ // If the attribute is a wildcard we are done
138
+ let { attributes } = selector;
139
+ if (attributes === undefined) {
140
+ attributeRequests.push(prototype);
141
+ return;
142
+ }
143
+
144
+ // Add concrete attribute requests
145
+ if (!Array.isArray(attributes)) {
146
+ attributes = [attributes];
147
+ }
148
+ for (const specifier of attributes) {
149
+ attributeRequests.push({ ...prototype, attributeId: Specifier.attributeFor(cluster, specifier).id });
150
+ }
151
+ }
152
+
153
+ /**
154
+ * Update "real" ReadRequest fields from our convenience event "selector"
155
+ */
156
+ function reifyEventSelector(selector: Read.EventSelector) {
157
+ const cluster = Specifier.clusterOf(selector);
158
+ const { endpoint } = selector;
159
+
160
+ // Install event minimum if the endpoint reports ingested events
161
+ if (typeof endpoint === "object" && endpoint.minEvent !== undefined) {
162
+ if (eventFilters === undefined) {
163
+ eventFilters = [{ eventMin: endpoint.minEvent }];
164
+ }
165
+ }
166
+
167
+ // Configure base EventPath
168
+ if (eventRequests === undefined) {
169
+ eventRequests = [];
170
+ }
171
+ const prototype: EventPath = {};
172
+ if (endpoint !== undefined) {
173
+ prototype.endpointId = Specifier.endpointIdOf(selector);
174
+ }
175
+ if (cluster !== undefined) {
176
+ prototype.clusterId = cluster.id;
177
+ }
178
+
179
+ // If the event is a wildcard we are done
180
+ let { events } = selector;
181
+ if (events === undefined) {
182
+ eventRequests.push(prototype);
183
+ return;
184
+ }
185
+
186
+ // Add concrete event requests
187
+ if (!Array.isArray(events)) {
188
+ events = [events];
189
+ }
190
+ for (const specifier of events) {
191
+ eventRequests.push({ ...prototype, eventId: Specifier.eventFor(cluster, specifier).id });
192
+ }
193
+ }
194
+ }
195
+
196
+ export namespace Read {
197
+ export interface Options {
198
+ attributes?: AttributePath[];
199
+ versionFilters?: DataVersionFilter[];
200
+ events?: EventPath[];
201
+ eventFilters?: EventFilter[];
202
+ fabricFilter?: boolean;
203
+ interactionModelRevision?: number;
204
+ }
205
+
206
+ export interface Attributes extends Read {
207
+ attributeRequests: Exclude<Read["attributeRequests"], undefined>;
208
+ }
209
+
210
+ export function isAttribute(request: Read): request is Attributes {
211
+ return !!request.attributeRequests?.length;
212
+ }
213
+
214
+ export interface Events extends Read {
215
+ eventRequests: Exclude<Read["eventRequests"], undefined>;
216
+ }
217
+
218
+ export function isEvent(request: Read): request is Events {
219
+ return !!request.eventRequests?.length;
220
+ }
221
+
222
+ /**
223
+ * Selects attributes or events to read.
224
+ */
225
+ export type Selector<C extends Specifier.Cluster = Specifier.Cluster> =
226
+ | ({ kind: "attribute" } & AttributeSelector<C>)
227
+ | ({ kind: "event" } & EventSelector<C>);
228
+
229
+ /**
230
+ * Selects attributes to read. Limits fields to legal permutations per the Matter specification.
231
+ */
232
+ export type AttributeSelector<C extends Specifier.Cluster = Specifier.Cluster> =
233
+ | AttributeSelector.Concrete<C>
234
+ | AttributeSelector.FullWildcard
235
+ | AttributeSelector.Global
236
+ | AttributeSelector.WildcardEndpoint<C>
237
+ | AttributeSelector.WildcardAttribute
238
+ | AttributeSelector.Endpoint;
239
+
240
+ /**
241
+ * Selects events to read. Limits fields to legal permutations per the Matter specification.
242
+ */
243
+ export type EventSelector<C extends Specifier.Cluster = Specifier.Cluster> =
244
+ | EventSelector.Concrete<C>
245
+ | EventSelector.FullWildcard
246
+ | EventSelector.WildcardEndpoint<C>
247
+ | EventSelector.WildcardEvent
248
+ | EventSelector.Endpoint;
249
+
250
+ export function Attribute<const C extends ClusterType>(
251
+ selector?: AttributeSelector<C>,
252
+ ): { kind: "attribute" } & AttributeSelector<C> {
253
+ return {
254
+ kind: "attribute",
255
+ ...selector,
256
+ };
257
+ }
258
+
259
+ export function Event<const T extends EventSelector>(selector: T): { kind: "event" } & T {
260
+ return {
261
+ kind: "event",
262
+ ...selector,
263
+ };
264
+ }
265
+
266
+ export interface WildcardFlags {
267
+ skipRoot?: boolean;
268
+ skipCustom?: boolean;
269
+ skipDiagnostics?: boolean;
270
+ skipGlobals?: boolean;
271
+ skipAttributeList?: boolean;
272
+ skipCommandList?: boolean;
273
+ skipFixed?: boolean;
274
+ skipChangesOmitted?: boolean;
275
+ }
276
+
277
+ export type GlobalAttributeSpecifier = ClusterType.Attribute | keyof GlobalAttributes<any>;
278
+
279
+ export namespace AttributeSelector {
280
+ export interface Concrete<C extends Specifier.Cluster> {
281
+ endpoint: Specifier.Endpoint;
282
+ cluster: C;
283
+ attributes: Specifier.Attribute<Specifier.ClusterFor<C>> | Specifier.Attribute<Specifier.ClusterFor<C>>[];
284
+ }
285
+
286
+ export interface Wildcard {
287
+ flags?: WildcardFlags;
288
+ }
289
+
290
+ export interface FullWildcard extends Wildcard {
291
+ endpoint?: undefined;
292
+ cluster?: undefined;
293
+ attributes?: undefined;
294
+ }
295
+
296
+ export interface Global extends Wildcard {
297
+ endpoint?: Specifier.Endpoint;
298
+ cluster?: undefined;
299
+ attributes: GlobalAttributeSpecifier | GlobalAttributeSpecifier[];
300
+ }
301
+
302
+ export interface WildcardEndpoint<C extends Specifier.Cluster> extends Wildcard {
303
+ endpoint?: undefined;
304
+ cluster: C;
305
+ attributes: Specifier.Attribute<Specifier.ClusterFor<C>> | Specifier.Attribute<Specifier.ClusterFor<C>>[];
306
+ }
307
+
308
+ export interface WildcardAttribute extends Wildcard {
309
+ endpoint?: Specifier.Endpoint;
310
+ cluster: Specifier.Cluster;
311
+ attributes?: undefined;
312
+ }
313
+
314
+ export interface Endpoint extends Wildcard {
315
+ endpoint: Specifier.Endpoint;
316
+ cluster?: undefined;
317
+ attributes?: undefined;
318
+ }
319
+ }
320
+
321
+ export namespace EventSelector {
322
+ export interface Concrete<C extends Specifier.Cluster> {
323
+ endpoint: Specifier.Endpoint;
324
+ cluster: Specifier.Cluster;
325
+ events: Specifier.Event<Specifier.ClusterFor<C>> | Specifier.Event<Specifier.ClusterFor<C>>[];
326
+ }
327
+
328
+ export interface Wildcard {
329
+ flags?: WildcardFlags;
330
+ }
331
+
332
+ export interface FullWildcard extends Wildcard {
333
+ endpoint?: undefined;
334
+ cluster?: undefined;
335
+ events?: undefined;
336
+ }
337
+
338
+ export interface WildcardEndpoint<C extends Specifier.Cluster> extends Wildcard {
339
+ endpoint?: undefined;
340
+ cluster: Specifier.Cluster;
341
+ events: Specifier.Event<Specifier.ClusterFor<C>> | Specifier.Event<Specifier.ClusterFor<C>>[];
342
+ }
343
+
344
+ export interface WildcardEvent extends Wildcard {
345
+ endpoint: Specifier.Endpoint;
346
+ cluster: Specifier.Cluster;
347
+ events?: undefined;
348
+ }
349
+
350
+ export interface Endpoint extends Wildcard {
351
+ endpoint: Specifier.Endpoint;
352
+ cluster?: undefined;
353
+ events?: undefined;
354
+ }
355
+ }
356
+ }
@@ -0,0 +1,146 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022-2025 Matter.js Authors
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import { ClusterType, EndpointNumber, GlobalAttributeNames, GlobalAttributes } from "#types";
8
+ import { MalformedRequestError } from "./MalformedRequestError.js";
9
+
10
+ const GlobalAttrMap = GlobalAttributes({}) as Record<string, ClusterType.Attribute>;
11
+
12
+ /**
13
+ * A "specifier" addresses a specific element of the Matter data model in the context of a request.
14
+ */
15
+ export namespace Specifier {
16
+ /**
17
+ * Clusters we designate with an object to convey structural and type information. The second form of this union
18
+ * allows for specification with a host object (such as a ClusterBehavior instance or class).
19
+ */
20
+ export type Cluster = ClusterType | { cluster: ClusterType };
21
+
22
+ /**
23
+ * You may address endpoints with a bare ID but the object form allows an "endpoint object" as input and optionally
24
+ * conveys additional metadata.
25
+ */
26
+ export type Endpoint =
27
+ | EndpointNumber
28
+ | { number: EndpointNumber; versions?: Record<string, number>; minEvent?: number };
29
+
30
+ /**
31
+ * An attribute specifier may be the name of a cluster attribute or the name of a cluster or global attribute.
32
+ */
33
+ export type Attribute<C extends ClusterType = ClusterType> =
34
+ | ClusterType.Attribute
35
+ | (string & keyof C["attributes"])
36
+ | GlobalAttributeNames<any>;
37
+
38
+ /**
39
+ * A command specifier may be the name of a cluster attribute or the name of a cluster command.
40
+ */
41
+ export type Command<C extends ClusterType = ClusterType> = ClusterType.Command | (string & keyof C["commands"]);
42
+
43
+ /**
44
+ * An event specifier may be the name of a cluser event or an event object.
45
+ */
46
+ export type Event<C extends ClusterType = ClusterType> = ClusterType.Event | (string & keyof C["events"]);
47
+
48
+ /**
49
+ * Extract a cluster type from a cluster specifier type.
50
+ */
51
+ export type ClusterFor<T extends Cluster> = T extends ClusterType
52
+ ? T
53
+ : T extends { cluster: ClusterType }
54
+ ? T["cluster"]
55
+ : never;
56
+
57
+ /**
58
+ * Extract a cluster type from a cluster specifier.
59
+ */
60
+ export function clusterFor<const T extends Cluster>(specifier: T) {
61
+ if ("cluster" in specifier) {
62
+ return specifier["cluster"] as ClusterFor<T>;
63
+ }
64
+ return specifier as ClusterFor<T>;
65
+ }
66
+
67
+ /**
68
+ * Extract an attribute object from a cluster and attribute specifier.
69
+ */
70
+ export function attributeFor(cluster: ClusterType | undefined, specifier: Specifier.Attribute) {
71
+ if (typeof specifier === "object") {
72
+ return specifier;
73
+ }
74
+
75
+ if (cluster === undefined) {
76
+ const attr = GlobalAttrMap[specifier];
77
+ if (attr === undefined) {
78
+ throw new MalformedRequestError(`Cannot designate event "${specifier}" without a cluster`);
79
+ }
80
+ return attr;
81
+ }
82
+
83
+ const attr = cluster.attributes?.[specifier];
84
+ if (attr === undefined) {
85
+ throw new MalformedRequestError(`Cluster ${cluster.name} does not define attribute ${specifier}`);
86
+ }
87
+
88
+ return attr;
89
+ }
90
+
91
+ /**
92
+ * Extract a command type from a cluster type and command specifier.
93
+ */
94
+ export type CommandFor<C extends ClusterType, CMD extends Specifier.Command<C>> = CMD extends string
95
+ ? C["commands"][CMD]
96
+ : CMD extends ClusterType.Command
97
+ ? CMD
98
+ : never;
99
+
100
+ /**
101
+ * Extract an event object from a cluster and event specifier.
102
+ */
103
+ export function eventFor(cluster: ClusterType | undefined, specifier: Specifier.Event) {
104
+ if (typeof specifier === "object") {
105
+ return specifier;
106
+ }
107
+
108
+ if (cluster === undefined) {
109
+ throw new MalformedRequestError(`Cannot designate event "${specifier}" without a cluster`);
110
+ }
111
+
112
+ const event = cluster.events?.[specifier];
113
+ if (event === undefined) {
114
+ throw new MalformedRequestError(`Cluster ${cluster.name} does not define event ${specifier}`);
115
+ }
116
+
117
+ return event;
118
+ }
119
+
120
+ /**
121
+ * Extract the cluster type from a cluster request type.
122
+ */
123
+ export type ClusterOf<T extends { cluster?: Cluster }> = T extends { cluster: Specifier.Cluster }
124
+ ? Specifier.ClusterFor<T["cluster"]>
125
+ : undefined;
126
+
127
+ /**
128
+ * Extract the cluster type from an element request.
129
+ */
130
+ export function clusterOf<const T extends { cluster?: Cluster }>(request: T): ClusterOf<T> {
131
+ if (request.cluster) {
132
+ return Specifier.clusterFor(request.cluster) as ClusterOf<T>;
133
+ }
134
+ return undefined as ClusterOf<T>;
135
+ }
136
+
137
+ /**
138
+ * Determine endpoint number for an object with an endpoint specifier.
139
+ */
140
+ export function endpointIdOf<const T extends { endpoint?: Endpoint }>(request: T): EndpointNumber | undefined {
141
+ if (typeof request.endpoint === "number") {
142
+ return request.endpoint;
143
+ }
144
+ return request.endpoint?.number;
145
+ }
146
+ }
@@ -0,0 +1,54 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022-2025 Matter.js Authors
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import { UINT16_MAX } from "#general";
8
+ import { MalformedRequestError } from "./MalformedRequestError.js";
9
+ import { Read } from "./Read.js";
10
+
11
+ /**
12
+ * Defines a subscription.
13
+ *
14
+ * The subscription interval fields are optional as matter.js will set them to appropriate defaults based on physical
15
+ * attributes of the target device. If you are unsure of appropriate values do not set them.
16
+ */
17
+ export interface Subscribe extends Read {
18
+ keepSubscriptions: boolean;
19
+ minIntervalFloorSeconds?: number;
20
+ maxIntervalCeilingSeconds?: number;
21
+ }
22
+
23
+ export function Subscribe(options: Subscribe.Options): Subscribe {
24
+ const subscribe = Read(options) as unknown as Subscribe;
25
+
26
+ const { keepSubscriptions, minIntervalFloorSeconds, maxIntervalCeilingSeconds } = options;
27
+ subscribe.keepSubscriptions = keepSubscriptions ?? true;
28
+
29
+ if (minIntervalFloorSeconds !== undefined) {
30
+ if (minIntervalFloorSeconds < 0 || minIntervalFloorSeconds > UINT16_MAX) {
31
+ throw new MalformedRequestError(`Minimum interval floor ${minIntervalFloorSeconds} is out of range`);
32
+ }
33
+ subscribe.minIntervalFloorSeconds = minIntervalFloorSeconds;
34
+ }
35
+
36
+ if (maxIntervalCeilingSeconds !== undefined) {
37
+ if (maxIntervalCeilingSeconds < 0 || maxIntervalCeilingSeconds > UINT16_MAX) {
38
+ throw new MalformedRequestError(`Maximum interval ceiling ${maxIntervalCeilingSeconds} is out of range`);
39
+ }
40
+ subscribe.maxIntervalCeilingSeconds = maxIntervalCeilingSeconds;
41
+ }
42
+
43
+ return subscribe;
44
+ }
45
+
46
+ export namespace Subscribe {
47
+ export interface Options extends Read.Options {
48
+ keepSubscriptions?: boolean;
49
+ minIntervalFloorSeconds?: number;
50
+ maxIntervalCeilingSeconds?: number;
51
+ }
52
+ }
53
+
54
+ // TODO - subscribe DSL extending read DSL
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022-2025 Matter.js Authors
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import { WriteRequest } from "#types";
8
+
9
+ export interface Write extends WriteRequest {
10
+ timeout?: number;
11
+ }
12
+
13
+ // TODO - write DSL
@@ -0,0 +1,11 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022-2025 Matter.js Authors
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ export * from "./Invoke.js";
8
+ export * from "./Read.js";
9
+ export * from "./Specifier.js";
10
+ export * from "./Subscribe.js";
11
+ export * from "./Write.js";
@@ -0,0 +1,17 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022-2025 Matter.js Authors
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import type { Invoke } from "#action/request/Invoke.js";
8
+ import type { CommandData } from "#types";
9
+ import { CancelablePromise } from "@matter/general";
10
+
11
+ export type InvokeResult<T extends Invoke> = T extends { suppressResponse: true }
12
+ ? CancelablePromise<void>
13
+ : AsyncIterable<InvokeResult.Chunk>;
14
+
15
+ export namespace InvokeResult {
16
+ export type Chunk = CommandData[];
17
+ }
@@ -0,0 +1,89 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022-2025 Matter.js Authors
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import type {
8
+ AttributeId,
9
+ AttributePath,
10
+ ClusterId,
11
+ EndpointNumber,
12
+ EventId,
13
+ EventPath,
14
+ NodeId,
15
+ Status,
16
+ StatusCode,
17
+ } from "#types";
18
+
19
+ /**
20
+ * Streaming result for a Matter protocol-level read.
21
+ *
22
+ * These structures contain data for AttributeReportIB and EventReportIB. We don't use the deeply-nested native TLV
23
+ * structure directly for reasons of performance and developer convenience.
24
+ *
25
+ * Iteration occurs in chunks for performance reasons. A chunk is an iterable of reports, one per output attribute or
26
+ * event.
27
+ */
28
+ export interface ReadResult<Chunk = ReadResult.Chunk> extends AsyncIterable<ReadResult.Chunk> {}
29
+
30
+ export namespace ReadResult {
31
+ export type Chunk = Iterable<Report>;
32
+
33
+ export type Report =
34
+ | AttributeValue
35
+ | GlobalAttributeStatus
36
+ | ClusterAttributeStatus
37
+ | EventValue
38
+ | GlobalEventStatus
39
+ | ClusterEventStatus;
40
+
41
+ export interface ConcreteAttributePath extends AttributePath {
42
+ nodeId?: NodeId;
43
+ endpointId: EndpointNumber;
44
+ clusterId: ClusterId;
45
+ attributeId: AttributeId;
46
+ }
47
+
48
+ export interface AttributeValue {
49
+ kind: "attr-value";
50
+ path: ConcreteAttributePath;
51
+ value: unknown;
52
+ }
53
+
54
+ export interface GlobalAttributeStatus {
55
+ kind: "attr-status";
56
+ path: ConcreteAttributePath;
57
+ status: StatusCode;
58
+ }
59
+
60
+ export interface ClusterAttributeStatus {
61
+ kind: "attr-cluster-status";
62
+ path: ConcreteAttributePath;
63
+ clusterStatus: number;
64
+ }
65
+
66
+ export interface ConcreteEventPath extends EventPath {
67
+ nodeId?: NodeId;
68
+ endpointId: EndpointNumber;
69
+ clusterId: ClusterId;
70
+ eventId: EventId;
71
+ }
72
+
73
+ export interface EventValue {
74
+ kind: "event-value";
75
+ path: ConcreteEventPath;
76
+ }
77
+
78
+ export interface GlobalEventStatus {
79
+ kind: "event-status";
80
+ path: ConcreteEventPath;
81
+ status: Status;
82
+ }
83
+
84
+ export interface ClusterEventStatus {
85
+ kind: "event-cluster-status";
86
+ path: ConcreteEventPath;
87
+ clusterStatus: number;
88
+ }
89
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022-2025 Matter.js Authors
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import { SubscribeResponse } from "#types";
8
+ import { ReadResult } from "./ReadResult.js";
9
+
10
+ export interface SubscribeResult extends AsyncIterator<SubscribeResult.Chunk> {}
11
+
12
+ export namespace SubscribeResult {
13
+ export type Chunk = ReadResult.Chunk | SubscribeResponse;
14
+ }