Bundle
Copia un prompt di configurazione con i passaggi di installazione e la guida markdown completa per questo plugin.
I bundle sono i pacchetti di aggiornamento principali in Capgo. Ogni bundle contiene gli asset web (HTML, CSS, JS) che compongono il contenuto della tua app. La API Bundles ti permette di gestire questi pacchetti di aggiornamento, inclusi elenco ed eliminazione.
Capire i bundle
Sezione intitolata “Capire i bundle”Un bundle rappresenta una specifica versione del contenuto web della tua app e include:
- Bundle (versione): Numero di versione semantica per il bundle
- Checksum: Hash univoco per verificare l'integrità del bundle
- Info Storage: Dettagli su dove e come viene salvato il bundle
- Requisiti Native: Requisiti minimi della versione dell'app native
- Metadati: Timestamp di creazione, proprietario e altre info di tracciamento
Creazione manuale del bundle (senza CLI)
Sezione intitolata “Creazione manuale del bundle (Senza CLI)”Ecco come creare e caricare i bundle manualmente senza usare Capgo CLI:
Passaggio 1: Build della tua app
Sezione intitolata “Passaggio 1: Build della tua App”Per prima cosa, builda gli asset web della tua app:
npm run buildPassaggio 2: Crea lo zip del bundle usando gli stessi pacchetti di Capgo CLI
Sezione intitolata “Passaggio 2: Crea il bundle zip usando gli stessi pacchetti di Capgo CLI”Importante: Usa gli stessi identici pacchetti JavaScript che Capgo CLI usa internamente per garantire la compatibilità.
Installa i pacchetti richiesti
Sezione intitolata “Installa i pacchetti richiesti”npm install adm-zip @tomasklaen/checksumCrea un bundle Zip con JavaScript (come Capgo CLI)
Sezione intitolata “Crea un bundle Zip con JavaScript (come Capgo CLI)”Nota: negli esempi seguenti, version si riferisce al nome del bundle (versione) usato da 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 CLIfunction 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 };}
// Usageasync 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();Passaggio 3: Calcola il checksum SHA256 usando lo stesso pacchetto di CLI
Sezione intitolata “Passaggio 3: Calcola il checksum SHA256 usando lo stesso pacchetto di 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;}
// Usageasync function main() { const checksum = await calculateChecksum('./my-app-1.2.3.zip'); console.log('Checksum:', checksum);}
main();Passaggio 4: Upload del bundle sul tuo storage
Sezione intitolata “Passaggio 4: Carica il bundle sul tuo storage”Carica il tuo file zip su uno storage accessibile via web:
# Example: Upload to your server via scpscp my-app-1.2.3.zip user@your-server.com:/var/www/bundles/
# Example: Upload to S3 using AWS CLIaws s3 cp my-app-1.2.3.zip s3://your-bucket/bundles/
# Example: Upload via curl to a custom endpointcurl -X POST https://your-storage-api.com/upload \ -H "Authorization: Bearer YOUR_TOKEN" \ -F "file=@my-app-1.2.3.zip"Importante: Il tuo bundle deve essere accessibile pubblicamente tramite un URL HTTPS (senza autenticazione). I server di Capgo devono scaricare il bundle da questo URL.
Esempi di URL pubblici validi:
https://your-storage.com/bundles/my-app-1.2.3.ziphttps://github.com/username/repo/releases/download/v1.2.3/bundle.ziphttps://cdn.jsdelivr.net/gh/username/repo@v1.2.3/dist.zip
Passaggio 5: Registra il bundle con Capgo API
Sezione intitolata “Passaggio 5: Registra il bundle con Capgo API”Registra il bundle esterno con Capgo tramite chiamate API dirette:
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;}Parametri API
Sezione intitolata “Parametri API”| Parametro | Descrizione | Obbligatorio |
|---|---|---|
app_id | L'identifier della tua app | Sì |
version | Bundle (versione) versione semantica (es. “1.2.3”) | Sì |
external_url | Accessibile pubblicamente URL HTTPS per il download del bundle (senza auth) | Sì |
checksum | Checksum SHA256 del file zip | Sì |
Requisiti della struttura del bundle
Sezione intitolata “Requisiti della struttura del bundle”Il tuo bundle zip deve rispettare questi requisiti:
- File index nella root: Deve avere
index.htmlal livello root - Integrazione Capacitor: Deve chiamare
notifyAppReady()nella tua app code - Asset Paths: Usa percorsi relativi per tutti gli asset
Struttura del bundle valida
Sezione intitolata “Struttura Bundle Valida”bundle.zip├── index.html├── assets/│ ├── app.js│ └── styles.css└── images/Esempio di workflow manuale completo
Sezione intitolata “Esempio Workflow Manuale Completo”Script Node.js semplice per zip, checksum e upload su 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);Installa le dipendenze:
npm install adm-zip @tomasklaen/checksum node-fetchVerifica del checksum
Sezione intitolata “Verifica del Checksum”Calcolo del checksum JavaScript (come Capgo CLI)
Sezione intitolata “Calcolo Checksum JavaScript (uguale a Capgo CLI)”Usa lo stesso identico pacchetto e metodo che Capgo CLI usa internamente:
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 matchesasync 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;}
// Usageasync function main() { const bundleChecksum = await calculateChecksum('./my-app-1.2.3.zip'); console.log('SHA256 Checksum:', bundleChecksum);}
main();Importanza del Checksum
Sezione intitolata “Importanza del Checksum”- Integrità del Bundle: Garantisce che il bundle non sia stato corrotto durante il trasferimento
- Verifica API: Capgo verifica i checksum prima di accettare i bundle
- Verifica del Plugin: Il plugin mobile verifica i checksum prima di applicare gli update
Best practice
Sezione “Best practice”- Gestione Bundle (versione): Usa versionamento semantico in modo costante
- Ottimizzazione dello Storage: Rimuovi periodicamente i bundle non utilizzati
- Compatibilità Bundle (versione): Imposta i requisiti minimi della versione native
- Strategia di Backup: Mantieni backup dei bundle critici (versioni)
Endpoint
Sezione intitolata “Endpoints”https://api.capgo.app/bundle/
Recupera le informazioni sul bundle. Senza filtri, restituisce 50 bundle per pagina. Con version o id, restituisce lo stesso array JSON con zero o un bundle.
Parametri di query
Sezione intitolata “Parametri di query”app_id: Obbligatorio. L'ID della tua apppage: Opzionale. Numero di pagina per la paginazione (ignorato quandoversionoidè impostato)version: Opzionale. Nome esatto della versione del bundle ("app_versions.name, ad esempio1.2.3). Restituisce un array JSON con zero o un elemento.id: Opzionale. ID numerico del bundle ("app_versions.id). Restituisce un array JSON con zero o un elemento.
Usa lo stesso authorization header e API per lo scoping dell'app come lista paginata. I valori rifiutati dalla validazione dello schema di query restituiscono un invalid_query errore.
Verifica se esiste una versione (CI)
Sezione intitolata “Verifica se esiste una versione (CI)”Usa questo endpoint prima dell'upload o dell'assegnazione del canale se ti serve un controllo HTTP invece di CLI:
curl -H "authorization: YOUR_API_KEY" \ "https://api.capgo.app/bundle/?app_id=com.example.app&version=1.2.3"Un array JSON non vuoto indica che la versione esiste già per l'app. Un array vuoto indica che non esiste.
Per i workflow di upload, il flag Capgo CLI bundle upload --version-exists-ok risulta già di successo se la versione target esiste, coprendo molti job CI senza chiamare questo endpoint.
Tipo di risposta
Sezione intitolata “Tipo di risposta”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}Esempio di richiesta
Sezione intitolata “Esempio di richiesta”# Get all bundlescurl -H "authorization: your-api-key" \ "https://api.capgo.app/bundle/?app_id=app_123"
# Get next pagecurl -H "authorization: your-api-key" \ "https://api.capgo.app/bundle/?app_id=app_123&page=1"
# Look up one bundle by version namecurl -H "authorization: your-api-key" \ "https://api.capgo.app/bundle/?app_id=app_123&version=1.0.0"
# Look up one bundle by idcurl -H "authorization: your-api-key" \ "https://api.capgo.app/bundle/?app_id=app_123&id=456"Risposta di esempio
Sezione intitolata “Risposta di esempio”[ { "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" }]ELIMINA
Sezione intitolata “DELETE”https://api.capgo.app/bundle/
Elimina uno o tutti i bundle di un'app. Usa questa funzione con cautela: l'azione non è reversibile.
Parametri di query
Sezione intitolata “Parametri di query”Per eliminare un bundle specifico:
interface BundleDelete { app_id: string version: string}Per eliminare tutti i bundle:
interface BundleDeleteAll { app_id: string}Esempi di richieste
Sezione intitolata “Esempi di richieste”# Delete specific bundlecurl -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 bundlescurl -X DELETE \ -H "authorization: your-api-key" \ -H "Content-Type: application/json" \ -d '{ "app_id": "app_123" }' \ https://api.capgo.app/bundle/Risposta di successo
Sezione intitolata “Risposta di successo”{ "status": "ok"}https://api.capgo.app/bundle/
Crea un nuovo bundle con URL esterno.
Corpo della richiesta
Sezione intitolata “Request Body”interface CreateBundleBody { app_id: string version: string external_url: string // Must be publicly accessible HTTPS URL checksum: string}Esempio di richiesta
Sezione intitolata “Esempio di richiesta”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/Risposta di successo
Sezione intitolata “Risposta di successo”{ "status": "ok"}POST (Metadati)
Sezione intitolata “POST (Metadata)”https://api.capgo.app/bundle/metadata
Aggiorna i metadati del bundle, come il link e le informazioni sul commento.
Corpo della richiesta
Sezione intitolata “Request Body”interface UpdateMetadataBody { app_id: string version_id: number // bundle (version) id link?: string comment?: string}Esempio di richiesta
Sezione intitolata “Esempio di richiesta”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/metadataRisposta di successo
Sezione intitolata “Risposta di successo”{ "status": "success"}https://api.capgo.app/bundle/
Assegna un bundle a un canale specifico. Questo collega un bundle (versione) a un canale per la distribuzione.
Corpo della richiesta
Sezione intitolata “Request Body”interface SetChannelBody { app_id: string version_id: number // bundle (version) id channel_id: number target?: "auto" | "stable" | "rollout" // default: auto}target determina dove viene collegato il bundle quando il canale ha un progressive rollout configurato:
auto— il target del rollout se il progressive rollout è configurato; altrimenti stable (default).rollout— imposta sempre il target del rollout; il fallback stable rimane invariato.stable— sostituisce il fallback stable (escape hatch).
Esempio di richiesta
Sezione intitolata “Esempio di richiesta”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/Risposta di successo
Sezione intitolata “Risposta di successo”{ "status": "success", "message": "Bundle 1.0.0 set to channel production"}Gestione degli errori
Sezione: “Gestione degli errori”Tutti gli errori seguono il formato standard descritto nella panoramica di API.
Scenari di errore comuni e relative risposte:
// 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": {}}Casi d'uso comuni
Sezione intitolata “Casi d'uso comuni”- Pulizia vecchi Bundle (Versioni)
// Delete outdated beta bundles (versions){ "app_id": "app_123", "version": "1.0.0-beta.1"}- Reset App
// Remove all bundles to start fresh{ "app_id": "app_123"}Considerazioni sullo storage
Sezione intitolata “Considerazioni sullo storage”- Policy di Retention: Definisci per quanto tempo conservare i vecchi bundle
- Gestione Dimensioni: Monitora le dimensioni dei bundle e l'uso dello storage
- Strategia di Backup: Valuta il backup dei bundle critici (versioni)
- Ottimizzazione Costi: Rimuovi i bundle non necessari per ottimizzare i costi di storage
Continua da Bundles
Sezione intitolata “Continua da Bundles”Se stai usando Bundle per pianificare lo storage e la gestione dei file, collegalo a @capgo/capacitor-data-storage-sqlite per i dettagli di implementazione in @capgo/capacitor-data-storage-sqlite, Utilizzo di @capgo/capacitor-data-storage-sqlite per la funzionalità nativa in Utilizzo di @capgo/capacitor-data-storage-sqlite, @capgo/capacitor-file per i dettagli di implementazione in @capgo/capacitor-file, Utilizzo di @capgo/capacitor-file per la funzionalità nativa in Usare @capgo/capacitor-file, e @capgo/capacitor-uploader per i dettagli implementativi in @capgo/capacitor-uploader.