跳过内容

复制页面选项

Bundles are the core update packages in Capgo. Each bundle contains the web assets (HTML, CSS, JS) that make up your app’s content. The Bundles API allows you to manage these update packages, including listing and deleting them.

包含安装、同步和源码markdown指南。

理解捆绑包

一个捆绑包代表了您的应用程序的特定捆绑包(版本),并包含:

  • 捆绑包(版本): 语义版本号 捆绑包的版本
  • 校验和: 验证捆绑包完整性的唯一哈希
  • 存储信息: 关于捆绑包存储位置和方式的详细信息
  • 原生要求: 最低原生应用程序版本要求
  • 元数据: 创建时间、拥有者和其他跟踪信息

手动创建捆绑包(不使用CLI)

手动创建捆绑包(不使用CLI)

以下是手动创建和上传捆绑包的步骤,使用Capgo CLI:

步骤 1:构建您的应用

步骤 1:构建您的应用

首先,构建您的应用的 Web 资产:

终端窗口
npm run build

步骤 2:使用Capgo CLI内部使用的相同包创建捆绑包 zip

步骤 2:使用Capgo CLI内部使用的相同包创建捆绑包 zip

重要: 使用Capgo CLI内部使用的相同 JavaScript 包来确保兼容性。

终端窗口
npm install adm-zip @tomasklaen/checksum

创建 JavaScript ZIP 包(与 Capgo CLI 相同)

标题:创建 JavaScript ZIP 包(与 Capgo CLI 相同)

注意:以下示例中, version 指的是 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();

步骤 3:使用相同的包计算 SHA256 校验和(CLI)

标题:步骤 3:使用相同的包计算 SHA256 校验和(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();

第 4 步:将包上传到您的存储

步骤 4:将包上传到您的存储

将您的 zip 文件上传到任何可访问的存储:

终端窗口
# 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"

重要您的包必须是 通过 HTTPS URL 公开可访问(无需身份验证)。__CAPGO_KEEP_0__的服务器需要从此 URL 下载包。 通过HTTPS URL(无需身份验证)。Capgo的服务器需要从此URL下载包。

第 5 步:将包注册到__CAPGO_KEEP_0__ __CAPGO_KEEP_1__

  • 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

使用 Capgo 直接调用 API 来注册外部包:

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;
}

API 参数

API 参数
参数描述必填
app_id应用标识符是
version版本 语义版本 (例如,“1.2.3”)是
external_url公开可访问 https url 可以下载包 (无需认证)是
checksumsha256 校验和是

根索引文件

  1. : 必须位于根级别必须位于根级别 index.html 包结构要求
  2. Capacitor 集成: 必须调用 notifyAppReady() 在您的应用程序中 code
  3. 资产路径: 为所有资产使用相对路径

有效的捆绑结构

标题:有效的捆绑结构
bundle.zip
├── index.html
├── assets/
│ ├── app.js
│ └── styles.css
└── images/

上下文:页面/区域:Capgo营销网站。角色:UI标签。见于:页面代理/[slug].astro。消息键`agents_page_copy_label`(代理页面复制标签)。

完整的手动工作流程示例

使用 Node.js 脚本简单地压缩、校验和上传到 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);

安装依赖项:

终端窗口
npm install adm-zip @tomasklaen/checksum node-fetch

页面/区域:Capgo营销网站。角色:UI标签。见于:页面代理/[slug].astro。消息键 `agents_page_copy_label` (代理页面复制标签)。

校验和验证

JavaScript 检查和计算 (与 Capgo CLI 相同)

JavaScript校验和计算(与Capgo CLI相同)

JavaScript校验和计算(与Capgo 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;
}
// 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();

使用与__CAPGO_KEEP_0__ __CAPGO_KEEP_1__内部相同的包和方法:

校验和重要性
  • 校验和重要性部分: 确保传输过程中捆绑包未被损坏
  • API 验证: Capgo 在接受捆绑包之前验证校验和
  • 插件验证: 移动插件在应用更新之前验证校验和

最佳实践

最佳实践
  1. 捆绑包(版本)管理: 使用 语义版本 一致
  2. 存储优化: 移除未使用的捆绑包周期性
  3. 捆绑包 (版本) 兼容性: 设置合适的原生版本要求
  4. 备份策略: 保持关键捆绑包 (版本) 的备份

端点

端点

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

或 version or idcontext

  • app_id: 必填。应用程序的 ID
  • page: 可选。分页时的页码(当设置时忽略) version 或 id 设置为)
  • version: 可选。数字包 ID(例如app_versions.name: 必填。应用程序的 ID 1.2.3: 可选。分页时的页码(当设置时忽略)
  • id: 可选。精确的包版本名称(例如app_versions.id: 可选。分页时的页码(当设置时忽略)

: 可选。数字包 ID(例如 authorization header 和 API key app scoping as the paginated list. Values rejected by query-schema validation return an invalid_query 错误。

检查是否存在版本(CI)

标题:检查是否存在版本(CI)

在上传或频道分配之前使用此项,需要 HTTP 检查而不是 CLI:

终端窗口
curl -H "authorization: YOUR_API_KEY" \
"https://api.capgo.app/bundle/?app_id=com.example.app&version=1.2.3"

context:Capgo营销网站。角色:UI标签。位置:页面 agents/[slug].astro。消息键 `agents_page_copy_label` (Agents Page Copy Label)。

For upload workflows, the Capgo CLI flag bundle upload --version-exists-ok 对于上传工作流程,__CAPGO_KEEP_0__ __CAPGO_KEEP_1__ 标志

已存在目标版本时,__CAPGO_KEEP_0__ __CAPGO_KEEP_1__ 标志

响应类型
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
}

__CAPGO_KEEP_0__

__CAPGO_KEEP_0__
__CAPGO_KEEP_0__
# 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"

__CAPGO_KEEP_0__

__CAPGO_KEEP_0__
[
{
"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/

删除

请谨慎使用,删除后无法恢复。

参数查询

为了删除一个特定的包:

interface BundleDelete {
app_id: string
version: string
}

删除所有捆绑包:

interface BundleDeleteAll {
app_id: string
}

请求示例

终端窗口
Section titled “Success Response”
# 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"
}

POST

POST

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

创建一个带有外部 URL 的新包

请求体

请求体
interface CreateBundleBody {
app_id: string
version: string
external_url: string // Must be publicly accessible HTTPS URL
checksum: string
}

页面上下文: Capgo 营销网站。角色: UI 标签。位置: 页面 agents/[slug].astro。消息键 `agents_page_copy_label` (Agents Page Copy Label)。

示例请求
终端窗口
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"
}

POST (元数据)

POST (元数据)部分

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

更新包元数据,例如链接和评论信息。

interface UpdateMetadataBody {
app_id: string
version_id: number // bundle (version) id
link?: string
comment?: string
}

示例请求

示例请求部分
终端窗口
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"
}

PUT

PUT

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

将包设置为特定频道。该设置将包(版本)与频道关联以进行分发。

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

target 控制包在频道配置了渐进式发布时的链接位置:

  • auto — 当配置了渐进式发布时,使用发布目标;否则使用稳定版本(默认值)。
  • rollout — 始终设置发布目标;稳定版本回退保持不变。
  • stable — 替换稳定版本回退(逃生门)。

示例请求

示例请求
终端窗口
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"
}

错误处理

错误处理

常见错误场景和响应:

// Bundle not found
{
"error": "Bundle not found",
"status": "KO"
}
// Invalid bundle (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. 清理旧版包
// Delete outdated beta bundles (versions)
{
"app_id": "app_123",
"version": "1.0.0-beta.1"
}
  1. 应用重置
// Remove all bundles to start fresh
{
"app_id": "app_123"
}

存储考虑

存储考虑
  1. 保留策略: 定义保留旧版包的时间
  2. 大小管理: 监控包大小和存储使用
  3. 备份策略: 考虑备份关键的包(版本)
  4. 成本优化: 删除不必要的包以优化存储成本

如果您正在使用 包 来规划存储和文件处理,连接它到 @capgo/capacitor-sqlite-数据存储 有关在 @capgo/capacitor-data-storage-sqlite 中的实现细节 使用 @capgo/capacitor-data-storage-sqlite 为 @capgo/capacitor-data-storage-sqlite 中的本机能力 @capgo/capacitor文件 为了 @capgo/capacitor 文件中的实现细节 使用 @capgo/capacitor 文件 为了在使用 @capgo/capacitor 文件时获得本地能力, @capgo/capacitor 上传器 为了 @capgo/capacitor 上传器中的实现细节