1- export const isValidHex = ( value : string ) =>
2- value . match ( / .{ 1 , 2 } / g) ?. length === 32 ;
1+ // Common constants and instances
2+ const base64Chars =
3+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' ;
4+ const base64Map = new Uint8Array ( 256 ) ;
5+ for ( let i = 0 ; i < base64Chars . length ; i ++ ) {
6+ base64Map [ base64Chars . charCodeAt ( i ) ] = i ;
7+ }
8+
9+ const textEncoder = new TextEncoder ( ) ;
10+ const textDecoder = new TextDecoder ( ) ;
11+
12+ // Utility Functions
13+ export const isValidHex = ( value : string ) : boolean =>
14+ / ^ [ 0 - 9 a - f A - F ] { 64 } $ / . test ( value ) ;
315
4- export const stringToBytes = ( string : string ) => {
5- return new TextEncoder ( ) . encode ( string ) ;
16+ export const stringToBytes = ( string : string ) : Uint8Array => {
17+ return textEncoder . encode ( string ) ;
618} ;
719
8- export const hexToBytes = ( hex : string ) => {
9- const bytes = [ ] ;
10- for ( let i = 0 ; i < hex . length ; i += 2 ) {
11- bytes . push ( parseInt ( hex . slice ( i , i + 2 ) , 16 ) ) ;
12- }
13- return Uint8Array . from ( bytes ) ;
20+ export const bytesToString = ( bytes : Uint8Array ) : string => {
21+ return textDecoder . decode ( bytes ) ;
1422} ;
1523
16- export const bytesToString = ( uint8Array : Uint8Array ) => {
17- const decoder = new TextDecoder ( ) ;
18- const string = decoder . decode ( uint8Array ) ;
19- return string ;
24+ export const hexToBytes = ( hex : string ) : Uint8Array => {
25+ if ( ! / ^ [ 0 - 9 a - f A - F ] + $ / . test ( hex ) || hex . length % 2 !== 0 ) {
26+ throw new Error ( 'Invalid hex string' ) ;
27+ }
28+ const bytes = new Uint8Array ( hex . length / 2 ) ;
29+ for ( let i = 0 ; i < bytes . length ; i ++ ) {
30+ bytes [ i ] = parseInt ( hex . substr ( i * 2 , 2 ) , 16 ) ;
31+ }
32+ return bytes ;
2033} ;
2134
22- export const bytesToHex = ( uint8Array : Uint8Array ) => {
23- return Array . from ( uint8Array )
35+ export const bytesToHex = ( bytes : Uint8Array ) : string => {
36+ return Array . from ( bytes )
2437 . map ( ( byte ) => byte . toString ( 16 ) . padStart ( 2 , '0' ) )
2538 . join ( '' ) ;
2639} ;
2740
28- export const stringToHex = ( string : string ) => {
29- const uint8Array = stringToBytes ( string ) ;
30- return bytesToHex ( uint8Array ) ;
41+ export const stringToHex = ( string : string ) : string => {
42+ return bytesToHex ( stringToBytes ( string ) ) ;
3143} ;
3244
33- export const bytesFromBase64 = ( base64String : string ) => {
34- // Base64 character set
35- const base64Chars =
36- 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' ;
37- const base64Map = new Uint8Array ( 256 ) ;
38-
39- // Initialize the inverse mapping from character code to Base64 value
40- for ( let i = 0 ; i < base64Chars . length ; i ++ ) {
41- base64Map [ base64Chars . charCodeAt ( i ) ] = i ;
42- }
43-
44- // Remove any characters not part of the Base64 character set
45+ // Base64 Encoding/Decoding Functions
46+ export const bytesFromBase64 = ( base64String : string ) : Uint8Array => {
4547 base64String = base64String . replace ( / [ ^ A - Z a - z 0 - 9 + / = ] / g, '' ) ;
4648
47- // Calculate padding
4849 let padding = 0 ;
4950 if ( base64String . endsWith ( '==' ) ) {
5051 padding = 2 ;
5152 } else if ( base64String . endsWith ( '=' ) ) {
5253 padding = 1 ;
5354 }
5455
55- const byteLength = ( base64String . length * 6 ) / 8 - padding ;
56+ const byteLength = Math . floor ( ( base64String . length * 6 ) / 8 - padding ) ;
5657 const bytes = new Uint8Array ( byteLength ) ;
5758
5859 let buffer = 0 ;
@@ -61,15 +62,11 @@ export const bytesFromBase64 = (base64String: string) => {
6162
6263 for ( let i = 0 ; i < base64String . length ; i ++ ) {
6364 const c = base64String . charAt ( i ) ;
64- if ( c === '=' ) {
65- break ; // Padding character, end of data
66- }
65+ if ( c === '=' ) break ;
6766
68- // Accumulate bits
6967 buffer = ( buffer << 6 ) | base64Map [ c . charCodeAt ( 0 ) ] ;
7068 bitsCollected += 6 ;
7169
72- // If we have 8 or more bits, extract the byte
7370 if ( bitsCollected >= 8 ) {
7471 bitsCollected -= 8 ;
7572 bytes [ byteIndex ++ ] = ( buffer >> bitsCollected ) & 0xff ;
@@ -79,42 +76,22 @@ export const bytesFromBase64 = (base64String: string) => {
7976 return bytes ;
8077} ;
8178
82- export const toBase64FromStringOrBytes = ( input : string | Uint8Array ) => {
83- // Base64 character set
84- const base64Chars =
85- 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' ;
86-
87- let bytes ;
88-
89- // Convert input to Uint8Array if it's a string
90- if ( typeof input === 'string' ) {
91- const encoder = new TextEncoder ( ) ;
92- bytes = encoder . encode ( input ) ;
93- } else if ( input instanceof Uint8Array ) {
94- bytes = input ;
95- } else {
96- throw new Error ( 'Input must be a string or Uint8Array' ) ;
97- }
98-
79+ export const bytesToBase64 = ( bytes : Uint8Array ) : string => {
9980 let base64 = '' ;
10081 const len = bytes . length ;
10182
10283 for ( let i = 0 ; i < len ; i += 3 ) {
103- // Collect three bytes (or pad with zeros)
10484 const byte1 = bytes [ i ] ;
10585 const byte2 = i + 1 < len ? bytes [ i + 1 ] : 0 ;
10686 const byte3 = i + 2 < len ? bytes [ i + 2 ] : 0 ;
10787
108- // Combine the three bytes into a 24-bit number
10988 const combined = ( byte1 << 16 ) | ( byte2 << 8 ) | byte3 ;
11089
111- // Extract four 6-bit values
11290 const enc1 = ( combined >> 18 ) & 0x3f ;
11391 const enc2 = ( combined >> 12 ) & 0x3f ;
11492 const enc3 = ( combined >> 6 ) & 0x3f ;
11593 const enc4 = combined & 0x3f ;
11694
117- // Append the Base64 characters
11895 base64 += base64Chars . charAt ( enc1 ) ;
11996 base64 += base64Chars . charAt ( enc2 ) ;
12097 base64 += i + 1 < len ? base64Chars . charAt ( enc3 ) : '=' ;
@@ -124,7 +101,19 @@ export const toBase64FromStringOrBytes = (input: string | Uint8Array) => {
124101 return base64 ;
125102} ;
126103
127- export const combineBytes = ( bytesArray : Uint8Array [ ] ) => {
104+ export const stringFromBase64 = ( base64String : string ) : string => {
105+ return bytesToString ( bytesFromBase64 ( base64String ) ) ;
106+ } ;
107+
108+ export const toBase64FromStringOrBytes = (
109+ input : string | Uint8Array
110+ ) : string => {
111+ const bytes = typeof input === 'string' ? stringToBytes ( input ) : input ;
112+ return bytesToBase64 ( bytes ) ;
113+ } ;
114+
115+ // Combine Bytes
116+ export const combineBytes = ( bytesArray : Uint8Array [ ] ) : Uint8Array => {
128117 const totalLength = bytesArray . reduce ( ( sum , bytes ) => sum + bytes . length , 0 ) ;
129118 const combinedBytes = new Uint8Array ( totalLength ) ;
130119 let offset = 0 ;
@@ -137,61 +126,7 @@ export const combineBytes = (bytesArray: Uint8Array[]) => {
137126 return combinedBytes ;
138127} ;
139128
140- export const stringFromBase64 = ( base64String : string ) => {
141- // Base64 character set
142- const base64Chars =
143- 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' ;
144- const base64Map = new Uint8Array ( 256 ) ;
145-
146- // Initialize the inverse mapping from character code to Base64 value
147- for ( let i = 0 ; i < base64Chars . length ; i ++ ) {
148- base64Map [ base64Chars . charCodeAt ( i ) ] = i ;
149- }
150-
151- // Remove any characters not part of the Base64 character set
152- base64String = base64String . replace ( / [ ^ A - Z a - z 0 - 9 + / = ] / g, '' ) ;
153-
154- // Calculate padding
155- let padding = 0 ;
156- if ( base64String . endsWith ( '==' ) ) {
157- padding = 2 ;
158- } else if ( base64String . endsWith ( '=' ) ) {
159- padding = 1 ;
160- }
161-
162- const byteLength = ( base64String . length * 6 ) / 8 - padding ;
163- const bytes = new Uint8Array ( byteLength ) ;
164-
165- let buffer = 0 ;
166- let bitsCollected = 0 ;
167- let byteIndex = 0 ;
168-
169- for ( let i = 0 ; i < base64String . length ; i ++ ) {
170- const c = base64String . charAt ( i ) ;
171- if ( c === '=' ) {
172- break ; // Padding character, end of data
173- }
174-
175- // Accumulate bits
176- buffer = ( buffer << 6 ) | base64Map [ c . charCodeAt ( 0 ) ] ;
177- bitsCollected += 6 ;
178-
179- // If we have 8 or more bits, extract the byte
180- if ( bitsCollected >= 8 ) {
181- bitsCollected -= 8 ;
182- bytes [ byteIndex ++ ] = ( buffer >> bitsCollected ) & 0xff ;
183- }
184- }
185-
186- // Decode bytes to string
187- const decoder = new TextDecoder ( ) ;
188- const decodedString = decoder . decode ( bytes ) ;
189-
190- return decodedString ;
191- } ;
192-
193- // ================== qs-like replacement start
194-
129+ // Query String Parsing and Stringifying
195130function parseKey ( key : string ) : Array < string | number > {
196131 const keys : Array < string | number > = [ ] ;
197132 const regex = / ( [ ^ [ \] ] + ) | \[ ( .* ?) \] / g;
@@ -222,14 +157,10 @@ function setDeep(obj: any, keys: Array<string | number>, value: any) {
222157
223158 if ( i === keys . length - 1 ) {
224159 if ( key === '' ) {
225- if ( ! Array . isArray ( current ) ) {
226- current = [ ] ;
227- }
160+ if ( ! Array . isArray ( current ) ) current = [ ] ;
228161 current . push ( value ) ;
229162 } else if ( typeof key === 'number' ) {
230- if ( ! Array . isArray ( current ) ) {
231- current = [ ] ;
232- }
163+ if ( ! Array . isArray ( current ) ) current = [ ] ;
233164 current [ key ] = value ;
234165 } else {
235166 current [ key ] = value ;
@@ -238,9 +169,7 @@ function setDeep(obj: any, keys: Array<string | number>, value: any) {
238169 const nextKey = keys [ i + 1 ] ;
239170
240171 if ( key === '' ) {
241- if ( ! Array . isArray ( current ) ) {
242- current = [ ] ;
243- }
172+ if ( ! Array . isArray ( current ) ) current = [ ] ;
244173 if (
245174 current . length === 0 ||
246175 typeof current [ current . length - 1 ] !== 'object'
@@ -249,9 +178,7 @@ function setDeep(obj: any, keys: Array<string | number>, value: any) {
249178 }
250179 current = current [ current . length - 1 ] ;
251180 } else if ( typeof key === 'number' ) {
252- if ( ! Array . isArray ( current ) ) {
253- current = [ ] ;
254- }
181+ if ( ! Array . isArray ( current ) ) current = [ ] ;
255182 if ( ! current [ key ] ) {
256183 current [ key ] = typeof nextKey === 'number' ? [ ] : { } ;
257184 }
@@ -320,29 +247,19 @@ export function stringifyQueryParams(params: Record<string, any>): string {
320247 return queryParams . join ( '&' ) ;
321248}
322249
323- // ================== qs-like replacement stop
250+ // Window and Document Utilities
251+ export const isWindowAvailable = ( ) : boolean =>
252+ typeof window !== 'undefined' && typeof window . location !== 'undefined' ;
324253
325- export const isWindowAvailable = ( ) =>
326- typeof window != 'undefined' && typeof window ?. location != 'undefined' ;
327-
328- export const getTargetOrigin = ( ) => {
254+ export const getTargetOrigin = ( ) : string => {
329255 if ( isWindowAvailable ( ) ) {
330256 const ancestorOrigins = window . location . ancestorOrigins ;
331257 return ancestorOrigins ?. [ ancestorOrigins . length - 1 ] ?? '*' ;
332258 }
333-
334259 return '*' ;
335260} ;
336261
337- export const getSafeWindow = ( ) => {
338- return typeof window !== 'undefined' ? window : ( { } as any ) ;
339- } ;
340-
341- export const getSafeDocument = ( ) => {
342- return typeof document !== 'undefined' ? document : ( { } as any ) ;
343- } ;
344-
345- export const isMobileWebview = ( ) => {
346- const safeWindow = getSafeWindow ( ) ;
347- return safeWindow . ReactNativeWebView || safeWindow . webkit ;
262+ export const isMobileWebview = ( ) : boolean => {
263+ const windowObj = window as any ;
264+ return Boolean ( windowObj ?. ReactNativeWebView || windowObj ?. webkit ) ;
348265} ;
0 commit comments