dodil/erp-ui

public/r/json.json

{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "json",
  "title": "Lossless JSON",
  "description": "JSON.parse that keeps integers past 2^53 (64-bit ids) exact, as strings.",
  "files": [
    {
      "path": "src/lib/json.ts",
      "content": "/**\n * JSON without losing ids.\n *\n * Bricks key partners by a 64-bit integer derived from a business key (`\"bp_id\": 45665172796086509`). JSON\n * has only doubles, and `JSON.parse` rounds anything past 2^53 to the nearest double — 45665172796086509\n * becomes 45665172796086510, a DIFFERENT partner, and the next request for it is a 404. Found building the CRM\n * screens (2026-10-17): every bp_id the API returns is past 2^53.\n *\n * `quoteUnsafeIntegers` rewrites the text so every integer a double cannot hold exactly arrives as a string;\n * everything else is untouched (strings are skipped, decimals and safe integers stay numbers). Use the\n * value with `String(x)`, and it is exact whichever way it arrived.\n */\n\nexport function quoteUnsafeIntegers(text: string): string {\n  let out = \"\";\n  let i = 0;\n  const n = text.length;\n  while (i < n) {\n    const ch = text[i];\n    if (ch === '\"') {\n      let j = i + 1;\n      while (j < n && text[j] !== '\"') j += text[j] === \"\\\\\" ? 2 : 1;\n      out += text.slice(i, j + 1);\n      i = j + 1;\n    } else if (ch === \"-\" || (ch >= \"0\" && ch <= \"9\")) {\n      let j = i + 1;\n      while (j < n && /[0-9eE+\\-.]/.test(text[j])) j++;\n      const token = text.slice(i, j);\n      out += /^-?\\d+$/.test(token) && !Number.isSafeInteger(Number(token)) ? `\"${token}\"` : token;\n      i = j;\n    } else {\n      out += ch;\n      i++;\n    }\n  }\n  return out;\n}\n\n/** `JSON.parse`, with integers past 2^53 kept exactly (as strings). */\nexport function parseJsonLossless<T = unknown>(text: string): T {\n  return JSON.parse(quoteUnsafeIntegers(text)) as T;\n}\n",
      "type": "registry:lib",
      "target": "erp-ui/lib/json.ts"
    }
  ],
  "type": "registry:lib"
}