diff --git a/.changeset/easy-ideas-kick.md b/.changeset/easy-ideas-kick.md new file mode 100644 index 000000000..1c53aff8a --- /dev/null +++ b/.changeset/easy-ideas-kick.md @@ -0,0 +1,5 @@ +--- +'@graphprotocol/graph-cli': minor +--- + +Add a new command to install graph-node dev binary (gnd) diff --git a/packages/cli/package.json b/packages/cli/package.json index 221015e37..bb0e46d48 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -46,6 +46,7 @@ "assemblyscript": "0.19.23", "chokidar": "4.0.3", "debug": "4.4.1", + "decompress": "^4.2.1", "docker-compose": "1.2.0", "fs-extra": "11.3.0", "glob": "11.0.2", @@ -57,6 +58,7 @@ "kubo-rpc-client": "^5.0.2", "open": "10.1.2", "prettier": "3.5.3", + "progress": "^2.0.3", "semver": "7.7.2", "tmp-promise": "3.0.3", "undici": "7.9.0", @@ -65,8 +67,10 @@ }, "devDependencies": { "@types/debug": "^4.1.12", + "@types/decompress": "^4.2.7", "@types/fs-extra": "^11.0.4", "@types/js-yaml": "^4.0.9", + "@types/progress": "^2.0.7", "@types/semver": "^7.5.8", "@types/which": "^3.0.4", "copyfiles": "^2.4.1", diff --git a/packages/cli/src/command-helpers/local-node.ts b/packages/cli/src/command-helpers/local-node.ts new file mode 100644 index 000000000..692723d90 --- /dev/null +++ b/packages/cli/src/command-helpers/local-node.ts @@ -0,0 +1,157 @@ +import * as fs from 'node:fs'; +import { createReadStream, createWriteStream } from 'node:fs'; +import * as os from 'node:os'; +import * as path from 'node:path'; +import { Readable } from 'node:stream'; +import { pipeline } from 'node:stream/promises'; +import { createGunzip } from 'node:zlib'; +import decompress from 'decompress'; +import fetch from '../fetch.js'; + +function getPlatformBinaryName(): string { + const platform = os.platform(); + const arch = os.arch(); + + if (platform === 'linux' && arch === 'x64') return 'gnd-linux-x86_64.gz'; + if (platform === 'linux' && arch === 'arm64') return 'gnd-linux-aarch64.gz'; + if (platform === 'darwin' && arch === 'x64') return 'gnd-macos-x86_64.gz'; + if (platform === 'darwin' && arch === 'arm64') return 'gnd-macos-aarch64.gz'; + if (platform === 'win32' && arch === 'x64') return 'gnd-windows-x86_64.exe.zip'; + + throw new Error(`Unsupported platform: ${platform} ${arch}`); +} + +export async function getGlobalBinDir(): Promise { + const platform = os.platform(); + let binDir: string; + + if (platform === 'win32') { + // Prefer %USERPROFILE%\gnd\bin + binDir = path.join(process.env.USERPROFILE || os.homedir(), 'gnd', 'bin'); + } else { + binDir = path.join(os.homedir(), '.local', 'bin'); + } + + await fs.promises.mkdir(binDir, { recursive: true }); + return binDir; +} + +async function getLatestGithubRelease(owner: string, repo: string) { + const res = await fetch(`https://api.github.com/repos/${owner}/${repo}/releases/latest`); + const data = await res.json(); + return data.tag_name; +} + +export async function getLatestGraphNodeRelease(): Promise { + return getLatestGithubRelease('incrypto32', 'graph-node'); +} + +export async function downloadGraphNodeRelease( + release: string, + outputDir: string, + onProgress?: (downloaded: number, total: number | null) => void, +): Promise { + const fileName = getPlatformBinaryName(); + + try { + return await downloadGithubRelease( + 'incrypto32', + 'graph-node', + release, + outputDir, + fileName, + onProgress, + ); + } catch (e) { + if (e === 404) { + throw `Graph Node release ${release} does not exist, please check the release page for the correct release tag`; + } + + throw `Failed to download: ${release}`; + } +} + +async function downloadGithubRelease( + owner: string, + repo: string, + release: string, + outputDir: string, + fileName: string, + onProgress?: (downloaded: number, total: number | null) => void, +): Promise { + const url = `https://github.com/${owner}/${repo}/releases/download/${release}/${fileName}`; + return downloadFile(url, path.join(outputDir, fileName), onProgress); +} + +export async function downloadFile( + url: string, + outputPath: string, + onProgress?: (downloaded: number, total: number | null) => void, +): Promise { + return download(url, outputPath, onProgress); +} + +export async function download( + url: string, + outputPath: string, + onProgress?: (downloaded: number, total: number | null) => void, +): Promise { + const res = await fetch(url); + if (!res.ok || !res.body) { + throw res.status; + } + + const totalLength = Number(res.headers.get('content-length')) || null; + let downloaded = 0; + + const fileStream = fs.createWriteStream(outputPath); + const nodeStream = Readable.from(res.body); + + nodeStream.on('data', chunk => { + downloaded += chunk.length; + onProgress?.(downloaded, totalLength); + }); + + nodeStream.pipe(fileStream); + + await new Promise((resolve, reject) => { + nodeStream.on('error', reject); + fileStream.on('finish', resolve); + fileStream.on('error', reject); + }); + + return outputPath; +} + +export async function extractGz(gzPath: string, outputPath?: string): Promise { + const outPath = outputPath || path.join(path.dirname(gzPath), path.basename(gzPath, '.gz')); + + await pipeline(createReadStream(gzPath), createGunzip(), createWriteStream(outPath)); + + return outPath; +} + +export async function extractZipAndGetExe(zipPath: string, outputDir: string): Promise { + const files = await decompress(zipPath, outputDir); + const exe = files.filter(file => file.path.endsWith('.exe')); + + if (exe.length !== 1) { + throw new Error(`Expected 1 executable file in zip, got ${exe.length}`); + } + + return path.join(outputDir, exe[0].path); +} + +export async function moveFileToBinDir(srcPath: string, binDir?: string): Promise { + const targetDir = binDir || (await getGlobalBinDir()); + const platform = os.platform(); + const binaryName = platform === 'win32' ? 'gnd.exe' : 'gnd'; + const destPath = path.join(targetDir, binaryName); + await fs.promises.rename(srcPath, destPath); + return destPath; +} + +export async function moveFile(srcPath: string, destPath: string): Promise { + await fs.promises.rename(srcPath, destPath); + return destPath; +} diff --git a/packages/cli/src/commands/node.ts b/packages/cli/src/commands/node.ts new file mode 100644 index 000000000..3764a9334 --- /dev/null +++ b/packages/cli/src/commands/node.ts @@ -0,0 +1,111 @@ +import * as fs from 'node:fs'; +import { chmod } from 'node:fs/promises'; +import * as os from 'node:os'; +import * as path from 'node:path'; +import { print } from 'gluegun'; +import ProgressBar from 'progress'; +import { Args, Command, Flags } from '@oclif/core'; +import { + downloadGraphNodeRelease, + extractGz, + extractZipAndGetExe, + getLatestGraphNodeRelease, + moveFileToBinDir, +} from '../command-helpers/local-node.js'; + +export default class NodeCommand extends Command { + static description = 'Manage Graph node related operations'; + + static override flags = { + help: Flags.help({ + char: 'h', + }), + tag: Flags.string({ + summary: 'Tag of the Graph Node release to install.', + }), + 'bin-dir': Flags.string({ + summary: 'Directory to install the Graph Node binary to.', + }), + }; + + static override args = { + install: Args.boolean({ + description: 'Install the Graph Node', + }), + }; + + static examples = [ + '$ graph node install', + '$ graph node install --tag v1.0.0', + '$ graph node install --bin-dir /usr/local/bin', + ]; + + static strict = false; + + async run() { + const { flags, args } = await this.parse(NodeCommand); + + if (args.install) { + await installGraphNode(flags.tag, flags['bin-dir']); + return; + } + + // If no valid subcommand is provided, show help + await this.config.runCommand('help', ['node']); + } +} + +async function installGraphNode(tag?: string, binDir?: string) { + const latestRelease = tag || (await getLatestGraphNodeRelease()); + const tmpBase = os.tmpdir(); + const tmpDir = await fs.promises.mkdtemp(path.join(tmpBase, 'graph-node-')); + let progressBar: ProgressBar | undefined; + + let downloadPath: string; + try { + downloadPath = await downloadGraphNodeRelease(latestRelease, tmpDir, (downloaded, total) => { + if (!total) return; + + progressBar ||= new ProgressBar(`Downloading ${latestRelease} [:bar] :percent`, { + width: 30, + total, + complete: '=', + incomplete: ' ', + }); + + progressBar.tick(downloaded - (progressBar.curr || 0)); + }); + } catch (e) { + print.error(e); + throw e; + } + + let extractedPath: string; + + print.info(`\nExtracting binary...`); + if (downloadPath.endsWith('.gz')) { + extractedPath = await extractGz(downloadPath); + } else if (downloadPath.endsWith('.zip')) { + extractedPath = await extractZipAndGetExe(downloadPath, tmpDir); + } else { + print.error(`Unsupported file type: ${downloadPath}`); + throw new Error(`Unsupported file type: ${downloadPath}`); + } + + const movedPath = await moveFileToBinDir(extractedPath, binDir); + print.info(`✅ Graph Node ${latestRelease} installed successfully`); + print.info(`Binary location: ${movedPath}`); + + if (os.platform() !== 'win32') { + await chmod(movedPath, 0o755); + } + + print.info(''); + print.info(`📋 Next steps:`); + print.info(` Add ${path.dirname(movedPath)} to your PATH (if not already)`); + print.info(` Run 'gnd' to start your local Graph Node development environment`); + print.info(''); + + // Delete the temporary directory + await fs.promises.rm(tmpDir, { recursive: true, force: true }); +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 474ff0815..1ae5cd71f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -263,6 +263,9 @@ importers: debug: specifier: 4.4.1 version: 4.4.1(supports-color@5.5.0) + decompress: + specifier: ^4.2.1 + version: 4.2.1 docker-compose: specifier: 1.2.0 version: 1.2.0 @@ -296,6 +299,9 @@ importers: prettier: specifier: 3.5.3 version: 3.5.3 + progress: + specifier: ^2.0.3 + version: 2.0.3 semver: specifier: 7.7.2 version: 7.7.2 @@ -315,12 +321,18 @@ importers: '@types/debug': specifier: ^4.1.12 version: 4.1.12 + '@types/decompress': + specifier: ^4.2.7 + version: 4.2.7 '@types/fs-extra': specifier: ^11.0.4 version: 11.0.4 '@types/js-yaml': specifier: ^4.0.9 version: 4.0.9 + '@types/progress': + specifier: ^2.0.7 + version: 2.0.7 '@types/semver': specifier: ^7.5.8 version: 7.7.0 @@ -3407,6 +3419,9 @@ packages: '@types/debug@4.1.12': resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} + '@types/decompress@4.2.7': + resolution: {integrity: sha512-9z+8yjKr5Wn73Pt17/ldnmQToaFHZxK0N1GHysuk/JIPT8RIdQeoInM01wWPgypRcvb6VH1drjuFpQ4zmY437g==} + '@types/dns-packet@5.6.5': resolution: {integrity: sha512-qXOC7XLOEe43ehtWJCMnQXvgcIpv6rPmQ1jXT98Ad8A3TB1Ue50jsCbSSSyuazScEuZ/Q026vHbrOTVkmwA+7Q==} @@ -3503,6 +3518,9 @@ packages: '@types/prettier@2.7.3': resolution: {integrity: sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==} + '@types/progress@2.0.7': + resolution: {integrity: sha512-iadjw02vte8qWx7U0YM++EybBha2CQLPGu9iJ97whVgJUT5Zq9MjAPYUnbfRI2Kpehimf1QjFJYxD0t8nqzu5w==} + '@types/qs@6.9.18': resolution: {integrity: sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA==} @@ -4299,6 +4317,9 @@ packages: buffer-alloc@1.2.0: resolution: {integrity: sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==} + buffer-crc32@0.2.13: + resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} + buffer-fill@1.0.0: resolution: {integrity: sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==} @@ -4852,6 +4873,26 @@ packages: resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} engines: {node: '>=10'} + decompress-tar@4.1.1: + resolution: {integrity: sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==} + engines: {node: '>=4'} + + decompress-tarbz2@4.1.1: + resolution: {integrity: sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==} + engines: {node: '>=4'} + + decompress-targz@4.1.1: + resolution: {integrity: sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==} + engines: {node: '>=4'} + + decompress-unzip@4.0.1: + resolution: {integrity: sha512-1fqeluvxgnn86MOh66u8FjbtJpAFv5wgCT9Iw8rcBqQcCo5tO8eiJw7NNTrvt9n4CRBVq7CstiS922oPgyGLrw==} + engines: {node: '>=4'} + + decompress@4.2.1: + resolution: {integrity: sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ==} + engines: {node: '>=4'} + deep-eql@4.1.4: resolution: {integrity: sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==} engines: {node: '>=6'} @@ -5604,6 +5645,9 @@ packages: fastq@1.19.0: resolution: {integrity: sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA==} + fd-slicer@1.1.0: + resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} + fdir@6.4.3: resolution: {integrity: sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==} peerDependencies: @@ -5627,6 +5671,18 @@ packages: resolution: {integrity: sha512-hw9gNZXUfZ02Jo0uafWLaFVPter5/k2rfcrjFJJHX/77xtSDOfJuEFb6oKlFV86FLP1SuyHMW1PSk0U9M5tKkQ==} engines: {node: '>=18'} + file-type@3.9.0: + resolution: {integrity: sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA==} + engines: {node: '>=0.10.0'} + + file-type@5.2.0: + resolution: {integrity: sha512-Iq1nJ6D2+yIO4c8HHg4fyVb8mAJieo1Oloy1mLLaB2PvezNedhBVm+QU7g0qM42aiMbRXTxKKwGD17rjKNJYVQ==} + engines: {node: '>=4'} + + file-type@6.2.0: + resolution: {integrity: sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==} + engines: {node: '>=4'} + filelist@1.0.4: resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} @@ -5809,6 +5865,10 @@ packages: resolution: {integrity: sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==} engines: {node: '>=12'} + get-stream@2.3.1: + resolution: {integrity: sha512-AUGhbbemXxrZJRD5cDvKtQxLuYaIbNtDTK8YqupCI393Q2KSTreEsLUN3ZxAWFGiKTzL6nKuzfcIvieflUX9qA==} + engines: {node: '>=0.10.0'} + get-stream@6.0.1: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} engines: {node: '>=10'} @@ -6364,6 +6424,9 @@ packages: resolution: {integrity: sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==} engines: {node: '>= 0.4'} + is-natural-number@4.0.1: + resolution: {integrity: sha512-Y4LTamMe0DDQIIAlaer9eKebAlDSV6huy+TWhJVPlzZh2o4tRP5SQWFlLn5N0To4mDD22/qdOq+veo1cSISLgQ==} + is-number-object@1.1.1: resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} engines: {node: '>= 0.4'} @@ -6918,6 +6981,10 @@ packages: magic-string@0.30.17: resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} + make-dir@1.3.0: + resolution: {integrity: sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==} + engines: {node: '>=4'} + make-error@1.3.6: resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} @@ -7677,6 +7744,9 @@ packages: resolution: {integrity: sha512-nri2TO5JE3/mRryik9LlHFT53cgHfRK0Lt0BAZQXku/AW3E6XLt2GaY8siWi7dvW/m1z0ecn+J+bpDa9ZN3IsQ==} engines: {node: '>=18'} + pend@1.2.0: + resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} + picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -7688,6 +7758,10 @@ packages: resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} engines: {node: '>=12'} + pify@2.3.0: + resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} + engines: {node: '>=0.10.0'} + pify@3.0.0: resolution: {integrity: sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==} engines: {node: '>=4'} @@ -7700,6 +7774,14 @@ packages: resolution: {integrity: sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==} engines: {node: '>=10'} + pinkie-promise@2.0.1: + resolution: {integrity: sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==} + engines: {node: '>=0.10.0'} + + pinkie@2.0.4: + resolution: {integrity: sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==} + engines: {node: '>=0.10.0'} + pino-abstract-transport@0.5.0: resolution: {integrity: sha512-+KAgmVeqXYbTtU2FScx1XS3kNyfZ5TrXY07V96QnUSFqo2gAqlvmaxH67Lj7SWazqsMabf+58ctdTcBgnOLUOQ==} @@ -7806,6 +7888,10 @@ packages: progress-events@1.0.1: resolution: {integrity: sha512-MOzLIwhpt64KIVN64h1MwdKWiyKFNc/S6BoYKPIVUHFg0/eIEyBulhWCgn678v/4c0ri3FdGuzXymNCv02MUIw==} + progress@2.0.3: + resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} + engines: {node: '>=0.4.0'} + promise-inflight@1.0.1: resolution: {integrity: sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==} peerDependencies: @@ -8290,6 +8376,10 @@ packages: resolution: {integrity: sha512-6JfvwvjUOn8F/jUoBY2Q1v5WY5XS+rj8qSe0v8Y4ezH4InLgTEeOOPQsRll9OV429Pvo6BCHGavIyJfr3TAhsw==} engines: {node: '>=18.0.0'} + seek-bzip@1.0.6: + resolution: {integrity: sha512-e1QtP3YL5tWww8uKaOCQ18UxIT2laNBXHjV/S2WYCiK4udiv8lkG89KRIoCjUagnAmCBurjF4zEVX2ByBbnCjQ==} + hasBin: true + semver@5.7.2: resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} hasBin: true @@ -8637,6 +8727,9 @@ packages: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} engines: {node: '>=4'} + strip-dirs@2.1.0: + resolution: {integrity: sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==} + strip-final-newline@2.0.0: resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} engines: {node: '>=6'} @@ -9024,6 +9117,9 @@ packages: resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} engines: {node: '>= 0.4'} + unbzip2-stream@1.4.3: + resolution: {integrity: sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==} + uncrypto@0.1.3: resolution: {integrity: sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==} @@ -9653,6 +9749,9 @@ packages: resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} engines: {node: '>=12'} + yauzl@2.10.0: + resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} + yn@3.1.1: resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} engines: {node: '>=6'} @@ -13923,6 +14022,10 @@ snapshots: dependencies: '@types/ms': 2.1.0 + '@types/decompress@4.2.7': + dependencies: + '@types/node': 22.15.18 + '@types/dns-packet@5.6.5': dependencies: '@types/node': 22.15.18 @@ -14015,6 +14118,10 @@ snapshots: '@types/prettier@2.7.3': {} + '@types/progress@2.0.7': + dependencies: + '@types/node': 22.15.18 + '@types/qs@6.9.18': {} '@types/react-dom@19.1.1(@types/react@19.1.0)': @@ -14965,7 +15072,7 @@ snapshots: axios@1.9.0: dependencies: - follow-redirects: 1.15.9(debug@4.4.1) + follow-redirects: 1.15.9(debug@4.4.0) form-data: 4.0.2 proxy-from-env: 1.1.0 transitivePeerDependencies: @@ -15310,6 +15417,8 @@ snapshots: buffer-alloc-unsafe: 1.1.0 buffer-fill: 1.0.0 + buffer-crc32@0.2.13: {} + buffer-fill@1.0.0: {} buffer-from@1.1.2: {} @@ -15920,6 +16029,44 @@ snapshots: dependencies: mimic-response: 3.1.0 + decompress-tar@4.1.1: + dependencies: + file-type: 5.2.0 + is-stream: 1.1.0 + tar-stream: 1.6.2 + + decompress-tarbz2@4.1.1: + dependencies: + decompress-tar: 4.1.1 + file-type: 6.2.0 + is-stream: 1.1.0 + seek-bzip: 1.0.6 + unbzip2-stream: 1.4.3 + + decompress-targz@4.1.1: + dependencies: + decompress-tar: 4.1.1 + file-type: 5.2.0 + is-stream: 1.1.0 + + decompress-unzip@4.0.1: + dependencies: + file-type: 3.9.0 + get-stream: 2.3.1 + pify: 2.3.0 + yauzl: 2.10.0 + + decompress@4.2.1: + dependencies: + decompress-tar: 4.1.1 + decompress-tarbz2: 4.1.1 + decompress-targz: 4.1.1 + decompress-unzip: 4.0.1 + graceful-fs: 4.2.11 + make-dir: 1.3.0 + pify: 2.3.0 + strip-dirs: 2.1.0 + deep-eql@4.1.4: dependencies: type-detect: 4.1.0 @@ -16999,6 +17146,10 @@ snapshots: dependencies: reusify: 1.0.4 + fd-slicer@1.1.0: + dependencies: + pend: 1.2.0 + fdir@6.4.3(picomatch@4.0.2): optionalDependencies: picomatch: 4.0.2 @@ -17022,6 +17173,12 @@ snapshots: transitivePeerDependencies: - supports-color + file-type@3.9.0: {} + + file-type@5.2.0: {} + + file-type@6.2.0: {} + filelist@1.0.4: dependencies: minimatch: 5.1.6 @@ -17229,6 +17386,11 @@ snapshots: get-stdin@9.0.0: {} + get-stream@2.3.1: + dependencies: + object-assign: 4.1.1 + pinkie-promise: 2.0.1 + get-stream@6.0.1: {} get-symbol-description@1.1.0: @@ -17999,6 +18161,8 @@ snapshots: call-bind: 1.0.8 define-properties: 1.2.1 + is-natural-number@4.0.1: {} + is-number-object@1.1.1: dependencies: call-bound: 1.0.3 @@ -18538,6 +18702,10 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 + make-dir@1.3.0: + dependencies: + pify: 3.0.0 + make-error@1.3.6: {} markdown-table@1.1.3: {} @@ -19567,18 +19735,28 @@ snapshots: peek-readable@7.0.0: {} + pend@1.2.0: {} + picocolors@1.1.1: {} picomatch@2.3.1: {} picomatch@4.0.2: {} + pify@2.3.0: {} + pify@3.0.0: {} pify@4.0.1: {} pify@5.0.0: {} + pinkie-promise@2.0.1: + dependencies: + pinkie: 2.0.4 + + pinkie@2.0.4: {} + pino-abstract-transport@0.5.0: dependencies: duplexify: 4.1.3 @@ -19665,6 +19843,8 @@ snapshots: progress-events@1.0.1: {} + progress@2.0.3: {} + promise-inflight@1.0.1: {} promise-retry@2.0.1: @@ -20231,6 +20411,10 @@ snapshots: node-addon-api: 5.1.0 node-gyp-build: 4.8.4 + seek-bzip@1.0.6: + dependencies: + commander: 2.20.3 + semver@5.7.2: {} semver@6.3.1: {} @@ -20670,6 +20854,10 @@ snapshots: strip-bom@3.0.0: {} + strip-dirs@2.1.0: + dependencies: + is-natural-number: 4.0.1 + strip-final-newline@2.0.0: {} strip-hex-prefix@1.0.0: @@ -21089,6 +21277,11 @@ snapshots: has-symbols: 1.1.0 which-boxed-primitive: 1.1.1 + unbzip2-stream@1.4.3: + dependencies: + buffer: 5.7.1 + through: 2.3.8 + uncrypto@0.1.3: {} undici-types@6.19.8: {} @@ -21779,6 +21972,11 @@ snapshots: y18n: 5.0.8 yargs-parser: 21.1.1 + yauzl@2.10.0: + dependencies: + buffer-crc32: 0.2.13 + fd-slicer: 1.1.0 + yn@3.1.1: {} yocto-queue@0.1.0: {}