Bundle
Salin prompt setup yang berisi langkah install dan panduan markdown lengkap untuk plugin ini.
Bundle adalah paket update utama di Capgo. Setiap bundle berisi aset web (HTML, CSS, JS) yang membentuk konten aplikasi Anda. API Bundles memungkinkan Anda mengelola paket update ini, termasuk melihat daftar dan menghapusnya.
Memahami Bundle
Bagian berjudul “Memahami Bundle”Sebuah bundle merepresentasikan versi spesifik dari konten web aplikasi Anda dan mencakup:
- Bundle (versi): Nomor versi semantik untuk bundle tersebut
- Checksum: Hash unik untuk verifikasi integritas bundle
- Info Penyimpanan: Detail mengenai lokasi dan cara bundle disimpan
- Persyaratan Native: Syarat minimum versi aplikasi native
- Metadata: Waktu pembuatan, kepemilikan, dan info pelacakan lainnya
Membuat Bundle Secara Manual (Tanpa CLI)
Bagian berjudul “Pembuatan Bundle Manual (Tanpa CLI)”Berikut cara membuat dan upload bundle secara manual tanpa menggunakan Capgo CLI:
Langkah 1: Build Aplikasi Anda
Bagian berjudul “Langkah 1: Build Aplikasi Anda”Pertama, build web assets aplikasi Anda:
npm run buildLangkah 2: Buat Bundle Zip Menggunakan Package yang Sama dengan Capgo CLI
Bagian berjudul “Langkah 2: Buat Bundle Zip Menggunakan Package yang Sama dengan Capgo CLI”Penting: Gunakan package JavaScript yang persis sama dengan yang digunakan Capgo CLI secara internal untuk memastikan kompatibilitas.
Install package yang dibutuhkan
Bagian berjudul “Install package yang dibutuhkan”npm install adm-zip @tomasklaen/checksumBuat Zip Bundle dengan JavaScript (Sama dengan Capgo CLI)
Bagian berjudul “Buat Zip Bundle dengan JavaScript (Sama dengan Capgo CLI)”Catatan: Dalam contoh di bawah ini, version merujuk pada nama bundle (versi) yang digunakan oleh 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();Langkah 3: Hitung Checksum SHA256 Menggunakan Package yang Sama dengan CLI
Bagian berjudul “Langkah 3: Hitung SHA256 Checksum Menggunakan Package yang Sama dengan 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();Langkah 4: Upload Bundle ke Storage Anda
Bagian berjudul “Langkah 4: Upload Bundle ke Storage Anda”Unggah file zip Anda ke penyimpanan web apa pun:
# 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"Penting: Bundle Anda harus dapat diakses secara publik melalui URL HTTPS (tanpa autentikasi). Server Capgo perlu mengunduh bundle dari URL ini.
Contoh URL publik yang valid:
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
Langkah 5: Daftarkan Bundle ke Capgo API
Bagian berjudul “Langkah 5: Daftarkan Bundle ke Capgo API”Daftarkan bundle eksternal ke Capgo menggunakan panggilan API langsung:
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;}Parameter API
Bagian berjudul “Parameter API”| Parameter | Deskripsi | Wajib |
|---|---|---|
app_id | Identifier aplikasi Anda | Ya |
version | Bundle (versi) versi semantik (misalnya, “1.2.3”) | Ya |
external_url | Dapat diakses publik URL HTTPS untuk download bundle (tanpa auth) | Ya |
checksum | Checksum SHA256 dari file zip | Ya |
Persyaratan Struktur Bundle
Bagian berjudul “Persyaratan Struktur Bundle”Zip bundle Anda harus memenuhi persyaratan berikut:
- File Index Root: Wajib memiliki
index.htmldi level root - Integrasi Capacitor: Wajib memanggil
notifyAppReady()di app Anda code - Path Aset: Gunakan path relatif untuk semua aset
Struktur Bundle yang Valid
Bagian berjudul “Valid Bundle Structure”bundle.zip├── index.html├── assets/│ ├── app.js│ └── styles.css└── images/Contoh Workflow Manual Lengkap
Bagian berjudul “Complete Manual Workflow Example”Script Node.js sederhana untuk zip, checksum, dan upload ke 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);Instal dependensi:
npm install adm-zip @tomasklaen/checksum node-fetchVerifikasi Checksum
Bagian berjudul “Verifikasi Checksum”Perhitungan Checksum JavaScript (Sama dengan Capgo CLI)
Bagian berjudul “Perhitungan Checksum JavaScript (Sama dengan Capgo CLI)”Gunakan package dan method yang sama persis seperti yang dipakai Capgo CLI secara internal:
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();Pentingnya Checksum
Bagian berjudul “Pentingnya Checksum”- Integritas Bundle: Memastikan bundle tidak rusak selama transfer
- Verifikasi API: Capgo memverifikasi checksum sebelum menerima bundle
- Verifikasi Plugin: Plugin mobile memverifikasi checksum sebelum menerapkan update
Praktik Terbaik
Bagian berjudul “Praktik Terbaik”- Manajemen Bundle (versi): Gunakan semantic versioning secara konsisten
- Optimasi Penyimpanan: Hapus bundle yang tidak terpakai secara berkala
- Kompatibilitas Bundle (versi): Atur persyaratan versi native minimum yang sesuai
- Strategi Backup: Simpan backup bundle penting (versi)
Endpoint
Bagian berjudul “Endpoints”https://api.capgo.app/bundle/
Ambil informasi bundle. Tanpa filter, mengembalikan 50 bundle per halaman. Dengan version atau id, mengembalikan bentuk array JSON yang sama dengan nol atau satu bundle.
Parameter Query
Bagian berjudul “Parameter Query”app_id: Wajib. ID aplikasi Andapage: Opsional. Nomor halaman untuk paginasi (diabaikan saatversionatauidtelah diatur)version: Opsional. Nama versi bundle yang tepat ("app_versions.name, contohnya1.2.3). Mengembalikan array JSON dengan nol atau satu item.id: Opsional. ID bundle numerik ("app_versions.id). Mengembalikan array JSON dengan nol atau satu item.
Gunakan yang sama authorization header dan kunci API untuk pembatasan scope aplikasi seperti pada daftar paginasi. Nilai yang ditolak oleh validasi query-schema akan mengembalikan invalid_query error.
Cek apakah versi tersedia (CI)
Bagian berjudul “Cek apakah versi tersedia (CI)”Gunakan ini sebelum upload atau penugasan channel jika Anda memerlukan pengecekan HTTP alih-alih CLI:
curl -H "authorization: YOUR_API_KEY" \ "https://api.capgo.app/bundle/?app_id=com.example.app&version=1.2.3"Array JSON yang tidak kosong berarti versi tersebut sudah ada untuk aplikasi ini. Array kosong berarti belum ada.
Untuk workflow upload, flag Capgo CLI bundle upload --version-exists-ok sudah berhasil dieksekusi jika versi target sudah ada, sehingga banyak job CI tidak perlu memanggil endpoint ini.
Tipe Respons
Bagian berjudul “Tipe Respons”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}Contoh Request
Bagian berjudul “Contoh Request”# 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"Contoh Response
Bagian berjudul “Contoh Response”[ { "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/
Hapus satu atau semua bundle untuk sebuah app. Gunakan dengan hati-hati karena tindakan ini tidak bisa dibatalkan.
Parameter Query
Bagian berjudul “Parameter Query”Untuk menghapus bundle tertentu:
interface BundleDelete { app_id: string version: string}Untuk menghapus semua bundle:
interface BundleDeleteAll { app_id: string}Contoh Request
Bagian berjudul “Contoh Request”# 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/Respons Sukses
Bagian berjudul “Respons Sukses”{ "status": "ok"}https://api.capgo.app/bundle/
Buat bundle baru dengan URL eksternal.
Body Request
Bagian berjudul “Request Body”interface CreateBundleBody { app_id: string version: string external_url: string // Must be publicly accessible HTTPS URL checksum: string}Contoh Request
Bagian berjudul “Contoh Request”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/Respons Sukses
Bagian berjudul “Respons Sukses”{ "status": "ok"}POST (Metadata)
Bagian berjudul “POST (Metadata)”https://api.capgo.app/bundle/metadata
Perbarui metadata bundle seperti informasi link dan komentar.
Body Request
Bagian berjudul “Request Body”interface UpdateMetadataBody { app_id: string version_id: number // bundle (version) id link?: string comment?: string}Contoh Request
Bagian berjudul “Contoh Request”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/metadataRespons Sukses
Bagian berjudul “Respons Sukses”{ "status": "success"}https://api.capgo.app/bundle/
Atur bundle ke channel tertentu. Ini menghubungkan bundle (versi) ke channel untuk distribusi.
Body Request
Bagian berjudul “Request Body”interface SetChannelBody { app_id: string version_id: number // bundle (version) id channel_id: number target?: "auto" | "stable" | "rollout" // default: auto}target mengontrol ke mana bundle di-link saat channel dikonfigurasi dengan progressive rollout:
auto— target rollout saat progressive rollout dikonfigurasi; jika tidak, stable (default).rollout— selalu set target rollout; fallback stable tidak berubah.stable— ganti fallback stable (escape hatch).
Contoh Request
Bagian berjudul “Contoh Request”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/Respons Sukses
Bagian berjudul “Respons Sukses”{ "status": "success", "message": "Bundle 1.0.0 set to channel production"}Penanganan error
Bagian berjudul “Error Handling”Semua error menggunakan format error standar yang dijelaskan di Ikhtisar API.
Skenario error umum dan responsnya:
// 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": {}}Kasus Penggunaan Umum
Bagian berjudul “Kasus Penggunaan Umum”- Bersihkan Bundle Lama (Versi)
// Delete outdated beta bundles (versions){ "app_id": "app_123", "version": "1.0.0-beta.1"}- Reset Aplikasi
// Remove all bundles to start fresh{ "app_id": "app_123"}Pertimbangan Storage
Bagian berjudul “Pertimbangan Penyimpanan”- Kebijakan Retensi: Tentukan berapa lama bundle lama disimpan
- Manajemen Ukuran: Pantau ukuran bundle dan penggunaan storage
- Strategi Backup: Pertimbangkan backup bundle penting (versi)
- Optimasi Biaya: Hapus bundle yang tidak perlu untuk optimasi biaya storage
Lanjut dari Bundles
Bagian berjudul “Lanjutkan dari Bundles”Jika Anda menggunakan Bundle untuk merencanakan penyimpanan dan penanganan file, hubungkan dengan @capgo/capacitor-data-storage-sqlite untuk detail implementasi di @capgo/capacitor-data-storage-sqlite, Menggunakan @capgo/capacitor-data-storage-sqlite untuk kapabilitas native di Menggunakan @capgo/capacitor-data-storage-sqlite, @capgo/capacitor-file untuk detail implementasi di @capgo/capacitor-file, Menggunakan @capgo/capacitor-file untuk kemampuan native di Menggunakan @capgo/capacitor-file, dan @capgo/capacitor-uploader untuk detail implementasi di @capgo/capacitor-uploader.