Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/build/lib/fetch.js
3520 views
1
"use strict";
2
var __importDefault = (this && this.__importDefault) || function (mod) {
3
return (mod && mod.__esModule) ? mod : { "default": mod };
4
};
5
Object.defineProperty(exports, "__esModule", { value: true });
6
exports.fetchUrls = fetchUrls;
7
exports.fetchUrl = fetchUrl;
8
exports.fetchGithub = fetchGithub;
9
/*---------------------------------------------------------------------------------------------
10
* Copyright (c) Microsoft Corporation. All rights reserved.
11
* Licensed under the MIT License. See License.txt in the project root for license information.
12
*--------------------------------------------------------------------------------------------*/
13
const event_stream_1 = __importDefault(require("event-stream"));
14
const vinyl_1 = __importDefault(require("vinyl"));
15
const fancy_log_1 = __importDefault(require("fancy-log"));
16
const ansi_colors_1 = __importDefault(require("ansi-colors"));
17
const crypto_1 = __importDefault(require("crypto"));
18
const through2_1 = __importDefault(require("through2"));
19
function fetchUrls(urls, options) {
20
if (options === undefined) {
21
options = {};
22
}
23
if (typeof options.base !== 'string' && options.base !== null) {
24
options.base = '/';
25
}
26
if (!Array.isArray(urls)) {
27
urls = [urls];
28
}
29
return event_stream_1.default.readArray(urls).pipe(event_stream_1.default.map((data, cb) => {
30
const url = [options.base, data].join('');
31
fetchUrl(url, options).then(file => {
32
cb(undefined, file);
33
}, error => {
34
cb(error);
35
});
36
}));
37
}
38
async function fetchUrl(url, options, retries = 10, retryDelay = 1000) {
39
const verbose = !!options.verbose || !!process.env['CI'] || !!process.env['BUILD_ARTIFACTSTAGINGDIRECTORY'] || !!process.env['GITHUB_WORKSPACE'];
40
try {
41
let startTime = 0;
42
if (verbose) {
43
(0, fancy_log_1.default)(`Start fetching ${ansi_colors_1.default.magenta(url)}${retries !== 10 ? ` (${10 - retries} retry)` : ''}`);
44
startTime = new Date().getTime();
45
}
46
const controller = new AbortController();
47
const timeout = setTimeout(() => controller.abort(), 30 * 1000);
48
try {
49
const response = await fetch(url, {
50
...options.nodeFetchOptions,
51
signal: controller.signal /* Typings issue with lib.dom.d.ts */
52
});
53
if (verbose) {
54
(0, fancy_log_1.default)(`Fetch completed: Status ${response.status}. Took ${ansi_colors_1.default.magenta(`${new Date().getTime() - startTime} ms`)}`);
55
}
56
if (response.ok && (response.status >= 200 && response.status < 300)) {
57
const contents = Buffer.from(await response.arrayBuffer());
58
if (options.checksumSha256) {
59
const actualSHA256Checksum = crypto_1.default.createHash('sha256').update(contents).digest('hex');
60
if (actualSHA256Checksum !== options.checksumSha256) {
61
throw new Error(`Checksum mismatch for ${ansi_colors_1.default.cyan(url)} (expected ${options.checksumSha256}, actual ${actualSHA256Checksum}))`);
62
}
63
else if (verbose) {
64
(0, fancy_log_1.default)(`Verified SHA256 checksums match for ${ansi_colors_1.default.cyan(url)}`);
65
}
66
}
67
else if (verbose) {
68
(0, fancy_log_1.default)(`Skipping checksum verification for ${ansi_colors_1.default.cyan(url)} because no expected checksum was provided`);
69
}
70
if (verbose) {
71
(0, fancy_log_1.default)(`Fetched response body buffer: ${ansi_colors_1.default.magenta(`${contents.byteLength} bytes`)}`);
72
}
73
return new vinyl_1.default({
74
cwd: '/',
75
base: options.base,
76
path: url,
77
contents
78
});
79
}
80
let err = `Request ${ansi_colors_1.default.magenta(url)} failed with status code: ${response.status}`;
81
if (response.status === 403) {
82
err += ' (you may be rate limited)';
83
}
84
throw new Error(err);
85
}
86
finally {
87
clearTimeout(timeout);
88
}
89
}
90
catch (e) {
91
if (verbose) {
92
(0, fancy_log_1.default)(`Fetching ${ansi_colors_1.default.cyan(url)} failed: ${e}`);
93
}
94
if (retries > 0) {
95
await new Promise(resolve => setTimeout(resolve, retryDelay));
96
return fetchUrl(url, options, retries - 1, retryDelay);
97
}
98
throw e;
99
}
100
}
101
const ghApiHeaders = {
102
Accept: 'application/vnd.github.v3+json',
103
'User-Agent': 'VSCode Build',
104
};
105
if (process.env.GITHUB_TOKEN) {
106
ghApiHeaders.Authorization = 'Basic ' + Buffer.from(process.env.GITHUB_TOKEN).toString('base64');
107
}
108
const ghDownloadHeaders = {
109
...ghApiHeaders,
110
Accept: 'application/octet-stream',
111
};
112
/**
113
* @param repo for example `Microsoft/vscode`
114
* @param version for example `16.17.1` - must be a valid releases tag
115
* @param assetName for example (name) => name === `win-x64-node.exe` - must be an asset that exists
116
* @returns a stream with the asset as file
117
*/
118
function fetchGithub(repo, options) {
119
return fetchUrls(`/repos/${repo.replace(/^\/|\/$/g, '')}/releases/tags/v${options.version}`, {
120
base: 'https://api.github.com',
121
verbose: options.verbose,
122
nodeFetchOptions: { headers: ghApiHeaders }
123
}).pipe(through2_1.default.obj(async function (file, _enc, callback) {
124
const assetFilter = typeof options.name === 'string' ? (name) => name === options.name : options.name;
125
const asset = JSON.parse(file.contents.toString()).assets.find((a) => assetFilter(a.name));
126
if (!asset) {
127
return callback(new Error(`Could not find asset in release of ${repo} @ ${options.version}`));
128
}
129
try {
130
callback(null, await fetchUrl(asset.url, {
131
nodeFetchOptions: { headers: ghDownloadHeaders },
132
verbose: options.verbose,
133
checksumSha256: options.checksumSha256
134
}));
135
}
136
catch (error) {
137
callback(error);
138
}
139
}));
140
}
141
//# sourceMappingURL=fetch.js.map
142