Skip to content

Documentation JavaScript CDN

JavaScript CDN Sharokey léger pour intégration rapide dans le navigateur. Fichier unique, aucun processus de build requis - parfait pour les projets simples et le prototypage rapide.

🚀 Démarrage Rapide

Installation

Il suffit d'inclure le script dans votre page HTML :

html
<!-- Inclure le script CDN Sharokey -->
<script src="sharokey.js"></script>
html
<!-- Ou télécharger et utiliser localement -->
<script src="/js/sharokey.js"></script>

Configuration de Base

html
<!DOCTYPE html>
<html>
<head>
    <title>Intégration Sharokey</title>
    <script src="sharokey.js"></script>
</head>
<body>
    <script>
        // Configurer une fois
        Sharokey.config({
            token: 'votre-token-api'
        });
    </script>
</body>
</html>

Premier Secret

javascript
// Créer votre premier secret (syntaxe style CLI)
const secret = await Sharokey.create('Mon premier secret', 24, 1);

console.log('URL du Secret :', secret.share_url);
console.log('Slug du Secret :', secret.slug);

⚙️ Configuration

Configuration Globale

javascript
// Configurer l'objet Sharokey global
Sharokey.config({
    token: 'votre-token-api',              // Requis : Token d'authentification API
    apiUrl: 'https://api.sharokey.com/api/v1'  // Optionnel : URL API personnalisée (utilise la valeur par défaut si omis)
});

Sécurité du Token

Le token API sera visible dans le code côté client. N'utilisez cette approche que sur des domaines de confiance ou pour des opérations non sensibles.

Configuration Spécifique à l'Environnement

javascript
// Développement
if (window.location.hostname === 'localhost') {
    Sharokey.config({
        token: 'dev-token-ici',
        apiUrl: 'https://dev-api.sharokey.com/api/v1'
    });
} else {
    // Production
    Sharokey.config({
        token: 'prod-token-ici'
    });
}

🔐 Créer des Secrets

Création de Secret Basique

Le JavaScript CDN utilise une syntaxe cohérente avec le CLI pour la simplicité :

javascript
// Basique : contenu, heures, vues
const secret = await Sharokey.create(
    'Mot de passe base de données : secret123',
    24,  // 24 heures
    1    // 1 vue
);

console.log('URL de Partage :', secret.share_url);

Avec Options Supplémentaires

javascript
// Avec description, mot de passe et OTP
const secret = await Sharokey.create(
    'Rapport financier T4',
    48,  // 48 heures
    3,   // 3 vues
    {
        description: 'Données financières trimestrielles',
        password: 'ProtectionSupplementaire2024!',
        otp_email: '[email protected]'
    }
);

Limitation OTP

Les OTP par email et SMS sont mutuellement exclusifs - vous ne pouvez en utiliser qu'un par secret.

Avec Pièces Jointes

Depuis un Input Fichier

html
<input type="file" id="fileInput" multiple>
<button onclick="shareWithFiles()">Partager le Secret</button>

<script>
async function shareWithFiles() {
    const fileInput = document.getElementById('fileInput');
    const files = Array.from(fileInput.files);
    
    const secret = await Sharokey.create(
        'Documents du projet',
        72,  // 72 heures
        5,   // 5 vues
        {
            description: 'Contrat et spécifications',
            attachments: files,
            password: 'ProjetSecure2024'
        }
    );
    
    console.log('URL de Partage avec pièces jointes :', secret.share_url);
}
</script>

Intégration Glisser-Déposer

html
<div id="dropZone" ondrop="handleDrop(event)" ondragover="allowDrop(event)">
    Déposez les fichiers ici ou cliquez pour sélectionner
</div>

<script>
function allowDrop(event) {
    event.preventDefault();
}

async function handleDrop(event) {
    event.preventDefault();
    
    const files = Array.from(event.dataTransfer.files);
    
    const secret = await Sharokey.create(
        'Fichiers déposés',
        24, 1,
        {
            description: `${files.length} fichier(s) partagé(s)`,
            attachments: files
        }
    );
    
    alert(`Fichiers partagés ! URL : ${secret.share_url}`);
}
</script>

Limites des pièces jointes : Identiques aux autres librairies - varie selon l'implémentation

Exemple Complet

javascript
// Exemple avec toutes les options
const secret = await Sharokey.create(
    'Documents de fusion hautement confidentiels',
    72,  // 3 jours
    2,   // 2 vues max
    {
        description: 'Documents M&A pour révision du conseil',
        password: 'ConseilAdministration2024!',
        otp_email: '[email protected]',
        attachments: attachmentFiles // Depuis input fichier ou glisser-déposer
    }
);

// Afficher le résultat
document.getElementById('result').innerHTML = `
    <h3>Secret Créé avec Succès !</h3>
    <p><strong>URL de Partage :</strong> <a href="${secret.share_url}" target="_blank">${secret.share_url}</a></p>
    <p><strong>Expire :</strong> ${secret.expires_at}</p>
    <p><strong>Vues Max :</strong> ${secret.maximum_views}</p>
    <p><strong>Pièces jointes :</strong> ${secret.attachment_count || 0}</p>
`;

📝 Gestion des Secrets

Lister les Secrets

javascript
// Listage basique
const secrets = await Sharokey.list();

// Avec filtres
const filtered = await Sharokey.list({
    limit: 10,
    status: 'active'
});

// Afficher dans un tableau
function displaySecrets(secrets) {
    const tableRows = secrets.map(secret => `
        <tr>
            <td>${secret.slug}</td>
            <td>${secret.description || 'Aucune description'}</td>
            <td>${secret.status}</td>
            <td>${secret.remaining_views}/${secret.maximum_views}</td>
            <td>${new Date(secret.expires_at).toLocaleDateString()}</td>
        </tr>
    `).join('');
    
    document.getElementById('secretsTable').innerHTML = `
        <table border="1">
            <thead>
                <tr>
                    <th>Slug</th>
                    <th>Description</th>
                    <th>Statut</th>
                    <th>Vues</th>
                    <th>Expire</th>
                </tr>
            </thead>
            <tbody>
                ${tableRows}
            </tbody>
        </table>
    `;
}

Détails d'un Secret

javascript
// Obtenir un secret spécifique
const secret = await Sharokey.get('ABC123XYZ');

// Afficher les détails
document.getElementById('secretDetails').innerHTML = `
    <h3>Détails du Secret</h3>
    <p><strong>Description :</strong> ${secret.description}</p>
    <p><strong>Statut :</strong> ${secret.status}</p>
    <p><strong>Créé :</strong> ${new Date(secret.created_at).toLocaleString()}</p>
    <p><strong>Expire :</strong> ${new Date(secret.expires_at).toLocaleString()}</p>
    <p><strong>Vues Restantes :</strong> ${secret.remaining_views}/${secret.maximum_views}</p>
    <p><strong>A un Mot de Passe :</strong> ${secret.has_password ? 'Oui' : 'Non'}</p>
    <p><strong>A un OTP :</strong> ${secret.has_otp ? 'Oui' : 'Non'}</p>
    <p><strong>Pièces jointes :</strong> ${secret.attachment_count || 0}</p>
`;

Supprimer des Secrets

javascript
// Supprimer un secret unique
await Sharokey.delete('ABC123XYZ');
alert('Secret supprimé avec succès');

// Supprimer avec confirmation
function confirmDelete(slug) {
    if (confirm(`Êtes-vous sûr de vouloir supprimer le secret ${slug} ?`)) {
        Sharokey.delete(slug)
            .then(() => alert('Secret supprimé'))
            .catch(error => alert('Échec de suppression : ' + error.message));
    }
}

🔧 Fonctions Utilitaires

Génération de Mots de Passe

javascript
// Générer un mot de passe sécurisé
const password = await Sharokey.generatePassword();
console.log('Mot de passe généré :', password); // 16 caractères par défaut

// Longueur personnalisée (8-32 caractères)
const longPassword = await Sharokey.generatePassword(24);

// Utiliser dans un formulaire
document.getElementById('passwordField').value = await Sharokey.generatePassword(16);

Test de Connectivité

javascript
// Tester la connectivité API
try {
    const isConnected = await Sharokey.testConnection();
    if (isConnected) {
        document.getElementById('status').innerHTML = '✅ API Connectée';
        document.getElementById('status').className = 'success';
    }
} catch (error) {
    document.getElementById('status').innerHTML = '❌ Échec de Connexion : ' + error.message;
    document.getElementById('status').className = 'error';
}

Statistiques

javascript
// Obtenir les statistiques du compte
const stats = await Sharokey.stats();

// Afficher dans un tableau de bord
document.getElementById('dashboard').innerHTML = `
    <div class="stats-grid">
        <div class="stat">
            <h3>${stats.total_secrets}</h3>
            <p>Total des Secrets</p>
        </div>
        <div class="stat">
            <h3>${stats.active_secrets}</h3>
            <p>Secrets Actifs</p>
        </div>
        <div class="stat">
            <h3>${stats.total_views}</h3>
            <p>Total des Vues</p>
        </div>
        <div class="stat">
            <h3>${(stats.storage_used / 1024 / 1024).toFixed(1)} Mo</h3>
            <p>Stockage Utilisé</p>
        </div>
    </div>
`;

📧 Demandes de Secret

Demander à d'autres personnes de partager des secrets avec vous de manière sécurisée via des URL de demande générées.

Créer une Demande de Secret

javascript
// Demande de secret de base
const request = await Sharokey.createRequest({
  message: "Merci de partager les identifiants de base de données",
  description: "Accès DB production nécessaire",
  secretExpirationHours: 24,  // Le secret expirera dans 24h
  requestExpirationHours: 48, // La demande expire dans 48h
  maximumViews: 1,            // Le secret peut être vu une seule fois
  emailTo: "[email protected]",
  emailReply: "[email protected]"
});

console.log('Demande créée:', request.url);
console.log('Envoyer cette URL au destinataire:', request.url);

Intégration avec un Formulaire

html
<form id="requestForm">
    <div>
        <label for="requestMessage">Message pour le destinataire :</label>
        <textarea id="requestMessage" placeholder="Merci de partager les informations demandées"></textarea>
    </div>
    <div>
        <label for="requestDescription">Description interne :</label>
        <input type="text" id="requestDescription" placeholder="Description pour votre référence">
    </div>
    <div>
        <label for="emailTo">Email du destinataire :</label>
        <input type="email" id="emailTo" placeholder="[email protected]">
    </div>
    <button type="submit">Créer la Demande</button>
</form>

<div id="requestResult"></div>

<script>
document.getElementById('requestForm').addEventListener('submit', async (e) => {
    e.preventDefault();
    
    try {
        const request = await Sharokey.createRequest({
            message: document.getElementById('requestMessage').value,
            description: document.getElementById('requestDescription').value,
            emailTo: document.getElementById('emailTo').value,
            secretExpirationHours: 24,
            requestExpirationHours: 48,
            maximumViews: 1
        });
        
        document.getElementById('requestResult').innerHTML = `
            <div class="success">
                <h3>Demande Créée !</h3>
                <p><strong>URL de la Demande :</strong> <br>
                <input type="text" value="${request.url}" readonly onclick="this.select()"></p>
                <button onclick="copyToClipboard('${request.url}')">Copier l'URL</button>
                <p><small>Envoyez cette URL au destinataire pour qu'il puisse partager le secret de manière sécurisée.</small></p>
            </div>
        `;
        
        document.getElementById('requestForm').reset();
        
    } catch (error) {
        document.getElementById('requestResult').innerHTML = `
            <div class="error">
                <h3>Erreur de Création de la Demande</h3>
                <p>${error.message}</p>
            </div>
        `;
    }
});
</script>

Lister et Gérer les Demandes

javascript
// Lister toutes les demandes
const requests = await Sharokey.listRequests({status: 'active', limit: 10});
console.log('Demandes actives:', requests.data.length);

// Afficher dans un tableau
function displayRequests(requests) {
    const tableRows = requests.data.map(req => `
        <tr>
            <td>${req.token}</td>
            <td>${req.description || 'Aucune description'}</td>
            <td>${req.status}</td>
            <td>${new Date(req.request_expiration).toLocaleDateString()}</td>
            <td>
                <button onclick="deleteRequest(${req.id})">Supprimer</button>
                <button onclick="copyToClipboard('${req.url}')">Copier URL</button>
            </td>
        </tr>
    `).join('');
    
    document.getElementById('requestsTable').innerHTML = `
        <table border="1">
            <thead>
                <tr>
                    <th>Token</th>
                    <th>Description</th>
                    <th>Statut</th>
                    <th>Expire</th>
                    <th>Actions</th>
                </tr>
            </thead>
            <tbody>
                ${tableRows}
            </tbody>
        </table>
    `;
}

// Supprimer une demande
async function deleteRequest(requestId) {
    if (confirm('Êtes-vous sûr de vouloir supprimer cette demande ?')) {
        try {
            await Sharokey.deleteRequest(requestId);
            alert('Demande supprimée avec succès');
            // Recharger la liste
            loadRequests();
        } catch (error) {
            alert('Erreur lors de la suppression : ' + error.message);
        }
    }
}

// Charger les demandes
async function loadRequests() {
    try {
        const requests = await Sharokey.listRequests({limit: 20});
        displayRequests(requests);
    } catch (error) {
        document.getElementById('requestsTable').innerHTML = `
            <div class="error">Erreur de chargement des demandes : ${error.message}</div>
        `;
    }
}

Statistiques des Demandes

javascript
// Obtenir les statistiques des demandes
const stats = await Sharokey.requestStats();

// Afficher dans un tableau de bord
document.getElementById('requestStats').innerHTML = `
    <div class="stats-grid">
        <div class="stat">
            <h3>${stats.total_requests || 0}</h3>
            <p>Total Demandes</p>
        </div>
        <div class="stat">
            <h3>${stats.active_requests || 0}</h3>
            <p>Demandes Actives</p>
        </div>
        <div class="stat">
            <h3>${stats.expired_requests || 0}</h3>
            <p>Demandes Expirées</p>
        </div>
        <div class="stat">
            <h3>${stats.requests_created_today || 0}</h3>
            <p>Créées Aujourd'hui</p>
        </div>
    </div>
`;

Tableau de Bord Complet avec Demandes

html
<div id="fullDashboard">
    <div class="tabs">
        <button onclick="showTab('secrets')" class="tab-button active">Secrets</button>
        <button onclick="showTab('requests')" class="tab-button">Demandes</button>
        <button onclick="showTab('stats')" class="tab-button">Statistiques</button>
    </div>
    
    <div id="secretsTab" class="tab-content active">
        <h3>Mes Secrets</h3>
        <div id="secretsList"></div>
    </div>
    
    <div id="requestsTab" class="tab-content">
        <h3>Mes Demandes de Secret</h3>
        <button onclick="loadRequests()">Actualiser</button>
        <div id="requestsList"></div>
    </div>
    
    <div id="statsTab" class="tab-content">
        <h3>Statistiques</h3>
        <div id="combinedStats"></div>
    </div>
</div>

<script>
function showTab(tabName) {
    // Masquer tous les onglets
    document.querySelectorAll('.tab-content').forEach(tab => {
        tab.classList.remove('active');
    });
    document.querySelectorAll('.tab-button').forEach(btn => {
        btn.classList.remove('active');
    });
    
    // Afficher l'onglet sélectionné
    document.getElementById(tabName + 'Tab').classList.add('active');
    event.target.classList.add('active');
    
    // Charger le contenu si nécessaire
    if (tabName === 'requests') {
        loadRequests();
    } else if (tabName === 'stats') {
        loadCombinedStats();
    }
}

async function loadCombinedStats() {
    try {
        const [secretStats, requestStats] = await Promise.all([
            Sharokey.stats(),
            Sharokey.requestStats()
        ]);
        
        document.getElementById('combinedStats').innerHTML = `
            <div class="stats-section">
                <h4>Secrets</h4>
                <p>Total : ${secretStats.total_secrets} | Actifs : ${secretStats.active_secrets}</p>
            </div>
            <div class="stats-section">
                <h4>Demandes de Secret</h4>
                <p>Total : ${requestStats.total_requests || 0} | Actives : ${requestStats.active_requests || 0}</p>
            </div>
        `;
    } catch (error) {
        document.getElementById('combinedStats').innerHTML = `
            <div class="error">Erreur de chargement des statistiques : ${error.message}</div>
        `;
    }
}
</script>

<style>
.tabs {
    border-bottom: 1px solid #ccc;
    margin-bottom: 20px;
}

.tab-button {
    background: none;
    border: none;
    padding: 10px 20px;
    cursor: pointer;
    border-bottom: 2px solid transparent;
}

.tab-button.active {
    border-bottom-color: #007cba;
    font-weight: bold;
}

.tab-content {
    display: none;
}

.tab-content.active {
    display: block;
}

.stats-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 20px;
}

.stat {
    text-align: center;
    padding: 20px;
    border: 1px solid #ddd;
    border-radius: 5px;
}
</style>

🎯 Compatibilité Navigateurs

Le JavaScript CDN prend en charge les navigateurs modernes avec l'API Web Crypto :

  • Chrome : 60+
  • Firefox : 55+
  • Safari : 11+
  • Edge : 79+
  • Internet Explorer : Non supporté (manque l'API Web Crypto)

Détection de Fonctionnalité

javascript
// Vérifier la compatibilité avant utilisation
if (!window.crypto || !window.crypto.subtle) {
    document.getElementById('app').innerHTML = `
        <div class="error">
            <h2>Navigateur Non Supporté</h2>
            <p>Cette application nécessite un navigateur moderne avec support de l'API Web Crypto.</p>
            <p>Veuillez mettre à niveau vers une version récente de Chrome, Firefox, Safari, ou Edge.</p>
        </div>
    `;
} else {
    // Initialiser Sharokey
    Sharokey.config({ token: 'votre-token' });
}

🚨 Gestion d'Erreurs

Gestion d'Erreurs Basique

javascript
// Gérer les erreurs avec try-catch
try {
    const secret = await Sharokey.create('Mon secret', 24, 1);
    showSuccess('Secret créé : ' + secret.share_url);
} catch (error) {
    showError('Échec de création du secret : ' + error.message);
}

function showSuccess(message) {
    document.getElementById('message').innerHTML = `<div class="success">${message}</div>`;
}

function showError(message) {
    document.getElementById('message').innerHTML = `<div class="error">${message}</div>`;
}

Information d'Erreur Détaillée

javascript
// Gestion d'erreurs plus détaillée
async function createSecretSafely(content, hours, views, options = {}) {
    try {
        return await Sharokey.create(content, hours, views, options);
    } catch (error) {
        console.error('Erreur Sharokey :', error);
        
        // Vérifier le type d'erreur
        if (error.message.includes('Authentication')) {
            showError('Échec de l\'authentification. Veuillez vérifier votre token API.');
        } else if (error.message.includes('validation')) {
            showError('Erreur de validation : ' + error.message);
        } else if (error.message.includes('file')) {
            showError('Erreur de fichier : ' + error.message);
        } else if (error.message.includes('network')) {
            showError('Erreur réseau. Veuillez vérifier votre connexion.');
        } else {
            showError('Une erreur inattendue s\'est produite : ' + error.message);
        }
        
        return null;
    }
}

🔐 Considérations de Sécurité

Gestion des Tokens

javascript
// Utiliser des tokens spécifiques à l'environnement
const getApiToken = () => {
    if (window.location.hostname === 'localhost') {
        return 'dev_token_ici';
    } else if (window.location.hostname.includes('staging')) {
        return 'staging_token_ici';
    } else {
        return 'production_token_ici';
    }
};

Sharokey.config({ token: getApiToken() });

HTTPS Uniquement

javascript
// Assurer HTTPS en production
if (location.protocol !== 'https:' && location.hostname !== 'localhost') {
    location.replace(`https:${location.href.substring(location.protocol.length)}`);
}

Sécurité du Contenu

javascript
// Valider le contenu avant partage
function validateSecretContent(content) {
    if (!content || content.trim().length === 0) {
        throw new Error('Le contenu du secret ne peut pas être vide');
    }
    
    if (content.length > 100000) { // Limite 100Ko
        throw new Error('Contenu trop volumineux');
    }
    
    // Vérifier les motifs potentiellement sensibles
    const sensitivePatterns = [
        /password\s*[:=]\s*\w+/i,
        /api[_-]?key\s*[:=]\s*\w+/i
    ];
    
    for (const pattern of sensitivePatterns) {
        if (pattern.test(content)) {
            console.warn('Le contenu semble contenir des informations sensibles');
            break;
        }
    }
    
    return true;
}

🎨 Exemples d'Intégration

Intégration de Formulaire Simple

html
<form id="secretForm">
    <div>
        <label for="content">Contenu du Secret :</label>
        <textarea id="content" required></textarea>
    </div>
    <div>
        <label for="hours">Expire dans (heures) :</label>
        <input type="number" id="hours" min="1" max="1000" value="24">
    </div>
    <div>
        <label for="views">Vues maximum :</label>
        <input type="number" id="views" min="1" max="10" value="1">
    </div>
    <div>
        <label for="password">Protection par mot de passe (optionnel) :</label>
        <input type="password" id="password">
    </div>
    <div>
        <label for="files">Pièces jointes (optionnel) :</label>
        <input type="file" id="files" multiple>
    </div>
    <button type="submit">Créer le Secret</button>
</form>

<div id="result"></div>

<script>
document.getElementById('secretForm').addEventListener('submit', async (e) => {
    e.preventDefault();
    
    const content = document.getElementById('content').value;
    const hours = parseInt(document.getElementById('hours').value);
    const views = parseInt(document.getElementById('views').value);
    const password = document.getElementById('password').value;
    const files = Array.from(document.getElementById('files').files);
    
    try {
        const options = {};
        if (password) options.password = password;
        if (files.length > 0) options.attachments = files;
        
        const secret = await Sharokey.create(content, hours, views, options);
        
        document.getElementById('result').innerHTML = `
            <div class="success">
                <h3>Secret Créé !</h3>
                <p><strong>URL de Partage :</strong> <br>
                <input type="text" value="${secret.share_url}" readonly onclick="this.select()"></p>
                <button onclick="copyToClipboard('${secret.share_url}')">Copier l'URL</button>
            </div>
        `;
        
        // Vider le formulaire
        document.getElementById('secretForm').reset();
        
    } catch (error) {
        document.getElementById('result').innerHTML = `
            <div class="error">
                <h3>Erreur de Création du Secret</h3>
                <p>${error.message}</p>
            </div>
        `;
    }
});

function copyToClipboard(text) {
    navigator.clipboard.writeText(text).then(() => {
        alert('URL copiée dans le presse-papiers !');
    });
}
</script>

Tableau de Bord de Gestion

html
<div id="dashboard">
    <div class="controls">
        <button onclick="loadSecrets()">Actualiser les Secrets</button>
        <button onclick="loadStats()">Charger les Statistiques</button>
        <button onclick="testConnection()">Tester la Connexion</button>
    </div>
    
    <div id="stats"></div>
    <div id="secrets"></div>
</div>

<script>
async function loadSecrets() {
    try {
        const secrets = await Sharokey.list({ limit: 50 });
        displaySecrets(secrets);
    } catch (error) {
        document.getElementById('secrets').innerHTML = `<div class="error">Erreur de chargement des secrets : ${error.message}</div>`;
    }
}

async function loadStats() {
    try {
        const stats = await Sharokey.stats();
        document.getElementById('stats').innerHTML = `
            <div class="stats">
                <h3>Statistiques du Compte</h3>
                <p>Total : ${stats.total_secrets} | Actifs : ${stats.active_secrets} | Vues : ${stats.total_views}</p>
            </div>
        `;
    } catch (error) {
        document.getElementById('stats').innerHTML = `<div class="error">Erreur de chargement des stats : ${error.message}</div>`;
    }
}

async function testConnection() {
    try {
        const connected = await Sharokey.testConnection();
        alert(connected ? 'Connexion réussie !' : 'Échec de connexion !');
    } catch (error) {
        alert('Test de connexion échoué : ' + error.message);
    }
}

// Charger le tableau de bord au chargement de la page
window.addEventListener('load', () => {
    loadSecrets();
    loadStats();
});
</script>

📏 Taille de Fichier et Limites

Le fichier JavaScript CDN est conçu pour la simplicité :

  • Taille du fichier : ~150Ko (minifié)
  • Dépendances : Aucune (autonome)
  • Limitations navigateur : Mêmes limites de pièces jointes que les autres librairies
  • Exposition du token : Visible côté client (utiliser des mesures de sécurité appropriées)

🔗 Ressources Associées

📜 License

Le JavaScript CDN Sharokey est distribué sous la Licence MIT.
Voir LICENSE pour plus de détails.

Released under the MIT License.