diff --git a/src/__mocks__/service.mocks.js b/src/__mocks__/service.mocks.js index 09600e3..f0c0158 100644 --- a/src/__mocks__/service.mocks.js +++ b/src/__mocks__/service.mocks.js @@ -5,7 +5,7 @@ export const mockUiService = { showInfoMessage: vi.fn(), showErrorMessage: vi.fn(), askMultipleChoice: vi.fn(), - askPrompt: vi.fn() + askPrompt: vi.fn(), }; export const mockConfigService = { diff --git a/src/__mocks__/ui.mocks.js b/src/__mocks__/ui.mocks.js index ad74c7d..1b0b0e2 100644 --- a/src/__mocks__/ui.mocks.js +++ b/src/__mocks__/ui.mocks.js @@ -1,9 +1,9 @@ import { vi } from "vitest"; export const mockInstallMenu = { - show: vi.fn() + show: vi.fn(), }; export const mockConfigMenu = { - show: vi.fn() + show: vi.fn(), }; diff --git a/src/main.js b/src/main.js index c15aadf..ef0bde8 100644 --- a/src/main.js +++ b/src/main.js @@ -99,7 +99,12 @@ export async function main() { const pathSelector = new PathSelector(uiService, fsService); const numberSelector = new NumberSelector(uiService); const installMenu = new InstallMenu(uiService, configService); - const configMenu = new ConfigMenu(uiService, configService, pathSelector, numberSelector) + const configMenu = new ConfigMenu( + uiService, + configService, + pathSelector, + numberSelector, + ); const mainMenu = new MainMenu(uiService, installMenu, configMenu); await mainMenu.show(); diff --git a/src/services/configService.js b/src/services/configService.js index 7a2539b..038235d 100644 --- a/src/services/configService.js +++ b/src/services/configService.js @@ -28,7 +28,7 @@ export class ConfigService { get = () => { return this.config; - } + }; loadConfig = () => { const filePath = this.getConfigFilename(); @@ -44,7 +44,7 @@ export class ConfigService { ); throw error; } - } + }; saveConfig = () => { const filePath = this.getConfigFilename(); @@ -56,9 +56,9 @@ export class ConfigService { ); throw error; } - } - + }; + getConfigFilename = () => { return path.join(getAppDataDir(), "config.json"); - } + }; } diff --git a/src/ui/configmenu.js b/src/ui/configmenu.js index 1d55340..ce50aa6 100644 --- a/src/ui/configmenu.js +++ b/src/ui/configmenu.js @@ -1,54 +1,66 @@ export class ConfigMenu { - constructor(uiService, configService, pathSelector, numberSelector) { + constructor( + uiService, + menuLoop, + configService, + pathSelector, + numberSelector, + ) { this.ui = uiService; + this.loop = menuLoop; this.configService = configService; this.pathSelector = pathSelector; this.numberSelector = numberSelector; + + this.loop.initialize(this.showConfigMenu); } - show = async() => { - this.running = true; + show = async () => { this.config = this.configService.get(); - while (this.running) { - this.ui.showInfoMessage("Codex Configuration"); - await this.ui.askMultipleChoice("Select to edit:",[ - { - label: `Data path = "${this.config.dataDir}"`, - action: this.editDataDir, - }, - { - label: `Logs path = "${this.config.logsDir}"`, - action: this.editLogsDir, - }, - { - label: `Storage quota = ${this.bytesAmountToString(this.config.storageQuota)}`, - action: this.editStorageQuota, - }, - { - label: `Discovery port = ${this.config.ports.discPort}`, - action: this.editDiscPort, - }, - { - label: `P2P listen port = ${this.config.ports.listenPort}`, - action: this.editListenPort, - }, - { - label: `API port = ${this.config.ports.apiPort}`, - action: this.editApiPort, - }, - { - label: "Save changes and exit", - action: this.saveChangesAndExit, - }, - { - label: "Discard changes and exit", - action: this.discardChangesAndExit, - } - ] - ) - } - } - + this.ui.showInfoMessage("Codex Configuration"); + await this.loop.showLoop(); + }; + + showConfigMenu = async () => { + await this.ui.askMultipleChoice("Select to edit:", [ + { + label: `Data path = "${this.config.dataDir}"`, + action: this.editDataDir, + }, + { + label: `Logs path = "${this.config.logsDir}"`, + action: this.editLogsDir, + }, + { + label: `Storage quota = ${this.bytesAmountToString(this.config.storageQuota)}`, + action: this.editStorageQuota, + }, + { + label: `Discovery port = ${this.config.ports.discPort}`, + action: this.editDiscPort, + }, + { + label: `P2P listen port = ${this.config.ports.listenPort}`, + action: this.editListenPort, + }, + { + label: `API port = ${this.config.ports.apiPort}`, + action: this.editApiPort, + }, + { + label: "Save changes and exit", + action: this.saveChangesAndExit, + }, + { + label: "Discard changes and exit", + action: this.discardChangesAndExit, + }, + ]); + }; + + // this and the byte-format handling in + // numberSelector should be extracted to + // their own util. bytesAmountToString = (numBytes) => { const units = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]; @@ -61,18 +73,16 @@ export class ConfigMenu { if (index == 0) return `${numBytes} Bytes`; return `${numBytes} Bytes (${value} ${units[index]})`; - } + }; editDataDir = async () => { // todo // function updateDataDir(config, newDataDir) { // if (config.dataDir == newDataDir) return config; - // // The Codex dataDir is a little strange: // // If the old one is empty: The new one should not exist, so that codex creates it // // with the correct security permissions. // // If the old one does exist: We move it. - // if (isDir(config.dataDir)) { // console.log( // showInfoMessage( @@ -81,7 +91,6 @@ export class ConfigMenu { // `To: "${newDataDir}"`, // ), // ); - // try { // fs.moveSync(config.dataDir, newDataDir); // } catch (error) { @@ -104,64 +113,82 @@ export class ConfigMenu { // ); // } // } - // config.dataDir = newDataDir; // return config; // } - } + }; editLogsDir = async () => { - this.config.logsDir = await this.pathSelector.show(this.config.logsDir, true); - } + this.config.logsDir = await this.pathSelector.show( + this.config.logsDir, + true, + ); + }; editStorageQuota = async () => { this.ui.showInfoMessage("You can use: 'GB' or 'gb', etc."); - const newQuota = await this.numberSelector.show(this.config.storageQuota, "Storage quota", true); + const newQuota = await this.numberSelector.show( + this.config.storageQuota, + "Storage quota", + true, + ); if (newQuota < 100 * 1024 * 1024) { this.ui.showErrorMessage("Storage quote should be >= 100mb."); } else { this.config.storageQuota = newQuota; } - } + }; editDiscPort = async () => { - const newPort = await this.numberSelector.show(this.config.ports.discPort, "Discovery port", false); + const newPort = await this.numberSelector.show( + this.config.ports.discPort, + "Discovery port", + false, + ); if (this.isInPortRange(newPort)) { this.config.ports.discPort = newPort; } - } + }; editListenPort = async () => { - const newPort = await this.numberSelector.show(this.config.ports.listenPort, "P2P listen port", false); + const newPort = await this.numberSelector.show( + this.config.ports.listenPort, + "P2P listen port", + false, + ); if (this.isInPortRange(newPort)) { this.config.ports.listenPort = newPort; } - } + }; editApiPort = async () => { - const newPort = await this.numberSelector.show(this.config.ports.apiPort, "API port", false); + const newPort = await this.numberSelector.show( + this.config.ports.apiPort, + "API port", + false, + ); if (this.isInPortRange(newPort)) { this.config.ports.apiPort = newPort; } - } + }; isInPortRange = (number) => { if (number < 1024 || number > 65535) { this.ui.showErrorMessage("Port should be between 1024 and 65535."); return false; - } + } return true; - } + }; saveChangesAndExit = async () => { this.configService.saveConfig(); this.ui.showInfoMessage("Configuration changes saved."); - this.running = false; - } + this.loop.stopLoop(); + }; discardChangesAndExit = async () => { this.configService.loadConfig(); this.ui.showInfoMessage("Changes discarded."); - this.running = false; - } + this.loop.stopLoop(); + }; } diff --git a/src/ui/configmenu.test.js b/src/ui/configmenu.test.js index 8887c81..1135bab 100644 --- a/src/ui/configmenu.test.js +++ b/src/ui/configmenu.test.js @@ -2,143 +2,242 @@ import { describe, beforeEach, it, expect, vi } from "vitest"; import { ConfigMenu } from "./configmenu.js"; import { mockUiService } from "../__mocks__/service.mocks.js"; import { mockConfigService } from "../__mocks__/service.mocks.js"; -import { mockPathSelector, mockNumberSelector } from "../__mocks__/ui.mocks.js"; +import { + mockPathSelector, + mockNumberSelector, + mockMenuLoop, +} from "../__mocks__/utils.mocks.js"; describe("ConfigMenu", () => { + const config = { + dataDir: "/data", + logsDir: "/logs", + storageQuota: 1024 * 1024 * 1024, + ports: { + discPort: 8090, + listenPort: 8070, + apiPort: 8080, + }, + }; let configMenu; beforeEach(() => { vi.resetAllMocks(); - mockConfigService.get.mockReturnValue({ - dataDir: "/data", - logsDir: "/logs", - storageQuota: 1024 * 1024 * 1024, - ports: { - discPort: 8090, - listenPort: 8070, - apiPort: 8080, - } - }); + mockConfigService.get.mockReturnValue(config); configMenu = new ConfigMenu( mockUiService, + mockMenuLoop, mockConfigService, mockPathSelector, - mockNumberSelector + mockNumberSelector, ); }); - // it("displays the configuration menu", async () => { - // configMenu.running = false; // Prevent infinite loop - // await configMenu.show(); + it("initializes the loop with the config menu", () => { + expect(mockMenuLoop.initialize).toHaveBeenCalledWith( + configMenu.showConfigMenu, + ); + }); - // expect(mockUiService.showInfoMessage).toHaveBeenCalledWith( - // "Codex Configuration", - // ); - // expect(mockUiService.askMultipleChoice).toHaveBeenCalledWith([ - // { - // label: `Data path = "${mockConfigService.get().dataDir}"`, - // action: configMenu.editDataDir, - // }, - // { - // label: `Logs path = "${mockConfigService.get().logsDir}"`, - // action: configMenu.editLogsDir, - // }, - // { - // label: `Storage quota = 1Gb`, - // action: configMenu.editStorageQuota, - // }, - // { - // label: `Discovery port = ${mockConfigService.get().ports.discPort}`, - // action: configMenu.editDiscPort, - // }, - // { - // label: `P2P listen port = ${mockConfigService.get().ports.listenPort}`, - // action: configMenu.editListenPort, - // }, - // { - // label: `API port = ${mockConfigService.get().ports.apiPort}`, - // action: configMenu.editApiPort, - // }, - // { - // label: "Save changes and exit", - // action: configMenu.saveChangesAndExit, - // }, - // { - // label: "Discard changes and exit", - // action: configMenu.discardChangesAndExit, - // } - // ]); - // }); + it("shows the config menu header", async () => { + await configMenu.show(); + expect(mockUiService.showInfoMessage).toHaveBeenCalledWith( + "Codex Configuration", + ); + }); -// it("edits the logs directory", async () => { -// mockPathSelector.show.mockResolvedValue("/new-logs"); -// await configMenu.editLogsDir(); + it("starts the menu loop", async () => { + await configMenu.show(); + expect(mockMenuLoop.showLoop).toHaveBeenCalled(); + }); -// expect(mockPathSelector.show).toHaveBeenCalledWith("/logs", true); -// expect(configMenu.config.logsDir).toEqual("/new-logs"); -// }); + it("sets the config field", async () => { + await configMenu.show(); + expect(configMenu.config).toEqual(config); + }); -// it("edits the storage quota", async () => { -// mockNumberSelector.show.mockResolvedValue(200 * 1024 * 1024); -// await configMenu.editStorageQuota(); + describe("config menu options", () => { + beforeEach(() => { + configMenu.config = config; + }); -// expect(mockUiService.showInfoMessage).toHaveBeenCalledWith( -// "You can use: 'GB' or 'gb', etc.", -// ); -// expect(mockNumberSelector.show).toHaveBeenCalledWith( -// 1024 * 1024 * 1024, -// "Storage quota", -// true, -// ); -// expect(configMenu.config.storageQuota).toEqual(200 * 1024 * 1024); -// }); + it("displays the configuration menu", async () => { + await configMenu.showConfigMenu(); + expect(mockUiService.askMultipleChoice).toHaveBeenCalledWith( + "Select to edit:", + [ + { + label: `Data path = "${mockConfigService.get().dataDir}"`, + action: configMenu.editDataDir, + }, + { + label: `Logs path = "${mockConfigService.get().logsDir}"`, + action: configMenu.editLogsDir, + }, + { + label: `Storage quota = 1073741824 Bytes (1024 MB)`, + action: configMenu.editStorageQuota, + }, + { + label: `Discovery port = ${mockConfigService.get().ports.discPort}`, + action: configMenu.editDiscPort, + }, + { + label: `P2P listen port = ${mockConfigService.get().ports.listenPort}`, + action: configMenu.editListenPort, + }, + { + label: `API port = ${mockConfigService.get().ports.apiPort}`, + action: configMenu.editApiPort, + }, + { + label: "Save changes and exit", + action: configMenu.saveChangesAndExit, + }, + { + label: "Discard changes and exit", + action: configMenu.discardChangesAndExit, + }, + ], + ); + }); -// it("shows an error if storage quota is too small", async () => { -// mockNumberSelector.show.mockResolvedValue(50 * 1024 * 1024); -// await configMenu.editStorageQuota(); + it("edits the logs directory", async () => { + const originalPath = config.logsDir; + mockPathSelector.show.mockResolvedValue("/new-logs"); + await configMenu.editLogsDir(); -// expect(mockUiService.showErrorMessage).toHaveBeenCalledWith( -// "Storage quote should be >= 100mb.", -// ); -// expect(configMenu.config.storageQuota).toEqual(1024 * 1024 * 1024); // Unchanged -// }); + expect(mockPathSelector.show).toHaveBeenCalledWith(originalPath, true); + expect(configMenu.config.logsDir).toEqual("/new-logs"); + }); -// it("edits the discovery port", async () => { -// mockNumberSelector.show.mockResolvedValue(9000); -// await configMenu.editDiscPort(); + it("edits the storage quota", async () => { + const originalQuota = config.storageQuota; + const newQuota = 200 * 1024 * 1024; + mockNumberSelector.show.mockResolvedValue(newQuota); -// expect(mockNumberSelector.show).toHaveBeenCalledWith(8090, "Discovery port", false); -// expect(configMenu.config.ports.discPort).toEqual(9000); -// }); + await configMenu.editStorageQuota(); -// it("shows an error if port is out of range", async () => { -// mockNumberSelector.show.mockResolvedValue(1000); -// await configMenu.editDiscPort(); + expect(mockUiService.showInfoMessage).toHaveBeenCalledWith( + "You can use: 'GB' or 'gb', etc.", + ); + expect(mockNumberSelector.show).toHaveBeenCalledWith( + originalQuota, + "Storage quota", + true, + ); + expect(configMenu.config.storageQuota).toEqual(newQuota); + }); -// expect(mockUiService.showErrorMessage).toHaveBeenCalledWith( -// "Port should be between 1024 and 65535.", -// ); -// expect(configMenu.config.ports.discPort).toEqual(8090); // Unchanged -// }); + it("shows an error if storage quota is too small", async () => { + const originalQuota = config.storageQuota; + mockNumberSelector.show.mockResolvedValue(50 * 1024 * 1024); -// it("saves changes and exits", async () => { -// await configMenu.saveChangesAndExit(); + await configMenu.editStorageQuota(); -// expect(mockConfigService.saveConfig).toHaveBeenCalled(); -// expect(mockUiService.showInfoMessage).toHaveBeenCalledWith( -// "Configuration changes saved.", -// ); -// expect(configMenu.running).toEqual(false); -// }); + expect(mockUiService.showErrorMessage).toHaveBeenCalledWith( + "Storage quote should be >= 100mb.", + ); + expect(configMenu.config.storageQuota).toEqual(originalQuota); + }); -// it("discards changes and exits", async () => { -// await configMenu.discardChangesAndExit(); + it("edits the discovery port", async () => { + const originalPort = config.ports.discPort; + const newPort = 9000; + mockNumberSelector.show.mockResolvedValue(newPort); -// expect(mockConfigService.loadConfig).toHaveBeenCalled(); -// expect(mockUiService.showInfoMessage).toHaveBeenCalledWith( -// "Changes discarded.", -// ); -// expect(configMenu.running).toEqual(false); -// }); + await configMenu.editDiscPort(); + + expect(mockNumberSelector.show).toHaveBeenCalledWith( + originalPort, + "Discovery port", + false, + ); + expect(configMenu.config.ports.discPort).toEqual(newPort); + }); + + it("shows an error if discovery port is out of range", async () => { + const originalPort = config.ports.discPort; + mockNumberSelector.show.mockResolvedValue(1000); + await configMenu.editDiscPort(); + + expect(mockUiService.showErrorMessage).toHaveBeenCalledWith( + "Port should be between 1024 and 65535.", + ); + expect(configMenu.config.ports.discPort).toEqual(originalPort); + }); + + it("edits the listen port", async () => { + const originalPort = config.ports.listenPort; + const newPort = 9000; + mockNumberSelector.show.mockResolvedValue(newPort); + + await configMenu.editListenPort(); + + expect(mockNumberSelector.show).toHaveBeenCalledWith( + originalPort, + "P2P listen port", + false, + ); + expect(configMenu.config.ports.listenPort).toEqual(newPort); + }); + + it("shows an error if listen port is out of range", async () => { + const originalPort = config.ports.listenPort; + mockNumberSelector.show.mockResolvedValue(1000); + await configMenu.editListenPort(); + + expect(mockUiService.showErrorMessage).toHaveBeenCalledWith( + "Port should be between 1024 and 65535.", + ); + expect(configMenu.config.ports.listenPort).toEqual(originalPort); + }); + + it("edits the API port", async () => { + const originalPort = config.ports.apiPort; + const newPort = 9000; + mockNumberSelector.show.mockResolvedValue(newPort); + + await configMenu.editApiPort(); + + expect(mockNumberSelector.show).toHaveBeenCalledWith( + originalPort, + "API port", + false, + ); + expect(configMenu.config.ports.apiPort).toEqual(newPort); + }); + + it("shows an error if API port is out of range", async () => { + const originalPort = config.ports.apiPort; + mockNumberSelector.show.mockResolvedValue(1000); + await configMenu.editApiPort(); + + expect(mockUiService.showErrorMessage).toHaveBeenCalledWith( + "Port should be between 1024 and 65535.", + ); + expect(configMenu.config.ports.apiPort).toEqual(originalPort); + }); + + it("saves changes and exits", async () => { + await configMenu.saveChangesAndExit(); + + expect(mockConfigService.saveConfig).toHaveBeenCalled(); + expect(mockUiService.showInfoMessage).toHaveBeenCalledWith( + "Configuration changes saved.", + ); + expect(mockMenuLoop.stopLoop).toHaveBeenCalled(); + }); + + it("discards changes and exits", async () => { + await configMenu.discardChangesAndExit(); + + expect(mockConfigService.loadConfig).toHaveBeenCalled(); + expect(mockUiService.showInfoMessage).toHaveBeenCalledWith( + "Changes discarded.", + ); + expect(mockMenuLoop.stopLoop).toHaveBeenCalled(); + }); + }); }); diff --git a/src/ui/mainmenu.test.js b/src/ui/mainmenu.test.js index de28c54..116792f 100644 --- a/src/ui/mainmenu.test.js +++ b/src/ui/mainmenu.test.js @@ -10,11 +10,18 @@ describe("mainmenu", () => { beforeEach(() => { vi.resetAllMocks(); - mainmenu = new MainMenu(mockUiService, mockMenuLoop, mockInstallMenu, mockConfigMenu); + mainmenu = new MainMenu( + mockUiService, + mockMenuLoop, + mockInstallMenu, + mockConfigMenu, + ); }); it("initializes the menu loop with the promptMainMenu function", () => { - expect(mockMenuLoop.initialize).toHaveBeenCalledWith(mainmenu.promptMainMenu); + expect(mockMenuLoop.initialize).toHaveBeenCalledWith( + mainmenu.promptMainMenu, + ); }); it("shows the logo", async () => { diff --git a/src/utils/menuLoop.js b/src/utils/menuLoop.js index a914ac7..638429e 100644 --- a/src/utils/menuLoop.js +++ b/src/utils/menuLoop.js @@ -1,20 +1,20 @@ export class MenuLoop { - initialize = (menuPrompt) => { - this.menuPrompt = menuPrompt; - } + initialize = (menuPrompt) => { + this.menuPrompt = menuPrompt; + }; - showOnce = async () => { - await this.menuPrompt(); - } + showOnce = async () => { + await this.menuPrompt(); + }; - showLoop = async () => { - this.running = true; - while (this.running) { - await this.menuPrompt(); - } + showLoop = async () => { + this.running = true; + while (this.running) { + await this.menuPrompt(); } + }; - stopLoop = () => { - this.running = false; - } + stopLoop = () => { + this.running = false; + }; } diff --git a/src/utils/menuLoop.test.js b/src/utils/menuLoop.test.js index 756f2b1..e03e194 100644 --- a/src/utils/menuLoop.test.js +++ b/src/utils/menuLoop.test.js @@ -2,41 +2,41 @@ import { describe, beforeEach, it, expect, vi } from "vitest"; import { MenuLoop } from "./menuLoop.js"; describe("MenuLoop", () => { - let menuLoop; - const mockPrompt = vi.fn(); + let menuLoop; + const mockPrompt = vi.fn(); - beforeEach(() => { - vi.resetAllMocks(); - menuLoop = new MenuLoop(); - menuLoop.initialize(mockPrompt); + beforeEach(() => { + vi.resetAllMocks(); + menuLoop = new MenuLoop(); + menuLoop.initialize(mockPrompt); + }); + + it("can show menu once", async () => { + await menuLoop.showOnce(); + expect(mockPrompt).toHaveBeenCalledTimes(1); + }); + + it("can stop the menu loop", async () => { + mockPrompt.mockImplementation(() => { + menuLoop.stopLoop(); + }); + await menuLoop.showLoop(); + + expect(mockPrompt).toHaveBeenCalledTimes(1); + expect(menuLoop.running).toBe(false); + }); + + it("can run menu in a loop", async () => { + let calls = 0; + mockPrompt.mockImplementation(() => { + calls++; + if (calls >= 3) { + menuLoop.stopLoop(); + } }); - it("can show menu once", async () => { - await menuLoop.showOnce(); - expect(mockPrompt).toHaveBeenCalledTimes(1); - }); + await menuLoop.showLoop(); - it("can stop the menu loop", async () => { - mockPrompt.mockImplementation(() => { - menuLoop.stopLoop(); - }); - await menuLoop.showLoop(); - - expect(mockPrompt).toHaveBeenCalledTimes(1); - expect(menuLoop.running).toBe(false); - }); - - it("can run menu in a loop", async () => { - let calls = 0; - mockPrompt.mockImplementation(() => { - calls++; - if (calls >= 3) { - menuLoop.stopLoop(); - } - }); - - await menuLoop.showLoop(); - - expect(mockPrompt).toHaveBeenCalledTimes(3); - }); + expect(mockPrompt).toHaveBeenCalledTimes(3); + }); }); diff --git a/src/utils/numberSelector.js b/src/utils/numberSelector.js index d790a0b..1accc04 100644 --- a/src/utils/numberSelector.js +++ b/src/utils/numberSelector.js @@ -3,11 +3,7 @@ export class NumberSelector { this.uiService = uiService; } - show = async ( - currentValue, - promptMessage, - allowMetricPostfixes, - ) => { + show = async (currentValue, promptMessage, allowMetricPostfixes) => { try { var valueStr = await this.promptForValueStr(promptMessage); valueStr = valueStr.replaceAll(" ", ""); diff --git a/src/utils/numberSelector.test.js b/src/utils/numberSelector.test.js index 20d67c3..166641c 100644 --- a/src/utils/numberSelector.test.js +++ b/src/utils/numberSelector.test.js @@ -34,11 +34,7 @@ describe("number selector", () => { mockUiService.askPrompt.mockResolvedValue("what?!"); - const number = await numberSelector.show( - currentValue, - prompt, - false, - ); + const number = await numberSelector.show(currentValue, prompt, false); expect(number).toEqual(currentValue); }); diff --git a/src/utils/pathSelector.js b/src/utils/pathSelector.js index a0de9f4..84304d9 100644 --- a/src/utils/pathSelector.js +++ b/src/utils/pathSelector.js @@ -106,14 +106,14 @@ export class PathSelector { console.log("The path does not exist."); } this.updateCurrentIfValidParts(this.splitPath(newFullPath)); - } + }; updateCurrentIfValidParts = (newParts) => { if (!this.hasValidRoot(newParts)) { console.log("The path has no valid root."); } this.currentPath = newParts; - } + }; enterPath = async () => { const newPath = await this.ui.askPrompt("Enter Path:"); @@ -156,8 +156,8 @@ export class PathSelector { action: () => { selected = option; }, - }) - }) + }); + }); await this.ui.askMultipleChoice("Select an subdir", uiOptions); @@ -174,7 +174,7 @@ export class PathSelector { selectThisPath = async () => { this.resultingPath = this.combine(this.currentPath); this.running = false; - } + }; cancel = async () => { this.resultingPath = this.startingPath;