From eaf6bb41cdd668b52a835aa984ad7c02410ae86f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C3=ABl=20Minelli?= <git@minelli.me>
Date: Thu, 29 Feb 2024 14:39:28 +0100
Subject: [PATCH] Sonar => Minimize code duplication

---
 .gitignore                                    |  3 ++
 NodeApp/.idea/DojoCLI.iml                     |  3 ++
 .../subcommands/AssignmentCheckCommand.ts     |  8 ++---
 .../subcommands/AssignmentRunCommand.ts       | 10 ++----
 .../subcommands/CompletionBashCommand.ts      | 33 +++++++++--------
 .../subcommands/CompletionFishCommand.ts      | 35 +++++++++----------
 .../subcommands/CompletionZshCommand.ts       | 35 +++++++++----------
 .../subcommands/ExerciseRunCommand.ts         | 10 ++----
 NodeApp/src/helpers/GlobalHelper.ts           | 26 ++++++++++++++
 NodeApp/src/shared                            |  2 +-
 10 files changed, 89 insertions(+), 76 deletions(-)
 create mode 100644 NodeApp/src/helpers/GlobalHelper.ts

diff --git a/.gitignore b/.gitignore
index b30f2e1..5d889f5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,6 +8,9 @@ NodeApp/src/config/Version.ts
 dojo_bash_completion.sh
 dojo.fish
 
+sonarlint.xml
+sonarlint/
+
 ############################ MacOS
 # General
 .DS_Store
diff --git a/NodeApp/.idea/DojoCLI.iml b/NodeApp/.idea/DojoCLI.iml
index d47865a..dd6c9d8 100644
--- a/NodeApp/.idea/DojoCLI.iml
+++ b/NodeApp/.idea/DojoCLI.iml
@@ -12,4 +12,7 @@
     <orderEntry type="inheritedJdk" />
     <orderEntry type="sourceFolder" forTests="false" />
   </component>
+  <component name="SonarLintModuleSettings">
+    <option name="uniqueId" value="7e31b6fd-1f86-4d26-8c50-c9ab6530f54e" />
+  </component>
 </module>
\ No newline at end of file
diff --git a/NodeApp/src/commander/assignment/subcommands/AssignmentCheckCommand.ts b/NodeApp/src/commander/assignment/subcommands/AssignmentCheckCommand.ts
index b818c73..c83a3d1 100644
--- a/NodeApp/src/commander/assignment/subcommands/AssignmentCheckCommand.ts
+++ b/NodeApp/src/commander/assignment/subcommands/AssignmentCheckCommand.ts
@@ -4,20 +4,16 @@ import ora                           from 'ora';
 import chalk                         from 'chalk';
 import AssignmentValidator           from '../../../sharedByClients/helpers/Dojo/AssignmentValidator';
 import ClientsSharedAssignmentHelper from '../../../sharedByClients/helpers/Dojo/ClientsSharedAssignmentHelper';
-import { Option }                    from 'commander';
 import SharedConfig                  from '../../../shared/config/SharedConfig';
+import GlobalHelper                  from '../../../helpers/GlobalHelper';
 
 
 class AssignmentCheckCommand extends CommanderCommand {
     protected commandName: string = 'check';
 
     protected defineCommand() {
-        this.command
+        GlobalHelper.runCommandDefinition(this.command)
         .description('locally run a check of an assignment')
-        .option('-p, --path <value>', 'assignment path', Config.folders.defaultLocalExercise)
-        .option('-v, --verbose', 'verbose mode - display principal container output in live')
-        .addOption(new Option('-w, --super-verbose', 'verbose mode - display all docker compose logs (build included) in live').conflicts('verbose'))
-        .addOption(new Option('--verbose-ssj2').hideHelp().implies({ superVerbose: true }))
         .action(this.commandAction.bind(this));
     }
 
diff --git a/NodeApp/src/commander/assignment/subcommands/AssignmentRunCommand.ts b/NodeApp/src/commander/assignment/subcommands/AssignmentRunCommand.ts
index 9a7489f..3b44f98 100644
--- a/NodeApp/src/commander/assignment/subcommands/AssignmentRunCommand.ts
+++ b/NodeApp/src/commander/assignment/subcommands/AssignmentRunCommand.ts
@@ -1,20 +1,14 @@
 import CommanderCommand  from '../../CommanderCommand';
-import Config            from '../../../config/Config';
-import { Option }        from 'commander';
 import ExerciseRunHelper from '../../../helpers/Dojo/ExerciseRunHelper';
+import GlobalHelper      from '../../../helpers/GlobalHelper';
 
 
 class AssignmentRunCommand extends CommanderCommand {
     protected commandName: string = 'run';
 
     protected defineCommand() {
-        // This command is synced with the "exercise run" command
-        this.command
+        GlobalHelper.runCommandDefinition(this.command)
         .description('locally run the assignment as an exercise')
-        .option('-p, --path <value>', 'exercise path', Config.folders.defaultLocalExercise)
-        .option('-v, --verbose', 'verbose mode - display principal container output in live')
-        .addOption(new Option('-w, --super-verbose', 'verbose mode - display all docker compose logs (build included) in live').conflicts('verbose'))
-        .addOption(new Option('--verbose-ssj2').hideHelp().implies({ superVerbose: true }))
         .action(this.commandAction.bind(this));
     }
 
diff --git a/NodeApp/src/commander/completion/subcommands/CompletionBashCommand.ts b/NodeApp/src/commander/completion/subcommands/CompletionBashCommand.ts
index a10dc0e..0127d78 100644
--- a/NodeApp/src/commander/completion/subcommands/CompletionBashCommand.ts
+++ b/NodeApp/src/commander/completion/subcommands/CompletionBashCommand.ts
@@ -5,6 +5,7 @@ import TextStyle                                          from '../../../types/T
 import fs                                                 from 'fs-extra';
 import path                                               from 'path';
 import os                                                 from 'os';
+import GlobalHelper                                       from '../../../helpers/GlobalHelper';
 
 
 class CompletionBashCommand extends CommanderCommand {
@@ -13,10 +14,8 @@ class CompletionBashCommand extends CommanderCommand {
     private installPath = path.join(os.homedir(), '.bash_completion');
 
     protected defineCommand() {
-        this.command
+        GlobalHelper.completionCommandDefinition(this.command)
         .description('generate bash completion')
-        .option('-f, --file <filename>')
-        .option('-y, --force', 'don\'t ask for file overwrite confirmation')
         .action(this.commandAction.bind(this));
     }
 
@@ -47,20 +46,20 @@ For more details: ${ TextStyle.URL('https://github.com/scop/bash-completion/blob
     }
 
     /* The completion command must do the following:
-       - if a file is provided: 
-            - if force is not enabled:
-                - check if the file exists:
-                    - if it exists, prompt the user that it will be erased
-                        - if ok is given write the file and prompt that a backup has been created
-            - else create the file containing the completion
-        - else
-            - if force is not enabled:
-                - check if the default file exists:
-                    - if it exists, prompt the user that it will be erased:
-                        - if ok is given write the file and prompt that a backup has been created
-            - else
-                - create the file containing the completion
-    */
+     - if a file is provided:
+     - if force is not enabled:
+     - check if the file exists:
+     - if it exists, prompt the user that it will be erased
+     - if ok is given write the file and prompt that a backup has been created
+     - else create the file containing the completion
+     - else
+     - if force is not enabled:
+     - check if the default file exists:
+     - if it exists, prompt the user that it will be erased:
+     - if ok is given write the file and prompt that a backup has been created
+     - else
+     - create the file containing the completion
+     */
     protected async commandAction(options: { file: string, force: boolean }): Promise<void> {
         const filePath = path.resolve(options.file ?? this.installPath); // change that if file is empty
         const showInstructions = !!options.file;
diff --git a/NodeApp/src/commander/completion/subcommands/CompletionFishCommand.ts b/NodeApp/src/commander/completion/subcommands/CompletionFishCommand.ts
index 51431a5..9395550 100644
--- a/NodeApp/src/commander/completion/subcommands/CompletionFishCommand.ts
+++ b/NodeApp/src/commander/completion/subcommands/CompletionFishCommand.ts
@@ -5,6 +5,7 @@ import TextStyle                                          from '../../../types/T
 import path                                               from 'path';
 import os                                                 from 'os';
 import fs                                                 from 'fs-extra';
+import GlobalHelper                                       from '../../../helpers/GlobalHelper';
 
 
 class CompletionFishCommand extends CommanderCommand {
@@ -13,15 +14,14 @@ class CompletionFishCommand extends CommanderCommand {
     private installPath = path.join(os.homedir(), '.config/fish/completions/dojo.fish');
 
     protected defineCommand() {
-        this.command
+        GlobalHelper.completionCommandDefinition(this.command)
         .description('generate fish completion')
-        .option('-f, --file <filename>', `filename where the bash completion will be stored`)
-        .option('-y, --force', 'don\'t ask for file overwrite confirmation')
         .action(this.commandAction.bind(this));
     }
 
     private writeFile(filename: string, showInstructions: boolean) {
         const spinner: ora.Ora = ora(`Writing fish completion in ${ filename }...`).start();
+
         try {
             fs.mkdirsSync(path.dirname(filename));
 
@@ -29,7 +29,6 @@ class CompletionFishCommand extends CommanderCommand {
 
             spinner.succeed(`Fish completion successfully written in ${ filename }.`);
             if ( showInstructions ) {
-
                 console.log(`
 The easiest way to install the completion is to copy the ${ TextStyle.CODE(filename) } into the ${ TextStyle.CODE('~/.config/fish/completions') } directory.
 
@@ -42,20 +41,20 @@ ${ TextStyle.CODE(` cp -i ${ filename } ~/.config/fish/completions  # interactiv
 
 
     /* The completion command must do the following:
-       - if a file is provided:
-            - if force is not enabled:
-                - check if the file exists:
-                    - if it exists, prompt the user that it will be erased
-                        - if ok is given write the file and prompt that a backup has been created
-            - else create the file containing the completion
-        - else
-            - if force is not enabled:
-                - check if the default file exists:
-                    - if it exists, prompt the user that it will be erased:
-                        - if ok is given write the file and prompt that a backup has been created
-            - else
-                - create the file containing the completion
-    */
+     - if a file is provided:
+     - if force is not enabled:
+     - check if the file exists:
+     - if it exists, prompt the user that it will be erased
+     - if ok is given write the file and prompt that a backup has been created
+     - else create the file containing the completion
+     - else
+     - if force is not enabled:
+     - check if the default file exists:
+     - if it exists, prompt the user that it will be erased:
+     - if ok is given write the file and prompt that a backup has been created
+     - else
+     - create the file containing the completion
+     */
     protected async commandAction(options: { file: string, force: boolean }): Promise<void> {
         const filePath = path.resolve(options.file ?? this.installPath); // change that if file is empty
         const showInstructions = !!options.file;
diff --git a/NodeApp/src/commander/completion/subcommands/CompletionZshCommand.ts b/NodeApp/src/commander/completion/subcommands/CompletionZshCommand.ts
index 9e277aa..1e97b2b 100644
--- a/NodeApp/src/commander/completion/subcommands/CompletionZshCommand.ts
+++ b/NodeApp/src/commander/completion/subcommands/CompletionZshCommand.ts
@@ -5,6 +5,7 @@ import TextStyle                                          from '../../../types/T
 import path                                               from 'path';
 import { homedir }                                        from 'os';
 import fs                                                 from 'fs-extra';
+import GlobalHelper                                       from '../../../helpers/GlobalHelper';
 
 
 class CompletionZshCommand extends CommanderCommand {
@@ -21,10 +22,8 @@ source ${ this.bash_completion }
 
 
     protected defineCommand() {
-        this.command
+        GlobalHelper.completionCommandDefinition(this.command)
         .description('generate zsh completion, which is derived from the bash completion')
-        .option('-f, --file <filename>', 'bash completion filename')
-        .option('-y, --force', 'don\'t ask for file overwrite confirmation')
         .action(this.commandAction.bind(this));
     }
 
@@ -102,21 +101,21 @@ source ${ filename }
     }
 
     /* The completion command must do the following:
-    - if a file is provided: 
-        - if force is not enabled:
-            - check if the bash completion file exists:
-                - if it exists, prompt the user that it will be overwritten
-                    - if ok is given write the file and prompt that a backup has been created
-        - else create the file containing the completion
-    - else
-        - if force is not enabled:
-            - check if the default file exists:
-                - if it exists, prompt the user that it will be erased:
-                    - if ok is given write the file and prompt that a backup has been created
-        - else
-            - create the file containing the completion
-    - create a .zprofile or append the appropriate commands into the .zprofile file
-    */
+     - if a file is provided:
+     - if force is not enabled:
+     - check if the bash completion file exists:
+     - if it exists, prompt the user that it will be overwritten
+     - if ok is given write the file and prompt that a backup has been created
+     - else create the file containing the completion
+     - else
+     - if force is not enabled:
+     - check if the default file exists:
+     - if it exists, prompt the user that it will be erased:
+     - if ok is given write the file and prompt that a backup has been created
+     - else
+     - create the file containing the completion
+     - create a .zprofile or append the appropriate commands into the .zprofile file
+     */
     protected async commandAction(options: { file: string, force: boolean }): Promise<void> {
         const filePath = path.resolve(options.file ?? this.bash_completion); // change that if file is empty
         const showInstructions = !!options.file;
diff --git a/NodeApp/src/commander/exercise/subcommands/ExerciseRunCommand.ts b/NodeApp/src/commander/exercise/subcommands/ExerciseRunCommand.ts
index c4d6b21..75af946 100644
--- a/NodeApp/src/commander/exercise/subcommands/ExerciseRunCommand.ts
+++ b/NodeApp/src/commander/exercise/subcommands/ExerciseRunCommand.ts
@@ -1,20 +1,14 @@
 import CommanderCommand  from '../../CommanderCommand';
-import Config            from '../../../config/Config';
 import ExerciseRunHelper from '../../../helpers/Dojo/ExerciseRunHelper';
-import { Option }        from 'commander';
+import GlobalHelper      from '../../../helpers/GlobalHelper';
 
 
 class ExerciseRunCommand extends CommanderCommand {
     protected commandName: string = 'run';
 
     protected defineCommand() {
-        // This command is synced with the "assignment run" command
-        this.command
+        GlobalHelper.runCommandDefinition(this.command)
         .description('locally run an exercise')
-        .option('-p, --path <value>', 'exercise path', Config.folders.defaultLocalExercise)
-        .option('-v, --verbose', 'verbose mode - display principal container output in live')
-        .addOption(new Option('-w, --super-verbose', 'verbose mode - display all docker compose logs (build included) in live').conflicts('verbose'))
-        .addOption(new Option('--verbose-ssj2').hideHelp().implies({ superVerbose: true }))
         .action(this.commandAction.bind(this));
     }
 
diff --git a/NodeApp/src/helpers/GlobalHelper.ts b/NodeApp/src/helpers/GlobalHelper.ts
new file mode 100644
index 0000000..7f0991c
--- /dev/null
+++ b/NodeApp/src/helpers/GlobalHelper.ts
@@ -0,0 +1,26 @@
+import { Command, Option } from 'commander';
+import Config              from '../config/Config';
+
+
+class GlobalHelper {
+    public runCommandDefinition(command: Command) {
+        command
+        .option('-p, --path <value>', 'assignment path', Config.folders.defaultLocalExercise)
+        .option('-v, --verbose', 'verbose mode - display principal container output in live')
+        .addOption(new Option('-w, --super-verbose', 'verbose mode - display all docker compose logs (build included) in live').conflicts('verbose'))
+        .addOption(new Option('--verbose-ssj2').hideHelp().implies({ superVerbose: true }));
+
+        return command;
+    }
+
+    public completionCommandDefinition(command: Command) {
+        command
+        .option('-f, --file <filename>')
+        .option('-y, --force', 'don\'t ask for file overwrite confirmation');
+
+        return command;
+    }
+}
+
+
+export default new GlobalHelper();
\ No newline at end of file
diff --git a/NodeApp/src/shared b/NodeApp/src/shared
index 9e3f29d..6214acb 160000
--- a/NodeApp/src/shared
+++ b/NodeApp/src/shared
@@ -1 +1 @@
-Subproject commit 9e3f29d2f313ef96944a199da0db39f1827c496a
+Subproject commit 6214acbd799d9eed3f5b6840858f8d5ecda82c86
-- 
GitLab