function base64urlEncode(buffer: ArrayBuffer): string { const bytes = new Uint8Array(buffer); let binary = ''; for (let i = 0; i < bytes.length; i++) { binary += String.fromCharCode(bytes[i]); } return btoa(binary).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, ''); } export function generateCodeVerifier(): string { const array = new Uint8Array(32); crypto.getRandomValues(array); return base64urlEncode(array.buffer); } export async function generateCodeChallenge(verifier: string): Promise { const encoder = new TextEncoder(); const data = encoder.encode(verifier); const digest = await crypto.subtle.digest('SHA-256', data); return base64urlEncode(digest); } export function generateState(): string { const array = new Uint8Array(32); crypto.getRandomValues(array); return base64urlEncode(array.buffer); }