(url: string, dest: string)
| 569 | } |
| 570 | |
| 571 | async function downloadUvTarball(url: string, dest: string): Promise<void> { |
| 572 | const tmpDest = `${dest}.${process.pid}.${Date.now()}.tmp`; |
| 573 | const controller = new AbortController(); |
| 574 | const timeout = setTimeout(() => controller.abort(), 60_000); |
| 575 | |
| 576 | try { |
| 577 | const response = await fetch(url, { |
| 578 | redirect: 'follow', |
| 579 | signal: controller.signal, |
| 580 | }); |
| 581 | |
| 582 | if (!response.ok) { |
| 583 | throw new NowBuildError({ |
| 584 | code: 'RUNTIME_DEPENDENCY_INSTALLATION_FAILED', |
| 585 | message: `could not download ${url}: HTTP ${response.status}`, |
| 586 | }); |
| 587 | } |
| 588 | |
| 589 | if (!response.body) { |
| 590 | throw new NowBuildError({ |
| 591 | code: 'RUNTIME_DEPENDENCY_INSTALLATION_FAILED', |
| 592 | message: `could not download ${url}: response body was empty`, |
| 593 | }); |
| 594 | } |
| 595 | |
| 596 | await pipeline( |
| 597 | Readable.fromWeb(response.body), |
| 598 | fs.createWriteStream(tmpDest) |
| 599 | ); |
| 600 | await fs.promises.rename(tmpDest, dest); |
| 601 | } catch (err) { |
| 602 | await fs.promises.unlink(tmpDest).catch(() => {}); |
| 603 | if (err instanceof NowBuildError) { |
| 604 | throw err; |
| 605 | } |
| 606 | throw new NowBuildError({ |
| 607 | code: 'RUNTIME_DEPENDENCY_INSTALLATION_FAILED', |
| 608 | message: `could not download ${url}: ${ |
| 609 | err instanceof Error ? err.message : String(err) |
| 610 | }`, |
| 611 | }); |
| 612 | } finally { |
| 613 | clearTimeout(timeout); |
| 614 | } |
| 615 | } |
| 616 | |
| 617 | async function sha256File(filePath: string): Promise<string> { |
| 618 | const data = await fs.promises.readFile(filePath); |
no test coverage detected