@matter-server/ws-controller 0.5.7 → 0.5.9

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 (45) hide show
  1. package/dist/esm/controller/ControllerCommandHandler.d.ts +3 -3
  2. package/dist/esm/controller/ControllerCommandHandler.d.ts.map +1 -1
  3. package/dist/esm/controller/ControllerCommandHandler.js +2 -2
  4. package/dist/esm/controller/ControllerCommandHandler.js.map +1 -1
  5. package/dist/esm/controller/CustomClusterPoller.d.ts +2 -2
  6. package/dist/esm/controller/CustomClusterPoller.d.ts.map +1 -1
  7. package/dist/esm/controller/CustomClusterPoller.js +21 -5
  8. package/dist/esm/controller/CustomClusterPoller.js.map +1 -1
  9. package/dist/esm/controller/LegacyDataInjector.d.ts +3 -3
  10. package/dist/esm/controller/LegacyDataInjector.d.ts.map +1 -1
  11. package/dist/esm/controller/LegacyDataInjector.js +5 -1
  12. package/dist/esm/controller/LegacyDataInjector.js.map +1 -1
  13. package/dist/esm/controller/MatterController.d.ts.map +1 -1
  14. package/dist/esm/controller/MatterController.js +3 -3
  15. package/dist/esm/controller/MatterController.js.map +1 -1
  16. package/dist/esm/controller/TestNodeCommandHandler.d.ts +1 -1
  17. package/dist/esm/controller/TestNodeCommandHandler.d.ts.map +1 -1
  18. package/dist/esm/model/ModelMapper.js +2 -2
  19. package/dist/esm/model/ModelMapper.js.map +1 -1
  20. package/dist/esm/server/ConfigStorage.d.ts +2 -2
  21. package/dist/esm/server/ConfigStorage.d.ts.map +1 -1
  22. package/dist/esm/server/ConfigStorage.js.map +1 -1
  23. package/dist/esm/server/Converters.js +4 -4
  24. package/dist/esm/server/Converters.js.map +1 -1
  25. package/dist/esm/server/WebSocketControllerHandler.d.ts.map +1 -1
  26. package/dist/esm/server/WebSocketControllerHandler.js +7 -5
  27. package/dist/esm/server/WebSocketControllerHandler.js.map +1 -1
  28. package/dist/esm/types/CommandHandler.d.ts +2 -4
  29. package/dist/esm/types/CommandHandler.d.ts.map +1 -1
  30. package/dist/esm/types/WebSocketMessageTypes.d.ts +6 -453
  31. package/dist/esm/types/WebSocketMessageTypes.d.ts.map +1 -1
  32. package/dist/esm/types/WebSocketMessageTypes.js +4 -7
  33. package/dist/esm/types/WebSocketMessageTypes.js.map +2 -2
  34. package/package.json +7 -6
  35. package/src/controller/ControllerCommandHandler.ts +2 -2
  36. package/src/controller/CustomClusterPoller.ts +21 -7
  37. package/src/controller/LegacyDataInjector.ts +8 -4
  38. package/src/controller/MatterController.ts +4 -3
  39. package/src/model/ModelMapper.ts +2 -2
  40. package/src/server/ConfigStorage.ts +2 -2
  41. package/src/server/Converters.ts +4 -4
  42. package/src/server/WebSocketControllerHandler.ts +9 -7
  43. package/src/tsconfig.json +9 -3
  44. package/src/types/CommandHandler.ts +2 -4
  45. package/src/types/WebSocketMessageTypes.ts +38 -456
@@ -95,20 +95,20 @@ export interface LegacyVendorInfo {
95
95
 
96
96
  /** Node data from Python Matter Server nodes map */
97
97
  export interface LegacyNodeData {
98
- node_id: number;
98
+ node_id: number | bigint;
99
99
  date_commissioned: string;
100
100
  last_interview: string;
101
101
  interview_version: number;
102
102
  available: boolean;
103
103
  is_bridge: boolean;
104
104
  attributes: Record<string, unknown>;
105
- attribute_subscriptions: unknown[];
105
+ attribute_subscriptions: readonly [];
106
106
  }
107
107
 
108
108
  /** Structure of the <compressedFabricId>.json file */
109
109
  export interface LegacyServerFile {
110
110
  vendor_info: Record<string, LegacyVendorInfo>;
111
- last_node_id: number;
111
+ last_node_id: number | bigint;
112
112
  nodes: Record<string, LegacyNodeData>;
113
113
  }
114
114
 
@@ -279,9 +279,13 @@ export namespace LegacyDataInjector {
279
279
  }
280
280
  commissionedNodes.push([NodeId(BigInt(nodeId)), {}]);
281
281
  let newNode = true;
282
+ const attributes = Object.entries(nodeDetails.attributes);
283
+ if (attributes.length === 0) {
284
+ continue;
285
+ }
282
286
  logger.info(`Injecting node ${nodeId} into storage`);
283
287
  const nodeWrites = new Array<MaybePromise<void>>();
284
- for (const [attributeKey, value] of Object.entries(nodeDetails.attributes)) {
288
+ for (const [attributeKey, value] of attributes) {
285
289
  let currentEndpointId: string | undefined;
286
290
  let currentClusterId: string | undefined;
287
291
  let endpointStorage: StorageContext | undefined;
@@ -122,9 +122,10 @@ export class MatterController {
122
122
 
123
123
  // Check if the nextNodeId needs to be updated based on legacy data
124
124
  const lastNodeId = legacyData.nodeData?.last_node_id;
125
- if (typeof lastNodeId === "number") {
126
- if (config.nextNodeId <= lastNodeId) {
127
- const newNextNodeId = lastNodeId + 10;
125
+ if (typeof lastNodeId === "number" || typeof lastNodeId === "bigint") {
126
+ // Compare as BigInt to safely handle both number and bigint types
127
+ if (BigInt(config.nextNodeId) <= BigInt(lastNodeId)) {
128
+ const newNextNodeId = BigInt(lastNodeId) + 10n;
128
129
  logger.info(
129
130
  `Updating nextNodeId from ${config.nextNodeId} to ${newNextNodeId} (legacy last_node_id: ${lastNodeId})`,
130
131
  );
@@ -15,7 +15,7 @@ import {
15
15
  EventModel,
16
16
  FeatureMap,
17
17
  GeneratedCommandList,
18
- MatterModel,
18
+ Matter,
19
19
  } from "@matter/main/model";
20
20
 
21
21
  type AttributeDetails = { readonly [key: string]: AttributeModel | undefined };
@@ -53,7 +53,7 @@ export type ClusterMapType = {
53
53
  // Build the cluster map at module load time
54
54
  const clusterMapBuilder: { [key: string]: ClusterMapEntry | undefined } = {};
55
55
 
56
- MatterModel.standard.clusters.forEach(cluster => {
56
+ Matter.clusters.forEach(cluster => {
57
57
  if (cluster.id === undefined) {
58
58
  return;
59
59
  } // Skip clusters without an ID
@@ -20,7 +20,7 @@ function sanitizeForLog(key: string, value: unknown): string {
20
20
 
21
21
  interface ConfigData {
22
22
  fabricLabel: string;
23
- nextNodeId: number; // formally wrong, should be bigint
23
+ nextNodeId: number | bigint;
24
24
  wifiSsid?: string;
25
25
  wifiCredentials?: string;
26
26
  threadDataset?: string;
@@ -68,7 +68,7 @@ export class ConfigStorage {
68
68
  const fabricLabel = (await this.#configStore.has("fabricLabel"))
69
69
  ? await this.#configStore.get<string>("fabricLabel")
70
70
  : (this.#env.vars.string("fabricLabel") ?? this.#data.fabricLabel);
71
- const nextNodeId = await this.#configStore.get<number>("nextNodeId", this.#data.nextNodeId);
71
+ const nextNodeId = await this.#configStore.get<number | bigint>("nextNodeId", this.#data.nextNodeId);
72
72
 
73
73
  const wifiSsid = (await this.#configStore.has("wifiSsid"))
74
74
  ? await this.#configStore.get<string>("wifiSsid", "")
@@ -90,7 +90,7 @@ export function convertWebSocketTagBasedToMatter(
90
90
 
91
91
  // Handle lists
92
92
  if (Array.isArray(value) && model.type === "list") {
93
- return value.map(v => convertWebSocketTagBasedToMatter(v, model.members[0], clusterModel));
93
+ return value.map(v => convertWebSocketTagBasedToMatter(v, model.members.at(0), clusterModel));
94
94
  }
95
95
 
96
96
  // Handle structs - convert numeric keys to camelCased member names
@@ -136,7 +136,7 @@ export function convertCommandDataToMatter(
136
136
 
137
137
  // Handle lists
138
138
  if (Array.isArray(value) && model.type === "list") {
139
- return value.map(v => convertCommandDataToMatter(v, model.members[0], clusterModel));
139
+ return value.map(v => convertCommandDataToMatter(v, model.members.at(0), clusterModel));
140
140
  }
141
141
 
142
142
  // Handle structs - convert numeric keys to camelCased member names
@@ -303,7 +303,7 @@ function convertMatterToWebSocket(
303
303
 
304
304
  case ConvKind.List:
305
305
  return Array.isArray(value)
306
- ? value.map(v => convertMatterToWebSocket(v, model.members[0], clusterModel, tagBased))
306
+ ? value.map(v => convertMatterToWebSocket(v, model.members.at(0), clusterModel, tagBased))
307
307
  : value;
308
308
 
309
309
  case ConvKind.Struct: {
@@ -527,7 +527,7 @@ export function convertWebsocketDataToMatter(value: any, model: ValueModel): any
527
527
  value = parseChipJSON(value);
528
528
  }
529
529
  if (Array.isArray(value)) {
530
- return value.map(v => convertWebsocketDataToMatter(v, model.members[0]));
530
+ return value.map(v => convertWebsocketDataToMatter(v, model.members.at(0)!));
531
531
  }
532
532
  }
533
533
 
@@ -361,7 +361,6 @@ export class WebSocketControllerHandler implements WebServerHandler {
361
361
  }
362
362
  }
363
363
  });
364
- console.log("send close to clients");
365
364
 
366
365
  const wss = this.#wss;
367
366
  // Wait for the WebSocket server to close properly
@@ -379,7 +378,7 @@ export class WebSocketControllerHandler implements WebServerHandler {
379
378
  async #handleWebSocketRequest(
380
379
  connId: string,
381
380
  data: string,
382
- ): Promise<{ response: ErrorResultMessage | SuccessResultMessage<any>; enableListeners?: boolean }> {
381
+ ): Promise<{ response: ErrorResultMessage | SuccessResultMessage; enableListeners?: boolean }> {
383
382
  let messageId: string | undefined;
384
383
  try {
385
384
  logger.debug(`[${connId}] WebSocket request`, () => data);
@@ -603,7 +602,9 @@ export class WebSocketControllerHandler implements WebServerHandler {
603
602
  }
604
603
  }
605
604
 
606
- await this.#config.set({ nextNodeId: nextNodeId + 1 });
605
+ await this.#config.set({
606
+ nextNodeId: typeof nextNodeId === "bigint" ? nextNodeId + 1n : nextNodeId + 1,
607
+ });
607
608
 
608
609
  const { nodeId } = await this.#commandHandler.commissionNode({
609
610
  nodeId: NodeId(nextNodeId),
@@ -657,7 +658,9 @@ export class WebSocketControllerHandler implements WebServerHandler {
657
658
  break;
658
659
  }
659
660
 
660
- await this.#config.set({ nextNodeId: nextNodeId + 1 });
661
+ await this.#config.set({
662
+ nextNodeId: typeof nextNodeId === "bigint" ? nextNodeId + 1n : nextNodeId + 1,
663
+ });
661
664
 
662
665
  const { nodeId } = await this.#commandHandler.commissionNode(commissionRequest);
663
666
 
@@ -796,7 +799,6 @@ export class WebSocketControllerHandler implements WebServerHandler {
796
799
  cluster_id: clusterId,
797
800
  command_name: commandName,
798
801
  payload,
799
- response_type,
800
802
  timed_request_timeout_ms: timedInteractionTimeoutMs,
801
803
  } = args;
802
804
 
@@ -810,8 +812,8 @@ export class WebSocketControllerHandler implements WebServerHandler {
810
812
  typeof timedInteractionTimeoutMs === "number" ? Millis(timedInteractionTimeoutMs) : undefined,
811
813
  });
812
814
 
813
- // Test nodes and null response_type return null
814
- if (TestNodeCommandHandler.isTestNodeId(nodeId) || response_type === null) {
815
+ // Test nodes return null
816
+ if (TestNodeCommandHandler.isTestNodeId(nodeId)) {
815
817
  return null;
816
818
  }
817
819
  const cmdResult = this.#convertCommandDataToWebSocket(ClusterId(clusterId), commandName, result);
package/src/tsconfig.json CHANGED
@@ -1,7 +1,13 @@
1
1
  {
2
2
  "extends": "../../tools/tsc/tsconfig.lib.json",
3
3
  "compilerOptions": {
4
- "types": ["globals"]
4
+ "types": [
5
+ "globals"
6
+ ]
5
7
  },
6
- "references": []
7
- }
8
+ "references": [
9
+ {
10
+ "path": "../../ws-client/src"
11
+ }
12
+ ]
13
+ }
@@ -211,11 +211,9 @@ export type OpenCommissioningWindowResponse = {
211
211
  qrCode: string;
212
212
  };
213
213
 
214
- import { AttributesData, MatterNode } from "./WebSocketMessageTypes.js";
214
+ import type { AttributesData, MatterNodeData } from "@matter-server/ws-client";
215
215
 
216
- /** MatterNode details for WebSocket API - re-export from WebSocketMessageTypes */
217
- export type { AttributesData };
218
- export type MatterNodeData = MatterNode;
216
+ export type { AttributesData, MatterNodeData };
219
217
 
220
218
  /**
221
219
  * Interface for node command handlers.