diff --git a/src/SignalR/clients/ts/signalr/package.json b/src/SignalR/clients/ts/signalr/package.json index db9d0bd3cade..3a4f43382c3a 100644 --- a/src/SignalR/clients/ts/signalr/package.json +++ b/src/SignalR/clients/ts/signalr/package.json @@ -59,14 +59,5 @@ }, "resolutions": { "ansi-regex": "5.0.1" - }, - "browser": { - "./src/DynamicImports.ts": "./src/DynamicImports.browser.ts", - "abort-controller": false, - "eventsource": false, - "fetch-cookie": false, - "node-fetch": false, - "ws": false, - "tough-cookie": false } } diff --git a/src/SignalR/clients/ts/signalr/src/DynamicImports.browser.ts b/src/SignalR/clients/ts/signalr/src/DynamicImports.browser.ts deleted file mode 100644 index 376783f4a4d6..000000000000 --- a/src/SignalR/clients/ts/signalr/src/DynamicImports.browser.ts +++ /dev/null @@ -1,22 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/** @private */ -export function configureFetch(): boolean { - return false; -} - -/** @private */ -export function configureAbortController(): boolean { - return false; -} - -/** @private */ -export function getWS(): any { - throw new Error("Trying to import 'ws' in the browser."); -} - -/** @private */ -export function getEventSource(): any { - throw new Error("Trying to import 'eventsource' in the browser."); -} \ No newline at end of file diff --git a/src/SignalR/clients/ts/signalr/src/DynamicImports.ts b/src/SignalR/clients/ts/signalr/src/DynamicImports.ts deleted file mode 100644 index 8ae470578a54..000000000000 --- a/src/SignalR/clients/ts/signalr/src/DynamicImports.ts +++ /dev/null @@ -1,54 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -// @ts-ignore: This will be removed from built files and is here to make the types available during dev work -import { CookieJar } from "@types/tough-cookie"; -import { Platform } from "./Utils"; - -/** @private */ -export function configureFetch(obj: { _fetchType?: (input: RequestInfo, init?: RequestInit) => Promise, - _jar?: CookieJar }): boolean -{ - // Node added a fetch implementation to the global scope starting in v18. - // We need to add a cookie jar in node to be able to share cookies with WebSocket - if (typeof fetch === "undefined" || Platform.isNode) { - // Cookies aren't automatically handled in Node so we need to add a CookieJar to preserve cookies across requests - // eslint-disable-next-line @typescript-eslint/no-var-requires - obj._jar = new (require("tough-cookie")).CookieJar(); - - if (typeof fetch === "undefined") { - // eslint-disable-next-line @typescript-eslint/no-var-requires - obj._fetchType = require("node-fetch"); - } else { - // Use fetch from Node if available - obj._fetchType = fetch; - } - - // node-fetch doesn't have a nice API for getting and setting cookies - // fetch-cookie will wrap a fetch implementation with a default CookieJar or a provided one - // eslint-disable-next-line @typescript-eslint/no-var-requires - obj._fetchType = require("fetch-cookie")(obj._fetchType, obj._jar); - return true; - } - return false; -} - -/** @private */ -export function configureAbortController(obj: { _abortControllerType: { prototype: AbortController, new(): AbortController } }): boolean { - if (typeof AbortController === "undefined") { - // Node needs EventListener methods on AbortController which our custom polyfill doesn't provide - obj._abortControllerType = require("abort-controller"); - return true; - } - return false; -} - -/** @private */ -export function getWS(): any { - return require("ws"); -} - -/** @private */ -export function getEventSource(): any { - return require("eventsource"); -} \ No newline at end of file diff --git a/src/SignalR/clients/ts/signalr/src/FetchHttpClient.ts b/src/SignalR/clients/ts/signalr/src/FetchHttpClient.ts index 9b26e98c3a78..d6a94fc10239 100644 --- a/src/SignalR/clients/ts/signalr/src/FetchHttpClient.ts +++ b/src/SignalR/clients/ts/signalr/src/FetchHttpClient.ts @@ -8,7 +8,6 @@ import { AbortError, HttpError, TimeoutError } from "./Errors"; import { HttpClient, HttpRequest, HttpResponse } from "./HttpClient"; import { ILogger, LogLevel } from "./ILogger"; import { Platform, getGlobalThis, isArrayBuffer } from "./Utils"; -import { configureAbortController, configureFetch } from "./DynamicImports"; export class FetchHttpClient extends HttpClient { private readonly _abortControllerType: { prototype: AbortController, new(): AbortController }; @@ -21,19 +20,38 @@ export class FetchHttpClient extends HttpClient { super(); this._logger = logger; - // This is how you do "reference" arguments - const fetchObj = { _fetchType: undefined, _jar: undefined }; - if (configureFetch(fetchObj)) { - this._fetchType = fetchObj._fetchType!; - this._jar = fetchObj._jar; + // Node added a fetch implementation to the global scope starting in v18. + // We need to add a cookie jar in node to be able to share cookies with WebSocket + if (typeof fetch === "undefined" || Platform.isNode) { + // In order to ignore the dynamic require in webpack builds we need to do this magic + // @ts-ignore: TS doesn't know about these names + const requireFunc = typeof __webpack_require__ === "function" ? __non_webpack_require__ : require; + + // Cookies aren't automatically handled in Node so we need to add a CookieJar to preserve cookies across requests + this._jar = new (requireFunc("tough-cookie")).CookieJar(); + + if (typeof fetch === "undefined") { + this._fetchType = requireFunc("node-fetch"); + } else { + // Use fetch from Node if available + this._fetchType = fetch; + } + + // node-fetch doesn't have a nice API for getting and setting cookies + // fetch-cookie will wrap a fetch implementation with a default CookieJar or a provided one + this._fetchType = requireFunc("fetch-cookie")(this._fetchType, this._jar); } else { this._fetchType = fetch.bind(getGlobalThis()); } + if (typeof AbortController === "undefined") { + // In order to ignore the dynamic require in webpack builds we need to do this magic + // @ts-ignore: TS doesn't know about these names + const requireFunc = typeof __webpack_require__ === "function" ? __non_webpack_require__ : require; - this._abortControllerType = AbortController; - const abortObj = { _abortControllerType: this._abortControllerType }; - if (configureAbortController(abortObj)) { - this._abortControllerType = abortObj._abortControllerType; + // Node needs EventListener methods on AbortController which our custom polyfill doesn't provide + this._abortControllerType = requireFunc("abort-controller"); + } else { + this._abortControllerType = AbortController; } } diff --git a/src/SignalR/clients/ts/signalr/src/HttpConnection.ts b/src/SignalR/clients/ts/signalr/src/HttpConnection.ts index 3e48a83d61f4..f8397f4d65b5 100644 --- a/src/SignalR/clients/ts/signalr/src/HttpConnection.ts +++ b/src/SignalR/clients/ts/signalr/src/HttpConnection.ts @@ -3,7 +3,6 @@ import { AccessTokenHttpClient } from "./AccessTokenHttpClient"; import { DefaultHttpClient } from "./DefaultHttpClient"; -import { getEventSource, getWS } from "./DynamicImports"; import { AggregateErrors, DisabledTransportError, FailedToNegotiateWithServerError, FailedToStartTransportError, HttpError, UnsupportedTransportError, AbortError } from "./Errors"; import { IConnection } from "./IConnection"; import { IHttpConnectionOptions } from "./IHttpConnectionOptions"; @@ -88,8 +87,11 @@ export class HttpConnection implements IConnection { let eventSourceModule: any = null; if (Platform.isNode && typeof require !== "undefined") { - webSocketModule = getWS(); - eventSourceModule = getEventSource(); + // In order to ignore the dynamic require in webpack builds we need to do this magic + // @ts-ignore: TS doesn't know about these names + const requireFunc = typeof __webpack_require__ === "function" ? __non_webpack_require__ : require; + webSocketModule = requireFunc("ws"); + eventSourceModule = requireFunc("eventsource"); } if (!Platform.isNode && typeof WebSocket !== "undefined" && !options.WebSocket) {