From bdb5148e0bcc40eec22a447b0077af5dbf77c379 Mon Sep 17 00:00:00 2001 From: SebClem Date: Thu, 11 Jul 2024 15:47:27 +0200 Subject: [PATCH] Eslint --- nextcloud_backup/backend/.eslintrc.cjs | 6 - nextcloud_backup/backend/eslint.config.js | 20 + nextcloud_backup/backend/package.json | 14 +- nextcloud_backup/backend/pnpm-lock.yaml | 497 +++++++++++------- nextcloud_backup/backend/src/app.ts | 35 +- nextcloud_backup/backend/src/postInit.ts | 11 +- nextcloud_backup/backend/src/routes/action.ts | 2 +- nextcloud_backup/backend/src/routes/config.ts | 35 +- .../backend/src/routes/homeAssistant.ts | 14 +- nextcloud_backup/backend/src/routes/webdav.ts | 60 ++- nextcloud_backup/backend/src/server.ts | 24 +- .../src/services/backupConfigService.ts | 4 +- .../src/services/homeAssistantService.ts | 73 ++- .../backend/src/services/orchestrator.ts | 40 +- .../src/services/webdavConfigService.ts | 10 +- .../backend/src/services/webdavService.ts | 41 +- .../backend/src/tools/settingsTools.ts | 213 -------- nextcloud_backup/backend/src/tools/status.ts | 3 +- .../types/services/webdavConfigValidation.ts | 23 +- 19 files changed, 522 insertions(+), 603 deletions(-) delete mode 100644 nextcloud_backup/backend/.eslintrc.cjs create mode 100644 nextcloud_backup/backend/eslint.config.js delete mode 100644 nextcloud_backup/backend/src/tools/settingsTools.ts diff --git a/nextcloud_backup/backend/.eslintrc.cjs b/nextcloud_backup/backend/.eslintrc.cjs deleted file mode 100644 index b38e9f2..0000000 --- a/nextcloud_backup/backend/.eslintrc.cjs +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = { - extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended'], - parser: '@typescript-eslint/parser', - plugins: ['@typescript-eslint'], - root: true, - }; diff --git a/nextcloud_backup/backend/eslint.config.js b/nextcloud_backup/backend/eslint.config.js new file mode 100644 index 0000000..d67dc6e --- /dev/null +++ b/nextcloud_backup/backend/eslint.config.js @@ -0,0 +1,20 @@ +// @ts-check + +import eslint from '@eslint/js'; +import tseslint from 'typescript-eslint'; + +export default tseslint.config( + eslint.configs.recommended, + ...tseslint.configs.recommendedTypeChecked, + { + languageOptions: { + parserOptions: { + project: true, + tsconfigRootDir: import.meta.dirname, + } + } + }, + { + ignores: ["dist/", "eslint.config.js"] + } +); \ No newline at end of file diff --git a/nextcloud_backup/backend/package.json b/nextcloud_backup/backend/package.json index 87b5272..e696def 100644 --- a/nextcloud_backup/backend/package.json +++ b/nextcloud_backup/backend/package.json @@ -7,12 +7,11 @@ "build:watch": "tsc -w", "build": "tsc --build --verbose", "dev": "pnpm build && concurrently -n tsc,node \"pnpm build:watch\" \"pnpm serve:watch\"", - "lint": "tsc --noEmit && eslint \"**/*.{js,ts}\" --quiet --fix", + "lint": "tsc --noEmit && eslint --quiet --fix", "serve:watch": "nodemon dist/server.js", "serve": "node dist/server.js" }, "dependencies": { - "@typescript-eslint/eslint-plugin": "^7.0.1", "app-root-path": "3.1.0", "cookie-parser": "1.4.6", "cors": "^2.8.5", @@ -35,23 +34,24 @@ }, "packageManager": "pnpm@8.15.3", "devDependencies": { + "@eslint/js": "^9.6.0", "@tsconfig/recommended": "^1.0.3", "@types/cookie-parser": "^1.4.6", "@types/cors": "^2.8.17", - "@types/cron": "^2.4.0", "@types/errorhandler": "^1.5.3", + "@types/eslint__js": "^8.42.3", "@types/express": "^4.17.21", "@types/figlet": "^1.5.8", "@types/http-errors": "^2.0.4", "@types/luxon": "^3.4.2", "@types/morgan": "^1.9.9", "@types/node": "^20.11.19", - "@typescript-eslint/parser": "^7.0.1", "concurrently": "8.2.2", "dotenv": "^16.4.4", - "eslint": "8.56.0", + "eslint": "^9.6.0", "nodemon": "^3.0.3", "ts-node": "^10.9.2", - "typescript": "^5.3.3" + "typescript": "^5.3.3", + "typescript-eslint": "8.0.0-alpha.41" } -} +} \ No newline at end of file diff --git a/nextcloud_backup/backend/pnpm-lock.yaml b/nextcloud_backup/backend/pnpm-lock.yaml index 99cc8c4..4aadaaa 100644 --- a/nextcloud_backup/backend/pnpm-lock.yaml +++ b/nextcloud_backup/backend/pnpm-lock.yaml @@ -5,9 +5,6 @@ settings: excludeLinksFromLockfile: false dependencies: - '@typescript-eslint/eslint-plugin': - specifier: ^7.0.1 - version: 7.0.1(@typescript-eslint/parser@7.0.1)(eslint@8.56.0)(typescript@5.3.3) app-root-path: specifier: 3.1.0 version: 3.1.0 @@ -67,6 +64,9 @@ dependencies: version: 3.11.0 devDependencies: + '@eslint/js': + specifier: ^9.6.0 + version: 9.6.0 '@tsconfig/recommended': specifier: ^1.0.3 version: 1.0.3 @@ -76,12 +76,12 @@ devDependencies: '@types/cors': specifier: ^2.8.17 version: 2.8.17 - '@types/cron': - specifier: ^2.4.0 - version: 2.4.0 '@types/errorhandler': specifier: ^1.5.3 version: 1.5.3 + '@types/eslint__js': + specifier: ^8.42.3 + version: 8.42.3 '@types/express': specifier: ^4.17.21 version: 4.17.21 @@ -100,9 +100,6 @@ devDependencies: '@types/node': specifier: ^20.11.19 version: 20.11.19 - '@typescript-eslint/parser': - specifier: ^7.0.1 - version: 7.0.1(eslint@8.56.0)(typescript@5.3.3) concurrently: specifier: 8.2.2 version: 8.2.2 @@ -110,8 +107,8 @@ devDependencies: specifier: ^16.4.4 version: 16.4.4 eslint: - specifier: 8.56.0 - version: 8.56.0 + specifier: ^9.6.0 + version: 9.6.0 nodemon: specifier: ^3.0.3 version: 3.0.3 @@ -121,12 +118,16 @@ devDependencies: typescript: specifier: ^5.3.3 version: 5.3.3 + typescript-eslint: + specifier: 8.0.0-alpha.41 + version: 8.0.0-alpha.41(eslint@9.6.0)(typescript@5.3.3) packages: /@aashutoshrathi/word-wrap@1.2.6: resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} engines: {node: '>=0.10.0'} + dev: true /@babel/runtime@7.23.9: resolution: {integrity: sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==} @@ -161,27 +162,40 @@ packages: kuler: 2.0.0 dev: false - /@eslint-community/eslint-utils@4.4.0(eslint@8.56.0): + /@eslint-community/eslint-utils@4.4.0(eslint@9.6.0): resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 dependencies: - eslint: 8.56.0 + eslint: 9.6.0 eslint-visitor-keys: 3.4.3 + dev: true /@eslint-community/regexpp@4.10.0: resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + dev: true - /@eslint/eslintrc@2.1.4: - resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + /@eslint/config-array@0.17.0: + resolution: {integrity: sha512-A68TBu6/1mHHuc5YJL0U0VVeGNiklLAL6rRmhTCP2B5XjWLMnrX+HkO+IAXyHvks5cyyY1jjK5ITPQ1HGS2EVA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + dependencies: + '@eslint/object-schema': 2.1.4 + debug: 4.3.4(supports-color@5.5.0) + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@eslint/eslintrc@3.1.0: + resolution: {integrity: sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} dependencies: ajv: 6.12.6 debug: 4.3.4(supports-color@5.5.0) - espree: 9.6.1 - globals: 13.24.0 + espree: 10.1.0 + globals: 14.0.0 ignore: 5.3.1 import-fresh: 3.3.0 js-yaml: 4.1.0 @@ -189,10 +203,17 @@ packages: strip-json-comments: 3.1.1 transitivePeerDependencies: - supports-color + dev: true - /@eslint/js@8.56.0: - resolution: {integrity: sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + /@eslint/js@9.6.0: + resolution: {integrity: sha512-D9B0/3vNg44ZeWbYMpBoXqNP4j6eQD5vNwIlGAuFRRzK/WtT/jvDQW3Bi9kkf3PMDMlM7Yi+73VLUsn5bJcl8A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + dev: true + + /@eslint/object-schema@2.1.4: + resolution: {integrity: sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + dev: true /@hapi/hoek@9.3.0: resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==} @@ -204,22 +225,15 @@ packages: '@hapi/hoek': 9.3.0 dev: false - /@humanwhocodes/config-array@0.11.14: - resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} - engines: {node: '>=10.10.0'} - dependencies: - '@humanwhocodes/object-schema': 2.0.2 - debug: 4.3.4(supports-color@5.5.0) - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color - /@humanwhocodes/module-importer@1.0.1: resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} engines: {node: '>=12.22'} + dev: true - /@humanwhocodes/object-schema@2.0.2: - resolution: {integrity: sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==} + /@humanwhocodes/retry@0.3.0: + resolution: {integrity: sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==} + engines: {node: '>=18.18'} + dev: true /@jridgewell/resolve-uri@3.1.2: resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} @@ -243,10 +257,12 @@ packages: dependencies: '@nodelib/fs.stat': 2.0.5 run-parallel: 1.2.0 + dev: true /@nodelib/fs.stat@2.0.5: resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} engines: {node: '>= 8'} + dev: true /@nodelib/fs.walk@1.2.8: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} @@ -254,6 +270,7 @@ packages: dependencies: '@nodelib/fs.scandir': 2.1.5 fastq: 1.17.1 + dev: true /@sideway/address@4.1.5: resolution: {integrity: sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==} @@ -326,19 +343,29 @@ packages: '@types/node': 20.11.19 dev: true - /@types/cron@2.4.0: - resolution: {integrity: sha512-5bBaAkqvSFBX8JMi/xCofNzG5E594TNsApMz68dLd/sQYz/HGQqgcxGHTRjOvD4G3Y+YF1Oo3S7QdCvKt1KAJQ==} - deprecated: This is a stub types definition. cron provides its own type definitions, so you do not need this installed. - dependencies: - cron: 3.1.6 - dev: true - /@types/errorhandler@1.5.3: resolution: {integrity: sha512-YPTrIcgs84Tuz+IcVq0WQKI44J9Ox1/BP/kVWkN7hRCib0F2zAHBfP9SMWmE74sIca4xUbzoAalxSsj6BlVAkQ==} dependencies: '@types/express': 4.17.21 dev: true + /@types/eslint@8.56.10: + resolution: {integrity: sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==} + dependencies: + '@types/estree': 1.0.5 + '@types/json-schema': 7.0.15 + dev: true + + /@types/eslint__js@8.42.3: + resolution: {integrity: sha512-alfG737uhmPdnvkrLdZLcEKJ/B8s9Y4hrZ+YAdzUeoArBlSUERA2E87ROfOaS4jd/C45fzOoZzidLc1IPwLqOw==} + dependencies: + '@types/eslint': 8.56.10 + dev: true + + /@types/estree@1.0.5: + resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + dev: true + /@types/express-serve-static-core@4.17.43: resolution: {integrity: sha512-oaYtiBirUOPQGSWNGPWnzyAFJ0BP3cwvN4oWZQY+zUBwpVIGsKUkpBpSztp74drYcjavs7SKFZ4DX1V2QeN8rg==} dependencies: @@ -371,10 +398,11 @@ packages: /@types/json-schema@7.0.15: resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - dev: false + dev: true /@types/luxon@3.3.8: resolution: {integrity: sha512-jYvz8UMLDgy3a5SkGJne8H7VA7zPV2Lwohjx0V8V31+SqAjNmurWMkk9cQhfvlcnXWudBpK9xPM1n4rljOcHYQ==} + dev: false /@types/luxon@3.4.2: resolution: {integrity: sha512-TifLZlFudklWlMBfhubvgqTXRzLDI5pCbGa4P8a3wPyUQSW+1xQ5eDsreP9DWHX3tjq1ke96uYG/nwundroWcA==} @@ -408,10 +436,6 @@ packages: resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} dev: true - /@types/semver@7.5.7: - resolution: {integrity: sha512-/wdoPq1QqkSj9/QOeKkFquEuPzQbHTWAMPH/PaUMB+JuR31lXhlWXRZ52IpfDYVlDOUBvX09uBrPwxGT1hjNBg==} - dev: false - /@types/send@0.17.4: resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==} dependencies: @@ -431,135 +455,131 @@ packages: resolution: {integrity: sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==} dev: false - /@typescript-eslint/eslint-plugin@7.0.1(@typescript-eslint/parser@7.0.1)(eslint@8.56.0)(typescript@5.3.3): - resolution: {integrity: sha512-OLvgeBv3vXlnnJGIAgCLYKjgMEU+wBGj07MQ/nxAaON+3mLzX7mJbhRYrVGiVvFiXtwFlkcBa/TtmglHy0UbzQ==} - engines: {node: ^16.0.0 || >=18.0.0} + /@typescript-eslint/eslint-plugin@8.0.0-alpha.41(@typescript-eslint/parser@8.0.0-alpha.41)(eslint@9.6.0)(typescript@5.3.3): + resolution: {integrity: sha512-WePtbzWMaQO4qtGAXp3zzEN8yYZCEuAHVCERCUXgoSUTQ80F5UB7T5lYyA9ySpFDB7rqJ2ev98DtnbS4U3Ms+w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^7.0.0 - eslint: ^8.56.0 + '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 + eslint: ^8.57.0 || ^9.0.0 typescript: '*' peerDependenciesMeta: typescript: optional: true dependencies: '@eslint-community/regexpp': 4.10.0 - '@typescript-eslint/parser': 7.0.1(eslint@8.56.0)(typescript@5.3.3) - '@typescript-eslint/scope-manager': 7.0.1 - '@typescript-eslint/type-utils': 7.0.1(eslint@8.56.0)(typescript@5.3.3) - '@typescript-eslint/utils': 7.0.1(eslint@8.56.0)(typescript@5.3.3) - '@typescript-eslint/visitor-keys': 7.0.1 - debug: 4.3.4(supports-color@5.5.0) - eslint: 8.56.0 + '@typescript-eslint/parser': 8.0.0-alpha.41(eslint@9.6.0)(typescript@5.3.3) + '@typescript-eslint/scope-manager': 8.0.0-alpha.41 + '@typescript-eslint/type-utils': 8.0.0-alpha.41(eslint@9.6.0)(typescript@5.3.3) + '@typescript-eslint/utils': 8.0.0-alpha.41(eslint@9.6.0)(typescript@5.3.3) + '@typescript-eslint/visitor-keys': 8.0.0-alpha.41 + eslint: 9.6.0 graphemer: 1.4.0 ignore: 5.3.1 natural-compare: 1.4.0 - semver: 7.6.0 - ts-api-utils: 1.2.1(typescript@5.3.3) + ts-api-utils: 1.3.0(typescript@5.3.3) typescript: 5.3.3 transitivePeerDependencies: - supports-color - dev: false + dev: true - /@typescript-eslint/parser@7.0.1(eslint@8.56.0)(typescript@5.3.3): - resolution: {integrity: sha512-8GcRRZNzaHxKzBPU3tKtFNing571/GwPBeCvmAUw0yBtfE2XVd0zFKJIMSWkHJcPQi0ekxjIts6L/rrZq5cxGQ==} - engines: {node: ^16.0.0 || >=18.0.0} + /@typescript-eslint/parser@8.0.0-alpha.41(eslint@9.6.0)(typescript@5.3.3): + resolution: {integrity: sha512-7HMXwy/q/59ZASBXz2FtdIsR7LgABrR8j2dTKq9GMR8OkjjdO4klxWSY/uOBozVt4UxlMRYsBdBDhEq4/tHRiw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: ^8.56.0 + eslint: ^8.57.0 || ^9.0.0 typescript: '*' peerDependenciesMeta: typescript: optional: true dependencies: - '@typescript-eslint/scope-manager': 7.0.1 - '@typescript-eslint/types': 7.0.1 - '@typescript-eslint/typescript-estree': 7.0.1(typescript@5.3.3) - '@typescript-eslint/visitor-keys': 7.0.1 + '@typescript-eslint/scope-manager': 8.0.0-alpha.41 + '@typescript-eslint/types': 8.0.0-alpha.41 + '@typescript-eslint/typescript-estree': 8.0.0-alpha.41(typescript@5.3.3) + '@typescript-eslint/visitor-keys': 8.0.0-alpha.41 debug: 4.3.4(supports-color@5.5.0) - eslint: 8.56.0 + eslint: 9.6.0 typescript: 5.3.3 transitivePeerDependencies: - supports-color + dev: true - /@typescript-eslint/scope-manager@7.0.1: - resolution: {integrity: sha512-v7/T7As10g3bcWOOPAcbnMDuvctHzCFYCG/8R4bK4iYzdFqsZTbXGln0cZNVcwQcwewsYU2BJLay8j0/4zOk4w==} - engines: {node: ^16.0.0 || >=18.0.0} + /@typescript-eslint/scope-manager@8.0.0-alpha.41: + resolution: {integrity: sha512-iNxuQ0TMVfFiMJ2al4bGd/mY9+aLtBxnHfo7B2xoVzR6cRFgUdBLlMa//MSIjSmVRpCEqNLQnkxpJb96tFG+xw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} dependencies: - '@typescript-eslint/types': 7.0.1 - '@typescript-eslint/visitor-keys': 7.0.1 + '@typescript-eslint/types': 8.0.0-alpha.41 + '@typescript-eslint/visitor-keys': 8.0.0-alpha.41 + dev: true - /@typescript-eslint/type-utils@7.0.1(eslint@8.56.0)(typescript@5.3.3): - resolution: {integrity: sha512-YtT9UcstTG5Yqy4xtLiClm1ZpM/pWVGFnkAa90UfdkkZsR1eP2mR/1jbHeYp8Ay1l1JHPyGvoUYR6o3On5Nhmw==} - engines: {node: ^16.0.0 || >=18.0.0} + /@typescript-eslint/type-utils@8.0.0-alpha.41(eslint@9.6.0)(typescript@5.3.3): + resolution: {integrity: sha512-+QIA1z/jrox6bbvqlyqBQjotpevieLTycfiuoKuqGcKoskFZV5Rma51BV8LCJacnOafwJtSi+7b8zDo8OsXUvA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: ^8.56.0 typescript: '*' peerDependenciesMeta: typescript: optional: true dependencies: - '@typescript-eslint/typescript-estree': 7.0.1(typescript@5.3.3) - '@typescript-eslint/utils': 7.0.1(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/typescript-estree': 8.0.0-alpha.41(typescript@5.3.3) + '@typescript-eslint/utils': 8.0.0-alpha.41(eslint@9.6.0)(typescript@5.3.3) debug: 4.3.4(supports-color@5.5.0) - eslint: 8.56.0 - ts-api-utils: 1.2.1(typescript@5.3.3) + ts-api-utils: 1.3.0(typescript@5.3.3) typescript: 5.3.3 transitivePeerDependencies: + - eslint - supports-color - dev: false + dev: true - /@typescript-eslint/types@7.0.1: - resolution: {integrity: sha512-uJDfmirz4FHib6ENju/7cz9SdMSkeVvJDK3VcMFvf/hAShg8C74FW+06MaQPODHfDJp/z/zHfgawIJRjlu0RLg==} - engines: {node: ^16.0.0 || >=18.0.0} + /@typescript-eslint/types@8.0.0-alpha.41: + resolution: {integrity: sha512-n0P2FP3YC3pD3yoiCf4lHqbUP45xlnOk8HkjB+LtKSUZZWLLJ8k1ZXZtQj7MEX22tytCMj//Bmq403xFuCwfIg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + dev: true - /@typescript-eslint/typescript-estree@7.0.1(typescript@5.3.3): - resolution: {integrity: sha512-SO9wHb6ph0/FN5OJxH4MiPscGah5wjOd0RRpaLvuBv9g8565Fgu0uMySFEPqwPHiQU90yzJ2FjRYKGrAhS1xig==} - engines: {node: ^16.0.0 || >=18.0.0} + /@typescript-eslint/typescript-estree@8.0.0-alpha.41(typescript@5.3.3): + resolution: {integrity: sha512-adCr+vbLYTFhwhIwjIjjMxTdUYiPA2Jlyuhnbj092IzgLHtT79bvuwcgPWeTyLbFb/13SMKmOEka00xHiqLpig==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '*' peerDependenciesMeta: typescript: optional: true dependencies: - '@typescript-eslint/types': 7.0.1 - '@typescript-eslint/visitor-keys': 7.0.1 + '@typescript-eslint/types': 8.0.0-alpha.41 + '@typescript-eslint/visitor-keys': 8.0.0-alpha.41 debug: 4.3.4(supports-color@5.5.0) globby: 11.1.0 is-glob: 4.0.3 - minimatch: 9.0.3 + minimatch: 9.0.5 semver: 7.6.0 - ts-api-utils: 1.2.1(typescript@5.3.3) + ts-api-utils: 1.3.0(typescript@5.3.3) typescript: 5.3.3 transitivePeerDependencies: - supports-color + dev: true - /@typescript-eslint/utils@7.0.1(eslint@8.56.0)(typescript@5.3.3): - resolution: {integrity: sha512-oe4his30JgPbnv+9Vef1h48jm0S6ft4mNwi9wj7bX10joGn07QRfqIqFHoMiajrtoU88cIhXf8ahwgrcbNLgPA==} - engines: {node: ^16.0.0 || >=18.0.0} + /@typescript-eslint/utils@8.0.0-alpha.41(eslint@9.6.0)(typescript@5.3.3): + resolution: {integrity: sha512-DTxc9VdERS6iloiw1P5tgRDqRArmp/sIuvgdHBvGh2SiltEFc3VjLGnHHGSTr6GfH7tjFWvcCnCtxx+pjWfp5Q==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: ^8.56.0 + eslint: ^8.57.0 || ^9.0.0 dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.56.0) - '@types/json-schema': 7.0.15 - '@types/semver': 7.5.7 - '@typescript-eslint/scope-manager': 7.0.1 - '@typescript-eslint/types': 7.0.1 - '@typescript-eslint/typescript-estree': 7.0.1(typescript@5.3.3) - eslint: 8.56.0 - semver: 7.6.0 + '@eslint-community/eslint-utils': 4.4.0(eslint@9.6.0) + '@typescript-eslint/scope-manager': 8.0.0-alpha.41 + '@typescript-eslint/types': 8.0.0-alpha.41 + '@typescript-eslint/typescript-estree': 8.0.0-alpha.41(typescript@5.3.3) + eslint: 9.6.0 transitivePeerDependencies: - supports-color - typescript - dev: false + dev: true - /@typescript-eslint/visitor-keys@7.0.1: - resolution: {integrity: sha512-hwAgrOyk++RTXrP4KzCg7zB2U0xt7RUU0ZdMSCsqF3eKUwkdXUMyTb0qdCuji7VIbcpG62kKTU9M1J1c9UpFBw==} - engines: {node: ^16.0.0 || >=18.0.0} + /@typescript-eslint/visitor-keys@8.0.0-alpha.41: + resolution: {integrity: sha512-uetCAUBVC+YarBdZnWzDDgX11PpAEGV8Cw31I3d1xNrhx6/bJGThKX+holEmd3amMdnr4w/XUKH/4YuQOgtjDA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} dependencies: - '@typescript-eslint/types': 7.0.1 + '@typescript-eslint/types': 8.0.0-alpha.41 eslint-visitor-keys: 3.4.3 - - /@ungap/structured-clone@1.2.0: - resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} + dev: true /abbrev@1.1.1: resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} @@ -573,12 +593,13 @@ packages: negotiator: 0.6.3 dev: false - /acorn-jsx@5.3.2(acorn@8.11.3): + /acorn-jsx@5.3.2(acorn@8.12.1): resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 dependencies: - acorn: 8.11.3 + acorn: 8.12.1 + dev: true /acorn-walk@8.3.2: resolution: {integrity: sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==} @@ -589,6 +610,13 @@ packages: resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} engines: {node: '>=0.4.0'} hasBin: true + dev: true + + /acorn@8.12.1: + resolution: {integrity: sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: true /ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} @@ -597,16 +625,19 @@ packages: fast-json-stable-stringify: 2.1.0 json-schema-traverse: 0.4.1 uri-js: 4.4.1 + dev: true /ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} + dev: true /ansi-styles@4.3.0: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} dependencies: color-convert: 2.0.1 + dev: true /anymatch@3.1.3: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} @@ -627,6 +658,7 @@ packages: /argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + dev: true /array-flatten@1.1.1: resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} @@ -635,6 +667,7 @@ packages: /array-union@2.1.0: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} + dev: true /async@3.2.5: resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==} @@ -688,6 +721,7 @@ packages: dependencies: balanced-match: 1.0.2 concat-map: 0.0.1 + dev: true /brace-expansion@2.0.1: resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} @@ -699,6 +733,7 @@ packages: engines: {node: '>=8'} dependencies: fill-range: 7.0.1 + dev: true /byte-length@1.0.2: resolution: {integrity: sha512-ovBpjmsgd/teRmgcPh23d4gJvxDoXtAzEL9xTfMU8Yc2kqCDb7L9jAG0XHl1nzuGl+h3ebCIF1i62UFyA9V/2Q==} @@ -741,6 +776,7 @@ packages: /callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} + dev: true /chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} @@ -748,6 +784,7 @@ packages: dependencies: ansi-styles: 4.3.0 supports-color: 7.2.0 + dev: true /charenc@0.0.2: resolution: {integrity: sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==} @@ -788,6 +825,7 @@ packages: engines: {node: '>=7.0.0'} dependencies: color-name: 1.1.4 + dev: true /color-name@1.1.3: resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} @@ -826,6 +864,7 @@ packages: /concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + dev: true /concurrently@8.2.2: resolution: {integrity: sha512-1dP4gpXFhei8IOtlXRE/T/4H88ElHgTiUzh71YUmtjTEHMSRS2Z/fgOxHSxxusGHogsRfxNq1vyAwxSC+EVyDg==} @@ -894,6 +933,7 @@ packages: dependencies: '@types/luxon': 3.3.8 luxon: 3.4.4 + dev: false /cross-spawn@7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} @@ -902,6 +942,7 @@ packages: path-key: 3.1.1 shebang-command: 2.0.0 which: 2.0.2 + dev: true /crypt@0.0.2: resolution: {integrity: sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==} @@ -953,6 +994,7 @@ packages: /deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + dev: true /defer-to-connect@2.0.1: resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==} @@ -993,12 +1035,7 @@ packages: engines: {node: '>=8'} dependencies: path-type: 4.0.0 - - /doctrine@3.0.0: - resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} - engines: {node: '>=6.0.0'} - dependencies: - esutils: 2.0.3 + dev: true /dotenv@16.4.4: resolution: {integrity: sha512-XvPXc8XAQThSjAbY6cQ/9PcBXmFoWuw1sQ3b8HqUCR6ziGXjkTi//kB9SWa2UwqlgdAIuRqAa/9hVljzPehbYg==} @@ -1054,53 +1091,57 @@ packages: /escape-string-regexp@4.0.0: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} + dev: true - /eslint-scope@7.2.2: - resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + /eslint-scope@8.0.1: + resolution: {integrity: sha512-pL8XjgP4ZOmmwfFE8mEhSxA7ZY4C+LWyqjQ3o4yWkkmD0qcMT9kkW3zWHOczhWcjTSgqycYAgwSlXvZltv65og==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} dependencies: esrecurse: 4.3.0 estraverse: 5.3.0 + dev: true /eslint-visitor-keys@3.4.3: resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true - /eslint@8.56.0: - resolution: {integrity: sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + /eslint-visitor-keys@4.0.0: + resolution: {integrity: sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + dev: true + + /eslint@9.6.0: + resolution: {integrity: sha512-ElQkdLMEEqQNM9Njff+2Y4q2afHk7JpkPvrd7Xh7xefwgQynqPxwf55J7di9+MEibWUGdNjFF9ITG9Pck5M84w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.56.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@9.6.0) '@eslint-community/regexpp': 4.10.0 - '@eslint/eslintrc': 2.1.4 - '@eslint/js': 8.56.0 - '@humanwhocodes/config-array': 0.11.14 + '@eslint/config-array': 0.17.0 + '@eslint/eslintrc': 3.1.0 + '@eslint/js': 9.6.0 '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.3.0 '@nodelib/fs.walk': 1.2.8 - '@ungap/structured-clone': 1.2.0 ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.3 debug: 4.3.4(supports-color@5.5.0) - 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 + eslint-scope: 8.0.1 + eslint-visitor-keys: 4.0.0 + espree: 10.1.0 esquery: 1.5.0 esutils: 2.0.3 fast-deep-equal: 3.1.3 - file-entry-cache: 6.0.1 + file-entry-cache: 8.0.0 find-up: 5.0.0 glob-parent: 6.0.2 - globals: 13.24.0 - graphemer: 1.4.0 ignore: 5.3.1 imurmurhash: 0.1.4 is-glob: 4.0.3 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 @@ -1111,34 +1152,40 @@ packages: text-table: 0.2.0 transitivePeerDependencies: - supports-color + dev: true - /espree@9.6.1: - resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + /espree@10.1.0: + resolution: {integrity: sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} dependencies: - acorn: 8.11.3 - acorn-jsx: 5.3.2(acorn@8.11.3) - eslint-visitor-keys: 3.4.3 + acorn: 8.12.1 + acorn-jsx: 5.3.2(acorn@8.12.1) + eslint-visitor-keys: 4.0.0 + dev: true /esquery@1.5.0: resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} engines: {node: '>=0.10'} dependencies: estraverse: 5.3.0 + dev: true /esrecurse@4.3.0: resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} engines: {node: '>=4.0'} dependencies: estraverse: 5.3.0 + dev: true /estraverse@5.3.0: resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} engines: {node: '>=4.0'} + dev: true /esutils@2.0.3: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} + dev: true /etag@1.8.1: resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} @@ -1186,6 +1233,7 @@ packages: /fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + dev: true /fast-glob@3.3.2: resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} @@ -1196,12 +1244,15 @@ packages: glob-parent: 5.1.2 merge2: 1.4.1 micromatch: 4.0.5 + dev: true /fast-json-stable-stringify@2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + dev: true /fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + dev: true /fast-xml-parser@4.3.4: resolution: {integrity: sha512-utnwm92SyozgA3hhH2I8qldf2lBqm6qHOICawRNRFu1qMe3+oqr+GcXjGqTmXTMGE5T4eC03kr/rlh5C1IRdZA==} @@ -1214,6 +1265,7 @@ packages: resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} dependencies: reusify: 1.0.4 + dev: true /fecha@4.2.3: resolution: {integrity: sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==} @@ -1235,17 +1287,19 @@ packages: hasBin: true dev: false - /file-entry-cache@6.0.1: - resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} - engines: {node: ^10.12.0 || >=12.0.0} + /file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} dependencies: - flat-cache: 3.2.0 + flat-cache: 4.0.1 + dev: true /fill-range@7.0.1: resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} engines: {node: '>=8'} dependencies: to-regex-range: 5.0.1 + dev: true /finalhandler@1.2.0: resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==} @@ -1268,17 +1322,19 @@ packages: dependencies: locate-path: 6.0.0 path-exists: 4.0.0 + dev: true - /flat-cache@3.2.0: - resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} - engines: {node: ^10.12.0 || >=12.0.0} + /flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} dependencies: flatted: 3.2.9 keyv: 4.5.4 - rimraf: 3.0.2 + dev: true /flatted@3.2.9: resolution: {integrity: sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==} + dev: true /fn.name@1.1.0: resolution: {integrity: sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==} @@ -1317,9 +1373,6 @@ packages: engines: {node: '>= 0.6'} dev: false - /fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - /fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -1363,28 +1416,19 @@ packages: engines: {node: '>= 6'} dependencies: is-glob: 4.0.3 + dev: true /glob-parent@6.0.2: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} dependencies: is-glob: 4.0.3 + dev: true - /glob@7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - - /globals@13.24.0: - resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} - engines: {node: '>=8'} - dependencies: - type-fest: 0.20.2 + /globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} + dev: true /globby@11.1.0: resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} @@ -1396,6 +1440,7 @@ packages: ignore: 5.3.1 merge2: 1.4.1 slash: 3.0.0 + dev: true /gopd@1.0.1: resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} @@ -1422,6 +1467,7 @@ packages: /graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + dev: true /has-flag@3.0.0: resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} @@ -1430,6 +1476,7 @@ packages: /has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} + dev: true /has-property-descriptors@1.0.2: resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} @@ -1500,6 +1547,7 @@ packages: /ignore@5.3.1: resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} engines: {node: '>= 4'} + dev: true /import-fresh@3.3.0: resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} @@ -1507,19 +1555,16 @@ packages: dependencies: parent-module: 1.0.1 resolve-from: 4.0.0 + dev: true /imurmurhash@0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} - - /inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - dependencies: - once: 1.4.0 - wrappy: 1.0.2 + dev: true /inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + dev: false /ipaddr.js@1.9.1: resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} @@ -1544,6 +1589,7 @@ packages: /is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} + dev: true /is-fullwidth-code-point@3.0.0: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} @@ -1555,14 +1601,17 @@ packages: engines: {node: '>=0.10.0'} dependencies: is-extglob: 2.1.1 + dev: true /is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} + dev: true /is-path-inside@3.0.3: resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} engines: {node: '>=8'} + dev: true /is-stream@2.0.1: resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} @@ -1571,6 +1620,7 @@ packages: /isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + dev: true /joi@17.12.1: resolution: {integrity: sha512-vtxmq+Lsc5SlfqotnfVjlViWfOL9nt/avKNbKYizwf6gsCfq9NYY/ceYRMFD8XDdrjJ9abJyScWmhmIiy+XRtQ==} @@ -1591,15 +1641,18 @@ packages: hasBin: true dependencies: argparse: 2.0.1 + dev: true /json-buffer@3.0.1: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} /json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + dev: true /json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + dev: true /keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} @@ -1625,15 +1678,18 @@ packages: dependencies: prelude-ls: 1.2.1 type-check: 0.4.0 + dev: true /locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} dependencies: p-locate: 5.0.0 + dev: true /lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + dev: true /lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} @@ -1661,10 +1717,12 @@ packages: engines: {node: '>=10'} dependencies: yallist: 4.0.0 + dev: true /luxon@3.4.4: resolution: {integrity: sha512-zobTr7akeGHnv7eBOXcRgMeCP6+uyYsczwmeRCauvpvaAltgNyTbLH/+VaEAPUeWBT+1GuNmz4wC/6jtQzbbVA==} engines: {node: '>=12'} + dev: false /make-error@1.3.6: resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} @@ -1690,6 +1748,7 @@ packages: /merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} + dev: true /methods@1.1.2: resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} @@ -1702,6 +1761,7 @@ packages: dependencies: braces: 3.0.2 picomatch: 2.3.1 + dev: true /mime-db@1.52.0: resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} @@ -1735,6 +1795,7 @@ packages: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} dependencies: brace-expansion: 1.1.11 + dev: true /minimatch@7.4.6: resolution: {integrity: sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==} @@ -1743,11 +1804,12 @@ packages: brace-expansion: 2.0.1 dev: false - /minimatch@9.0.3: - resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} + /minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} engines: {node: '>=16 || 14 >=14.17'} dependencies: brace-expansion: 2.0.1 + dev: true /morgan@1.10.0: resolution: {integrity: sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==} @@ -1775,6 +1837,7 @@ packages: /natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + dev: true /negotiator@0.6.3: resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} @@ -1865,11 +1928,6 @@ packages: engines: {node: '>= 0.8'} dev: false - /once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - dependencies: - wrappy: 1.0.2 - /one-time@1.0.0: resolution: {integrity: sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==} dependencies: @@ -1886,6 +1944,7 @@ packages: levn: 0.4.1 prelude-ls: 1.2.1 type-check: 0.4.0 + dev: true /p-cancelable@4.0.1: resolution: {integrity: sha512-wBowNApzd45EIKdO1LaU+LrMBwAcjfPaYtVzV3lmfM3gf8Z4CHZsiIqlM8TZZ8okYvh5A1cP6gTfCRQtwUpaUg==} @@ -1897,18 +1956,21 @@ packages: engines: {node: '>=10'} dependencies: yocto-queue: 0.1.0 + dev: true /p-locate@5.0.0: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} engines: {node: '>=10'} dependencies: p-limit: 3.1.0 + dev: true /parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} dependencies: callsites: 3.1.0 + dev: true /parseurl@1.3.3: resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} @@ -1918,14 +1980,12 @@ packages: /path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} - - /path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} + dev: true /path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} + dev: true /path-posix@1.0.0: resolution: {integrity: sha512-1gJ0WpNIiYcQydgg3Ed8KzvIqTsDpNwq+cjBCssvBtuTWjEqY1AW+i+OepiEMqDCzyro9B2sLAe4RBPajMYFiA==} @@ -1938,14 +1998,17 @@ packages: /path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} + dev: true /picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} + dev: true /prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} + dev: true /proxy-addr@2.0.7: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} @@ -1962,6 +2025,7 @@ packages: /punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} + dev: true /qs@6.11.0: resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==} @@ -1976,6 +2040,7 @@ packages: /queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + dev: true /quick-lru@5.1.1: resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} @@ -2033,6 +2098,7 @@ packages: /resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} + dev: true /responselike@3.0.0: resolution: {integrity: sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==} @@ -2044,17 +2110,13 @@ packages: /reusify@1.0.4: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - - /rimraf@3.0.2: - resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} - hasBin: true - dependencies: - glob: 7.2.3 + dev: true /run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} dependencies: queue-microtask: 1.2.3 + dev: true /rxjs@7.8.1: resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} @@ -2085,6 +2147,7 @@ packages: hasBin: true dependencies: lru-cache: 6.0.0 + dev: true /send@0.18.0: resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==} @@ -2140,10 +2203,12 @@ packages: engines: {node: '>=8'} dependencies: shebang-regex: 3.0.0 + dev: true /shebang-regex@3.0.0: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} + dev: true /shell-quote@1.8.1: resolution: {integrity: sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==} @@ -2175,6 +2240,7 @@ packages: /slash@3.0.0: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} + dev: true /spawn-command@0.0.2: resolution: {integrity: sha512-zC8zGoGkmc8J9ndvml8Xksr1Amk9qBujgbF0JAIWO7kXr43w0h/0GJNM/Vustixu+YE8N/MTrQ7N31FvHUACxQ==} @@ -2209,10 +2275,12 @@ packages: engines: {node: '>=8'} dependencies: ansi-regex: 5.0.1 + dev: true /strip-json-comments@3.1.1: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} + dev: true /strnum@1.0.5: resolution: {integrity: sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==} @@ -2229,6 +2297,7 @@ packages: engines: {node: '>=8'} dependencies: has-flag: 4.0.0 + dev: true /supports-color@8.1.1: resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} @@ -2243,12 +2312,14 @@ packages: /text-table@0.2.0: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + dev: true /to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} dependencies: is-number: 7.0.0 + dev: true /toidentifier@1.0.1: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} @@ -2272,13 +2343,14 @@ packages: engines: {node: '>= 14.0.0'} dev: false - /ts-api-utils@1.2.1(typescript@5.3.3): - resolution: {integrity: sha512-RIYA36cJn2WiH9Hy77hdF9r7oEwxAtB/TS9/S4Qd90Ap4z5FSiin5zEiTL44OII1Y3IIlEvxwxFUVgrHSZ/UpA==} + /ts-api-utils@1.3.0(typescript@5.3.3): + resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} engines: {node: '>=16'} peerDependencies: typescript: '>=4.2.0' dependencies: typescript: 5.3.3 + dev: true /ts-node@10.9.2(@types/node@20.11.19)(typescript@5.3.3): resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} @@ -2320,10 +2392,7 @@ packages: engines: {node: '>= 0.8.0'} dependencies: prelude-ls: 1.2.1 - - /type-fest@0.20.2: - resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} - engines: {node: '>=10'} + dev: true /type-is@1.6.18: resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} @@ -2333,10 +2402,29 @@ packages: mime-types: 2.1.35 dev: false + /typescript-eslint@8.0.0-alpha.41(eslint@9.6.0)(typescript@5.3.3): + resolution: {integrity: sha512-+e7D2XDZeHLe9D3bP7S0Va8YdLHzn3YcesoxMS9SjMWhtaSb5ylxk2txqT84sUS0WIDQetZlvDg2/UmY5B/ycg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/eslint-plugin': 8.0.0-alpha.41(@typescript-eslint/parser@8.0.0-alpha.41)(eslint@9.6.0)(typescript@5.3.3) + '@typescript-eslint/parser': 8.0.0-alpha.41(eslint@9.6.0)(typescript@5.3.3) + '@typescript-eslint/utils': 8.0.0-alpha.41(eslint@9.6.0)(typescript@5.3.3) + typescript: 5.3.3 + transitivePeerDependencies: + - eslint + - supports-color + dev: true + /typescript@5.3.3: resolution: {integrity: sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==} engines: {node: '>=14.17'} hasBin: true + dev: true /undefsafe@2.0.5: resolution: {integrity: sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==} @@ -2355,6 +2443,7 @@ packages: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} dependencies: punycode: 2.3.1 + dev: true /url-join@5.0.0: resolution: {integrity: sha512-n2huDr9h9yzd6exQVnH/jU5mr+Pfx08LRXXZhkLLetAMESRj+anQsTAh940iMrIetKAmry9coFuZQ2jY8/p3WA==} @@ -2418,6 +2507,7 @@ packages: hasBin: true dependencies: isexe: 2.0.0 + dev: true /winston-transport@4.7.0: resolution: {integrity: sha512-ajBj65K5I7denzer2IYW6+2bNIVqLGDHqDw3Ow8Ohh+vdW+rv4MZ6eiDvHoKhfJFZ2auyN8byXieDDJ96ViONg==} @@ -2454,9 +2544,6 @@ packages: strip-ansi: 6.0.1 dev: true - /wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - /y18n@5.0.8: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} @@ -2464,6 +2551,7 @@ packages: /yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + dev: true /yargs-parser@21.1.1: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} @@ -2491,3 +2579,4 @@ packages: /yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} + dev: true diff --git a/nextcloud_backup/backend/src/app.ts b/nextcloud_backup/backend/src/app.ts index 12bea76..8ae53e1 100644 --- a/nextcloud_backup/backend/src/app.ts +++ b/nextcloud_backup/backend/src/app.ts @@ -1,31 +1,26 @@ import cookieParser from "cookie-parser"; -import express, { type NextFunction, type Request, type Response } from "express"; +import cors from "cors"; +import errorHandler from "errorhandler"; +import express from "express"; import createError from "http-errors"; import morgan from "morgan"; import path from "path"; import { fileURLToPath } from "url"; import logger from "./config/winston.js"; import apiV2Router from "./routes/apiV2.js"; -import cors from "cors" const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const app = express(); -app.use(cors({ - origin: true -})) +app.use( + cors({ + origin: true, + }) +); app.set("port", process.env.PORT || 3000); -// app.use( -// logger("dev", { -// skip: function (req, res) { -// return (res.statusCode = 304); -// }, -// }) -// ); - app.use( morgan("dev", { stream: { write: (message) => logger.debug(message) } }) ); @@ -46,15 +41,9 @@ app.use((req, res, next) => { }); // error handler -app.use((err: any, req: Request, res: Response, next: NextFunction) => { - // set locals, only providing error in development - res.locals.message = err.message; - res.locals.error = req.app.get("env") === "development" ? err : {}; - - // render the error page - res.status(err.status || 500); - res.render("error"); -}); - +if (process.env.NODE_ENV === "development") { + // only use in development + app.use(errorHandler()); +} export default app; diff --git a/nextcloud_backup/backend/src/postInit.ts b/nextcloud_backup/backend/src/postInit.ts index 1351174..8e47216 100644 --- a/nextcloud_backup/backend/src/postInit.ts +++ b/nextcloud_backup/backend/src/postInit.ts @@ -1,10 +1,12 @@ import { existsSync, mkdirSync } from "fs"; import logger from "./config/winston.js"; import * as homeAssistantService from "./services/homeAssistantService.js"; -import * as settingsTools from "./tools/settingsTools.js"; import * as statusTools from "./tools/status.js"; import kleur from "kleur"; -import { checkWebdavLogin, createBackupFolder } from "./services/webdavService.js"; +import { + checkWebdavLogin, + createBackupFolder, +} from "./services/webdavService.js"; import { getWebdavConfig, validateWebdavConfig, @@ -59,16 +61,15 @@ function postInit() { } ); }, - (reason) => { + (reason: Error) => { logger.error("Webdav config: " + kleur.red().bold("FAIL !")); logger.error(reason); messageManager.error("Invalid webdav config", reason.message); } ); - settingsTools.check(settingsTools.getSettings(), true); + // settingsTools.check(settingsTools.getSettings(), true); // cronTools.init(); - } export default postInit; diff --git a/nextcloud_backup/backend/src/routes/action.ts b/nextcloud_backup/backend/src/routes/action.ts index 3abbec9..188af3a 100644 --- a/nextcloud_backup/backend/src/routes/action.ts +++ b/nextcloud_backup/backend/src/routes/action.ts @@ -10,7 +10,7 @@ actionRouter.post("/backup", (req, res) => { .then(() => { logger.info("All good !"); }) - .catch((reason) => { + .catch(() => { logger.error("Something wrong !"); }); res.statusCode = 200; diff --git a/nextcloud_backup/backend/src/routes/config.ts b/nextcloud_backup/backend/src/routes/config.ts index 4fde6b2..5922d71 100644 --- a/nextcloud_backup/backend/src/routes/config.ts +++ b/nextcloud_backup/backend/src/routes/config.ts @@ -4,45 +4,56 @@ import { saveBackupConfig, validateBackupConfig, } from "../services/backupConfigService.js"; -import { getWebdavConfig, saveWebdavConfig, validateWebdavConfig } from "../services/webdavConfigService.js"; +import { + getWebdavConfig, + saveWebdavConfig, + validateWebdavConfig, +} from "../services/webdavConfigService.js"; import { checkWebdavLogin } from "../services/webdavService.js"; +import type { BackupConfig } from "../types/services/backupConfig.js"; +import { ValidationError } from "joi"; +import type { WebdavConfig } from "../types/services/webdavConfig.js"; const configRouter = express.Router(); -configRouter.get("/backup", (req, res, next) => { +configRouter.get("/backup", (req, res) => { res.json(getBackupConfig()); }); -configRouter.put("/backup", (req, res, next) => { - validateBackupConfig(req.body) +configRouter.put("/backup", (req, res) => { + validateBackupConfig(req.body as BackupConfig) .then(() => { - saveBackupConfig(req.body); + saveBackupConfig(req.body as BackupConfig); res.status(204); res.send(); }) - .catch((error) => { + .catch((error: ValidationError) => { res.status(400); res.json(error.details); }); }); -configRouter.get("/webdav", (req, res, next) => { +configRouter.get("/webdav", (req, res) => { res.json(getWebdavConfig()); }); -configRouter.put("/webdav", (req, res, next) => { - validateWebdavConfig(req.body) +configRouter.put("/webdav", (req, res) => { + validateWebdavConfig(req.body as WebdavConfig) .then(() => { - return checkWebdavLogin(req.body, true) + return checkWebdavLogin(req.body as WebdavConfig, true); }) .then(() => { - saveWebdavConfig(req.body); + saveWebdavConfig(req.body as WebdavConfig); res.status(204); res.send(); }) .catch((error) => { res.status(400); - res.json(error.details ? error.details : error); + if (error instanceof ValidationError) { + res.json(error.details); + } else { + res.json(error); + } }); }); diff --git a/nextcloud_backup/backend/src/routes/homeAssistant.ts b/nextcloud_backup/backend/src/routes/homeAssistant.ts index 10c4713..7b95d08 100644 --- a/nextcloud_backup/backend/src/routes/homeAssistant.ts +++ b/nextcloud_backup/backend/src/routes/homeAssistant.ts @@ -3,11 +3,15 @@ import * as haOsService from "../services/homeAssistantService.js"; const homeAssistantRouter = express.Router(); -homeAssistantRouter.get("/backups/", (req, res, next) => { +homeAssistantRouter.get("/backups/", (req, res) => { haOsService .getBackups() .then((value) => { - res.json(value.body.data.backups.sort((a, b)=> Date.parse(b.date) - Date.parse(a.date))); + res.json( + value.body.data.backups.sort( + (a, b) => Date.parse(b.date) - Date.parse(a.date) + ) + ); }) .catch((reason) => { res.status(500); @@ -15,7 +19,7 @@ homeAssistantRouter.get("/backups/", (req, res, next) => { }); }); -homeAssistantRouter.get("/backup/:slug", (req, res, next) => { +homeAssistantRouter.get("/backup/:slug", (req, res) => { haOsService .getBackupInfo(req.params.slug) .then((value) => { @@ -27,7 +31,7 @@ homeAssistantRouter.get("/backup/:slug", (req, res, next) => { }); }); -homeAssistantRouter.get("/addons", (req, res, next) => { +homeAssistantRouter.get("/addons", (req, res) => { haOsService .getAddonList() .then((value) => { @@ -39,7 +43,7 @@ homeAssistantRouter.get("/addons", (req, res, next) => { }); }); -homeAssistantRouter.get("/folders", (req, res, next) => { +homeAssistantRouter.get("/folders", (req, res) => { res.json(haOsService.getFolderList()); }); diff --git a/nextcloud_backup/backend/src/routes/webdav.ts b/nextcloud_backup/backend/src/routes/webdav.ts index cad8eeb..9d949d6 100644 --- a/nextcloud_backup/backend/src/routes/webdav.ts +++ b/nextcloud_backup/backend/src/routes/webdav.ts @@ -12,7 +12,7 @@ import { WebdavDeleteValidation } from "../types/services/webdavValidation.js"; const webdavRouter = express.Router(); -webdavRouter.get("/backup/auto", (req, res, next) => { +webdavRouter.get("/backup/auto", (req, res) => { const config = getWebdavConfig(); const backupConf = getBackupConfig(); validateWebdavConfig(config) @@ -20,8 +20,11 @@ webdavRouter.get("/backup/auto", (req, res, next) => { return webdavService.checkWebdavLogin(config); }) .then(async () => { - const value = await webdavService - .getBackups(pathTools.auto, config, backupConf.nameTemplate); + const value = await webdavService.getBackups( + pathTools.auto, + config, + backupConf.nameTemplate + ); res.json(value); }) .catch((reason) => { @@ -30,7 +33,7 @@ webdavRouter.get("/backup/auto", (req, res, next) => { }); }); -webdavRouter.get("/backup/manual", (req, res, next) => { +webdavRouter.get("/backup/manual", (req, res) => { const config = getWebdavConfig(); const backupConf = getBackupConfig(); validateWebdavConfig(config) @@ -38,8 +41,11 @@ webdavRouter.get("/backup/manual", (req, res, next) => { return webdavService.checkWebdavLogin(config); }) .then(async () => { - const value = await webdavService - .getBackups(pathTools.manual, config, backupConf.nameTemplate); + const value = await webdavService.getBackups( + pathTools.manual, + config, + backupConf.nameTemplate + ); res.json(value); }) .catch((reason) => { @@ -48,28 +54,30 @@ webdavRouter.get("/backup/manual", (req, res, next) => { }); }); -webdavRouter.delete("/", (req, res, next) => { - const body: WebdavDelete = req.body; +webdavRouter.delete("/", (req, res) => { + const body = req.body as WebdavDelete; const validator = Joi.object(WebdavDeleteValidation); const config = getWebdavConfig(); - validateWebdavConfig(config).then(() => { - validator - .validateAsync(body) - .then(() => { - return webdavService.checkWebdavLogin(config); - }) - .then(() => { - webdavService.deleteBackup(body.path, config) - .then(()=>{ - res.status(201).send(); - }).catch((reason)=>{ - res.status(500).json(reason); - }); - }) - .catch((reason) => { - res.status(400).json(reason); - }); - }); + validateWebdavConfig(config) + .then(() => { + return validator.validateAsync(body); + }) + .then(() => { + return webdavService.checkWebdavLogin(config); + }) + .then(() => { + webdavService + .deleteBackup(body.path, config) + .then(() => { + res.status(201).send(); + }) + .catch((reason) => { + res.status(500).json(reason); + }); + }) + .catch((reason) => { + res.status(400).json(reason); + }); }); export default webdavRouter; diff --git a/nextcloud_backup/backend/src/server.ts b/nextcloud_backup/backend/src/server.ts index a4d308c..5228a13 100755 --- a/nextcloud_backup/backend/src/server.ts +++ b/nextcloud_backup/backend/src/server.ts @@ -4,27 +4,29 @@ import app from "./app.js"; import logger from "./config/winston.js"; import postInit from "./postInit.js"; import figlet from "figlet"; -import kleur from 'kleur'; - +import kleur from "kleur"; /** * Error Handler. Provides full stack */ if (process.env.NODE_ENV === "development") { - app.use(errorHandler()); + app.use(errorHandler()); } - /** * Start Express server. */ const server = app.listen(app.get("port"), () => { - console.log(kleur.yellow().bold(figlet.textSync("NC Backup"))) - logger.info( - `App is running at ` + kleur.green().bold(`http://localhost:${app.get("port")}`) + " in " + kleur.green().bold(app.get("env")) + " mode" - ); - logger.info(kleur.red().bold("Press CTRL-C to stop")); - postInit(); + console.log(kleur.yellow().bold(figlet.textSync("NC Backup"))); + logger.info( + `App is running at ` + + kleur.green().bold(`http://localhost:${app.get("port")}`) + + " in " + + kleur.green().bold(app.get("env") as string) + + " mode" + ); + logger.info(kleur.red().bold("Press CTRL-C to stop")); + postInit(); }); -export default server; \ No newline at end of file +export default server; diff --git a/nextcloud_backup/backend/src/services/backupConfigService.ts b/nextcloud_backup/backend/src/services/backupConfigService.ts index 8f3a97a..f0df8a8 100644 --- a/nextcloud_backup/backend/src/services/backupConfigService.ts +++ b/nextcloud_backup/backend/src/services/backupConfigService.ts @@ -29,7 +29,9 @@ export function getBackupConfig(): BackupConfig { saveBackupConfig(defaultConfig); return defaultConfig; } else { - return JSON.parse(fs.readFileSync(backupConfigPath).toString()); + return JSON.parse( + fs.readFileSync(backupConfigPath).toString() + ) as BackupConfig; } } diff --git a/nextcloud_backup/backend/src/services/homeAssistantService.ts b/nextcloud_backup/backend/src/services/homeAssistantService.ts index d7205dd..258f524 100644 --- a/nextcloud_backup/backend/src/services/homeAssistantService.ts +++ b/nextcloud_backup/backend/src/services/homeAssistantService.ts @@ -5,27 +5,26 @@ import got, { RequestError, type OptionsOfJSONResponseBody, type PlainResponse, + type Progress, type Response, } from "got"; +import { DateTime } from "luxon"; import stream from "stream"; import { promisify } from "util"; import logger from "../config/winston.js"; import messageManager from "../tools/messageManager.js"; -import * as settingsTools from "../tools/settingsTools.js"; import * as statusTools from "../tools/status.js"; +import { BackupType } from "../types/services/backupConfig.js"; import type { NewBackupPayload } from "../types/services/ha_os_payload.js"; import type { AddonData, - AddonModel, BackupData, BackupDetailModel, BackupModel, CoreInfoBody, SupervisorResponse, } from "../types/services/ha_os_response.js"; -import { States, type Status } from "../types/status.js"; -import { DateTime } from "luxon"; -import { BackupType } from "../types/services/backupConfig.js"; +import { States } from "../types/status.js"; const pipeline = promisify(stream.pipeline); @@ -44,7 +43,7 @@ function getVersion(): Promise>> { (result) => { return result; }, - (error) => { + (error: Error) => { messageManager.error( "Fail to fetch Home Assistant version", error?.message @@ -73,7 +72,7 @@ function getAddonList(): Promise>> { }); return result; }, - (error) => { + (error: Error) => { messageManager.error("Fail to fetch addons list", error?.message); logger.error(`Fail to fetch addons list (${error?.message})`); logger.error(error); @@ -98,7 +97,7 @@ function getBackups(): Promise>> { statusTools.setStatus(status); return result; }, - (error) => { + (error: Error) => { const status = statusTools.getStatus(); status.hass.ok = false; status.hass.last_check = DateTime.now(); @@ -127,7 +126,7 @@ function downloadSnapshot(id: string): Promise { return pipeline( got.stream .get(`http://hassio/backups/${id}/download`, option) - .on("downloadProgress", (e) => { + .on("downloadProgress", (e: Progress) => { const percent = Math.round(e.percent * 100) / 100; if (status.progress !== percent) { status.progress = percent; @@ -147,7 +146,7 @@ function downloadSnapshot(id: string): Promise { ); return tmp_file; }, - (reason) => { + (reason: Error) => { fs.unlinkSync(tmp_file); messageManager.error( "Fail to download Home Assistant backup", @@ -170,7 +169,7 @@ function delSnap(id: string) { (result) => { return result; }, - (reason) => { + (reason: RequestError) => { messageManager.error( "Fail to delete Homme assistant backup detail.", reason.message @@ -196,7 +195,7 @@ function getBackupInfo(id: string) { logger.debug(`Backup size: ${result.body.data.size}`); return result; }, - (reason) => { + (reason: RequestError) => { messageManager.error( "Fail to retrive Homme assistant backup detail.", reason.message @@ -250,7 +249,7 @@ function createNewBackup( statusTools.setStatus(status); return result; }, - (reason) => { + (reason: RequestError) => { messageManager.error("Fail to create new backup.", reason.message); logger.error("Fail to create new backup"); logger.error(reason); @@ -263,19 +262,15 @@ function createNewBackup( ); } -function clean(backups: BackupModel[]) { +function clean(backups: BackupModel[], numberToKeep: number) { const promises = []; - let limit = settingsTools.getSettings().auto_clean_local_keep; - if (limit == null) { - limit = 5; - } - if (backups.length < limit) { + if (backups.length < numberToKeep) { return; } backups.sort((a, b) => { return Date.parse(b.date) - Date.parse(a.date); }); - const toDel = backups.slice(limit); + const toDel = backups.slice(numberToKeep); for (const i of toDel) { promises.push(delSnap(i.slug)); } @@ -284,6 +279,7 @@ function clean(backups: BackupModel[]) { let errors = false; for (const val of values) { if (val.status == "rejected") { + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument messageManager.error("Fail to delete backup", val.reason); logger.error("Fail to delete backup"); logger.error(val.reason); @@ -293,7 +289,7 @@ function clean(backups: BackupModel[]) { if (errors) { messageManager.error("Fail to clean backups in Home Assistant"); logger.error("Fail to clean backups in Home Assistant"); - return Promise.reject(); + return Promise.reject(new Error()); } }); } @@ -315,7 +311,7 @@ function uploadSnapshot(path: string) { }; got.stream .post(`http://hassio/backups/new/upload`, options) - .on("uploadProgress", (e) => { + .on("uploadProgress", (e: Progress) => { const percent = e.percent; if (status.progress !== percent) { status.progress = percent; @@ -329,13 +325,13 @@ function uploadSnapshot(path: string) { if (res.statusCode !== 200) { messageManager.error( "Fail to upload backup to Home Assistant", - `Code: ${res.statusCode} Body: ${res.body}` + `Code: ${res.statusCode} Body: ${res.body as string}` ); logger.error("Fail to upload backup to Home Assistant"); logger.error(`Code: ${res.statusCode}`); - logger.error(`Body: ${res.body}`); + logger.error(`Body: ${res.body as string}`); fs.unlinkSync(path); - reject(res.statusCode); + reject(new Error(res.statusCode.toString())); } else { logger.info(`...Upload finish ! (status: ${res.statusCode})`); const status = statusTools.getStatus(); @@ -388,17 +384,17 @@ function stopAddons(addonSlugs: string[]) { statusTools.setStatus(status); for (const val of values) { if (val.status == "rejected") { + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument messageManager.error("Fail to stop addon", val.reason); logger.error("Fail to stop addon"); logger.error(val.reason); - logger.error; errors = true; } } if (errors) { messageManager.error("Fail to stop addon"); logger.error("Fail to stop addon"); - return Promise.reject(); + return Promise.reject(new Error()); } }); } @@ -428,6 +424,7 @@ function startAddons(addonSlugs: string[]) { let errors = false; for (const val of values) { if (val.status == "rejected") { + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument messageManager.error("Fail to start addon", val.reason); logger.error("Fail to start addon"); logger.error(val.reason); @@ -437,7 +434,7 @@ function startAddons(addonSlugs: string[]) { if (errors) { messageManager.error("Fail to start addon"); logger.error("Fail to start addon"); - return Promise.reject(); + return Promise.reject(new Error()); } }); } @@ -467,7 +464,7 @@ export function getFolderList() { ]; } -function publish_state(state: Status) { +function publish_state() { // let data_error_sensor = { // state: state.status == "error" ? "on" : "off", // attributes: { @@ -532,15 +529,15 @@ function publish_state(state: Status) { } export { - getVersion, - getAddonList, - getBackups, - downloadSnapshot, - createNewBackup, - uploadSnapshot, - stopAddons, - startAddons, clean, - publish_state, + createNewBackup, + downloadSnapshot, + getAddonList, getBackupInfo, + getBackups, + getVersion, + publish_state, + startAddons, + stopAddons, + uploadSnapshot, }; diff --git a/nextcloud_backup/backend/src/services/orchestrator.ts b/nextcloud_backup/backend/src/services/orchestrator.ts index fa3a82e..ed2806a 100644 --- a/nextcloud_backup/backend/src/services/orchestrator.ts +++ b/nextcloud_backup/backend/src/services/orchestrator.ts @@ -1,15 +1,15 @@ +import { unlinkSync } from "fs"; +import { DateTime } from "luxon"; +import logger from "../config/winston.js"; +import messageManager from "../tools/messageManager.js"; +import * as statusTools from "../tools/status.js"; +import { BackupType } from "../types/services/backupConfig.js"; import type { AddonModel } from "../types/services/ha_os_response.js"; import { WorkflowType } from "../types/services/orchecstrator.js"; import * as backupConfigService from "./backupConfigService.js"; import * as homeAssistantService from "./homeAssistantService.js"; import { getBackupFolder, getWebdavConfig } from "./webdavConfigService.js"; import * as webDavService from "./webdavService.js"; -import * as statusTools from "../tools/status.js"; -import { stat, unlinkSync } from "fs"; -import logger from "../config/winston.js"; -import { BackupType } from "../types/services/backupConfig.js"; -import { DateTime } from "luxon"; -import messageManager from "../tools/messageManager.js"; export function doBackupWorkflow(type: WorkflowType) { let name = ""; @@ -38,7 +38,7 @@ export function doBackupWorkflow(type: WorkflowType) { .then(() => { return homeAssistantService.stopAddons(addonsToStartStop); }) - .then((response) => { + .then(() => { if (backupConfig.backupType == BackupType.FULL) { return homeAssistantService.createNewBackup( name, @@ -66,21 +66,23 @@ export function doBackupWorkflow(type: WorkflowType) { } }) .then((response) => { - response.body.data.slug; return homeAssistantService.downloadSnapshot(response.body.data.slug); }) .then((tmpFile) => { tmpBackupFile = tmpFile; - return webDavService.chunkedUpload( - tmpFile, - getBackupFolder(type, webdavConfig) + name, - webdavConfig - ); - // return webDavService.webdavUploadFile( - // tmpFile, - // getBackupFolder(type, webdavConfig) + name, - // webdavConfig - // ); + if (webdavConfig.chunckedUpload) { + return webDavService.chunkedUpload( + tmpFile, + getBackupFolder(type, webdavConfig) + name, + webdavConfig + ); + } else { + return webDavService.webdavUploadFile( + tmpFile, + getBackupFolder(type, webdavConfig) + name, + webdavConfig + ); + } }) .then(() => { logger.info("Backup workflow finished successfully !"); @@ -96,7 +98,7 @@ export function doBackupWorkflow(type: WorkflowType) { if (tmpBackupFile != "") { unlinkSync(tmpBackupFile); } - return Promise.reject(); + return Promise.reject(new Error()); }); } diff --git a/nextcloud_backup/backend/src/services/webdavConfigService.ts b/nextcloud_backup/backend/src/services/webdavConfigService.ts index fca98ed..a1b36b5 100644 --- a/nextcloud_backup/backend/src/services/webdavConfigService.ts +++ b/nextcloud_backup/backend/src/services/webdavConfigService.ts @@ -1,16 +1,14 @@ import fs from "fs"; import Joi from "joi"; import logger from "../config/winston.js"; +import * as pathTools from "../tools/pathTools.js"; import { default_root } from "../tools/pathTools.js"; +import { WorkflowType } from "../types/services/orchecstrator.js"; import { type WebdavConfig, WebdavEndpointType, } from "../types/services/webdavConfig.js"; import WebdavConfigValidation from "../types/services/webdavConfigValidation.js"; -import { BackupType } from "../types/services/backupConfig.js"; -import * as pathTools from "../tools/pathTools.js"; -import { WorkflowType } from "../types/services/orchecstrator.js"; -import e from "express"; const webdavConfigPath = "/data/webdavConfigV2.json"; const NEXTCLOUD_ENDPOINT = "/remote.php/dav/files/$username"; @@ -34,7 +32,9 @@ export function getWebdavConfig(): WebdavConfig { saveWebdavConfig(defaultConfig); return defaultConfig; } else { - return JSON.parse(fs.readFileSync(webdavConfigPath).toString()); + return JSON.parse( + fs.readFileSync(webdavConfigPath).toString() + ) as WebdavConfig; } } diff --git a/nextcloud_backup/backend/src/services/webdavService.ts b/nextcloud_backup/backend/src/services/webdavService.ts index c16e6a9..3b45af3 100644 --- a/nextcloud_backup/backend/src/services/webdavService.ts +++ b/nextcloud_backup/backend/src/services/webdavService.ts @@ -1,3 +1,7 @@ +/* eslint-disable @typescript-eslint/no-unsafe-argument */ +/* eslint-disable @typescript-eslint/no-unsafe-call */ +/* eslint-disable @typescript-eslint/no-unsafe-member-access */ +/* eslint-disable @typescript-eslint/no-unsafe-assignment */ import { XMLParser } from "fast-xml-parser"; import fs from "fs"; import got, { @@ -54,7 +58,10 @@ export function checkWebdavLogin( }, (reason) => { if (!silent) { - messageManager.error("Fail to connect to Webdav", reason?.message); + messageManager.error( + "Fail to connect to Webdav", + (reason as Error).message + ); } const status = statusTools.getStatus(); status.webdav = { @@ -65,7 +72,7 @@ export function checkWebdavLogin( statusTools.setStatus(status); logger.error(`Fail to connect to Webdav`); logger.error(reason); - return Promise.reject(reason); + return Promise.reject(reason as Error); } ); } @@ -90,7 +97,7 @@ export async function createBackupFolder(conf: WebdavConfig) { status.webdav.folder_created = false; status.webdav.last_check = DateTime.now(); statusTools.setStatus(status); - return Promise.reject(error); + return Promise.reject(error as Error); } } } @@ -110,7 +117,7 @@ export async function createBackupFolder(conf: WebdavConfig) { status.webdav.folder_created = false; status.webdav.last_check = DateTime.now(); statusTools.setStatus(status); - return Promise.reject(error); + return Promise.reject(error as Error); } } } @@ -139,7 +146,7 @@ export function getBackups( ) { const status = statusTools.getStatus(); if (!status.webdav.logged_in && !status.webdav.folder_created) { - return Promise.reject("Not logged in"); + return Promise.reject(new Error("Not logged in")); } const endpoint = getEndpoint(config); return got(config.url + endpoint + config.backupDir + folder, { @@ -165,7 +172,7 @@ export function getBackups( ); logger.error(`Fail to retrive webdav backups in ${folder} folder`); logger.error(reason); - return Promise.reject(reason); + return Promise.reject(reason as Error); } ); } @@ -214,11 +221,11 @@ export function deleteBackup(path: string, config: WebdavConfig) { (reason) => { messageManager.error( "Fail to delete backup in webdav", - reason?.message + (reason as Error)?.message ); logger.error(`Fail to delete backup in Cloud`); logger.error(reason); - return Promise.reject(reason); + return Promise.reject(reason as Error); } ); } @@ -302,13 +309,13 @@ export function webdavUploadFile( if (res.statusCode != 201 && res.statusCode != 204) { messageManager.error( "Fail to upload file to Cloud.", - `Code: ${res.statusCode} Body: ${res.body}` + `Code: ${res.statusCode} Body: ${res.body as string}` ); logger.error(`Fail to upload file to Cloud`); logger.error(`Code: ${res.statusCode}`); - logger.error(`Body: ${res.body}`); + logger.error(`Body: ${res.body as string}`); fs.unlinkSync(localPath); - reject(res); + reject(new Error(res.statusCode.toString())); } else { logger.info(`...Upload finish ! (status: ${res.statusCode})`); fs.unlinkSync(localPath); @@ -340,6 +347,10 @@ export async function chunkedUpload( const chunkEndpoint = getChunkEndpoint(config); const chunkedUrl = config.url + chunkEndpoint + uuid; const finalDestination = config.url + getEndpoint(config) + webdavPath; + const status = statusTools.getStatus(); + status.status = States.BKUP_UPLOAD_CLOUD; + status.progress = 0; + statusTools.setStatus(status); try { await initChunkedUpload(chunkedUrl, finalDestination, config); } catch (err) { @@ -366,7 +377,7 @@ export async function chunkedUpload( let start = 0; let end = fileSize > CHUNK_SIZE ? CHUNK_SIZE : fileSize; let current_size = end; - let uploadedBytes = 0; + // const uploadedBytes = 0; let i = 0; while (start < fileSize) { @@ -396,12 +407,12 @@ export async function chunkedUpload( messageManager.error( "Fail to upload file to Cloud.", `Code: ${(error as PlainResponse).statusCode} Body: ${ - (error as PlainResponse).body + (error as PlainResponse).body as string }` ); logger.error(`Fail to upload file to Cloud`); logger.error(`Code: ${(error as PlainResponse).statusCode}`); - logger.error(`Body: ${(error as PlainResponse).body}`); + logger.error(`Body: ${(error as PlainResponse).body as string}`); } throw error; } @@ -462,7 +473,7 @@ export function uploadChunk( resolve(res); } else { logger.error(`Fail to upload chunk: ${res.statusCode}`); - reject(res); + reject(new Error(res.statusCode.toString())); } }) .on("error", (err) => { diff --git a/nextcloud_backup/backend/src/tools/settingsTools.ts b/nextcloud_backup/backend/src/tools/settingsTools.ts deleted file mode 100644 index bdfe78b..0000000 --- a/nextcloud_backup/backend/src/tools/settingsTools.ts +++ /dev/null @@ -1,213 +0,0 @@ -import { CronJob } from "cron"; -import fs from "fs"; - -import { DateTime } from "luxon"; -import logger from "../config/winston.js"; -import type { Settings } from "../types/settings.js"; - -const settingsPath = "/data/backup_conf.json"; - -function check_cron(conf: Settings) { - if (conf.cron_base != null) { - if ( - conf.cron_base == "1" || - conf.cron_base == "2" || - conf.cron_base == "3" - ) { - if (conf.cron_hour != null && conf.cron_hour.match(/\d\d:\d\d/)) { - if (conf.cron_base === "1") return true; - } else return false; - } - - if (conf.cron_base === "2") { - return ( - conf.cron_weekday != null && - conf.cron_weekday >= 0 && - conf.cron_weekday <= 6 - ); - } - - if (conf.cron_base === "3") { - return ( - conf.cron_month_day != null && - conf.cron_month_day >= 1 && - conf.cron_month_day <= 28 - ); - } - - if (conf.cron_base === "4") { - if (conf.cron_custom != null) { - try { - // TODO Need to be destroy - new CronJob(conf.cron_custom, () => { - //Do nothing - }); - return true; - } catch (e) { - return false; - } - } else return false; - } - - if (conf.cron_base === "0") return true; - } else return false; - - return false; -} - -function check(conf: Settings, fallback = false) { - let needSave = false; - if (!check_cron(conf)) { - if (fallback) { - logger.warn("Bad value for cron settings, fallback to default "); - conf.cron_base = "0"; - conf.cron_hour = "00:00"; - conf.cron_weekday = 0; - conf.cron_month_day = 1; - conf.cron_custom = "5 4 * * *"; - } else { - logger.error("Bad value for cron settings"); - return [false, "Bad cron settings"]; - } - } - if (!conf.name_template) { - if (fallback) { - logger.warn("Bad value for 'name_template', fallback to default "); - conf.name_template = "{type}-{ha_version}-{date}_{hour}"; - } else { - logger.error("Bad value for 'name_template'"); - return [false, "Bad value for 'name_template'"]; - } - } - if ( - conf.auto_clean_local_keep == undefined || - !/^\d+$/.test(conf.auto_clean_local_keep) - ) { - if (fallback) { - logger.warn("Bad value for 'auto_clean_local_keep', fallback to 5 "); - conf.auto_clean_local_keep = "5"; - } else { - logger.error("Bad value for 'auto_clean_local_keep'"); - return [false, "Bad value for 'auto_clean_local_keep'"]; - } - } - if ( - conf.auto_clean_backup_keep == undefined || - !/^\d+$/.test(conf.auto_clean_backup_keep) - ) { - if (fallback) { - logger.warn("Bad value for 'auto_clean_backup_keep', fallback to 5 "); - conf.auto_clean_backup_keep = "5"; - } else { - logger.error("Bad value for 'auto_clean_backup_keep'"); - return [false, "Bad value for 'auto_clean_backup_keep'"]; - } - } - if (conf.auto_clean_local == undefined) { - if (fallback) { - logger.warn("Bad value for 'auto_clean_local', fallback to false "); - conf.auto_clean_local = "false"; - } else { - logger.error("Bad value for 'auto_clean_local'"); - return [false, "Bad value for 'auto_clean_local'"]; - } - } - if (conf.auto_clean_backup == undefined) { - if (fallback) { - logger.warn("Bad value for 'auto_clean_backup', fallback to false "); - conf.auto_clean_backup = "false"; - } else { - logger.error("Bad value for 'auto_clean_backup'"); - return [false, "Bad value for 'auto_clean_backup'"]; - } - } - if (conf.exclude_addon == undefined) { - if (fallback) { - logger.warn("Bad value for 'exclude_addon', fallback to [] "); - conf.exclude_addon = []; - } else { - logger.error("Bad value for 'exclude_addon'"); - return [false, "Bad value for 'exclude_addon'"]; - } - } - if (conf.exclude_folder == undefined) { - if (fallback) { - logger.warn("Bad value for 'exclude_folder', fallback to [] "); - conf.exclude_folder = []; - } else { - logger.error("Bad value for 'exclude_folder'"); - return [false, "Bad value for 'exclude_folder'"]; - } - } - if (conf.auto_stop_addon == undefined) { - if (fallback) { - logger.warn("Bad value for 'auto_stop_addon', fallback to [] "); - conf.auto_stop_addon = []; - } else { - logger.error("Bad value for 'auto_stop_addon'"); - return [false, "Bad value for 'auto_stop_addon'"]; - } - } - - if (!Array.isArray(conf.exclude_folder)) { - logger.debug("exclude_folder is not array (Empty value), reset..."); - conf.exclude_folder = []; - needSave = true; - } - if (!Array.isArray(conf.exclude_addon)) { - logger.debug("exclude_addon is not array (Empty value), reset..."); - conf.exclude_addon = []; - needSave = true; - } - if (conf.password_protected == undefined) { - if (fallback) { - logger.warn("Bad value for 'password_protected', fallback to false "); - conf.password_protected = "false"; - } else { - logger.error("Bad value for 'password_protect_value'"); - return [false, "Bad value for 'password_protect_value'"]; - } - } - - if (conf.password_protect_value == null) { - if (fallback) { - logger.warn("Bad value for 'password_protect_value', fallback to '' "); - conf.password_protect_value = ""; - } else { - logger.error("Bad value for 'password_protect_value'"); - return [false, "Bad value for 'password_protect_value'"]; - } - } - - if (fallback || needSave) { - setSettings(conf); - } - return [true, null]; -} - -function getFormatedName(is_manual: boolean, ha_version: string) { - const setting = getSettings(); - let template = setting.name_template; - template = template.replace("{type_low}", is_manual ? "manual" : "auto"); - template = template.replace("{type}", is_manual ? "Manual" : "Auto"); - template = template.replace("{ha_version}", ha_version); - const now = DateTime.now().setLocale("en"); - template = template.replace("{hour_12}", now.toFormat("hhmma")); - template = template.replace("{hour}", now.toFormat("HHmm")); - template = template.replace("{date}", now.toFormat("yyyy-MM-dd")); - return template; -} - -function getSettings() { - if (!fs.existsSync(settingsPath)) { - return {}; - } else { - return JSON.parse(fs.readFileSync(settingsPath).toString()); - } -} - -function setSettings(settings: Settings) { - fs.writeFileSync(settingsPath, JSON.stringify(settings)); -} - -export { getSettings, setSettings, check, check_cron, getFormatedName }; diff --git a/nextcloud_backup/backend/src/tools/status.ts b/nextcloud_backup/backend/src/tools/status.ts index d14cdf1..d7591d1 100644 --- a/nextcloud_backup/backend/src/tools/status.ts +++ b/nextcloud_backup/backend/src/tools/status.ts @@ -1,4 +1,3 @@ -import { publish_state } from "../services/homeAssistantService.js"; import { States, type Status } from "../types/status.js"; import { DateTime } from "luxon"; @@ -33,6 +32,6 @@ export function setStatus(new_state: Status) { const old_state_str = JSON.stringify(status); if (old_state_str !== JSON.stringify(new_state)) { status = new_state; - publish_state(status); + // publish_state(status); } } diff --git a/nextcloud_backup/backend/src/types/services/webdavConfigValidation.ts b/nextcloud_backup/backend/src/types/services/webdavConfigValidation.ts index 945a43a..36c867c 100644 --- a/nextcloud_backup/backend/src/types/services/webdavConfigValidation.ts +++ b/nextcloud_backup/backend/src/types/services/webdavConfigValidation.ts @@ -1,7 +1,6 @@ import Joi from "joi"; import { WebdavEndpointType } from "./webdavConfig.js"; - const WebdavConfigValidation = { url: Joi.string().not().empty().uri().required().label("Url"), username: Joi.string().not().empty().label("Username"), @@ -10,18 +9,22 @@ const WebdavConfigValidation = { allowSelfSignedCerts: Joi.boolean().label("Allow self signed certificate"), chunckedUpload: Joi.boolean().required().label("Chuncked upload"), webdavEndpoint: Joi.object({ - type: Joi.string().valid(WebdavEndpointType.CUSTOM, WebdavEndpointType.NEXTCLOUD).required(), + type: Joi.string() + .valid(WebdavEndpointType.CUSTOM, WebdavEndpointType.NEXTCLOUD) + .required(), customEndpoint: Joi.alternatives().conditional("type", { is: WebdavEndpointType.CUSTOM, - then: Joi.string().not().empty().required, - otherwise: Joi.disallow() + then: Joi.string().not().empty().required(), + otherwise: Joi.disallow(), }), customChunkEndpoint: Joi.alternatives().conditional("type", { is: WebdavEndpointType.CUSTOM, - then: Joi.string().not().empty().required, - otherwise: Joi.disallow() - }) - }).required().label("Webdav endpoint"), -} + then: Joi.string().not().empty().required(), + otherwise: Joi.disallow(), + }), + }) + .required() + .label("Webdav endpoint"), +}; -export default WebdavConfigValidation; \ No newline at end of file +export default WebdavConfigValidation;