diff --git a/README.md b/README.md index 8fb486d4..01aa17f6 100644 --- a/README.md +++ b/README.md @@ -123,17 +123,17 @@ locations are: * MacOS: `~/Library/Caches/electron/` * Windows: `%LOCALAPPDATA%/electron/Cache` or `~/AppData/Local/electron/Cache/` -By default, the module uses [`got`](https://github.com/sindresorhus/got) as the -downloader. As a result, you can use the same [options](https://github.com/sindresorhus/got#options) -via `downloadOptions`. +By default, the module uses the built-in [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) +as the downloader. As a result, you can pass [`RequestInit`](https://developer.mozilla.org/en-US/docs/Web/API/RequestInit) +options via `downloadOptions`. ### Progress Bar By default, a progress bar is shown when downloading an artifact for more than 30 seconds. To disable, set the `ELECTRON_GET_NO_PROGRESS` environment variable to any non-empty value, or set `quiet` to `true` in `downloadOptions`. If you need to monitor progress yourself via the API, set -`getProgressCallback` in `downloadOptions`, which has the same function signature as `got`'s -[`downloadProgress` event callback](https://github.com/sindresorhus/got#ondownloadprogress-progress). +`getProgressCallback` in `downloadOptions`, which receives a `Progress` object with `transferred`, +`total`, and `percent` properties. ### Proxies diff --git a/package.json b/package.json index 9e14074f..f32a781b 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,6 @@ "dependencies": { "debug": "^4.1.1", "env-paths": "^3.0.0", - "got": "^14.4.5", "graceful-fs": "^4.2.11", "progress": "^2.0.3", "semver": "^7.6.3", @@ -79,7 +78,7 @@ "release" ], "optionalDependencies": { - "global-agent": "^3.0.0" + "undici": "^7.24.4" }, "packageManager": "yarn@4.10.3+sha512.c38cafb5c7bb273f3926d04e55e1d8c9dfa7d9c3ea1f36a4868fa028b9e5f72298f0b7f401ad5eb921749eb012eb1c3bb74bf7503df3ee43fd600d14a018266f" } diff --git a/src/Downloader.ts b/src/Downloader.ts index f0cdd878..346514ab 100644 --- a/src/Downloader.ts +++ b/src/Downloader.ts @@ -1,6 +1,6 @@ /** * Generic interface for the artifact downloader library. - * The default implementation is {@link GotDownloader}, + * The default implementation is {@link FetchDownloader}, * but any custom downloader can be passed to `@electron/get` via * the {@link ElectronDownloadRequestOptions.downloader} option. * diff --git a/src/FetchDownloader.ts b/src/FetchDownloader.ts new file mode 100644 index 00000000..1fb25e5a --- /dev/null +++ b/src/FetchDownloader.ts @@ -0,0 +1,129 @@ +import fs from 'graceful-fs'; + +import path from 'node:path'; +import ProgressBar from 'progress'; + +import { Downloader } from './Downloader.js'; +import { pipeline } from 'node:stream/promises'; +import { Readable } from 'node:stream'; + +const PROGRESS_BAR_DELAY_IN_SECONDS = 30; + +/** + * @category Downloader + */ +export interface Progress { + /** Bytes downloaded so far. */ + transferred: number; + /** Total bytes to download, or `null` if the response had no `Content-Length` header. */ + total: number | null; + /** + * Ratio of `transferred` to `total` between 0 and 1. + * If `total` is unknown, this is 0 until the download completes, then 1. + */ + percent: number; +} + +/** + * @category Downloader + */ +export class HTTPError extends Error { + constructor(public readonly response: Response) { + super(`Response code ${response.status} (${response.statusText}) for ${response.url}`); + this.name = 'HTTPError'; + } +} + +/** + * @category Downloader + * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/RequestInit | `RequestInit`} for possible keys/values. + */ +export type FetchDownloaderOptions = RequestInit & { + /** Called on each chunk with the current download {@link Progress}. */ + getProgressCallback?: (progress: Progress) => Promise; + /** + * Disables the console progress bar. Setting the `ELECTRON_GET_NO_PROGRESS` + * environment variable to a non-empty value also does this. + */ + quiet?: boolean; +}; + +/** + * Default {@link Downloader} implemented with the built-in + * {@link https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API | Fetch API}. + * @category Downloader + */ +export class FetchDownloader implements Downloader { + async download( + url: string, + targetFilePath: string, + options: FetchDownloaderOptions = {}, + ): Promise { + const { quiet, getProgressCallback, ...fetchOptions } = options; + let downloadCompleted = false; + let bar: ProgressBar | undefined; + let progressPercent: number; + let timeout: NodeJS.Timeout | undefined = undefined; + await fs.promises.mkdir(path.dirname(targetFilePath), { recursive: true }); + + if (!quiet && !process.env.ELECTRON_GET_NO_PROGRESS) { + const start = new Date(); + timeout = setTimeout(() => { + if (!downloadCompleted) { + bar = new ProgressBar( + `Downloading ${path.basename(url)}: [:bar] :percent ETA: :eta seconds `, + { + curr: progressPercent, + total: 100, + }, + ); + // https://github.com/visionmedia/node-progress/issues/159 + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (bar as any).start = start; + } + }, PROGRESS_BAR_DELAY_IN_SECONDS * 1000); + } + try { + const response = await fetch(url, fetchOptions); + if (!response.ok) { + throw new HTTPError(response); + } + if (!response.body) { + throw new Error('Response body is empty'); + } + + const contentLength = response.headers.get('content-length'); + const total = contentLength ? parseInt(contentLength, 10) : null; + let transferred = 0; + + const onProgress = (percent: number): void => { + progressPercent = percent; + if (bar) { + bar.update(percent); + } + if (getProgressCallback) { + void getProgressCallback({ transferred, total, percent }); + } + }; + + await pipeline( + Readable.fromWeb(response.body), + async function* (source) { + for await (const chunk of source) { + transferred += chunk.length; + onProgress(total ? transferred / total : 0); + yield chunk; + } + }, + fs.createWriteStream(targetFilePath), + ); + + onProgress(1); + } finally { + downloadCompleted = true; + if (timeout) { + clearTimeout(timeout); + } + } + } +} diff --git a/src/GotDownloader.ts b/src/GotDownloader.ts deleted file mode 100644 index 544733be..00000000 --- a/src/GotDownloader.ts +++ /dev/null @@ -1,93 +0,0 @@ -import got, { HTTPError, Progress as GotProgress, Options as GotOptions, Progress } from 'got'; -import fs from 'graceful-fs'; - -import path from 'node:path'; -import ProgressBar from 'progress'; - -import { Downloader } from './Downloader.js'; -import { pipeline } from 'node:stream/promises'; - -const PROGRESS_BAR_DELAY_IN_SECONDS = 30; - -/** - * Options for the default [`got`](https://github.com/sindresorhus/got) Downloader implementation. - * - * @category Downloader - * @see {@link https://github.com/sindresorhus/got/tree/v11.8.5?tab=readme-ov-file#options | `got#options`} for possible keys/values. - */ -export type GotDownloaderOptions = GotOptions & { isStream?: true } & { - /** - * if defined, triggers every time `got`'s - * {@link https://github.com/sindresorhus/got/tree/v11.8.5?tab=readme-ov-file#downloadprogress | `downloadProgress``} event callback is triggered. - */ - getProgressCallback?: (progress: GotProgress) => Promise; - /** - * if `true`, disables the console progress bar (setting the `ELECTRON_GET_NO_PROGRESS` - * environment variable to a non-empty value also does this). - */ - quiet?: boolean; -}; - -/** - * Default {@link Downloader} implemented with {@link https://npmjs.com/package/got | `got`}. - * @category Downloader - */ -export class GotDownloader implements Downloader { - async download( - url: string, - targetFilePath: string, - options?: Partial, - ): Promise { - if (!options) { - options = {}; - } - const { quiet, getProgressCallback, ...gotOptions } = options; - let downloadCompleted = false; - let bar: ProgressBar | undefined; - let progressPercent: number; - let timeout: NodeJS.Timeout | undefined = undefined; - await fs.promises.mkdir(path.dirname(targetFilePath), { recursive: true }); - const writeStream = fs.createWriteStream(targetFilePath); - - if (!quiet && !process.env.ELECTRON_GET_NO_PROGRESS) { - const start = new Date(); - timeout = setTimeout(() => { - if (!downloadCompleted) { - bar = new ProgressBar( - `Downloading ${path.basename(url)}: [:bar] :percent ETA: :eta seconds `, - { - curr: progressPercent, - total: 100, - }, - ); - // https://github.com/visionmedia/node-progress/issues/159 - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (bar as any).start = start; - } - }, PROGRESS_BAR_DELAY_IN_SECONDS * 1000); - } - const downloadStream = got.stream(url, gotOptions); - downloadStream.on('downloadProgress', async (progress: Progress) => { - progressPercent = progress.percent; - if (bar) { - bar.update(progress.percent); - } - if (getProgressCallback) { - await getProgressCallback(progress); - } - }); - try { - await pipeline(downloadStream, writeStream); - } catch (error) { - if (error instanceof HTTPError && (error as HTTPError).response.statusCode === 404) { - error.message += ` for ${(error as HTTPError).response.url}`; - } - throw error; - } finally { - downloadCompleted = true; - if (timeout) { - clearTimeout(timeout); - } - } - } -} diff --git a/src/downloader-resolver.ts b/src/downloader-resolver.ts index c448da60..6c1106d3 100644 --- a/src/downloader-resolver.ts +++ b/src/downloader-resolver.ts @@ -1,12 +1,7 @@ import { DownloadOptions } from './types.js'; import { Downloader } from './Downloader.js'; - -// TODO: Resolve the downloader or default to GotDownloader -// Current thoughts are a dot-file traversal for something like -// ".electron.downloader" which would be a text file with the name of the -// npm module to import() and use as the downloader -import { GotDownloader } from './GotDownloader.js'; +import { FetchDownloader } from './FetchDownloader.js'; export async function getDownloaderForSystem(): Promise> { - return new GotDownloader(); + return new FetchDownloader(); } diff --git a/src/proxy.ts b/src/proxy.ts index 732e3953..92f11464 100644 --- a/src/proxy.ts +++ b/src/proxy.ts @@ -1,7 +1,6 @@ import { createRequire } from 'node:module'; import debug from 'debug'; -import { getEnv, setEnv } from './utils.js'; const d = debug('@electron/get:proxy'); const require = createRequire(import.meta.url); @@ -13,31 +12,18 @@ const require = createRequire(import.meta.url); * If the `ELECTRON_GET_USE_PROXY` environment variable is set to `true`, this function will be * called automatically for `@electron/get` requests. * + * Supported environment variables are `HTTP_PROXY`, `HTTPS_PROXY`, and `NO_PROXY`. + * * @category Utility - * @see {@link https://github.com/gajus/global-agent?tab=readme-ov-file#environment-variables | `global-agent`} + * @see {@link https://undici.nodejs.org/#/docs/api/EnvHttpProxyAgent | `EnvHttpProxyAgent`} * documentation for available environment variables. - * - * @example - * ```sh - * export GLOBAL_AGENT_HTTPS_PROXY="$HTTPS_PROXY" - * ``` */ export function initializeProxy(): void { try { - // See: https://github.com/electron/get/pull/214#discussion_r798845713 - const env = getEnv('GLOBAL_AGENT_'); - - setEnv('GLOBAL_AGENT_HTTP_PROXY', env('HTTP_PROXY')); - setEnv('GLOBAL_AGENT_HTTPS_PROXY', env('HTTPS_PROXY')); - setEnv('GLOBAL_AGENT_NO_PROXY', env('NO_PROXY')); - - /** - * TODO: replace global-agent with a hpagent. @BlackHole1 - * https://github.com/sindresorhus/got/blob/HEAD/documentation/tips.md#proxying - */ // eslint-disable-next-line @typescript-eslint/no-require-imports - require('global-agent').bootstrap(); + const { EnvHttpProxyAgent, setGlobalDispatcher } = require('undici'); + setGlobalDispatcher(new EnvHttpProxyAgent()); } catch (e) { - d('Could not load either proxy modules, built-in proxy support not available:', e); + d('Could not load undici, built-in proxy support not available:', e); } } diff --git a/src/types.ts b/src/types.ts index 4e041c5c..5a97b977 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,7 +1,7 @@ import { Downloader } from './Downloader.js'; -import { GotDownloader, GotDownloaderOptions } from './GotDownloader.js'; +import { FetchDownloader, FetchDownloaderOptions, HTTPError, Progress } from './FetchDownloader.js'; -export { Downloader, GotDownloader, GotDownloaderOptions }; +export { Downloader, FetchDownloader, FetchDownloaderOptions, HTTPError, Progress }; /** * Custom downloaders can implement any set of options. @@ -140,7 +140,7 @@ export interface ElectronDownloadRequestOptions { /** * Options passed to the downloader module. * - * @see {@link GotDownloaderOptions} for options for the default {@link GotDownloader}. + * @see {@link FetchDownloaderOptions} for options for the default {@link FetchDownloader}. */ downloadOptions?: DownloadOptions; /** @@ -149,7 +149,7 @@ export interface ElectronDownloadRequestOptions { mirrorOptions?: MirrorOptions; /** * A custom {@link Downloader} class used to download artifacts. Defaults to the - * built-in {@link GotDownloader}. + * built-in {@link FetchDownloader}. */ downloader?: Downloader; /** diff --git a/test/GotDownloader.network.spec.ts b/test/FetchDownloader.network.spec.ts similarity index 88% rename from test/GotDownloader.network.spec.ts rename to test/FetchDownloader.network.spec.ts index 42148691..44381b27 100644 --- a/test/GotDownloader.network.spec.ts +++ b/test/FetchDownloader.network.spec.ts @@ -4,14 +4,19 @@ import util from 'node:util'; import { describe, expect, it, vi } from 'vitest'; -import { GotDownloader } from '../src/GotDownloader'; +import { FetchDownloader } from '../src/FetchDownloader'; +import { initializeProxy } from '../src/proxy'; import { TempDirCleanUpMode, withTempDirectory } from '../src/utils'; import { PathLike } from 'node:fs'; -describe('GotDownloader', () => { +if (process.env.ELECTRON_GET_USE_PROXY) { + initializeProxy(); +} + +describe('FetchDownloader', () => { describe('download()', () => { it('should download a remote file to the given file path', async () => { - const downloader = new GotDownloader(); + const downloader = new FetchDownloader(); let progressCallbackCalled = false; await withTempDirectory(async (dir) => { const testFile = path.resolve(dir, 'test.txt'); @@ -33,7 +38,7 @@ describe('GotDownloader', () => { }); it('should throw an error if the file does not exist', async () => { - const downloader = new GotDownloader(); + const downloader = new FetchDownloader(); await withTempDirectory(async (dir) => { const testFile = path.resolve(dir, 'test.txt'); const url = 'https://github.com/electron/electron/releases/download/v2.0.18/bad.file'; @@ -43,7 +48,7 @@ describe('GotDownloader', () => { }); it('should throw an error if the file write stream fails', async () => { - const downloader = new GotDownloader(); + const downloader = new FetchDownloader(); const createWriteStream = fs.createWriteStream; const spy = vi.spyOn(fs, 'createWriteStream'); spy.mockImplementationOnce((path: PathLike) => { @@ -63,7 +68,7 @@ describe('GotDownloader', () => { }); it('should download to a deep uncreated path', async () => { - const downloader = new GotDownloader(); + const downloader = new FetchDownloader(); await withTempDirectory(async (dir) => { const testFile = path.resolve(dir, 'f', 'b', 'test.txt'); expect(fs.existsSync(testFile)).toEqual(false); diff --git a/test/GotDownloader.spec.ts b/test/FetchDownloader.spec.ts similarity index 56% rename from test/GotDownloader.spec.ts rename to test/FetchDownloader.spec.ts index 5948212f..08dd85a9 100644 --- a/test/GotDownloader.spec.ts +++ b/test/FetchDownloader.spec.ts @@ -2,22 +2,15 @@ import fs from 'graceful-fs'; import os from 'node:os'; import path from 'node:path'; -import { PathLike } from 'node:fs'; import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; -import { GotDownloader } from '../src/GotDownloader'; +import { FetchDownloader } from '../src/FetchDownloader'; -async function flushMicrotasks(): Promise { - for (let i = 0; i < 10; i++) { - await Promise.resolve(); - } -} - -describe('GotDownloader', () => { +describe('FetchDownloader', () => { let tmpDir: string; beforeEach(async () => { - tmpDir = await fs.promises.mkdtemp(path.resolve(os.tmpdir(), 'got-spec-')); + tmpDir = await fs.promises.mkdtemp(path.resolve(os.tmpdir(), 'fetch-spec-')); }); afterEach(async () => { @@ -30,71 +23,48 @@ describe('GotDownloader', () => { describe('progress bar suppression', () => { it('should not schedule a progress bar timer when quiet: true', async () => { vi.spyOn(fs.promises, 'mkdir').mockResolvedValue(undefined); + vi.spyOn(globalThis, 'fetch').mockRejectedValue(new Error('mocked')); vi.useFakeTimers(); - const downloader = new GotDownloader(); + const downloader = new FetchDownloader(); const target = path.resolve(tmpDir, 'out.txt'); - const p = downloader.download('http://127.0.0.1:1/nope', target, { quiet: true }); - p.catch(() => { + await downloader.download(target, target, { quiet: true }).catch(() => { /* ignore */ }); - await flushMicrotasks(); - expect(vi.getTimerCount()).toBe(0); - - vi.useRealTimers(); - await p.catch(() => { - /* ignore */ - }); }); it('should not schedule a progress bar timer when ELECTRON_GET_NO_PROGRESS is set', async () => { process.env.ELECTRON_GET_NO_PROGRESS = '1'; vi.spyOn(fs.promises, 'mkdir').mockResolvedValue(undefined); + vi.spyOn(globalThis, 'fetch').mockRejectedValue(new Error('mocked')); vi.useFakeTimers(); - const downloader = new GotDownloader(); + const downloader = new FetchDownloader(); const target = path.resolve(tmpDir, 'out.txt'); - const p = downloader.download('http://127.0.0.1:1/nope', target); - p.catch(() => { + await downloader.download(target, target).catch(() => { /* ignore */ }); - await flushMicrotasks(); - expect(vi.getTimerCount()).toBe(0); - - vi.useRealTimers(); - await p.catch(() => { - /* ignore */ - }); }); }); describe('timer cleanup', () => { it('should clear the progress timer even when the download fails', async () => { vi.spyOn(fs.promises, 'mkdir').mockResolvedValue(undefined); - - const realCreateWriteStream = fs.createWriteStream; - vi.spyOn(fs, 'createWriteStream').mockImplementationOnce((p: PathLike) => { - const stream = realCreateWriteStream(p); - setImmediate(() => stream.emit('error', new Error('boom'))); - return stream; - }); - + vi.spyOn(globalThis, 'fetch').mockRejectedValue(new Error('boom')); vi.useFakeTimers({ toFake: ['setTimeout', 'clearTimeout'] }); - const downloader = new GotDownloader(); + const downloader = new FetchDownloader(); const target = path.resolve(tmpDir, 'out.txt'); - await expect(downloader.download('http://127.0.0.1:1/nope', target)).rejects.toThrow(); + await expect(downloader.download(target, target)).rejects.toThrow('boom'); expect(vi.getTimerCount()).toBe(0); - - vi.clearAllTimers(); }); }); }); diff --git a/test/__snapshots__/GotDownloader.network.spec.ts.snap b/test/__snapshots__/FetchDownloader.network.spec.ts.snap similarity index 98% rename from test/__snapshots__/GotDownloader.network.spec.ts.snap rename to test/__snapshots__/FetchDownloader.network.spec.ts.snap index 892802f2..838623b1 100644 --- a/test/__snapshots__/GotDownloader.network.spec.ts.snap +++ b/test/__snapshots__/FetchDownloader.network.spec.ts.snap @@ -1,6 +1,6 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`GotDownloader > download() > should download a remote file to the given file path 1`] = ` +exports[`FetchDownloader > download() > should download a remote file to the given file path 1`] = ` "d186456c8e44155298521aafc5e270875c6cde41bbd3c19ce38ae53f1d98f284 *chromedriver-v2.0.18-darwin-x64.zip dfb244c4347481a526567418f78a0fb6b9ccff6205a55f51225cfe4d1796b0d9 *chromedriver-v2.0.18-linux-arm.zip 516981ca6f7465dba55228df9ba30b7e0566a3eec694e5a2cc2fbe58a41ff006 *chromedriver-v2.0.18-linux-arm64.zip @@ -58,7 +58,7 @@ f83f0433d0e2f4d62db59892d4105c5693242da867cb76f3ec42ce020868bf98 *mksnapshot-v2. " `; -exports[`GotDownloader > download() > should download to a deep uncreated path 1`] = ` +exports[`FetchDownloader > download() > should download to a deep uncreated path 1`] = ` "06fbdc5cdebf63b6fc579092d572878304125286b0db3ed0d6b1d506dc75e286 *chromedriver-v2.0.1-darwin-x64.zip 7347204e847fd7403dfac7de0a92a345932cc99a60b3279ca9e6d307483a190a *chromedriver-v2.0.1-linux-arm.zip 0a5807a4f26bc42de70d008e6ec775fed54a66f55d517b68071b801c3b306b4c *chromedriver-v2.0.1-linux-arm64.zip diff --git a/typedoc.json b/typedoc.json index 0daca6a7..71464384 100644 --- a/typedoc.json +++ b/typedoc.json @@ -2,12 +2,6 @@ "$schema": "https://typedoc.org/schema.json", "entryPoints": ["src/index.ts"], "excludeInternal": true, - "externalSymbolLinkMappings": { - "got": { - "Options": "https://github.com/sindresorhus/got/tree/v11.8.5?tab=readme-ov-file#options", - "Progress": "https://github.com/sindresorhus/got/tree/v11.8.5?tab=readme-ov-file#downloadprogress" - } - }, "navigation": true, "categoryOrder": ["Download Electron", "Download Artifact", "Downloader", "Utility", "*"], "categorizeByGroup": false, diff --git a/yarn.lock b/yarn.lock index beca663a..d8c1392f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -76,8 +76,6 @@ __metadata: eslint: "npm:^8.57.0" eslint-config-prettier: "npm:^6.15.0" eslint-plugin-import: "npm:^2.31.0" - global-agent: "npm:^3.0.0" - got: "npm:^14.4.5" graceful-fs: "npm:^4.2.11" husky: "npm:^9.1.7" lint-staged: "npm:^16.2.7" @@ -87,9 +85,10 @@ __metadata: sumchecker: "npm:^3.0.1" typedoc: "npm:~0.25.13" typescript: "npm:~5.4.5" + undici: "npm:^7.24.4" vitest: "npm:^3.0.5" dependenciesMeta: - global-agent: + undici: optional: true languageName: unknown linkType: soft @@ -653,29 +652,6 @@ __metadata: languageName: node linkType: hard -"@sec-ant/readable-stream@npm:^0.4.1": - version: 0.4.1 - resolution: "@sec-ant/readable-stream@npm:0.4.1" - checksum: 10c0/64e9e9cf161e848067a5bf60cdc04d18495dc28bb63a8d9f8993e4dd99b91ad34e4b563c85de17d91ffb177ec17a0664991d2e115f6543e73236a906068987af - languageName: node - linkType: hard - -"@sindresorhus/is@npm:^7.0.1": - version: 7.0.1 - resolution: "@sindresorhus/is@npm:7.0.1" - checksum: 10c0/6d43a916d70d9b64066394c272883869b22faf21f4748aaf399c1b691ea704ea607d1668ff2eb5704e5be8809c4a7faafe16be048ce5e1a2ba6e8928b8e3461c - languageName: node - linkType: hard - -"@szmarczak/http-timer@npm:^5.0.1": - version: 5.0.1 - resolution: "@szmarczak/http-timer@npm:5.0.1" - dependencies: - defer-to-connect: "npm:^2.0.1" - checksum: 10c0/4629d2fbb2ea67c2e9dc03af235c0991c79ebdddcbc19aed5d5732fb29ce01c13331e9b1a491584b9069bd6ecde6581dcbf871f11b7eefdebbab34de6cf2197e - languageName: node - linkType: hard - "@tsconfig/node22@npm:^22.0.0": version: 22.0.0 resolution: "@tsconfig/node22@npm:22.0.0" @@ -713,13 +689,6 @@ __metadata: languageName: node linkType: hard -"@types/http-cache-semantics@npm:^4.0.4": - version: 4.0.4 - resolution: "@types/http-cache-semantics@npm:4.0.4" - checksum: 10c0/51b72568b4b2863e0fe8d6ce8aad72a784b7510d72dc866215642da51d84945a9459fa89f49ec48f1e9a1752e6a78e85a4cda0ded06b1c73e727610c925f9ce6 - languageName: node - linkType: hard - "@types/json5@npm:^0.0.29": version: 0.0.29 resolution: "@types/json5@npm:0.0.29" @@ -1182,13 +1151,6 @@ __metadata: languageName: node linkType: hard -"boolean@npm:^3.0.1": - version: 3.1.4 - resolution: "boolean@npm:3.1.4" - checksum: 10c0/bf8c524e2cadfa80fbd84436089b33aecb06b041b25f4db6d561457315980f46086b2b90a056b3f1affb92b9e9120957a5a9d8055132b5301148440eabb38da6 - languageName: node - linkType: hard - "brace-expansion@npm:^1.1.7": version: 1.1.11 resolution: "brace-expansion@npm:1.1.11" @@ -1244,28 +1206,6 @@ __metadata: languageName: node linkType: hard -"cacheable-lookup@npm:^7.0.0": - version: 7.0.0 - resolution: "cacheable-lookup@npm:7.0.0" - checksum: 10c0/63a9c144c5b45cb5549251e3ea774c04d63063b29e469f7584171d059d3a88f650f47869a974e2d07de62116463d742c287a81a625e791539d987115cb081635 - languageName: node - linkType: hard - -"cacheable-request@npm:^12.0.1": - version: 12.0.1 - resolution: "cacheable-request@npm:12.0.1" - dependencies: - "@types/http-cache-semantics": "npm:^4.0.4" - get-stream: "npm:^9.0.1" - http-cache-semantics: "npm:^4.1.1" - keyv: "npm:^4.5.4" - mimic-response: "npm:^4.0.0" - normalize-url: "npm:^8.0.1" - responselike: "npm:^3.0.0" - checksum: 10c0/3ccc26519c8dd0821fcb21fa00781e55f05ab6e1da1487fbbee9c8c03435a3cf72c29a710a991cebe398fb9a5274e2a772fc488546d402db8dc21310764ed83a - languageName: node - linkType: hard - "call-bind-apply-helpers@npm:^1.0.0, call-bind-apply-helpers@npm:^1.0.1": version: 1.0.1 resolution: "call-bind-apply-helpers@npm:1.0.1" @@ -1487,15 +1427,6 @@ __metadata: languageName: node linkType: hard -"decompress-response@npm:^6.0.0": - version: 6.0.0 - resolution: "decompress-response@npm:6.0.0" - dependencies: - mimic-response: "npm:^3.1.0" - checksum: 10c0/bd89d23141b96d80577e70c54fb226b2f40e74a6817652b80a116d7befb8758261ad073a8895648a29cc0a5947021ab66705cb542fa9c143c82022b27c5b175e - languageName: node - linkType: hard - "deep-eql@npm:^5.0.1": version: 5.0.2 resolution: "deep-eql@npm:5.0.2" @@ -1510,13 +1441,6 @@ __metadata: languageName: node linkType: hard -"defer-to-connect@npm:^2.0.1": - version: 2.0.1 - resolution: "defer-to-connect@npm:2.0.1" - checksum: 10c0/625ce28e1b5ad10cf77057b9a6a727bf84780c17660f6644dab61dd34c23de3001f03cedc401f7d30a4ed9965c2e8a7336e220a329146f2cf85d4eddea429782 - languageName: node - linkType: hard - "define-data-property@npm:^1.0.1, define-data-property@npm:^1.1.4": version: 1.1.4 resolution: "define-data-property@npm:1.1.4" @@ -1528,15 +1452,6 @@ __metadata: languageName: node linkType: hard -"define-properties@npm:^1.1.3": - version: 1.1.3 - resolution: "define-properties@npm:1.1.3" - dependencies: - object-keys: "npm:^1.0.12" - checksum: 10c0/a2fa03d97ee44bb7c679bac7c3b3e63431a2efd83c12c0d61c7f5adf4fa1cf0a669c77afd274babbc5400926bdc2befb25679e4bf687140b078c0fe14f782e4f - languageName: node - linkType: hard - "define-properties@npm:^1.2.1": version: 1.2.1 resolution: "define-properties@npm:1.2.1" @@ -1548,13 +1463,6 @@ __metadata: languageName: node linkType: hard -"detect-node@npm:^2.0.4": - version: 2.0.4 - resolution: "detect-node@npm:2.0.4" - checksum: 10c0/51357b37b1b26afef72fa3fa70ae7aeb37346874a41802cd5e2c9a81400eeeeec04293b153e3b30bcb982997b0952b608bb7d1c08777325da4dd93bd25891e0a - languageName: node - linkType: hard - "doctrine@npm:^2.1.0": version: 2.1.0 resolution: "doctrine@npm:2.1.0" @@ -1770,13 +1678,6 @@ __metadata: languageName: node linkType: hard -"es6-error@npm:^4.1.1": - version: 4.1.1 - resolution: "es6-error@npm:4.1.1" - checksum: 10c0/357663fb1e845c047d548c3d30f86e005db71e122678f4184ced0693f634688c3f3ef2d7de7d4af732f734de01f528b05954e270f06aa7d133679fb9fe6600ef - languageName: node - linkType: hard - "esbuild-plugin-file-path-extensions@npm:^2.1.4": version: 2.1.4 resolution: "esbuild-plugin-file-path-extensions@npm:2.1.4" @@ -2210,13 +2111,6 @@ __metadata: languageName: node linkType: hard -"form-data-encoder@npm:^4.0.2": - version: 4.0.2 - resolution: "form-data-encoder@npm:4.0.2" - checksum: 10c0/559d3130e265316452434eaf68d68560fb36392ff4d04614683419de4fb43c3dbe152dc303599fae382ce24d3451a6d3d289d3bcc182ae3d8ad32e7ce8e35e53 - languageName: node - linkType: hard - "fs-minipass@npm:^3.0.0": version: 3.0.3 resolution: "fs-minipass@npm:3.0.3" @@ -2329,16 +2223,6 @@ __metadata: languageName: node linkType: hard -"get-stream@npm:^9.0.1": - version: 9.0.1 - resolution: "get-stream@npm:9.0.1" - dependencies: - "@sec-ant/readable-stream": "npm:^0.4.1" - is-stream: "npm:^4.0.1" - checksum: 10c0/d70e73857f2eea1826ac570c3a912757dcfbe8a718a033fa0c23e12ac8e7d633195b01710e0559af574cbb5af101009b42df7b6f6b29ceec8dbdf7291931b948 - languageName: node - linkType: hard - "get-symbol-description@npm:^1.1.0": version: 1.1.0 resolution: "get-symbol-description@npm:1.1.0" @@ -2398,20 +2282,6 @@ __metadata: languageName: node linkType: hard -"global-agent@npm:^3.0.0": - version: 3.0.0 - resolution: "global-agent@npm:3.0.0" - dependencies: - boolean: "npm:^3.0.1" - es6-error: "npm:^4.1.1" - matcher: "npm:^3.0.0" - roarr: "npm:^2.15.3" - semver: "npm:^7.3.2" - serialize-error: "npm:^7.0.1" - checksum: 10c0/bb8750d026b25da437072762fd739098bad92ff72f66483c3929db4579e072f5523960f7e7fd70ee0d75db48898067b5dc1c9c1d17888128cff008fcc34d1bd3 - languageName: node - linkType: hard - "globals@npm:^13.19.0": version: 13.24.0 resolution: "globals@npm:13.24.0" @@ -2421,15 +2291,6 @@ __metadata: languageName: node linkType: hard -"globalthis@npm:^1.0.1": - version: 1.0.2 - resolution: "globalthis@npm:1.0.2" - dependencies: - define-properties: "npm:^1.1.3" - checksum: 10c0/dcb1f502192d1bdcd9bf07911e44567c4d7041d62ed65a31cc1df00e0e8fc1ac9669844c78c763cc89533a34f2e62c008260d3d1dc775954f7ca59027d0694b4 - languageName: node - linkType: hard - "globalthis@npm:^1.0.4": version: 1.0.4 resolution: "globalthis@npm:1.0.4" @@ -2447,25 +2308,6 @@ __metadata: languageName: node linkType: hard -"got@npm:^14.4.5": - version: 14.4.5 - resolution: "got@npm:14.4.5" - dependencies: - "@sindresorhus/is": "npm:^7.0.1" - "@szmarczak/http-timer": "npm:^5.0.1" - cacheable-lookup: "npm:^7.0.0" - cacheable-request: "npm:^12.0.1" - decompress-response: "npm:^6.0.0" - form-data-encoder: "npm:^4.0.2" - http2-wrapper: "npm:^2.2.1" - lowercase-keys: "npm:^3.0.0" - p-cancelable: "npm:^4.0.1" - responselike: "npm:^3.0.0" - type-fest: "npm:^4.26.1" - checksum: 10c0/37bcb77dcbe6b2d00345d11e2749bb9f5fcab38850dab84015684545b72ba0169324330ccde81e40ef356150238008c3b282ea38fb774bde66289f6433681cd8 - languageName: node - linkType: hard - "graceful-fs@npm:^4.2.11, graceful-fs@npm:^4.2.6": version: 4.2.11 resolution: "graceful-fs@npm:4.2.11" @@ -2561,16 +2403,6 @@ __metadata: languageName: node linkType: hard -"http2-wrapper@npm:^2.2.1": - version: 2.2.1 - resolution: "http2-wrapper@npm:2.2.1" - dependencies: - quick-lru: "npm:^5.1.1" - resolve-alpn: "npm:^1.2.0" - checksum: 10c0/7207201d3c6e53e72e510c9b8912e4f3e468d3ecc0cf3bf52682f2aac9cd99358b896d1da4467380adc151cf97c412bedc59dc13dae90c523f42053a7449eedb - languageName: node - linkType: hard - "https-proxy-agent@npm:^7.0.1": version: 7.0.6 resolution: "https-proxy-agent@npm:7.0.6" @@ -2858,13 +2690,6 @@ __metadata: languageName: node linkType: hard -"is-stream@npm:^4.0.1": - version: 4.0.1 - resolution: "is-stream@npm:4.0.1" - checksum: 10c0/2706c7f19b851327ba374687bc4a3940805e14ca496dc672b9629e744d143b1ad9c6f1b162dece81c7bfbc0f83b32b61ccc19ad2e05aad2dd7af347408f60c7f - languageName: node - linkType: hard - "is-string@npm:^1.0.7, is-string@npm:^1.1.1": version: 1.1.1 resolution: "is-string@npm:1.1.1" @@ -3026,13 +2851,6 @@ __metadata: languageName: node linkType: hard -"json-stringify-safe@npm:^5.0.1": - version: 5.0.1 - resolution: "json-stringify-safe@npm:5.0.1" - checksum: 10c0/7dbf35cd0411d1d648dceb6d59ce5857ec939e52e4afc37601aa3da611f0987d5cee5b38d58329ceddf3ed48bd7215229c8d52059ab01f2444a338bf24ed0f37 - languageName: node - linkType: hard - "json5@npm:^1.0.2": version: 1.0.2 resolution: "json5@npm:1.0.2" @@ -3051,7 +2869,7 @@ __metadata: languageName: node linkType: hard -"keyv@npm:^4.5.3, keyv@npm:^4.5.4": +"keyv@npm:^4.5.3": version: 4.5.4 resolution: "keyv@npm:4.5.4" dependencies: @@ -3137,13 +2955,6 @@ __metadata: languageName: node linkType: hard -"lowercase-keys@npm:^3.0.0": - version: 3.0.0 - resolution: "lowercase-keys@npm:3.0.0" - checksum: 10c0/ef62b9fa5690ab0a6e4ef40c94efce68e3ed124f583cc3be38b26ff871da0178a28b9a84ce0c209653bb25ca135520ab87fea7cd411a54ac4899cb2f30501430 - languageName: node - linkType: hard - "lru-cache@npm:^10.0.1, lru-cache@npm:^10.2.0": version: 10.4.3 resolution: "lru-cache@npm:10.4.3" @@ -3215,15 +3026,6 @@ __metadata: languageName: node linkType: hard -"matcher@npm:^3.0.0": - version: 3.0.0 - resolution: "matcher@npm:3.0.0" - dependencies: - escape-string-regexp: "npm:^4.0.0" - checksum: 10c0/2edf24194a2879690bcdb29985fc6bc0d003df44e04df21ebcac721fa6ce2f6201c579866bb92f9380bffe946f11ecd8cd31f34117fb67ebf8aca604918e127e - languageName: node - linkType: hard - "math-intrinsics@npm:^1.1.0": version: 1.1.0 resolution: "math-intrinsics@npm:1.1.0" @@ -3255,20 +3057,6 @@ __metadata: languageName: node linkType: hard -"mimic-response@npm:^3.1.0": - version: 3.1.0 - resolution: "mimic-response@npm:3.1.0" - checksum: 10c0/0d6f07ce6e03e9e4445bee655202153bdb8a98d67ee8dc965ac140900d7a2688343e6b4c9a72cfc9ef2f7944dfd76eef4ab2482eb7b293a68b84916bac735362 - languageName: node - linkType: hard - -"mimic-response@npm:^4.0.0": - version: 4.0.0 - resolution: "mimic-response@npm:4.0.0" - checksum: 10c0/761d788d2668ae9292c489605ffd4fad220f442fbae6832adce5ebad086d691e906a6d5240c290293c7a11e99fbdbbef04abbbed498bf8699a4ee0f31315e3fb - languageName: node - linkType: hard - "minimatch@npm:^3.0.4, minimatch@npm:^3.0.5, minimatch@npm:^3.1.2": version: 3.1.5 resolution: "minimatch@npm:3.1.5" @@ -3452,13 +3240,6 @@ __metadata: languageName: node linkType: hard -"normalize-url@npm:^8.0.1": - version: 8.0.1 - resolution: "normalize-url@npm:8.0.1" - checksum: 10c0/eb439231c4b84430f187530e6fdac605c5048ef4ec556447a10c00a91fc69b52d8d8298d9d608e68d3e0f7dc2d812d3455edf425e0f215993667c3183bcab1ef - languageName: node - linkType: hard - "object-inspect@npm:^1.13.3": version: 1.13.3 resolution: "object-inspect@npm:1.13.3" @@ -3466,7 +3247,7 @@ __metadata: languageName: node linkType: hard -"object-keys@npm:^1.0.12, object-keys@npm:^1.1.1": +"object-keys@npm:^1.1.1": version: 1.1.1 resolution: "object-keys@npm:1.1.1" checksum: 10c0/b11f7ccdbc6d406d1f186cdadb9d54738e347b2692a14439ca5ac70c225fa6db46db809711b78589866d47b25fc3e8dee0b4c722ac751e11180f9380e3d8601d @@ -3565,13 +3346,6 @@ __metadata: languageName: node linkType: hard -"p-cancelable@npm:^4.0.1": - version: 4.0.1 - resolution: "p-cancelable@npm:4.0.1" - checksum: 10c0/12636623f46784ba962b6fe7a1f34d021f1d9a2cc12c43e270baa715ea872d5c8c7d9f086ed420b8b9817e91d9bbe92c14c90e5dddd4a9968c81a2a7aef7089d - languageName: node - linkType: hard - "p-limit@npm:^3.0.2": version: 3.1.0 resolution: "p-limit@npm:3.1.0" @@ -3767,13 +3541,6 @@ __metadata: languageName: node linkType: hard -"quick-lru@npm:^5.1.1": - version: 5.1.1 - resolution: "quick-lru@npm:5.1.1" - checksum: 10c0/a24cba5da8cec30d70d2484be37622580f64765fb6390a928b17f60cd69e8dbd32a954b3ff9176fa1b86d86ff2ba05252fae55dc4d40d0291c60412b0ad096da - languageName: node - linkType: hard - "reflect.getprototypeof@npm:^1.0.6, reflect.getprototypeof@npm:^1.0.9": version: 1.0.10 resolution: "reflect.getprototypeof@npm:1.0.10" @@ -3804,13 +3571,6 @@ __metadata: languageName: node linkType: hard -"resolve-alpn@npm:^1.2.0": - version: 1.2.1 - resolution: "resolve-alpn@npm:1.2.1" - checksum: 10c0/b70b29c1843bc39781ef946c8cd4482e6d425976599c0f9c138cec8209e4e0736161bf39319b01676a847000085dfdaf63583c6fb4427bf751a10635bd2aa0c4 - languageName: node - linkType: hard - "resolve-from@npm:^4.0.0": version: 4.0.0 resolution: "resolve-from@npm:4.0.0" @@ -3844,15 +3604,6 @@ __metadata: languageName: node linkType: hard -"responselike@npm:^3.0.0": - version: 3.0.0 - resolution: "responselike@npm:3.0.0" - dependencies: - lowercase-keys: "npm:^3.0.0" - checksum: 10c0/8af27153f7e47aa2c07a5f2d538cb1e5872995f0e9ff77def858ecce5c3fe677d42b824a62cde502e56d275ab832b0a8bd350d5cd6b467ac0425214ac12ae658 - languageName: node - linkType: hard - "restore-cursor@npm:^5.0.0": version: 5.1.0 resolution: "restore-cursor@npm:5.1.0" @@ -3895,20 +3646,6 @@ __metadata: languageName: node linkType: hard -"roarr@npm:^2.15.3": - version: 2.15.4 - resolution: "roarr@npm:2.15.4" - dependencies: - boolean: "npm:^3.0.1" - detect-node: "npm:^2.0.4" - globalthis: "npm:^1.0.1" - json-stringify-safe: "npm:^5.0.1" - semver-compare: "npm:^1.0.0" - sprintf-js: "npm:^1.1.2" - checksum: 10c0/7d01d4c14513c461778dd673a8f9e53255221f8d04173aafeb8e11b23d8b659bb83f1c90cfe81af7f9c213b8084b404b918108fd792bda76678f555340cc64ec - languageName: node - linkType: hard - "rollup@npm:^4.34.9": version: 4.59.0 resolution: "rollup@npm:4.59.0" @@ -4049,13 +3786,6 @@ __metadata: languageName: node linkType: hard -"semver-compare@npm:^1.0.0": - version: 1.0.0 - resolution: "semver-compare@npm:1.0.0" - checksum: 10c0/9ef4d8b81847556f0865f46ddc4d276bace118c7cb46811867af82e837b7fc473911981d5a0abc561fa2db487065572217e5b06e18701c4281bcdd2a1affaff1 - languageName: node - linkType: hard - "semver@npm:^6.3.1": version: 6.3.1 resolution: "semver@npm:6.3.1" @@ -4065,15 +3795,6 @@ __metadata: languageName: node linkType: hard -"semver@npm:^7.3.2, semver@npm:^7.5.3, semver@npm:^7.6.0, semver@npm:^7.6.3": - version: 7.6.3 - resolution: "semver@npm:7.6.3" - bin: - semver: bin/semver.js - checksum: 10c0/88f33e148b210c153873cb08cfe1e281d518aaa9a666d4d148add6560db5cd3c582f3a08ccb91f38d5f379ead256da9931234ed122057f40bb5766e65e58adaf - languageName: node - linkType: hard - "semver@npm:^7.3.5": version: 7.7.3 resolution: "semver@npm:7.7.3" @@ -4083,12 +3804,12 @@ __metadata: languageName: node linkType: hard -"serialize-error@npm:^7.0.1": - version: 7.0.1 - resolution: "serialize-error@npm:7.0.1" - dependencies: - type-fest: "npm:^0.13.1" - checksum: 10c0/7982937d578cd901276c8ab3e2c6ed8a4c174137730f1fb0402d005af209a0e84d04acc874e317c936724c7b5b26c7a96ff7e4b8d11a469f4924a4b0ea814c05 +"semver@npm:^7.5.3, semver@npm:^7.6.0, semver@npm:^7.6.3": + version: 7.6.3 + resolution: "semver@npm:7.6.3" + bin: + semver: bin/semver.js + checksum: 10c0/88f33e148b210c153873cb08cfe1e281d518aaa9a666d4d148add6560db5cd3c582f3a08ccb91f38d5f379ead256da9931234ed122057f40bb5766e65e58adaf languageName: node linkType: hard @@ -4264,13 +3985,6 @@ __metadata: languageName: node linkType: hard -"sprintf-js@npm:^1.1.2": - version: 1.1.2 - resolution: "sprintf-js@npm:1.1.2" - checksum: 10c0/6cc8382f746348bd64b31bc5c99d8ebda7efff716025c41bf501e0e8be4f6744a9fa507e18513554753553d0bcb57fd5fc8dc8c42f94f8008127a52a2c544d21 - languageName: node - linkType: hard - "ssri@npm:^12.0.0": version: 12.0.0 resolution: "ssri@npm:12.0.0" @@ -4554,13 +4268,6 @@ __metadata: languageName: node linkType: hard -"type-fest@npm:^0.13.1": - version: 0.13.1 - resolution: "type-fest@npm:0.13.1" - checksum: 10c0/0c0fa07ae53d4e776cf4dac30d25ad799443e9eef9226f9fddbb69242db86b08584084a99885cfa5a9dfe4c063ebdc9aa7b69da348e735baede8d43f1aeae93b - languageName: node - linkType: hard - "type-fest@npm:^0.20.2": version: 0.20.2 resolution: "type-fest@npm:0.20.2" @@ -4568,13 +4275,6 @@ __metadata: languageName: node linkType: hard -"type-fest@npm:^4.26.1": - version: 4.33.0 - resolution: "type-fest@npm:4.33.0" - checksum: 10c0/20015eea353605e08e3f4b967291b225fa4e7c43361de44f39b88131715e41877458af80da59c8f17e40c0e3842298996f0651219dc9823e35c7e46ecbc8a44f - languageName: node - linkType: hard - "typed-array-buffer@npm:^1.0.3": version: 1.0.3 resolution: "typed-array-buffer@npm:1.0.3" @@ -4683,6 +4383,13 @@ __metadata: languageName: node linkType: hard +"undici@npm:^7.24.4": + version: 7.24.4 + resolution: "undici@npm:7.24.4" + checksum: 10c0/cb302e81fadb7f0b7946ab77595715c0961b46a025ccecae79ba599432d0bc8d1e3da4dfe7ff66bc74f115c1b8ff0f099bc4e9bf313db4562da23995872c6d17 + languageName: node + linkType: hard + "unique-filename@npm:^4.0.0": version: 4.0.0 resolution: "unique-filename@npm:4.0.0"