+ console.error('Buffer type:', buffer ? buffer.constructor.name : 'null');
+ console.error('Buffer length:', buffer ? buffer.length || buffer.byteLength : 'N/A');
+
+ // Try alternative method
+ try {
+ let binary = '';
+ const bytes = new Uint8Array(buffer);
+ const len = bytes.byteLength;
+
+ for (let i = 0; i < len; i++) {
+ binary += String.fromCharCode(bytes[i]);
+ }
+
+ return btoa(binary);
+ } catch (fallbackError) {
+ console.error('Fallback method also failed:', fallbackError);
+ throw new Error('Failed to convert ArrayBuffer to Base64: ' + error.message);
+ }
+ }
+ }
+
+ // Helper function to convert base64 to Uint8Array
+ function base64ToUint8Array(base64) {
+ try {
+ // Handle both standard base64 and base64url
+ let processedBase64 = base64.replace(/-/g, '+').replace(/_/g, '/');
+
+ // Add padding if needed
+ const padLength = processedBase64.length % 4;
+ const paddedBase64 = padLength ? processedBase64 + '==='.slice(padLength) : processedBase64;
+
+ // Convert to binary string
+ const binaryString = atob(paddedBase64);
+
+ // Convert to Uint8Array
+ const bytes = new Uint8Array(binaryString.length);
+ for (let i = 0; i < binaryString.length; i++) {
+ bytes[i] = binaryString.charCodeAt(i);
+ }
+
+ return bytes;
+ } catch (error) {
+ console.error('Error in base64ToUint8Array:', error);
+ console.error('Input:', base64);
+ console.error('Input length:', base64 ? base64.length : 'N/A');
+ throw new Error('Failed to convert base64 to Uint8Array: ' + error.message);
+ }
+ }
+
+ // Helper function to convert string to Uint8Array
+ function stringToUint8Array(str) {
+ try {
+ // If it's already in the right format, return as-is
+ if (str instanceof ArrayBuffer) {
+ return new Uint8Array(str);
+ }
+
+ // If it's a hex string (from PHP hash)
+ if (/^[0-9a-f]+$/i.test(str)) {
+ const matches = str.match(/.{1,2}/g);
+ const bytes = new Uint8Array(matches.length);
+ for (let i = 0; i < matches.length; i++) {
+ bytes[i] = parseInt(matches[i], 16);
+ }
+ return bytes;
+ }
+
+ // If it's base64
+ try {
+ const binaryString = atob(str);
+ const bytes = new Uint8Array(binaryString.length);
+ for (let i = 0; i < binaryString.length; i++) {
+ bytes[i] = binaryString.charCodeAt(i);
+ }
+ return bytes;
+ } catch (e) {
+ // Fallback: treat as regular string
+ const encoder = new TextEncoder();
+ return encoder.encode(str);
+ }
+ } catch (error) {
+ console.error('Error converting string to Uint8Array:', error);
+ throw new Error('Failed to convert user ID: ' + error.message);