* Load and cache a marketplace from its source * * Handles different source types: * - URL: Downloads marketplace.json directly * - GitHub: Clones repo and looks for .claude-plugin/marketplace.json * - Git: Clones repository from git URL * - NPM: (Not yet implemented) Would fetch from npm pack
( source: MarketplaceSource, onProgress?: MarketplaceProgressCallback, )
| 1431 | * @throws If marketplace file not found or validation fails |
| 1432 | */ |
| 1433 | async function loadAndCacheMarketplace( |
| 1434 | source: MarketplaceSource, |
| 1435 | onProgress?: MarketplaceProgressCallback, |
| 1436 | ): Promise<LoadedPluginMarketplace> { |
| 1437 | const fs = getFsImplementation() |
| 1438 | const cacheDir = getMarketplacesCacheDir() |
| 1439 | |
| 1440 | // Ensure cache directory exists |
| 1441 | await fs.mkdir(cacheDir) |
| 1442 | |
| 1443 | let temporaryCachePath: string |
| 1444 | let marketplacePath: string |
| 1445 | let cleanupNeeded = false |
| 1446 | |
| 1447 | // Generate a temp name for the cache path |
| 1448 | const tempName = getCachePathForSource(source) |
| 1449 | |
| 1450 | try { |
| 1451 | switch (source.source) { |
| 1452 | case 'url': { |
| 1453 | // Direct URL to marketplace.json |
| 1454 | temporaryCachePath = join(cacheDir, `${tempName}.json`) |
| 1455 | cleanupNeeded = true |
| 1456 | await cacheMarketplaceFromUrl( |
| 1457 | source.url, |
| 1458 | temporaryCachePath, |
| 1459 | source.headers, |
| 1460 | onProgress, |
| 1461 | ) |
| 1462 | marketplacePath = temporaryCachePath |
| 1463 | break |
| 1464 | } |
| 1465 | |
| 1466 | case 'github': { |
| 1467 | // Smart SSH/HTTPS selection: check if SSH is configured before trying it |
| 1468 | // This avoids waiting for timeout on SSH when it's not configured |
| 1469 | const sshUrl = `git@github.com:${source.repo}.git` |
| 1470 | const httpsUrl = `https://github.com/${source.repo}.git` |
| 1471 | temporaryCachePath = join(cacheDir, tempName) |
| 1472 | cleanupNeeded = true |
| 1473 | |
| 1474 | let lastError: Error | null = null |
| 1475 | |
| 1476 | // Quick check if SSH is likely to work |
| 1477 | const sshConfigured = await isGitHubSshLikelyConfigured() |
| 1478 | |
| 1479 | if (sshConfigured) { |
| 1480 | // SSH looks good, try it first |
| 1481 | safeCallProgress(onProgress, `Cloning via SSH: ${sshUrl}`) |
| 1482 | try { |
| 1483 | await cacheMarketplaceFromGit( |
| 1484 | sshUrl, |
| 1485 | temporaryCachePath, |
| 1486 | source.ref, |
| 1487 | source.sparsePaths, |
| 1488 | onProgress, |
| 1489 | ) |
| 1490 | } catch (err) { |
no test coverage detected