diff --git a/packages/core/package-lock.json b/packages/core/package-lock.json index 9e3f42e6..6dd38177 100644 --- a/packages/core/package-lock.json +++ b/packages/core/package-lock.json @@ -399,15 +399,6 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.1.tgz", "integrity": "sha512-tCkE96/ZTO+cWbln2xfyvd6ngHLanvVlJ3e5BeirJ3BYI5GbAyubIrmV4JjjugDly5D9fHjOL5MNsqsCnqwW6g==" }, - "@types/node-fetch": { - "version": "2.5.8", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.8.tgz", - "integrity": "sha512-fbjI6ja0N5ZA8TV53RUqzsKNkl9fv8Oj3T7zxW7FGv1GSH7gwJaNF8dzCjrqKaxKeUpTz4yT1DaJFq/omNpGfw==", - "requires": { - "@types/node": "*", - "form-data": "^3.0.0" - } - }, "@types/raf": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/@types/raf/-/raf-3.4.0.tgz", @@ -430,6 +421,11 @@ "@types/node": "*" } }, + "@types/tough-cookie": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.0.tgz", + "integrity": "sha512-I99sngh224D0M7XgW1s120zxCt3VYQ3IQsuw3P3jbq5GG4yc79+ZjyKznyOGIQrflfylLgcfekeZW/vk0yng6A==" + }, "@types/valid-url": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@types/valid-url/-/valid-url-1.0.3.tgz", @@ -475,6 +471,14 @@ "uri-js": "^4.2.2" } }, + "already": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/already/-/already-1.13.2.tgz", + "integrity": "sha512-GU0ZqMhSetZeDlivqttmAmd2UpCbPSucziaDJcCN2NdOTedzaJTqZZwHHuGJvp0Us1wzQG0vSqFqax1SqgH8Aw==", + "requires": { + "throat": "^5.0.0" + } + }, "ansi-escapes": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", @@ -629,6 +633,11 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" }, + "callguard": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/callguard/-/callguard-2.0.0.tgz", + "integrity": "sha512-I3nd+fuj20FK1qu00ImrbH+II+8ULS6ioYr9igqR1xyqySoqc3DiHEyUM0mkoAdKeLGg2CtGnO8R3VRQX5krpQ==" + }, "canvas": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.6.1.tgz", @@ -973,6 +982,32 @@ "pend": "~1.2.0" } }, + "fetch-h2": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/fetch-h2/-/fetch-h2-2.5.1.tgz", + "integrity": "sha512-U+LQ+fHwF6TMg82A88wjljC5L174eoJfrc+0g4e7JWqL7U0w0QAoOkPDCGkO9KGH9BY55s4n45gLGOtlTAoqmw==", + "requires": { + "@types/tough-cookie": "^4.0.0", + "already": "^1.13.1", + "callguard": "^2.0.0", + "get-stream": "^6.0.0", + "through2": "^4.0.2", + "to-arraybuffer": "^1.0.1", + "tough-cookie": "^4.0.0" + }, + "dependencies": { + "tough-cookie": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", + "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==", + "requires": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.1.2" + } + } + } + }, "figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -991,16 +1026,6 @@ "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" }, - "form-data": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", - "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - }, "fs-minipass": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", @@ -1062,6 +1087,11 @@ } } }, + "get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==" + }, "getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", @@ -1509,11 +1539,6 @@ } } }, - "node-fetch": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", - "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" - }, "node-pre-gyp": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.11.0.tgz", @@ -2114,11 +2139,36 @@ } } }, + "throat": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz", + "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==" + }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" }, + "through2": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "requires": { + "readable-stream": "3" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, "timm": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/timm/-/timm-1.6.2.tgz", @@ -2137,6 +2187,11 @@ "os-tmpdir": "~1.0.2" } }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=" + }, "tough-cookie": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-3.0.1.tgz", @@ -2191,6 +2246,11 @@ "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + }, "uri-js": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", diff --git a/packages/core/package.json b/packages/core/package.json index d58c5cff..3e88e438 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -36,16 +36,15 @@ "@types/lodash.template": "^4.5.0", "@types/mime-types": "^2.1.0", "@types/node": "^12.20.1", - "@types/node-fetch": "^2.5.8", "@types/tar": "^4.0.4", "@types/valid-url": "^1.0.3", "color": "^3.1.3", "extract-zip": "^1.7.0", + "fetch-h2": "^2.5.1", "inquirer": "^7.3.3", "jimp": "^0.14.0", "lodash.template": "^4.5.0", "mime-types": "^2.1.28", - "node-fetch": "^2.6.0", "svg2img": "^0.8.1", "tar": "^6.1.0", "valid-url": "^1.0.9" diff --git a/packages/core/src/lib/ImageHelper.ts b/packages/core/src/lib/ImageHelper.ts index 04166576..5fc7ab58 100644 --- a/packages/core/src/lib/ImageHelper.ts +++ b/packages/core/src/lib/ImageHelper.ts @@ -17,7 +17,7 @@ import * as path from 'path'; import * as fs from 'fs'; import * as Jimp from 'jimp'; -import fetch from 'node-fetch'; +import {fetch} from 'fetch-h2'; import Color = require('color'); import {promisify} from 'util'; import {svg2img} from './wrappers/svg2img'; @@ -109,7 +109,7 @@ export class ImageHelper { * @returns an Object containing the original URL and the icon image data. */ async fetchIcon(iconUrl: string): Promise { - const response = await fetch(iconUrl); + const response = await fetch(iconUrl, {redirect: 'follow'}); if (response.status !== 200) { throw new Error( `Failed to download icon ${iconUrl}. Responded with status ${response.status}`); @@ -120,14 +120,13 @@ export class ImageHelper { throw new Error(`Received icon "${iconUrl}" with invalid Content-Type.` + ` Responded with Content-Type "${contentType}"`); } - let body; - body = await response.buffer(); + let body = await response.arrayBuffer(); if (contentType.startsWith('image/svg')) { body = await svg2img(iconUrl); } return { url: iconUrl, - data: await Jimp.read(body), + data: await Jimp.read(Buffer.from(body)), }; } } diff --git a/packages/core/src/lib/TwaGenerator.ts b/packages/core/src/lib/TwaGenerator.ts index 49e482ff..e762cb31 100644 --- a/packages/core/src/lib/TwaGenerator.ts +++ b/packages/core/src/lib/TwaGenerator.ts @@ -17,7 +17,7 @@ import * as path from 'path'; import * as fs from 'fs'; import * as Color from 'color'; -import fetch from 'node-fetch'; +import {fetch} from 'fetch-h2'; import {template} from 'lodash'; import {promisify} from 'util'; import {TwaManifest} from './TwaManifest'; @@ -266,7 +266,7 @@ export class TwaGenerator { 'Unable to write the Web Manifest. The TWA Manifest does not have a webManifestUrl'); } - const response = await fetch(twaManifest.webManifestUrl); + const response = await fetch(twaManifest.webManifestUrl.toString(), {redirect: 'follow'}); if (response.status !== 200) { throw new Error(`Failed to download Web Manifest ${twaManifest.webManifestUrl}.` + `Responded with status ${response.status}`); diff --git a/packages/core/src/lib/TwaManifest.ts b/packages/core/src/lib/TwaManifest.ts index d7301058..b6075570 100644 --- a/packages/core/src/lib/TwaManifest.ts +++ b/packages/core/src/lib/TwaManifest.ts @@ -17,7 +17,7 @@ 'use strict'; import * as fs from 'fs'; -import fetch from 'node-fetch'; +import {fetch} from 'fetch-h2'; import {findSuitableIcon, generatePackageId, validateNotEmpty} from './util'; import Color = require('color'); import {ConsoleLog} from './Log'; @@ -354,7 +354,7 @@ export class TwaManifest { * @returns {TwaManifest} */ static async fromWebManifest(url: string): Promise { - const response = await fetch(url); + const response = await fetch(url, {redirect: 'follow'}); const webManifest = await response.json(); const webManifestUrl: URL = new URL(url); return TwaManifest.fromWebManifestJson(webManifestUrl, webManifest); diff --git a/packages/core/src/lib/util.ts b/packages/core/src/lib/util.ts index ed46cbbb..da6567e7 100644 --- a/packages/core/src/lib/util.ts +++ b/packages/core/src/lib/util.ts @@ -15,7 +15,7 @@ */ import * as extractZip from 'extract-zip'; -import fetch from 'node-fetch'; +import {fetch} from 'fetch-h2'; import * as fs from 'fs'; import {join} from 'path'; import {promisify} from 'util'; @@ -59,7 +59,7 @@ export async function executeFile( */ export async function downloadFile(url: string, path: string, progressCallback?: (current: number, total: number) => void): Promise { - const result = await fetch(url); + const result = await fetch(url, {redirect: 'follow'}); // Try to determine the file size via the `Content-Length` header. This may not be available // for all cases. @@ -69,20 +69,22 @@ export async function downloadFile(url: string, path: string, const fileStream = fs.createWriteStream(path); let received = 0; + const readableStream = await result.readable(); await new Promise((resolve, reject) => { - result.body.pipe(fileStream); + readableStream.pipe(fileStream); // Even though we're piping the chunks, we intercept them to check for the download progress. if (progressCallback) { - result.body.on('data', (chunk) => { + readableStream.on('data', (chunk) => { received = received + chunk.length; progressCallback(received, fileSize); }); } - result.body.on('error', (err) => { + readableStream.on('error', (err) => { reject(err); }); + fileStream.on('finish', () => { resolve(); }); @@ -271,7 +273,7 @@ export async function rmdir(path: string): Promise { * @returns {Promise { - const response = await fetch(webManifestUrl); + const response = await fetch(webManifestUrl.toString()); if (response.status !== 200) { throw new Error(`Failed to download Web Manifest ${webManifestUrl}. ` + `Responded with status ${response.status}`);