1 | import * as os from 'os';
|
2 | import * as path from 'path';
|
3 | import * as fs from 'fs';
|
4 |
|
5 | import nodeFetch, {
|
6 | RequestInit as FetchOptions,
|
7 | Response,
|
8 | Request,
|
9 | Headers,
|
10 | } from 'node-fetch';
|
11 | import {CLIError} from './errors';
|
12 | import logger from './logger';
|
13 |
|
14 | async function unwrapFetchResult(response: Response) {
|
15 | const data = await response.text();
|
16 |
|
17 | try {
|
18 | return JSON.parse(data);
|
19 | } catch (e) {
|
20 | return data;
|
21 | }
|
22 | }
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 | const fetchToTemp = (url: string): Promise<string> => {
|
29 | try {
|
30 | return new Promise((resolve, reject) => {
|
31 | const fileName = path.basename(url);
|
32 | const tmpDir = path.join(os.tmpdir(), fileName);
|
33 |
|
34 | nodeFetch(url).then((result) => {
|
35 | if (result.status >= 400) {
|
36 | return reject(`Fetch request failed with status ${result.status}`);
|
37 | }
|
38 |
|
39 | const dest = fs.createWriteStream(tmpDir);
|
40 | result.body.pipe(dest);
|
41 |
|
42 | result.body.on('end', () => {
|
43 | resolve(tmpDir);
|
44 | });
|
45 |
|
46 | result.body.on('error', reject);
|
47 | });
|
48 | });
|
49 | } catch (e) {
|
50 | logger.error(e);
|
51 | throw e;
|
52 | }
|
53 | };
|
54 |
|
55 | const fetch = async (
|
56 | url: string | Request,
|
57 | options?: FetchOptions,
|
58 | ): Promise<{status: number; data: any; headers: Headers}> => {
|
59 | const result = await nodeFetch(url, options);
|
60 | const data = await unwrapFetchResult(result);
|
61 |
|
62 | if (result.status >= 400) {
|
63 | throw new CLIError(
|
64 | `Fetch request failed with status ${result.status}: ${data}.`,
|
65 | );
|
66 | }
|
67 |
|
68 | return {
|
69 | status: result.status,
|
70 | headers: result.headers,
|
71 | data,
|
72 | };
|
73 | };
|
74 |
|
75 | export {fetch, fetchToTemp};
|