@matter-server/ws-client 0.2.5 → 0.2.7-alpha.0-20260118-993a1c7

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.
@@ -14,6 +14,8 @@ export declare function toBigIntAwareJson(value: unknown, spaces?: number): stri
14
14
  * Parse JSON with BigInt support for large numbers that exceed JavaScript precision.
15
15
  * Numbers with 15+ digits that exceed MAX_SAFE_INTEGER are converted to BigInt.
16
16
  * Use this for incoming WebSocket messages.
17
+ *
18
+ * This function carefully avoids modifying numbers that appear inside string values.
17
19
  */
18
20
  export declare function parseBigIntAwareJson(json: string): unknown;
19
21
  //# sourceMappingURL=json-utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"json-utils.d.ts","sourceRoot":"","sources":["../../src/json-utils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAWH;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CA2BzE;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAmB1D"}
1
+ {"version":3,"file":"json-utils.d.ts","sourceRoot":"","sources":["../../src/json-utils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAWH;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CA2BzE;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAsG1D"}
@@ -29,13 +29,77 @@ function toBigIntAwareJson(value, spaces) {
29
29
  return result;
30
30
  }
31
31
  function parseBigIntAwareJson(json) {
32
- const processed = json.replace(/([:,[])\s*(\d{15,})(?=[,}\]\s])/g, (match, prefix, number) => {
33
- const num = BigInt(number);
34
- if (num > Number.MAX_SAFE_INTEGER) {
35
- return `${prefix}"${BIGINT_MARKER}${number}"`;
32
+ const result = [];
33
+ let i = 0;
34
+ let inString = false;
35
+ while (i < json.length) {
36
+ const char = json[i];
37
+ if (inString) {
38
+ if (char === "\\") {
39
+ result.push(char);
40
+ i++;
41
+ if (i < json.length) {
42
+ result.push(json[i]);
43
+ i++;
44
+ }
45
+ } else if (char === '"') {
46
+ result.push(char);
47
+ inString = false;
48
+ i++;
49
+ } else {
50
+ result.push(char);
51
+ i++;
52
+ }
53
+ } else {
54
+ if (char === '"') {
55
+ result.push(char);
56
+ inString = true;
57
+ i++;
58
+ } else if (char >= "0" && char <= "9") {
59
+ const hasMinus = result.length > 0 && result[result.length - 1] === "-";
60
+ if (hasMinus) {
61
+ result.pop();
62
+ }
63
+ const start = i;
64
+ while (i < json.length && json[i] >= "0" && json[i] <= "9") {
65
+ i++;
66
+ }
67
+ let isFloat = false;
68
+ if (i < json.length && json[i] === ".") {
69
+ isFloat = true;
70
+ i++;
71
+ while (i < json.length && json[i] >= "0" && json[i] <= "9") {
72
+ i++;
73
+ }
74
+ }
75
+ if (i < json.length && (json[i] === "e" || json[i] === "E")) {
76
+ isFloat = true;
77
+ i++;
78
+ if (i < json.length && (json[i] === "+" || json[i] === "-")) {
79
+ i++;
80
+ }
81
+ while (i < json.length && json[i] >= "0" && json[i] <= "9") {
82
+ i++;
83
+ }
84
+ }
85
+ const numberStr = (hasMinus ? "-" : "") + json.slice(start, i);
86
+ if (!isFloat && numberStr.length - (hasMinus ? 1 : 0) >= 15) {
87
+ const num = BigInt(numberStr);
88
+ if (num > Number.MAX_SAFE_INTEGER || num < Number.MIN_SAFE_INTEGER) {
89
+ result.push(`"${BIGINT_MARKER}${numberStr}"`);
90
+ } else {
91
+ result.push(numberStr);
92
+ }
93
+ } else {
94
+ result.push(numberStr);
95
+ }
96
+ } else {
97
+ result.push(char);
98
+ i++;
99
+ }
36
100
  }
37
- return match;
38
- });
101
+ }
102
+ const processed = result.join("");
39
103
  return JSON.parse(processed, (_key, value) => {
40
104
  if (typeof value === "string" && value.startsWith(BIGINT_MARKER)) {
41
105
  return BigInt(value.slice(BIGINT_MARKER.length));
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/json-utils.ts"],
4
- "mappings": "AAAA;AAAA;AAAA;AAAA;AAAA;AAaA,MAAM,gBAAgB;AAQf,SAAS,kBAAkB,OAAgB,QAAyB;AACvE,QAAM,eAAe,IAAI,MAAoC;AAC7D,MAAI,SAAS,KAAK;AAAA,IACd;AAAA,IACA,CAAC,MAAM,QAAQ;AACX,UAAI,OAAO,QAAQ,UAAU;AACzB,YAAI,MAAM,OAAO,kBAAkB;AAE/B,uBAAa,KAAK,EAAE,MAAM,MAAM,IAAI,SAAS,EAAE,CAAC,KAAK,IAAI,IAAI,SAAS,EAAE,CAAC;AACzE,iBAAO,KAAK,IAAI,SAAS,EAAE,CAAC;AAAA,QAChC,OAAO;AACH,iBAAO,OAAO,GAAG;AAAA,QACrB;AAAA,MACJ;AACA,aAAO;AAAA,IACX;AAAA,IACA;AAAA,EACJ;AAGA,MAAI,aAAa,SAAS,GAAG;AACzB,iBAAa,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM;AACnC,eAAS,OAAO,WAAW,MAAM,EAAE;AAAA,IACvC,CAAC;AAAA,EACL;AAEA,SAAO;AACX;AAOO,SAAS,qBAAqB,MAAuB;AAIxD,QAAM,YAAY,KAAK,QAAQ,oCAAoC,CAAC,OAAO,QAAQ,WAAW;AAC1F,UAAM,MAAM,OAAO,MAAM;AACzB,QAAI,MAAM,OAAO,kBAAkB;AAC/B,aAAO,GAAG,MAAM,IAAI,aAAa,GAAG,MAAM;AAAA,IAC9C;AACA,WAAO;AAAA,EACX,CAAC;AAGD,SAAO,KAAK,MAAM,WAAW,CAAC,MAAM,UAAU;AAC1C,QAAI,OAAO,UAAU,YAAY,MAAM,WAAW,aAAa,GAAG;AAC9D,aAAO,OAAO,MAAM,MAAM,cAAc,MAAM,CAAC;AAAA,IACnD;AACA,WAAO;AAAA,EACX,CAAC;AACL;",
4
+ "mappings": "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",
5
5
  "names": []
6
6
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@matter-server/ws-client",
3
- "version": "0.2.5",
3
+ "version": "0.2.7-alpha.0-20260118-993a1c7",
4
4
  "type": "module",
5
5
  "description": "WebSocket client library for Matter server",
6
6
  "bugs": {
@@ -24,7 +24,10 @@
24
24
  },
25
25
  "dependencies": {},
26
26
  "devDependencies": {
27
- "@types/node": "^25.0.8"
27
+ "@types/node": "^25.0.8",
28
+ "@types/ws": "^8.18.1",
29
+ "@matter/testing": "0.16.5",
30
+ "ws": "^8.18.3"
28
31
  },
29
32
  "files": [
30
33
  "dist/**/*",
package/src/json-utils.ts CHANGED
@@ -52,18 +52,103 @@ export function toBigIntAwareJson(value: unknown, spaces?: number): string {
52
52
  * Parse JSON with BigInt support for large numbers that exceed JavaScript precision.
53
53
  * Numbers with 15+ digits that exceed MAX_SAFE_INTEGER are converted to BigInt.
54
54
  * Use this for incoming WebSocket messages.
55
+ *
56
+ * This function carefully avoids modifying numbers that appear inside string values.
55
57
  */
56
58
  export function parseBigIntAwareJson(json: string): unknown {
57
59
  // Pre-process: Replace large numbers (15+ digits) with marked string placeholders
58
60
  // This must happen before JSON.parse to preserve precision
59
- // Match numbers after colon (object values) or after [ or , (array elements)
60
- const processed = json.replace(/([:,[])\s*(\d{15,})(?=[,}\]\s])/g, (match, prefix, number) => {
61
- const num = BigInt(number);
62
- if (num > Number.MAX_SAFE_INTEGER) {
63
- return `${prefix}"${BIGINT_MARKER}${number}"`;
61
+ // We need to track whether we're inside a string to avoid modifying string contents
62
+ const result: string[] = [];
63
+ let i = 0;
64
+ let inString = false;
65
+
66
+ while (i < json.length) {
67
+ const char = json[i];
68
+
69
+ if (inString) {
70
+ // Inside a string - copy characters as-is until we find the closing quote
71
+ if (char === "\\") {
72
+ // Escape sequence - copy both the backslash and the next character
73
+ result.push(char);
74
+ i++;
75
+ if (i < json.length) {
76
+ result.push(json[i]);
77
+ i++;
78
+ }
79
+ } else if (char === '"') {
80
+ // End of string
81
+ result.push(char);
82
+ inString = false;
83
+ i++;
84
+ } else {
85
+ result.push(char);
86
+ i++;
87
+ }
88
+ } else {
89
+ // Outside a string
90
+ if (char === '"') {
91
+ // Start of a string
92
+ result.push(char);
93
+ inString = true;
94
+ i++;
95
+ } else if (char >= "0" && char <= "9") {
96
+ // Potential number - extract and check
97
+ // Check if previous character was a minus sign (for negative numbers)
98
+ const hasMinus = result.length > 0 && result[result.length - 1] === "-";
99
+ if (hasMinus) {
100
+ result.pop(); // Remove the minus sign, we'll include it in the number
101
+ }
102
+
103
+ // Extract the integer part
104
+ const start = i;
105
+ while (i < json.length && json[i] >= "0" && json[i] <= "9") {
106
+ i++;
107
+ }
108
+
109
+ // Check for decimal point (fractional number) or exponent
110
+ let isFloat = false;
111
+ if (i < json.length && json[i] === ".") {
112
+ isFloat = true;
113
+ i++; // consume the decimal point
114
+ while (i < json.length && json[i] >= "0" && json[i] <= "9") {
115
+ i++;
116
+ }
117
+ }
118
+
119
+ // Check for exponent (e.g., 1e10, 1E-5)
120
+ if (i < json.length && (json[i] === "e" || json[i] === "E")) {
121
+ isFloat = true;
122
+ i++; // consume 'e' or 'E'
123
+ if (i < json.length && (json[i] === "+" || json[i] === "-")) {
124
+ i++; // consume sign
125
+ }
126
+ while (i < json.length && json[i] >= "0" && json[i] <= "9") {
127
+ i++;
128
+ }
129
+ }
130
+
131
+ const numberStr = (hasMinus ? "-" : "") + json.slice(start, i);
132
+
133
+ // Only convert integers (not floats) with 15+ digits that exceed safe integer range
134
+ if (!isFloat && numberStr.length - (hasMinus ? 1 : 0) >= 15) {
135
+ const num = BigInt(numberStr);
136
+ if (num > Number.MAX_SAFE_INTEGER || num < Number.MIN_SAFE_INTEGER) {
137
+ result.push(`"${BIGINT_MARKER}${numberStr}"`);
138
+ } else {
139
+ result.push(numberStr);
140
+ }
141
+ } else {
142
+ result.push(numberStr);
143
+ }
144
+ } else {
145
+ result.push(char);
146
+ i++;
147
+ }
64
148
  }
65
- return match;
66
- });
149
+ }
150
+
151
+ const processed = result.join("");
67
152
 
68
153
  // Parse with reviver to convert marked strings back to BigInt
69
154
  return JSON.parse(processed, (_key, value) => {