Introduction
Le SDK @cloudforge/sdk est le client officiel TypeScript pour CloudForge. Il couvre l'intégralité de l'API REST et fournit des helpers typés pour l'authentification, les projets, les déploiements, l'IA, les domaines et la gestion des tokens CLI.
TypeScript natif
Strict types
Edge-compatible
Web Crypto
Auto refresh
Rotation 30j
MFA TOTP
RFC 6238
Installation
# npm npm install @cloudforge/sdk # pnpm pnpm add @cloudforge/sdk # yarn yarn add @cloudforge/sdk
Démarrage rapide
Authentification par Personal Access Token (recommandé pour scripts, CI/CD, backend) :
import { CloudForge } from '@cloudforge/sdk';
const cf = new CloudForge({
baseUrl: 'https://cloudforge-ai.pages.dev',
apiToken: process.env.CLOUDFORGE_TOKEN!, // cfp_xxx
});
// Lister les projets
const { projects } = await cf.projects.list({ limit: 10 });
// Créer un projet
const project = await cf.projects.create({
name: 'Mon API',
type: 'api',
framework: 'express',
});
// Déclencher un déploiement
const deploy = await cf.deploy.trigger({ projectId: project.id });
console.log('Deployment ID:', deploy.deploymentId);Authentification
Pour les flux interactifs (scripts E2E, tests) — login/mot de passe avec cookies HttpOnly :
const cf = new CloudForge({ baseUrl: 'https://cloudforge-ai.pages.dev' });
await cf.auth.login({
email: 'user@example.com',
password: 'secret',
});
// Le token est automatiquement stocké dans le client
// Le refresh token est géré automatiquement
const me = await cf.me();
console.log(`Connecté en tant que ${me?.email}`);Authentification MFA TOTP
Si MFA est activé sur le compte, la première invocation de login() sans code TOTP lève une erreur avec code = 'MFA_REQUIRED'.
try {
await cf.auth.login({ email, password });
} catch (e: any) {
if (e.code === 'MFA_REQUIRED') {
const code = await promptUser('Code TOTP:');
await cf.auth.login({ email, password, mfaCode: code });
}
}
// Activer le MFA sur un compte existant
const setup = await cf.auth.mfaSetup();
console.log('Scannez ce QR:', setup.otpauth);
const result = await cf.auth.mfaVerify(userCode);
console.log('Backup codes:', result.backupCodes);Refresh tokens automatiques
Le SDK gère automatiquement le cycle de vie des tokens. Si une requête renvoie 401 (token expiré), le SDK appelle /api/auth/refresh en arrière-plan et rejoue la requête originale.
const cf = new CloudForge({
baseUrl,
token: accessToken,
refreshToken,
onTokensRefreshed: ({ token, refreshToken }) => {
// Persister les nouveaux tokens
saveToKeychain({ token, refreshToken });
},
});Projets, fichiers, versions
// CRUD projets
const project = await cf.projects.create({ name: 'API', type: 'api' });
const detail = await cf.projects.get(project.id);
await cf.projects.update(project.id, { description: '...' });
await cf.projects.delete(project.id);
// Fichiers
await cf.projects.upsertFile(project.id, {
path: '/src/index.ts',
content: 'console.log("hello")',
language: 'typescript',
});
// Versions (snapshots)
await cf.projects.saveVersion(project.id, 'v1.0', 'Initial release');
await cf.projects.restoreVersion(project.id, versionId);Déploiement
const trigger = await cf.deploy.trigger({ projectId });
// Polling du statut
while (true) {
const { deployment } = await cf.deploy.get(trigger.deploymentId);
if (deployment.status === 'live') {
console.log('URL:', deployment.url);
break;
}
if (deployment.status === 'failed') throw new Error('deploy failed');
await new Promise(r => setTimeout(r, 3000));
}Gestion d'erreurs
import { CloudForgeError, isCloudForgeError } from '@cloudforge/sdk';
try {
await cf.projects.get('invalid-id');
} catch (e) {
if (isCloudForgeError(e)) {
console.error('Status:', e.status); // 404
console.error('Code:', e.code); // 'PROJECT_NOT_FOUND'
console.error('Message:', e.message); // 'Projet introuvable'
}
}UNAUTHORIZEDToken manquant ou invalide
MFA_REQUIREDMFA activé, code TOTP requis
MFA_INVALIDCode TOTP ou backup code invalide
RATE_LIMITEDLimite de débit dépassée
DOMAIN_UNAVAILABLEDomaine déjà enregistré