(assetId, deps)
| 535 | } |
| 536 | |
| 537 | async function fetchAssetById(assetId, deps) { |
| 538 | const hubUrl = getHubUrl(deps); |
| 539 | if (!hubUrl) throw new ContractError('auth_required', 'Hub URL is required'); |
| 540 | if (!hasHubAuthorization(deps)) throw new ContractError('auth_required', 'Hub authentication required'); |
| 541 | const a2a = deps.a2a || require('./a2aProtocol'); |
| 542 | const message = a2a.buildFetch({ assetIds: [assetId] }); |
| 543 | const posted = await postEnvelope('/a2a/fetch', message, deps); |
| 544 | if (!posted.ok) { |
| 545 | const stableReason = stableHubReason(posted.body, REUSE_FAILURE_REASONS); |
| 546 | if (stableReason === 'unsupported' || stableReason === 'cli_unavailable') { |
| 547 | throw new ContractError(stableReason, reuseReasonMessage(stableReason)); |
| 548 | } |
| 549 | if (posted.status === 401 || posted.status === 403) throw new ContractError('auth_required', 'Hub authentication required'); |
| 550 | if (posted.status === 404) return null; |
| 551 | throw new ContractError('network_error', 'Hub fetch failed'); |
| 552 | } |
| 553 | const assets = assetsFromBody(posted.body); |
| 554 | return assets.find(asset => asset && asset.asset_id === assetId) || null; |
| 555 | } |
| 556 | |
| 557 | async function postValidate(message, deps) { |
| 558 | if (deps.validate) return normalizeValidateResult(await deps.validate(message)); |
no test coverage detected