From 94c504067dea42a28377c545ab2f25aabb81ff9d Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 26 May 2025 11:22:29 +0200 Subject: [PATCH] setting up data menu and service --- src/main.js | 5 ++++ src/services/dataService.js | 56 +++++++++++++++++++++++++++++++++++++ src/ui/dataMenu.js | 36 ++++++++++++++++++++++++ src/ui/mainMenu.js | 38 ++++++------------------- src/ui/mainMenu.test.js | 5 +++- 5 files changed, 109 insertions(+), 31 deletions(-) create mode 100644 src/services/dataService.js create mode 100644 src/ui/dataMenu.js diff --git a/src/main.js b/src/main.js index c10ebcb..a4bca65 100644 --- a/src/main.js +++ b/src/main.js @@ -36,6 +36,8 @@ import { CodexGlobals } from "./services/codexGlobals.js"; import { CodexApp } from "./services/codexApp.js"; import { EthersService } from "./services/ethersService.js"; import { MarketplaceSetup } from "./ui/marketplaceSetup.js"; +import { DataService } from "./services/dataService.js"; +import { DataMenu } from "./ui/dataMenu.js"; async function showNavigationMenu() { console.log("\n"); @@ -147,6 +149,8 @@ export async function main() { fsService, codexGlobals, ); + const dataService = new DataService(configService); + const dataMenu = new DataMenu(uiService, fsService, dataService); const mainMenu = new MainMenu( uiService, new MenuLoop(), @@ -155,6 +159,7 @@ export async function main() { installer, processControl, codexApp, + dataMenu, ); await mainMenu.show(); diff --git a/src/services/dataService.js b/src/services/dataService.js new file mode 100644 index 0000000..abc1a00 --- /dev/null +++ b/src/services/dataService.js @@ -0,0 +1,56 @@ +import { Codex } from "@codex-storage/sdk-js"; +import { NodeUploadStategy } from "@codex-storage/sdk-js/node"; +import mime from "mime-types"; +import path from "path"; +import fs from "fs"; + +export class DataService { + constructor(configService) { + this.configService = configService; + } + + upload = async (filePath) => { + const data = this.getCodexData(); + const filename = path.basename(filePath); + const contentType = mime.lookup(filePath) || "application/octet-stream"; + const fileData = fs.readFileSync(filePath); + + const strategy = new NodeUploadStategy(fileData, { + filename: filename, + mimetype: contentType, + }); + const uploadResponse = data.upload(strategy); + const res = await uploadResponse.result; + + if (res.error) { + throw new Exception(res.data); + } + return res.data; + }; + + download = async (cid) => { + const data = this.getCodexData(); + const manifest = await data.fetchManifest(cid); + const filename = this.getFilename(manifest); + + const response = await data.networkDownloadStream(cid); + const fileData = response.data; + + fs.writeFileSync(filename, fileData); + }; + + getCodexData = () => { + const config = this.configService.get(); + const url = `http://localhost:${config.ports.apiPort}`; + const codex = new Codex(url); + return codex.data; + }; + + getFilename = (manifest) => { + const defaultFilename = "unknown_" + Math.random(); + const filename = manifest?.data?.manifest?.filename; + + if (filename == undefined || filename.length < 1) return defaultFilename; + return filename; + }; +} diff --git a/src/ui/dataMenu.js b/src/ui/dataMenu.js new file mode 100644 index 0000000..456b97b --- /dev/null +++ b/src/ui/dataMenu.js @@ -0,0 +1,36 @@ +export class DataMenu { + constructor(uiService, fsService, dataService) { + this.ui = uiService; + this.fs = fsService; + this.dataService = dataService; + } + + performUpload = async () => { + this.ui.showInfoMessage( + "⚠️ Codex does not encrypt files. Anything uploaded will be available publicly on testnet.", + ); + + const filePath = this.ui.askPrompt("Enter the file path"); + if (!this.fs.isFile(filePath)) { + this.ui.showErrorMessage("File not found"); + } else { + try { + const cid = this.dataService.upload(filePath); + this.ui.showInfoMessage(`Upload successful.\n CID: '${cid}'`); + } catch (exception) { + this.ui.showErrorMessage("Error during upload: " + exception); + } + } + }; + + performDownload = async () => { + const cid = this.ui.askPrompt("Enter the CID"); + if (cid.length < 1) return; + try { + const filename = this.dataService.download(cid); + this.ui.showInfoMessage(`Download successful.\n File: '${filename}'`); + } catch (exception) { + this.ui.showErrorMessage("Error during download: " + exception); + } + }; +} diff --git a/src/ui/mainMenu.js b/src/ui/mainMenu.js index ad7f768..1c02562 100644 --- a/src/ui/mainMenu.js +++ b/src/ui/mainMenu.js @@ -1,6 +1,3 @@ -import { Codex } from "@codex-storage/sdk-js"; -import { NodeUploadStategy } from "@codex-storage/sdk-js/node"; - export class MainMenu { constructor( uiService, @@ -10,6 +7,7 @@ export class MainMenu { installer, processControl, codexApp, + dataMenu, ) { this.ui = uiService; this.loop = menuLoop; @@ -18,6 +16,7 @@ export class MainMenu { this.installer = installer; this.processControl = processControl; this.codexApp = codexApp; + this.dataMenu = dataMenu; this.loop.initialize(this.promptMainMenu); } @@ -64,8 +63,12 @@ export class MainMenu { action: this.stopCodex, }, { - label: "DoThing", - action: this.doThing, + label: "Upload a file", + action: this.dataMenu.performUpload, + }, + { + label: "Download a file", + action: this.dataMenu.performDownload, }, { label: "Exit (Codex keeps running)", @@ -116,29 +119,4 @@ export class MainMenu { this.ui.showErrorMessage(`Failed to stop Codex. "${exception}"`); } }; - - doThing = async () => { - console.log("A!"); - - const codex = new Codex("http://localhost:8080"); - const data = codex.data; - - const stategy = new NodeUploadStategy("Hello World !"); - const uploadResponse = data.upload(stategy); - - const res = await uploadResponse.result; - - if (res.error) { - console.error(res.data); - return; - } - - console.info("CID is", res.data); - const cid = res.data; - - const result = await data.networkDownloadStream(cid); - - console.log("download: " + JSON.stringify(result)); - - } } diff --git a/src/ui/mainMenu.test.js b/src/ui/mainMenu.test.js index f3318db..445af30 100644 --- a/src/ui/mainMenu.test.js +++ b/src/ui/mainMenu.test.js @@ -110,7 +110,10 @@ describe("mainmenu", () => { [ { label: "Open Codex app", action: mockCodexApp.openCodexApp }, { label: "Stop Codex", action: mainmenu.stopCodex }, - { label: "Exit (Codex keeps running)", action: mockMenuLoop.stopLoop }, + { + label: "Exit (Codex keeps running)", + action: mockMenuLoop.stopLoop, + }, ], ); });