Aller au contenu

Les bundles

Les bundles sont les packages de mise à jour centraux de Capgo. Chaque bundle contient les assets web (HTML, CSS, JS) qui constituent le contenu de votre application. L'API des bundles vous permet de gérer ces packages, notamment en les listant ou en les supprimant.

Un bundle représente une version spécifique du contenu web de votre application et comprend :

  • Bundle (version): Numéro de version sémantique pour le bundle
  • Checksum: Hash unique pour vérifier l'intégrité du bundle
  • Infos de stockage: Détails sur l'emplacement et la méthode de stockage du bundle
  • Prérequis natifs: Exigences minimales de version de l'application native
  • Métadonnées: Heure de création, propriétaire et autres infos de suivi

Voici comment créer et envoyer des bundles manuellement sans utiliser le CLI Capgo :

Étape 1 : Compiler votre application

Étape 1 : Compilez votre application

First, build your app’s web assets:

Fenêtre de terminal
npm run build

Étape 2 : Créer le zip du bundle avec les mêmes packages que Capgo CLI

Étape 2 : Créez le zip du bundle avec les mêmes packages que Capgo CLI

Important: Utilisez exactement les mêmes packages JavaScript que Capgo CLI utilise en interne pour garantir la compatibilité.

Fenêtre de terminal
npm install adm-zip @tomasklaen/checksum

Créer un bundle Zip avec JavaScript (identique à Capgo CLI)

Section intitulée « Créer un bundle Zip avec JavaScript (identique à Capgo CLI) »

Note : dans les exemples ci-dessous, version fait référence au nom du bundle (version) utilisé par API.

const fs = require('node:fs');
const path = require('node:path');
const os = require('node:os');
const AdmZip = require('adm-zip');
const { checksum: getChecksum } = require('@tomasklaen/checksum');
// Exact same implementation as Capgo CLI
function zipFileUnix(filePath) {
const zip = new AdmZip();
zip.addLocalFolder(filePath);
return zip.toBuffer();
}
async function zipFileWindows(filePath) {
console.log('Zipping file windows mode');
const zip = new AdmZip();
const addToZip = (folderPath, zipPath) => {
const items = fs.readdirSync(folderPath);
for (const item of items) {
const itemPath = path.join(folderPath, item);
const stats = fs.statSync(itemPath);
if (stats.isFile()) {
const fileContent = fs.readFileSync(itemPath);
zip.addFile(path.join(zipPath, item).split(path.sep).join('/'), fileContent);
} else if (stats.isDirectory()) {
addToZip(itemPath, path.join(zipPath, item));
}
}
};
addToZip(filePath, '');
return zip.toBuffer();
}
// Main zipFile function (exact same logic as CLI)
async function zipFile(filePath) {
if (os.platform() === 'win32') {
return zipFileWindows(filePath);
} else {
return zipFileUnix(filePath);
}
}
async function createBundle(inputPath, outputPath, version) {
// Create zip using exact same method as Capgo CLI
const zipped = await zipFile(inputPath);
// Write to file
fs.writeFileSync(outputPath, zipped);
// Calculate checksum using exact same package as CLI
const checksum = await getChecksum(zipped, 'sha256');
return {
filename: path.basename(outputPath),
version: version,
size: zipped.length,
checksum: checksum
};
}
// Usage
async function main() {
try {
const result = await createBundle('./dist', './my-app-1.2.3.zip', '1.2.3');
console.log('Bundle info:', JSON.stringify(result, null, 2));
} catch (error) {
console.error('Error creating bundle:', error);
}
}
main();

Étape 3 : Calculer le checksum SHA256 avec le même package que CLI

Section intitulée « Étape 3 : Calculer le checksum SHA256 avec le même package que CLI »
const fs = require('node:fs');
const { checksum: getChecksum } = require('@tomasklaen/checksum');
async function calculateChecksum(filePath) {
const fileBuffer = fs.readFileSync(filePath);
// Use exact same package and method as Capgo CLI
const checksum = await getChecksum(fileBuffer, 'sha256');
return checksum;
}
// Usage
async function main() {
const checksum = await calculateChecksum('./my-app-1.2.3.zip');
console.log('Checksum:', checksum);
}
main();

Upload your zip file to any web-accessible storage:

Fenêtre de terminal
# Example: Upload to your server via scp
scp my-app-1.2.3.zip user@your-server.com:/var/www/bundles/
# Example: Upload to S3 using AWS CLI
aws s3 cp my-app-1.2.3.zip s3://your-bucket/bundles/
# Example: Upload via curl to a custom endpoint
curl -X POST https://your-storage-api.com/upload \
-H "Authorization: Bearer YOUR_TOKEN" \
-F "file=@my-app-1.2.3.zip"

Important: votre bundle doit être accessible publiquement via une URL HTTPS (sans authentification). Les serveurs de Capgo doivent pouvoir télécharger le bundle depuis cette URL.

Exemples d'URL publiques valides :

  • https://your-storage.com/bundles/my-app-1.2.3.zip
  • https://github.com/username/repo/releases/download/v1.2.3/bundle.zip
  • https://cdn.jsdelivr.net/gh/username/repo@v1.2.3/dist.zip

Enregistrez le bundle externe auprès de Capgo via des appels API directs :

async function registerWithCapgo(appId, version, bundleUrl, checksum, apiKey) {
const fetch = require('node-fetch');
// Create bundle (version)
const response = await fetch('https://api.capgo.app/bundle/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'authorization': apiKey
},
body: JSON.stringify({
app_id: appId,
version: version,
external_url: bundleUrl,
checksum: checksum
})
});
if (!response.ok) {
throw new Error(`Failed to create bundle: ${response.statusText}`);
}
const data = await response.json();
console.log('Bundle created:', data);
return data;
}
ParamètreDescriptionRequis
app_idL'identifiant de votre applicationOui
versionBundle (version) Version sémantique (ex. : « 1.2.3 »)Oui
external_urlAccessible publiquement URL HTTPS pour télécharger le bundle (sans authentification)Oui
checksumChecksum SHA256 du fichier zipOui

Votre zip de bundle doit respecter ces exigences :

  1. Fichier index à la racine: Doit être présent index.html au niveau racine
  2. Intégration Capacitor: Doit appeler notifyAppReady() dans votre application code
  3. Chemins des assets: Utilisez des chemins relatifs pour tous les assets
bundle.zip
├── index.html
├── assets/
│ ├── app.js
│ └── styles.css
└── images/

Script Node.js simple pour zipper, calculer le checksum et envoyer vers Capgo :

const fs = require('node:fs');
const os = require('node:os');
const AdmZip = require('adm-zip');
const { checksum: getChecksum } = require('@tomasklaen/checksum');
const fetch = require('node-fetch');
async function deployToCapgo() {
const APP_ID = 'com.example.app';
const VERSION = '1.2.3';
const BUNDLE_URL = 'https://your-storage.com/bundles/app-1.2.3.zip';
const API_KEY = process.env.CAPGO_API_KEY;
// 1. Create zip (same as Capgo CLI)
const zip = new AdmZip();
zip.addLocalFolder('./dist');
const zipped = zip.toBuffer();
// 2. Calculate checksum (same as Capgo CLI)
const checksum = await getChecksum(zipped, 'sha256');
console.log('Checksum:', checksum);
// 3. Upload to your storage (replace with your upload logic)
// fs.writeFileSync('./bundle.zip', zipped);
// ... upload bundle.zip to your storage ...
// 4. Register with Capgo API
const response = await fetch('https://api.capgo.app/bundle/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'authorization': API_KEY
},
body: JSON.stringify({
app_id: APP_ID,
version: VERSION,
external_url: BUNDLE_URL,
checksum: checksum
})
});
if (!response.ok) {
throw new Error(`Failed: ${response.statusText}`);
}
console.log('Bundle registered with Capgo!');
}
deployToCapgo().catch(console.error);

Installer les dépendances :

Fenêtre de terminal
npm install adm-zip @tomasklaen/checksum node-fetch

Calcul du checksum JavaScript (identique à Capgo CLI)

Section intitulée « Calcul du checksum JavaScript (identique à Capgo CLI) »

Utilisez exactement le même package et la même méthode que Capgo CLI utilise en interne :

const fs = require('node:fs');
const { checksum: getChecksum } = require('@tomasklaen/checksum');
async function calculateChecksum(filePath) {
const fileBuffer = fs.readFileSync(filePath);
// Use exact same package and method as Capgo CLI
const checksum = await getChecksum(fileBuffer, 'sha256');
return checksum;
}
// Verify checksum matches
async function verifyChecksum(filePath, expectedChecksum) {
const actualChecksum = await calculateChecksum(filePath);
const isValid = actualChecksum === expectedChecksum;
console.log(`File: ${filePath}`);
console.log(`Expected: ${expectedChecksum}`);
console.log(`Actual: ${actualChecksum}`);
console.log(`Valid: ${isValid}`);
return isValid;
}
// Usage
async function main() {
const bundleChecksum = await calculateChecksum('./my-app-1.2.3.zip');
console.log('SHA256 Checksum:', bundleChecksum);
}
main();
  • Intégrité du bundle: Garantit que le bundle n'a pas été corrompu pendant le transfert
  • Vérification API: Capgo vérifie les checksums avant d'accepter les bundles
  • Vérification du plugin: Le plugin mobile vérifie les checksums avant d'appliquer les mises à jour
  1. Gestion des bundles (versions) : Utilisez versionnage sémantique consistently
  2. Optimisation du stockage: Supprimez périodiquement les bundles inutilisés
  3. Compatibilité des bundles (versions): Définissez les exigences minimales de version native appropriées
  4. Stratégie de sauvegarde: Maintenez des sauvegardes de vos bundles critiques (versions)

https://api.capgo.app/bundle/

Récupère les informations du bundle. Sans filtres, retourne 50 bundles par page. Avec version ou id, retourne le même format de tableau JSON avec zéro ou un bundle.

  • app_id: Requis. L'ID de votre application
  • page: Optionnel. Numéro de page pour la pagination (ignoré quand version ou id est définie)
  • version: Optionnel. Nom exact de la version du bundle (app_versions.name, par exemple 1.2.3"). Renvoie un tableau JSON contenant zéro ou un élément.
  • id: Optionnel. ID numérique du bundle (app_versions.id"). Renvoie un tableau JSON contenant zéro ou un élément.

Utilisez le même authorization header et le même scoping d'application via la clé API que la liste paginée. Les valeurs rejetées par la validation du query-schema renvoient une invalid_query erreur.

Utilisez ceci avant l'upload ou l'assignation d'un canal si vous avez besoin d'une vérification HTTP plutôt que du CLI :

Fenêtre de terminal
curl -H "authorization: YOUR_API_KEY" \
"https://api.capgo.app/bundle/?app_id=com.example.app&version=1.2.3"

Un tableau JSON non vide signifie que cette version existe déjà pour l'app. Un tableau vide signifie qu'elle n'existe pas.

Pour les workflows d'upload, le flag Capgo CLI bundle upload --version-exists-ok renvoie déjà un succès si la version cible existe, ce qui évite d'appeler cet endpoint pour de nombreux jobs CI.

interface Bundle {
app_id: string
bucket_id: string | null
checksum: string | null
created_at: string | null
deleted: boolean
external_url: string | null
id: number
minUpdateVersion: string | null
name: string
native_packages: Json[] | null
owner_org: string
r2_path: string | null
session_key: string | null
storage_provider: string
updated_at: string | null
user_id: string | null
}
Fenêtre de terminal
# Get all bundles
curl -H "authorization: your-api-key" \
"https://api.capgo.app/bundle/?app_id=app_123"
# Get next page
curl -H "authorization: your-api-key" \
"https://api.capgo.app/bundle/?app_id=app_123&page=1"
# Look up one bundle by version name
curl -H "authorization: your-api-key" \
"https://api.capgo.app/bundle/?app_id=app_123&version=1.0.0"
# Look up one bundle by id
curl -H "authorization: your-api-key" \
"https://api.capgo.app/bundle/?app_id=app_123&id=456"
[
{
"id": 1,
"app_id": "app_123",
"name": "1.0.0",
"checksum": "abc123...",
"minUpdateVersion": "1.0.0",
"storage_provider": "r2",
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-01T00:00:00Z",
"deleted": false,
"owner_org": "org_123",
"user_id": "user_123"
}
]

https://api.capgo.app/bundle/

Supprimez un ou tous les bundles d'une application. Utilisez cette action avec prudence, car elle est irréversible.

Pour supprimer un bundle spécifique :

interface BundleDelete {
app_id: string
version: string
}

Pour supprimer tous les bundles :

interface BundleDeleteAll {
app_id: string
}
Fenêtre de terminal
# Delete specific bundle
curl -X DELETE \
-H "authorization: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"app_id": "app_123",
"version": "1.0.0"
}' \
https://api.capgo.app/bundle/
# Delete all bundles
curl -X DELETE \
-H "authorization: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"app_id": "app_123"
}' \
https://api.capgo.app/bundle/
{
"status": "ok"
}

https://api.capgo.app/bundle/

Créer un nouveau bundle avec une URL externe.

interface CreateBundleBody {
app_id: string
version: string
external_url: string // Must be publicly accessible HTTPS URL
checksum: string
}
Fenêtre de terminal
curl -X POST \
-H "authorization: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"app_id": "com.example.app",
"version": "1.2.3",
"external_url": "https://your-storage.com/bundles/app-1.2.3.zip",
"checksum": "a1b2c3d4e5f6789abcdef123456789abcdef123456789abcdef123456789abcd"
}' \
https://api.capgo.app/bundle/
{
"status": "ok"
}

https://api.capgo.app/bundle/metadata

Mettre à jour les métadonnées du bundle, comme le lien et les informations de commentaire.

interface UpdateMetadataBody {
app_id: string
version_id: number // bundle (version) id
link?: string
comment?: string
}
Fenêtre de terminal
curl -X POST \
-H "authorization: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"app_id": "app_123",
"version_id": 456,
"link": "https://github.com/myorg/myapp/releases/tag/v1.0.0",
"comment": "Fixed critical bug in authentication"
}' \
https://api.capgo.app/bundle/metadata
{
"status": "success"
}

https://api.capgo.app/bundle/

Assigne un bundle à un canal spécifique. Cela lie un bundle (version) à un canal pour sa distribution.

interface SetChannelBody {
app_id: string
version_id: number // bundle (version) id
channel_id: number
target?: "auto" | "stable" | "rollout" // default: auto
}

target contrôle l'endroit où le bundle est lié lorsque le canal a un déploiement progressif configuré :

  • auto — la cible de déploiement si le déploiement progressif est configuré ; stable sinon (par défaut).
  • rollout — always set the rollout target; stable fallback unchanged.
  • stable — remplace le fallback stable (solution de secours).
Fenêtre de terminal
curl -X PUT \
-H "authorization: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"app_id": "app_123",
"version_id": 456,
"channel_id": 789
}' \
https://api.capgo.app/bundle/
{
"status": "success",
"message": "Bundle 1.0.0 set to channel production"
}

Toutes les erreurs utilisent le format d'erreur standard décrit dans la Aperçu de API.

Scénarios d'erreur courants et leurs réponses :

// app_id is not a reverse-domain identifier
{
"error": "invalid_app_id",
"message": "App ID must be a reverse domain string",
"moreInfo": { "app_id": "my app" }
}
// Deleting a bundle without access to the app
{
"error": "cannot_delete_bundle",
"message": "You can't access this app",
"moreInfo": { "app_id": "com.example.app" }
}
// Deleting a bundle that a channel still uses
{
"error": "cannot_delete_linked_version",
"message": "Cannot delete a bundle linked to a channel",
"moreInfo": { "app_id": "com.example.app", "version": "1.0.0" }
}
// Creating a bundle whose version is not valid semver
{
"error": "invalid_version_format",
"message": "Version must be valid semver format (e.g., 1.0.0, 1.0.0-alpha.1)",
"moreInfo": { "version": "v1" }
}
// Setting a channel to a bundle that does not exist
{
"error": "cannot_find_version",
"message": "Cannot find version",
"moreInfo": {}
}
  1. Nettoyer les anciens bundles (versions)
// Delete outdated beta bundles (versions)
{
"app_id": "app_123",
"version": "1.0.0-beta.1"
}
  1. App Reset
// Remove all bundles to start fresh
{
"app_id": "app_123"
}
  1. Politique de rétention: Define how long to keep old bundles
  2. Gestion de la taille: Monitor bundle sizes and storage usage
  3. Stratégie de sauvegarde: Envisagez de sauvegarder les bundles (versions) critiques
  4. Optimisation des coûts: Supprimez les bundles inutiles pour optimiser vos coûts de stockage

Si vous utilisez Les bundles pour planifier le stockage et la gestion des fichiers, connectez-l’à @capgo/capacitor-data-storage-sqlite pour les détails d'implémentation dans @capgo/capacitor-data-storage-sqlite, Utiliser @capgo/capacitor-data-storage-sqlite pour la capacité native dans Utiliser @capgo/capacitor-data-storage-sqlite @capgo/capacitor-file pour les détails d'implémentation dans @capgo/capacitor-file, Utiliser @capgo/capacitor-file pour la capacité native dans Utiliser @capgo/capacitor-file, et @capgo/capacitor-uploader pour les détails d'implémentation dans @capgo/capacitor-uploader.