diff --git a/package.json b/package.json index aae0e06..e7ba31e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rs-bundler", - "version": "0.13.1", + "version": "0.14.0", "description": "RageStudio Bundler Utility GUI", "main": "./out/main/index.js", "author": "RageStudio", diff --git a/src/main/commands/install.js b/src/main/commands/install.js index be0bb9e..7f84c19 100644 --- a/src/main/commands/install.js +++ b/src/main/commands/install.js @@ -43,6 +43,8 @@ export default async function install(manifest) { await fs.rmSync(pkg.install_path, { recursive: true }) } + console.log(`[${pkg_id}] install() | creating install path [${pkg.install_path}]...`) + await fs.mkdirSync(pkg.install_path, { recursive: true }) // append to db diff --git a/src/main/generic_steps/http.js b/src/main/generic_steps/http.js index d25f611..4fe6975 100644 --- a/src/main/generic_steps/http.js +++ b/src/main/generic_steps/http.js @@ -93,6 +93,8 @@ export default async (manifest, step) => { await extractFile(_path, step.extract) if (step.delete_after_extract) { + console.log(`[${manifest.id}] steps.http() | Deleting temporal file [${_path}]...`) + sendToRender(`pkg:update:status:${manifest.id}`, { statusText: `Deleting temporal files...`, }) diff --git a/src/main/lib/execa/public_lib.js b/src/main/lib/execa/public_lib.js new file mode 100644 index 0000000..329057d --- /dev/null +++ b/src/main/lib/execa/public_lib.js @@ -0,0 +1,17 @@ +import { execa } from "." +import path from "node:path" + +export default class ExecLib { + constructor(manifest) { + this.manifest = manifest + } + + async file(file, args, options) { + file = path.resolve(this.manifest.install_path, file) + + return await execa(file, [...args], { + ...options, + cwd: this.manifest.install_path, + }) + } +} \ No newline at end of file diff --git a/src/main/lib/mcl/index.js b/src/main/lib/mcl/index.js index 3a026c3..a280b5a 100644 --- a/src/main/lib/mcl/index.js +++ b/src/main/lib/mcl/index.js @@ -9,7 +9,7 @@ export default class MCL { * @param {string} password - the password of the user * @return {Promise} the authentication information */ - static async auth(username, password) { + async auth(username, password) { return await Authenticator.getAuth(username, password) } @@ -19,7 +19,7 @@ export default class MCL { * @param {Object} opts - The options to be passed for launching the client. * @return {Promise} A promise that resolves with the launched client. */ - static async launch(opts, callbacks) { + async launch(opts, callbacks) { const launcher = new Client() launcher.on("debug", (e) => console.log(e)) diff --git a/src/main/lib/public_bind.js b/src/main/lib/public_bind.js index 4adcc04..61c0674 100644 --- a/src/main/lib/public_bind.js +++ b/src/main/lib/public_bind.js @@ -1,7 +1,11 @@ import MCL from "./mcl" import RendererIPC from "./renderer_ipc" +import rfs from "./rfs" +import exec from "./execa/public_lib" export default { mcl: MCL, ipc: RendererIPC, + rfs: rfs, + exec: exec, } \ No newline at end of file diff --git a/src/main/lib/renderer_ipc/index.js b/src/main/lib/renderer_ipc/index.js index 0050a9d..6a1cc1f 100644 --- a/src/main/lib/renderer_ipc/index.js +++ b/src/main/lib/renderer_ipc/index.js @@ -1,7 +1,7 @@ import sendToRender from "../../utils/sendToRender" export default class RendererIPC { - static async send(...args) { + async send(...args) { return await sendToRender(...args) } } \ No newline at end of file diff --git a/src/main/lib/rfs/index.js b/src/main/lib/rfs/index.js new file mode 100644 index 0000000..4461cd5 --- /dev/null +++ b/src/main/lib/rfs/index.js @@ -0,0 +1,76 @@ +import path from "node:path" +import fs from "node:fs" +import { execa } from "../../lib/execa" +import Vars from "../../vars" + +async function readDirRecurse(dir, maxDepth=3, current = 0) { + if (current > maxDepth) { + return [] + } + + const files = await fs.promises.readdir(dir) + + const promises = files.map(async (file) => { + const filePath = path.join(dir, file) + const stat = await fs.promises.stat(filePath) + + if (stat.isDirectory()) { + return readDirRecurse(filePath, maxDepth, current + 1) + } + + return filePath + }) + + return (await Promise.all(promises)).flat() +} + +export default class RFS { + constructor(manifest) { + this.manifest = manifest + } + + async mount(remote_dir, to, cb) { + let mountPoint = path.resolve(this.manifest.install_path) + + if (typeof to === "string") { + mountPoint = path.join(mountPoint, to) + } else { + mountPoint = path.join(mountPoint, "rfs_mount") + } + + // check if already mounted + if (fs.existsSync(mountPoint)) { + return true + } + + const process = execa( + Vars.rclone_path, + [ + "mount", + "--vfs-cache-mode", + "full", + "--http-url", + remote_dir, + ":http:", + mountPoint, + ], { + stdout: "inherit", + stderr: "inherit", + }) + + await new Promise((r) => { + setTimeout(r, 1000) + }) + + // // try to read from the mount point + // let dirs = await readDirRecurse(mountPoint) + + // console.log(dirs) + + if (typeof cb === "function") { + cb(process) + } + + return process + } +} \ No newline at end of file diff --git a/src/main/setup.js b/src/main/setup.js index c196f57..e1b9016 100644 --- a/src/main/setup.js +++ b/src/main/setup.js @@ -34,6 +34,7 @@ async function main() { let sevenzip_exec = Vars.sevenzip_path let git_exec = Vars.git_path + let rclone_exec = Vars.rclone_path if (!fs.existsSync(sevenzip_exec)) { global.win.webContents.send("initializing_text", "Downloading 7z binaries...") @@ -79,10 +80,39 @@ async function main() { await new Promise((resolve, reject) => { fs.createReadStream(tempPath).pipe(unzipper.Extract({ path: binPath })).on("close", resolve).on("error", reject) }) + + fs.unlinkSync(tempPath) + } + + if (!fs.existsSync(Vars.rclone_path)) { + console.log(`Downloading rclone binaries...`) + global.win.webContents.send("initializing_text", "Downloading rclone binaries...") + + const tempPath = path.resolve(binariesPath, "rclone-bin.zip") + + let url = resolveDestBin(`https://storage.ragestudio.net/rstudio/binaries/rclone`, "rclone-bin.zip") + + await streamPipeline( + got.stream(url), + fs.createWriteStream(tempPath) + ) + + global.win.webContents.send("initializing_text", "Extracting rclone binaries...") + + await new Promise((resolve, reject) => { + fs.createReadStream(tempPath).pipe(unzipper.Extract({ path: path.resolve(binariesPath, "rclone-bin") })).on("close", resolve).on("error", reject) + }) + + if (os.platform() !== "win32") { + ChildProcess.execSync("chmod +x " + Vars.rclone_path) + } + + fs.unlinkSync(tempPath) } console.log(`7z binaries: ${sevenzip_exec}`) console.log(`GIT binaries: ${git_exec}`) + console.log(`rclone binaries: ${rclone_exec}`) } export default main \ No newline at end of file diff --git a/src/main/utils/initManifest.js b/src/main/utils/initManifest.js index f87bf42..2cf2677 100644 --- a/src/main/utils/initManifest.js +++ b/src/main/utils/initManifest.js @@ -5,12 +5,16 @@ import lodash from "lodash" import Vars from "../vars" import PublicLibs from "../lib/public_bind" -async function importLib(libs) { +async function importLib(libs, bindCtx) { const libraries = {} - for (const lib of libs) { + for await (const lib of libs) { if (PublicLibs[lib]) { - libraries[lib] = PublicLibs[lib] + if (typeof PublicLibs[lib] === "function") { + libraries[lib] = new PublicLibs[lib](bindCtx) + }else { + libraries[lib] = PublicLibs[lib] + } } } @@ -36,7 +40,12 @@ export default async (manifest = {}) => { } if (Array.isArray(manifest.import_libs)) { - manifest.libraries = await importLib(manifest.import_libs) + manifest.libraries = await importLib(manifest.import_libs, { + id: manifest.id, + version: manifest.version, + install_path: install_path, + }) + console.log(`[${manifest.id}] initManifest() | Using libraries: ${manifest.import_libs.join(", ")}`) } diff --git a/src/main/vars.js b/src/main/vars.js index d327ca9..d5c44b5 100644 --- a/src/main/vars.js +++ b/src/main/vars.js @@ -14,12 +14,14 @@ global.LOCAL_DB = upath.normalizeSafe(path.join(global.RUNTIME_PATH, "local_db.j global.SEVENZIP_PATH = upath.normalizeSafe(path.resolve(global.BINARIES_PATH, "7z-bin", process.platform === "win32" ? "7za.exe" : "7za")) global.GIT_PATH = upath.normalizeSafe(path.resolve(global.BINARIES_PATH, "git-bin", "bin", process.platform === "win32" ? "git.exe" : "git")) +global.RCLONE_PATH = upath.normalizeSafe(path.resolve(global.BINARIES_PATH, "rclone-bin", process.platform === "win32" ? "rclone.exe" : "rclone")) export default { binaries_path: global.BINARIES_PATH, sevenzip_path: global.SEVENZIP_PATH, git_path: global.GIT_PATH, + rclone_path: global.RCLONE_PATH, runtime_path: global.RUNTIME_PATH, packages_path: global.PACKAGES_PATH,