# SDK Client TypeScript - Documentation complète ## Vue d'ensemble Le SDK Client TypeScript pour l'API Vault 4NK fournit une interface type-safe et moderne pour interagir avec l'API de stockage sécurisé. Il inclut le déchiffrement côté client, la gestion d'erreurs avancée, et des utilitaires cryptographiques. ## Installation ### NPM ```bash npm install @4nk/vault-sdk ``` ### Depuis les sources ```bash git clone https://git.4nkweb.com/4nk/vault-sdk.git cd vault-sdk npm install npm run build ``` ## Configuration ### Importation de base ```typescript import { VaultClient, createVaultClient, VaultCrypto } from '@4nk/vault-sdk'; ``` ### Création d'un client #### Méthode simple ```typescript const client = createVaultClient( 'https://vault.4nkweb.com:6666', 'quantum_resistant_demo_key_32byt' ); ``` #### Méthode avancée ```typescript const client = new VaultClient( { baseUrl: 'https://vault.4nkweb.com:6666', verifySsl: false, // Pour les certificats auto-signés timeout: 15000, // 15 secondes }, 'quantum_resistant_demo_key_32byt' ); ``` ## API Reference ### Classe VaultClient #### Constructeur ```typescript constructor(config: VaultConfig, decryptionKey: string) ``` **Paramètres** : - `config` : Configuration du client - `decryptionKey` : Clé de déchiffrement (32 bytes exactement) **Configuration** : ```typescript interface VaultConfig { baseUrl: string; // URL de base de l'API verifySsl?: boolean; // Validation SSL (défaut: true) timeout?: number; // Timeout en ms (défaut: 30000) } ``` #### Méthodes ##### `getFile(env: string, filePath: string): Promise` Récupère et déchiffre un fichier depuis l'API. **Paramètres** : - `env` : Environnement (ex: "dev", "prod") - `filePath` : Chemin du fichier relatif **Retour** : ```typescript interface VaultFile { content: string; // Contenu déchiffré filename: string; // Nom du fichier size: number; // Taille en caractères encrypted: boolean; // Était chiffré algorithm?: string; // Algorithme utilisé } ``` **Exemple** : ```typescript try { const file = await client.getFile('dev', 'bitcoin/bitcoin.conf'); console.log(`Fichier: ${file.filename}`); console.log(`Taille: ${file.size} caractères`); console.log(`Contenu: ${file.content}`); } catch (error) { console.error('Erreur:', error.message); } ``` ##### `getFiles(requests: FileRequest[]): Promise` Récupère plusieurs fichiers en parallèle. **Paramètres** : ```typescript interface FileRequest { env: string; filePath: string; } ``` **Exemple** : ```typescript const files = await client.getFiles([ { env: 'dev', filePath: 'bitcoin/bitcoin.conf' }, { env: 'dev', filePath: 'tor/torrc' }, { env: 'dev', filePath: 'sdk_relay/sdk_relay.conf' } ]); files.forEach(file => { console.log(`${file.filename}: ${file.size} caractères`); }); ``` ##### `health(): Promise` Vérifie l'état de santé de l'API. **Retour** : ```typescript interface VaultHealth { status: string; // "healthy" ou "unhealthy" service: string; // Nom du service encryption: string; // Type de chiffrement algorithm: string; // Algorithme utilisé } ``` **Exemple** : ```typescript const health = await client.health(); console.log(`Statut: ${health.status}`); console.log(`Chiffrement: ${health.encryption}`); ``` ##### `info(): Promise` Récupère les informations sur l'API. **Retour** : ```typescript interface VaultInfo { name: string; // Nom de l'API version: string; // Version domain: string; // Domaine port: number; // Port protocol: string; // Protocole encryption: string; // Type de chiffrement endpoints: Record; // Endpoints disponibles } ``` **Exemple** : ```typescript const info = await client.info(); console.log(`API: ${info.name} v${info.version}`); console.log(`Domaine: ${info.domain}:${info.port}`); ``` ##### `ping(): Promise` Teste la connectivité à l'API. **Retour** : `true` si connecté, `false` sinon **Exemple** : ```typescript const isConnected = await client.ping(); if (isConnected) { console.log('✅ API accessible'); } else { console.log('❌ API inaccessible'); } ``` ##### `searchFiles(env: string, pattern?: RegExp): Promise` Recherche des fichiers par pattern (non implémenté côté serveur). **Note** : Cette méthode retourne toujours un tableau vide car l'endpoint de recherche n'est pas encore implémenté côté serveur. ### Classe VaultCrypto Utilitaires pour la gestion des clés de chiffrement. #### `generateKey(): string` Génère une clé de déchiffrement aléatoire de 32 bytes. **Retour** : Clé de 32 caractères UTF-8 **Exemple** : ```typescript const randomKey = VaultCrypto.generateKey(); console.log(`Clé générée: ${randomKey.substring(0, 10)}...`); ``` #### `hashToKey(password: string): string` Dérive une clé de 32 bytes depuis un mot de passe. **Paramètres** : - `password` : Mot de passe source **Retour** : Clé de 32 bytes dérivée avec SHA-256 **Exemple** : ```typescript const password = 'mon-mot-de-passe-secret'; const derivedKey = VaultCrypto.hashToKey(password); console.log(`Clé dérivée: ${derivedKey.substring(0, 10)}...`); ``` #### `validateKey(key: string): boolean` Vérifie qu'une clé fait exactement 32 bytes. **Paramètres** : - `key` : Clé à valider **Retour** : `true` si la clé est valide, `false` sinon **Exemple** : ```typescript const key = 'quantum_resistant_demo_key_32byt'; const isValid = VaultCrypto.validateKey(key); console.log(`Clé valide: ${isValid}`); ``` ## Gestion d'erreurs ### Classes d'erreurs #### VaultApiError Erreurs liées aux requêtes HTTP vers l'API. ```typescript class VaultApiError extends Error { constructor( message: string, public statusCode?: number, public endpoint?: string ); } ``` **Propriétés** : - `message` : Message d'erreur - `statusCode` : Code HTTP d'erreur - `endpoint` : Endpoint qui a échoué **Exemple** : ```typescript try { await client.getFile('dev', 'fichier-inexistant.conf'); } catch (error) { if (error instanceof VaultApiError) { console.error(`Erreur API: ${error.message}`); console.error(`Code: ${error.statusCode}`); console.error(`Endpoint: ${error.endpoint}`); } } ``` #### VaultDecryptionError Erreurs liées au déchiffrement des fichiers. ```typescript class VaultDecryptionError extends Error { constructor(message: string); } ``` **Exemple** : ```typescript try { const file = await client.getFile('dev', 'config.conf'); } catch (error) { if (error instanceof VaultDecryptionError) { console.error(`Erreur de déchiffrement: ${error.message}`); } } ``` ### Gestion d'erreurs complète ```typescript async function handleFileRequest(env: string, filePath: string) { try { const file = await client.getFile(env, filePath); return file; } catch (error) { if (error instanceof VaultApiError) { switch (error.statusCode) { case 404: console.error(`Fichier non trouvé: ${filePath}`); break; case 403: console.error(`Accès non autorisé: ${filePath}`); break; case 500: console.error(`Erreur serveur pour: ${filePath}`); break; default: console.error(`Erreur API: ${error.message}`); } } else if (error instanceof VaultDecryptionError) { console.error(`Erreur de déchiffrement: ${error.message}`); } else { console.error(`Erreur inconnue: ${error.message}`); } throw error; } } ``` ## Exemples d'utilisation ### Exemple basique ```typescript import { createVaultClient } from '@4nk/vault-sdk'; async function basicExample() { // Création du client const client = createVaultClient( 'https://vault.4nkweb.com:6666', 'quantum_resistant_demo_key_32byt' ); // Test de connectivité const isConnected = await client.ping(); if (!isConnected) { throw new Error('Impossible de se connecter à l\'API'); } // Récupération d'un fichier const file = await client.getFile('dev', 'bitcoin/bitcoin.conf'); console.log(`Fichier: ${file.filename}`); console.log(`Taille: ${file.size} caractères`); console.log(`Contenu: ${file.content.substring(0, 100)}...`); } ``` ### Exemple avancé avec gestion d'erreurs ```typescript import { VaultClient, VaultApiError, VaultDecryptionError } from '@4nk/vault-sdk'; async function advancedExample() { const client = new VaultClient( { baseUrl: 'https://vault.4nkweb.com:6666', timeout: 10000, }, 'quantum_resistant_demo_key_32byt' ); // Informations sur l'API try { const info = await client.info(); console.log(`API: ${info.name} v${info.version}`); } catch (error) { console.error('Erreur info:', error.message); } // Récupération de plusieurs fichiers const requests = [ { env: 'dev', filePath: 'bitcoin/bitcoin.conf' }, { env: 'dev', filePath: 'tor/torrc' }, { env: 'dev', filePath: 'sdk_relay/sdk_relay.conf' } ]; try { const files = await client.getFiles(requests); console.log(`${files.length} fichiers récupérés`); files.forEach((file, index) => { console.log(`${index + 1}. ${file.filename}: ${file.size} chars`); }); } catch (error) { if (error instanceof VaultApiError) { console.error(`Erreur API: ${error.statusCode} - ${error.message}`); } else if (error instanceof VaultDecryptionError) { console.error(`Erreur de déchiffrement: ${error.message}`); } } } ``` ### Exemple avec retry automatique ```typescript async function retryOperation( operation: () => Promise, maxRetries: number = 3, delay: number = 1000 ): Promise { let lastError: Error; for (let attempt = 1; attempt <= maxRetries; attempt++) { try { return await operation(); } catch (error) { lastError = error as Error; console.log(`Tentative ${attempt}/${maxRetries} échouée: ${lastError.message}`); if (attempt < maxRetries) { await new Promise(resolve => setTimeout(resolve, delay)); } } } throw lastError!; } // Utilisation const file = await retryOperation( () => client.getFile('dev', 'bitcoin/bitcoin.conf'), 3, 500 ); ``` ## Configuration TypeScript ### tsconfig.json recommandé ```json { "compilerOptions": { "target": "ES2020", "module": "commonjs", "lib": ["ES2020", "DOM"], "strict": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, "declaration": true, "sourceMap": true } } ``` ### Types personnalisés ```typescript // Extension des types existants interface CustomVaultFile extends VaultFile { metadata?: { lastModified: Date; checksum: string; }; } // Types pour vos applications interface ConfigFile { environment: string; services: string[]; variables: Record; } ``` ## Tests ### Tests unitaires avec Jest ```typescript import { VaultClient, VaultCrypto } from '@4nk/vault-sdk'; describe('VaultClient', () => { let client: VaultClient; beforeEach(() => { client = new VaultClient( { baseUrl: 'https://vault.4nkweb.com:6666' }, 'quantum_resistant_demo_key_32byt' ); }); it('devrait récupérer un fichier', async () => { const file = await client.getFile('dev', 'bitcoin/bitcoin.conf'); expect(file).toBeDefined(); expect(file.filename).toBe('bitcoin.conf'); expect(file.content).toBeTruthy(); }); it('devrait gérer les erreurs 404', async () => { await expect(client.getFile('dev', 'fichier-inexistant.conf')) .rejects .toThrow('Fichier non trouvé'); }); }); ``` ### Tests d'intégration ```typescript describe('Intégration API', () => { it('devrait fonctionner end-to-end', async () => { const client = createVaultClient( 'https://vault.4nkweb.com:6666', 'quantum_resistant_demo_key_32byt' ); // Test de santé const health = await client.health(); expect(health.status).toBe('healthy'); // Test de fichier const file = await client.getFile('dev', 'bitcoin/bitcoin.conf'); expect(file.content).toContain('bitcoin'); }); }); ``` ## Performance et optimisation ### Récupération parallèle ```typescript // ✅ Bon : Récupération parallèle const files = await client.getFiles(requests); // ❌ Mauvais : Récupération séquentielle const files = []; for (const request of requests) { const file = await client.getFile(request.env, request.filePath); files.push(file); } ``` ### Cache local ```typescript class CachedVaultClient extends VaultClient { private cache = new Map(); async getFile(env: string, filePath: string): Promise { const key = `${env}/${filePath}`; if (this.cache.has(key)) { return this.cache.get(key)!; } const file = await super.getFile(env, filePath); this.cache.set(key, file); return file; } } ``` ## Dépannage ### Problèmes courants #### Erreur de clé de déchiffrement ``` Error: La clé de déchiffrement doit faire exactement 32 bytes ``` **Solution** : Vérifiez que votre clé fait exactement 32 caractères UTF-8. #### Erreur de connectivité ``` Error: fetch failed ``` **Solutions** : - Vérifiez que l'API est démarrée - Vérifiez l'URL de base - Désactivez la validation SSL si nécessaire (`verifySsl: false`) #### Erreur de déchiffrement ``` VaultDecryptionError: Erreur de déchiffrement ``` **Solutions** : - Vérifiez que la clé correspond à celle utilisée côté serveur - Vérifiez que le fichier n'est pas corrompu ### Debug ```typescript // Activation des logs détaillés const client = new VaultClient( { baseUrl: 'https://vault.4nkweb.com:6666', timeout: 30000 }, 'quantum_resistant_demo_key_32byt' ); // Test de connectivité const isConnected = await client.ping(); console.log('Connecté:', isConnected); // Test d'information try { const info = await client.info(); console.log('Info API:', info); } catch (error) { console.error('Erreur info:', error); } ``` ## Support - **Documentation** : [docs/README.md](README.md) - **API Specification** : [docs/api-specification.md](api-specification.md) - **Issues** : [Git Issues](https://git.4nkweb.com/4nk/vault-sdk/issues) - **Email** : sdk-support@4nkweb.com --- **Version SDK** : 1.0.0 **Compatibilité API** : 1.0.0+