From f9ff3ffdb32c654310b0cb795ea4aff712ce0d8b Mon Sep 17 00:00:00 2001 From: gnuxie Date: Fri, 27 Sep 2024 14:51:49 +0100 Subject: [PATCH] Allow recover options to be used. Now we just need to anotate the status information/command with a partial command that calls the recover command. --- src/safemode/commands/RecoverCommand.tsx | 83 ++++++++++++++++++++++ src/safemode/commands/SafeModeCommands.tsx | 2 + 2 files changed, 85 insertions(+) create mode 100644 src/safemode/commands/RecoverCommand.tsx diff --git a/src/safemode/commands/RecoverCommand.tsx b/src/safemode/commands/RecoverCommand.tsx new file mode 100644 index 0000000..a018448 --- /dev/null +++ b/src/safemode/commands/RecoverCommand.tsx @@ -0,0 +1,83 @@ +// SPDX-FileCopyrightText: 2024 Gnuxie +// +// SPDX-License-Identifier: AFL-3.0 + +import { Ok, Result, ResultError, isError } from "@gnuxie/typescript-result"; +import { + DeadDocumentJSX, + StringPresentationType, + describeCommand, + tuple, +} from "@the-draupnir-project/interface-manager"; +import { SafeModeDraupnir } from "../DraupnirSafeMode"; +import { SafeModeReason } from "../SafeModeCause"; +import { + ConfigRecoverableError, + ConfigRecoveryOption, +} from "matrix-protection-suite"; +import { SafeModeInterfaceAdaptor } from "./SafeModeAdaptor"; + +export const SafeModeRecoverCommand = describeCommand({ + summary: "Select an availale recovery option to enact.", + parameters: tuple({ + name: "recovery option", + acceptor: StringPresentationType, + description: "The recovery option to enact, e.g. 1.", + }), + async executor( + safeModeDraupnir: SafeModeDraupnir, + _info, + _keywords, + _rest, + optionDesignator + ): Promise> { + const optionNumber = (() => { + try { + return Ok(parseInt(optionDesignator)); + } catch { + return ResultError.Result( + `Unable to parse the recovery option from ${optionDesignator}` + ); + } + })(); + if (isError(optionNumber)) { + return optionNumber; + } + const options = + safeModeDraupnir.cause.reason === SafeModeReason.ByRequest + ? [] + : safeModeDraupnir.cause.error instanceof ConfigRecoverableError + ? safeModeDraupnir.cause.error.recoveryOptions + : []; + const selectedOption = options[optionNumber.ok - 1]; + if (selectedOption === undefined) { + return ResultError.Result( + `No recovery option with the number ${optionNumber.ok} exists.` + ); + } + const recoveryResult = await selectedOption.recover(); + if (isError(recoveryResult)) { + return recoveryResult; + } + return Ok(selectedOption); + }, +}); + +SafeModeInterfaceAdaptor.describeRenderer(SafeModeRecoverCommand, { + JSXRenderer(result) { + if (isError(result)) { + return Ok(undefined); + } + return Ok( + + + The recovery following recovery option has sucessfully been applied: +
+ {result.ok.description} +
+ You may now restart Draupnir with !draupnir restart +
+
+ ); + }, +}); diff --git a/src/safemode/commands/SafeModeCommands.tsx b/src/safemode/commands/SafeModeCommands.tsx index c7ab642..d5b04ce 100644 --- a/src/safemode/commands/SafeModeCommands.tsx +++ b/src/safemode/commands/SafeModeCommands.tsx @@ -6,8 +6,10 @@ import { StandardCommandTable } from "@the-draupnir-project/interface-manager"; import { SafeModeHelpCommand } from "./HelpCommand"; import { SafeModeStatusCommand } from "./StatusCommand"; import { SafeModeRestartCommand } from "./RestartDraupnirCommand"; +import { SafeModeRecoverCommand } from "./RecoverCommand"; export const SafeModeCommands = new StandardCommandTable("safe mode") .internCommand(SafeModeHelpCommand, ["draupnir", "help"]) .internCommand(SafeModeStatusCommand, ["draupnir", "status"]) + .internCommand(SafeModeRecoverCommand, ["draupnir", "recover"]) .internCommand(SafeModeRestartCommand, ["draupnir", "restart"]);