From dc32f185391f44ca7705be213f9321dce846e548 Mon Sep 17 00:00:00 2001 From: ECRZ Date: Tue, 6 Jan 2026 11:01:47 +0800 Subject: [PATCH] =?UTF-8?q?modify=EF=BC=9Aapi=20=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 + commonApi.js | 171 ++++++++++++++++++++++++ loginApi.js | 348 +++++++++++++++++++++++++++++++++++++++++++++++++ package.json | 1 + pnpm-lock.yaml | 94 +++++++++++++ 5 files changed, 617 insertions(+) create mode 100644 commonApi.js create mode 100644 loginApi.js diff --git a/.gitignore b/.gitignore index c6e35a7..e933f37 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,6 @@ build/ # 临时文件 tmp/ temp/ + +# Token 缓存文件(敏感信息) +.token-cache.json diff --git a/commonApi.js b/commonApi.js new file mode 100644 index 0000000..a9120e6 --- /dev/null +++ b/commonApi.js @@ -0,0 +1,171 @@ +const axios = require('axios'); +const login = require('./loginApi.js'); +/** + * 钢材价格数据采集服务 + * 从德钢云平台获取价格数据 + */ +class SteelPriceCollector { + constructor() { + this.baseURL = 'https://xdwlgyl.yciccloud.com'; + this.pageId = 'PG-D615-D8E2-2FD84B8D'; + this.menuId = 'MK-A8B8-109E-13D34116'; + } + + /** + * 构建请求配置(先获取 Token) + * @param {Object} params - 查询参数 + * @param {string} params.startDate - 开始日期 (YYYY-MM-DD) + * @param {string} params.endDate - 结束日期 (YYYY-MM-DD) + * @param {number} params.page - 页码,默认1 + * @param {number} params.pageSize - 每页大小,默认1000 + * @returns {Promise} Axios请求配置 + */ + async _buildConfig(params = {}) { + const { + startDate = new Date().toISOString().split('T')[0], + endDate = new Date(Date.now() + 365 * 24 * 60 * 60 * 1000).toISOString().split('T')[0], + page = 1, + pageSize = 10 + } = params; + + // 先获取 Token + console.log('🔐 正在获取 Token...'); + const tokenResult = await login.getToken(); + + if (!tokenResult.success) { + throw new Error(`Token 获取失败: ${tokenResult.error}`); + } + + const tokenId = tokenResult.data; + console.log('✅ Token 获取成功:', tokenId); + + // 构建查询条件对象 + const searchParams = { + _PIRCE_DATE_DATE_START_: startDate, + _PIRCE_DATE_DATE_END_: endDate, + PARTSNAME_NAME: null, + _PARTSNAME_NAME_ADVANCE_SEARCH_: null, + _PARTSNAME_NAME_IS_LIKE_: '1', + GOODS_MATERIAL: null, + _GOODS_MATERIAL_ADVANCE_SEARCH_: null, + _GOODS_MATERIAL_IS_LIKE_: '1', + GOODS_SPEC: null, + _GOODS_SPEC_ADVANCE_SEARCH_: null, + _GOODS_SPEC_IS_LIKE_: '1', + PRODUCTAREA_NAME: null, + _PRODUCTAREA_NAME_ADVANCE_SEARCH_: null, + _PRODUCTAREA_NAME_IS_LIKE_: '1', + PNTREE_NAME: null, + _PNTREE_NAME_ADVANCE_SEARCH_: null, + _PNTREE_NAME_IS_LIKE_: '1', + OPERATOR_NAME: null, + _OPERATOR_NAME_ADVANCE_SEARCH_: null, + PR_PRICE_REGION: null, + _PR_PRICE_REGION_ADVANCE_SEARCH_: null, + OPERATOR_CODE: null, + PRICE_ID: null, + _orderFields_: [] + }; + + // 构建URL编码的请求体 + const requestData = new URLSearchParams({ + pageId: this.pageId, + pageSize: pageSize.toString(), + page: page.toString(), + isPageNoChange: '0', + ctrlId: 'mainTable', + json: JSON.stringify(searchParams), + searchBoxId: 'searchForm', + groupSumFields: JSON.stringify([]) + }); + + // 使用获取到的 Token 构建 Cookie + const cookie = `SameSite=Lax; HWWAFSESTIME=1767596069712; HWWAFSESID=e2b2773ee2641b98e5; SameSite=Lax; SYS-A7EE-D0E8-BE614B80=1108@${tokenId}; JSESSIONID=2389858DBE6A7EDAF695C767A764995B; SameSite=Lax`; + + return { + method: 'POST', + url: `${this.baseURL}/gdpaas/mainpage/findPage.htm?_p_=${this.pageId}`, + headers: { + 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', + 'Accept': 'application/json, text/javascript, */*; q=0.01', + 'X-Requested-With': 'XMLHttpRequest', + 'Pageid': 'PG_D615_D8E2_2FD84B8D', + 'Menuid': this.menuId, + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', + 'Referer': `${this.baseURL}/gdpaas/home/index.htm`, + 'Origin': this.baseURL, + 'Accept-Language': 'zh-CN,zh;q=0.9', + 'Accept-Encoding': 'gzip, deflate, br', + 'Sec-Fetch-Site': 'same-origin', + 'Sec-Fetch-Mode': 'cors', + 'Sec-Fetch-Dest': 'empty', + 'Sec-Ch-Ua': '"Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120"', + 'Sec-Ch-Ua-Mobile': '?0', + 'Sec-Ch-Ua-Platform': '"Windows"', + 'cookie': cookie + }, + data: requestData.toString() + }; + } + + /** + * 获取钢材价格数据 + * @param {Object} params - 查询参数 + * @returns {Promise} 响应数据 + */ + async fetchPrices(params = {}) { + try { + const config = await this._buildConfig(params); + const response = await axios.request(config); + + // 验证响应数据 + if (!response.data) { + throw new Error('响应数据为空'); + } + + return { + success: true, + data: response.data, + timestamp: new Date().toISOString() + }; + } catch (error) { + return { + success: false, + error: error.message, + timestamp: new Date().toISOString() + }; + } + } +} + +/** + * 导出单例实例 + */ +module.exports = new SteelPriceCollector(); + +/** + * 如果直接运行此文件,执行示例请求 + */ +if (require.main === module) { + const collector = require('./commonApi.js'); + + // 示例:获取最近一年的价格数据 + collector.fetchPrices({ + startDate: '2025-01-06', + endDate: '2026-01-06', + page: 1, + pageSize: 1 + }) + .then(result => { + if (result.success) { + console.log('✅ 数据获取成功'); + console.log('📅 时间:', result.timestamp); + console.log('📊 数据预览:', JSON.stringify(result.data, null, 2)); + } else { + console.error('❌ 数据获取失败:', result.error); + } + }) + .catch(error => { + console.error('💥 未捕获的错误:', error); + }); +} diff --git a/loginApi.js b/loginApi.js new file mode 100644 index 0000000..beb8b81 --- /dev/null +++ b/loginApi.js @@ -0,0 +1,348 @@ +const axios = require("axios"); +const fs = require('fs'); +const path = require('path'); + +/** + * Token 缓存信息 + * @typedef {Object} TokenCache + * @property {string} token - Token 值 + * @property {string} expiresAt - 过期时间 (ISO 字符串) + */ + +/** + * 外部 Token 获取服务 + * 支持文件持久化和自动过期更新 + * @class ExternalToken + */ +class ExternalToken { + constructor() { + /** + * Token 文件存储路径 + * @type {string} + * @private + */ + this._tokenFilePath = path.join(__dirname, '.token-cache.json'); + + /** + * Token 有效期(毫秒),默认 30 分钟 + * @type {number} + * @private + */ + this._tokenValidityMs = 30 * 60 * 1000; + + /** + * 是否正在刷新 Token(防止并发重复请求) + * @type {Promise|null} + * @private + */ + this._refreshingPromise = null; + + /** + * 内存中的 Token 缓存 + * @type {TokenCache|null} + * @private + */ + this._memoryCache = null; + + // 初始化时从文件加载 Token + this._loadTokenFromFile(); + } + + /** + * 从文件加载 Token + * @private + */ + _loadTokenFromFile() { + try { + if (fs.existsSync(this._tokenFilePath)) { + const data = fs.readFileSync(this._tokenFilePath, 'utf-8'); + const cache = JSON.parse(data); + + // 验证数据结构 + if (cache.token && cache.expiresAt) { + this._memoryCache = { + token: cache.token, + expiresAt: new Date(cache.expiresAt) + }; + + const isExpired = this._isTokenExpired(); + console.log(`📂 从文件加载 Token ${isExpired ? '(已过期)' : '(有效)'}`); + console.log(` 过期时间: ${this._memoryCache.expiresAt.toLocaleString('zh-CN')}`); + } else { + console.warn('⚠️ Token 文件格式无效,将重新获取'); + this._memoryCache = null; + } + } else { + console.log('📄 Token 文件不存在,将创建新文件'); + } + } catch (error) { + console.error('❌ 读取 Token 文件失败:', error.message); + this._memoryCache = null; + } + } + + /** + * 保存 Token 到文件 + * @param {string} token - Token 值 + * @private + */ + _saveTokenToFile(token) { + try { + const expiresAt = new Date(Date.now() + this._tokenValidityMs); + const cache = { + token, + expiresAt: expiresAt.toISOString(), + updatedAt: new Date().toISOString() + }; + + fs.writeFileSync(this._tokenFilePath, JSON.stringify(cache, null, 2), 'utf-8'); + console.log(`💾 Token 已保存到文件: ${this._tokenFilePath}`); + console.log(` 过期时间: ${expiresAt.toLocaleString('zh-CN')}`); + } catch (error) { + console.error('❌ 保存 Token 文件失败:', error.message); + } + } + + /** + * 删除 Token 文件 + * @private + */ + _deleteTokenFile() { + try { + if (fs.existsSync(this._tokenFilePath)) { + fs.unlinkSync(this._tokenFilePath); + console.log('🗑️ Token 文件已删除'); + } + } catch (error) { + console.error('❌ 删除 Token 文件失败:', error.message); + } + } + + /** + * 检查 Token 是否过期 + * @returns {boolean} + * @private + */ + _isTokenExpired() { + if (!this._memoryCache) { + return true; + } + + const now = new Date(); + return now >= this._memoryCache.expiresAt; + } + + /** + * 清除 Token 缓存(内存和文件) + */ + clearTokenCache() { + this._memoryCache = null; + this._deleteTokenFile(); + console.log('🗑️ Token 缓存已清除'); + } + + /** + * 设置 Token 有效期 + * @param {number} minutes - 有效期(分钟) + */ + setTokenValidity(minutes) { + this._tokenValidityMs = minutes * 60 * 1000; + console.log(`⏱️ Token 有效期已设置为 ${minutes} 分钟`); + } + + /** + * 获取新的登录 Token + * @returns {Promise} Token 值 + * @throws {Error} 当获取失败时抛出错误 + * @private + */ + async _fetchNewToken() { + const config = { + method: 'POST', + url: 'https://xdwlgyl.yciccloud.com/gdpaas/login/doLogin.htm', + headers: { + 'host': 'xdwlgyl.yciccloud.com', + 'sec-ch-ua': '"Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120"', + 'accept': 'application/json, text/javascript, */*; q=0.01', + 'content-type': 'application/x-www-form-urlencoded; charset=UTF-8', + 'x-requested-with': 'XMLHttpRequest', + 'sec-ch-ua-mobile': '?0', + 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', + 'sec-ch-ua-platform': '"Windows"', + 'origin': 'https://xdwlgyl.yciccloud.com', + 'sec-fetch-site': 'same-origin', + 'sec-fetch-mode': 'cors', + 'sec-fetch-dest': 'empty', + 'referer': 'https://xdwlgyl.yciccloud.com/gdpaas/login/index.htm', + 'accept-encoding': 'gzip, deflate, br', + 'accept-language': 'zh-CN,zh;q=0.9', + 'cookie': 'SYS-A7EE-D0E8-BE614B80=1108%405b2bc1b4b8be40dfb104b1f5c84c1245;SameSite=Lax;HWWAFSESTIME=1767662772583;HWWAFSESID=7817173569731ea415;JSESSIONID=7AF7F82CBD7C1FFC6CBCAF67CFD22AC6', + 'Connection': 'keep-alive' + }, + data: 'userId=15758339512&pwd=4E71002969FCD46813B869E931AEDF4B&randCode=&langId=' + }; + + try { + console.log('🔄 正在请求新 Token...'); + const response = await axios.request(config); + + // 安全地提取 tokenId + const tokenId = response?.data?.data?.user?.exts?.tokenId; + + if (!tokenId) { + throw new Error('响应中未找到 tokenId'); + } + + console.log('✅ 新 Token 获取成功:', tokenId); + + // 保存到内存和文件 + const expiresAt = new Date(Date.now() + this._tokenValidityMs); + this._memoryCache = { token: tokenId, expiresAt }; + this._saveTokenToFile(tokenId); + + return tokenId; + } catch (error) { + const errorMsg = error.response?.data || error.message; + console.error('❌ Token 获取失败:', errorMsg); + throw new Error(`Token 获取失败: ${errorMsg}`); + } + } + + /** + * 获取登录 Token(支持文件持久化和自动过期更新) + * @param {boolean} forceRefresh - 是否强制刷新 Token + * @returns {Promise<{success: boolean, data?: string, error?: string, timestamp: string, cached?: boolean, source?: string}>} + */ + async getToken(forceRefresh = false) { + try { + // 如果未强制刷新且 Token 未过期,直接返回缓存 + if (!forceRefresh && !this._isTokenExpired()) { + const source = this._memoryCache ? '文件缓存' : '内存缓存'; + console.log(`♻️ 使用${source}的 Token`); + return { + success: true, + data: this._memoryCache.token, + timestamp: new Date().toISOString(), + cached: true, + source + }; + } + + // 如果正在刷新,等待刷新完成(防止并发请求) + if (this._refreshingPromise) { + console.log('⏳ Token 刷新中,等待完成...'); + await this._refreshingPromise; + return { + success: true, + data: this._memoryCache.token, + timestamp: new Date().toISOString(), + cached: false, + source: '新获取' + }; + } + + // 开始刷新 Token + this._refreshingPromise = this._fetchNewToken(); + + const token = await this._refreshingPromise; + + // 清除刷新标记 + this._refreshingPromise = null; + + return { + success: true, + data: token, + timestamp: new Date().toISOString(), + cached: false, + source: '新获取' + }; + } catch (error) { + this._refreshingPromise = null; + return { + success: false, + error: error.message, + timestamp: new Date().toISOString() + }; + } + } + + /** + * 获取当前缓存的 Token(不检查过期) + * @returns {string|null} + */ + getCachedToken() { + return this._memoryCache?.token || null; + } + + /** + * 获取 Token 过期时间 + * @returns {Date|null} + */ + getTokenExpiresAt() { + return this._memoryCache?.expiresAt || null; + } + + /** + * 检查 Token 是否即将过期(剩余时间少于 5 分钟) + * @returns {boolean} + */ + isTokenExpiringSoon() { + if (!this._memoryCache) { + return true; + } + + const now = new Date(); + const timeLeft = this._memoryCache.expiresAt - now; + const fiveMinutes = 5 * 60 * 1000; + + return timeLeft < fiveMinutes; + } + + /** + * 获取 Token 剩余有效时间(秒) + * @returns {number|null} 剩余秒数,如果 Token 不存在或已过期返回 null + */ + getTokenRemainingTime() { + if (!this._memoryCache) { + return null; + } + + const now = new Date(); + const timeLeft = Math.max(0, this._memoryCache.expiresAt - now); + return Math.floor(timeLeft / 1000); + } + + /** + * 获取 Token 文件路径 + * @returns {string} + */ + getTokenFilePath() { + return this._tokenFilePath; + } +} + +/** + * 导出单例实例 + */ +module.exports = new ExternalToken(); + +/** + * 如果直接运行此文件,执行示例请求 + */ +if (require.main === module) { + const collector = require('./loginApi.js'); + + collector.getToken() + .then(result => { + if (result.success) { + console.log('✅ 数据获取成功'); + console.log('📅 时间:', result.timestamp); + console.log('📊 数据预览:', JSON.stringify(result.data, null, 2)); + } else { + console.error('❌ 数据获取失败:', result.error); + } + }) + .catch(error => { + console.error('💥 未捕获的错误:', error); + }); +} diff --git a/package.json b/package.json index e2a6707..d71a81b 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "author": "", "license": "MIT", "dependencies": { + "axios": "^1.13.2", "cors": "^2.8.5", "dotenv": "^17.2.3", "express": "^5.2.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e54ea16..1f3efc7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,9 @@ importers: .: dependencies: + axios: + specifier: ^1.13.2 + version: 1.13.2 cors: specifier: ^2.8.5 version: 2.8.5 @@ -63,10 +66,16 @@ packages: argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + aws-ssl-profiles@1.1.2: resolution: {integrity: sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==} engines: {node: '>= 6.0.0'} + axios@1.13.2: + resolution: {integrity: sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==} + balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} @@ -96,6 +105,10 @@ packages: call-me-maybe@1.0.2: resolution: {integrity: sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==} + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + commander@6.2.0: resolution: {integrity: sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q==} engines: {node: '>= 6'} @@ -144,6 +157,10 @@ packages: supports-color: optional: true + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + denque@2.1.0: resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==} engines: {node: '>=0.10'} @@ -183,6 +200,10 @@ packages: resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} engines: {node: '>= 0.4'} + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + escape-html@1.0.3: resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} @@ -202,6 +223,19 @@ packages: resolution: {integrity: sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==} engines: {node: '>= 18.0.0'} + follow-redirects@1.15.11: + resolution: {integrity: sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + form-data@4.0.5: + resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} + engines: {node: '>= 6'} + forwarded@0.2.0: resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} engines: {node: '>= 0.6'} @@ -239,6 +273,10 @@ packages: resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} engines: {node: '>= 0.4'} + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + hasown@2.0.2: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} @@ -302,10 +340,18 @@ packages: resolution: {integrity: sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==} engines: {node: '>=18'} + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + mime-db@1.54.0: resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} engines: {node: '>= 0.6'} + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + mime-types@3.0.2: resolution: {integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==} engines: {node: '>=18'} @@ -376,6 +422,9 @@ packages: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} engines: {node: '>= 0.10'} + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + qs@6.14.1: resolution: {integrity: sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==} engines: {node: '>=0.6'} @@ -522,8 +571,18 @@ snapshots: argparse@2.0.1: {} + asynckit@0.4.0: {} + aws-ssl-profiles@1.1.2: {} + axios@1.13.2: + dependencies: + follow-redirects: 1.15.11 + form-data: 4.0.5 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + balanced-match@1.0.2: {} basic-auth@2.0.1: @@ -563,6 +622,10 @@ snapshots: call-me-maybe@1.0.2: {} + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + commander@6.2.0: {} commander@9.5.0: @@ -591,6 +654,8 @@ snapshots: dependencies: ms: 2.1.3 + delayed-stream@1.0.0: {} + denque@2.1.0: {} depd@2.0.0: {} @@ -619,6 +684,13 @@ snapshots: dependencies: es-errors: 1.3.0 + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + escape-html@1.0.3: {} esutils@2.0.3: {} @@ -669,6 +741,16 @@ snapshots: transitivePeerDependencies: - supports-color + follow-redirects@1.15.11: {} + + form-data@4.0.5: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + hasown: 2.0.2 + mime-types: 2.1.35 + forwarded@0.2.0: {} fresh@2.0.0: {} @@ -712,6 +794,10 @@ snapshots: has-symbols@1.1.0: {} + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + hasown@2.0.2: dependencies: function-bind: 1.1.2 @@ -761,8 +847,14 @@ snapshots: merge-descriptors@2.0.0: {} + mime-db@1.52.0: {} + mime-db@1.54.0: {} + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + mime-types@3.0.2: dependencies: mime-db: 1.54.0 @@ -834,6 +926,8 @@ snapshots: forwarded: 0.2.0 ipaddr.js: 1.9.1 + proxy-from-env@1.1.0: {} + qs@6.14.1: dependencies: side-channel: 1.1.0