UNPKG

3.28 kBJavaScriptView Raw
1"use strict";
2var __importDefault = (this && this.__importDefault) || function (mod) {
3 return (mod && mod.__esModule) ? mod : { "default": mod };
4};
5Object.defineProperty(exports, "__esModule", { value: true });
6const assert_1 = __importDefault(require("assert"));
7const node_fetch_1 = __importDefault(require("node-fetch"));
8const multistream_1 = __importDefault(require("multistream"));
9const async_retry_1 = __importDefault(require("async-retry"));
10const async_sema_1 = __importDefault(require("async-sema"));
11const semaToDownloadFromS3 = new async_sema_1.default(5);
12class BailableError extends Error {
13 constructor(...args) {
14 super(...args);
15 this.bail = false;
16 }
17}
18class FileRef {
19 constructor({ mode = 0o100644, digest, contentType, mutable = false, }) {
20 assert_1.default(typeof mode === 'number');
21 assert_1.default(typeof digest === 'string');
22 this.type = 'FileRef';
23 this.mode = mode;
24 this.digest = digest;
25 this.contentType = contentType;
26 this.mutable = mutable;
27 }
28 async toStreamAsync() {
29 let url = '';
30 // sha:24be087eef9fac01d61b30a725c1a10d7b45a256
31 const [digestType, digestHash] = this.digest.split(':');
32 if (digestType === 'sha') {
33 // This CloudFront URL edge caches the `now-files` S3 bucket to prevent
34 // overloading it. Mutable files cannot be cached.
35 // `https://now-files.s3.amazonaws.com/${digestHash}`
36 url = this.mutable
37 ? `https://now-files.s3.amazonaws.com/${digestHash}`
38 : `https://dmmcy0pwk6bqi.cloudfront.net/${digestHash}`;
39 }
40 else if (digestType === 'sha+ephemeral') {
41 // This URL is currently only used for cache files that constantly
42 // change. We shouldn't cache it on CloudFront because it'd always be a
43 // MISS.
44 url = `https://now-ephemeral-files.s3.amazonaws.com/${digestHash}`;
45 }
46 else {
47 throw new Error('Expected digest to be sha');
48 }
49 await semaToDownloadFromS3.acquire();
50 // console.time(`downloading ${url}`);
51 try {
52 return await async_retry_1.default(async () => {
53 const resp = await node_fetch_1.default(url);
54 if (!resp.ok) {
55 const error = new BailableError(`download: ${resp.status} ${resp.statusText} for ${url}`);
56 if (resp.status === 403)
57 error.bail = true;
58 throw error;
59 }
60 return resp.body;
61 }, { factor: 1, retries: 3 });
62 }
63 finally {
64 // console.timeEnd(`downloading ${url}`);
65 semaToDownloadFromS3.release();
66 }
67 }
68 toStream() {
69 let flag = false;
70 // eslint-disable-next-line consistent-return
71 return multistream_1.default(cb => {
72 if (flag)
73 return cb(null, null);
74 flag = true;
75 this.toStreamAsync()
76 .then(stream => {
77 cb(null, stream);
78 })
79 .catch(error => {
80 cb(error, null);
81 });
82 });
83 }
84}
85exports.default = FileRef;