diff --git a/.chronus/changes/use-node-fetch-builtin-2024-3-26-17-50-57.md b/.chronus/changes/use-node-fetch-builtin-2024-3-26-17-50-57.md new file mode 100644 index 0000000000..628ffc4f73 --- /dev/null +++ b/.chronus/changes/use-node-fetch-builtin-2024-3-26-17-50-57.md @@ -0,0 +1,8 @@ +--- +# Change versionKind to one of: internal, fix, dependencies, feature, deprecation, breaking +changeKind: fix +packages: + - "@typespec/compiler" +--- + +Internals: Use node built-in `fetch` API that is now stable since node `18.13.0` diff --git a/packages/compiler/package.json b/packages/compiler/package.json index 4f46b2f020..ebcabd7de7 100644 --- a/packages/compiler/package.json +++ b/packages/compiler/package.json @@ -85,7 +85,6 @@ "@babel/code-frame": "~7.24.2", "ajv": "~8.12.0", "change-case": "~5.4.4", - "follow-redirects": "^1.15.6", "globby": "~14.0.1", "mustache": "~4.2.0", "picocolors": "~1.0.0", @@ -99,7 +98,6 @@ }, "devDependencies": { "@types/babel__code-frame": "~7.0.6", - "@types/follow-redirects": "^1.14.4", "@types/mustache": "~4.2.5", "@types/node": "~18.11.19", "@types/prompts": "~2.4.9", diff --git a/packages/compiler/src/core/fetch.ts b/packages/compiler/src/core/fetch.ts deleted file mode 100644 index dbf26a8015..0000000000 --- a/packages/compiler/src/core/fetch.ts +++ /dev/null @@ -1,47 +0,0 @@ -import followRedirects from "follow-redirects"; -import { compilerAssert } from "./diagnostics.js"; - -export interface FetchResponse { - readonly url: string; - text(): Promise; -} -/** - * Basic implementation of fetch to fit our needs. - * We are not using `node-fetch` due to a vulnerability and an issue in `<=3.2.8` the typing if `version >=3.2.9` - * Node built-in fetch is still experimental as of node 19 - */ -export function fetch(uri: string): Promise { - return new Promise((resolve, reject) => { - request(uri, resolve, reject); - }); - - function request(uri: string, resolve: (arg: FetchResponse) => void, reject: (arg: any) => void) { - const url = new URL(uri); - const protocol = - url.protocol === "https:" - ? followRedirects.https - : url.protocol === "http:" - ? followRedirects.http - : undefined; - compilerAssert(protocol, `Protocol '${url.protocol}' is not supported`); - - protocol - .get(url, (res) => { - let data = ""; - - res.on("data", (chunk) => { - data += chunk; - }); - - res.on("end", () => { - resolve({ - url: url.href, - text: () => Promise.resolve(data), - }); - }); - }) - .on("error", (err) => { - reject(err); - }); - } -} diff --git a/packages/compiler/src/core/node-host.ts b/packages/compiler/src/core/node-host.ts index 4eee44f8f3..34d8998c3b 100644 --- a/packages/compiler/src/core/node-host.ts +++ b/packages/compiler/src/core/node-host.ts @@ -2,7 +2,6 @@ import { realpath } from "fs"; import { mkdir, readdir, readFile, rm, stat, writeFile } from "fs/promises"; import { fileURLToPath, pathToFileURL } from "url"; import { findProjectRoot } from "../utils/misc.js"; -import { fetch } from "./fetch.js"; import { createConsoleSink } from "./logger/index.js"; import { joinPaths } from "./path-utils.js"; import { createSourceFile, getSourceFileKindFromExt } from "./source-file.js"; @@ -16,7 +15,7 @@ export const CompilerPackageRoot = (await findProjectRoot(stat, fileURLToPath(im */ export const NodeHost: CompilerHost = { readUrl: async (url: string) => { - const response = await fetch(url); + const response = await fetch(url, { redirect: "follow" }); const text = await response.text(); return createSourceFile(text, response.url); }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cb59457fe5..a4c32c6ff8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -225,9 +225,6 @@ importers: change-case: specifier: ~5.4.4 version: 5.4.4 - follow-redirects: - specifier: ^1.15.6 - version: 1.15.6 globby: specifier: ~14.0.1 version: 14.0.1 @@ -262,9 +259,6 @@ importers: '@types/babel__code-frame': specifier: ~7.0.6 version: 7.0.6 - '@types/follow-redirects': - specifier: ^1.14.4 - version: 1.14.4 '@types/mustache': specifier: ~4.2.5 version: 4.2.5 @@ -7722,12 +7716,6 @@ packages: '@types/serve-static': 1.15.5 dev: false - /@types/follow-redirects@1.14.4: - resolution: {integrity: sha512-GWXfsD0Jc1RWiFmMuMFCpXMzi9L7oPDVwxUnZdg89kDNnqsRfUKXEtUYtA98A6lig1WXH/CYY/fvPW9HuN5fTA==} - dependencies: - '@types/node': 18.11.19 - dev: true - /@types/gtag.js@0.0.12: resolution: {integrity: sha512-YQV9bUsemkzG81Ea295/nF/5GijnD2Af7QhEofh7xu+kvCN6RdodgNwwGWXB5GMI3NoyvQo0odNctoH/qLMIpg==} dev: false