Documentation SDK JavaScript
La librairie JavaScript Sharokey permet d'intégrer facilement le partage de secrets sécurisés dans vos applications JavaScript/TypeScript. Elle reproduit toutes les fonctionnalités du CLI Sharokey avec une API moderne et intuitive.
✨ Fonctionnalités principales
- 🔐 Chiffrement Zero Knowledge : AES-GCM-256 côté client
- 🌍 Multi-environnement : Node.js et navigateurs
- 📱 API moderne : Promises, async/await, TypeScript
- 🔑 Authentification flexible : Token API ou Microsoft SSO
- 📎 Pièces jointes : Support des fichiers chiffrés
- 🎛️ Configuration avancée : Retry, timeout, logs
- 🧪 Tests complets : Coverage et validation
📦 Installation
⚠️ Note importante : Ce package n'est pas encore disponible sur NPM. La documentation décrit l'API future.
NPM (à venir)
# Pas encore disponible
# npm install sharokey-jsYarn (à venir)
# Pas encore disponible
# yarn add sharokey-jsCDN (navigateur) - Pas encore disponible
<!-- Pas encore disponible -->
<!-- <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/sharokey.min.js"></script> -->🚀 Démarrage rapide
Import ES6/TypeScript
import { SharokeyClient } from 'sharokey-js';
// ou
import SharokeyClient from 'sharokey-js';Require CommonJS
const { SharokeyClient } = require('sharokey-js');Usage de base
// Configuration du client
const client = new SharokeyClient({
token: 'votre-token-api',
apiUrl: 'https://api.sharokey.com/api/v1'
});
// Créer un secret
const secret = await client.createSecret({
content: "Mon mot de passe secret",
expirationHours: 24,
maximumViews: 1,
description: "Accès temporaire"
});
console.log('Secret créé:', secret.shareUrl);
console.log('Expire le:', secret.expiration);⚙️ Configuration
Configuration de base
const client = new SharokeyClient({
token: 'votre-token-api', // REQUIS
apiUrl: 'https://api.sharokey.com/api/v1', // Optionnel
timeout: 30000, // 30 secondes
retries: 3 // 3 tentatives
});Configuration avancée
const client = new SharokeyClient({
token: 'votre-token-api',
apiUrl: 'https://api.sharokey.com/api/v1',
timeout: 60000,
retries: 5,
defaultExpirationHours: 48,
defaultMaximumViews: 3,
logLevel: 'info', // debug, info, warn, error
validateSsl: true,
headers: {
'X-Custom-Header': 'value'
}
});Validation de configuration
import { validateConfig } from 'sharokey-js';
const errors = validateConfig({
token: 'test',
timeout: -1 // Erreur
});
if (errors.length > 0) {
console.error('Erreurs de configuration:', errors);
}🔑 Authentification
Avec token API
const client = new SharokeyClient({
token: 'sk_live_abcdefghijklmnop1234567890'
});
// Valider le token
const userInfo = await client.validateToken();
if (userInfo) {
console.log('Connecté en tant que:', userInfo.email);
} else {
console.error('Token invalide');
}Test de connectivité
const isConnected = await client.testConnection();
if (!isConnected) {
throw new Error('Impossible de se connecter à l\'API Sharokey');
}Informations utilisateur
const user = client.getCurrentUser();
console.log('Utilisateur actuel:', user);📝 Créer des secrets
Création simple
const secret = await client.createSecret("Mon secret");
console.log('Lien de partage:', secret.shareUrl);Création avec options
const secret = await client.createSecret({
content: "Informations confidentielles",
description: "Données client importantes",
message: "Merci de consulter avant demain",
expirationHours: 48,
maximumViews: 3,
password: "protection-additionnelle"
});Avec pièces jointes
import fs from 'fs';
const fileData = fs.readFileSync('document.pdf');
const secret = await client.createSecret({
content: "Voici le document demandé",
description: "Contrat confidentiel",
expirationHours: 72,
maximumViews: 1,
attachments: [
{
name: 'contrat.pdf',
data: fileData
},
{
name: 'annexe.docx',
data: annexeData
}
]
});Avec protection OTP
const secret = await client.createSecret({
content: "Code d'accès critique",
expirationHours: 1,
maximumViews: 1,
otpEmail: "[email protected]",
// ou
otpPhone: "+33123456789"
});Générateur de mot de passe
// Générer un mot de passe simple
const password = client.generatePassword();
console.log('Mot de passe généré:', password);
// Générer et créer un secret
const result = await client.createPasswordSecret(
"Accès temporaire serveur",
{
passwordLength: 20,
includeSymbols: true,
expirationHours: 2,
maximumViews: 1
}
);
console.log('Mot de passe:', result.password);
console.log('Lien:', result.secret.shareUrl);Builder pattern
import { createSecretRequest } from 'sharokey-js';
const request = createSecretRequest()
.setContent("Secret complexe")
.setDescription("Description détaillée")
.setExpirationHours(24)
.setMaximumViews(5)
.setPassword("motdepasse")
.addAttachment('fichier1.txt', buffer1)
.addAttachment('fichier2.pdf', buffer2);
const secret = await client.createSecret(request);📊 Lister et gérer
Lister tous les secrets
const result = await client.listSecrets();
console.log(`${result.data.length} secrets trouvés`);
result.data.forEach(secret => {
console.log(`${secret.slug}: ${secret.description} (${secret.currentViews}/${secret.maximumViews})`);
});Lister avec filtres
const secrets = await client.listSecrets({
status: 'active',
creator: '[email protected]',
limit: 10,
search: 'mot-clé'
});Détails d'un secret
const secret = await client.getSecret('ABC123XY');
console.log('Description:', secret.description);
console.log('Créateur:', secret.creator);
console.log('Vues restantes:', secret.getRemainingViews());
console.log('Expire dans:', secret.getTimeRemaining(), 'ms');
console.log('Actif:', secret.isActive());Supprimer un secret
const deleted = await client.deleteSecret('ABC123XY');
if (deleted) {
console.log('Secret supprimé avec succès');
}Statistiques d'usage
const stats = await client.getStatistics();
console.log('Statistiques:');
console.log('- Total secrets:', stats.totalSecrets);
console.log('- Secrets actifs:', stats.activeSecrets);
console.log('- Secrets expirés:', stats.expiredSecrets);
console.log('- Total vues:', stats.totalViews);
console.log('- Taux protection:', stats.getPasswordProtectionRate() + '%');
console.log('- Moyenne vues:', stats.getAverageViewsPerSecret());🔧 Fonctionnalités avancées
Recherche de secrets
const secrets = await client.searchSecrets("mot-clé", {
limit: 20,
status: 'active'
});
console.log(`${secrets.length} secrets trouvés`);Secrets actifs uniquement
const activeSecrets = await client.getActiveSecrets(50);
console.log('Secrets encore consultables:', activeSecrets.length);Mise à jour de configuration
client.updateConfig({
timeout: 60000,
retries: 5,
logLevel: 'debug'
});
// Chaînable
client.updateConfig({ timeout: 30000 })
.updateConfig({ retries: 3 });📖 Référence API
SharokeyClient
Méthodes principales
createSecret(content, options?)→Promise<Secret>listSecrets(filters?)→Promise<ListResponse<Secret>>getSecret(slug)→Promise<Secret>deleteSecret(slug)→Promise<boolean>getStatistics()→Promise<Statistics>
Méthodes utilitaires
generatePassword(length?, symbols?)→stringtestConnection()→Promise<boolean>validateToken()→Promise<Object|null>getCurrentUser()→Object|nullgetInfo()→ClientInfo
Méthodes avancées
createPasswordSecret(desc, options?)→Promise<{secret, password}>searchSecrets(query, options?)→Promise<Secret[]>getActiveSecrets(limit?)→Promise<Secret[]>
Méthodes de Demandes de Secret
createSecretRequest(options?)→Promise<SecretRequest>listSecretRequests(filters?)→Promise<ListResponse<SecretRequest>>getSecretRequest(id)→Promise<SecretRequest>deleteSecretRequest(id)→Promise<boolean>getSecretRequestStatistics()→Promise<Object>getActiveSecretRequests(limit?)→Promise<SecretRequest[]>
Secret
Propriétés
slug: string- Identifiant uniquedescription: string- Descriptioncreator: string- Email du créateurmaximumViews: number- Vues maximumcurrentViews: number- Vues actuellesexpiration: Date- Date d'expirationhasAttachments: boolean- A des pièces jointesshareUrl: string- URL de partage complète
Méthodes
isActive()→booleangetRemainingViews()→numbergetTimeRemaining()→number|null
Statistics
Propriétés
totalSecrets: number- Total des secretsactiveSecrets: number- Secrets actifsexpiredSecrets: number- Secrets expiréstotalViews: number- Total des vues
Méthodes
getPasswordProtectionRate()→numbergetAverageViewsPerSecret()→number
SecretRequest
Propriétés
id: number- Identifiant uniquetoken: string- Token de la demandemessage: string- Message pour le destinatairedescription: string- Description internesecretExpirationHours: number- Heures avant expiration du secretrequestExpirationHours: number- Heures avant expiration de la demandemaximumViews: number- Vues maximum pour le secretemailTo: string- Email du destinataireemailReply: string- Email de réponsecreator: string- Email du créateurstatus: string- Statut de la demande (active, expired)url: string- URL de partage de la demandecreatedAt: Date- Date de création
Méthodes
isActive()→booleanisExpired()→booleangetShareUrl()→string
💡 Exemples pratiques
Application web de partage
class SecretManager {
constructor(token) {
this.client = new SharokeyClient({ token });
}
async sharePassword(password, recipient) {
const secret = await this.client.createSecret({
content: password,
description: `Mot de passe pour ${recipient}`,
expirationHours: 1,
maximumViews: 1,
otpEmail: recipient
});
return secret.shareUrl;
}
async shareDocument(filePath, description) {
const fs = require('fs');
const fileData = fs.readFileSync(filePath);
const secret = await this.client.createSecret({
content: "Document confidentiel ci-joint",
description: description,
expirationHours: 48,
maximumViews: 3,
attachments: [{
name: path.basename(filePath),
data: fileData
}]
});
return secret.shareUrl;
}
async requestCredentials(email, description) {
const request = await this.client.createSecretRequest({
message: "Merci de partager les identifiants demandés de manière sécurisée",
description: description,
secretExpirationHours: 24,
requestExpirationHours: 48,
maximumViews: 1,
emailTo: email,
emailReply: "[email protected]"
});
return request.url;
}
async getDashboard() {
const [stats, activeSecrets, activeRequests] = await Promise.all([
this.client.getStatistics(),
this.client.getActiveSecrets(10),
this.client.getActiveSecretRequests(5)
]);
return { stats, activeSecrets, activeRequests };
}
}Script de maintenance
#!/usr/bin/env node
const { SharokeyClient } = require('sharokey-js');
async function maintenance() {
const client = new SharokeyClient({
token: process.env.SHAROKEY_TOKEN,
logLevel: 'info'
});
// Vérifier la connectivité
const connected = await client.testConnection();
if (!connected) {
console.error('❌ Impossible de se connecter');
process.exit(1);
}
// Afficher les secrets actifs
console.log('📋 Récupération des secrets actifs...');
const activeSecrets = await client.getActiveSecrets();
console.log(`✅ ${activeSecrets.length} secrets actifs`);
// Afficher les statistiques
const stats = await client.getStatistics();
console.log('\n📊 Statistiques:');
console.log(`- Secrets actifs: ${stats.activeSecrets}`);
console.log(`- Total vues: ${stats.totalViews}`);
process.exit(0);
}
maintenance().catch(console.error);Intégration Express.js
const express = require('express');
const { SharokeyClient } = require('sharokey-js');
const app = express();
const client = new SharokeyClient({
token: process.env.SHAROKEY_TOKEN
});
app.use(express.json());
// Créer un secret via API REST
app.post('/api/secrets', async (req, res) => {
try {
const { content, description, hours, views } = req.body;
const secret = await client.createSecret({
content,
description,
expirationHours: hours || 24,
maximumViews: views || 1
});
res.json({
success: true,
shareUrl: secret.shareUrl,
expiresAt: secret.expiration
});
} catch (error) {
res.status(500).json({
success: false,
error: error.message
});
}
});
// Lister les secrets
app.get('/api/secrets', async (req, res) => {
try {
const result = await client.listSecrets({
limit: parseInt(req.query.limit) || 50
});
res.json({
success: true,
secrets: result.data,
pagination: result.meta
});
} catch (error) {
res.status(500).json({
success: false,
error: error.message
});
}
});
app.listen(3000, () => {
console.log('API démarrée sur http://localhost:3000');
});Usage React Hook
import { useState, useEffect } from 'react';
import { SharokeyClient } from 'sharokey-js';
function useSharokey(token) {
const [client] = useState(() => new SharokeyClient({ token }));
const [secrets, setSecrets] = useState([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const createSecret = async (content, options) => {
setLoading(true);
try {
const secret = await client.createSecret(content, options);
setSecrets(prev => [secret, ...prev]);
return secret;
} catch (err) {
setError(err.message);
throw err;
} finally {
setLoading(false);
}
};
const refreshSecrets = async () => {
setLoading(true);
try {
const result = await client.listSecrets();
setSecrets(result.data);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
};
useEffect(() => {
refreshSecrets();
}, []);
return {
secrets,
loading,
error,
createSecret,
refreshSecrets,
client
};
}
// Usage dans un composant
function SecretManager() {
const { secrets, createSecret, loading } = useSharokey(process.env.REACT_APP_SHAROKEY_TOKEN);
const handleCreate = async () => {
await createSecret("Mon nouveau secret", {
expirationHours: 24,
maximumViews: 1
});
};
return (
<div>
<button onClick={handleCreate} disabled={loading}>
Créer un secret
</button>
<ul>
{secrets.map(secret => (
<li key={secret.slug}>
{secret.description} - {secret.getRemainingViews()} vues restantes
</li>
))}
</ul>
</div>
);
}🚨 Gestion d'erreurs
Types d'erreurs
import { ApiError } from 'sharokey-js';
try {
await client.createSecret("test");
} catch (error) {
if (error instanceof ApiError) {
switch (error.status) {
case 401:
console.error('Token invalide ou expiré');
break;
case 403:
console.error('Accès refusé');
break;
case 429:
console.error('Limite de taux atteinte');
break;
case 500:
console.error('Erreur serveur:', error.message);
break;
default:
console.error(`Erreur API ${error.status}:`, error.message);
}
} else {
console.error('Erreur locale:', error.message);
}
}Validation locale
try {
const secret = await client.createSecret({
content: "", // Erreur de validation
expirationHours: -1 // Erreur de validation
});
} catch (error) {
console.error('Erreur de validation:', error.message);
// "Erreurs de validation : Le contenu est requis, Les heures d'expiration doivent être entre 1 et 1000"
}Retry automatique
// Les erreurs réseau sont automatiquement retentées
const client = new SharokeyClient({
token: 'test',
retries: 5, // 5 tentatives maximum
timeout: 60000 // 60 secondes
});
// Les erreurs 4xx ne sont PAS retentées (erreurs client)
// Les erreurs 5xx SONT retentées (erreurs serveur)Gestion robuste
async function createSecretSafely(content, options) {
const maxRetries = 3;
let lastError;
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await client.createSecret(content, options);
} catch (error) {
lastError = error;
if (error instanceof ApiError) {
// Erreurs non récupérables
if (error.status === 401 || error.status === 403) {
throw error;
}
// Erreurs temporaires - attendre avant retry
if (error.status >= 500) {
const delay = Math.min(1000 * Math.pow(2, attempt - 1), 10000);
console.warn(`Tentative ${attempt}/${maxRetries} échouée, retry dans ${delay}ms`);
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}
}
// Autres erreurs - retry immédiat
console.warn(`Tentative ${attempt}/${maxRetries} échouée:`, error.message);
}
}
throw lastError;
}🎛️ Configuration avancée
Variables d'environnement
# .env
SHAROKEY_TOKEN=sk_live_abcdefghijklmnop1234567890
SHAROKEY_API_URL=https://api.sharokey.com/api/v1
SHAROKEY_TIMEOUT=60000
SHAROKEY_LOG_LEVEL=infoconst client = new SharokeyClient({
token: process.env.SHAROKEY_TOKEN,
apiUrl: process.env.SHAROKEY_API_URL,
timeout: parseInt(process.env.SHAROKEY_TIMEOUT) || 30000,
logLevel: process.env.SHAROKEY_LOG_LEVEL || 'info'
});Configuration par environnement
const configs = {
development: {
apiUrl: 'https://dev.api.sharokey.com/api/v1',
logLevel: 'debug',
validateSsl: false
},
staging: {
apiUrl: 'https://staging.api.sharokey.com/api/v1',
logLevel: 'info'
},
production: {
apiUrl: 'https://api.sharokey.com/api/v1',
logLevel: 'warn',
retries: 5
}
};
const client = new SharokeyClient({
token: process.env.SHAROKEY_TOKEN,
...configs[process.env.NODE_ENV || 'development']
});Logging personnalisé
// La librairie log automatiquement selon le niveau configuré
// debug: Requêtes détaillées
// info: Opérations importantes
// warn: Problèmes non critiques
// error: Erreurs critiques
const client = new SharokeyClient({
token: 'test',
logLevel: 'debug' // Voir toutes les requêtes HTTP
});💬 Support
Documentation technique
- API REST : https://api.sharokey.com/docs
- CLI : Documentation du CLI Sharokey
- Outlook : Guide du complément Outlook
Ressources
- GitHub : https://github.com/sharokey/sharokey-js
- NPM : https://www.npmjs.com/package/sharokey-js
- Changelog : Historique des versions
Contact
- Support technique : [email protected]
- Bugs et features : Issues GitHub
- Documentation : [email protected]
FAQ
Q: La librairie fonctionne-t-elle dans les navigateurs ?
R: Oui, elle fonctionne dans tous les navigateurs modernes supportant l'API Web Crypto (Chrome 37+, Firefox 34+, Safari 7+).
Q: Puis-je utiliser des tokens d'entreprise ?
R: Oui, tous les types de tokens API Sharokey sont supportés (utilisateur et entreprise).
Q: Les secrets sont-ils vraiment chiffrés côté client ?
R: Oui, le chiffrement AES-GCM-256 est effectué entièrement côté client. Le serveur ne reçoit que les données chiffrées.
Q: Quelle est la taille maximum des fichiers ?
R: 10MB total pour tous les fichiers combinés, 10 fichiers maximum par secret.
Q: La librairie supporte-t-elle TypeScript ?
R: Oui, les définitions TypeScript sont incluses dans le package.
Documentation générée le 08/01/2025 - Équipe Sharokey
