diff --git a/crafty.js b/crafty.js index 9958ce0..40da564 100644 --- a/crafty.js +++ b/crafty.js @@ -1,4 +1,8 @@ const axios = require('axios'); +const https = require('https'); +const FormData = require('form-data'); +const fs = require('fs'); +const path = require('path'); class CraftyClient { constructor(baseUrl, token) { @@ -9,16 +13,25 @@ class CraftyClient { headers: { 'Authorization': `Bearer ${this.token}`, 'Content-Type': 'application/json' - } + }, + httpsAgent: new https.Agent({ + rejectUnauthorized: false + }) }); } async testConnection() { try { - const resp = await this.client.get('/stats'); + const resp = await this.client.get('/servers'); return resp.status === 200; } catch (err) { - console.error('Crafty Connection Error:', err.message); + if (err.response) { + console.error(`Crafty Connection Error: ${err.response.status} - ${JSON.stringify(err.response.data)}`); + } else if (err.request) { + console.error(`Crafty Connection Error: No response received. Check if your CRAFTY_URL is correct and reachable.`); + } else { + console.error('Crafty Connection Error:', err.message); + } return false; } } @@ -44,6 +57,30 @@ class CraftyClient { const resp = await this.client.post('/servers', payload); return resp.data.data; } + + async uploadFile(serverId, localFilePath, remotePath = 'mods') { + const stats = fs.statSync(localFilePath); + const fileName = path.basename(localFilePath); + const fileId = Math.random().toString(36).substring(2, 15); + + // Remove leading slash for 'location' header + const targetLocation = remotePath.replace(/^\//, ''); + + console.log(` Sending raw binary to Crafty (${(stats.size / 1024 / 1024).toFixed(2)} MB)...`); + + const resp = await this.client.post(`/servers/${serverId}/files/upload`, fs.createReadStream(localFilePath), { + headers: { + 'Content-Type': 'application/octet-stream', + 'location': targetLocation, + 'fileName': fileName, + 'fileSize': stats.size.toString(), + 'fileId': fileId + }, + maxContentLength: Infinity, + maxBodyLength: Infinity + }); + return resp.data; + } } module.exports = CraftyClient; diff --git a/curseforge.js b/curseforge.js index 23ae3ae..703f8c3 100644 --- a/curseforge.js +++ b/curseforge.js @@ -11,13 +11,20 @@ class CurseForgeHandler { } async getMod(id) { - // identifier can be numeric ID or slug (though the library might need specific search for slug) - if (isNaN(id)) { - const results = await this.client.searchMods({ slug: id }); + // Extract ID/slug from URL if needed + let identifier = id; + if (id.includes('curseforge.com')) { + const parts = id.split('/'); + identifier = parts[parts.length - 1] || parts[parts.length - 2]; + } + + if (isNaN(identifier)) { + // 432 is the ID for Minecraft + const results = await this.client.searchMods(432, { slug: identifier }); if (results.data.length === 0) throw new Error('Mod not found'); return results.data[0]; } - return await this.client.getMod(id); + return await this.client.getMod(identifier); } async getFiles(id) { diff --git a/index.js b/index.js index f24b890..8d791d5 100644 --- a/index.js +++ b/index.js @@ -80,74 +80,100 @@ async function main() { targetServerId = selection; } - // 4. Mod Selection - const { platform } = await inquirer.prompt([ - { - type: 'list', - name: 'platform', - message: 'Which platform are you using?', - choices: ['Modrinth', 'CurseForge'] - } - ]); - - const { identifier } = await inquirer.prompt([ - { - type: 'input', - name: 'identifier', - message: `Enter ${platform} Link or ID:` - } - ]); - - // 5. Installation - console.log('🔄 Preparing installation...'); - - // Determine final target directory - let targetDir = ''; - if (isLocal) { - const serverInfo = await crafty.getServerDetails(targetServerId); - // Crafty stores servers in folders named by their UUID or name - // We assume the folder is in the base serverPath - targetDir = path.join(serverPath, serverInfo.server_id); - // Note: Crafty 4 might use specific naming, we should verify info.path - if (serverInfo.path) targetDir = serverInfo.path; - } else { - targetDir = path.join(process.cwd(), 'temp_server_files'); - await fs.ensureDir(targetDir); - } - - if (platform === 'Modrinth') { - const project = await modrinth.getProject(identifier); - const versions = await modrinth.getVersions(project.id); - const { versionSelection } = await inquirer.prompt([ + // 4. Mod Selection Loop + let keepInstalling = true; + while (keepInstalling) { + const { platform } = await inquirer.prompt([ { type: 'list', - name: 'versionSelection', - message: 'Select a version to install:', - choices: versions.slice(0, 10).map(v => ({ name: `${v.version_number} (${v.loaders.join(', ')})`, value: v.id })) + name: 'platform', + message: 'Which platform are you using?', + choices: ['Modrinth', 'CurseForge'] } ]); - await modrinth.installModpack(versionSelection, targetDir); - } else { - const mod = await curseforge.getMod(identifier); - const files = await curseforge.getFiles(mod.id); - const { fileSelection } = await inquirer.prompt([ - { - type: 'list', - name: 'fileSelection', - message: 'Select a file to install:', - choices: files.slice(0, 10).map(f => ({ name: f.displayName, value: f.id })) - } - ]); - await curseforge.installModpack(mod.id, fileSelection, targetDir); - } - if (!isLocal) { - console.log('🚀 Remote mode: Files are in ./temp_server_files. Please upload them to Crafty.'); - } else { - console.log(`✅ Success! Files installed to: ${targetDir}`); + const { identifier } = await inquirer.prompt([ + { + type: 'input', + name: 'identifier', + message: `Enter ${platform} Link or ID:` + } + ]); + + // 5. Installation + console.log('🔄 Preparing installation...'); + + // Determine final target directory + let targetDir = ''; + if (isLocal) { + const serverInfo = await crafty.getServerDetails(targetServerId); + targetDir = serverInfo.path || path.join(serverPath, serverInfo.server_id); + } else { + targetDir = path.join(process.cwd(), 'temp_server_files'); + await fs.ensureDir(targetDir); + } + + if (platform === 'Modrinth') { + const project = await modrinth.getProject(identifier); + const versions = await modrinth.getVersions(project.id); + const { versionSelection } = await inquirer.prompt([ + { + type: 'list', + name: 'versionSelection', + message: 'Select a version to install:', + choices: versions.slice(0, 10).map(v => ({ + name: `${v.version_number} [MC: ${v.game_versions.join(', ')}] (${v.loaders.join(', ')})`, + value: v.id + })) + } + ]); + await modrinth.installMod(versionSelection, targetDir); + } else { + const mod = await curseforge.getMod(identifier); + const files = await curseforge.getFiles(mod.id); + const { fileSelection } = await inquirer.prompt([ + { + type: 'list', + name: 'fileSelection', + message: 'Select a file to install:', + choices: files.slice(0, 10).map(f => ({ + name: `${f.displayName} [MC: ${f.gameVersions.join(', ')}]`, + value: f.id + })) + } + ]); + await curseforge.installModpack(mod.id, fileSelection, targetDir); + } + + if (!isLocal) { + console.log('🚀 Remote mode: Syncing files to Crafty...'); + const modsDir = path.join(targetDir, 'mods'); + if (await fs.pathExists(modsDir)) { + const files = await fs.readdir(modsDir); + for (const file of files) { + console.log(` Uploading ${file} to Crafty...`); + await crafty.uploadFile(targetServerId, path.join(modsDir, file), 'mods'); + } + } + console.log('✅ Remote sync complete!'); + await fs.remove(targetDir); + } else { + console.log(`✅ Success! Files installed to: ${targetDir}`); + } + + const { another } = await inquirer.prompt([ + { + type: 'confirm', + name: 'another', + message: 'Do you want to install another mod?', + default: false + } + ]); + keepInstalling = another; } } catch (err) { console.error('❌ Error:', err.message); + if (err.response) console.log(JSON.stringify(err.response.data)); } } diff --git a/modrinth.js b/modrinth.js index 157aa31..c60b2d2 100644 --- a/modrinth.js +++ b/modrinth.js @@ -12,7 +12,13 @@ class ModrinthHandler { } async getProject(id) { - const resp = await this.client.get(`/project/${id}`); + // Extract slug from URL if needed + let slug = id; + if (id.includes('modrinth.com')) { + const parts = id.split('/'); + slug = parts[parts.length - 1] || parts[parts.length - 2]; + } + const resp = await this.client.get(`/project/${slug}`); return resp.data; } @@ -21,6 +27,11 @@ class ModrinthHandler { return resp.data; } + async getVersions(projectId) { + const resp = await this.client.get(`/project/${projectId}/version`); + return resp.data; + } + async downloadFile(url, targetPath) { const response = await axios({ url, @@ -35,13 +46,29 @@ class ModrinthHandler { }); } - async installModpack(versionId, targetDir) { - console.log(`Downloading Modrinth pack version: ${versionId}...`); + async installMod(versionId, targetDir) { + console.log(`Downloading Modrinth file version: ${versionId}...`); const version = await this.getVersion(versionId); - const mrpackFile = version.files.find(f => f.filename.endsWith('.mrpack')); - if (!mrpackFile) throw new Error('No .mrpack file found in this version'); + // Find .mrpack for modpacks or the primary .jar for mods + const packFile = version.files.find(f => f.filename.endsWith('.mrpack')); + if (packFile) { + return await this.installModpack(version, packFile, targetDir); + } + const jarFile = version.files.find(f => f.primary) || version.files[0]; + if (!jarFile) throw new Error('No files found for this version'); + + const modsDir = path.join(targetDir, 'mods'); + await fs.ensureDir(modsDir); + const destPath = path.join(modsDir, jarFile.filename); + + console.log(` Downloading ${jarFile.filename}...`); + await this.downloadFile(jarFile.url, destPath); + console.log('✅ Mod installation complete!'); + } + + async installModpack(version, mrpackFile, targetDir) { const tempPath = path.join(process.cwd(), 'temp_pack.mrpack'); await this.downloadFile(mrpackFile.url, tempPath); @@ -51,11 +78,7 @@ class ModrinthHandler { const index = JSON.parse(zip.readAsText(indexEntry)); - // Ensure mods directory exists - const modsDir = path.join(targetDir, 'mods'); - await fs.ensureDir(modsDir); - - console.log(`Downloading ${index.files.length} mods...`); + console.log(`Downloading ${index.files.length} mods from pack...`); for (const file of index.files) { const destPath = path.join(targetDir, file.path); await fs.ensureDir(path.dirname(destPath)); @@ -65,11 +88,25 @@ class ModrinthHandler { // Handle overrides console.log('Applying overrides...'); - zip.extractAllTo(targetDir, true); // This is a simplification; should only extract 'overrides' folder - // TODO: Properly merge overrides folder contents into root + const overridesDir = 'overrides'; + const zipEntries = zip.getEntries(); + zipEntries.forEach(entry => { + if (entry.entryName.startsWith(overridesDir + '/')) { + const relativePath = entry.entryName.substring(overridesDir.length + 1); + if (relativePath) { + const dest = path.join(targetDir, relativePath); + if (entry.isDirectory) { + fs.ensureDirSync(dest); + } else { + fs.ensureDirSync(path.dirname(dest)); + fs.writeFileSync(dest, entry.getData()); + } + } + } + }); await fs.remove(tempPath); - console.log('Modpack installation complete!'); + console.log('✅ Modpack installation complete!'); } } diff --git a/package-lock.json b/package-lock.json index 77e8010..e38549d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,38 +12,9 @@ "axios": "^1.6.0", "curseforge-api": "^1.2.0", "dotenv": "^16.3.1", - "fs-extra": "^11.1.1", - "inquirer": "^9.2.11" - } - }, - "node_modules/@inquirer/external-editor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.3.tgz", - "integrity": "sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==", - "license": "MIT", - "dependencies": { - "chardet": "^2.1.1", - "iconv-lite": "^0.7.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/figures": { - "version": "1.0.15", - "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.15.tgz", - "integrity": "sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==", - "license": "MIT", - "engines": { - "node": ">=18" + "form-data": "^4.0.5", + "fs-extra": "^11.3.4", + "inquirer": "^8.2.5" } }, "node_modules/adm-zip": { @@ -196,9 +167,9 @@ } }, "node_modules/chardet": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-2.1.1.tgz", - "integrity": "sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", "license": "MIT" }, "node_modules/cli-cursor": { @@ -226,12 +197,12 @@ } }, "node_modules/cli-width": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", - "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", "license": "ISC", "engines": { - "node": ">= 12" + "node": ">= 10" } }, "node_modules/clone": { @@ -377,6 +348,44 @@ "node": ">= 0.4" } }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "license": "MIT", + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/follow-redirects": { "version": "1.16.0", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", @@ -540,19 +549,15 @@ } }, "node_modules/iconv-lite": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", - "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "license": "MIT", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" + "safer-buffer": ">= 2.1.2 < 3" }, "engines": { "node": ">=0.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" } }, "node_modules/ieee754": { @@ -582,26 +587,29 @@ "license": "ISC" }, "node_modules/inquirer": { - "version": "9.3.8", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.3.8.tgz", - "integrity": "sha512-pFGGdaHrmRKMh4WoDDSowddgjT1Vkl90atobmTeSmcPGdYiwikch/m/Ef5wRaiamHejtw0cUUMMerzDUXCci2w==", + "version": "8.2.5", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.5.tgz", + "integrity": "sha512-QAgPDQMEgrDssk1XiwwHoOGYF9BAbUcc1+j+FhEvaOt8/cKRqyLn0U5qA6F74fGhTMGxf92pOvPBeh29jQJDTQ==", "license": "MIT", "dependencies": { - "@inquirer/external-editor": "^1.0.2", - "@inquirer/figures": "^1.0.3", - "ansi-escapes": "^4.3.2", - "cli-width": "^4.1.0", - "mute-stream": "1.0.0", + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", "ora": "^5.4.1", - "run-async": "^3.0.0", - "rxjs": "^7.8.1", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^6.2.0", - "yoctocolors-cjs": "^2.1.2" + "run-async": "^2.4.0", + "rxjs": "^7.5.5", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6", + "wrap-ansi": "^7.0.0" }, "engines": { - "node": ">=18" + "node": ">=12.0.0" } }, "node_modules/is-fullwidth-code-point": { @@ -646,6 +654,12 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/lodash": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "license": "MIT" + }, "node_modules/log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", @@ -702,13 +716,10 @@ } }, "node_modules/mute-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", - "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "license": "ISC" }, "node_modules/onetime": { "version": "5.1.2", @@ -748,6 +759,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/proxy-from-env": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", @@ -785,9 +805,9 @@ } }, "node_modules/run-async": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz", - "integrity": "sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", "license": "MIT", "engines": { "node": ">=0.12.0" @@ -881,6 +901,24 @@ "node": ">=8" } }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "license": "MIT" + }, + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "license": "MIT", + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", @@ -924,9 +962,9 @@ } }, "node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", @@ -934,19 +972,10 @@ "strip-ansi": "^6.0.0" }, "engines": { - "node": ">=8" - } - }, - "node_modules/yoctocolors-cjs": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.3.tgz", - "integrity": "sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==", - "license": "MIT", - "engines": { - "node": ">=18" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } } } diff --git a/package.json b/package.json index 67ebd38..4c68687 100644 --- a/package.json +++ b/package.json @@ -7,11 +7,12 @@ "start": "node index.js" }, "dependencies": { + "adm-zip": "^0.5.10", "axios": "^1.6.0", "curseforge-api": "^1.2.0", "dotenv": "^16.3.1", - "inquirer": "^9.2.11", - "adm-zip": "^0.5.10", - "fs-extra": "^11.1.1" + "form-data": "^4.0.5", + "fs-extra": "^11.3.4", + "inquirer": "^8.2.5" } }