Vai al contenuto

Bundles

I Bundles sono i pacchetti di aggiornamento principali in Capgo. Ogni bundle contiene gli asset web (HTML, CSS, JS) che compongono il contenuto della tua app. L’API Bundles ti permette di gestire questi pacchetti di aggiornamento, inclusi elenco ed eliminazione.

Un bundle rappresenta una versione specifica del contenuto web della tua app e include:

  • Version: Numero di versione semantica del bundle
  • Checksum: Hash univoco per verificare l’integrità del bundle
  • Storage Info: Dettagli su dove e come il bundle è archiviato
  • Native Requirements: Requisiti minimi della versione dell’app nativa
  • Metadata: Tempo di creazione, proprietà e altre informazioni di tracciamento

Ecco come creare e caricare bundle manualmente senza utilizzare la CLI di Capgo:

Prima, costruisci gli asset web della tua app:

Terminal window
npm run build

Passo 2: Creare Bundle Zip usando gli stessi pacchetti della CLI di Capgo

Section titled “Passo 2: Creare Bundle Zip usando gli stessi pacchetti della CLI di Capgo”

Importante: Usa esattamente gli stessi pacchetti JavaScript che la CLI di Capgo usa internamente per garantire la compatibilità.

Terminal window
npm install adm-zip @tomasklaen/checksum

Creare Bundle Zip con JavaScript (Come la CLI di Capgo)

Section titled “Creare Bundle Zip con JavaScript (Come la CLI di Capgo)”
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();

Passo 3: Calcolare Checksum SHA256 usando lo stesso pacchetto della CLI

Section titled “Passo 3: Calcolare Checksum SHA256 usando lo stesso pacchetto della 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();

Passo 4: Caricare il Bundle nel tuo Storage

Section titled “Passo 4: Caricare il Bundle nel tuo Storage”

Upload your zip file to any web-accessible storage:

Terminal window
# 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: Your bundle must be publicly accessible via HTTPS URL (no authentication required). Capgo’s servers need to download the bundle from this URL.

Examples of valid public URLs:

  • 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

Passo 5: Registrare il Bundle con l’API di Capgo

Section titled “Passo 5: Registrare il Bundle con l’API di Capgo”

Register the external bundle with Capgo using direct API calls:

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;
}
ParameterDescriptionRequired
app_idYour app identifierYes
versionSemantic version (e.g., “1.2.3”)Yes
external_urlPublicly accessible HTTPS URL where bundle can be downloaded (no auth required)Yes
checksumSHA256 checksum of the zip fileYes

Your bundle zip must follow these requirements:

  1. Root Index File: Must have index.html at the root level
  2. Capacitor Integration: Must call notifyAppReady() in your app code
  3. Asset Paths: Use relative paths for all assets
bundle.zip
├── index.html
├── assets/
│ ├── app.js
│ └── styles.css
└── images/

Esempio Completo di Flusso di Lavoro Manuale

Section titled “Esempio Completo di Flusso di Lavoro Manuale”

Simple Node.js script to zip, checksum, and upload to 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);

Install dependencies:

Terminal window
npm install adm-zip @tomasklaen/checksum node-fetch

Calcolo Checksum JavaScript (Come la CLI di Capgo)

Section titled “Calcolo Checksum JavaScript (Come la CLI di Capgo)”

Use the exact same package and method that Capgo CLI uses internally:

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();
  • Bundle Integrity: Ensures the bundle hasn’t been corrupted during transfer
  • API Verification: Capgo verifies checksums before accepting bundles
  • Plugin Verification: The mobile plugin verifies checksums before applying updates
  1. Version Management: Use semantic versioning consistently
  2. Storage Optimization: Remove unused bundles periodically
  3. Version Compatibility: Set appropriate minimum native version requirements
  4. Backup Strategy: Maintain backups of critical bundle versions

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

Retrieve bundle information. Returns 50 bundles per page.

  • app_id: Required. The ID of your app
  • page: Optional. Page number for pagination
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
}
Terminal window
# 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"
{
"data": [
{
"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/

Delete one or all bundles for an app. Use with caution as this action cannot be undone.

For deleting a specific bundle:

interface BundleDelete {
app_id: string
version: string
}

For deleting all bundles:

interface BundleDeleteAll {
app_id: string
}
Terminal window
# 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/

Create a new bundle with external URL.

interface CreateBundleBody {
app_id: string
version: string
external_url: string // Must be publicly accessible HTTPS URL
checksum: string
}
Terminal window
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

Update bundle metadata such as link and comment information.

interface UpdateMetadataBody {
app_id: string
version_id: number
link?: string
comment?: string
}
Terminal window
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/

Set a bundle to a specific channel. This links a bundle version to a channel for distribution.

interface SetChannelBody {
app_id: string
version_id: number
channel_id: number
}
Terminal window
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"
}

Common error scenarios and their responses:

// Bundle not found
{
"error": "Bundle not found",
"status": "KO"
}
// Invalid version format
{
"error": "Invalid version format",
"status": "KO"
}
// Storage error
{
"error": "Failed to delete bundle from storage",
"status": "KO"
}
// Permission denied
{
"error": "Insufficient permissions to manage bundles",
"status": "KO"
}
  1. Cleanup Old Versions
// Delete outdated beta 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. Retention Policy: Define how long to keep old bundles
  2. Size Management: Monitor bundle sizes and storage usage
  3. Backup Strategy: Consider backing up critical versions
  4. Cost Optimization: Remove unnecessary bundles to optimize storage costs