diff --git a/NodeApp/.eslintignore b/NodeApp/.eslintignore
new file mode 100644
index 0000000000000000000000000000000000000000..ecded56c0bd829718e46ffea13b1e3b6791c794e
--- /dev/null
+++ b/NodeApp/.eslintignore
@@ -0,0 +1,3 @@
+dist
+node_modules
+.gitlab-ci
\ No newline at end of file
diff --git a/NodeApp/.eslintrc.json b/NodeApp/.eslintrc.json
new file mode 100644
index 0000000000000000000000000000000000000000..be8c02d07111eec0c73437a65326e56150fda24d
--- /dev/null
+++ b/NodeApp/.eslintrc.json
@@ -0,0 +1,11 @@
+{
+    "root"   : true,
+    "parser" : "@typescript-eslint/parser",
+    "plugins": [
+        "@typescript-eslint"
+    ],
+    "extends": [
+        "eslint:recommended",
+        "plugin:@typescript-eslint/recommended"
+    ]
+}
\ No newline at end of file
diff --git a/NodeApp/.gitlab-ci/03_stages.yml b/NodeApp/.gitlab-ci/03_stages.yml
index c459c1651b62a43f93c894fd8b640bb8df071386..92fa9e8c1a2fbcfdb84f251cc41370ba5d6421c5 100644
--- a/NodeApp/.gitlab-ci/03_stages.yml
+++ b/NodeApp/.gitlab-ci/03_stages.yml
@@ -1,4 +1,5 @@
 stages:
+    - code_quality
     - test
     - build
     - pkg_and_sign
diff --git a/NodeApp/.gitlab-ci/04_stageCodeQuality.yml b/NodeApp/.gitlab-ci/04_stageCodeQuality.yml
new file mode 100644
index 0000000000000000000000000000000000000000..9fda59d835ec0c91e23548db55a43a1df8d6ab1b
--- /dev/null
+++ b/NodeApp/.gitlab-ci/04_stageCodeQuality.yml
@@ -0,0 +1,10 @@
+code_quality:lint:
+    stage: code_quality
+    tags:
+        - code_quality
+    image: node:latest
+    script:
+        - cd "${PROJECT_FOLDER}"
+        
+        - npm install
+        - npm run lint
diff --git a/NodeApp/.gitlab-ci/04_stageTest.yml b/NodeApp/.gitlab-ci/05_stageTest.yml
similarity index 100%
rename from NodeApp/.gitlab-ci/04_stageTest.yml
rename to NodeApp/.gitlab-ci/05_stageTest.yml
diff --git a/NodeApp/.gitlab-ci/05_stageBuild.yml b/NodeApp/.gitlab-ci/06_stageBuild.yml
similarity index 100%
rename from NodeApp/.gitlab-ci/05_stageBuild.yml
rename to NodeApp/.gitlab-ci/06_stageBuild.yml
diff --git a/NodeApp/.gitlab-ci/06_stagePkgAndSign.yml b/NodeApp/.gitlab-ci/07_stagePkgAndSign.yml
similarity index 100%
rename from NodeApp/.gitlab-ci/06_stagePkgAndSign.yml
rename to NodeApp/.gitlab-ci/07_stagePkgAndSign.yml
diff --git a/NodeApp/.gitlab-ci/07_stageClean.yml b/NodeApp/.gitlab-ci/08_stageClean.yml
similarity index 100%
rename from NodeApp/.gitlab-ci/07_stageClean.yml
rename to NodeApp/.gitlab-ci/08_stageClean.yml
diff --git a/NodeApp/.gitlab-ci/08_stageUpload.yml b/NodeApp/.gitlab-ci/09_stageUpload.yml
similarity index 100%
rename from NodeApp/.gitlab-ci/08_stageUpload.yml
rename to NodeApp/.gitlab-ci/09_stageUpload.yml
diff --git a/NodeApp/.gitlab-ci/09_stageRelease.yml b/NodeApp/.gitlab-ci/10_stageRelease.yml
similarity index 100%
rename from NodeApp/.gitlab-ci/09_stageRelease.yml
rename to NodeApp/.gitlab-ci/10_stageRelease.yml
diff --git a/NodeApp/.idea/jetbrainsConfiguration b/NodeApp/.idea/jetbrainsConfiguration
index 4d703a2dd39ec0c2b71bbbbda8900588c4e360bd..ffc5d65f9f0f0e825688177425e526131aa84631 160000
--- a/NodeApp/.idea/jetbrainsConfiguration
+++ b/NodeApp/.idea/jetbrainsConfiguration
@@ -1 +1 @@
-Subproject commit 4d703a2dd39ec0c2b71bbbbda8900588c4e360bd
+Subproject commit ffc5d65f9f0f0e825688177425e526131aa84631
diff --git a/NodeApp/.idea/jsLinters/eslint.xml b/NodeApp/.idea/jsLinters/eslint.xml
new file mode 100644
index 0000000000000000000000000000000000000000..541945bb0819b8ff4a3dae9431632ebd10e6f98b
--- /dev/null
+++ b/NodeApp/.idea/jsLinters/eslint.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="EslintConfiguration">
+    <option name="fix-on-save" value="true" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/NodeApp/.idea/jsLinters/jshint.xml b/NodeApp/.idea/jsLinters/jshint.xml
new file mode 100644
index 0000000000000000000000000000000000000000..93655fde02e4d1d5e76b1661cb2e59eaebe9c2bd
--- /dev/null
+++ b/NodeApp/.idea/jsLinters/jshint.xml
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="JSHintConfiguration" version="2.13.6" use-config-file="false">
+    <option asi="false" />
+    <option bitwise="true" />
+    <option boss="false" />
+    <option browser="true" />
+    <option browserify="false" />
+    <option camelcase="false" />
+    <option couch="false" />
+    <option curly="true" />
+    <option debug="false" />
+    <option devel="false" />
+    <option dojo="false" />
+    <option elision="false" />
+    <option enforceall="false" />
+    <option eqeqeq="true" />
+    <option eqnull="false" />
+    <option es3="false" />
+    <option es5="false" />
+    <option esnext="false" />
+    <option evil="false" />
+    <option expr="false" />
+    <option forin="true" />
+    <option freeze="false" />
+    <option funcscope="false" />
+    <option futurehostile="false" />
+    <option gcl="false" />
+    <option globalstrict="false" />
+    <option immed="false" />
+    <option iterator="false" />
+    <option jasmine="false" />
+    <option jquery="false" />
+    <option lastsemic="false" />
+    <option latedef="false" />
+    <option laxbreak="false" />
+    <option laxcomma="false" />
+    <option loopfunc="false" />
+    <option maxerr="50" />
+    <option mocha="false" />
+    <option module="false" />
+    <option mootools="false" />
+    <option moz="false" />
+    <option multistr="false" />
+    <option newcap="false" />
+    <option noarg="true" />
+    <option nocomma="false" />
+    <option node="true" />
+    <option noempty="true" />
+    <option nomen="false" />
+    <option nonbsp="false" />
+    <option nonew="true" />
+    <option nonstandard="false" />
+    <option notypeof="false" />
+    <option noyield="false" />
+    <option onevar="false" />
+    <option passfail="false" />
+    <option phantom="false" />
+    <option plusplus="false" />
+    <option proto="false" />
+    <option prototypejs="false" />
+    <option qunit="false" />
+    <option quotmark="false" />
+    <option rhino="false" />
+    <option scripturl="false" />
+    <option shadow="false" />
+    <option shelljs="false" />
+    <option singleGroups="false" />
+    <option smarttabs="false" />
+    <option strict="true" />
+    <option sub="false" />
+    <option supernew="false" />
+    <option trailing="false" />
+    <option typed="false" />
+    <option undef="true" />
+    <option unused="false" />
+    <option validthis="false" />
+    <option varstmt="false" />
+    <option white="false" />
+    <option withstmt="false" />
+    <option worker="false" />
+    <option wsh="false" />
+    <option yui="false" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/NodeApp/package-lock.json b/NodeApp/package-lock.json
index bed60a32df6a7f752acf5f8c5e5d9541ad70c8b2..fb1bd888e9523ac99e94d7d6e33c49dc85b79378 100644
--- a/NodeApp/package-lock.json
+++ b/NodeApp/package-lock.json
@@ -1,12 +1,12 @@
 {
     "name": "dojo_cli",
-    "version": "3.0.0",
+    "version": "3.1.0",
     "lockfileVersion": 3,
     "requires": true,
     "packages": {
         "": {
             "name": "dojo_cli",
-            "version": "3.0.0",
+            "version": "3.1.0",
             "license": "AGPLv3",
             "dependencies": {
                 "ajv": "^8.12.0",
@@ -38,6 +38,8 @@
                 "@types/node": "^18.17.2",
                 "@types/openurl": "^1.0.1",
                 "@types/tar-stream": "^2.2.2",
+                "@typescript-eslint/eslint-plugin": "^6.10.0",
+                "@typescript-eslint/parser": "^6.10.0",
                 "dotenv-vault": "^1.25.0",
                 "genversion": "^3.1.1",
                 "pkg": "^5.8.1",
@@ -46,6 +48,16 @@
                 "typescript": "^5.1.6"
             }
         },
+        "node_modules/@aashutoshrathi/word-wrap": {
+            "version": "1.2.6",
+            "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz",
+            "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==",
+            "dev": true,
+            "peer": true,
+            "engines": {
+                "node": ">=0.10.0"
+            }
+        },
         "node_modules/@babel/generator": {
             "version": "7.18.2",
             "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.2.tgz",
@@ -144,6 +156,157 @@
                 "kuler": "^2.0.0"
             }
         },
+        "node_modules/@eslint-community/eslint-utils": {
+            "version": "4.4.0",
+            "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
+            "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==",
+            "dev": true,
+            "dependencies": {
+                "eslint-visitor-keys": "^3.3.0"
+            },
+            "engines": {
+                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+            },
+            "peerDependencies": {
+                "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
+            }
+        },
+        "node_modules/@eslint-community/regexpp": {
+            "version": "4.10.0",
+            "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz",
+            "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==",
+            "dev": true,
+            "engines": {
+                "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
+            }
+        },
+        "node_modules/@eslint/eslintrc": {
+            "version": "2.1.3",
+            "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.3.tgz",
+            "integrity": "sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==",
+            "dev": true,
+            "peer": true,
+            "dependencies": {
+                "ajv": "^6.12.4",
+                "debug": "^4.3.2",
+                "espree": "^9.6.0",
+                "globals": "^13.19.0",
+                "ignore": "^5.2.0",
+                "import-fresh": "^3.2.1",
+                "js-yaml": "^4.1.0",
+                "minimatch": "^3.1.2",
+                "strip-json-comments": "^3.1.1"
+            },
+            "engines": {
+                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/eslint"
+            }
+        },
+        "node_modules/@eslint/eslintrc/node_modules/ajv": {
+            "version": "6.12.6",
+            "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+            "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+            "dev": true,
+            "peer": true,
+            "dependencies": {
+                "fast-deep-equal": "^3.1.1",
+                "fast-json-stable-stringify": "^2.0.0",
+                "json-schema-traverse": "^0.4.1",
+                "uri-js": "^4.2.2"
+            },
+            "funding": {
+                "type": "github",
+                "url": "https://github.com/sponsors/epoberezkin"
+            }
+        },
+        "node_modules/@eslint/eslintrc/node_modules/argparse": {
+            "version": "2.0.1",
+            "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+            "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+            "dev": true,
+            "peer": true
+        },
+        "node_modules/@eslint/eslintrc/node_modules/js-yaml": {
+            "version": "4.1.0",
+            "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+            "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+            "dev": true,
+            "peer": true,
+            "dependencies": {
+                "argparse": "^2.0.1"
+            },
+            "bin": {
+                "js-yaml": "bin/js-yaml.js"
+            }
+        },
+        "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": {
+            "version": "0.4.1",
+            "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+            "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+            "dev": true,
+            "peer": true
+        },
+        "node_modules/@eslint/eslintrc/node_modules/strip-json-comments": {
+            "version": "3.1.1",
+            "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+            "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+            "dev": true,
+            "peer": true,
+            "engines": {
+                "node": ">=8"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
+        "node_modules/@eslint/js": {
+            "version": "8.53.0",
+            "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.53.0.tgz",
+            "integrity": "sha512-Kn7K8dx/5U6+cT1yEhpX1w4PCSg0M+XyRILPgvwcEBjerFWCwQj5sbr3/VmxqV0JGHCBCzyd6LxypEuehypY1w==",
+            "dev": true,
+            "peer": true,
+            "engines": {
+                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+            }
+        },
+        "node_modules/@humanwhocodes/config-array": {
+            "version": "0.11.13",
+            "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz",
+            "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==",
+            "dev": true,
+            "peer": true,
+            "dependencies": {
+                "@humanwhocodes/object-schema": "^2.0.1",
+                "debug": "^4.1.1",
+                "minimatch": "^3.0.5"
+            },
+            "engines": {
+                "node": ">=10.10.0"
+            }
+        },
+        "node_modules/@humanwhocodes/module-importer": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+            "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+            "dev": true,
+            "peer": true,
+            "engines": {
+                "node": ">=12.22"
+            },
+            "funding": {
+                "type": "github",
+                "url": "https://github.com/sponsors/nzakas"
+            }
+        },
+        "node_modules/@humanwhocodes/object-schema": {
+            "version": "2.0.1",
+            "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz",
+            "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==",
+            "dev": true,
+            "peer": true
+        },
         "node_modules/@jridgewell/gen-mapping": {
             "version": "0.3.3",
             "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz",
@@ -661,6 +824,12 @@
                 "rxjs": "^7.2.0"
             }
         },
+        "node_modules/@types/json-schema": {
+            "version": "7.0.15",
+            "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
+            "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
+            "dev": true
+        },
         "node_modules/@types/jsonfile": {
             "version": "6.1.2",
             "resolved": "https://registry.npmjs.org/@types/jsonfile/-/jsonfile-6.1.2.tgz",
@@ -694,6 +863,12 @@
                 "@types/node": "*"
             }
         },
+        "node_modules/@types/semver": {
+            "version": "7.5.5",
+            "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.5.tgz",
+            "integrity": "sha512-+d+WYC1BxJ6yVOgUgzK8gWvp5qF8ssV5r4nsDcZWKRWcDQLQ619tvWAxJQYGgBrO1MnLJC7a5GtiYsAoQ47dJg==",
+            "dev": true
+        },
         "node_modules/@types/tar-stream": {
             "version": "2.2.3",
             "resolved": "https://registry.npmjs.org/@types/tar-stream/-/tar-stream-2.2.3.tgz",
@@ -717,6 +892,202 @@
             "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.3.tgz",
             "integrity": "sha512-6tOUG+nVHn0cJbVp25JFayS5UE6+xlbcNF9Lo9mU7U0zk3zeUShZied4YEQZjy1JBF043FSkdXw8YkUJuVtB5g=="
         },
+        "node_modules/@typescript-eslint/eslint-plugin": {
+            "version": "6.10.0",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.10.0.tgz",
+            "integrity": "sha512-uoLj4g2OTL8rfUQVx2AFO1hp/zja1wABJq77P6IclQs6I/m9GLrm7jCdgzZkvWdDCQf1uEvoa8s8CupsgWQgVg==",
+            "dev": true,
+            "dependencies": {
+                "@eslint-community/regexpp": "^4.5.1",
+                "@typescript-eslint/scope-manager": "6.10.0",
+                "@typescript-eslint/type-utils": "6.10.0",
+                "@typescript-eslint/utils": "6.10.0",
+                "@typescript-eslint/visitor-keys": "6.10.0",
+                "debug": "^4.3.4",
+                "graphemer": "^1.4.0",
+                "ignore": "^5.2.4",
+                "natural-compare": "^1.4.0",
+                "semver": "^7.5.4",
+                "ts-api-utils": "^1.0.1"
+            },
+            "engines": {
+                "node": "^16.0.0 || >=18.0.0"
+            },
+            "funding": {
+                "type": "opencollective",
+                "url": "https://opencollective.com/typescript-eslint"
+            },
+            "peerDependencies": {
+                "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha",
+                "eslint": "^7.0.0 || ^8.0.0"
+            },
+            "peerDependenciesMeta": {
+                "typescript": {
+                    "optional": true
+                }
+            }
+        },
+        "node_modules/@typescript-eslint/parser": {
+            "version": "6.10.0",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.10.0.tgz",
+            "integrity": "sha512-+sZwIj+s+io9ozSxIWbNB5873OSdfeBEH/FR0re14WLI6BaKuSOnnwCJ2foUiu8uXf4dRp1UqHP0vrZ1zXGrog==",
+            "dev": true,
+            "dependencies": {
+                "@typescript-eslint/scope-manager": "6.10.0",
+                "@typescript-eslint/types": "6.10.0",
+                "@typescript-eslint/typescript-estree": "6.10.0",
+                "@typescript-eslint/visitor-keys": "6.10.0",
+                "debug": "^4.3.4"
+            },
+            "engines": {
+                "node": "^16.0.0 || >=18.0.0"
+            },
+            "funding": {
+                "type": "opencollective",
+                "url": "https://opencollective.com/typescript-eslint"
+            },
+            "peerDependencies": {
+                "eslint": "^7.0.0 || ^8.0.0"
+            },
+            "peerDependenciesMeta": {
+                "typescript": {
+                    "optional": true
+                }
+            }
+        },
+        "node_modules/@typescript-eslint/scope-manager": {
+            "version": "6.10.0",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.10.0.tgz",
+            "integrity": "sha512-TN/plV7dzqqC2iPNf1KrxozDgZs53Gfgg5ZHyw8erd6jd5Ta/JIEcdCheXFt9b1NYb93a1wmIIVW/2gLkombDg==",
+            "dev": true,
+            "dependencies": {
+                "@typescript-eslint/types": "6.10.0",
+                "@typescript-eslint/visitor-keys": "6.10.0"
+            },
+            "engines": {
+                "node": "^16.0.0 || >=18.0.0"
+            },
+            "funding": {
+                "type": "opencollective",
+                "url": "https://opencollective.com/typescript-eslint"
+            }
+        },
+        "node_modules/@typescript-eslint/type-utils": {
+            "version": "6.10.0",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.10.0.tgz",
+            "integrity": "sha512-wYpPs3hgTFblMYwbYWPT3eZtaDOjbLyIYuqpwuLBBqhLiuvJ+9sEp2gNRJEtR5N/c9G1uTtQQL5AhV0fEPJYcg==",
+            "dev": true,
+            "dependencies": {
+                "@typescript-eslint/typescript-estree": "6.10.0",
+                "@typescript-eslint/utils": "6.10.0",
+                "debug": "^4.3.4",
+                "ts-api-utils": "^1.0.1"
+            },
+            "engines": {
+                "node": "^16.0.0 || >=18.0.0"
+            },
+            "funding": {
+                "type": "opencollective",
+                "url": "https://opencollective.com/typescript-eslint"
+            },
+            "peerDependencies": {
+                "eslint": "^7.0.0 || ^8.0.0"
+            },
+            "peerDependenciesMeta": {
+                "typescript": {
+                    "optional": true
+                }
+            }
+        },
+        "node_modules/@typescript-eslint/types": {
+            "version": "6.10.0",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.10.0.tgz",
+            "integrity": "sha512-36Fq1PWh9dusgo3vH7qmQAj5/AZqARky1Wi6WpINxB6SkQdY5vQoT2/7rW7uBIsPDcvvGCLi4r10p0OJ7ITAeg==",
+            "dev": true,
+            "engines": {
+                "node": "^16.0.0 || >=18.0.0"
+            },
+            "funding": {
+                "type": "opencollective",
+                "url": "https://opencollective.com/typescript-eslint"
+            }
+        },
+        "node_modules/@typescript-eslint/typescript-estree": {
+            "version": "6.10.0",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.10.0.tgz",
+            "integrity": "sha512-ek0Eyuy6P15LJVeghbWhSrBCj/vJpPXXR+EpaRZqou7achUWL8IdYnMSC5WHAeTWswYQuP2hAZgij/bC9fanBg==",
+            "dev": true,
+            "dependencies": {
+                "@typescript-eslint/types": "6.10.0",
+                "@typescript-eslint/visitor-keys": "6.10.0",
+                "debug": "^4.3.4",
+                "globby": "^11.1.0",
+                "is-glob": "^4.0.3",
+                "semver": "^7.5.4",
+                "ts-api-utils": "^1.0.1"
+            },
+            "engines": {
+                "node": "^16.0.0 || >=18.0.0"
+            },
+            "funding": {
+                "type": "opencollective",
+                "url": "https://opencollective.com/typescript-eslint"
+            },
+            "peerDependenciesMeta": {
+                "typescript": {
+                    "optional": true
+                }
+            }
+        },
+        "node_modules/@typescript-eslint/utils": {
+            "version": "6.10.0",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.10.0.tgz",
+            "integrity": "sha512-v+pJ1/RcVyRc0o4wAGux9x42RHmAjIGzPRo538Z8M1tVx6HOnoQBCX/NoadHQlZeC+QO2yr4nNSFWOoraZCAyg==",
+            "dev": true,
+            "dependencies": {
+                "@eslint-community/eslint-utils": "^4.4.0",
+                "@types/json-schema": "^7.0.12",
+                "@types/semver": "^7.5.0",
+                "@typescript-eslint/scope-manager": "6.10.0",
+                "@typescript-eslint/types": "6.10.0",
+                "@typescript-eslint/typescript-estree": "6.10.0",
+                "semver": "^7.5.4"
+            },
+            "engines": {
+                "node": "^16.0.0 || >=18.0.0"
+            },
+            "funding": {
+                "type": "opencollective",
+                "url": "https://opencollective.com/typescript-eslint"
+            },
+            "peerDependencies": {
+                "eslint": "^7.0.0 || ^8.0.0"
+            }
+        },
+        "node_modules/@typescript-eslint/visitor-keys": {
+            "version": "6.10.0",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.10.0.tgz",
+            "integrity": "sha512-xMGluxQIEtOM7bqFCo+rCMh5fqI+ZxV5RUUOa29iVPz1OgCZrtc7rFnz5cLUazlkPKYqX+75iuDq7m0HQ48nCg==",
+            "dev": true,
+            "dependencies": {
+                "@typescript-eslint/types": "6.10.0",
+                "eslint-visitor-keys": "^3.4.1"
+            },
+            "engines": {
+                "node": "^16.0.0 || >=18.0.0"
+            },
+            "funding": {
+                "type": "opencollective",
+                "url": "https://opencollective.com/typescript-eslint"
+            }
+        },
+        "node_modules/@ungap/structured-clone": {
+            "version": "1.2.0",
+            "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
+            "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==",
+            "dev": true,
+            "peer": true
+        },
         "node_modules/acorn": {
             "version": "8.10.0",
             "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz",
@@ -729,6 +1100,16 @@
                 "node": ">=0.4.0"
             }
         },
+        "node_modules/acorn-jsx": {
+            "version": "5.3.2",
+            "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+            "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+            "dev": true,
+            "peer": true,
+            "peerDependencies": {
+                "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+            }
+        },
         "node_modules/acorn-walk": {
             "version": "8.2.0",
             "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz",
@@ -1013,6 +1394,16 @@
                 "node": ">=0.10.0"
             }
         },
+        "node_modules/callsites": {
+            "version": "3.1.0",
+            "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+            "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+            "dev": true,
+            "peer": true,
+            "engines": {
+                "node": ">=6"
+            }
+        },
         "node_modules/camelcase": {
             "version": "6.3.0",
             "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
@@ -1307,6 +1698,13 @@
                 "node": ">=4.0.0"
             }
         },
+        "node_modules/deep-is": {
+            "version": "0.1.4",
+            "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+            "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+            "dev": true,
+            "peer": true
+        },
         "node_modules/defaults": {
             "version": "1.0.4",
             "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz",
@@ -1356,6 +1754,19 @@
                 "node": ">=8"
             }
         },
+        "node_modules/doctrine": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+            "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+            "dev": true,
+            "peer": true,
+            "dependencies": {
+                "esutils": "^2.0.2"
+            },
+            "engines": {
+                "node": ">=6.0.0"
+            }
+        },
         "node_modules/dotenv": {
             "version": "16.3.1",
             "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz",
@@ -1479,6 +1890,166 @@
                 "url": "https://github.com/sponsors/sindresorhus"
             }
         },
+        "node_modules/eslint": {
+            "version": "8.53.0",
+            "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.53.0.tgz",
+            "integrity": "sha512-N4VuiPjXDUa4xVeV/GC/RV3hQW9Nw+Y463lkWaKKXKYMvmRiRDAtfpuPFLN+E1/6ZhyR8J2ig+eVREnYgUsiag==",
+            "dev": true,
+            "peer": true,
+            "dependencies": {
+                "@eslint-community/eslint-utils": "^4.2.0",
+                "@eslint-community/regexpp": "^4.6.1",
+                "@eslint/eslintrc": "^2.1.3",
+                "@eslint/js": "8.53.0",
+                "@humanwhocodes/config-array": "^0.11.13",
+                "@humanwhocodes/module-importer": "^1.0.1",
+                "@nodelib/fs.walk": "^1.2.8",
+                "@ungap/structured-clone": "^1.2.0",
+                "ajv": "^6.12.4",
+                "chalk": "^4.0.0",
+                "cross-spawn": "^7.0.2",
+                "debug": "^4.3.2",
+                "doctrine": "^3.0.0",
+                "escape-string-regexp": "^4.0.0",
+                "eslint-scope": "^7.2.2",
+                "eslint-visitor-keys": "^3.4.3",
+                "espree": "^9.6.1",
+                "esquery": "^1.4.2",
+                "esutils": "^2.0.2",
+                "fast-deep-equal": "^3.1.3",
+                "file-entry-cache": "^6.0.1",
+                "find-up": "^5.0.0",
+                "glob-parent": "^6.0.2",
+                "globals": "^13.19.0",
+                "graphemer": "^1.4.0",
+                "ignore": "^5.2.0",
+                "imurmurhash": "^0.1.4",
+                "is-glob": "^4.0.0",
+                "is-path-inside": "^3.0.3",
+                "js-yaml": "^4.1.0",
+                "json-stable-stringify-without-jsonify": "^1.0.1",
+                "levn": "^0.4.1",
+                "lodash.merge": "^4.6.2",
+                "minimatch": "^3.1.2",
+                "natural-compare": "^1.4.0",
+                "optionator": "^0.9.3",
+                "strip-ansi": "^6.0.1",
+                "text-table": "^0.2.0"
+            },
+            "bin": {
+                "eslint": "bin/eslint.js"
+            },
+            "engines": {
+                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/eslint"
+            }
+        },
+        "node_modules/eslint-scope": {
+            "version": "7.2.2",
+            "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
+            "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
+            "dev": true,
+            "peer": true,
+            "dependencies": {
+                "esrecurse": "^4.3.0",
+                "estraverse": "^5.2.0"
+            },
+            "engines": {
+                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/eslint"
+            }
+        },
+        "node_modules/eslint-visitor-keys": {
+            "version": "3.4.3",
+            "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+            "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+            "dev": true,
+            "engines": {
+                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/eslint"
+            }
+        },
+        "node_modules/eslint/node_modules/ajv": {
+            "version": "6.12.6",
+            "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+            "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+            "dev": true,
+            "peer": true,
+            "dependencies": {
+                "fast-deep-equal": "^3.1.1",
+                "fast-json-stable-stringify": "^2.0.0",
+                "json-schema-traverse": "^0.4.1",
+                "uri-js": "^4.2.2"
+            },
+            "funding": {
+                "type": "github",
+                "url": "https://github.com/sponsors/epoberezkin"
+            }
+        },
+        "node_modules/eslint/node_modules/argparse": {
+            "version": "2.0.1",
+            "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+            "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+            "dev": true,
+            "peer": true
+        },
+        "node_modules/eslint/node_modules/glob-parent": {
+            "version": "6.0.2",
+            "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+            "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+            "dev": true,
+            "peer": true,
+            "dependencies": {
+                "is-glob": "^4.0.3"
+            },
+            "engines": {
+                "node": ">=10.13.0"
+            }
+        },
+        "node_modules/eslint/node_modules/js-yaml": {
+            "version": "4.1.0",
+            "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+            "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+            "dev": true,
+            "peer": true,
+            "dependencies": {
+                "argparse": "^2.0.1"
+            },
+            "bin": {
+                "js-yaml": "bin/js-yaml.js"
+            }
+        },
+        "node_modules/eslint/node_modules/json-schema-traverse": {
+            "version": "0.4.1",
+            "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+            "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+            "dev": true,
+            "peer": true
+        },
+        "node_modules/espree": {
+            "version": "9.6.1",
+            "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
+            "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
+            "dev": true,
+            "peer": true,
+            "dependencies": {
+                "acorn": "^8.9.0",
+                "acorn-jsx": "^5.3.2",
+                "eslint-visitor-keys": "^3.4.1"
+            },
+            "engines": {
+                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/eslint"
+            }
+        },
         "node_modules/esprima": {
             "version": "4.0.1",
             "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
@@ -1492,6 +2063,52 @@
                 "node": ">=4"
             }
         },
+        "node_modules/esquery": {
+            "version": "1.5.0",
+            "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
+            "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
+            "dev": true,
+            "peer": true,
+            "dependencies": {
+                "estraverse": "^5.1.0"
+            },
+            "engines": {
+                "node": ">=0.10"
+            }
+        },
+        "node_modules/esrecurse": {
+            "version": "4.3.0",
+            "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+            "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+            "dev": true,
+            "peer": true,
+            "dependencies": {
+                "estraverse": "^5.2.0"
+            },
+            "engines": {
+                "node": ">=4.0"
+            }
+        },
+        "node_modules/estraverse": {
+            "version": "5.3.0",
+            "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+            "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+            "dev": true,
+            "peer": true,
+            "engines": {
+                "node": ">=4.0"
+            }
+        },
+        "node_modules/esutils": {
+            "version": "2.0.3",
+            "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+            "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+            "dev": true,
+            "peer": true,
+            "engines": {
+                "node": ">=0.10.0"
+            }
+        },
         "node_modules/expand-template": {
             "version": "2.0.3",
             "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
@@ -1540,6 +2157,13 @@
                 "node": ">=8.6.0"
             }
         },
+        "node_modules/fast-json-stable-stringify": {
+            "version": "2.1.0",
+            "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+            "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+            "dev": true,
+            "peer": true
+        },
         "node_modules/fast-levenshtein": {
             "version": "3.0.0",
             "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-3.0.0.tgz",
@@ -1594,6 +2218,19 @@
                 "node": ">=0.8.0"
             }
         },
+        "node_modules/file-entry-cache": {
+            "version": "6.0.1",
+            "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+            "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+            "dev": true,
+            "peer": true,
+            "dependencies": {
+                "flat-cache": "^3.0.4"
+            },
+            "engines": {
+                "node": "^10.12.0 || >=12.0.0"
+            }
+        },
         "node_modules/filelist": {
             "version": "1.0.4",
             "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz",
@@ -1654,6 +2291,45 @@
                 "parents": "^1.0.1"
             }
         },
+        "node_modules/find-up": {
+            "version": "5.0.0",
+            "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+            "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+            "dev": true,
+            "peer": true,
+            "dependencies": {
+                "locate-path": "^6.0.0",
+                "path-exists": "^4.0.0"
+            },
+            "engines": {
+                "node": ">=10"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
+        "node_modules/flat-cache": {
+            "version": "3.1.1",
+            "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.1.tgz",
+            "integrity": "sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==",
+            "dev": true,
+            "peer": true,
+            "dependencies": {
+                "flatted": "^3.2.9",
+                "keyv": "^4.5.3",
+                "rimraf": "^3.0.2"
+            },
+            "engines": {
+                "node": ">=12.0.0"
+            }
+        },
+        "node_modules/flatted": {
+            "version": "3.2.9",
+            "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz",
+            "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==",
+            "dev": true,
+            "peer": true
+        },
         "node_modules/fn.name": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz",
@@ -1750,6 +2426,13 @@
                 "node": ">=14.14"
             }
         },
+        "node_modules/fs.realpath": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+            "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+            "dev": true,
+            "peer": true
+        },
         "node_modules/genversion": {
             "version": "3.1.1",
             "resolved": "https://registry.npmjs.org/genversion/-/genversion-3.1.1.tgz",
@@ -1799,6 +2482,27 @@
             "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==",
             "dev": true
         },
+        "node_modules/glob": {
+            "version": "7.2.3",
+            "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+            "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+            "dev": true,
+            "peer": true,
+            "dependencies": {
+                "fs.realpath": "^1.0.0",
+                "inflight": "^1.0.4",
+                "inherits": "2",
+                "minimatch": "^3.1.1",
+                "once": "^1.3.0",
+                "path-is-absolute": "^1.0.0"
+            },
+            "engines": {
+                "node": "*"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/isaacs"
+            }
+        },
         "node_modules/glob-parent": {
             "version": "5.1.2",
             "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
@@ -1811,6 +2515,22 @@
                 "node": ">= 6"
             }
         },
+        "node_modules/globals": {
+            "version": "13.23.0",
+            "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz",
+            "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==",
+            "dev": true,
+            "peer": true,
+            "dependencies": {
+                "type-fest": "^0.20.2"
+            },
+            "engines": {
+                "node": ">=8"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
         "node_modules/globby": {
             "version": "11.1.0",
             "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
@@ -1836,6 +2556,12 @@
             "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
             "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="
         },
+        "node_modules/graphemer": {
+            "version": "1.4.0",
+            "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
+            "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
+            "dev": true
+        },
         "node_modules/has": {
             "version": "1.0.4",
             "resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz",
@@ -1936,6 +2662,33 @@
                 "node": ">= 4"
             }
         },
+        "node_modules/import-fresh": {
+            "version": "3.3.0",
+            "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+            "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+            "dev": true,
+            "peer": true,
+            "dependencies": {
+                "parent-module": "^1.0.0",
+                "resolve-from": "^4.0.0"
+            },
+            "engines": {
+                "node": ">=6"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
+        "node_modules/imurmurhash": {
+            "version": "0.1.4",
+            "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+            "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+            "dev": true,
+            "peer": true,
+            "engines": {
+                "node": ">=0.8.19"
+            }
+        },
         "node_modules/indent-string": {
             "version": "4.0.0",
             "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
@@ -1945,6 +2698,17 @@
                 "node": ">=8"
             }
         },
+        "node_modules/inflight": {
+            "version": "1.0.6",
+            "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+            "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+            "dev": true,
+            "peer": true,
+            "dependencies": {
+                "once": "^1.3.0",
+                "wrappy": "1"
+            }
+        },
         "node_modules/inherits": {
             "version": "2.0.4",
             "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
@@ -2089,6 +2853,16 @@
                 "node": ">=0.12.0"
             }
         },
+        "node_modules/is-path-inside": {
+            "version": "3.0.3",
+            "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
+            "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
+            "dev": true,
+            "peer": true,
+            "engines": {
+                "node": ">=8"
+            }
+        },
         "node_modules/is-retry-allowed": {
             "version": "1.2.0",
             "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz",
@@ -2187,6 +2961,13 @@
                 "node": ">=4"
             }
         },
+        "node_modules/json-buffer": {
+            "version": "3.0.1",
+            "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+            "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+            "dev": true,
+            "peer": true
+        },
         "node_modules/json-parse-better-errors": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
@@ -2198,6 +2979,13 @@
             "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
             "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="
         },
+        "node_modules/json-stable-stringify-without-jsonify": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+            "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+            "dev": true,
+            "peer": true
+        },
         "node_modules/json5": {
             "version": "2.2.3",
             "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
@@ -2268,11 +3056,51 @@
                 "safe-buffer": "^5.0.1"
             }
         },
+        "node_modules/keyv": {
+            "version": "4.5.4",
+            "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+            "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+            "dev": true,
+            "peer": true,
+            "dependencies": {
+                "json-buffer": "3.0.1"
+            }
+        },
         "node_modules/kuler": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz",
             "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A=="
         },
+        "node_modules/levn": {
+            "version": "0.4.1",
+            "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+            "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+            "dev": true,
+            "peer": true,
+            "dependencies": {
+                "prelude-ls": "^1.2.1",
+                "type-check": "~0.4.0"
+            },
+            "engines": {
+                "node": ">= 0.8.0"
+            }
+        },
+        "node_modules/locate-path": {
+            "version": "6.0.0",
+            "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+            "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+            "dev": true,
+            "peer": true,
+            "dependencies": {
+                "p-locate": "^5.0.0"
+            },
+            "engines": {
+                "node": ">=10"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
         "node_modules/lodash": {
             "version": "4.17.21",
             "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
@@ -2314,6 +3142,13 @@
             "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
             "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw=="
         },
+        "node_modules/lodash.merge": {
+            "version": "4.6.2",
+            "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+            "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+            "dev": true,
+            "peer": true
+        },
         "node_modules/lodash.once": {
             "version": "4.1.1",
             "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
@@ -2530,6 +3365,12 @@
             "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==",
             "dev": true
         },
+        "node_modules/natural-compare": {
+            "version": "1.4.0",
+            "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+            "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+            "dev": true
+        },
         "node_modules/natural-orderby": {
             "version": "2.0.3",
             "resolved": "https://registry.npmjs.org/natural-orderby/-/natural-orderby-2.0.3.tgz",
@@ -2616,6 +3457,31 @@
             "resolved": "https://registry.npmjs.org/openurl/-/openurl-1.1.1.tgz",
             "integrity": "sha512-d/gTkTb1i1GKz5k3XE3XFV/PxQ1k45zDqGP2OA7YhgsaLoqm6qRvARAZOFer1fcXritWlGBRCu/UgeS4HAnXAA=="
         },
+        "node_modules/optionator": {
+            "version": "0.9.3",
+            "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz",
+            "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==",
+            "dev": true,
+            "peer": true,
+            "dependencies": {
+                "@aashutoshrathi/word-wrap": "^1.2.3",
+                "deep-is": "^0.1.3",
+                "fast-levenshtein": "^2.0.6",
+                "levn": "^0.4.1",
+                "prelude-ls": "^1.2.1",
+                "type-check": "^0.4.0"
+            },
+            "engines": {
+                "node": ">= 0.8.0"
+            }
+        },
+        "node_modules/optionator/node_modules/fast-levenshtein": {
+            "version": "2.0.6",
+            "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+            "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+            "dev": true,
+            "peer": true
+        },
         "node_modules/ora": {
             "version": "5.4.1",
             "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz",
@@ -2655,6 +3521,51 @@
                 "node": ">=8"
             }
         },
+        "node_modules/p-limit": {
+            "version": "3.1.0",
+            "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+            "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+            "dev": true,
+            "peer": true,
+            "dependencies": {
+                "yocto-queue": "^0.1.0"
+            },
+            "engines": {
+                "node": ">=10"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
+        "node_modules/p-locate": {
+            "version": "5.0.0",
+            "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+            "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+            "dev": true,
+            "peer": true,
+            "dependencies": {
+                "p-limit": "^3.0.2"
+            },
+            "engines": {
+                "node": ">=10"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
+        "node_modules/parent-module": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+            "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+            "dev": true,
+            "peer": true,
+            "dependencies": {
+                "callsites": "^3.0.0"
+            },
+            "engines": {
+                "node": ">=6"
+            }
+        },
         "node_modules/parents": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz",
@@ -2687,6 +3598,26 @@
                 "cross-spawn": "^7.0.3"
             }
         },
+        "node_modules/path-exists": {
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+            "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+            "dev": true,
+            "peer": true,
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/path-is-absolute": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+            "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+            "dev": true,
+            "peer": true,
+            "engines": {
+                "node": ">=0.10.0"
+            }
+        },
         "node_modules/path-key": {
             "version": "3.1.1",
             "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
@@ -2840,6 +3771,16 @@
                 "node": ">=10"
             }
         },
+        "node_modules/prelude-ls": {
+            "version": "1.2.1",
+            "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+            "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+            "dev": true,
+            "peer": true,
+            "engines": {
+                "node": ">= 0.8.0"
+            }
+        },
         "node_modules/process-nextick-args": {
             "version": "2.0.1",
             "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
@@ -2974,6 +3915,16 @@
                 "url": "https://github.com/sponsors/ljharb"
             }
         },
+        "node_modules/resolve-from": {
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+            "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+            "dev": true,
+            "peer": true,
+            "engines": {
+                "node": ">=4"
+            }
+        },
         "node_modules/resolve/node_modules/is-core-module": {
             "version": "2.13.0",
             "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz",
@@ -3008,6 +3959,22 @@
                 "node": ">=0.10.0"
             }
         },
+        "node_modules/rimraf": {
+            "version": "3.0.2",
+            "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+            "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+            "dev": true,
+            "peer": true,
+            "dependencies": {
+                "glob": "^7.1.3"
+            },
+            "bin": {
+                "rimraf": "bin.js"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/isaacs"
+            }
+        },
         "node_modules/run-async": {
             "version": "2.4.1",
             "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz",
@@ -3386,6 +4353,13 @@
             "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz",
             "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg=="
         },
+        "node_modules/text-table": {
+            "version": "0.2.0",
+            "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+            "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
+            "dev": true,
+            "peer": true
+        },
         "node_modules/through": {
             "version": "2.3.8",
             "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
@@ -3443,6 +4417,18 @@
                 "node": ">= 14.0.0"
             }
         },
+        "node_modules/ts-api-utils": {
+            "version": "1.0.3",
+            "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz",
+            "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==",
+            "dev": true,
+            "engines": {
+                "node": ">=16.13.0"
+            },
+            "peerDependencies": {
+                "typescript": ">=4.2.0"
+            }
+        },
         "node_modules/ts-node": {
             "version": "10.9.1",
             "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz",
@@ -3503,6 +4489,19 @@
                 "node": "*"
             }
         },
+        "node_modules/type-check": {
+            "version": "0.4.0",
+            "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+            "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+            "dev": true,
+            "peer": true,
+            "dependencies": {
+                "prelude-ls": "^1.2.1"
+            },
+            "engines": {
+                "node": ">= 0.8.0"
+            }
+        },
         "node_modules/type-fest": {
             "version": "0.20.2",
             "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
@@ -3724,6 +4723,19 @@
             "engines": {
                 "node": ">=6"
             }
+        },
+        "node_modules/yocto-queue": {
+            "version": "0.1.0",
+            "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+            "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+            "dev": true,
+            "peer": true,
+            "engines": {
+                "node": ">=10"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
         }
     }
 }
diff --git a/NodeApp/package.json b/NodeApp/package.json
index f4d6fb8d5625f131413dbbbf072570dd8bd030d7..9ae4a08e1f991b40717b4d10197bd84e1fb2480b 100644
--- a/NodeApp/package.json
+++ b/NodeApp/package.json
@@ -26,9 +26,10 @@
     },
     "scripts"        : {
         "dotenv:build": "npx dotenv-vault local build",
+        "lint"        : "npx eslint .",
         "genversion"  : "npx genversion -s -e src/config/Version.ts",
         "build"       : "npm run genversion; npx tsc",
-        "start:dev"   : "npm run genversion; npx ts-node src/app.ts",
+        "start:dev"   : "npm run genversion; npm run lint; npx ts-node src/app.ts",
         "test"        : "echo \"Error: no test specified\" && exit 1"
     },
     "dependencies"   : {
@@ -52,17 +53,19 @@
         "yaml"             : "^2.3.2"
     },
     "devDependencies": {
-        "@types/fs-extra"    : "^11.0.1",
-        "@types/inquirer"    : "^8.2.6",
-        "@types/jsonwebtoken": "^8.5.9",
-        "@types/node"        : "^18.17.2",
-        "@types/openurl"     : "^1.0.1",
-        "@types/tar-stream"  : "^2.2.2",
-        "dotenv-vault"       : "^1.25.0",
-        "genversion"         : "^3.1.1",
-        "pkg"                : "^5.8.1",
-        "tiny-typed-emitter" : "^2.1.0",
-        "ts-node"            : "^10.9.1",
-        "typescript"         : "^5.1.6"
+        "@types/fs-extra"                 : "^11.0.1",
+        "@types/inquirer"                 : "^8.2.6",
+        "@types/jsonwebtoken"             : "^8.5.9",
+        "@types/node"                     : "^18.17.2",
+        "@types/openurl"                  : "^1.0.1",
+        "@types/tar-stream"               : "^2.2.2",
+        "@typescript-eslint/eslint-plugin": "^6.10.0",
+        "@typescript-eslint/parser"       : "^6.10.0",
+        "dotenv-vault"                    : "^1.25.0",
+        "genversion"                      : "^3.1.1",
+        "pkg"                             : "^5.8.1",
+        "tiny-typed-emitter"              : "^2.1.0",
+        "ts-node"                         : "^10.9.1",
+        "typescript"                      : "^5.1.6"
     }
 }
diff --git a/NodeApp/src/app.ts b/NodeApp/src/app.ts
index 236e2d79bff4df0a07333e01c129ca008994c0cc..be01e40ef06b23244940be8b6e228a38344a74d3 100644
--- a/NodeApp/src/app.ts
+++ b/NodeApp/src/app.ts
@@ -1,11 +1,15 @@
 // Read from the .env file
-// ATTENTION : This lines MUST be the first of this file (except for the path import)
-const path = require('node:path');
-const myEnv = require('dotenv').config({
-                                           path      : path.join(__dirname, '../.env'),
-                                           DOTENV_KEY: 'dotenv://:key_fc323d8e0a02349342f1c6a119bb38495958ce3a43a87d19a3f674b7e2896dcb@dotenv.local/vault/.env.vault?environment=development'
-                                       });
-require('dotenv-expand').expand(myEnv);
+// ATTENTION : These lines MUST be the first of this file (except for the path import)
+import path = require('node:path');
+import myEnv = require('dotenv');
+import dotenvExpand = require('dotenv-expand');
+
+
+dotenvExpand.expand(myEnv.config({
+                                     path      : path.join(__dirname, '../.env'),
+                                     DOTENV_KEY: 'dotenv://:key_fc323d8e0a02349342f1c6a119bb38495958ce3a43a87d19a3f674b7e2896dcb@dotenv.local/vault/.env.vault?environment=development'
+                                 }));
+
 require('./shared/helpers/TypeScriptExtensions'); // ATTENTION : This line MUST be the second of this file
 
 
@@ -15,4 +19,5 @@ import HttpManager  from './managers/HttpManager';
 
 HttpManager.registerAxiosInterceptor();
 
+
 new CommanderApp();
\ No newline at end of file
diff --git a/NodeApp/src/commander/CommanderCommand.ts b/NodeApp/src/commander/CommanderCommand.ts
index 7d2c2ccb1e9dd7be9ad3478f79664f08b848c4e7..b5fd5e7d363c8d9d8d16e6022b8529397685a4af 100644
--- a/NodeApp/src/commander/CommanderCommand.ts
+++ b/NodeApp/src/commander/CommanderCommand.ts
@@ -10,13 +10,13 @@ abstract class CommanderCommand {
 
         this.defineCommand();
         this.defineSubCommands();
-    };
+    }
 
     protected abstract defineCommand(): void;
 
     protected defineSubCommands() {}
 
-    protected abstract commandAction(...args: Array<any>): Promise<void>;
+    protected abstract commandAction(...args: Array<unknown>): Promise<void>;
 }
 
 
diff --git a/NodeApp/src/commander/assignment/AssignmentCommand.ts b/NodeApp/src/commander/assignment/AssignmentCommand.ts
index d78a64aa54d0920f49377a029e7de78806b338d1..70f09e2ff18e17774067e71a3d6e773dbf201f18 100644
--- a/NodeApp/src/commander/assignment/AssignmentCommand.ts
+++ b/NodeApp/src/commander/assignment/AssignmentCommand.ts
@@ -20,7 +20,7 @@ class AssignmentCommand extends CommanderCommand {
         AssignmentUnpublishCommand.registerOnCommand(this.command);
     }
 
-    protected async commandAction(options: any): Promise<void> { }
+    protected async commandAction(): Promise<void> { }
 }
 
 
diff --git a/NodeApp/src/commander/assignment/subcommands/AssignmentCheckCommand.ts b/NodeApp/src/commander/assignment/subcommands/AssignmentCheckCommand.ts
index d46efaa66632054313f3bf246b419c280841287e..718b7b97d11a74390d2de9e53753566f8f8565b1 100644
--- a/NodeApp/src/commander/assignment/subcommands/AssignmentCheckCommand.ts
+++ b/NodeApp/src/commander/assignment/subcommands/AssignmentCheckCommand.ts
@@ -1,16 +1,11 @@
 import CommanderCommand              from '../../CommanderCommand';
 import Config                        from '../../../config/Config';
 import ora                           from 'ora';
-import util                          from 'util';
-import { exec }                      from 'child_process';
 import chalk                         from 'chalk';
 import AssignmentValidator           from '../../../sharedByClients/helpers/Dojo/AssignmentValidator';
 import ClientsSharedAssignmentHelper from '../../../sharedByClients/helpers/Dojo/ClientsSharedAssignmentHelper';
 
 
-const execAsync = util.promisify(exec);
-
-
 class AssignmentCheckCommand extends CommanderCommand {
     protected commandName: string = 'check';
 
@@ -76,13 +71,13 @@ class AssignmentCheckCommand extends CommanderCommand {
                     }
                 });
 
-                assignmentValidator.events.on('finished', (success: boolean, exitCode: number) => {
+                assignmentValidator.events.on('finished', (success: boolean) => {
                     success ? resolve() : reject();
                 });
 
                 assignmentValidator.run(true);
             });
-        } catch ( error ) { }
+        } catch ( error ) { /* empty */ }
 
         ClientsSharedAssignmentHelper.displayExecutionResults(assignmentValidator, `The assignment is ready to be pushed.`, {
             INFO   : chalk.bold,
diff --git a/NodeApp/src/commander/assignment/subcommands/AssignmentCreateCommand.ts b/NodeApp/src/commander/assignment/subcommands/AssignmentCreateCommand.ts
index 7a5bea4403c7e963a948ccc04c945ee17e35fa4d..623f9b64116a5229814aa481de7087914ed7b82d 100644
--- a/NodeApp/src/commander/assignment/subcommands/AssignmentCreateCommand.ts
+++ b/NodeApp/src/commander/assignment/subcommands/AssignmentCreateCommand.ts
@@ -22,7 +22,7 @@ class AssignmentCreateCommand extends CommanderCommand {
         .action(this.commandAction.bind(this));
     }
 
-    protected async commandAction(options: any): Promise<void> {
+    protected async commandAction(options: { name: string, template?: string, members_id?: Array<number>, members_username?: Array<string> }): Promise<void> {
         let members!: Array<GitlabUser> | false;
         let templateIdOrNamespace: string | null = null;
 
diff --git a/NodeApp/src/commander/exercise/ExerciseCommand.ts b/NodeApp/src/commander/exercise/ExerciseCommand.ts
index bc122a864f7cc7fd9b32c00879b4427cdaae67e6..a475d4f91bf8d7a39bf74acc7c131cf32b7564f4 100644
--- a/NodeApp/src/commander/exercise/ExerciseCommand.ts
+++ b/NodeApp/src/commander/exercise/ExerciseCommand.ts
@@ -16,7 +16,7 @@ class ExerciseCommand extends CommanderCommand {
         ExerciseRunCommand.registerOnCommand(this.command);
     }
 
-    protected async commandAction(options: any): Promise<void> { }
+    protected async commandAction(): Promise<void> { }
 }
 
 
diff --git a/NodeApp/src/commander/exercise/subcommands/ExerciseCreateCommand.ts b/NodeApp/src/commander/exercise/subcommands/ExerciseCreateCommand.ts
index 5b547df82b9c26433806d861a5ae5f7da581a8c7..9660a3e753c67c3e2c590c39cef4adae763a3e9f 100644
--- a/NodeApp/src/commander/exercise/subcommands/ExerciseCreateCommand.ts
+++ b/NodeApp/src/commander/exercise/subcommands/ExerciseCreateCommand.ts
@@ -21,7 +21,7 @@ class ExerciseCreateCommand extends CommanderCommand {
         .action(this.commandAction.bind(this));
     }
 
-    protected async commandAction(options: any): Promise<void> {
+    protected async commandAction(options: { assignment: string, members_id?: Array<number>, members_username?: Array<string> }): Promise<void> {
         let members!: Array<GitlabUser> | false;
         let assignment!: Assignment | undefined;
 
diff --git a/NodeApp/src/commander/exercise/subcommands/ExerciseRunCommand.ts b/NodeApp/src/commander/exercise/subcommands/ExerciseRunCommand.ts
index e10f030ee540b0170c11113ad5c231566dc1c99f..cc139fe0a399909a51bee3a976d2d8debf2d5fce 100644
--- a/NodeApp/src/commander/exercise/subcommands/ExerciseRunCommand.ts
+++ b/NodeApp/src/commander/exercise/subcommands/ExerciseRunCommand.ts
@@ -188,13 +188,13 @@ class ExerciseRunCommand extends CommanderCommand {
                         }
                     });
 
-                    exerciseDockerCompose.events.on('finished', (success: boolean, exitCode: number) => {
+                    exerciseDockerCompose.events.on('finished', (success: boolean) => {
                         success ? resolve() : reject();
                     });
 
                     exerciseDockerCompose.run(true);
                 });
-            } catch ( error ) { }
+            } catch ( error ) { /* empty */ }
 
             fs.rmSync(composeOverridePath, { force: true });
             fs.writeFileSync(this.fileComposeLogs, exerciseDockerCompose.allLogs);
diff --git a/NodeApp/src/commander/session/SessionCommand.ts b/NodeApp/src/commander/session/SessionCommand.ts
index bbf0374ee9617ccc44e4463bd84554db2f8d4aa7..6dff026f2eae88717b4ca3bebe53f2db8025e749 100644
--- a/NodeApp/src/commander/session/SessionCommand.ts
+++ b/NodeApp/src/commander/session/SessionCommand.ts
@@ -18,7 +18,7 @@ class SessionCommand extends CommanderCommand {
         SessionTestCommand.registerOnCommand(this.command);
     }
 
-    protected async commandAction(options: any): Promise<void> { }
+    protected async commandAction(): Promise<void> { }
 }
 
 
diff --git a/NodeApp/src/commander/session/subcommands/SessionLoginCommand.ts b/NodeApp/src/commander/session/subcommands/SessionLoginCommand.ts
index 53610a2fab179d5577f373cce51f3633209464df..d9061e261f67f35104d1836d75cc78adea55dbc1 100644
--- a/NodeApp/src/commander/session/subcommands/SessionLoginCommand.ts
+++ b/NodeApp/src/commander/session/subcommands/SessionLoginCommand.ts
@@ -17,9 +17,7 @@ class SessionLoginCommand extends CommanderCommand {
         try {
             console.log(chalk.cyan('Please wait while we login you into Dojo...'));
             await SessionManager.login(options.cli);
-        } catch ( error ) {
-
-        }
+        } catch ( error ) { /* empty */ }
     }
 }
 
diff --git a/NodeApp/src/commander/session/subcommands/SessionLogoutCommand.ts b/NodeApp/src/commander/session/subcommands/SessionLogoutCommand.ts
index e0c7bb374c5138cd01ee3fd08db04d38e1e6472c..e71d882d4935b8b3f8cc1b4f248a2a3d9ae6ab33 100644
--- a/NodeApp/src/commander/session/subcommands/SessionLogoutCommand.ts
+++ b/NodeApp/src/commander/session/subcommands/SessionLogoutCommand.ts
@@ -14,7 +14,7 @@ class SessionLogoutCommand extends CommanderCommand {
         .action(this.commandAction.bind(this));
     }
 
-    protected async commandAction(options: any): Promise<void> {
+    protected async commandAction(options: { force: boolean }): Promise<void> {
         if ( !options.force ) {
             const confirm: boolean = (await inquirer.prompt({
                                                                 name   : 'confirm',
diff --git a/NodeApp/src/config/LocalConfigFile.ts b/NodeApp/src/config/LocalConfigFile.ts
index 33cabe255728f5c990ceab23a4143fb0271877ed..c69c89c71a67fc2ff100c28c6e8b38987c0686a2 100644
--- a/NodeApp/src/config/LocalConfigFile.ts
+++ b/NodeApp/src/config/LocalConfigFile.ts
@@ -10,7 +10,7 @@ class LocalConfigFile {
         return `${ Config.localConfig.folder }/${ this.filename }`;
     }
 
-    private _config: { [key: string]: any } = {};
+    private _config: { [key: string]: unknown } = {};
 
     loadConfig() {
         if ( !fs.existsSync(this.configPath) ) {
@@ -26,7 +26,7 @@ class LocalConfigFile {
         }
     }
 
-    getParam(key: string): any | null {
+    getParam(key: string): unknown | null {
         const value = key in this._config ? this._config[key] : null;
         if ( value === null ) {
             return null;
@@ -37,8 +37,8 @@ class LocalConfigFile {
         }
     }
 
-    setParam(key: string, value: any): void {
-        let previousValue = this.getParam(key);
+    setParam(key: string, value: unknown): void {
+        const previousValue = this.getParam(key);
         if ( JSON5.stringify(previousValue) === JSON5.stringify(value) ) {
             return;
         }
diff --git a/NodeApp/src/helpers/AccessesHelper.ts b/NodeApp/src/helpers/AccessesHelper.ts
index 0327ed2ddc644e485460ec3903df3d74219ba70b..e49e5819e59c74042fb5f23f79ace5587ae128c3 100644
--- a/NodeApp/src/helpers/AccessesHelper.ts
+++ b/NodeApp/src/helpers/AccessesHelper.ts
@@ -4,7 +4,7 @@ import GitlabManager  from '../managers/GitlabManager';
 
 class AccessesHelper {
     async checkStudent(): Promise<boolean> {
-        let sessionResult = await SessionManager.testSession(true, [ 'student' ]);
+        const sessionResult = await SessionManager.testSession(true, [ 'student' ]);
 
         if ( !sessionResult ) {
             return false;
@@ -14,7 +14,7 @@ class AccessesHelper {
     }
     
     async checkTeachingStaff(): Promise<boolean> {
-        let sessionResult = await SessionManager.testSession(true, [ 'teachingStaff' ]);
+        const sessionResult = await SessionManager.testSession(true, [ 'teachingStaff' ]);
 
         if ( !sessionResult || !sessionResult.teachingStaff ) {
             return false;
@@ -22,6 +22,6 @@ class AccessesHelper {
 
         return (await GitlabManager.testToken(true)).every(result => result);
     }
-};
+}
 
 export default new AccessesHelper();
\ No newline at end of file
diff --git a/NodeApp/src/managers/DojoBackendManager.ts b/NodeApp/src/managers/DojoBackendManager.ts
index 42bda3fa67ec31b4f9be6bba3e5da406c8f8224e..d3711009cf433867a339eb495161397d895a0fd4 100644
--- a/NodeApp/src/managers/DojoBackendManager.ts
+++ b/NodeApp/src/managers/DojoBackendManager.ts
@@ -107,7 +107,7 @@ class DojoBackendManager {
                         if ( error.response.status === StatusCodes.CONFLICT ) {
                             spinner.fail(`The assignment name is already used. Please choose another one.`);
                         } else {
-                            if ( (error.response.data as DojoBackendResponse<any>).code === DojoStatusCode.ASSIGNMENT_CREATION_GITLAB_ERROR ) {
+                            if ( (error.response.data as DojoBackendResponse<unknown>).code === DojoStatusCode.ASSIGNMENT_CREATION_GITLAB_ERROR ) {
                                 spinner.fail(`Assignment creation error: An unknown error occurred while creating the assignment on Gitlab. Please try again later or contact an administrator.`);
                             } else {
                                 spinner.fail(`Assignment creation error: An unknown error occurred while creating the assignment on Dojo server. Please try again later or contact an administrator.`);
@@ -145,7 +145,7 @@ class DojoBackendManager {
                         if ( error.response.status === StatusCodes.CONFLICT ) {
                             spinner.fail(`You've already reached the max number of exercise of this assignment.`);
                         } else {
-                            if ( (error.response.data as DojoBackendResponse<any>).code === DojoStatusCode.EXERCISE_CREATION_GITLAB_ERROR ) {
+                            if ( (error.response.data as DojoBackendResponse<unknown>).code === DojoStatusCode.EXERCISE_CREATION_GITLAB_ERROR ) {
                                 spinner.fail(`Exercise creation error: An unknown error occurred while creating the exercise on Gitlab. Please try again later or contact an administrator.`);
                             } else {
                                 spinner.fail(`Exercise creation error: An unknown error occurred while creating the exercise on Dojo server. Please try again later or contact an administrator.`);
diff --git a/NodeApp/src/managers/GitlabManager.ts b/NodeApp/src/managers/GitlabManager.ts
index 6562ad9980914e02cb7ef3b67b96cd85342e0748..67de5c9dad4cfe101e7c270410bd80448b9e727e 100644
--- a/NodeApp/src/managers/GitlabManager.ts
+++ b/NodeApp/src/managers/GitlabManager.ts
@@ -1,8 +1,9 @@
-import axios        from 'axios';
-import ora          from 'ora';
-import GitlabUser   from '../shared/types/Gitlab/GitlabUser';
-import GitlabRoute  from '../shared/types/Gitlab/GitlabRoute';
-import SharedConfig from '../shared/config/SharedConfig';
+import axios            from 'axios';
+import ora              from 'ora';
+import GitlabUser       from '../shared/types/Gitlab/GitlabUser';
+import GitlabRoute      from '../shared/types/Gitlab/GitlabRoute';
+import SharedConfig     from '../shared/config/SharedConfig';
+import GitlabRepository from '../shared/types/Gitlab/GitlabRepository';
 
 
 class GitlabManager {
@@ -15,7 +16,7 @@ class GitlabManager {
             ora('Checking Gitlab token: ').start().info();
         }
 
-        let result: [ boolean, boolean ] = [ false, false ];
+        const result: [ boolean, boolean ] = [ false, false ];
 
         type NotificationSettings = { level: string }
 
@@ -84,7 +85,7 @@ class GitlabManager {
         return axios.get(this.getApiUrl(GitlabRoute.NOTIFICATION_SETTINGS));
     }
 
-    public setNotificationSettings(newSettings: any) {
+    public setNotificationSettings(newSettings: Record<string, string>) {
         return axios.put(this.getApiUrl(GitlabRoute.NOTIFICATION_SETTINGS), { params: new URLSearchParams(newSettings) });
     }
 
@@ -98,7 +99,7 @@ class GitlabManager {
                 if ( verbose ) {
                     spinner.start();
                 }
-                const params: any = {};
+                const params: { [key: string]: unknown } = {};
                 params[paramName] = param;
                 const user = await axios.get<Array<GitlabUser>>(this.getApiUrl(GitlabRoute.USERS_GET), { params: params });
 
@@ -128,19 +129,19 @@ class GitlabManager {
         return await this.getGitlabUsers(usernames, 'search', verbose, verboseIndent);
     }
 
-    public async getRepository(repoId: number): Promise<any> {
+    public async getRepository(repoId: number): Promise<GitlabRepository> {
         return await axios.get(this.getApiUrl(GitlabRoute.REPOSITORY_GET).replace('{{id}}', repoId.toString()));
     }
 
-    public async fetchMembers(options: any): Promise<Array<GitlabUser> | false> {
+    public async fetchMembers(options: { members_id?: Array<number>, members_username?: Array<string> }): Promise<Array<GitlabUser> | false> {
         if ( options.members_id || options.members_username ) {
             ora('Checking Gitlab members:').start().info();
         }
 
         let members: Array<GitlabUser> = [];
 
-        async function getMembers<T>(context: any, functionName: string, paramsToSearch: Array<T>): Promise<boolean> {
-            const result = await (context[functionName] as (arg: Array<T>, verbose: boolean, verboseIndent: number) => Promise<Array<GitlabUser | undefined>>)(paramsToSearch, true, 8);
+        async function getMembers<T>(context: unknown, functionName: string, paramsToSearch: Array<T>): Promise<boolean> {
+            const result = await ((context as { [functionName: string]: (arg: Array<T>, verbose: boolean, verboseIndent: number) => Promise<Array<GitlabUser | undefined>> })[functionName])(paramsToSearch, true, 8);
 
             if ( result.every(user => user) ) {
                 members = members.concat(result as Array<GitlabUser>);
diff --git a/NodeApp/src/managers/HttpManager.ts b/NodeApp/src/managers/HttpManager.ts
index e90f666c4967739d857af9a604a39ca0e82fad34..a0f54387fe3c53b166aa9b8a14f8c44a0071edcd 100644
--- a/NodeApp/src/managers/HttpManager.ts
+++ b/NodeApp/src/managers/HttpManager.ts
@@ -1,14 +1,14 @@
-import axios, { AxiosRequestHeaders } from 'axios';
-import SessionManager                 from './SessionManager';
-import FormData                       from 'form-data';
-import { StatusCodes }                from 'http-status-codes';
-import ClientsSharedConfig            from '../sharedByClients/config/ClientsSharedConfig';
-import { version }                    from '../config/Version';
-import DojoBackendResponse            from '../shared/types/Dojo/DojoBackendResponse';
-import DojoStatusCode                 from '../shared/types/Dojo/DojoStatusCode';
-import boxen                          from 'boxen';
-import Config                         from '../config/Config';
-import SharedConfig                   from '../shared/config/SharedConfig';
+import axios, { AxiosError, AxiosRequestHeaders } from 'axios';
+import SessionManager                             from './SessionManager';
+import FormData                                   from 'form-data';
+import { StatusCodes }                            from 'http-status-codes';
+import ClientsSharedConfig                        from '../sharedByClients/config/ClientsSharedConfig';
+import { version }                                from '../config/Version';
+import DojoBackendResponse                        from '../shared/types/Dojo/DojoBackendResponse';
+import DojoStatusCode                             from '../shared/types/Dojo/DojoStatusCode';
+import boxen                                      from 'boxen';
+import Config                                     from '../config/Config';
+import SharedConfig                               from '../shared/config/SharedConfig';
 
 
 class HttpManager {
@@ -84,17 +84,19 @@ class HttpManager {
                         await SessionManager.refreshTokens();
 
                         return axios(originalConfig);
-                    } catch ( _error: any ) {
-                        if ( _error.response && _error.response.data ) {
-                            return Promise.reject(_error.response.data);
+                    } catch ( error: unknown ) {
+                        if ( error instanceof AxiosError ) {
+                            if ( error.response && error.response.data ) {
+                                return Promise.reject(error.response.data);
+                            }
                         }
 
-                        return Promise.reject(_error);
+                        return Promise.reject(error);
                     }
                 }
 
                 if ( error.response.status === StatusCodes.METHOD_NOT_ALLOWED && isFromApi && error.response.data ) {
-                    const data: DojoBackendResponse<{}> = error.response.data;
+                    const data: DojoBackendResponse<void> = error.response.data;
 
                     switch ( data.code ) {
                         case DojoStatusCode.CLIENT_NOT_SUPPORTED:
diff --git a/NodeApp/src/managers/SessionManager.ts b/NodeApp/src/managers/SessionManager.ts
index 580b6d854da7fa201243682ee8cd126aff84e8af..9bbd640f523b04e530b5fcaadf591ee2b208e6e0 100644
--- a/NodeApp/src/managers/SessionManager.ts
+++ b/NodeApp/src/managers/SessionManager.ts
@@ -36,7 +36,7 @@ class LoginServer {
             };
 
             if ( req.url?.match(Config.login.server.route) ) {
-                let urlParts = req.url.split('=');
+                const urlParts = req.url.split('=');
                 if ( urlParts.length > 0 ) {
                     this.events.emit('code', urlParts[1]);
 
@@ -84,7 +84,7 @@ class SessionManager {
     }
 
     get apiToken(): string {
-        const apisToken = this.configFile.getParam(LocalConfigKeys.APIS_TOKEN);
+        const apisToken = this.configFile.getParam(LocalConfigKeys.APIS_TOKEN) as null | { [key: string]: string };
 
         if ( apisToken !== null && ClientsSharedConfig.apiURL in apisToken ) {
             return apisToken[ClientsSharedConfig.apiURL];
@@ -94,7 +94,7 @@ class SessionManager {
     }
 
     set apiToken(token: string) {
-        let apisToken = this.configFile.getParam(LocalConfigKeys.APIS_TOKEN);
+        let apisToken = this.configFile.getParam(LocalConfigKeys.APIS_TOKEN) as null | { [key: string]: string };
         if ( apisToken === null ) {
             apisToken = {};
         }
@@ -113,7 +113,7 @@ class SessionManager {
     }
 
     get gitlabCredentials(): DojoGitlabCredentials {
-        return this.configFile.getParam(LocalConfigKeys.GITLAB);
+        return this.configFile.getParam(LocalConfigKeys.GITLAB) as DojoGitlabCredentials;
     }
 
     set gitlabCredentials(credentials: DojoGitlabCredentials) {
@@ -216,10 +216,10 @@ class SessionManager {
             gitlabCode = await this.getGitlabCodeFromHeadlessEnvironment();
         }
 
-        let gitlabTokensSpinner = ora({
-                                          text  : 'Retrieving gitlab tokens',
-                                          indent: 4
-                                      }).start();
+        const gitlabTokensSpinner = ora({
+                                            text  : 'Retrieving gitlab tokens',
+                                            indent: 4
+                                        }).start();
         let gitlabTokens: GitlabToken;
         try {
             gitlabTokens = await SharedGitlabManager.getTokens(gitlabCode);
@@ -239,10 +239,10 @@ class SessionManager {
         }
 
         ora(`Login to Dojo backend:`).start().info();
-        let dojoLoginSpinner = ora({
-                                       text  : 'Login to Dojo backend',
-                                       indent: 4
-                                   }).start();
+        const dojoLoginSpinner = ora({
+                                         text  : 'Login to Dojo backend',
+                                         indent: 4
+                                     }).start();
 
         try {
             await DojoBackendManager.login(gitlabTokens);
@@ -256,7 +256,7 @@ class SessionManager {
     }
 
     async refreshTokens() {
-        let gitlabTokens = await DojoBackendManager.refreshTokens(this.gitlabCredentials.refreshToken!);
+        const gitlabTokens = await DojoBackendManager.refreshTokens(this.gitlabCredentials.refreshToken!);
 
         this.gitlabCredentials = {
             refreshToken: gitlabTokens.refresh_token,
@@ -274,7 +274,7 @@ class SessionManager {
 
     checkPermissions(verbose: boolean = true, indent: number = 8, checkPermissions: Array<string> | null = []): Permissions {
         const hasPermission = (permissionPredicate: () => boolean, verboseText: string): boolean => {
-            let isAllowed: boolean = this.profile !== undefined && permissionPredicate();
+            const isAllowed: boolean = this.profile !== undefined && permissionPredicate();
 
             if ( verbose ) {
                 const spinner: ora.Ora = ora({
diff --git a/NodeApp/src/shared b/NodeApp/src/shared
index 4a5eb68209ae9204b6d4cc8020bd62cf6a5be989..101cc26895eb0b5fe97e03bb96039e0cddd94391 160000
--- a/NodeApp/src/shared
+++ b/NodeApp/src/shared
@@ -1 +1 @@
-Subproject commit 4a5eb68209ae9204b6d4cc8020bd62cf6a5be989
+Subproject commit 101cc26895eb0b5fe97e03bb96039e0cddd94391