// @ts-nocheck import './4nk.css'; import { initHeader } from '../src/components/header/header'; /*import { initChat } from '../src/pages/chat/chat';*/ import Database from './services/database.service'; import Services from './services/service'; import TokenService from './services/token'; import { cleanSubscriptions } from './utils/subscription.utils'; import { prepareAndSendPairingTx } from './utils/sp-address.utils'; import ModalService from './services/modal.service'; import { MessageType } from './models/process.model'; import { splitPrivateData, isValid32ByteHex } from './utils/service.utils'; import { MerkleProofResult } from 'pkg/sdk_client'; // =================================================================================== // ## 🧭 1. Routage de Page (Navigation) // =================================================================================== const routes: { [key: string]: string } = { home: '/src/pages/home/home.html', process: '/src/pages/process/process.html', 'process-element': '/src/pages/process-element/process-element.html', account: '/src/pages/account/account.html', chat: '/src/pages/chat/chat.html', signature: '/src/pages/signature/signature.html', }; export let currentRoute = ''; export async function navigate(path: string) { console.log(`[Router] 🧭 Navigation vers: ${path}`); cleanSubscriptions(); cleanPage(); path = path.replace(/^\//, ''); // Retire le slash de début // Gère les chemins simples ou avec paramètres (ex: 'process-element/123_456') if (path.includes('/')) { const parsedPath = path.split('/')[0]; if (!routes[parsedPath]) { console.warn(`[Router] ⚠️ Route inconnue "${parsedPath}", redirection vers 'home'.`); path = 'home'; } } else if (!routes[path]) { console.warn(`[Router] ⚠️ Route inconnue "${path}", redirection vers 'home'.`); path = 'home'; } await handleLocation(path); } async function handleLocation(path: string) { // 1. Log de démarrage console.log(`[Router:handleLocation] 🧭 Gestion de la nouvelle route: ${path}`); const parsedPath = path.split('/'); const baseRoute = parsedPath[0]; currentRoute = baseRoute; const routeHtml = routes[baseRoute] || routes['home']; const content = document.getElementById('containerId'); if (!content) { console.error('[Router] 💥 Erreur critique: div #containerId non trouvée !'); return; } else { // console.debug('[Router:handleLocation] ✅ conteneur #containerId trouvé.'); } // --- Injection de Contenu --- if (baseRoute === 'home') { console.log('[Router:handleLocation] 🏠 Route "home" détectée. Importation dynamique de ...'); const { LoginComponent } = await import('./pages/home/home-component'); if (!customElements.get('login-4nk-component')) { customElements.define('login-4nk-component', LoginComponent); console.log('[Router:handleLocation] ℹ️ défini.'); } const container = document.querySelector('#containerId'); const accountComponent = document.createElement('login-4nk-component'); accountComponent.setAttribute('style', 'width: 100vw; height: 100vh; position: relative; grid-row: 2;'); if (container) { container.appendChild(accountComponent); // 4. Log de succès (le plus important pour ton bug) console.log('[Router:handleLocation] ✅ ajouté au DOM.'); } } else if (baseRoute !== 'process') { // 2. Log pour les autres pages console.log(`[Router:handleLocation] 📄 Fetching et injection de HTML pour: ${routeHtml}`); const html = await fetch(routeHtml).then((data) => data.text()); content.innerHTML = html; console.log(`[Router:handleLocation] ✅ HTML pour "${baseRoute}" injecté.`); } // (Le cas 'process' est géré plus bas dans le switch) await new Promise(requestAnimationFrame); console.log('[Router:handleLocation] 💉 Injection du header...'); injectHeader(); // --- Logique Spécifique à la Page (Lazy Loading) --- console.log(`[Router] Initialisation de la logique pour la route: ${baseRoute}`); switch (baseRoute) { case 'process': console.log('[Router:switch] 📦 Chargement de ProcessListComponent...'); const { ProcessListComponent } = await import('./pages/process/process-list-component'); const container2 = document.querySelector('#containerId'); const processListComponent = document.createElement('process-list-4nk-component'); if (!customElements.get('process-list-4nk-component')) { console.log('[Router:switch] ℹ️ Définition de ...'); customElements.define('process-list-4nk-component', ProcessListComponent); } processListComponent.setAttribute('style', 'height: 100vh; position: relative; grid-row: 2; grid-column: 4;'); if (container2) { container2.appendChild(processListComponent); console.log('[Router:switch] ✅ ajouté au DOM.'); } break; case 'process-element': console.log(`[Router:switch] 📦 Chargement de ...`); if (parsedPath[1]) { // 1. Importe le composant (juste pour être sûr qu'il est défini) const { ProcessElementComponent } = await import('./pages/process-element/process-component'); if (!customElements.get('process-4nk-component')) { customElements.define('process-4nk-component', ProcessElementComponent); } // 2. Sépare les IDs const [processId, stateId] = parsedPath[1].split('_'); // 3. Crée l'élément et passe les attributs const container = document.querySelector('#containerId'); const processElement = document.createElement('process-4nk-component'); processElement.setAttribute('process-id', processId); processElement.setAttribute('state-id', stateId); if (container) { container.appendChild(processElement); console.log(`[Router:switch] ✅ ajouté au DOM pour ${processId}_${stateId}`); } } else { console.error('[Router] 💥 Route process-element appelée sans ID (ex: process-element/processId_stateId)'); navigate('process'); } break; case 'account': console.log('[Router:switch] 📦 Chargement de AccountComponent...'); const { AccountComponent } = await import('./pages/account/account-component'); const accountContainer = document.querySelector('.parameter-list'); if (accountContainer) { if (!customElements.get('account-component')) { console.log('[Router:switch] ℹ️ Définition de ...'); customElements.define('account-component', AccountComponent); } const accountComponent = document.createElement('account-component'); accountContainer.appendChild(accountComponent); console.log('[Router:switch] ✅ ajouté au DOM.'); } else { console.warn('[Router:switch] ⚠️ Impossible de trouver ".parameter-list" pour injecter AccountComponent.'); } break; case 'signature': console.log('[Router:switch] 📦 Chargement de SignatureComponent...'); const { SignatureComponent } = await import('./pages/signature/signature-component'); const container = document.querySelector('.group-list'); if (container) { if (!customElements.get('signature-component')) { console.log('[Router:switch] ℹ️ Définition de ...'); customElements.define('signature-component', SignatureComponent); } const signatureComponent = document.createElement('signature-component'); container.appendChild(signatureComponent); console.log('[Router:switch] ✅ ajouté au DOM.'); } else { console.warn('[Router:switch] ⚠️ Impossible de trouver ".group-list" pour injecter SignatureComponent.'); } break; // Log pour les cas non gérés case 'home': console.log('[Router:switch] ℹ️ Route "home". La logique a déjà été gérée avant le switch.'); break; default: console.log(`[Router:switch] ℹ️ Route "${baseRoute}" n'a pas de logique d'initialisation spécifique dans le switch.`); } } window.onpopstate = async () => { console.log('[Router] 🔄 Changement d\'état "popstate" (bouton retour/avant)'); const services = await Services.getInstance(); if (!services.isPaired()) { handleLocation('home'); } else { handleLocation('process'); } }; // --- Fin de la section Routage de Page --- // =================================================================================== // =================================================================================== // ## 🚀 2. Initialisation de l'Application // =================================================================================== export async function init(): Promise { console.log("[Router:Init] 🚀 Démarrage de l'application..."); try { const services = await Services.getInstance(); (window as any).myService = services; // Pour débogage manuel console.log('[Router:Init] 📦 Initialisation de la base de données (IndexedDB)...'); const db = await Database.getInstance(); db.registerServiceWorker('/src/service-workers/database.worker.js'); console.log("[Router:Init] 📱 Vérification de l'appareil (device)..."); const device = await services.getDeviceFromDatabase(); console.log('🚀 ~ setTimeout ~ device:', device); // Log original gardé if (!device) { console.log("[Router:Init] ✨ Aucun appareil trouvé. Création d'un nouvel appareil..."); await services.createNewDevice(); } else { console.log("[Router:Init] 🔄 Restauration de l'appareil depuis la BDD..."); services.restoreDevice(device); } console.log("[Router:Init] 💾 Restauration de l'état (processus et secrets) depuis la BDD..."); await services.restoreProcessesFromDB(); await services.restoreSecretsFromDB(); console.log('[Router:Init] 🔌 Connexion à tous les relais...'); await services.connectAllRelays(); // S'enregistre comme "serveur" API si nous sommes dans une iframe if (window.self !== window.top) { console.log('[Router:Init] 📡 Nous sommes dans une iframe. Enregistrement des listeners API...'); await registerAllListeners(); } else { console.log('[Router:Init] ℹ️ Exécution en mode standalone (pas dans une iframe).'); } console.log("[Router:Init] 🧭 Vérification du statut d'appairage pour la navigation..."); if (services.isPaired()) { console.log('[Router:Init] ✅ Appairé. Navigation vers "process".'); await navigate('process'); } else { console.log('[Router:Init] ❌ Non appairé. Navigation vers "home".'); await navigate('home'); } } catch (error) { console.error("[Router:Init] 💥 ERREUR CRITIQUE PENDANT L'INITIALISATION:", error); await navigate('home'); } } // --- Fin de la section Initialisation --- // =================================================================================== // =================================================================================== // ## 📡 3. API (Message Listeners pour Iframe) // =================================================================================== export async function registerAllListeners() { console.log('[Router:API] 🎧 Enregistrement des gestionnaires de messages (postMessage)...'); const services = await Services.getInstance(); const tokenService = await TokenService.getInstance(); /** * Fonction centralisée pour envoyer des réponses d'erreur à la fenêtre parente (l'application A). */ const errorResponse = (errorMsg: string, origin: string, messageId?: string) => { console.error(`[Router:API] 📤 Envoi Erreur: ${errorMsg} (Origine: ${origin}, MsgID: ${messageId})`); window.parent.postMessage( { type: MessageType.ERROR, error: errorMsg, messageId, }, origin, ); }; // --- Définitions des gestionnaires (Handlers) --- const handleRequestLink = async (event: MessageEvent) => { console.log(`[Router:API] 📨 Message ${MessageType.REQUEST_LINK} reçu de ${event.origin}`); const modalService = await ModalService.getInstance(); const result = await modalService.showConfirmationModal( { title: 'Confirmation de liaison', content: ` `, confirmText: 'Ajouter un service', cancelText: 'Annuler', }, true, ); if (!result) { throw new Error('Failed to pair device: User refused to link'); } const tokens = await tokenService.generateSessionToken(event.origin); window.parent.postMessage( { type: MessageType.LINK_ACCEPTED, accessToken: tokens.accessToken, refreshToken: tokens.refreshToken, messageId: event.data.messageId, }, event.origin, ); console.log(`[Router:API] ✅ ${MessageType.REQUEST_LINK} accepté et jetons envoyés.`); }; const handleCreatePairing = async (event: MessageEvent) => { console.log(`[Router:API] 📨 Message ${MessageType.CREATE_PAIRING} reçu`); if (services.isPaired()) { throw new Error('Device already paired — ignoring CREATE_PAIRING request'); } const { accessToken } = event.data; if (!accessToken || !(await tokenService.validateToken(accessToken, event.origin))) { throw new Error('Invalid or expired session token'); } console.log("[Router:API] 🚀 Démarrage du processus d'appairage..."); const myAddress = services.getDeviceAddress(); console.log('[Router:API] 1/7: Création du processus de pairing...'); const createPairingProcessReturn = await services.createPairingProcess('', [myAddress]); const pairingId = createPairingProcessReturn.updated_process?.process_id; const stateId = createPairingProcessReturn.updated_process?.current_process?.states[0]?.state_id as string; if (!pairingId || !stateId) { throw new Error('Pairing process creation failed to return valid IDs'); } console.log(`[Router:API] 2/7: Processus ${pairingId} créé.`); console.log("[Router:API] 3/7: Enregistrement local de l'appareil..."); services.pairDevice(pairingId, [myAddress]); console.log('[Router:API] 4/7: Traitement du retour (handleApiReturn)...'); await services.handleApiReturn(createPairingProcessReturn); console.log('[Router:API] 5/7: Création de la mise à jour PRD...'); const createPrdUpdateReturn = await services.createPrdUpdate(pairingId, stateId); await services.handleApiReturn(createPrdUpdateReturn); console.log('[Router:API] 6/7: Approbation du changement...'); const approveChangeReturn = await services.approveChange(pairingId, stateId); await services.handleApiReturn(approveChangeReturn); console.log('[Router:API] 7/7: Confirmation finale du pairing...'); await services.confirmPairing(); console.log('[Router:API] 🎉 Appairage terminé avec succès !'); const successMsg = { type: MessageType.PAIRING_CREATED, pairingId, messageId: event.data.messageId, }; window.parent.postMessage(successMsg, event.origin); }; const handleGetMyProcesses = async (event: MessageEvent) => { console.log(`[Router:API] 📨 Message ${MessageType.GET_MY_PROCESSES} reçu`); if (!services.isPaired()) throw new Error('Device not paired'); const { accessToken } = event.data; if (!accessToken || !(await tokenService.validateToken(accessToken, event.origin))) { throw new Error('Invalid or expired session token'); } const myProcesses = await services.getMyProcesses(); window.parent.postMessage( { type: MessageType.GET_MY_PROCESSES, myProcesses, messageId: event.data.messageId, }, event.origin, ); }; const handleGetProcesses = async (event: MessageEvent) => { console.log(`[Router:API] 📨 Message ${MessageType.GET_PROCESSES} reçu`); if (!services.isPaired()) throw new Error('Device not paired'); const { accessToken } = event.data; if (!accessToken || !(await tokenService.validateToken(accessToken, event.origin))) { throw new Error('Invalid or expired session token'); } const processes = await services.getProcesses(); window.parent.postMessage( { type: MessageType.PROCESSES_RETRIEVED, processes, messageId: event.data.messageId, }, event.origin, ); }; const handleDecryptState = async (event: MessageEvent) => { console.log(`[Router:API] 📨 Message ${MessageType.RETRIEVE_DATA} reçu`); if (!services.isPaired()) throw new Error('Device not paired'); const { processId, stateId, accessToken } = event.data; if (!accessToken || !(await tokenService.validateToken(accessToken, event.origin))) { throw new Error('Invalid or expired session token'); } const process = await services.getProcess(processId); if (!process) throw new Error("Can't find process"); const state = services.getStateFromId(process, stateId); if (!state) throw new Error(`Unknown state ${stateId} for process ${processId}`); console.log(`[Router:API] 🔐 Démarrage du déchiffrement pour ${processId}:${stateId}`); await services.ensureConnections(process, stateId); const res: Record = {}; for (const attribute of Object.keys(state.pcd_commitment)) { if (attribute === 'roles' || (state.public_data && state.public_data[attribute])) { continue; } const decryptedAttribute = await services.decryptAttribute(processId, state, attribute); if (decryptedAttribute) { res[attribute] = decryptedAttribute; } } console.log(`[Router:API] ✅ Déchiffrement terminé pour ${processId}:${stateId}. ${Object.keys(res).length} attribut(s) déchiffré(s).`); window.parent.postMessage( { type: MessageType.DATA_RETRIEVED, data: res, messageId: event.data.messageId, }, event.origin, ); }; const handleValidateToken = async (event: MessageEvent) => { console.log(`[Router:API] 📨 Message ${MessageType.VALIDATE_TOKEN} reçu`); const accessToken = event.data.accessToken; const refreshToken = event.data.refreshToken; if (!accessToken || !refreshToken) { throw new Error('Missing access, refresh token or both'); } const isValid = await tokenService.validateToken(accessToken, event.origin); console.log(`[Router:API] 🔑 Validation Jeton: ${isValid}`); window.parent.postMessage( { type: MessageType.VALIDATE_TOKEN, accessToken: accessToken, refreshToken: refreshToken, isValid: isValid, messageId: event.data.messageId, }, event.origin, ); }; const handleRenewToken = async (event: MessageEvent) => { console.log(`[Router:API] 📨 Message ${MessageType.RENEW_TOKEN} reçu`); const refreshToken = event.data.refreshToken; if (!refreshToken) throw new Error('No refresh token provided'); const newAccessToken = await tokenService.refreshAccessToken(refreshToken, event.origin); if (!newAccessToken) throw new Error('Failed to refresh token (invalid refresh token)'); console.log(`[Router:API] 🔑 Jeton d'accès renouvelé.`); window.parent.postMessage( { type: MessageType.RENEW_TOKEN, accessToken: newAccessToken, refreshToken: refreshToken, messageId: event.data.messageId, }, event.origin, ); }; const handleGetPairingId = async (event: MessageEvent) => { console.log(`[Router:API] 📨 Message ${MessageType.GET_PAIRING_ID} reçu`); if (!services.isPaired()) throw new Error('Device not paired'); const { accessToken } = event.data; if (!accessToken || !(await tokenService.validateToken(accessToken, event.origin))) { throw new Error('Invalid or expired session token'); } const userPairingId = services.getPairingProcessId(); window.parent.postMessage( { type: MessageType.GET_PAIRING_ID, userPairingId, messageId: event.data.messageId, }, event.origin, ); }; const handleCreateProcess = async (event: MessageEvent) => { console.log(`[Router:API] 📨 Message ${MessageType.CREATE_PROCESS} reçu`); if (!services.isPaired()) throw new Error('Device not paired'); const { processData, privateFields, roles, accessToken } = event.data; if (!accessToken || !(await tokenService.validateToken(accessToken, event.origin))) { throw new Error('Invalid or expired session token'); } console.log('[Router:API] 🚀 Démarrage de la création de processus standard...'); const { privateData, publicData } = splitPrivateData(processData, privateFields); console.log('[Router:API] 1/2: Création du processus...'); const createProcessReturn = await services.createProcess(privateData, publicData, roles); if (!createProcessReturn.updated_process) { throw new Error('Empty updated_process in createProcessReturn'); } const processId = createProcessReturn.updated_process.process_id; const process = createProcessReturn.updated_process.current_process; const stateId = process.states[0].state_id; console.log(`[Router:API] 2/2: Processus ${processId} créé. Traitement...`); await services.handleApiReturn(createProcessReturn); console.log(`[Router:API] 🎉 Processus ${processId} créé.`); const res = { processId, process, processData, }; window.parent.postMessage( { type: MessageType.PROCESS_CREATED, processCreated: res, messageId: event.data.messageId, }, event.origin, ); }; const handleNotifyUpdate = async (event: MessageEvent) => { console.log(`[Router:API] 📨 Message ${MessageType.NOTIFY_UPDATE} reçu`); if (!services.isPaired()) throw new Error('Device not paired'); const { processId, stateId, accessToken } = event.data; if (!accessToken || !(await tokenService.validateToken(accessToken, event.origin))) { throw new Error('Invalid or expired session token'); } if (!isValid32ByteHex(stateId)) throw new Error('Invalid state id'); const res = await services.createPrdUpdate(processId, stateId); await services.handleApiReturn(res); window.parent.postMessage( { type: MessageType.UPDATE_NOTIFIED, messageId: event.data.messageId, }, event.origin, ); }; const handleValidateState = async (event: MessageEvent) => { console.log(`[Router:API] 📨 Message ${MessageType.VALIDATE_STATE} reçu`); if (!services.isPaired()) throw new Error('Device not paired'); const { processId, stateId, accessToken } = event.data; if (!accessToken || !(await tokenService.validateToken(accessToken, event.origin))) { throw new Error('Invalid or expired session token'); } const res = await services.approveChange(processId, stateId); await services.handleApiReturn(res); window.parent.postMessage( { type: MessageType.STATE_VALIDATED, validatedProcess: res.updated_process, messageId: event.data.messageId, }, event.origin, ); }; const handleUpdateProcess = async (event: MessageEvent) => { console.log(`[Router:API] 📨 Message ${MessageType.UPDATE_PROCESS} reçu`); if (!services.isPaired()) throw new Error('Device not paired'); const { processId, newData, privateFields, roles, accessToken } = event.data; if (!accessToken || !(await tokenService.validateToken(accessToken, event.origin))) { throw new Error('Invalid or expired session token'); } const process = await services.getProcess(processId); if (!process) throw new Error('Process not found'); // --- Logique complexe de gestion d'état --- // (Cette logique est très dense et pourrait être déplacée dans le service) console.log(`[Router:API] 🔄 Calcul de la diff pour la mise à jour de ${processId}...`); let lastState = services.getLastCommitedState(process); if (!lastState) { console.warn(`[Router:API] ⚠️ Processus ${processId} n'a pas d'état "commited". Tentative d'auto-approbation du 1er état...`); const firstState = process.states[0]; const roles = firstState.roles; if (services.rolesContainsUs(roles)) { const approveChangeRes = await services.approveChange(processId, firstState.state_id); await services.handleApiReturn(approveChangeRes); const prdUpdateRes = await services.createPrdUpdate(processId, firstState.state_id); await services.handleApiReturn(prdUpdateRes); } else { if (firstState.validation_tokens.length > 0) { const res = await services.createPrdUpdate(processId, firstState.state_id); await services.handleApiReturn(res); } } await new Promise((resolve) => setTimeout(resolve, 2000)); // Attente arbitraire lastState = services.getLastCommitedState(process); if (!lastState) { throw new Error("Process doesn't have a commited state yet"); } } const lastStateIndex = services.getLastCommitedStateIndex(process); if (lastStateIndex === null) throw new Error("Process doesn't have a commited state yet"); const privateData: Record = {}; const publicData: Record = {}; for (const field of Object.keys(newData)) { if (lastState.public_data[field]) { publicData[field] = newData[field]; continue; } if (privateFields.includes(field)) { privateData[field] = newData[field]; continue; } for (let i = lastStateIndex; i >= 0; i--) { const state = process.states[i]; if (state.pcd_commitment[field]) { privateData[field] = newData[field]; break; } else { continue; } } if (privateData[field]) continue; publicData[field] = newData[field]; } console.log(`[Router:API] 🔄 Envoi de la mise à jour à services.updateProcess...`); const res = await services.updateProcess(process, privateData, publicData, roles); await services.handleApiReturn(res); window.parent.postMessage( { type: MessageType.PROCESS_UPDATED, updatedProcess: res.updated_process, messageId: event.data.messageId, }, event.origin, ); }; const handleDecodePublicData = async (event: MessageEvent) => { console.log(`[Router:API] 📨 Message ${MessageType.DECODE_PUBLIC_DATA} reçu`); if (!services.isPaired()) throw new Error('Device not paired'); const { accessToken, encodedData } = event.data; if (!accessToken || !(await tokenService.validateToken(accessToken, event.origin))) { throw new Error('Invalid or expired session token'); } const decodedData = services.decodeValue(encodedData); window.parent.postMessage( { type: MessageType.PUBLIC_DATA_DECODED, decodedData, messageId: event.data.messageId, }, event.origin, ); }; const handleHashValue = async (event: MessageEvent) => { console.log(`[Router:API] 📨 Message ${MessageType.HASH_VALUE} reçu`); const { accessToken, commitedIn, label, fileBlob } = event.data; if (!accessToken || !(await tokenService.validateToken(accessToken, event.origin))) { throw new Error('Invalid or expired session token'); } const hash = services.getHashForFile(commitedIn, label, fileBlob); window.parent.postMessage( { type: MessageType.VALUE_HASHED, hash, messageId: event.data.messageId, }, event.origin, ); }; const handleGetMerkleProof = async (event: MessageEvent) => { console.log(`[Router:API] 📨 Message ${MessageType.GET_MERKLE_PROOF} reçu`); const { accessToken, processState, attributeName } = event.data; if (!accessToken || !(await tokenService.validateToken(accessToken, event.origin))) { throw new Error('Invalid or expired session token'); } const proof = services.getMerkleProofForFile(processState, attributeName); window.parent.postMessage( { type: MessageType.MERKLE_PROOF_RETRIEVED, proof, messageId: event.data.messageId, }, event.origin, ); }; const handleValidateMerkleProof = async (event: MessageEvent) => { console.log(`[Router:API] 📨 Message ${MessageType.VALIDATE_MERKLE_PROOF} reçu`); const { accessToken, merkleProof, documentHash } = event.data; if (!accessToken || !(await tokenService.validateToken(accessToken, event.origin))) { throw new Error('Invalid or expired session token'); } let parsedMerkleProof: MerkleProofResult; try { parsedMerkleProof = JSON.parse(merkleProof); } catch (e) { throw new Error('Provided merkleProof is not a valid json object'); } const res = services.validateMerkleProof(parsedMerkleProof, documentHash); window.parent.postMessage( { type: MessageType.MERKLE_PROOF_VALIDATED, isValid: res, messageId: event.data.messageId, }, event.origin, ); }; // --- Le "Switchyard" : il reçoit tous les messages et les dispatche --- window.removeEventListener('message', handleMessage); window.addEventListener('message', handleMessage); async function handleMessage(event: MessageEvent) { try { switch (event.data.type) { case MessageType.REQUEST_LINK: await handleRequestLink(event); break; case MessageType.CREATE_PAIRING: await handleCreatePairing(event); break; case MessageType.GET_MY_PROCESSES: await handleGetMyProcesses(event); break; case MessageType.GET_PROCESSES: await handleGetProcesses(event); break; case MessageType.RETRIEVE_DATA: await handleDecryptState(event); break; case MessageType.VALIDATE_TOKEN: await handleValidateToken(event); break; case MessageType.RENEW_TOKEN: await handleRenewToken(event); break; case MessageType.GET_PAIRING_ID: await handleGetPairingId(event); break; case MessageType.CREATE_PROCESS: await handleCreateProcess(event); break; case MessageType.NOTIFY_UPDATE: await handleNotifyUpdate(event); break; case MessageType.VALIDATE_STATE: await handleValidateState(event); break; case MessageType.UPDATE_PROCESS: await handleUpdateProcess(event); break; case MessageType.DECODE_PUBLIC_DATA: await handleDecodePublicData(event); break; case MessageType.HASH_VALUE: await handleHashValue(event); break; case MessageType.GET_MERKLE_PROOF: await handleGetMerkleProof(event); break; case MessageType.VALIDATE_MERKLE_PROOF: await handleValidateMerkleProof(event); break; default: console.warn('[Router:API] ⚠️ Message non géré reçu:', event.data); } } catch (error) { const errorMsg = `[Router:API] 💥 Erreur de haut niveau: ${error.message || error}`; errorResponse(errorMsg, event.origin, event.data.messageId); } } window.parent.postMessage( { type: MessageType.LISTENING, }, '*', ); console.log('[Router:API] ✅ Tous les listeners sont actifs. Envoi du message LISTENING au parent.'); } // --- Fonctions utilitaires de la page --- async function cleanPage() { const container = document.querySelector('#containerId'); if (container) container.innerHTML = ''; } async function injectHeader() { const headerContainer = document.getElementById('header-container'); if (headerContainer) { const headerHtml = await fetch('/src/components/header/header.html').then((res) => res.text()); headerContainer.innerHTML = headerHtml; const script = document.createElement('script'); script.src = '/src/components/header/header.ts'; script.type = 'module'; document.head.appendChild(script); initHeader(); } } (window as any).navigate = navigate; // Gère les événements de navigation personnalisés (ex: depuis le header) document.addEventListener('navigate', (e: Event) => { const event = e as CustomEvent<{ page: string; processId?: string }>; console.log(`[Router] 🧭 Événement de navigation personnalisé reçu: ${event.detail.page}`); if (event.detail.page === 'chat') { // Logique spécifique pour 'chat' const container = document.querySelector('.container'); if (container) container.innerHTML = ''; //initChat(); const chatElement = document.querySelector('chat-element'); if (chatElement) { chatElement.setAttribute('process-id', event.detail.processId || ''); } } else { // Gère les autres navigations personnalisées navigate(event.detail.page); } }); // --- Fin de la section API --- // ===================================================================================