diff --git a/.changeset/plenty-beers-decide.md b/.changeset/plenty-beers-decide.md new file mode 100644 index 00000000000..87bc58c3589 --- /dev/null +++ b/.changeset/plenty-beers-decide.md @@ -0,0 +1,13 @@ +--- +'@firebase/rules-unit-testing': patch +'@firebase/firestore-compat': patch +'@firebase/functions-compat': patch +'@firebase/storage-compat': patch +'@firebase/auth-compat': patch +'@firebase/firestore': patch +'@firebase/functions': patch +'@firebase/storage': patch +'@firebase/auth': patch +--- + +Removed dependency on undici and node-fetch in our node bundles, replacing them with the native fetch implementation. diff --git a/integration/messaging/package.json b/integration/messaging/package.json index 864faa99987..f34637fba05 100644 --- a/integration/messaging/package.json +++ b/integration/messaging/package.json @@ -15,7 +15,6 @@ "express": "4.19.2", "geckodriver": "2.0.4", "mocha": "9.2.2", - "undici": "6.19.7", "selenium-assistant": "6.1.1" }, "engines": { diff --git a/integration/messaging/test/utils/sendMessage.js b/integration/messaging/test/utils/sendMessage.js index 1d2e95054eb..6393e90364c 100644 --- a/integration/messaging/test/utils/sendMessage.js +++ b/integration/messaging/test/utils/sendMessage.js @@ -15,7 +15,6 @@ * limitations under the License. */ -const undici = require('undici'); const FCM_SEND_ENDPOINT = 'https://fcm.googleapis.com/fcm/send'; // Rotatable fcm server key. It's generally a bad idea to expose server keys. The reason is to // simplify testing process (no need to implement server side decryption of git secret). The @@ -28,7 +27,7 @@ module.exports = async payload => { 'Requesting to send an FCM message with payload: ' + JSON.stringify(payload) ); - const response = await undici.fetch(FCM_SEND_ENDPOINT, { + const response = await fetch(FCM_SEND_ENDPOINT, { method: 'POST', body: JSON.stringify(payload), headers: { diff --git a/package.json b/package.json index 18ddbe42bff..41d92b74fb6 100644 --- a/package.json +++ b/package.json @@ -156,7 +156,6 @@ "tslint": "6.1.3", "typedoc": "0.16.11", "typescript": "4.7.4", - "undici": "6.19.7", "watch": "1.0.2", "webpack": "5.76.0", "yargs": "17.7.2" diff --git a/packages/auth-compat/index.node.ts b/packages/auth-compat/index.node.ts index 6d8dd2c07a5..1513148bea9 100644 --- a/packages/auth-compat/index.node.ts +++ b/packages/auth-compat/index.node.ts @@ -23,15 +23,6 @@ */ export * from './index'; import { FetchProvider } from '@firebase/auth/internal'; -import { - fetch as undiciFetch, - Headers as undiciHeaders, - Response as undiciResponse -} from 'undici'; import './index'; -FetchProvider.initialize( - undiciFetch as unknown as typeof fetch, - undiciHeaders as unknown as typeof Headers, - undiciResponse as unknown as typeof Response -); +FetchProvider.initialize(fetch, Headers, Response); diff --git a/packages/auth-compat/karma.conf.js b/packages/auth-compat/karma.conf.js index f3f14e8d1b1..6283ffbc3f1 100644 --- a/packages/auth-compat/karma.conf.js +++ b/packages/auth-compat/karma.conf.js @@ -30,18 +30,6 @@ module.exports = function (config) { // frameworks to use // available frameworks: https://npmjs.org/browse/keyword/karma-adapter frameworks: ['mocha'], - // undici is a fetch polyfill that test helpers call for Node tests, and browser tests should - // ignore its import to avoid compilation errors in those test helpers. - webpack: { - ...webpackBase, - resolve: { - ...webpackBase.resolve, - alias: { - 'undici': false - } - } - }, - client: Object.assign({}, karmaBase.client, getClientConfig()) }); diff --git a/packages/auth-compat/package.json b/packages/auth-compat/package.json index 6db6e7ba89d..d6d5d9573b8 100644 --- a/packages/auth-compat/package.json +++ b/packages/auth-compat/package.json @@ -55,7 +55,6 @@ "@firebase/auth-types": "0.12.2", "@firebase/component": "0.6.8", "@firebase/util": "1.9.7", - "undici": "6.19.7", "tslib": "^2.1.0" }, "license": "Apache-2.0", diff --git a/packages/auth/karma.conf.js b/packages/auth/karma.conf.js index 1d28c329f55..f8dcd5b0341 100644 --- a/packages/auth/karma.conf.js +++ b/packages/auth/karma.conf.js @@ -27,17 +27,6 @@ module.exports = function (config) { // frameworks to use // available frameworks: https://npmjs.org/browse/keyword/karma-adapter frameworks: ['mocha'], - // undici is a fetch polyfill that test helpers call for Node tests, and browser tests should - // ignore its import to avoid compilation errors in those test helpers. - webpack: { - ...webpackBase, - resolve: { - ...webpackBase.resolve, - alias: { - 'undici': false - } - } - }, client: Object.assign({}, karmaBase.client, getClientConfig(argv)) }); diff --git a/packages/auth/package.json b/packages/auth/package.json index 7d41b0c5962..2dff1631c02 100644 --- a/packages/auth/package.json +++ b/packages/auth/package.json @@ -130,7 +130,6 @@ "@firebase/component": "0.6.8", "@firebase/logger": "0.4.2", "@firebase/util": "1.9.7", - "undici": "6.19.7", "tslib": "^2.1.0" }, "license": "Apache-2.0", diff --git a/packages/auth/src/platform_node/index.ts b/packages/auth/src/platform_node/index.ts index 41da18ff643..67618b5b773 100644 --- a/packages/auth/src/platform_node/index.ts +++ b/packages/auth/src/platform_node/index.ts @@ -28,18 +28,9 @@ import { AuthImpl } from '../core/auth/auth_impl'; import { FetchProvider } from '../core/util/fetch_provider'; import { getDefaultEmulatorHost } from '@firebase/util'; -import { - fetch as undiciFetch, - Headers as undiciHeaders, - Response as undiciResponse -} from 'undici'; // Initialize the fetch polyfill, the types are slightly off so just cast and hope for the best -FetchProvider.initialize( - undiciFetch as unknown as typeof fetch, - undiciHeaders as unknown as typeof Headers, - undiciResponse as unknown as typeof Response -); +FetchProvider.initialize(fetch, Headers, Response); // First, we set up the various platform-specific features for Node (register // the version and declare the Node getAuth function) diff --git a/packages/auth/test/helpers/integration/emulator_rest_helpers.ts b/packages/auth/test/helpers/integration/emulator_rest_helpers.ts index 32b9aad2129..5a96d193ee1 100644 --- a/packages/auth/test/helpers/integration/emulator_rest_helpers.ts +++ b/packages/auth/test/helpers/integration/emulator_rest_helpers.ts @@ -15,7 +15,6 @@ * limitations under the License. */ -import { fetch as undiciFetch, RequestInit as undiciRequestInit } from 'undici'; import { getAppConfig, getEmulatorUrl } from './settings'; export interface VerificationSession { @@ -88,9 +87,8 @@ function doFetch(url: string, request?: RequestInit): ReturnType { if (typeof document !== 'undefined') { return fetch(url, request); } else { - return undiciFetch( - url, - request as undiciRequestInit - ) as unknown as ReturnType; + return fetch(url, request as RequestInit) as unknown as ReturnType< + typeof fetch + >; } } diff --git a/packages/firestore/package.json b/packages/firestore/package.json index 1ba59e3a8dd..5c630f7837e 100644 --- a/packages/firestore/package.json +++ b/packages/firestore/package.json @@ -103,7 +103,6 @@ "@firebase/webchannel-wrapper": "1.0.1", "@grpc/grpc-js": "~1.9.0", "@grpc/proto-loader": "^0.7.8", - "undici": "6.19.7", "tslib": "^2.1.0" }, "peerDependencies": { diff --git a/packages/firestore/src/platform/browser_lite/connection.ts b/packages/firestore/src/platform/browser_lite/connection.ts index a6464245441..573f743a882 100644 --- a/packages/firestore/src/platform/browser_lite/connection.ts +++ b/packages/firestore/src/platform/browser_lite/connection.ts @@ -24,5 +24,5 @@ export { newConnectivityMonitor } from '../browser/connection'; /** Initializes the HTTP connection for the REST API. */ export function newConnection(databaseInfo: DatabaseInfo): Connection { - return new FetchConnection(databaseInfo, fetch.bind(null)); + return new FetchConnection(databaseInfo); } diff --git a/packages/firestore/src/platform/browser_lite/fetch_connection.ts b/packages/firestore/src/platform/browser_lite/fetch_connection.ts index cad3c372ad5..d11247c8019 100644 --- a/packages/firestore/src/platform/browser_lite/fetch_connection.ts +++ b/packages/firestore/src/platform/browser_lite/fetch_connection.ts @@ -16,7 +16,6 @@ */ import { Token } from '../../api/credentials'; -import { DatabaseInfo } from '../../core/database_info'; import { Stream } from '../../remote/connection'; import { RestConnection } from '../../remote/rest_connection'; import { mapCodeFromHttpStatus } from '../../remote/rpc_error'; @@ -28,17 +27,6 @@ import { StringMap } from '../../util/types'; * (e.g. `fetch` or a polyfill). */ export class FetchConnection extends RestConnection { - /** - * @param databaseInfo - The connection info. - * @param fetchImpl - `fetch` or a Polyfill that implements the fetch API. - */ - constructor( - databaseInfo: DatabaseInfo, - private readonly fetchImpl: typeof fetch - ) { - super(databaseInfo); - } - openStream( rpcName: string, token: Token | null @@ -56,7 +44,7 @@ export class FetchConnection extends RestConnection { let response: Response; try { - response = await this.fetchImpl(url, { + response = await fetch(url, { method: 'POST', headers, body: requestJson diff --git a/packages/firestore/src/platform/node_lite/connection.ts b/packages/firestore/src/platform/node_lite/connection.ts index e85bb89bc97..7258661c184 100644 --- a/packages/firestore/src/platform/node_lite/connection.ts +++ b/packages/firestore/src/platform/node_lite/connection.ts @@ -15,8 +15,6 @@ * limitations under the License. */ -import { fetch as undiciFetch } from 'undici'; - import { DatabaseInfo } from '../../core/database_info'; import { Connection } from '../../remote/connection'; import { FetchConnection } from '../browser_lite/fetch_connection'; @@ -25,8 +23,5 @@ export { newConnectivityMonitor } from '../browser/connection'; /** Initializes the HTTP connection for the REST API. */ export function newConnection(databaseInfo: DatabaseInfo): Connection { - // undici is meant to be API compatible with `fetch`, but its type doesn't - // match 100%. - // eslint-disable-next-line @typescript-eslint/no-explicit-any - return new FetchConnection(databaseInfo, undiciFetch as any); + return new FetchConnection(databaseInfo); } diff --git a/packages/functions/karma.conf.js b/packages/functions/karma.conf.js index 3dc9b7d572c..db9bf05bfe0 100644 --- a/packages/functions/karma.conf.js +++ b/packages/functions/karma.conf.js @@ -26,18 +26,7 @@ module.exports = function (config) { files, // frameworks to use // available frameworks: https://npmjs.org/browse/keyword/karma-adapter - frameworks: ['mocha'], - // undici is a fetch polyfill that test helpers call for Node tests, and browser tests should - // ignore its import to avoid compilation errors in those test helpers. - webpack: { - ...webpackBase, - resolve: { - ...webpackBase.resolve, - alias: { - 'undici': false - } - } - } + frameworks: ['mocha'] }); config.set(karmaConfig); diff --git a/packages/functions/package.json b/packages/functions/package.json index 3ede8a4c3f9..5be9917b301 100644 --- a/packages/functions/package.json +++ b/packages/functions/package.json @@ -72,7 +72,6 @@ "@firebase/auth-interop-types": "0.2.3", "@firebase/app-check-interop-types": "0.3.2", "@firebase/util": "1.9.7", - "undici": "6.19.7", "tslib": "^2.1.0" }, "nyc": { diff --git a/packages/functions/src/config.ts b/packages/functions/src/config.ts index 6c4dac26e6a..656158da10d 100644 --- a/packages/functions/src/config.ts +++ b/packages/functions/src/config.ts @@ -35,10 +35,7 @@ const APP_CHECK_INTERNAL_NAME: AppCheckInternalComponentName = const MESSAGING_INTERNAL_NAME: MessagingInternalComponentName = 'messaging-internal'; -export function registerFunctions( - fetchImpl: typeof fetch, - variant?: string -): void { +export function registerFunctions(variant?: string): void { const factory: InstanceFactory<'functions'> = ( container: ComponentContainer, { instanceIdentifier: regionOrCustomDomain } @@ -55,8 +52,7 @@ export function registerFunctions( authProvider, messagingProvider, appCheckProvider, - regionOrCustomDomain, - fetchImpl + regionOrCustomDomain ); }; diff --git a/packages/functions/src/index.node.ts b/packages/functions/src/index.node.ts index 6fb63173957..6b1a2ee2939 100644 --- a/packages/functions/src/index.node.ts +++ b/packages/functions/src/index.node.ts @@ -15,9 +15,8 @@ * limitations under the License. */ import { registerFunctions } from './config'; -import { fetch as undiciFetch } from 'undici'; export * from './api'; +export * from './public-types'; -// eslint-disable-next-line @typescript-eslint/no-explicit-any -registerFunctions(undiciFetch as any, 'node'); +registerFunctions('node'); diff --git a/packages/functions/src/index.ts b/packages/functions/src/index.ts index 7318b3e64b7..6d404cc8245 100644 --- a/packages/functions/src/index.ts +++ b/packages/functions/src/index.ts @@ -25,4 +25,4 @@ import { registerFunctions } from './config'; export * from './api'; export * from './public-types'; -registerFunctions(fetch.bind(self)); +registerFunctions(); diff --git a/packages/functions/src/service.ts b/packages/functions/src/service.ts index c5fe7fa8a85..986dcbc735d 100644 --- a/packages/functions/src/service.ts +++ b/packages/functions/src/service.ts @@ -104,8 +104,7 @@ export class FunctionsService implements _FirebaseService { authProvider: Provider, messagingProvider: Provider, appCheckProvider: Provider, - regionOrCustomDomain: string = DEFAULT_REGION, - readonly fetchImpl: typeof fetch + regionOrCustomDomain: string = DEFAULT_REGION ) { this.contextProvider = new ContextProvider( authProvider, @@ -212,14 +211,13 @@ export function httpsCallableFromURL( async function postJSON( url: string, body: unknown, - headers: { [key: string]: string }, - fetchImpl: typeof fetch + headers: { [key: string]: string } ): Promise { headers['Content-Type'] = 'application/json'; let response: Response; try { - response = await fetchImpl(url, { + response = await fetch(url, { method: 'POST', body: JSON.stringify(body), headers @@ -296,7 +294,7 @@ async function callAtURL( const failAfterHandle = failAfter(timeout); const response = await Promise.race([ - postJSON(url, body, headers, functionsInstance.fetchImpl), + postJSON(url, body, headers), failAfterHandle.promise, functionsInstance.cancelAllRequests ]); diff --git a/packages/functions/test/utils.ts b/packages/functions/test/utils.ts index 0eb0b678c19..bcf0286b49d 100644 --- a/packages/functions/test/utils.ts +++ b/packages/functions/test/utils.ts @@ -21,7 +21,6 @@ import { FirebaseAuthInternalName } from '@firebase/auth-interop-types'; import { AppCheckInternalComponentName } from '@firebase/app-check-interop-types'; import { FunctionsService } from '../src/service'; import { connectFunctionsEmulator } from '../src/api'; -import { fetch as undiciFetch } from 'undici'; import { MessagingInternalComponentName } from '../../../packages/messaging-interop-types'; export function makeFakeApp(options: FirebaseOptions = {}): FirebaseApp { @@ -58,15 +57,12 @@ export function createTestService( new ComponentContainer('test') ) ): FunctionsService { - const fetchImpl: typeof fetch = - typeof window !== 'undefined' ? fetch.bind(window) : (undiciFetch as any); const functions = new FunctionsService( app, authProvider, messagingProvider, appCheckProvider, - region, - fetchImpl + region ); const useEmulator = !!process.env.FIREBASE_FUNCTIONS_EMULATOR_ORIGIN; if (useEmulator) { diff --git a/packages/rules-unit-testing/package.json b/packages/rules-unit-testing/package.json index 4053cca8e17..585a0efc5e8 100644 --- a/packages/rules-unit-testing/package.json +++ b/packages/rules-unit-testing/package.json @@ -53,9 +53,5 @@ "typings": "dist/index.d.ts", "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" - }, - "dependencies": { - "node-fetch": "2.6.7", - "@types/node-fetch": "2.6.4" } } diff --git a/packages/rules-unit-testing/src/impl/discovery.ts b/packages/rules-unit-testing/src/impl/discovery.ts index 9798f017241..3c7c20fedad 100644 --- a/packages/rules-unit-testing/src/impl/discovery.ts +++ b/packages/rules-unit-testing/src/impl/discovery.ts @@ -16,7 +16,6 @@ */ import { EmulatorConfig, HostAndPort } from '../public_types'; -import nodeFetch from 'node-fetch'; import { makeUrl, fixHostname } from './url'; /** @@ -27,9 +26,9 @@ import { makeUrl, fixHostname } from './url'; */ export async function discoverEmulators( hub: HostAndPort, - fetch: typeof nodeFetch = nodeFetch + fetchImpl: typeof fetch = fetch ): Promise { - const res = await fetch(makeUrl(hub, '/emulators')); + const res = await fetchImpl(makeUrl(hub, '/emulators')); if (!res.ok) { throw new Error( `HTTP Error ${res.status} when attempting to reach Emulator Hub at ${res.url}, are you sure it is running?` diff --git a/packages/rules-unit-testing/src/impl/rules.ts b/packages/rules-unit-testing/src/impl/rules.ts index 7d4d900367f..fefeb586233 100644 --- a/packages/rules-unit-testing/src/impl/rules.ts +++ b/packages/rules-unit-testing/src/impl/rules.ts @@ -17,7 +17,6 @@ import { HostAndPort } from '../public_types'; import { makeUrl } from './url'; -import fetch from 'node-fetch'; /** * @private diff --git a/packages/rules-unit-testing/src/impl/test_environment.ts b/packages/rules-unit-testing/src/impl/test_environment.ts index cb325912c29..5e0f4c613fe 100644 --- a/packages/rules-unit-testing/src/impl/test_environment.ts +++ b/packages/rules-unit-testing/src/impl/test_environment.ts @@ -15,7 +15,6 @@ * limitations under the License. */ -import fetch from 'node-fetch'; import firebase from 'firebase/compat/app'; import 'firebase/compat/firestore'; import 'firebase/compat/database'; diff --git a/packages/rules-unit-testing/src/util.ts b/packages/rules-unit-testing/src/util.ts index c96b22d8597..abcad41ef9b 100644 --- a/packages/rules-unit-testing/src/util.ts +++ b/packages/rules-unit-testing/src/util.ts @@ -21,7 +21,6 @@ import { } from './impl/discovery'; import { fixHostname, makeUrl } from './impl/url'; import { HostAndPort } from './public_types'; -import fetch from 'node-fetch'; /** * Run a setup function with background Cloud Functions triggers disabled. This can be used to diff --git a/packages/rules-unit-testing/test/impl/discovery.test.ts b/packages/rules-unit-testing/test/impl/discovery.test.ts index a2ac2be767b..39b5628ddc2 100644 --- a/packages/rules-unit-testing/test/impl/discovery.test.ts +++ b/packages/rules-unit-testing/test/impl/discovery.test.ts @@ -71,7 +71,7 @@ describe('discoverEmulators()', () => { // Connect to port:0. Should always fail (although error codes may differ among OSes). await expect( discoverEmulators({ host: '127.0.0.1', port: 0 }) - ).to.be.rejectedWith(/EADDRNOTAVAIL|ECONNREFUSED/); + ).to.be.rejectedWith(/EADDRNOTAVAIL|ECONNREFUSED|fetch failed/); }); it('throws if response status is not 2xx', async () => { diff --git a/packages/rules-unit-testing/test/util.test.ts b/packages/rules-unit-testing/test/util.test.ts index 9dc778fb93e..e3b514d6a10 100644 --- a/packages/rules-unit-testing/test/util.test.ts +++ b/packages/rules-unit-testing/test/util.test.ts @@ -165,7 +165,7 @@ describe('assertFails()', () => { describe('withFunctionTriggersDisabled()', () => { it('disabling function triggers does not throw, returns value', async function () { - const fetchSpy = sinon.spy(require('node-fetch'), 'default'); + const fetchSpy = sinon.spy(globalThis, 'fetch'); const res = await withFunctionTriggersDisabled(() => { return Promise.resolve(1234); @@ -176,7 +176,7 @@ describe('withFunctionTriggersDisabled()', () => { }); it('disabling function triggers always re-enables, event when the function throws', async function () { - const fetchSpy = sinon.spy(require('node-fetch'), 'default'); + const fetchSpy = sinon.spy(globalThis, 'fetch'); const res = withFunctionTriggersDisabled(() => { throw new Error('I throw!'); diff --git a/packages/storage/package.json b/packages/storage/package.json index 94453f9fce8..c588756199f 100644 --- a/packages/storage/package.json +++ b/packages/storage/package.json @@ -50,7 +50,6 @@ "dependencies": { "@firebase/util": "1.9.7", "@firebase/component": "0.6.8", - "undici": "6.19.7", "tslib": "^2.1.0" }, "peerDependencies": { diff --git a/packages/storage/src/platform/node/connection.ts b/packages/storage/src/platform/node/connection.ts index d7141e6ef68..c90f664c3b2 100644 --- a/packages/storage/src/platform/node/connection.ts +++ b/packages/storage/src/platform/node/connection.ts @@ -21,7 +21,6 @@ import { ErrorCode } from '../../implementation/connection'; import { internalError } from '../../implementation/error'; -import { fetch as undiciFetch, Headers as undiciHeaders } from 'undici'; /** An override for the text-based Connection. Used in tests. */ let textFactoryOverride: (() => Connection) | null = null; @@ -39,9 +38,8 @@ abstract class FetchConnection protected statusCode_: number | undefined; protected body_: ArrayBuffer | undefined; protected errorText_ = ''; - protected headers_: undiciHeaders | undefined; + protected headers_: Headers | undefined; protected sent_: boolean = false; - protected fetch_ = undiciFetch; constructor() { this.errorCode_ = ErrorCode.NO_ERROR; @@ -59,7 +57,7 @@ abstract class FetchConnection this.sent_ = true; try { - const response = await this.fetch_(url, { + const response = await fetch(url, { method, headers: headers || {}, body: body as NodeJS.ArrayBufferView | string @@ -163,7 +161,7 @@ export class FetchStreamConnection extends FetchConnection< this.sent_ = true; try { - const response = await this.fetch_(url, { + const response = await fetch(url, { method, headers: headers || {}, body: body as NodeJS.ArrayBufferView | string diff --git a/packages/storage/test/node/connection.test.ts b/packages/storage/test/node/connection.test.ts index 32c499f0209..925d1f8f7dc 100644 --- a/packages/storage/test/node/connection.test.ts +++ b/packages/storage/test/node/connection.test.ts @@ -24,9 +24,9 @@ describe('Connections', () => { it('FetchConnection.send() should not reject on network errors', async () => { const connection = new FetchBytesConnection(); - // need the casting here because fetch_ is a private member - stub(connection as any, 'fetch_').rejects(); + const fetchStub = stub(globalThis, 'fetch').rejects(); await connection.send('testurl', 'GET'); expect(connection.getErrorCode()).to.equal(ErrorCode.NETWORK_ERROR); + fetchStub.restore(); }); }); diff --git a/repo-scripts/changelog-generator/index.ts b/repo-scripts/changelog-generator/index.ts index 20f3de482f1..3570c8a96a5 100644 --- a/repo-scripts/changelog-generator/index.ts +++ b/repo-scripts/changelog-generator/index.ts @@ -17,7 +17,6 @@ import { ChangelogFunctions } from '@changesets/types'; import { getInfo } from '@changesets/get-github-info'; -import { fetch as undiciFetch, Response as undiciResponse } from 'undici'; const changelogFunctions: ChangelogFunctions = { getDependencyReleaseLine: async ( @@ -95,7 +94,7 @@ async function getFixedIssueLink( prNumber: number, repo: string ): Promise { - const response = await undiciFetch( + const response = await fetch( `https://api.github.com/repos/${repo}/pulls/${prNumber}`, { method: 'GET', @@ -105,7 +104,7 @@ async function getFixedIssueLink( } ).then(data => data.json()); - const body = (response as undiciResponse).body; + const body = (response as Response).body; if (!body) { return ''; } diff --git a/repo-scripts/changelog-generator/package.json b/repo-scripts/changelog-generator/package.json index 5d791be54bf..09313c27ed6 100644 --- a/repo-scripts/changelog-generator/package.json +++ b/repo-scripts/changelog-generator/package.json @@ -19,8 +19,7 @@ "dependencies": { "@changesets/types": "3.3.0", "@changesets/get-github-info": "0.5.2", - "@types/node": "20.8.10", - "undici": "6.19.7" + "@types/node": "20.8.10" }, "license": "Apache-2.0", "devDependencies": { diff --git a/scripts/emulator-testing/emulators/emulator.ts b/scripts/emulator-testing/emulators/emulator.ts index 1295d413e4b..ba69e049ad6 100644 --- a/scripts/emulator-testing/emulators/emulator.ts +++ b/scripts/emulator-testing/emulators/emulator.ts @@ -21,7 +21,6 @@ import { ChildProcess } from 'child_process'; import * as fs from 'fs'; import * as os from 'os'; import * as path from 'path'; -import fetch from 'node-fetch'; // @ts-ignore import * as tmp from 'tmp'; @@ -51,35 +50,60 @@ export abstract class Emulator { return new Promise((resolve, reject) => { tmp.dir((err: Error | null, dir: string) => { if (err) reject(err); - console.log(`Created temporary directory at [${dir}].`); const filepath: string = path.resolve(dir, this.binaryName); - const writeStream: fs.WriteStream = fs.createWriteStream(filepath); - + const writer = fs.createWriteStream(filepath); console.log(`Downloading emulator from [${this.binaryUrl}] ...`); - fetch(this.binaryUrl).then(resp => { - resp.body - .pipe(writeStream) - .on('finish', () => { - console.log(`Saved emulator binary file to [${filepath}].`); - // Change emulator binary file permission to 'rwxr-xr-x'. - // The execute permission is required for it to be able to start - // with 'java -jar'. - fs.chmod(filepath, 0o755, err => { - if (err) reject(err); - console.log( - `Changed emulator file permissions to 'rwxr-xr-x'.` - ); - this.binaryPath = filepath; - - if (this.copyToCache()) { - console.log(`Cached emulator at ${this.cacheBinaryPath}`); + // Map the DOM's fetch Reader to node's streaming file system + // operations. We will need to access class members `binaryPath` and `copyToCache` after the + // download completes. It's a compilation error to pass `this` into the named function + // `readChunk`, so the download operation is wrapped in a promise that we wait upon. + const downloadPromise = new Promise( + (downloadComplete, downloadFailed) => { + fetch(this.binaryUrl) + .then(resp => { + if (resp.status !== 200 || resp.body === null) { + console.log('Download of emulator failed: ', resp.statusText); + downloadFailed(); + } else { + const reader = resp.body.getReader(); + reader.read().then(function readChunk({ done, value }): any { + if (done) { + downloadComplete(); + } else { + writer.write(value); + return reader.read().then(readChunk); + } + }); } - resolve(); + }) + .catch(e => { + console.log(`Download of emulator failed: ${e}`); + downloadFailed(); }); - }) - .on('error', reject); - }); + } + ); + + downloadPromise.then( + () => { + console.log('Download complete'); + // Change emulator binary file permission to 'rwxr-xr-x'. + // The execute permission is required for it to be able to start + // with 'java -jar'. + fs.chmod(filepath, 0o755, err => { + if (err) reject(err); + console.log(`Changed emulator file permissions to 'rwxr-xr-x'.`); + this.binaryPath = filepath; + if (this.copyToCache()) { + console.log(`Cached emulator at ${this.cacheBinaryPath}`); + } + resolve(); + }); + }, + () => { + reject(); + } + ); }); }); } diff --git a/yarn.lock b/yarn.lock index 477e784871e..f3fc015f9ec 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3480,14 +3480,6 @@ dependencies: "@types/node" "*" -"@types/node-fetch@2.6.4": - version "2.6.4" - resolved "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.4.tgz" - integrity sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg== - dependencies: - "@types/node" "*" - form-data "^3.0.0" - "@types/node@*", "@types/node@>=10.0.0", "@types/node@^12.7.1": version "12.20.50" resolved "https://registry.npmjs.org/@types/node/-/node-12.20.50.tgz" @@ -8512,15 +8504,6 @@ form-data@^2.5.0: combined-stream "^1.0.6" mime-types "^2.1.12" -form-data@^3.0.0: - version "3.0.1" - resolved "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz" - integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.8" - mime-types "^2.1.12" - form-data@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz" @@ -12852,13 +12835,6 @@ node-emoji@^1.11.0: dependencies: lodash "^4.17.21" -node-fetch@2.6.7, node-fetch@^2.6.7: - version "2.6.7" - resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz" - integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== - dependencies: - whatwg-url "^5.0.0" - node-fetch@^2.5.0, node-fetch@^2.6.1: version "2.6.5" resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.5.tgz" @@ -12866,6 +12842,13 @@ node-fetch@^2.5.0, node-fetch@^2.6.1: dependencies: whatwg-url "^5.0.0" +node-fetch@^2.6.7: + version "2.6.7" + resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== + dependencies: + whatwg-url "^5.0.0" + node-forge@^0.10.0: version "0.10.0" resolved "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz" @@ -17388,11 +17371,6 @@ undici-types@~5.26.4: resolved "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== -undici@6.19.7: - version "6.19.7" - resolved "https://registry.npmjs.org/undici/-/undici-6.19.7.tgz#7d4cf26dc689838aa8b6753a3c5c4288fc1e0216" - integrity sha512-HR3W/bMGPSr90i8AAp2C4DM3wChFdJPLrWYpIS++LxS8K+W535qftjt+4MyjNYHeWabMj1nvtmLIi7l++iq91A== - unicode-canonical-property-names-ecmascript@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz"