feat: add branch support, sync resolution, and dynamic cache TTL

- Add branch detection in parseRemoteIOR for GitHub and Gitea
- Support fetching from branches in addition to tags
- Implement synchronous remote resolution using sync-fetch
- Add dynamic cache TTL based on version type (beta/rc/branch/stable)
- Export sync functions for Metro bundler usage
- Fix remote component resolution in Metro (no more sync errors)
This commit is contained in:
Chris Daßler
2025-09-29 12:32:41 +02:00
parent bb44c5c17c
commit 6e775258d1
3 changed files with 248 additions and 30 deletions

View File

@@ -31,14 +31,23 @@ function parseRemoteIOR(ior) {
// ior:github:owner/repo:componentname@version
const [, , repoPath, componentAndVersion] = parts;
const [owner, repo] = repoPath.split('/');
const [componentName, version] = componentAndVersion.split('@');
const [componentName, versionOrBranch] = componentAndVersion.split('@');
// Detect if it's a branch
const isBranch = versionOrBranch && (
versionOrBranch.includes('/') ||
versionOrBranch.startsWith('main') ||
versionOrBranch.startsWith('master') ||
versionOrBranch.startsWith('dev')
);
return {
type: 'github',
owner,
repository: repo,
componentName,
version,
version: !isBranch ? versionOrBranch : undefined,
branch: isBranch ? versionOrBranch : undefined,
};
}
@@ -46,24 +55,33 @@ function parseRemoteIOR(ior) {
// Two possible formats:
// ior:gitea:instance.com:owner/repo:componentname@version (5 parts)
// ior:gitea:instance.com:owner/repo/componentname@version (4 parts - component name in path)
if (parts.length === 4) {
// Format: ior:gitea:instance.com:owner/repo/componentname@version
const [, , instance, pathAndVersion] = parts;
const [fullPath, version] = pathAndVersion.split('@');
const [fullPath, versionOrBranch] = pathAndVersion.split('@');
const pathParts = fullPath.split('/');
const owner = pathParts[0];
const componentName = pathParts[pathParts.length - 1];
const repository = pathParts.slice(1).join('/') || componentName;
// Detect if it's a branch
const isBranch = versionOrBranch && (
versionOrBranch.includes('/') ||
versionOrBranch.startsWith('main') ||
versionOrBranch.startsWith('master') ||
versionOrBranch.startsWith('dev')
);
return {
type: 'gitea',
instance,
owner,
repository,
componentName,
version,
version: !isBranch ? versionOrBranch : undefined,
branch: isBranch ? versionOrBranch : undefined,
};
} else if (parts.length === 5) {
// Format: ior:gitea:instance.com:owner/repo:componentname@version
@@ -71,18 +89,27 @@ function parseRemoteIOR(ior) {
const repoPathParts = repoPath.split('/');
const owner = repoPathParts[0];
const repository = repoPathParts.slice(1).join('/');
const [componentName, version] = componentAndVersion.split('@');
const [componentName, versionOrBranch] = componentAndVersion.split('@');
// Detect if it's a branch
const isBranch = versionOrBranch && (
versionOrBranch.includes('/') ||
versionOrBranch.startsWith('main') ||
versionOrBranch.startsWith('master') ||
versionOrBranch.startsWith('dev')
);
return {
type: 'gitea',
instance,
owner,
repository,
componentName,
version,
version: !isBranch ? versionOrBranch : undefined,
branch: isBranch ? versionOrBranch : undefined,
};
}
return null;
}
@@ -199,15 +226,29 @@ async function fetchUrlBuffer(url) {
* Fetch component archive from GitHub
*/
async function fetchFromGitHub(config) {
const { owner, repository, componentName, version } = config;
// Try both tag formats: "1.0.0" and "v1.0.0"
const { owner, repository, componentName, version, branch } = config;
// If it's a branch, fetch from branch
if (branch) {
const archiveUrl = `https://api.github.com/repos/${owner}/${repository}/tarball/${branch}`;
try {
console.log(`[IOR Resolver] Fetching GitHub branch: ${branch}`);
const archiveBuffer = await fetchUrlBuffer(archiveUrl);
console.log(`[IOR Resolver] Downloaded archive from GitHub branch ${branch} (${archiveBuffer.length} bytes)`);
return { archive: archiveBuffer, componentName };
} catch (err) {
throw new Error(`Failed to fetch branch ${branch} from GitHub: ${owner}/${repository} - ${err.message}`);
}
}
// Otherwise, try tag formats: "1.0.0" and "v1.0.0"
const tagVariants = [version, `v${version}`];
for (const tag of tagVariants) {
// GitHub API endpoint for tarball
const archiveUrl = `https://api.github.com/repos/${owner}/${repository}/tarball/${tag}`;
try {
console.log(`[IOR Resolver] Fetching GitHub archive: ${archiveUrl}`);
const archiveBuffer = await fetchUrlBuffer(archiveUrl);
@@ -218,7 +259,7 @@ async function fetchFromGitHub(config) {
// Try next tag variant
}
}
throw new Error(`Failed to fetch component from GitHub: ${owner}/${repository}@${version} (tried tags: ${tagVariants.join(', ')})`);
}
@@ -226,15 +267,29 @@ async function fetchFromGitHub(config) {
* Fetch component archive from Gitea
*/
async function fetchFromGitea(config) {
const { instance, owner, repository, componentName, version } = config;
// Try both tag formats: "1.0.0" and "v1.0.0"
const { instance, owner, repository, componentName, version, branch } = config;
// If it's a branch, fetch from branch
if (branch) {
const archiveUrl = `https://${instance}/api/v1/repos/${owner}/${repository}/archive/${branch}.tar.gz`;
try {
console.log(`[IOR Resolver] Fetching Gitea branch: ${branch}`);
const archiveBuffer = await fetchUrlBuffer(archiveUrl);
console.log(`[IOR Resolver] Downloaded archive from Gitea branch ${branch} (${archiveBuffer.length} bytes)`);
return { archive: archiveBuffer, componentName };
} catch (err) {
throw new Error(`Failed to fetch branch ${branch} from Gitea: ${instance}/${owner}/${repository} - ${err.message}`);
}
}
// Otherwise, try tag formats: "1.0.0" and "v1.0.0"
const tagVariants = [version, `v${version}`];
for (const tag of tagVariants) {
// Try to download the archive
const archiveUrl = `https://${instance}/api/v1/repos/${owner}/${repository}/archive/${tag}.tar.gz`;
try {
console.log(`[IOR Resolver] Fetching Gitea archive: ${archiveUrl}`);
const archiveBuffer = await fetchUrlBuffer(archiveUrl);
@@ -245,7 +300,7 @@ async function fetchFromGitea(config) {
// Try next tag variant
}
}
throw new Error(`Failed to fetch component from Gitea: ${instance}/${owner}/${repository}@${version} (tried tags: ${tagVariants.join(', ')})`);
}