@matter-server/ws-controller 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.
@@ -293,18 +293,103 @@ const BIGINT_MARKER = "__BIGINT__";
293
293
  /**
294
294
  * Parse JSON with BigInt support for large numbers that exceed JavaScript precision.
295
295
  * Numbers with 15+ digits that exceed MAX_SAFE_INTEGER are converted to BigInt.
296
+ *
297
+ * This function carefully avoids modifying numbers that appear inside string values.
296
298
  */
297
299
  export function parseBigIntAwareJson(json: string): unknown {
298
300
  // Pre-process: Replace large numbers (15+ digits) with marked string placeholders
299
301
  // This must happen before JSON.parse to preserve precision
300
- // Match numbers after colon (object values) or after [ or , (array elements)
301
- const processed = json.replace(/([:,[])\s*(\d{15,})(?=[,}\]\s])/g, (match, prefix, number) => {
302
- const num = BigInt(number);
303
- if (num > Number.MAX_SAFE_INTEGER) {
304
- return `${prefix}"${BIGINT_MARKER}${number}"`;
302
+ // We need to track whether we're inside a string to avoid modifying string contents
303
+ const result: string[] = [];
304
+ let i = 0;
305
+ let inString = false;
306
+
307
+ while (i < json.length) {
308
+ const char = json[i];
309
+
310
+ if (inString) {
311
+ // Inside a string - copy characters as-is until we find the closing quote
312
+ if (char === "\\") {
313
+ // Escape sequence - copy both the backslash and the next character
314
+ result.push(char);
315
+ i++;
316
+ if (i < json.length) {
317
+ result.push(json[i]);
318
+ i++;
319
+ }
320
+ } else if (char === '"') {
321
+ // End of string
322
+ result.push(char);
323
+ inString = false;
324
+ i++;
325
+ } else {
326
+ result.push(char);
327
+ i++;
328
+ }
329
+ } else {
330
+ // Outside a string
331
+ if (char === '"') {
332
+ // Start of a string
333
+ result.push(char);
334
+ inString = true;
335
+ i++;
336
+ } else if (char >= "0" && char <= "9") {
337
+ // Potential number - extract and check
338
+ // Check if previous character was a minus sign (for negative numbers)
339
+ const hasMinus = result.length > 0 && result[result.length - 1] === "-";
340
+ if (hasMinus) {
341
+ result.pop(); // Remove the minus sign, we'll include it in the number
342
+ }
343
+
344
+ // Extract the integer part
345
+ const start = i;
346
+ while (i < json.length && json[i] >= "0" && json[i] <= "9") {
347
+ i++;
348
+ }
349
+
350
+ // Check for decimal point (fractional number) or exponent
351
+ let isFloat = false;
352
+ if (i < json.length && json[i] === ".") {
353
+ isFloat = true;
354
+ i++; // consume the decimal point
355
+ while (i < json.length && json[i] >= "0" && json[i] <= "9") {
356
+ i++;
357
+ }
358
+ }
359
+
360
+ // Check for exponent (e.g., 1e10, 1E-5)
361
+ if (i < json.length && (json[i] === "e" || json[i] === "E")) {
362
+ isFloat = true;
363
+ i++; // consume 'e' or 'E'
364
+ if (i < json.length && (json[i] === "+" || json[i] === "-")) {
365
+ i++; // consume sign
366
+ }
367
+ while (i < json.length && json[i] >= "0" && json[i] <= "9") {
368
+ i++;
369
+ }
370
+ }
371
+
372
+ const numberStr = (hasMinus ? "-" : "") + json.slice(start, i);
373
+
374
+ // Only convert integers (not floats) with 15+ digits that exceed safe integer range
375
+ if (!isFloat && numberStr.length - (hasMinus ? 1 : 0) >= 15) {
376
+ const num = BigInt(numberStr);
377
+ if (num > Number.MAX_SAFE_INTEGER || num < Number.MIN_SAFE_INTEGER) {
378
+ result.push(`"${BIGINT_MARKER}${numberStr}"`);
379
+ } else {
380
+ result.push(numberStr);
381
+ }
382
+ } else {
383
+ result.push(numberStr);
384
+ }
385
+ } else {
386
+ result.push(char);
387
+ i++;
388
+ }
305
389
  }
306
- return match;
307
- });
390
+ }
391
+
392
+ const processed = result.join("");
308
393
 
309
394
  // Parse with reviver to convert marked strings back to BigInt
310
395
  return JSON.parse(processed, (_key, value) => {
@@ -405,7 +405,7 @@ export class WebSocketControllerHandler implements WebServerHandler {
405
405
  if (result === undefined) {
406
406
  throw new Error("No response");
407
407
  }
408
- logger.info("WebSocket request handled", messageId, result);
408
+ logger.info(`WebSocket request (${command}) handled`, messageId, result);
409
409
  return {
410
410
  response: {
411
411
  message_id: messageId ?? "",