@@ -33,6 +33,22 @@ export const ObjectKeyAvoidTermList = new Set([
3333 "__lookupSetter__" ,
3434] ) ;
3535
36+ /**
37+ * Maximum safe integer value for .NET Int32 compatibility.
38+ * Using 2,000,000,000 as a round number that is obviously a cap,
39+ * well under Int32.MaxValue (2,147,483,647) to ensure compatibility
40+ * with downstream JSON consumers like .NET.
41+ */
42+ export const MAX_JSON_SAFE_INTEGER = 2_000_000_000 ;
43+
44+ /**
45+ * Minimum safe integer value for .NET Int32 compatibility.
46+ * Using -2,000,000,000 as a round number that is obviously a cap,
47+ * well above Int32.MinValue (-2,147,483,648) to ensure compatibility
48+ * with downstream JSON consumers like .NET.
49+ */
50+ export const MIN_JSON_SAFE_INTEGER = - 2_000_000_000 ;
51+
3652export default class Utilities {
3753 static _isDebug ?: boolean ;
3854 static _isAppSim ?: boolean ;
@@ -2067,4 +2083,62 @@ export default class Utilities {
20672083 static isNullOrUndefined < T > ( object : T | undefined | null ) : object is T {
20682084 return ( object as T ) === undefined || ( object as T ) === null ;
20692085 }
2086+
2087+ /**
2088+ * Clamps a number for broader compatibility (e.g., .NET).
2089+ * Returns undefined if the input is undefined.
2090+ */
2091+ static capNumberForJson ( value : number | undefined ) : number | undefined {
2092+ if ( value === undefined ) {
2093+ return undefined ;
2094+ }
2095+ return Math . max ( MIN_JSON_SAFE_INTEGER , Math . min ( value , MAX_JSON_SAFE_INTEGER ) ) ;
2096+ }
2097+
2098+ /**
2099+ * Deep clones a feature sets object, clamping all numeric values to the safe Int32 range.
2100+ * This ensures compatibility with .NET which has Int32 limits.
2101+ * Preserves undefined values for individual measures (undefined in = undefined out).
2102+ */
2103+ static capFeatureSetsForJson (
2104+ featureSets : { [ setName : string ] : { [ measureName : string ] : number | undefined } | undefined } | undefined
2105+ ) : { [ setName : string ] : { [ measureName : string ] : number | undefined } | undefined } | undefined {
2106+ if ( ! featureSets ) {
2107+ return undefined ;
2108+ }
2109+
2110+ const result : { [ setName : string ] : { [ measureName : string ] : number | undefined } | undefined } = { } ;
2111+
2112+ for ( const setName in featureSets ) {
2113+ const setVal = featureSets [ setName ] ;
2114+ if ( setVal ) {
2115+ const newSetVal : { [ measureName : string ] : number | undefined } = { } ;
2116+ for ( const measureName in setVal ) {
2117+ newSetVal [ measureName ] = Utilities . capNumberForJson ( setVal [ measureName ] ) ;
2118+ }
2119+ result [ setName ] = newSetVal ;
2120+ }
2121+ }
2122+
2123+ return result ;
2124+ }
2125+
2126+ /**
2127+ * Clamps a data value for broader compatibility (e.g., .NET).
2128+ * Handles the IInfoItemData.d type: string | boolean | number | number[] | undefined
2129+ */
2130+ static capDataValueForJson (
2131+ value : string | boolean | number | number [ ] | undefined
2132+ ) : string | boolean | number | number [ ] | undefined {
2133+ if ( value === undefined || typeof value === "string" || typeof value === "boolean" ) {
2134+ return value ;
2135+ }
2136+
2137+ if ( typeof value === "number" ) {
2138+ return Math . max ( MIN_JSON_SAFE_INTEGER , Math . min ( value , MAX_JSON_SAFE_INTEGER ) ) ;
2139+ }
2140+
2141+ // It's a number array
2142+ return value . map ( ( v ) => Math . max ( MIN_JSON_SAFE_INTEGER , Math . min ( v , MAX_JSON_SAFE_INTEGER ) ) ) ;
2143+ }
20702144}
0 commit comments