Skip to content

Commit 1a0cbdf

Browse files
authored
Deduplicate WebClient. (#5025)
* Add support for loading modules that only exist in async chunks. * Use WebClient in the plugins. * fixup! Use WebClient in the plugins. * fixup! Use WebClient in the plugins. * Remove node-fetch from rush-amazon-s3-build-cache-plugin. * Rush change. * fixup! Use WebClient in the plugins. * fixup! Use WebClient in the plugins. * Rush update.
1 parent 97c40b5 commit 1a0cbdf

File tree

18 files changed

+245
-317
lines changed

18 files changed

+245
-317
lines changed

build-tests/rush-amazon-s3-build-cache-plugin-integration-test/package.json

+5-6
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,16 @@
1111
"start-proxy-server": "node ./lib/startProxyServer.js"
1212
},
1313
"devDependencies": {
14+
"@microsoft/rush-lib": "workspace:*",
1415
"@rushstack/heft": "workspace:*",
15-
"local-node-rig": "workspace:*",
1616
"@rushstack/rush-amazon-s3-build-cache-plugin": "workspace:*",
1717
"@rushstack/node-core-library": "workspace:*",
18+
"@rushstack/terminal": "workspace:*",
19+
"@types/http-proxy": "~1.17.8",
1820
"@types/node": "18.17.15",
1921
"eslint": "~8.57.0",
20-
"typescript": "~5.4.2",
2122
"http-proxy": "~1.18.1",
22-
"@types/http-proxy": "~1.17.8"
23-
},
24-
"dependencies": {
25-
"@rushstack/terminal": "workspace:*"
23+
"local-node-rig": "workspace:*",
24+
"typescript": "~5.4.2"
2625
}
2726
}

build-tests/rush-amazon-s3-build-cache-plugin-integration-test/src/readObject.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// See LICENSE in the project root for license information.
33

44
import { AmazonS3Client } from '@rushstack/rush-amazon-s3-build-cache-plugin';
5-
import { WebClient } from '@rushstack/rush-amazon-s3-build-cache-plugin';
5+
import { WebClient } from '@microsoft/rush-lib/lib/utilities/WebClient';
66
import { ConsoleTerminalProvider, type ITerminal, Terminal } from '@rushstack/terminal';
77

88
const webClient: WebClient = new WebClient();

build-tests/rush-lib-declaration-paths-test/config/heft.json

+1-17
Original file line numberDiff line numberDiff line change
@@ -18,24 +18,8 @@
1818
}
1919
},
2020

21-
"copy-src-typings": {
22-
"taskPlugin": {
23-
"pluginPackage": "@rushstack/heft",
24-
"pluginName": "copy-files-plugin",
25-
"options": {
26-
"copyOperations": [
27-
{
28-
"sourcePath": "node_modules/@microsoft/rush-lib/src",
29-
"destinationFolders": ["src"],
30-
"includeGlobs": ["npm-check-typings.d.ts"]
31-
}
32-
]
33-
}
34-
}
35-
},
36-
3721
"typescript": {
38-
"taskDependencies": ["create-src", "copy-src-typings"]
22+
"taskDependencies": ["create-src"]
3923
}
4024
}
4125
}

build-tests/rush-lib-declaration-paths-test/scripts/createSrc.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ module.exports = {
2626
}
2727
}
2828

29-
const indexFileLines = ['/// <reference path="./npm-check-typings.d.ts" />', ''];
29+
const indexFileLines = [];
3030
for await (const dtsPath of collectDtsPaths(`${rushLibPath}/lib`, '@microsoft/rush-lib/lib')) {
3131
indexFileLines.push(`import '${dtsPath}';`);
3232
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"changes": [
3+
{
4+
"packageName": "@microsoft/rush",
5+
"comment": "Remove the `node-fetch` dependency from @rushstack/rush-amazon-s3-build-cache-plugin.",
6+
"type": "none"
7+
}
8+
],
9+
"packageName": "@microsoft/rush"
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"changes": [
3+
{
4+
"packageName": "@microsoft/rush",
5+
"comment": "(BREAKING API CHANGE) Remove the exported `WebClient` API from @rushstack/rush-amazon-s3-build-cache-plugin.",
6+
"type": "none"
7+
}
8+
],
9+
"packageName": "@microsoft/rush"
10+
}

common/config/subspaces/default/pnpm-lock.yaml

+6-10
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

common/reviews/api/rush-amazon-s3-build-cache-plugin.api.md

+1-41
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@
66

77
/// <reference types="node" />
88

9-
import * as fetch from 'node-fetch';
109
import type { IRushPlugin } from '@rushstack/rush-sdk';
1110
import { ITerminal } from '@rushstack/terminal';
1211
import type { RushConfiguration } from '@rushstack/rush-sdk';
1312
import type { RushSession } from '@rushstack/rush-sdk';
13+
import { WebClient } from '@rushstack/rush-sdk/lib/utilities/WebClient';
1414

1515
// @public
1616
export class AmazonS3Client {
@@ -61,22 +61,6 @@ export interface IAmazonS3Credentials {
6161
sessionToken: string | undefined;
6262
}
6363

64-
// Warning: (ae-forgotten-export) The symbol "IWebFetchOptionsBase" needs to be exported by the entry point index.d.ts
65-
//
66-
// @public
67-
export interface IGetFetchOptions extends IWebFetchOptionsBase {
68-
// (undocumented)
69-
verb: 'GET' | never;
70-
}
71-
72-
// @public
73-
export interface IPutFetchOptions extends IWebFetchOptionsBase {
74-
// (undocumented)
75-
body?: Buffer;
76-
// (undocumented)
77-
verb: 'PUT';
78-
}
79-
8064
// @public (undocumented)
8165
class RushAmazonS3BuildCachePlugin implements IRushPlugin {
8266
// (undocumented)
@@ -86,30 +70,6 @@ class RushAmazonS3BuildCachePlugin implements IRushPlugin {
8670
}
8771
export default RushAmazonS3BuildCachePlugin;
8872

89-
// @public
90-
export class WebClient {
91-
constructor();
92-
// (undocumented)
93-
accept: string | undefined;
94-
// (undocumented)
95-
addBasicAuthHeader(userName: string, password: string): void;
96-
// (undocumented)
97-
fetchAsync(url: string, options?: IGetFetchOptions | IPutFetchOptions): Promise<WebClientResponse>;
98-
// (undocumented)
99-
static mergeHeaders(target: fetch.Headers, source: fetch.Headers): void;
100-
// Warning: (ae-forgotten-export) The symbol "WebClientProxy" needs to be exported by the entry point index.d.ts
101-
//
102-
// (undocumented)
103-
proxy: WebClientProxy;
104-
// (undocumented)
105-
readonly standardHeaders: fetch.Headers;
106-
// (undocumented)
107-
userAgent: string | undefined;
108-
}
109-
110-
// @public
111-
export type WebClientResponse = fetch.Response;
112-
11373
// (No @packageDocumentation comment for this package)
11474

11575
```

libraries/rush-lib/src/utilities/WebClient.ts

+34-19
Original file line numberDiff line numberDiff line change
@@ -7,25 +7,27 @@ import * as fetch from 'node-fetch';
77
import type * as http from 'http';
88
import { Import } from '@rushstack/node-core-library';
99

10-
// ===================================================================================================================
11-
// AS A TEMPORARY WORKAROUND, THIS FILE WAS COPY+PASTED INTO THE "rush-amazon-s3-build-cache-plugin" PROJECT.
12-
// See that copy for notes.
13-
// ===================================================================================================================
14-
1510
const createHttpsProxyAgent: typeof import('https-proxy-agent') = Import.lazy('https-proxy-agent', require);
1611

1712
/**
1813
* For use with {@link WebClient}.
1914
*/
2015
export type WebClientResponse = fetch.Response;
2116

17+
/**
18+
* For use with {@link WebClient}.
19+
*/
20+
export type WebClientHeaders = fetch.Headers;
21+
// eslint-disable-next-line @typescript-eslint/no-redeclare
22+
export const WebClientHeaders: typeof fetch.Headers = fetch.Headers;
23+
2224
/**
2325
* For use with {@link WebClient}.
2426
*/
2527
export interface IWebFetchOptionsBase {
2628
timeoutMs?: number;
27-
verb?: 'GET' | 'PUT';
28-
headers?: fetch.Headers;
29+
headers?: WebClientHeaders | Record<string, string>;
30+
redirect?: fetch.RequestInit['redirect'];
2931
}
3032

3133
/**
@@ -38,8 +40,8 @@ export interface IGetFetchOptions extends IWebFetchOptionsBase {
3840
/**
3941
* For use with {@link WebClient}.
4042
*/
41-
export interface IPutFetchOptions extends IWebFetchOptionsBase {
42-
verb: 'PUT';
43+
export interface IFetchOptionsWithBody extends IWebFetchOptionsBase {
44+
verb: 'PUT' | 'POST' | 'PATCH';
4345
body?: Buffer;
4446
}
4547

@@ -56,19 +58,30 @@ export enum WebClientProxy {
5658
* A helper for issuing HTTP requests.
5759
*/
5860
export class WebClient {
61+
private static _requestFn: typeof fetch.default = fetch.default;
62+
5963
public readonly standardHeaders: fetch.Headers = new fetch.Headers();
6064

6165
public accept: string | undefined = '*/*';
6266
public userAgent: string | undefined = `rush node/${process.version} ${os.platform()} ${os.arch()}`;
6367

6468
public proxy: WebClientProxy = WebClientProxy.Detect;
6569

66-
public constructor() {}
70+
public static mockRequestFn(fn: typeof fetch.default): void {
71+
WebClient._requestFn = fn;
72+
}
73+
74+
public static resetMockRequestFn(): void {
75+
WebClient._requestFn = fetch.default;
76+
}
6777

68-
public static mergeHeaders(target: fetch.Headers, source: fetch.Headers): void {
69-
source.forEach((value, name) => {
78+
public static mergeHeaders(target: fetch.Headers, source: fetch.Headers | Record<string, string>): void {
79+
const iterator: Iterable<[string, string]> =
80+
'entries' in source && typeof source.entries === 'function' ? source.entries() : Object.entries(source);
81+
82+
for (const [name, value] of iterator) {
7083
target.set(name, value);
71-
});
84+
}
7285
}
7386

7487
public addBasicAuthHeader(userName: string, password: string): void {
@@ -80,7 +93,7 @@ export class WebClient {
8093

8194
public async fetchAsync(
8295
url: string,
83-
options?: IGetFetchOptions | IPutFetchOptions
96+
options?: IGetFetchOptions | IFetchOptionsWithBody
8497
): Promise<WebClientResponse> {
8598
const headers: fetch.Headers = new fetch.Headers();
8699

@@ -93,6 +106,7 @@ export class WebClient {
93106
if (this.userAgent) {
94107
headers.set('user-agent', this.userAgent);
95108
}
109+
96110
if (this.accept) {
97111
headers.set('accept', this.accept);
98112
}
@@ -126,13 +140,14 @@ export class WebClient {
126140
method: options?.verb,
127141
headers: headers,
128142
agent: agent,
129-
timeout: timeoutMs
143+
timeout: timeoutMs,
144+
redirect: options?.redirect
130145
};
131-
const putOptions: IPutFetchOptions | undefined = options as IPutFetchOptions | undefined;
132-
if (putOptions?.body) {
133-
requestInit.body = putOptions.body;
146+
const optionsWithBody: IFetchOptionsWithBody | undefined = options as IFetchOptionsWithBody | undefined;
147+
if (optionsWithBody?.body) {
148+
requestInit.body = optionsWithBody.body;
134149
}
135150

136-
return await fetch.default(url, requestInit);
151+
return await WebClient._requestFn(url, requestInit);
137152
}
138153
}

0 commit comments

Comments
 (0)