From d2575d8f00cffbd5db5e9229315e3f852f23b946 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 11 Feb 2025 18:50:18 +0000 Subject: [PATCH 1/5] fix(deps): update typescript-projects (#16023) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Daniel Dietzler --- cli/package-lock.json | 252 +++--- e2e/package-lock.json | 790 ++++++++++-------- server/package-lock.json | 485 ++++++----- server/package.json | 2 +- web/package-lock.json | 458 +++++----- web/package.json | 4 +- .../album-page/albums-controls.svelte | 2 + .../components/elements/buttons/button.svelte | 1 - .../buttons/circle-icon-button.svelte | 1 - .../places-page/places-controls.svelte | 2 + .../navigation-bar/navigation-bar.svelte | 1 + .../[[assetId=id]]/+page.svelte | 1 + .../routes/admin/user-management/+page.svelte | 4 + 13 files changed, 1050 insertions(+), 953 deletions(-) diff --git a/cli/package-lock.json b/cli/package-lock.json index 9c3067bacf5fc..2aca48b6488e4 100644 --- a/cli/package-lock.json +++ b/cli/package-lock.json @@ -881,9 +881,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.18.0.tgz", - "integrity": "sha512-fK6L7rxcq6/z+AaQMtiFTkvbHkBLNlwyRxHpKawP0x3u9+NC6MQTnFW+AdpwC6gfHTW0051cokQgtTN2FqlxQA==", + "version": "9.19.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.19.0.tgz", + "integrity": "sha512-rbq9/g38qjfqFLOVPvwjIvFFdNziEC5S65jmjPw5r6A//QH+W91akh9irMwjDN8zKUTak6W9EsAv4m/7Wnw0UQ==", "dev": true, "license": "MIT", "engines": { @@ -1498,21 +1498,21 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.20.0.tgz", - "integrity": "sha512-naduuphVw5StFfqp4Gq4WhIBE2gN1GEmMUExpJYknZJdRnc+2gDzB8Z3+5+/Kv33hPQRDGzQO/0opHE72lZZ6A==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.23.0.tgz", + "integrity": "sha512-vBz65tJgRrA1Q5gWlRfvoH+w943dq9K1p1yDBY2pc+a1nbBLZp7fB9+Hk8DaALUbzjqlMfgaqlVPT1REJdkt/w==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.20.0", - "@typescript-eslint/type-utils": "8.20.0", - "@typescript-eslint/utils": "8.20.0", - "@typescript-eslint/visitor-keys": "8.20.0", + "@typescript-eslint/scope-manager": "8.23.0", + "@typescript-eslint/type-utils": "8.23.0", + "@typescript-eslint/utils": "8.23.0", + "@typescript-eslint/visitor-keys": "8.23.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", - "ts-api-utils": "^2.0.0" + "ts-api-utils": "^2.0.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1528,16 +1528,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.20.0.tgz", - "integrity": "sha512-gKXG7A5HMyjDIedBi6bUrDcun8GIjnI8qOwVLiY3rx6T/sHP/19XLJOnIq/FgQvWLHja5JN/LSE7eklNBr612g==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.23.0.tgz", + "integrity": "sha512-h2lUByouOXFAlMec2mILeELUbME5SZRN/7R9Cw2RD2lRQQY08MWMM+PmVVKKJNK1aIwqTo9t/0CvOxwPbRIE2Q==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.20.0", - "@typescript-eslint/types": "8.20.0", - "@typescript-eslint/typescript-estree": "8.20.0", - "@typescript-eslint/visitor-keys": "8.20.0", + "@typescript-eslint/scope-manager": "8.23.0", + "@typescript-eslint/types": "8.23.0", + "@typescript-eslint/typescript-estree": "8.23.0", + "@typescript-eslint/visitor-keys": "8.23.0", "debug": "^4.3.4" }, "engines": { @@ -1553,14 +1553,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.20.0.tgz", - "integrity": "sha512-J7+VkpeGzhOt3FeG1+SzhiMj9NzGD/M6KoGn9f4dbz3YzK9hvbhVTmLj/HiTp9DazIzJ8B4XcM80LrR9Dm1rJw==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.23.0.tgz", + "integrity": "sha512-OGqo7+dXHqI7Hfm+WqkZjKjsiRtFUQHPdGMXzk5mYXhJUedO7e/Y7i8AK3MyLMgZR93TX4bIzYrfyVjLC+0VSw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.20.0", - "@typescript-eslint/visitor-keys": "8.20.0" + "@typescript-eslint/types": "8.23.0", + "@typescript-eslint/visitor-keys": "8.23.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1571,16 +1571,16 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.20.0.tgz", - "integrity": "sha512-bPC+j71GGvA7rVNAHAtOjbVXbLN5PkwqMvy1cwGeaxUoRQXVuKCebRoLzm+IPW/NtFFpstn1ummSIasD5t60GA==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.23.0.tgz", + "integrity": "sha512-iIuLdYpQWZKbiH+RkCGc6iu+VwscP5rCtQ1lyQ7TYuKLrcZoeJVpcLiG8DliXVkUxirW/PWlmS+d6yD51L9jvA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.20.0", - "@typescript-eslint/utils": "8.20.0", + "@typescript-eslint/typescript-estree": "8.23.0", + "@typescript-eslint/utils": "8.23.0", "debug": "^4.3.4", - "ts-api-utils": "^2.0.0" + "ts-api-utils": "^2.0.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1595,9 +1595,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.20.0.tgz", - "integrity": "sha512-cqaMiY72CkP+2xZRrFt3ExRBu0WmVitN/rYPZErA80mHjHx/Svgp8yfbzkJmDoQ/whcytOPO9/IZXnOc+wigRA==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.23.0.tgz", + "integrity": "sha512-1sK4ILJbCmZOTt9k4vkoulT6/y5CHJ1qUYxqpF1K/DBAd8+ZUL4LlSCxOssuH5m4rUaaN0uS0HlVPvd45zjduQ==", "dev": true, "license": "MIT", "engines": { @@ -1609,20 +1609,20 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.20.0.tgz", - "integrity": "sha512-Y7ncuy78bJqHI35NwzWol8E0X7XkRVS4K4P4TCyzWkOJih5NDvtoRDW4Ba9YJJoB2igm9yXDdYI/+fkiiAxPzA==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.23.0.tgz", + "integrity": "sha512-LcqzfipsB8RTvH8FX24W4UUFk1bl+0yTOf9ZA08XngFwMg4Kj8A+9hwz8Cr/ZS4KwHrmo9PJiLZkOt49vPnuvQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.20.0", - "@typescript-eslint/visitor-keys": "8.20.0", + "@typescript-eslint/types": "8.23.0", + "@typescript-eslint/visitor-keys": "8.23.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", - "ts-api-utils": "^2.0.0" + "ts-api-utils": "^2.0.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1636,16 +1636,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.20.0.tgz", - "integrity": "sha512-dq70RUw6UK9ei7vxc4KQtBRk7qkHZv447OUZ6RPQMQl71I3NZxQJX/f32Smr+iqWrB02pHKn2yAdHBb0KNrRMA==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.23.0.tgz", + "integrity": "sha512-uB/+PSo6Exu02b5ZEiVtmY6RVYO7YU5xqgzTIVZwTHvvK3HsL8tZZHFaTLFtRG3CsV4A5mhOv+NZx5BlhXPyIA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.20.0", - "@typescript-eslint/types": "8.20.0", - "@typescript-eslint/typescript-estree": "8.20.0" + "@typescript-eslint/scope-manager": "8.23.0", + "@typescript-eslint/types": "8.23.0", + "@typescript-eslint/typescript-estree": "8.23.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1660,13 +1660,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.20.0.tgz", - "integrity": "sha512-v/BpkeeYAsPkKCkR8BDwcno0llhzWVqPOamQrAEMdpZav2Y9OVjd9dwJyBLJWwf335B5DmlifECIkZRJCaGaHA==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.23.0.tgz", + "integrity": "sha512-oWWhcWDLwDfu++BGTZcmXWqpwtkwb5o7fxUIGksMQQDSdPW9prsSnfIOZMlsj4vBOSrcnjIUZMiIjODgGosFhQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.20.0", + "@typescript-eslint/types": "8.23.0", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -1691,9 +1691,9 @@ } }, "node_modules/@vitest/coverage-v8": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.0.3.tgz", - "integrity": "sha512-uVbJ/xhImdNtzPnLyxCZJMTeTIYdgcC2nWtBBBpR1H6z0w8m7D+9/zrDIx2nNxgMg9r+X8+RY2qVpUDeW2b3nw==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.0.5.tgz", + "integrity": "sha512-zOOWIsj5fHh3jjGwQg+P+J1FW3s4jBu1Zqga0qW60yutsBtqEqNEJKWYh7cYn1yGD+1bdPsPdC/eL4eVK56xMg==", "dev": true, "license": "MIT", "dependencies": { @@ -1714,8 +1714,8 @@ "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "@vitest/browser": "3.0.3", - "vitest": "3.0.3" + "@vitest/browser": "3.0.5", + "vitest": "3.0.5" }, "peerDependenciesMeta": { "@vitest/browser": { @@ -1724,14 +1724,14 @@ } }, "node_modules/@vitest/expect": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.3.tgz", - "integrity": "sha512-SbRCHU4qr91xguu+dH3RUdI5dC86zm8aZWydbp961aIR7G8OYNN6ZiayFuf9WAngRbFOfdrLHCGgXTj3GtoMRQ==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.5.tgz", + "integrity": "sha512-nNIOqupgZ4v5jWuQx2DSlHLEs7Q4Oh/7AYwNyE+k0UQzG7tSmjPXShUikn1mpNGzYEN2jJbTvLejwShMitovBA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "3.0.3", - "@vitest/utils": "3.0.3", + "@vitest/spy": "3.0.5", + "@vitest/utils": "3.0.5", "chai": "^5.1.2", "tinyrainbow": "^2.0.0" }, @@ -1740,13 +1740,13 @@ } }, "node_modules/@vitest/mocker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.3.tgz", - "integrity": "sha512-XT2XBc4AN9UdaxJAeIlcSZ0ILi/GzmG5G8XSly4gaiqIvPV3HMTSIDZWJVX6QRJ0PX1m+W8Cy0K9ByXNb/bPIA==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.5.tgz", + "integrity": "sha512-CLPNBFBIE7x6aEGbIjaQAX03ZZlBMaWwAjBdMkIf/cAn6xzLTiM3zYqO/WAbieEjsAZir6tO71mzeHZoodThvw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "3.0.3", + "@vitest/spy": "3.0.5", "estree-walker": "^3.0.3", "magic-string": "^0.30.17" }, @@ -1767,9 +1767,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.3.tgz", - "integrity": "sha512-gCrM9F7STYdsDoNjGgYXKPq4SkSxwwIU5nkaQvdUxiQ0EcNlez+PdKOVIsUJvh9P9IeIFmjn4IIREWblOBpP2Q==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.5.tgz", + "integrity": "sha512-CjUtdmpOcm4RVtB+up8r2vVDLR16Mgm/bYdkGFe3Yj/scRfCpbSi2W/BDSDcFK7ohw8UXvjMbOp9H4fByd/cOA==", "dev": true, "license": "MIT", "dependencies": { @@ -1780,38 +1780,38 @@ } }, "node_modules/@vitest/runner": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.3.tgz", - "integrity": "sha512-Rgi2kOAk5ZxWZlwPguRJFOBmWs6uvvyAAR9k3MvjRvYrG7xYvKChZcmnnpJCS98311CBDMqsW9MzzRFsj2gX3g==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.5.tgz", + "integrity": "sha512-BAiZFityFexZQi2yN4OX3OkJC6scwRo8EhRB0Z5HIGGgd2q+Nq29LgHU/+ovCtd0fOfXj5ZI6pwdlUmC5bpi8A==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "3.0.3", - "pathe": "^2.0.1" + "@vitest/utils": "3.0.5", + "pathe": "^2.0.2" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/snapshot": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.3.tgz", - "integrity": "sha512-kNRcHlI4txBGztuJfPEJ68VezlPAXLRT1u5UCx219TU3kOG2DplNxhWLwDf2h6emwmTPogzLnGVwP6epDaJN6Q==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.5.tgz", + "integrity": "sha512-GJPZYcd7v8QNUJ7vRvLDmRwl+a1fGg4T/54lZXe+UOGy47F9yUfE18hRCtXL5aHN/AONu29NGzIXSVFh9K0feA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.0.3", + "@vitest/pretty-format": "3.0.5", "magic-string": "^0.30.17", - "pathe": "^2.0.1" + "pathe": "^2.0.2" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/spy": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.3.tgz", - "integrity": "sha512-7/dgux8ZBbF7lEIKNnEqQlyRaER9nkAL9eTmdKJkDO3hS8p59ATGwKOCUDHcBLKr7h/oi/6hP+7djQk8049T2A==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.5.tgz", + "integrity": "sha512-5fOzHj0WbUNqPK6blI/8VzZdkBlQLnT25knX0r4dbZI9qoZDf3qAdjoMmDcLG5A83W6oUUFJgUd0EYBc2P5xqg==", "dev": true, "license": "MIT", "dependencies": { @@ -1822,13 +1822,13 @@ } }, "node_modules/@vitest/utils": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.3.tgz", - "integrity": "sha512-f+s8CvyzPtMFY1eZKkIHGhPsQgYo5qCm6O8KZoim9qm1/jT64qBgGpO5tHscNH6BzRHM+edLNOP+3vO8+8pE/A==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.5.tgz", + "integrity": "sha512-N9AX0NUoUtVwKwy21JtwzaqR5L5R5A99GAbrHfCCXK1lp593i/3AZAXhSP43wRQuxYsflrdzEfXZFo1reR1Nkg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.0.3", + "@vitest/pretty-format": "3.0.5", "loupe": "^3.1.2", "tinyrainbow": "^2.0.0" }, @@ -2334,9 +2334,9 @@ } }, "node_modules/eslint": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.18.0.tgz", - "integrity": "sha512-+waTfRWQlSbpt3KWE+CjrPPYnbq9kfZIYUqapc0uBXyjTp8aYXZDsUH16m39Ryq3NjAVP4tjuF7KaukeqoCoaA==", + "version": "9.19.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.19.0.tgz", + "integrity": "sha512-ug92j0LepKlbbEv6hD911THhoRHmbdXt2gX+VDABAW/Ir7D3nqKdv5Pf5vtlyY6HQMTEP2skXY43ueqTCWssEA==", "dev": true, "license": "MIT", "dependencies": { @@ -2345,7 +2345,7 @@ "@eslint/config-array": "^0.19.0", "@eslint/core": "^0.10.0", "@eslint/eslintrc": "^3.2.0", - "@eslint/js": "9.18.0", + "@eslint/js": "9.19.0", "@eslint/plugin-kit": "^0.2.5", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", @@ -2407,9 +2407,9 @@ } }, "node_modules/eslint-plugin-prettier": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.2.tgz", - "integrity": "sha512-1yI3/hf35wmlq66C8yOyrujQnel+v5l1Vop5Cl2I6ylyNTT1JbuUUnV3/41PzwTzcyDp/oF0jWE3HXvcH5AQOQ==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.3.tgz", + "integrity": "sha512-qJ+y0FfCp/mQYQ/vWQ3s7eUlFEL4PyKfAJxsnYTJ4YT73nsJBWqmEpFryxV9OeUiqmsTsYJ5Y+KDNaeP31wrRw==", "dev": true, "license": "MIT", "dependencies": { @@ -2685,9 +2685,9 @@ "dev": true }, "node_modules/fastq": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.18.0.tgz", - "integrity": "sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==", + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.0.tgz", + "integrity": "sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA==", "license": "ISC", "dependencies": { "reusify": "^1.0.4" @@ -3180,9 +3180,9 @@ "dev": true }, "node_modules/loupe": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.2.tgz", - "integrity": "sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.3.tgz", + "integrity": "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==", "dev": true, "license": "MIT" }, @@ -3285,9 +3285,9 @@ } }, "node_modules/mock-fs": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-5.4.1.tgz", - "integrity": "sha512-sz/Q8K1gXXXHR+qr0GZg2ysxCRr323kuN10O7CtQjraJsFDJ4SJ+0I5MzALz7aRp9lHk8Cc/YdsT95h9Ka1aFw==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-5.5.0.tgz", + "integrity": "sha512-d/P1M/RacgM3dB0sJ8rjeRNXxtapkPCUnMGmIN0ixJ16F/E4GUZCvWcSGfWGz8eaXYvn1s9baUwNjI4LOPEjiA==", "dev": true, "license": "MIT", "engines": { @@ -4166,9 +4166,9 @@ } }, "node_modules/ts-api-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.0.tgz", - "integrity": "sha512-xCt/TOAc+EOHS1XPnijD3/yzpH6qg2xppZO1YDqGoVsNXfQfzHpOdNuXwrwOU8u4ITXJyDCTyt8w5g1sZv9ynQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.1.tgz", + "integrity": "sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w==", "dev": true, "license": "MIT", "engines": { @@ -4288,15 +4288,15 @@ } }, "node_modules/vite": { - "version": "6.0.11", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.0.11.tgz", - "integrity": "sha512-4VL9mQPKoHy4+FE0NnRE/kbY51TOfaknxAjt3fJbGJxhIpBZiqVzlZDEesWWsuREXHwNdAoOFZ9MkPEVXczHwg==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.1.0.tgz", + "integrity": "sha512-RjjMipCKVoR4hVfPY6GQTgveinjNuyLw+qruksLDvA5ktI1150VmcMBKmQaEWJhg/j6Uaf6dNCNA0AfdzUb/hQ==", "dev": true, "license": "MIT", "dependencies": { "esbuild": "^0.24.2", - "postcss": "^8.4.49", - "rollup": "^4.23.0" + "postcss": "^8.5.1", + "rollup": "^4.30.1" }, "bin": { "vite": "bin/vite.js" @@ -4360,16 +4360,16 @@ } }, "node_modules/vite-node": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.3.tgz", - "integrity": "sha512-0sQcwhwAEw/UJGojbhOrnq3HtiZ3tC7BzpAa0lx3QaTX0S3YX70iGcik25UBdB96pmdwjyY2uyKNYruxCDmiEg==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.5.tgz", + "integrity": "sha512-02JEJl7SbtwSDJdYS537nU6l+ktdvcREfLksk/NDAqtdKWGqHl+joXzEubHROmS3E6pip+Xgu2tFezMu75jH7A==", "dev": true, "license": "MIT", "dependencies": { "cac": "^6.7.14", "debug": "^4.4.0", "es-module-lexer": "^1.6.0", - "pathe": "^2.0.1", + "pathe": "^2.0.2", "vite": "^5.0.0 || ^6.0.0" }, "bin": { @@ -4403,31 +4403,31 @@ } }, "node_modules/vitest": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.3.tgz", - "integrity": "sha512-dWdwTFUW9rcnL0LyF2F+IfvNQWB0w9DERySCk8VMG75F8k25C7LsZoh6XfCjPvcR8Nb+Lqi9JKr6vnzH7HSrpQ==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.5.tgz", + "integrity": "sha512-4dof+HvqONw9bvsYxtkfUp2uHsTN9bV2CZIi1pWgoFpL1Lld8LA1ka9q/ONSsoScAKG7NVGf2stJTI7XRkXb2Q==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/expect": "3.0.3", - "@vitest/mocker": "3.0.3", - "@vitest/pretty-format": "^3.0.3", - "@vitest/runner": "3.0.3", - "@vitest/snapshot": "3.0.3", - "@vitest/spy": "3.0.3", - "@vitest/utils": "3.0.3", + "@vitest/expect": "3.0.5", + "@vitest/mocker": "3.0.5", + "@vitest/pretty-format": "^3.0.5", + "@vitest/runner": "3.0.5", + "@vitest/snapshot": "3.0.5", + "@vitest/spy": "3.0.5", + "@vitest/utils": "3.0.5", "chai": "^5.1.2", "debug": "^4.4.0", "expect-type": "^1.1.0", "magic-string": "^0.30.17", - "pathe": "^2.0.1", + "pathe": "^2.0.2", "std-env": "^3.8.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", "tinypool": "^1.0.2", "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0", - "vite-node": "3.0.3", + "vite-node": "3.0.5", "why-is-node-running": "^2.3.0" }, "bin": { @@ -4441,9 +4441,10 @@ }, "peerDependencies": { "@edge-runtime/vm": "*", + "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "@vitest/browser": "3.0.3", - "@vitest/ui": "3.0.3", + "@vitest/browser": "3.0.5", + "@vitest/ui": "3.0.5", "happy-dom": "*", "jsdom": "*" }, @@ -4451,6 +4452,9 @@ "@edge-runtime/vm": { "optional": true }, + "@types/debug": { + "optional": true + }, "@types/node": { "optional": true }, diff --git a/e2e/package-lock.json b/e2e/package-lock.json index b077f716bd25a..73379bcdca050 100644 --- a/e2e/package-lock.json +++ b/e2e/package-lock.json @@ -361,9 +361,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz", + "integrity": "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==", "cpu": [ "ppc64" ], @@ -374,13 +374,13 @@ "aix" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.2.tgz", + "integrity": "sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==", "cpu": [ "arm" ], @@ -391,13 +391,13 @@ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.2.tgz", + "integrity": "sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==", "cpu": [ "arm64" ], @@ -408,13 +408,13 @@ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.2.tgz", + "integrity": "sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==", "cpu": [ "x64" ], @@ -425,13 +425,13 @@ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.2.tgz", + "integrity": "sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==", "cpu": [ "arm64" ], @@ -442,13 +442,13 @@ "darwin" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.2.tgz", + "integrity": "sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==", "cpu": [ "x64" ], @@ -459,13 +459,13 @@ "darwin" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.2.tgz", + "integrity": "sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==", "cpu": [ "arm64" ], @@ -476,13 +476,13 @@ "freebsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.2.tgz", + "integrity": "sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==", "cpu": [ "x64" ], @@ -493,13 +493,13 @@ "freebsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.2.tgz", + "integrity": "sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==", "cpu": [ "arm" ], @@ -510,13 +510,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.2.tgz", + "integrity": "sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==", "cpu": [ "arm64" ], @@ -527,13 +527,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.2.tgz", + "integrity": "sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==", "cpu": [ "ia32" ], @@ -544,13 +544,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.2.tgz", + "integrity": "sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==", "cpu": [ "loong64" ], @@ -561,13 +561,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.2.tgz", + "integrity": "sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==", "cpu": [ "mips64el" ], @@ -578,13 +578,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.2.tgz", + "integrity": "sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==", "cpu": [ "ppc64" ], @@ -595,13 +595,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.2.tgz", + "integrity": "sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==", "cpu": [ "riscv64" ], @@ -612,13 +612,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.2.tgz", + "integrity": "sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==", "cpu": [ "s390x" ], @@ -629,13 +629,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.2.tgz", + "integrity": "sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==", "cpu": [ "x64" ], @@ -646,13 +646,30 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.24.2.tgz", + "integrity": "sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.2.tgz", + "integrity": "sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==", "cpu": [ "x64" ], @@ -663,13 +680,30 @@ "netbsd" ], "engines": { - "node": ">=12" + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.2.tgz", + "integrity": "sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.2.tgz", + "integrity": "sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==", "cpu": [ "x64" ], @@ -680,13 +714,13 @@ "openbsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.2.tgz", + "integrity": "sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==", "cpu": [ "x64" ], @@ -697,13 +731,13 @@ "sunos" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.2.tgz", + "integrity": "sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==", "cpu": [ "arm64" ], @@ -714,13 +748,13 @@ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.2.tgz", + "integrity": "sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==", "cpu": [ "ia32" ], @@ -731,13 +765,13 @@ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.2.tgz", + "integrity": "sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==", "cpu": [ "x64" ], @@ -748,7 +782,7 @@ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@eslint-community/eslint-utils": { @@ -842,9 +876,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.18.0.tgz", - "integrity": "sha512-fK6L7rxcq6/z+AaQMtiFTkvbHkBLNlwyRxHpKawP0x3u9+NC6MQTnFW+AdpwC6gfHTW0051cokQgtTN2FqlxQA==", + "version": "9.19.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.19.0.tgz", + "integrity": "sha512-rbq9/g38qjfqFLOVPvwjIvFFdNziEC5S65jmjPw5r6A//QH+W91akh9irMwjDN8zKUTak6W9EsAv4m/7Wnw0UQ==", "dev": true, "license": "MIT", "engines": { @@ -1211,13 +1245,13 @@ } }, "node_modules/@playwright/test": { - "version": "1.49.1", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.49.1.tgz", - "integrity": "sha512-Ky+BVzPz8pL6PQxHqNRW1k3mIyv933LML7HktS8uik0bUXNCdPhoS/kLihiO1tMf/egaJb4IutXd7UywvXEW+g==", + "version": "1.50.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.50.1.tgz", + "integrity": "sha512-Jii3aBg+CEDpgnuDxEp/h7BimHcUTDlpEtce89xEumlJ5ef2hqepZ+PWp1DDpYC/VO9fmWVI1IlEaoI5fK9FXQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright": "1.49.1" + "playwright": "1.50.1" }, "bin": { "playwright": "cli.js" @@ -1227,9 +1261,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.27.3.tgz", - "integrity": "sha512-EzxVSkIvCFxUd4Mgm4xR9YXrcp976qVaHnqom/Tgm+vU79k4vV4eYTjmRvGfeoW8m9LVcsAy/lGjcgVegKEhLQ==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.6.tgz", + "integrity": "sha512-+GcCXtOQoWuC7hhX1P00LqjjIiS/iOouHXhMdiDSnq/1DGTox4SpUvO52Xm+div6+106r+TcvOeo/cxvyEyTgg==", "cpu": [ "arm" ], @@ -1241,9 +1275,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.27.3.tgz", - "integrity": "sha512-LJc5pDf1wjlt9o/Giaw9Ofl+k/vLUaYsE2zeQGH85giX2F+wn/Cg8b3c5CDP3qmVmeO5NzwVUzQQxwZvC2eQKw==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.6.tgz", + "integrity": "sha512-E8+2qCIjciYUnCa1AiVF1BkRgqIGW9KzJeesQqVfyRITGQN+dFuoivO0hnro1DjT74wXLRZ7QF8MIbz+luGaJA==", "cpu": [ "arm64" ], @@ -1255,9 +1289,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.27.3.tgz", - "integrity": "sha512-OuRysZ1Mt7wpWJ+aYKblVbJWtVn3Cy52h8nLuNSzTqSesYw1EuN6wKp5NW/4eSre3mp12gqFRXOKTcN3AI3LqA==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.6.tgz", + "integrity": "sha512-z9Ib+OzqN3DZEjX7PDQMHEhtF+t6Mi2z/ueChQPLS/qUMKY7Ybn5A2ggFoKRNRh1q1T03YTQfBTQCJZiepESAg==", "cpu": [ "arm64" ], @@ -1269,9 +1303,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.27.3.tgz", - "integrity": "sha512-xW//zjJMlJs2sOrCmXdB4d0uiilZsOdlGQIC/jjmMWT47lkLLoB1nsNhPUcnoqyi5YR6I4h+FjBpILxbEy8JRg==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.6.tgz", + "integrity": "sha512-PShKVY4u0FDAR7jskyFIYVyHEPCPnIQY8s5OcXkdU8mz3Y7eXDJPdyM/ZWjkYdR2m0izD9HHWA8sGcXn+Qrsyg==", "cpu": [ "x64" ], @@ -1283,9 +1317,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.27.3.tgz", - "integrity": "sha512-58E0tIcwZ+12nK1WiLzHOD8I0d0kdrY/+o7yFVPRHuVGY3twBwzwDdTIBGRxLmyjciMYl1B/U515GJy+yn46qw==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.6.tgz", + "integrity": "sha512-YSwyOqlDAdKqs0iKuqvRHLN4SrD2TiswfoLfvYXseKbL47ht1grQpq46MSiQAx6rQEN8o8URtpXARCpqabqxGQ==", "cpu": [ "arm64" ], @@ -1297,9 +1331,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.27.3.tgz", - "integrity": "sha512-78fohrpcVwTLxg1ZzBMlwEimoAJmY6B+5TsyAZ3Vok7YabRBUvjYTsRXPTjGEvv/mfgVBepbW28OlMEz4w8wGA==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.6.tgz", + "integrity": "sha512-HEP4CgPAY1RxXwwL5sPFv6BBM3tVeLnshF03HMhJYCNc6kvSqBgTMmsEjb72RkZBAWIqiPUyF1JpEBv5XT9wKQ==", "cpu": [ "x64" ], @@ -1311,9 +1345,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.27.3.tgz", - "integrity": "sha512-h2Ay79YFXyQi+QZKo3ISZDyKaVD7uUvukEHTOft7kh00WF9mxAaxZsNs3o/eukbeKuH35jBvQqrT61fzKfAB/Q==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.6.tgz", + "integrity": "sha512-88fSzjC5xeH9S2Vg3rPgXJULkHcLYMkh8faix8DX4h4TIAL65ekwuQMA/g2CXq8W+NJC43V6fUpYZNjaX3+IIg==", "cpu": [ "arm" ], @@ -1325,9 +1359,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.27.3.tgz", - "integrity": "sha512-Sv2GWmrJfRY57urktVLQ0VKZjNZGogVtASAgosDZ1aUB+ykPxSi3X1nWORL5Jk0sTIIwQiPH7iE3BMi9zGWfkg==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.6.tgz", + "integrity": "sha512-wM4ztnutBqYFyvNeR7Av+reWI/enK9tDOTKNF+6Kk2Q96k9bwhDDOlnCUNRPvromlVXo04riSliMBs/Z7RteEg==", "cpu": [ "arm" ], @@ -1339,9 +1373,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.27.3.tgz", - "integrity": "sha512-FPoJBLsPW2bDNWjSrwNuTPUt30VnfM8GPGRoLCYKZpPx0xiIEdFip3dH6CqgoT0RnoGXptaNziM0WlKgBc+OWQ==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.6.tgz", + "integrity": "sha512-9RyprECbRa9zEjXLtvvshhw4CMrRa3K+0wcp3KME0zmBe1ILmvcVHnypZ/aIDXpRyfhSYSuN4EPdCCj5Du8FIA==", "cpu": [ "arm64" ], @@ -1353,9 +1387,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.27.3.tgz", - "integrity": "sha512-TKxiOvBorYq4sUpA0JT+Fkh+l+G9DScnG5Dqx7wiiqVMiRSkzTclP35pE6eQQYjP4Gc8yEkJGea6rz4qyWhp3g==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.6.tgz", + "integrity": "sha512-qTmklhCTyaJSB05S+iSovfo++EwnIEZxHkzv5dep4qoszUMX5Ca4WM4zAVUMbfdviLgCSQOu5oU8YoGk1s6M9Q==", "cpu": [ "arm64" ], @@ -1366,10 +1400,24 @@ "linux" ] }, + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.34.6.tgz", + "integrity": "sha512-4Qmkaps9yqmpjY5pvpkfOerYgKNUGzQpFxV6rnS7c/JfYbDSU0y6WpbbredB5cCpLFGJEqYX40WUmxMkwhWCjw==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.27.3.tgz", - "integrity": "sha512-v2M/mPvVUKVOKITa0oCFksnQQ/TqGrT+yD0184/cWHIu0LoIuYHwox0Pm3ccXEz8cEQDLk6FPKd1CCm+PlsISw==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.34.6.tgz", + "integrity": "sha512-Zsrtux3PuaxuBTX/zHdLaFmcofWGzaWW1scwLU3ZbW/X+hSsFbz9wDIp6XvnT7pzYRl9MezWqEqKy7ssmDEnuQ==", "cpu": [ "ppc64" ], @@ -1381,9 +1429,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.27.3.tgz", - "integrity": "sha512-LdrI4Yocb1a/tFVkzmOE5WyYRgEBOyEhWYJe4gsDWDiwnjYKjNs7PS6SGlTDB7maOHF4kxevsuNBl2iOcj3b4A==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.6.tgz", + "integrity": "sha512-aK+Zp+CRM55iPrlyKiU3/zyhgzWBxLVrw2mwiQSYJRobCURb781+XstzvA8Gkjg/hbdQFuDw44aUOxVQFycrAg==", "cpu": [ "riscv64" ], @@ -1395,9 +1443,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.27.3.tgz", - "integrity": "sha512-d4wVu6SXij/jyiwPvI6C4KxdGzuZOvJ6y9VfrcleHTwo68fl8vZC5ZYHsCVPUi4tndCfMlFniWgwonQ5CUpQcA==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.6.tgz", + "integrity": "sha512-WoKLVrY9ogmaYPXwTH326+ErlCIgMmsoRSx6bO+l68YgJnlOXhygDYSZe/qbUJCSiCiZAQ+tKm88NcWuUXqOzw==", "cpu": [ "s390x" ], @@ -1409,9 +1457,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.27.3.tgz", - "integrity": "sha512-/6bn6pp1fsCGEY5n3yajmzZQAh+mW4QPItbiWxs69zskBzJuheb3tNynEjL+mKOsUSFK11X4LYF2BwwXnzWleA==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.6.tgz", + "integrity": "sha512-Sht4aFvmA4ToHd2vFzwMFaQCiYm2lDFho5rPcvPBT5pCdC+GwHG6CMch4GQfmWTQ1SwRKS0dhDYb54khSrjDWw==", "cpu": [ "x64" ], @@ -1423,9 +1471,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.27.3.tgz", - "integrity": "sha512-nBXOfJds8OzUT1qUreT/en3eyOXd2EH5b0wr2bVB5999qHdGKkzGzIyKYaKj02lXk6wpN71ltLIaQpu58YFBoQ==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.6.tgz", + "integrity": "sha512-zmmpOQh8vXc2QITsnCiODCDGXFC8LMi64+/oPpPx5qz3pqv0s6x46ps4xoycfUiVZps5PFn1gksZzo4RGTKT+A==", "cpu": [ "x64" ], @@ -1437,9 +1485,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.27.3.tgz", - "integrity": "sha512-ogfbEVQgIZOz5WPWXF2HVb6En+kWzScuxJo/WdQTqEgeyGkaa2ui5sQav9Zkr7bnNCLK48uxmmK0TySm22eiuw==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.6.tgz", + "integrity": "sha512-3/q1qUsO/tLqGBaD4uXsB6coVGB3usxw3qyeVb59aArCgedSF66MPdgRStUd7vbZOsko/CgVaY5fo2vkvPLWiA==", "cpu": [ "arm64" ], @@ -1451,9 +1499,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.27.3.tgz", - "integrity": "sha512-ecE36ZBMLINqiTtSNQ1vzWc5pXLQHlf/oqGp/bSbi7iedcjcNb6QbCBNG73Euyy2C+l/fn8qKWEwxr+0SSfs3w==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.6.tgz", + "integrity": "sha512-oLHxuyywc6efdKVTxvc0135zPrRdtYVjtVD5GUm55I3ODxhU/PwkQFD97z16Xzxa1Fz0AEe4W/2hzRtd+IfpOA==", "cpu": [ "ia32" ], @@ -1465,9 +1513,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.27.3.tgz", - "integrity": "sha512-vliZLrDmYKyaUoMzEbMTg2JkerfBjn03KmAw9CykO0Zzkzoyd7o3iZNam/TpyWNjNT+Cz2iO3P9Smv2wgrR+Eg==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.6.tgz", + "integrity": "sha512-0PVwmgzZ8+TZ9oGBmdZoQVXflbvuwzN/HRclujpl4N/q3i+y0lqLw8n1bXA8ru3sApDjlmONaNAuYr38y1Kr9w==", "cpu": [ "x64" ], @@ -1693,9 +1741,9 @@ } }, "node_modules/@types/pg": { - "version": "8.11.10", - "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.11.10.tgz", - "integrity": "sha512-LczQUW4dbOQzsH2RQ5qoeJ6qJPdrcM/DcMLoqWQkMLMsq83J5lAX3LXjdkWdpscFy67JSOWDnh7Ny/sPFykmkg==", + "version": "8.11.11", + "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.11.11.tgz", + "integrity": "sha512-kGT1qKM8wJQ5qlawUrEkXgvMSXoV213KfMGXcwfDwUIfUHXqXYXOfS1nE1LINRJVVVx5wCm70XnFlMHaIcQAfw==", "dev": true, "license": "MIT", "dependencies": { @@ -1830,21 +1878,21 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.20.0.tgz", - "integrity": "sha512-naduuphVw5StFfqp4Gq4WhIBE2gN1GEmMUExpJYknZJdRnc+2gDzB8Z3+5+/Kv33hPQRDGzQO/0opHE72lZZ6A==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.23.0.tgz", + "integrity": "sha512-vBz65tJgRrA1Q5gWlRfvoH+w943dq9K1p1yDBY2pc+a1nbBLZp7fB9+Hk8DaALUbzjqlMfgaqlVPT1REJdkt/w==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.20.0", - "@typescript-eslint/type-utils": "8.20.0", - "@typescript-eslint/utils": "8.20.0", - "@typescript-eslint/visitor-keys": "8.20.0", + "@typescript-eslint/scope-manager": "8.23.0", + "@typescript-eslint/type-utils": "8.23.0", + "@typescript-eslint/utils": "8.23.0", + "@typescript-eslint/visitor-keys": "8.23.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", - "ts-api-utils": "^2.0.0" + "ts-api-utils": "^2.0.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1860,16 +1908,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.20.0.tgz", - "integrity": "sha512-gKXG7A5HMyjDIedBi6bUrDcun8GIjnI8qOwVLiY3rx6T/sHP/19XLJOnIq/FgQvWLHja5JN/LSE7eklNBr612g==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.23.0.tgz", + "integrity": "sha512-h2lUByouOXFAlMec2mILeELUbME5SZRN/7R9Cw2RD2lRQQY08MWMM+PmVVKKJNK1aIwqTo9t/0CvOxwPbRIE2Q==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.20.0", - "@typescript-eslint/types": "8.20.0", - "@typescript-eslint/typescript-estree": "8.20.0", - "@typescript-eslint/visitor-keys": "8.20.0", + "@typescript-eslint/scope-manager": "8.23.0", + "@typescript-eslint/types": "8.23.0", + "@typescript-eslint/typescript-estree": "8.23.0", + "@typescript-eslint/visitor-keys": "8.23.0", "debug": "^4.3.4" }, "engines": { @@ -1885,14 +1933,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.20.0.tgz", - "integrity": "sha512-J7+VkpeGzhOt3FeG1+SzhiMj9NzGD/M6KoGn9f4dbz3YzK9hvbhVTmLj/HiTp9DazIzJ8B4XcM80LrR9Dm1rJw==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.23.0.tgz", + "integrity": "sha512-OGqo7+dXHqI7Hfm+WqkZjKjsiRtFUQHPdGMXzk5mYXhJUedO7e/Y7i8AK3MyLMgZR93TX4bIzYrfyVjLC+0VSw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.20.0", - "@typescript-eslint/visitor-keys": "8.20.0" + "@typescript-eslint/types": "8.23.0", + "@typescript-eslint/visitor-keys": "8.23.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1903,16 +1951,16 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.20.0.tgz", - "integrity": "sha512-bPC+j71GGvA7rVNAHAtOjbVXbLN5PkwqMvy1cwGeaxUoRQXVuKCebRoLzm+IPW/NtFFpstn1ummSIasD5t60GA==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.23.0.tgz", + "integrity": "sha512-iIuLdYpQWZKbiH+RkCGc6iu+VwscP5rCtQ1lyQ7TYuKLrcZoeJVpcLiG8DliXVkUxirW/PWlmS+d6yD51L9jvA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.20.0", - "@typescript-eslint/utils": "8.20.0", + "@typescript-eslint/typescript-estree": "8.23.0", + "@typescript-eslint/utils": "8.23.0", "debug": "^4.3.4", - "ts-api-utils": "^2.0.0" + "ts-api-utils": "^2.0.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1927,9 +1975,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.20.0.tgz", - "integrity": "sha512-cqaMiY72CkP+2xZRrFt3ExRBu0WmVitN/rYPZErA80mHjHx/Svgp8yfbzkJmDoQ/whcytOPO9/IZXnOc+wigRA==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.23.0.tgz", + "integrity": "sha512-1sK4ILJbCmZOTt9k4vkoulT6/y5CHJ1qUYxqpF1K/DBAd8+ZUL4LlSCxOssuH5m4rUaaN0uS0HlVPvd45zjduQ==", "dev": true, "license": "MIT", "engines": { @@ -1941,20 +1989,20 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.20.0.tgz", - "integrity": "sha512-Y7ncuy78bJqHI35NwzWol8E0X7XkRVS4K4P4TCyzWkOJih5NDvtoRDW4Ba9YJJoB2igm9yXDdYI/+fkiiAxPzA==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.23.0.tgz", + "integrity": "sha512-LcqzfipsB8RTvH8FX24W4UUFk1bl+0yTOf9ZA08XngFwMg4Kj8A+9hwz8Cr/ZS4KwHrmo9PJiLZkOt49vPnuvQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.20.0", - "@typescript-eslint/visitor-keys": "8.20.0", + "@typescript-eslint/types": "8.23.0", + "@typescript-eslint/visitor-keys": "8.23.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", - "ts-api-utils": "^2.0.0" + "ts-api-utils": "^2.0.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1994,16 +2042,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.20.0.tgz", - "integrity": "sha512-dq70RUw6UK9ei7vxc4KQtBRk7qkHZv447OUZ6RPQMQl71I3NZxQJX/f32Smr+iqWrB02pHKn2yAdHBb0KNrRMA==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.23.0.tgz", + "integrity": "sha512-uB/+PSo6Exu02b5ZEiVtmY6RVYO7YU5xqgzTIVZwTHvvK3HsL8tZZHFaTLFtRG3CsV4A5mhOv+NZx5BlhXPyIA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.20.0", - "@typescript-eslint/types": "8.20.0", - "@typescript-eslint/typescript-estree": "8.20.0" + "@typescript-eslint/scope-manager": "8.23.0", + "@typescript-eslint/types": "8.23.0", + "@typescript-eslint/typescript-estree": "8.23.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2018,13 +2066,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.20.0.tgz", - "integrity": "sha512-v/BpkeeYAsPkKCkR8BDwcno0llhzWVqPOamQrAEMdpZav2Y9OVjd9dwJyBLJWwf335B5DmlifECIkZRJCaGaHA==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.23.0.tgz", + "integrity": "sha512-oWWhcWDLwDfu++BGTZcmXWqpwtkwb5o7fxUIGksMQQDSdPW9prsSnfIOZMlsj4vBOSrcnjIUZMiIjODgGosFhQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.20.0", + "@typescript-eslint/types": "8.23.0", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -2049,9 +2097,9 @@ } }, "node_modules/@vitest/coverage-v8": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.0.3.tgz", - "integrity": "sha512-uVbJ/xhImdNtzPnLyxCZJMTeTIYdgcC2nWtBBBpR1H6z0w8m7D+9/zrDIx2nNxgMg9r+X8+RY2qVpUDeW2b3nw==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.0.5.tgz", + "integrity": "sha512-zOOWIsj5fHh3jjGwQg+P+J1FW3s4jBu1Zqga0qW60yutsBtqEqNEJKWYh7cYn1yGD+1bdPsPdC/eL4eVK56xMg==", "dev": true, "license": "MIT", "dependencies": { @@ -2072,8 +2120,8 @@ "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "@vitest/browser": "3.0.3", - "vitest": "3.0.3" + "@vitest/browser": "3.0.5", + "vitest": "3.0.5" }, "peerDependenciesMeta": { "@vitest/browser": { @@ -2100,14 +2148,14 @@ } }, "node_modules/@vitest/expect": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.3.tgz", - "integrity": "sha512-SbRCHU4qr91xguu+dH3RUdI5dC86zm8aZWydbp961aIR7G8OYNN6ZiayFuf9WAngRbFOfdrLHCGgXTj3GtoMRQ==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.5.tgz", + "integrity": "sha512-nNIOqupgZ4v5jWuQx2DSlHLEs7Q4Oh/7AYwNyE+k0UQzG7tSmjPXShUikn1mpNGzYEN2jJbTvLejwShMitovBA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "3.0.3", - "@vitest/utils": "3.0.3", + "@vitest/spy": "3.0.5", + "@vitest/utils": "3.0.5", "chai": "^5.1.2", "tinyrainbow": "^2.0.0" }, @@ -2116,13 +2164,13 @@ } }, "node_modules/@vitest/mocker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.3.tgz", - "integrity": "sha512-XT2XBc4AN9UdaxJAeIlcSZ0ILi/GzmG5G8XSly4gaiqIvPV3HMTSIDZWJVX6QRJ0PX1m+W8Cy0K9ByXNb/bPIA==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.5.tgz", + "integrity": "sha512-CLPNBFBIE7x6aEGbIjaQAX03ZZlBMaWwAjBdMkIf/cAn6xzLTiM3zYqO/WAbieEjsAZir6tO71mzeHZoodThvw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "3.0.3", + "@vitest/spy": "3.0.5", "estree-walker": "^3.0.3", "magic-string": "^0.30.17" }, @@ -2143,9 +2191,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.3.tgz", - "integrity": "sha512-gCrM9F7STYdsDoNjGgYXKPq4SkSxwwIU5nkaQvdUxiQ0EcNlez+PdKOVIsUJvh9P9IeIFmjn4IIREWblOBpP2Q==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.5.tgz", + "integrity": "sha512-CjUtdmpOcm4RVtB+up8r2vVDLR16Mgm/bYdkGFe3Yj/scRfCpbSi2W/BDSDcFK7ohw8UXvjMbOp9H4fByd/cOA==", "dev": true, "license": "MIT", "dependencies": { @@ -2156,38 +2204,38 @@ } }, "node_modules/@vitest/runner": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.3.tgz", - "integrity": "sha512-Rgi2kOAk5ZxWZlwPguRJFOBmWs6uvvyAAR9k3MvjRvYrG7xYvKChZcmnnpJCS98311CBDMqsW9MzzRFsj2gX3g==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.5.tgz", + "integrity": "sha512-BAiZFityFexZQi2yN4OX3OkJC6scwRo8EhRB0Z5HIGGgd2q+Nq29LgHU/+ovCtd0fOfXj5ZI6pwdlUmC5bpi8A==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "3.0.3", - "pathe": "^2.0.1" + "@vitest/utils": "3.0.5", + "pathe": "^2.0.2" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/snapshot": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.3.tgz", - "integrity": "sha512-kNRcHlI4txBGztuJfPEJ68VezlPAXLRT1u5UCx219TU3kOG2DplNxhWLwDf2h6emwmTPogzLnGVwP6epDaJN6Q==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.5.tgz", + "integrity": "sha512-GJPZYcd7v8QNUJ7vRvLDmRwl+a1fGg4T/54lZXe+UOGy47F9yUfE18hRCtXL5aHN/AONu29NGzIXSVFh9K0feA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.0.3", + "@vitest/pretty-format": "3.0.5", "magic-string": "^0.30.17", - "pathe": "^2.0.1" + "pathe": "^2.0.2" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/spy": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.3.tgz", - "integrity": "sha512-7/dgux8ZBbF7lEIKNnEqQlyRaER9nkAL9eTmdKJkDO3hS8p59ATGwKOCUDHcBLKr7h/oi/6hP+7djQk8049T2A==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.5.tgz", + "integrity": "sha512-5fOzHj0WbUNqPK6blI/8VzZdkBlQLnT25knX0r4dbZI9qoZDf3qAdjoMmDcLG5A83W6oUUFJgUd0EYBc2P5xqg==", "dev": true, "license": "MIT", "dependencies": { @@ -2198,13 +2246,13 @@ } }, "node_modules/@vitest/utils": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.3.tgz", - "integrity": "sha512-f+s8CvyzPtMFY1eZKkIHGhPsQgYo5qCm6O8KZoim9qm1/jT64qBgGpO5tHscNH6BzRHM+edLNOP+3vO8+8pE/A==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.5.tgz", + "integrity": "sha512-N9AX0NUoUtVwKwy21JtwzaqR5L5R5A99GAbrHfCCXK1lp593i/3AZAXhSP43wRQuxYsflrdzEfXZFo1reR1Nkg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.0.3", + "@vitest/pretty-format": "3.0.5", "loupe": "^3.1.2", "tinyrainbow": "^2.0.0" }, @@ -3036,9 +3084,9 @@ "license": "MIT" }, "node_modules/esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.2.tgz", + "integrity": "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -3046,32 +3094,34 @@ "esbuild": "bin/esbuild" }, "engines": { - "node": ">=12" + "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" + "@esbuild/aix-ppc64": "0.24.2", + "@esbuild/android-arm": "0.24.2", + "@esbuild/android-arm64": "0.24.2", + "@esbuild/android-x64": "0.24.2", + "@esbuild/darwin-arm64": "0.24.2", + "@esbuild/darwin-x64": "0.24.2", + "@esbuild/freebsd-arm64": "0.24.2", + "@esbuild/freebsd-x64": "0.24.2", + "@esbuild/linux-arm": "0.24.2", + "@esbuild/linux-arm64": "0.24.2", + "@esbuild/linux-ia32": "0.24.2", + "@esbuild/linux-loong64": "0.24.2", + "@esbuild/linux-mips64el": "0.24.2", + "@esbuild/linux-ppc64": "0.24.2", + "@esbuild/linux-riscv64": "0.24.2", + "@esbuild/linux-s390x": "0.24.2", + "@esbuild/linux-x64": "0.24.2", + "@esbuild/netbsd-arm64": "0.24.2", + "@esbuild/netbsd-x64": "0.24.2", + "@esbuild/openbsd-arm64": "0.24.2", + "@esbuild/openbsd-x64": "0.24.2", + "@esbuild/sunos-x64": "0.24.2", + "@esbuild/win32-arm64": "0.24.2", + "@esbuild/win32-ia32": "0.24.2", + "@esbuild/win32-x64": "0.24.2" } }, "node_modules/escalade": { @@ -3103,9 +3153,9 @@ } }, "node_modules/eslint": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.18.0.tgz", - "integrity": "sha512-+waTfRWQlSbpt3KWE+CjrPPYnbq9kfZIYUqapc0uBXyjTp8aYXZDsUH16m39Ryq3NjAVP4tjuF7KaukeqoCoaA==", + "version": "9.19.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.19.0.tgz", + "integrity": "sha512-ug92j0LepKlbbEv6hD911THhoRHmbdXt2gX+VDABAW/Ir7D3nqKdv5Pf5vtlyY6HQMTEP2skXY43ueqTCWssEA==", "dev": true, "license": "MIT", "dependencies": { @@ -3114,7 +3164,7 @@ "@eslint/config-array": "^0.19.0", "@eslint/core": "^0.10.0", "@eslint/eslintrc": "^3.2.0", - "@eslint/js": "9.18.0", + "@eslint/js": "9.19.0", "@eslint/plugin-kit": "^0.2.5", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", @@ -3176,9 +3226,9 @@ } }, "node_modules/eslint-plugin-prettier": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.2.tgz", - "integrity": "sha512-1yI3/hf35wmlq66C8yOyrujQnel+v5l1Vop5Cl2I6ylyNTT1JbuUUnV3/41PzwTzcyDp/oF0jWE3HXvcH5AQOQ==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.3.tgz", + "integrity": "sha512-qJ+y0FfCp/mQYQ/vWQ3s7eUlFEL4PyKfAJxsnYTJ4YT73nsJBWqmEpFryxV9OeUiqmsTsYJ5Y+KDNaeP31wrRw==", "dev": true, "license": "MIT", "dependencies": { @@ -3491,9 +3541,9 @@ "dev": true }, "node_modules/fastq": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.18.0.tgz", - "integrity": "sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==", + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.0.tgz", + "integrity": "sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA==", "dev": true, "license": "ISC", "dependencies": { @@ -4292,10 +4342,11 @@ } }, "node_modules/jsesc": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", - "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", "dev": true, + "license": "MIT", "bin": { "jsesc": "bin/jsesc" }, @@ -4476,9 +4527,9 @@ "dev": true }, "node_modules/loupe": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.2.tgz", - "integrity": "sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.3.tgz", + "integrity": "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==", "dev": true, "license": "MIT" }, @@ -4709,9 +4760,9 @@ "license": "MIT" }, "node_modules/nanoid": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.8.tgz", - "integrity": "sha512-TcJPw+9RV9dibz1hHUzlLVy8N4X9TnwirAjrU08Juo6BNKggzVfP2ZJ/3ZUSq15Xl5i85i+Z89XBO90pB2PghQ==", + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.9.tgz", + "integrity": "sha512-Aooyr6MXU6HpvvWXKoVoXwKMs/KyVakWwg7xQfv5/S/RIgJMy0Ifa45H9qqYy7pTCszrHzP21Uk4PZq2HpEM8Q==", "dev": true, "funding": [ { @@ -4869,21 +4920,21 @@ "dev": true }, "node_modules/oidc-provider": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/oidc-provider/-/oidc-provider-8.6.0.tgz", - "integrity": "sha512-LTzQza+KA72fFWe/70ttjTpCPvwZRoaydPFY2izNfQjo6u33lFOzJeqA9Q0TblTShkaH56ChoE2KdMYIQlNHdw==", + "version": "8.6.1", + "resolved": "https://registry.npmjs.org/oidc-provider/-/oidc-provider-8.6.1.tgz", + "integrity": "sha512-wJ+nhwkCjRtQiwJKACjjV8FAIn7QXGDc1UOAE5WW0i8fsqN1GgXi42S/ccOxEx/JV3tyVLEwIipAvJNsJ/3djA==", "dev": true, "license": "MIT", "dependencies": { "@koa/cors": "^5.0.0", "@koa/router": "^13.1.0", - "debug": "^4.3.7", + "debug": "^4.4.0", "eta": "^3.5.0", "got": "^13.0.0", "jose": "^5.9.6", - "jsesc": "^3.0.2", + "jsesc": "^3.1.0", "koa": "^2.15.3", - "nanoid": "^5.0.8", + "nanoid": "^5.0.9", "object-hash": "^3.0.0", "oidc-token-hash": "^5.0.3", "quick-lru": "^7.0.0", @@ -4893,6 +4944,24 @@ "url": "https://github.com/sponsors/panva" } }, + "node_modules/oidc-provider/node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, "node_modules/oidc-token-hash": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/oidc-token-hash/-/oidc-token-hash-5.0.3.tgz", @@ -5246,13 +5315,13 @@ } }, "node_modules/playwright": { - "version": "1.49.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.49.1.tgz", - "integrity": "sha512-VYL8zLoNTBxVOrJBbDuRgDWa3i+mfQgDTrL8Ah9QXZ7ax4Dsj0MSq5bYgytRnDVVe+njoKnfsYkH3HzqVj5UZA==", + "version": "1.50.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.50.1.tgz", + "integrity": "sha512-G8rwsOQJ63XG6BbKj2w5rHeavFjy5zynBA9zsJMMtBoe/Uf757oG12NXz6e6OirF7RCrTVAKFXbLmn1RbL7Qaw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.49.1" + "playwright-core": "1.50.1" }, "bin": { "playwright": "cli.js" @@ -5265,9 +5334,9 @@ } }, "node_modules/playwright-core": { - "version": "1.49.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.49.1.tgz", - "integrity": "sha512-BzmpVcs4kE2CH15rWfzpjzVGhWERJfmnXmniSyKeRZUs9Ws65m+RGIi7mjJK/euCegfn3i7jvqWeWyHe9y3Vgg==", + "version": "1.50.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.50.1.tgz", + "integrity": "sha512-ra9fsNWayuYumt+NiM069M6OkcRb1FZSK8bgi66AtpFoWkg2+y0bJSNmkFrWhMbEBbVKC/EruAHH3g0zmtwGmQ==", "dev": true, "license": "Apache-2.0", "bin": { @@ -5296,9 +5365,9 @@ } }, "node_modules/postcss": { - "version": "8.4.49", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", - "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", + "version": "8.5.2", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.2.tgz", + "integrity": "sha512-MjOadfU3Ys9KYoX0AdkBlFEF1Vx37uCCeN4ZHnmwm9FfpbsGWMZeBLMmmpY+6Ocqod7mkdZ0DT31OlbsFrLlkA==", "dev": true, "funding": [ { @@ -5316,7 +5385,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.7", + "nanoid": "^3.3.8", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -5325,9 +5394,9 @@ } }, "node_modules/postcss/node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", + "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", "dev": true, "funding": [ { @@ -5735,9 +5804,9 @@ } }, "node_modules/rollup": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.27.3.tgz", - "integrity": "sha512-SLsCOnlmGt9VoZ9Ek8yBK8tAdmPHeppkw+Xa7yDlCEhDTvwYei03JlWo1fdc7YTfLZ4tD8riJCUyAgTbszk1fQ==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.6.tgz", + "integrity": "sha512-wc2cBWqJgkU3Iz5oztRkQbfVkbxoz5EhnCGOrnJvnLnQ7O0WhQUYyv18qQI79O8L7DdHrrlJNeCHd4VGpnaXKQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5751,24 +5820,25 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.27.3", - "@rollup/rollup-android-arm64": "4.27.3", - "@rollup/rollup-darwin-arm64": "4.27.3", - "@rollup/rollup-darwin-x64": "4.27.3", - "@rollup/rollup-freebsd-arm64": "4.27.3", - "@rollup/rollup-freebsd-x64": "4.27.3", - "@rollup/rollup-linux-arm-gnueabihf": "4.27.3", - "@rollup/rollup-linux-arm-musleabihf": "4.27.3", - "@rollup/rollup-linux-arm64-gnu": "4.27.3", - "@rollup/rollup-linux-arm64-musl": "4.27.3", - "@rollup/rollup-linux-powerpc64le-gnu": "4.27.3", - "@rollup/rollup-linux-riscv64-gnu": "4.27.3", - "@rollup/rollup-linux-s390x-gnu": "4.27.3", - "@rollup/rollup-linux-x64-gnu": "4.27.3", - "@rollup/rollup-linux-x64-musl": "4.27.3", - "@rollup/rollup-win32-arm64-msvc": "4.27.3", - "@rollup/rollup-win32-ia32-msvc": "4.27.3", - "@rollup/rollup-win32-x64-msvc": "4.27.3", + "@rollup/rollup-android-arm-eabi": "4.34.6", + "@rollup/rollup-android-arm64": "4.34.6", + "@rollup/rollup-darwin-arm64": "4.34.6", + "@rollup/rollup-darwin-x64": "4.34.6", + "@rollup/rollup-freebsd-arm64": "4.34.6", + "@rollup/rollup-freebsd-x64": "4.34.6", + "@rollup/rollup-linux-arm-gnueabihf": "4.34.6", + "@rollup/rollup-linux-arm-musleabihf": "4.34.6", + "@rollup/rollup-linux-arm64-gnu": "4.34.6", + "@rollup/rollup-linux-arm64-musl": "4.34.6", + "@rollup/rollup-linux-loongarch64-gnu": "4.34.6", + "@rollup/rollup-linux-powerpc64le-gnu": "4.34.6", + "@rollup/rollup-linux-riscv64-gnu": "4.34.6", + "@rollup/rollup-linux-s390x-gnu": "4.34.6", + "@rollup/rollup-linux-x64-gnu": "4.34.6", + "@rollup/rollup-linux-x64-musl": "4.34.6", + "@rollup/rollup-win32-arm64-msvc": "4.34.6", + "@rollup/rollup-win32-ia32-msvc": "4.34.6", + "@rollup/rollup-win32-x64-msvc": "4.34.6", "fsevents": "~2.3.2" } }, @@ -6343,9 +6413,9 @@ "dev": true }, "node_modules/ts-api-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.0.tgz", - "integrity": "sha512-xCt/TOAc+EOHS1XPnijD3/yzpH6qg2xppZO1YDqGoVsNXfQfzHpOdNuXwrwOU8u4ITXJyDCTyt8w5g1sZv9ynQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.1.tgz", + "integrity": "sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w==", "dev": true, "license": "MIT", "engines": { @@ -6505,21 +6575,21 @@ } }, "node_modules/vite": { - "version": "5.4.11", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.11.tgz", - "integrity": "sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.1.0.tgz", + "integrity": "sha512-RjjMipCKVoR4hVfPY6GQTgveinjNuyLw+qruksLDvA5ktI1150VmcMBKmQaEWJhg/j6Uaf6dNCNA0AfdzUb/hQ==", "dev": true, "license": "MIT", "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.43", - "rollup": "^4.20.0" + "esbuild": "^0.24.2", + "postcss": "^8.5.1", + "rollup": "^4.30.1" }, "bin": { "vite": "bin/vite.js" }, "engines": { - "node": "^18.0.0 || >=20.0.0" + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" }, "funding": { "url": "https://github.com/vitejs/vite?sponsor=1" @@ -6528,19 +6598,25 @@ "fsevents": "~2.3.3" }, "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", - "terser": "^5.4.0" + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" }, "peerDependenciesMeta": { "@types/node": { "optional": true }, + "jiti": { + "optional": true + }, "less": { "optional": true }, @@ -6561,20 +6637,26 @@ }, "terser": { "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true } } }, "node_modules/vite-node": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.3.tgz", - "integrity": "sha512-0sQcwhwAEw/UJGojbhOrnq3HtiZ3tC7BzpAa0lx3QaTX0S3YX70iGcik25UBdB96pmdwjyY2uyKNYruxCDmiEg==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.5.tgz", + "integrity": "sha512-02JEJl7SbtwSDJdYS537nU6l+ktdvcREfLksk/NDAqtdKWGqHl+joXzEubHROmS3E6pip+Xgu2tFezMu75jH7A==", "dev": true, "license": "MIT", "dependencies": { "cac": "^6.7.14", "debug": "^4.4.0", "es-module-lexer": "^1.6.0", - "pathe": "^2.0.1", + "pathe": "^2.0.2", "vite": "^5.0.0 || ^6.0.0" }, "bin": { @@ -6621,31 +6703,31 @@ } }, "node_modules/vitest": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.3.tgz", - "integrity": "sha512-dWdwTFUW9rcnL0LyF2F+IfvNQWB0w9DERySCk8VMG75F8k25C7LsZoh6XfCjPvcR8Nb+Lqi9JKr6vnzH7HSrpQ==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.5.tgz", + "integrity": "sha512-4dof+HvqONw9bvsYxtkfUp2uHsTN9bV2CZIi1pWgoFpL1Lld8LA1ka9q/ONSsoScAKG7NVGf2stJTI7XRkXb2Q==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/expect": "3.0.3", - "@vitest/mocker": "3.0.3", - "@vitest/pretty-format": "^3.0.3", - "@vitest/runner": "3.0.3", - "@vitest/snapshot": "3.0.3", - "@vitest/spy": "3.0.3", - "@vitest/utils": "3.0.3", + "@vitest/expect": "3.0.5", + "@vitest/mocker": "3.0.5", + "@vitest/pretty-format": "^3.0.5", + "@vitest/runner": "3.0.5", + "@vitest/snapshot": "3.0.5", + "@vitest/spy": "3.0.5", + "@vitest/utils": "3.0.5", "chai": "^5.1.2", "debug": "^4.4.0", "expect-type": "^1.1.0", "magic-string": "^0.30.17", - "pathe": "^2.0.1", + "pathe": "^2.0.2", "std-env": "^3.8.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", "tinypool": "^1.0.2", "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0", - "vite-node": "3.0.3", + "vite-node": "3.0.5", "why-is-node-running": "^2.3.0" }, "bin": { @@ -6659,9 +6741,10 @@ }, "peerDependencies": { "@edge-runtime/vm": "*", + "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "@vitest/browser": "3.0.3", - "@vitest/ui": "3.0.3", + "@vitest/browser": "3.0.5", + "@vitest/ui": "3.0.5", "happy-dom": "*", "jsdom": "*" }, @@ -6669,6 +6752,9 @@ "@edge-runtime/vm": { "optional": true }, + "@types/debug": { + "optional": true + }, "@types/node": { "optional": true }, diff --git a/server/package-lock.json b/server/package-lock.json index a917ba7f7c95d..9c10d2d1c7442 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -19,7 +19,7 @@ "@nestjs/swagger": "^11.0.2", "@nestjs/typeorm": "^11.0.0", "@nestjs/websockets": "^11.0.4", - "@opentelemetry/auto-instrumentations-node": "^0.55.0", + "@opentelemetry/auto-instrumentations-node": "^0.56.0", "@opentelemetry/context-async-hooks": "^1.24.0", "@opentelemetry/exporter-prometheus": "^0.57.0", "@opentelemetry/sdk-node": "^0.57.0", @@ -1178,9 +1178,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.18.0.tgz", - "integrity": "sha512-fK6L7rxcq6/z+AaQMtiFTkvbHkBLNlwyRxHpKawP0x3u9+NC6MQTnFW+AdpwC6gfHTW0051cokQgtTN2FqlxQA==", + "version": "9.19.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.19.0.tgz", + "integrity": "sha512-rbq9/g38qjfqFLOVPvwjIvFFdNziEC5S65jmjPw5r6A//QH+W91akh9irMwjDN8zKUTak6W9EsAv4m/7Wnw0UQ==", "dev": true, "license": "MIT", "engines": { @@ -2310,9 +2310,9 @@ ] }, "node_modules/@nestjs/bull-shared": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/@nestjs/bull-shared/-/bull-shared-11.0.1.tgz", - "integrity": "sha512-FqpmIjhCONaYo+5AjtggPdo2lRIM/fv1VHiEq7YwFZBTNSPW0eOvcT96JDb5q4OuvLvADxgpnwP7rmzZywMMiw==", + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/@nestjs/bull-shared/-/bull-shared-11.0.2.tgz", + "integrity": "sha512-dFlttJvBqIFD6M8JVFbkrR4Feb39OTAJPJpFVILU50NOJCM4qziRw3dSNG84Q3v+7/M6xUGMFdZRRGvBBKxoSA==", "license": "MIT", "dependencies": { "tslib": "2.8.1" @@ -2323,12 +2323,12 @@ } }, "node_modules/@nestjs/bullmq": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/@nestjs/bullmq/-/bullmq-11.0.1.tgz", - "integrity": "sha512-BntU0Zfiyk4R5hlasUV22n1HuqmWWKvsx3knSR5A9/5vce808pmHOmHrtm4GZDs/8Pw9X8UGY8zdLe4a36S6KQ==", + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/@nestjs/bullmq/-/bullmq-11.0.2.tgz", + "integrity": "sha512-Lq6lGpKkETsm0RDcUktlzsthFoE3A5QTMp2FwPi1eztKqKD6/90KS1TcnC9CJFzjpUaYnQzIMrlNs55e+/wsHA==", "license": "MIT", "dependencies": { - "@nestjs/bull-shared": "^11.0.1", + "@nestjs/bull-shared": "^11.0.2", "tslib": "2.8.1" }, "peerDependencies": { @@ -2577,9 +2577,9 @@ } }, "node_modules/@nestjs/common": { - "version": "11.0.6", - "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-11.0.6.tgz", - "integrity": "sha512-j+M3WOU6loZPNirIHDiZ1LxXRXVNb62XicgLBqdgyrDBFCJrAZaq0lfERUEPlN0/j4GBFnTSPg+CNsoGTBW1zQ==", + "version": "11.0.8", + "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-11.0.8.tgz", + "integrity": "sha512-IB6wEl8RgT/vWzb6p3cmBwTY3R0qfQWvO8lW0PfIv4DTJfUiVqNNEikonGuH/6TX8KvRXNhXHCaQZrUN00Xe6g==", "license": "MIT", "dependencies": { "iterare": "1.2.1", @@ -2606,9 +2606,9 @@ } }, "node_modules/@nestjs/core": { - "version": "11.0.6", - "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-11.0.6.tgz", - "integrity": "sha512-Xf33bwc3waAJ/faJBW06+Dwq3m15p3wbFOc/CcK8ua5EZna4sMjIjXXAb6bQmEjR1KfTXV5z595UD2vwp6cyHg==", + "version": "11.0.8", + "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-11.0.8.tgz", + "integrity": "sha512-GQLLdZnjZOmV4Q+TzQ8YuHvEYOneRhzsDbSJRkKdFFAVuoVh+q1nWZy+bZNeTxdWZFGL2Rve70X5jc4MoSXJqQ==", "hasInstallScript": true, "license": "MIT", "dependencies": { @@ -2680,9 +2680,9 @@ } }, "node_modules/@nestjs/platform-express": { - "version": "11.0.6", - "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-11.0.6.tgz", - "integrity": "sha512-fP6vrpqDIBaf1FNfFtBeJm/BwtGtueatI4FHxaBgw93XxKmIOV4G4ZO7ouQKqfgyIxV2mkYr/Fhg7hwRmizIjw==", + "version": "11.0.8", + "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-11.0.8.tgz", + "integrity": "sha512-Ru7seOYYglKNGQFzNALE5ilLqkdtX/ge6AJDKLMt+WI7iElZ7lXjT40fE3+HVUiZODunmeKQ7jVxcQyZwLafVA==", "license": "MIT", "dependencies": { "cors": "2.8.5", @@ -2701,9 +2701,9 @@ } }, "node_modules/@nestjs/platform-socket.io": { - "version": "11.0.6", - "resolved": "https://registry.npmjs.org/@nestjs/platform-socket.io/-/platform-socket.io-11.0.6.tgz", - "integrity": "sha512-80r6hp0p+YK/+D5srjPTE/fc1w0aTM6ecqprJr8bFlzTPJbtYtpfHqMbEg0UfRKTsZ0krEgpv8fb0K4dSYzW0w==", + "version": "11.0.8", + "resolved": "https://registry.npmjs.org/@nestjs/platform-socket.io/-/platform-socket.io-11.0.8.tgz", + "integrity": "sha512-DUpfRSDgxu+z9czB6ddFdQFawSAIr7jEbNOvpjpjYErvDitUdos57FhTw9IJxIm2EAOHoiCk4g3tN59GfjdwfQ==", "license": "MIT", "dependencies": { "socket.io": "4.8.1", @@ -2720,9 +2720,9 @@ } }, "node_modules/@nestjs/schedule": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@nestjs/schedule/-/schedule-5.0.0.tgz", - "integrity": "sha512-RHqJIOo3AQvdeq0WuIFDqa5N0CkgxgqwmWRla96S6GmFV6qkQD1//EeH4k19MeCu4Ac9PzZ2y/Hu0zK9f//BQg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@nestjs/schedule/-/schedule-5.0.1.tgz", + "integrity": "sha512-kFoel84I4RyS2LNPH6yHYTKxB16tb3auAEciFuc788C3ph6nABkUfzX5IE+unjVaRX+3GuruJwurNepMlHXpQg==", "license": "MIT", "dependencies": { "cron": "3.5.0" @@ -2916,9 +2916,9 @@ } }, "node_modules/@nestjs/testing": { - "version": "11.0.6", - "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-11.0.6.tgz", - "integrity": "sha512-RZDWdnOncOQ1vT3630VlRzKee2P21ZJoF1+NAY+nzYUuYuYAaBdjrTZQGwymmiZQcrM+TQaViSjSPUmcJXdKyA==", + "version": "11.0.8", + "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-11.0.8.tgz", + "integrity": "sha512-5Reqec4MQSm4nFasKE5Pd799cAx3MmjkweF17Wgj/EJNWhFgVdv6N9OUIWXbU8nc8Pjso1fJmv0KJyN6h51qOA==", "dev": true, "license": "MIT", "dependencies": { @@ -2957,9 +2957,9 @@ } }, "node_modules/@nestjs/websockets": { - "version": "11.0.6", - "resolved": "https://registry.npmjs.org/@nestjs/websockets/-/websockets-11.0.6.tgz", - "integrity": "sha512-bsYZnmIXmZTYWzLJ3LbusH72kdppKSQLKUe9cfuUPXuTF+FaAX6TvErP11dJJ0W0S1Iwufr+LERTK211Txs8Eg==", + "version": "11.0.8", + "resolved": "https://registry.npmjs.org/@nestjs/websockets/-/websockets-11.0.8.tgz", + "integrity": "sha512-wyS512+QWhWhE8NU1DgbAPkCaaOSNK1xBIgRlgpYg5/tKuhu4lc5r8iMdZAQn6xay++ELlOqsSlyuj0J2BixOA==", "license": "MIT", "dependencies": { "iterare": "1.2.1", @@ -3186,9 +3186,9 @@ } }, "node_modules/@opentelemetry/auto-instrumentations-node": { - "version": "0.55.3", - "resolved": "https://registry.npmjs.org/@opentelemetry/auto-instrumentations-node/-/auto-instrumentations-node-0.55.3.tgz", - "integrity": "sha512-tX5k3ZG8Nk6f1DHAF0K1ClP/OiW2hNuSeCVqDHNMcJ58dZSiad0XO2mwrvSipo77/DPXXUl0j9MxqmUVITdujQ==", + "version": "0.56.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/auto-instrumentations-node/-/auto-instrumentations-node-0.56.0.tgz", + "integrity": "sha512-d1X3DQY0+VmhNUir/3U3JO6Uh0FOSm8G91zsPzVVKc6NGDwmHP6Dn7PMVH70O6FZ0yErzlHqRx8vkNiAsTWt5A==", "license": "Apache-2.0", "dependencies": { "@opentelemetry/instrumentation": "^0.57.0", @@ -3198,7 +3198,7 @@ "@opentelemetry/instrumentation-bunyan": "^0.45.0", "@opentelemetry/instrumentation-cassandra-driver": "^0.45.0", "@opentelemetry/instrumentation-connect": "^0.43.0", - "@opentelemetry/instrumentation-cucumber": "^0.13.0", + "@opentelemetry/instrumentation-cucumber": "^0.14.0", "@opentelemetry/instrumentation-dataloader": "^0.16.0", "@opentelemetry/instrumentation-dns": "^0.43.0", "@opentelemetry/instrumentation-express": "^0.47.0", @@ -3218,10 +3218,10 @@ "@opentelemetry/instrumentation-mongodb": "^0.51.0", "@opentelemetry/instrumentation-mongoose": "^0.46.0", "@opentelemetry/instrumentation-mysql": "^0.45.0", - "@opentelemetry/instrumentation-mysql2": "^0.45.0", + "@opentelemetry/instrumentation-mysql2": "^0.45.1", "@opentelemetry/instrumentation-nestjs-core": "^0.44.0", "@opentelemetry/instrumentation-net": "^0.43.0", - "@opentelemetry/instrumentation-pg": "^0.50.0", + "@opentelemetry/instrumentation-pg": "^0.51.0", "@opentelemetry/instrumentation-pino": "^0.46.0", "@opentelemetry/instrumentation-redis": "^0.46.0", "@opentelemetry/instrumentation-redis-4": "^0.46.0", @@ -3626,9 +3626,9 @@ } }, "node_modules/@opentelemetry/instrumentation-cucumber": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-cucumber/-/instrumentation-cucumber-0.13.0.tgz", - "integrity": "sha512-ZBswBKONU2g7mhjEKF4vkTXxezq16QdvGaD5W4o01/t5KzvCZGQ6hYPsB34miJIj/hh6UrFLRDAjqb7nur5I3Q==", + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-cucumber/-/instrumentation-cucumber-0.14.0.tgz", + "integrity": "sha512-i/GlurL1IM+CnbmItW8kx59YxAp0wu/YQkzQQRU/YGmUjym5g+/dOVjnk/K46lAU49Nn1XyFd7S3ZNf83PHL2Q==", "license": "Apache-2.0", "dependencies": { "@opentelemetry/instrumentation": "^0.57.0", @@ -3952,9 +3952,9 @@ } }, "node_modules/@opentelemetry/instrumentation-mysql2": { - "version": "0.45.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql2/-/instrumentation-mysql2-0.45.0.tgz", - "integrity": "sha512-qLslv/EPuLj0IXFvcE3b0EqhWI8LKmrgRPIa4gUd8DllbBpqJAvLNJSv3cC6vWwovpbSI3bagNO/3Q2SuXv2xA==", + "version": "0.45.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql2/-/instrumentation-mysql2-0.45.1.tgz", + "integrity": "sha512-9R/vxEc02vlSqyQSmXRTvFMZVht8vgSJokKhiWA3z8Idu0mmdKFKeHiuW5yRGxM/WOi+7DWqQfYM7zw/cJc3sA==", "license": "Apache-2.0", "dependencies": { "@opentelemetry/instrumentation": "^0.57.0", @@ -4001,14 +4001,14 @@ } }, "node_modules/@opentelemetry/instrumentation-pg": { - "version": "0.50.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-pg/-/instrumentation-pg-0.50.0.tgz", - "integrity": "sha512-TtLxDdYZmBhFswm8UIsrDjh/HFBeDXd4BLmE8h2MxirNHewLJ0VS9UUddKKEverb5Sm2qFVjqRjcU+8Iw4FJ3w==", + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-pg/-/instrumentation-pg-0.51.0.tgz", + "integrity": "sha512-/NStIcUWUofc11dL7tSgMk25NqvhtbHDCncgm+yc4iJF8Ste2Q/lwUitjfxqj4qWM280uFmBEtcmtMMjbjRU7Q==", "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "^1.26.0", "@opentelemetry/instrumentation": "^0.57.0", - "@opentelemetry/semantic-conventions": "1.27.0", + "@opentelemetry/semantic-conventions": "^1.27.0", "@opentelemetry/sql-common": "^0.40.1", "@types/pg": "8.6.1", "@types/pg-pool": "2.0.6" @@ -4020,15 +4020,6 @@ "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@opentelemetry/instrumentation-pg/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.27.0.tgz", - "integrity": "sha512-sAay1RrB+ONOem0OZanAR1ZI/k7yDpnOQSQmTMuGImUQb2y8EbSaCJ94FQluM74xoU03vlb2d2U90hZluL6nQg==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, "node_modules/@opentelemetry/instrumentation-pino": { "version": "0.46.0", "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-pino/-/instrumentation-pino-0.46.0.tgz", @@ -5270,9 +5261,9 @@ "license": "MIT" }, "node_modules/@swc/core": { - "version": "1.10.7", - "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.10.7.tgz", - "integrity": "sha512-py91kjI1jV5D5W/Q+PurBdGsdU5TFbrzamP7zSCqLdMcHkKi3rQEM5jkQcZr0MXXSJTaayLxS3MWYTBIkzPDrg==", + "version": "1.10.14", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.10.14.tgz", + "integrity": "sha512-WSrnE6JRnH20ZYjOOgSS4aOaPv9gxlkI2KRkN24kagbZnPZMnN8bZZyzw1rrLvwgpuRGv17Uz+hflosbR+SP6w==", "dev": true, "hasInstallScript": true, "license": "Apache-2.0", @@ -5288,16 +5279,16 @@ "url": "https://opencollective.com/swc" }, "optionalDependencies": { - "@swc/core-darwin-arm64": "1.10.7", - "@swc/core-darwin-x64": "1.10.7", - "@swc/core-linux-arm-gnueabihf": "1.10.7", - "@swc/core-linux-arm64-gnu": "1.10.7", - "@swc/core-linux-arm64-musl": "1.10.7", - "@swc/core-linux-x64-gnu": "1.10.7", - "@swc/core-linux-x64-musl": "1.10.7", - "@swc/core-win32-arm64-msvc": "1.10.7", - "@swc/core-win32-ia32-msvc": "1.10.7", - "@swc/core-win32-x64-msvc": "1.10.7" + "@swc/core-darwin-arm64": "1.10.14", + "@swc/core-darwin-x64": "1.10.14", + "@swc/core-linux-arm-gnueabihf": "1.10.14", + "@swc/core-linux-arm64-gnu": "1.10.14", + "@swc/core-linux-arm64-musl": "1.10.14", + "@swc/core-linux-x64-gnu": "1.10.14", + "@swc/core-linux-x64-musl": "1.10.14", + "@swc/core-win32-arm64-msvc": "1.10.14", + "@swc/core-win32-ia32-msvc": "1.10.14", + "@swc/core-win32-x64-msvc": "1.10.14" }, "peerDependencies": { "@swc/helpers": "*" @@ -5309,9 +5300,9 @@ } }, "node_modules/@swc/core-darwin-arm64": { - "version": "1.10.7", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.10.7.tgz", - "integrity": "sha512-SI0OFg987P6hcyT0Dbng3YRISPS9uhLX1dzW4qRrfqQdb0i75lPJ2YWe9CN47HBazrIA5COuTzrD2Dc0TcVsSQ==", + "version": "1.10.14", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.10.14.tgz", + "integrity": "sha512-Dh4VyrhDDb05tdRmqJ/MucOPMTnrB4pRJol18HVyLlqu1HOT5EzonUniNTCdQbUXjgdv5UVJSTE1lYTzrp+myA==", "cpu": [ "arm64" ], @@ -5326,9 +5317,9 @@ } }, "node_modules/@swc/core-darwin-x64": { - "version": "1.10.7", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.10.7.tgz", - "integrity": "sha512-RFIAmWVicD/l3RzxgHW0R/G1ya/6nyMspE2cAeDcTbjHi0I5qgdhBWd6ieXOaqwEwiCd0Mot1g2VZrLGoBLsjQ==", + "version": "1.10.14", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.10.14.tgz", + "integrity": "sha512-KpzotL/I0O12RE3tF8NmQErINv0cQe/0mnN/Q50ESFzB5kU6bLgp2HMnnwDTm/XEZZRJCNe0oc9WJ5rKbAJFRQ==", "cpu": [ "x64" ], @@ -5343,9 +5334,9 @@ } }, "node_modules/@swc/core-linux-arm-gnueabihf": { - "version": "1.10.7", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.10.7.tgz", - "integrity": "sha512-QP8vz7yELWfop5mM5foN6KkLylVO7ZUgWSF2cA0owwIaziactB2hCPZY5QU690coJouk9KmdFsPWDnaCFUP8tg==", + "version": "1.10.14", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.10.14.tgz", + "integrity": "sha512-20yRXZjMJVz1wp1TcscKiGTVXistG+saIaxOmxSNQia1Qun3hSWLL+u6+5kXbfYGr7R2N6kqSwtZbIfJI25r9Q==", "cpu": [ "arm" ], @@ -5360,9 +5351,9 @@ } }, "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.10.7", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.10.7.tgz", - "integrity": "sha512-NgUDBGQcOeLNR+EOpmUvSDIP/F7i/OVOKxst4wOvT5FTxhnkWrW+StJGKj+DcUVSK5eWOYboSXr1y+Hlywwokw==", + "version": "1.10.14", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.10.14.tgz", + "integrity": "sha512-Gy7cGrNkiMfPxQyLGxdgXPwyWzNzbHuWycJFcoKBihxZKZIW8hkPBttkGivuLC+0qOgsV2/U+S7tlvAju7FtmQ==", "cpu": [ "arm64" ], @@ -5377,9 +5368,9 @@ } }, "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.10.7", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.10.7.tgz", - "integrity": "sha512-gp5Un3EbeSThBIh6oac5ZArV/CsSmTKj5jNuuUAuEsML3VF9vqPO+25VuxCvsRf/z3py+xOWRaN2HY/rjMeZog==", + "version": "1.10.14", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.10.14.tgz", + "integrity": "sha512-+oYVqJvFw62InZ8PIy1rBACJPC2WTe4vbVb9kM1jJj2D7dKLm9acnnYIVIDsM5Wo7Uab8RvPHXVbs19IBurzuw==", "cpu": [ "arm64" ], @@ -5394,9 +5385,9 @@ } }, "node_modules/@swc/core-linux-x64-gnu": { - "version": "1.10.7", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.10.7.tgz", - "integrity": "sha512-k/OxLLMl/edYqbZyUNg6/bqEHTXJT15l9WGqsl/2QaIGwWGvles8YjruQYQ9d4h/thSXLT9gd8bExU2D0N+bUA==", + "version": "1.10.14", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.10.14.tgz", + "integrity": "sha512-OmEbVEKQFLQVHwo4EJl9osmlulURy46k232Opfpn/1ji0t2KcNCci3POsnfMuoZjLkGJv8vGNJdPQxX+CP+wSA==", "cpu": [ "x64" ], @@ -5411,9 +5402,9 @@ } }, "node_modules/@swc/core-linux-x64-musl": { - "version": "1.10.7", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.10.7.tgz", - "integrity": "sha512-XeDoURdWt/ybYmXLCEE8aSiTOzEn0o3Dx5l9hgt0IZEmTts7HgHHVeRgzGXbR4yDo0MfRuX5nE1dYpTmCz0uyA==", + "version": "1.10.14", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.10.14.tgz", + "integrity": "sha512-OZW+Icm8DMPqHbhdxplkuG8qrNnPk5i7xJOZWYi1y5bTjgGFI4nEzrsmmeHKMdQTaWwsFrm3uK1rlyQ48MmXmg==", "cpu": [ "x64" ], @@ -5428,9 +5419,9 @@ } }, "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.10.7", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.10.7.tgz", - "integrity": "sha512-nYAbi/uLS+CU0wFtBx8TquJw2uIMKBnl04LBmiVoFrsIhqSl+0MklaA9FVMGA35NcxSJfcm92Prl2W2LfSnTqQ==", + "version": "1.10.14", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.10.14.tgz", + "integrity": "sha512-sTvc+xrDQXy3HXZFtTEClY35Efvuc3D+busYm0+rb1+Thau4HLRY9WP+sOKeGwH9/16rzfzYEqD7Ds8A9ykrHw==", "cpu": [ "arm64" ], @@ -5445,9 +5436,9 @@ } }, "node_modules/@swc/core-win32-ia32-msvc": { - "version": "1.10.7", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.10.7.tgz", - "integrity": "sha512-+aGAbsDsIxeLxw0IzyQLtvtAcI1ctlXVvVcXZMNXIXtTURM876yNrufRo4ngoXB3jnb1MLjIIjgXfFs/eZTUSw==", + "version": "1.10.14", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.10.14.tgz", + "integrity": "sha512-j2iQ4y9GWTKtES5eMU0sDsFdYni7IxME7ejFej25Tv3Fq4B+U9tgtYWlJwh1858nIWDXelHiKcSh/UICAyVMdQ==", "cpu": [ "ia32" ], @@ -5462,9 +5453,9 @@ } }, "node_modules/@swc/core-win32-x64-msvc": { - "version": "1.10.7", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.10.7.tgz", - "integrity": "sha512-TBf4clpDBjF/UUnkKrT0/th76/zwvudk5wwobiTFqDywMApHip5O0VpBgZ+4raY2TM8k5+ujoy7bfHb22zu17Q==", + "version": "1.10.14", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.10.14.tgz", + "integrity": "sha512-TYtWkUSMkjs0jGPeWdtWbex4B+DlQZmN/ySVLiPI+EltYCLEXsFMkVFq6aWn48dqFHggFK0UYfvDrJUR2c3Qxg==", "cpu": [ "x64" ], @@ -5504,13 +5495,13 @@ } }, "node_modules/@testcontainers/postgresql": { - "version": "10.16.0", - "resolved": "https://registry.npmjs.org/@testcontainers/postgresql/-/postgresql-10.16.0.tgz", - "integrity": "sha512-zWFQI+3QxlEELRvVv27i6zlVEPNUz9zKaSh7iWmFlCdfhcyr78daS0FG8FIfdQ79VK7YXA4jv+dTYXa2SwXu/w==", + "version": "10.18.0", + "resolved": "https://registry.npmjs.org/@testcontainers/postgresql/-/postgresql-10.18.0.tgz", + "integrity": "sha512-WxkE/tBlBpoKvqDEqL3i/mL6BOBWnXb8FXKtLhEeZ3lSt0zlldkTozMmewNsKJtFTBZdv7uFwMzWyXP12t0sxQ==", "dev": true, "license": "MIT", "dependencies": { - "testcontainers": "^10.16.0" + "testcontainers": "^10.18.0" } }, "node_modules/@turf/boolean-point-in-polygon": { @@ -5777,9 +5768,9 @@ "license": "MIT" }, "node_modules/@types/lodash": { - "version": "4.17.14", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.14.tgz", - "integrity": "sha512-jsxagdikDiDBeIRaPYtArcT8my4tN1og7MtMRquFT3XNA6axxyHDRUemqDz/taRDdOUn0GnGHRCuff4q48sW9A==", + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-w/P33JFeySuhN6JLkysYUK2gEmy9kHHFN7E8ro0tkfmlDOgxBDzWEZ/J8cWA+fHqFevpswDTFZnDx+R9lbL6xw==", "dev": true, "license": "MIT" }, @@ -5919,9 +5910,9 @@ "license": "MIT" }, "node_modules/@types/react": { - "version": "19.0.7", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.0.7.tgz", - "integrity": "sha512-MoFsEJKkAtZCrC1r6CM8U22GzhG7u2Wir8ons/aCKH6MBdD1ibV24zOSSkdZVUKqN5i396zG5VKLYZ3yaUZdLA==", + "version": "19.0.8", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.0.8.tgz", + "integrity": "sha512-9P/o1IGdfmQxrujGbIMDyYaaCykhLKc0NGCtYcECNUr9UAaDe4gwvV9bR6tvd5Br1SG0j+PBpbKr2UYY8CwqSw==", "dev": true, "license": "MIT", "dependencies": { @@ -6068,21 +6059,21 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.20.0.tgz", - "integrity": "sha512-naduuphVw5StFfqp4Gq4WhIBE2gN1GEmMUExpJYknZJdRnc+2gDzB8Z3+5+/Kv33hPQRDGzQO/0opHE72lZZ6A==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.23.0.tgz", + "integrity": "sha512-vBz65tJgRrA1Q5gWlRfvoH+w943dq9K1p1yDBY2pc+a1nbBLZp7fB9+Hk8DaALUbzjqlMfgaqlVPT1REJdkt/w==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.20.0", - "@typescript-eslint/type-utils": "8.20.0", - "@typescript-eslint/utils": "8.20.0", - "@typescript-eslint/visitor-keys": "8.20.0", + "@typescript-eslint/scope-manager": "8.23.0", + "@typescript-eslint/type-utils": "8.23.0", + "@typescript-eslint/utils": "8.23.0", + "@typescript-eslint/visitor-keys": "8.23.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", - "ts-api-utils": "^2.0.0" + "ts-api-utils": "^2.0.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -6098,16 +6089,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.20.0.tgz", - "integrity": "sha512-gKXG7A5HMyjDIedBi6bUrDcun8GIjnI8qOwVLiY3rx6T/sHP/19XLJOnIq/FgQvWLHja5JN/LSE7eklNBr612g==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.23.0.tgz", + "integrity": "sha512-h2lUByouOXFAlMec2mILeELUbME5SZRN/7R9Cw2RD2lRQQY08MWMM+PmVVKKJNK1aIwqTo9t/0CvOxwPbRIE2Q==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.20.0", - "@typescript-eslint/types": "8.20.0", - "@typescript-eslint/typescript-estree": "8.20.0", - "@typescript-eslint/visitor-keys": "8.20.0", + "@typescript-eslint/scope-manager": "8.23.0", + "@typescript-eslint/types": "8.23.0", + "@typescript-eslint/typescript-estree": "8.23.0", + "@typescript-eslint/visitor-keys": "8.23.0", "debug": "^4.3.4" }, "engines": { @@ -6123,14 +6114,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.20.0.tgz", - "integrity": "sha512-J7+VkpeGzhOt3FeG1+SzhiMj9NzGD/M6KoGn9f4dbz3YzK9hvbhVTmLj/HiTp9DazIzJ8B4XcM80LrR9Dm1rJw==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.23.0.tgz", + "integrity": "sha512-OGqo7+dXHqI7Hfm+WqkZjKjsiRtFUQHPdGMXzk5mYXhJUedO7e/Y7i8AK3MyLMgZR93TX4bIzYrfyVjLC+0VSw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.20.0", - "@typescript-eslint/visitor-keys": "8.20.0" + "@typescript-eslint/types": "8.23.0", + "@typescript-eslint/visitor-keys": "8.23.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -6141,16 +6132,16 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.20.0.tgz", - "integrity": "sha512-bPC+j71GGvA7rVNAHAtOjbVXbLN5PkwqMvy1cwGeaxUoRQXVuKCebRoLzm+IPW/NtFFpstn1ummSIasD5t60GA==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.23.0.tgz", + "integrity": "sha512-iIuLdYpQWZKbiH+RkCGc6iu+VwscP5rCtQ1lyQ7TYuKLrcZoeJVpcLiG8DliXVkUxirW/PWlmS+d6yD51L9jvA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.20.0", - "@typescript-eslint/utils": "8.20.0", + "@typescript-eslint/typescript-estree": "8.23.0", + "@typescript-eslint/utils": "8.23.0", "debug": "^4.3.4", - "ts-api-utils": "^2.0.0" + "ts-api-utils": "^2.0.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -6165,9 +6156,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.20.0.tgz", - "integrity": "sha512-cqaMiY72CkP+2xZRrFt3ExRBu0WmVitN/rYPZErA80mHjHx/Svgp8yfbzkJmDoQ/whcytOPO9/IZXnOc+wigRA==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.23.0.tgz", + "integrity": "sha512-1sK4ILJbCmZOTt9k4vkoulT6/y5CHJ1qUYxqpF1K/DBAd8+ZUL4LlSCxOssuH5m4rUaaN0uS0HlVPvd45zjduQ==", "dev": true, "license": "MIT", "engines": { @@ -6179,20 +6170,20 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.20.0.tgz", - "integrity": "sha512-Y7ncuy78bJqHI35NwzWol8E0X7XkRVS4K4P4TCyzWkOJih5NDvtoRDW4Ba9YJJoB2igm9yXDdYI/+fkiiAxPzA==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.23.0.tgz", + "integrity": "sha512-LcqzfipsB8RTvH8FX24W4UUFk1bl+0yTOf9ZA08XngFwMg4Kj8A+9hwz8Cr/ZS4KwHrmo9PJiLZkOt49vPnuvQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.20.0", - "@typescript-eslint/visitor-keys": "8.20.0", + "@typescript-eslint/types": "8.23.0", + "@typescript-eslint/visitor-keys": "8.23.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", - "ts-api-utils": "^2.0.0" + "ts-api-utils": "^2.0.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -6232,16 +6223,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.20.0.tgz", - "integrity": "sha512-dq70RUw6UK9ei7vxc4KQtBRk7qkHZv447OUZ6RPQMQl71I3NZxQJX/f32Smr+iqWrB02pHKn2yAdHBb0KNrRMA==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.23.0.tgz", + "integrity": "sha512-uB/+PSo6Exu02b5ZEiVtmY6RVYO7YU5xqgzTIVZwTHvvK3HsL8tZZHFaTLFtRG3CsV4A5mhOv+NZx5BlhXPyIA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.20.0", - "@typescript-eslint/types": "8.20.0", - "@typescript-eslint/typescript-estree": "8.20.0" + "@typescript-eslint/scope-manager": "8.23.0", + "@typescript-eslint/types": "8.23.0", + "@typescript-eslint/typescript-estree": "8.23.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -6256,13 +6247,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.20.0.tgz", - "integrity": "sha512-v/BpkeeYAsPkKCkR8BDwcno0llhzWVqPOamQrAEMdpZav2Y9OVjd9dwJyBLJWwf335B5DmlifECIkZRJCaGaHA==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.23.0.tgz", + "integrity": "sha512-oWWhcWDLwDfu++BGTZcmXWqpwtkwb5o7fxUIGksMQQDSdPW9prsSnfIOZMlsj4vBOSrcnjIUZMiIjODgGosFhQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.20.0", + "@typescript-eslint/types": "8.23.0", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -6287,9 +6278,9 @@ } }, "node_modules/@vitest/coverage-v8": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.0.3.tgz", - "integrity": "sha512-uVbJ/xhImdNtzPnLyxCZJMTeTIYdgcC2nWtBBBpR1H6z0w8m7D+9/zrDIx2nNxgMg9r+X8+RY2qVpUDeW2b3nw==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.0.5.tgz", + "integrity": "sha512-zOOWIsj5fHh3jjGwQg+P+J1FW3s4jBu1Zqga0qW60yutsBtqEqNEJKWYh7cYn1yGD+1bdPsPdC/eL4eVK56xMg==", "dev": true, "license": "MIT", "dependencies": { @@ -6310,8 +6301,8 @@ "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "@vitest/browser": "3.0.3", - "vitest": "3.0.3" + "@vitest/browser": "3.0.5", + "vitest": "3.0.5" }, "peerDependenciesMeta": { "@vitest/browser": { @@ -6320,14 +6311,14 @@ } }, "node_modules/@vitest/expect": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.3.tgz", - "integrity": "sha512-SbRCHU4qr91xguu+dH3RUdI5dC86zm8aZWydbp961aIR7G8OYNN6ZiayFuf9WAngRbFOfdrLHCGgXTj3GtoMRQ==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.5.tgz", + "integrity": "sha512-nNIOqupgZ4v5jWuQx2DSlHLEs7Q4Oh/7AYwNyE+k0UQzG7tSmjPXShUikn1mpNGzYEN2jJbTvLejwShMitovBA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "3.0.3", - "@vitest/utils": "3.0.3", + "@vitest/spy": "3.0.5", + "@vitest/utils": "3.0.5", "chai": "^5.1.2", "tinyrainbow": "^2.0.0" }, @@ -6336,13 +6327,13 @@ } }, "node_modules/@vitest/mocker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.3.tgz", - "integrity": "sha512-XT2XBc4AN9UdaxJAeIlcSZ0ILi/GzmG5G8XSly4gaiqIvPV3HMTSIDZWJVX6QRJ0PX1m+W8Cy0K9ByXNb/bPIA==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.5.tgz", + "integrity": "sha512-CLPNBFBIE7x6aEGbIjaQAX03ZZlBMaWwAjBdMkIf/cAn6xzLTiM3zYqO/WAbieEjsAZir6tO71mzeHZoodThvw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "3.0.3", + "@vitest/spy": "3.0.5", "estree-walker": "^3.0.3", "magic-string": "^0.30.17" }, @@ -6373,9 +6364,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.3.tgz", - "integrity": "sha512-gCrM9F7STYdsDoNjGgYXKPq4SkSxwwIU5nkaQvdUxiQ0EcNlez+PdKOVIsUJvh9P9IeIFmjn4IIREWblOBpP2Q==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.5.tgz", + "integrity": "sha512-CjUtdmpOcm4RVtB+up8r2vVDLR16Mgm/bYdkGFe3Yj/scRfCpbSi2W/BDSDcFK7ohw8UXvjMbOp9H4fByd/cOA==", "dev": true, "license": "MIT", "dependencies": { @@ -6386,38 +6377,38 @@ } }, "node_modules/@vitest/runner": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.3.tgz", - "integrity": "sha512-Rgi2kOAk5ZxWZlwPguRJFOBmWs6uvvyAAR9k3MvjRvYrG7xYvKChZcmnnpJCS98311CBDMqsW9MzzRFsj2gX3g==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.5.tgz", + "integrity": "sha512-BAiZFityFexZQi2yN4OX3OkJC6scwRo8EhRB0Z5HIGGgd2q+Nq29LgHU/+ovCtd0fOfXj5ZI6pwdlUmC5bpi8A==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "3.0.3", - "pathe": "^2.0.1" + "@vitest/utils": "3.0.5", + "pathe": "^2.0.2" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/snapshot": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.3.tgz", - "integrity": "sha512-kNRcHlI4txBGztuJfPEJ68VezlPAXLRT1u5UCx219TU3kOG2DplNxhWLwDf2h6emwmTPogzLnGVwP6epDaJN6Q==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.5.tgz", + "integrity": "sha512-GJPZYcd7v8QNUJ7vRvLDmRwl+a1fGg4T/54lZXe+UOGy47F9yUfE18hRCtXL5aHN/AONu29NGzIXSVFh9K0feA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.0.3", + "@vitest/pretty-format": "3.0.5", "magic-string": "^0.30.17", - "pathe": "^2.0.1" + "pathe": "^2.0.2" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/spy": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.3.tgz", - "integrity": "sha512-7/dgux8ZBbF7lEIKNnEqQlyRaER9nkAL9eTmdKJkDO3hS8p59ATGwKOCUDHcBLKr7h/oi/6hP+7djQk8049T2A==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.5.tgz", + "integrity": "sha512-5fOzHj0WbUNqPK6blI/8VzZdkBlQLnT25knX0r4dbZI9qoZDf3qAdjoMmDcLG5A83W6oUUFJgUd0EYBc2P5xqg==", "dev": true, "license": "MIT", "dependencies": { @@ -6428,13 +6419,13 @@ } }, "node_modules/@vitest/utils": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.3.tgz", - "integrity": "sha512-f+s8CvyzPtMFY1eZKkIHGhPsQgYo5qCm6O8KZoim9qm1/jT64qBgGpO5tHscNH6BzRHM+edLNOP+3vO8+8pE/A==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.5.tgz", + "integrity": "sha512-N9AX0NUoUtVwKwy21JtwzaqR5L5R5A99GAbrHfCCXK1lp593i/3AZAXhSP43wRQuxYsflrdzEfXZFo1reR1Nkg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.0.3", + "@vitest/pretty-format": "3.0.5", "loupe": "^3.1.2", "tinyrainbow": "^2.0.0" }, @@ -8836,9 +8827,9 @@ } }, "node_modules/eslint": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.18.0.tgz", - "integrity": "sha512-+waTfRWQlSbpt3KWE+CjrPPYnbq9kfZIYUqapc0uBXyjTp8aYXZDsUH16m39Ryq3NjAVP4tjuF7KaukeqoCoaA==", + "version": "9.19.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.19.0.tgz", + "integrity": "sha512-ug92j0LepKlbbEv6hD911THhoRHmbdXt2gX+VDABAW/Ir7D3nqKdv5Pf5vtlyY6HQMTEP2skXY43ueqTCWssEA==", "dev": true, "license": "MIT", "dependencies": { @@ -8847,7 +8838,7 @@ "@eslint/config-array": "^0.19.0", "@eslint/core": "^0.10.0", "@eslint/eslintrc": "^3.2.0", - "@eslint/js": "9.18.0", + "@eslint/js": "9.19.0", "@eslint/plugin-kit": "^0.2.5", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", @@ -8909,9 +8900,9 @@ } }, "node_modules/eslint-plugin-prettier": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.2.tgz", - "integrity": "sha512-1yI3/hf35wmlq66C8yOyrujQnel+v5l1Vop5Cl2I6ylyNTT1JbuUUnV3/41PzwTzcyDp/oF0jWE3HXvcH5AQOQ==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.3.tgz", + "integrity": "sha512-qJ+y0FfCp/mQYQ/vWQ3s7eUlFEL4PyKfAJxsnYTJ4YT73nsJBWqmEpFryxV9OeUiqmsTsYJ5Y+KDNaeP31wrRw==", "dev": true, "license": "MIT", "dependencies": { @@ -9861,9 +9852,9 @@ } }, "node_modules/geo-tz": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/geo-tz/-/geo-tz-8.1.2.tgz", - "integrity": "sha512-S1udoP7MZ+CVu+7Iy/VayVNmEHTWgfJ52TjpfC2/4f+j0SB/ZXMjGrwZTqPMo6/O2m5lrGLCFCY0bkxUqiLN+g==", + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/geo-tz/-/geo-tz-8.1.3.tgz", + "integrity": "sha512-zzF0hjqLl+1n5tXDCxwdS/BmF+N1TdQc6rbubh6PO6/9DtntX/yBox1Ti0q24MrjajWG0fSv0gv2w6Zff/kmeA==", "license": "MIT", "dependencies": { "@turf/boolean-point-in-polygon": "^7.1.0", @@ -11210,9 +11201,9 @@ "license": "Apache-2.0" }, "node_modules/loupe": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.2.tgz", - "integrity": "sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.3.tgz", + "integrity": "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==", "dev": true, "license": "MIT" }, @@ -11515,9 +11506,9 @@ "license": "MIT" }, "node_modules/mock-fs": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-5.4.1.tgz", - "integrity": "sha512-sz/Q8K1gXXXHR+qr0GZg2ysxCRr323kuN10O7CtQjraJsFDJ4SJ+0I5MzALz7aRp9lHk8Cc/YdsT95h9Ka1aFw==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-5.5.0.tgz", + "integrity": "sha512-d/P1M/RacgM3dB0sJ8rjeRNXxtapkPCUnMGmIN0ixJ16F/E4GUZCvWcSGfWGz8eaXYvn1s9baUwNjI4LOPEjiA==", "dev": true, "license": "MIT", "engines": { @@ -11803,9 +11794,9 @@ } }, "node_modules/nestjs-cls": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nestjs-cls/-/nestjs-cls-5.0.0.tgz", - "integrity": "sha512-0rpkCngRISkd2x9z7q0bR8R4AeZe43WkLBaDuTE6Uaw9r1OEWfEGfGS6M4OlXG20CIxDtaAIbWW8wFM5YCNRkA==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/nestjs-cls/-/nestjs-cls-5.0.1.tgz", + "integrity": "sha512-TA1qkFkkWct1LXXjcNk4jxQgvZrL34bojK3D4oOo59ru7xrQ1erN3/737T+XezOZ2ZPngGVeJZ9WipaD9N+G0Q==", "license": "MIT", "engines": { "node": ">=16" @@ -11966,9 +11957,9 @@ "license": "MIT" }, "node_modules/nodemailer": { - "version": "6.9.16", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.16.tgz", - "integrity": "sha512-psAuZdTIRN08HKVd/E8ObdV6NO7NTBY3KsC30F7M4H1OnmLCUNaS56FpYxyb26zWLSyYF9Ozch9KYHhHegsiOQ==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.10.0.tgz", + "integrity": "sha512-SQ3wZCExjeSatLE/HBaXS5vqUOQk6GtBdIIKxiFdmm01mOQZX/POJkO3SUX1wDiYcwUOJwT23scFSC9fY2H8IA==", "license": "MIT-0", "engines": { "node": ">=6.0.0" @@ -14028,9 +14019,9 @@ } }, "node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -14569,9 +14560,9 @@ } }, "node_modules/sql-formatter": { - "version": "15.4.9", - "resolved": "https://registry.npmjs.org/sql-formatter/-/sql-formatter-15.4.9.tgz", - "integrity": "sha512-5vmt2HlCAVozxsBZuXWkAki/KGawaK+b5GG5x+BtXOFVpN/8cqppblFUxHl4jxdA0cvo14lABhM+KBnrUapOlw==", + "version": "15.4.10", + "resolved": "https://registry.npmjs.org/sql-formatter/-/sql-formatter-15.4.10.tgz", + "integrity": "sha512-zQfiuxU1F/C7TNu+880BdL+fuvJTd1Kj8R0wv48dfZ27NR3z1PWvQFkH8ai/HrIy+NyvXCaZBkJHp/EeZFXSOA==", "dev": true, "license": "MIT", "dependencies": { @@ -15262,9 +15253,9 @@ } }, "node_modules/testcontainers": { - "version": "10.16.0", - "resolved": "https://registry.npmjs.org/testcontainers/-/testcontainers-10.16.0.tgz", - "integrity": "sha512-oxPLuOtrRWS11A+Yn0+zXB7GkmNarflWqmy6CQJk8KJ75LZs2/zlUXDpizTbPpCGtk4kE2EQYwFZjrE967F8Wg==", + "version": "10.18.0", + "resolved": "https://registry.npmjs.org/testcontainers/-/testcontainers-10.18.0.tgz", + "integrity": "sha512-MnwWsPjsN5QVe+lSU1LwLZVOyjgwSwv1INzkw8FekdwgvOtvJ7FThQEkbmzRcguQootgwmA9FG54NoTChZDRvA==", "dev": true, "license": "MIT", "dependencies": { @@ -15282,7 +15273,7 @@ "ssh-remote-port-forward": "^1.0.4", "tar-fs": "^3.0.6", "tmp": "^0.2.3", - "undici": "^5.28.4" + "undici": "^5.28.5" } }, "node_modules/testcontainers/node_modules/tmp": { @@ -15456,9 +15447,9 @@ } }, "node_modules/ts-api-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.0.tgz", - "integrity": "sha512-xCt/TOAc+EOHS1XPnijD3/yzpH6qg2xppZO1YDqGoVsNXfQfzHpOdNuXwrwOU8u4ITXJyDCTyt8w5g1sZv9ynQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.1.tgz", + "integrity": "sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w==", "dev": true, "license": "MIT", "engines": { @@ -15839,9 +15830,9 @@ } }, "node_modules/undici": { - "version": "5.28.4", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", - "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", + "version": "5.28.5", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.5.tgz", + "integrity": "sha512-zICwjrDrcrUE0pyyJc1I2QzBkLM8FINsgOrt6WjA+BgajVq9Nxu2PbFFXUrAggLfDXlZGZBVZYw7WNV5KiBiBA==", "dev": true, "license": "MIT", "dependencies": { @@ -16078,16 +16069,16 @@ } }, "node_modules/vite-node": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.3.tgz", - "integrity": "sha512-0sQcwhwAEw/UJGojbhOrnq3HtiZ3tC7BzpAa0lx3QaTX0S3YX70iGcik25UBdB96pmdwjyY2uyKNYruxCDmiEg==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.5.tgz", + "integrity": "sha512-02JEJl7SbtwSDJdYS537nU6l+ktdvcREfLksk/NDAqtdKWGqHl+joXzEubHROmS3E6pip+Xgu2tFezMu75jH7A==", "dev": true, "license": "MIT", "dependencies": { "cac": "^6.7.14", "debug": "^4.4.0", "es-module-lexer": "^1.6.0", - "pathe": "^2.0.1", + "pathe": "^2.0.2", "vite": "^5.0.0 || ^6.0.0" }, "bin": { @@ -16580,31 +16571,31 @@ } }, "node_modules/vitest": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.3.tgz", - "integrity": "sha512-dWdwTFUW9rcnL0LyF2F+IfvNQWB0w9DERySCk8VMG75F8k25C7LsZoh6XfCjPvcR8Nb+Lqi9JKr6vnzH7HSrpQ==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.5.tgz", + "integrity": "sha512-4dof+HvqONw9bvsYxtkfUp2uHsTN9bV2CZIi1pWgoFpL1Lld8LA1ka9q/ONSsoScAKG7NVGf2stJTI7XRkXb2Q==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/expect": "3.0.3", - "@vitest/mocker": "3.0.3", - "@vitest/pretty-format": "^3.0.3", - "@vitest/runner": "3.0.3", - "@vitest/snapshot": "3.0.3", - "@vitest/spy": "3.0.3", - "@vitest/utils": "3.0.3", + "@vitest/expect": "3.0.5", + "@vitest/mocker": "3.0.5", + "@vitest/pretty-format": "^3.0.5", + "@vitest/runner": "3.0.5", + "@vitest/snapshot": "3.0.5", + "@vitest/spy": "3.0.5", + "@vitest/utils": "3.0.5", "chai": "^5.1.2", "debug": "^4.4.0", "expect-type": "^1.1.0", "magic-string": "^0.30.17", - "pathe": "^2.0.1", + "pathe": "^2.0.2", "std-env": "^3.8.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", "tinypool": "^1.0.2", "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0", - "vite-node": "3.0.3", + "vite-node": "3.0.5", "why-is-node-running": "^2.3.0" }, "bin": { @@ -16618,9 +16609,10 @@ }, "peerDependencies": { "@edge-runtime/vm": "*", + "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "@vitest/browser": "3.0.3", - "@vitest/ui": "3.0.3", + "@vitest/browser": "3.0.5", + "@vitest/ui": "3.0.5", "happy-dom": "*", "jsdom": "*" }, @@ -16628,6 +16620,9 @@ "@edge-runtime/vm": { "optional": true }, + "@types/debug": { + "optional": true + }, "@types/node": { "optional": true }, diff --git a/server/package.json b/server/package.json index 6bd84f2a75ae9..f2aeec79f83bd 100644 --- a/server/package.json +++ b/server/package.json @@ -45,7 +45,7 @@ "@nestjs/swagger": "^11.0.2", "@nestjs/typeorm": "^11.0.0", "@nestjs/websockets": "^11.0.4", - "@opentelemetry/auto-instrumentations-node": "^0.55.0", + "@opentelemetry/auto-instrumentations-node": "^0.56.0", "@opentelemetry/context-async-hooks": "^1.24.0", "@opentelemetry/exporter-prometheus": "^0.57.0", "@opentelemetry/sdk-node": "^0.57.0", diff --git a/web/package-lock.json b/web/package-lock.json index 6e6cc62fae866..276fcb7b988fe 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -11,7 +11,7 @@ "dependencies": { "@formatjs/icu-messageformat-parser": "^2.9.8", "@immich/sdk": "file:../open-api/typescript-sdk", - "@immich/ui": "^0.15.0", + "@immich/ui": "^0.16.0", "@mapbox/mapbox-gl-rtl-text": "0.2.3", "@mdi/js": "^7.4.47", "@photo-sphere-viewer/core": "^5.11.5", @@ -26,7 +26,7 @@ "justified-layout": "^4.1.0", "lodash-es": "^4.17.21", "luxon": "^3.4.4", - "socket.io-client": "~4.7.5", + "socket.io-client": "~4.8.0", "svelte-gestures": "^5.1.3", "svelte-i18n": "^4.0.1", "svelte-local-storage-store": "^0.6.4", @@ -83,7 +83,7 @@ "@oazapfts/runtime": "^1.0.2" }, "devDependencies": { - "@types/node": "^22.10.9", + "@types/node": "^22.13.1", "typescript": "^5.3.3" } }, @@ -783,9 +783,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.18.0.tgz", - "integrity": "sha512-fK6L7rxcq6/z+AaQMtiFTkvbHkBLNlwyRxHpKawP0x3u9+NC6MQTnFW+AdpwC6gfHTW0051cokQgtTN2FqlxQA==", + "version": "9.19.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.19.0.tgz", + "integrity": "sha512-rbq9/g38qjfqFLOVPvwjIvFFdNziEC5S65jmjPw5r6A//QH+W91akh9irMwjDN8zKUTak6W9EsAv4m/7Wnw0UQ==", "dev": true, "license": "MIT", "engines": { @@ -880,9 +880,9 @@ } }, "node_modules/@formatjs/icu-messageformat-parser": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.10.0.tgz", - "integrity": "sha512-PDeky6nDAyHYEtmSi2X1PG9YpqE+2BRTJT7JvPix8K8JX1wBWQNao6KcPtmZpttQHUHmzMcd/rne7lFesSzUKQ==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.11.0.tgz", + "integrity": "sha512-Hp81uTjjdTk3FLh/dggU5NK7EIsVWc5/ZDWrIldmf2rBuPejuZ13CZ/wpVE2SToyi4EiroPTQ1XJcJuZFIxTtw==", "license": "MIT", "dependencies": { "@formatjs/ecma402-abstract": "2.3.2", @@ -1345,9 +1345,9 @@ "link": true }, "node_modules/@immich/ui": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/@immich/ui/-/ui-0.15.0.tgz", - "integrity": "sha512-vGDNEOGj5Ma/BAIgj31M1roAVoEOVWws5lkgt1xPlIxSHk4pMhGRFMQaJaCsfXeX/nTRsQCd3gOk7Yo0XNrVfg==", + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/@immich/ui/-/ui-0.16.0.tgz", + "integrity": "sha512-itSOu0r7drZ46qJ+9eNNyq5YZVRAeUKwjRdzBUd6uz4Csy3oEDoepEtWF1EHDaph2XUcKJrNvQPUvETTWeQC6g==", "license": "GNU Affero General Public License version 3", "dependencies": { "@mdi/js": "^7.4.47", @@ -1743,9 +1743,9 @@ "dev": true }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.28.1.tgz", - "integrity": "sha512-2aZp8AES04KI2dy3Ss6/MDjXbwBzj+i0GqKtWXgw2/Ma6E4jJvujryO6gJAghIRVz7Vwr9Gtl/8na3nDUKpraQ==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.6.tgz", + "integrity": "sha512-+GcCXtOQoWuC7hhX1P00LqjjIiS/iOouHXhMdiDSnq/1DGTox4SpUvO52Xm+div6+106r+TcvOeo/cxvyEyTgg==", "cpu": [ "arm" ], @@ -1757,9 +1757,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.28.1.tgz", - "integrity": "sha512-EbkK285O+1YMrg57xVA+Dp0tDBRB93/BZKph9XhMjezf6F4TpYjaUSuPt5J0fZXlSag0LmZAsTmdGGqPp4pQFA==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.6.tgz", + "integrity": "sha512-E8+2qCIjciYUnCa1AiVF1BkRgqIGW9KzJeesQqVfyRITGQN+dFuoivO0hnro1DjT74wXLRZ7QF8MIbz+luGaJA==", "cpu": [ "arm64" ], @@ -1771,9 +1771,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.28.1.tgz", - "integrity": "sha512-prduvrMKU6NzMq6nxzQw445zXgaDBbMQvmKSJaxpaZ5R1QDM8w+eGxo6Y/jhT/cLoCvnZI42oEqf9KQNYz1fqQ==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.6.tgz", + "integrity": "sha512-z9Ib+OzqN3DZEjX7PDQMHEhtF+t6Mi2z/ueChQPLS/qUMKY7Ybn5A2ggFoKRNRh1q1T03YTQfBTQCJZiepESAg==", "cpu": [ "arm64" ], @@ -1785,9 +1785,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.28.1.tgz", - "integrity": "sha512-WsvbOunsUk0wccO/TV4o7IKgloJ942hVFK1CLatwv6TJspcCZb9umQkPdvB7FihmdxgaKR5JyxDjWpCOp4uZlQ==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.6.tgz", + "integrity": "sha512-PShKVY4u0FDAR7jskyFIYVyHEPCPnIQY8s5OcXkdU8mz3Y7eXDJPdyM/ZWjkYdR2m0izD9HHWA8sGcXn+Qrsyg==", "cpu": [ "x64" ], @@ -1799,9 +1799,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.28.1.tgz", - "integrity": "sha512-HTDPdY1caUcU4qK23FeeGxCdJF64cKkqajU0iBnTVxS8F7H/7BewvYoG+va1KPSL63kQ1PGNyiwKOfReavzvNA==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.6.tgz", + "integrity": "sha512-YSwyOqlDAdKqs0iKuqvRHLN4SrD2TiswfoLfvYXseKbL47ht1grQpq46MSiQAx6rQEN8o8URtpXARCpqabqxGQ==", "cpu": [ "arm64" ], @@ -1813,9 +1813,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.28.1.tgz", - "integrity": "sha512-m/uYasxkUevcFTeRSM9TeLyPe2QDuqtjkeoTpP9SW0XxUWfcYrGDMkO/m2tTw+4NMAF9P2fU3Mw4ahNvo7QmsQ==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.6.tgz", + "integrity": "sha512-HEP4CgPAY1RxXwwL5sPFv6BBM3tVeLnshF03HMhJYCNc6kvSqBgTMmsEjb72RkZBAWIqiPUyF1JpEBv5XT9wKQ==", "cpu": [ "x64" ], @@ -1827,9 +1827,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.28.1.tgz", - "integrity": "sha512-QAg11ZIt6mcmzpNE6JZBpKfJaKkqTm1A9+y9O+frdZJEuhQxiugM05gnCWiANHj4RmbgeVJpTdmKRmH/a+0QbA==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.6.tgz", + "integrity": "sha512-88fSzjC5xeH9S2Vg3rPgXJULkHcLYMkh8faix8DX4h4TIAL65ekwuQMA/g2CXq8W+NJC43V6fUpYZNjaX3+IIg==", "cpu": [ "arm" ], @@ -1841,9 +1841,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.28.1.tgz", - "integrity": "sha512-dRP9PEBfolq1dmMcFqbEPSd9VlRuVWEGSmbxVEfiq2cs2jlZAl0YNxFzAQS2OrQmsLBLAATDMb3Z6MFv5vOcXg==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.6.tgz", + "integrity": "sha512-wM4ztnutBqYFyvNeR7Av+reWI/enK9tDOTKNF+6Kk2Q96k9bwhDDOlnCUNRPvromlVXo04riSliMBs/Z7RteEg==", "cpu": [ "arm" ], @@ -1855,9 +1855,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.28.1.tgz", - "integrity": "sha512-uGr8khxO+CKT4XU8ZUH1TTEUtlktK6Kgtv0+6bIFSeiSlnGJHG1tSFSjm41uQ9sAO/5ULx9mWOz70jYLyv1QkA==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.6.tgz", + "integrity": "sha512-9RyprECbRa9zEjXLtvvshhw4CMrRa3K+0wcp3KME0zmBe1ILmvcVHnypZ/aIDXpRyfhSYSuN4EPdCCj5Du8FIA==", "cpu": [ "arm64" ], @@ -1869,9 +1869,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.28.1.tgz", - "integrity": "sha512-QF54q8MYGAqMLrX2t7tNpi01nvq5RI59UBNx+3+37zoKX5KViPo/gk2QLhsuqok05sSCRluj0D00LzCwBikb0A==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.6.tgz", + "integrity": "sha512-qTmklhCTyaJSB05S+iSovfo++EwnIEZxHkzv5dep4qoszUMX5Ca4WM4zAVUMbfdviLgCSQOu5oU8YoGk1s6M9Q==", "cpu": [ "arm64" ], @@ -1883,9 +1883,9 @@ ] }, "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.28.1.tgz", - "integrity": "sha512-vPul4uodvWvLhRco2w0GcyZcdyBfpfDRgNKU+p35AWEbJ/HPs1tOUrkSueVbBS0RQHAf/A+nNtDpvw95PeVKOA==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.34.6.tgz", + "integrity": "sha512-4Qmkaps9yqmpjY5pvpkfOerYgKNUGzQpFxV6rnS7c/JfYbDSU0y6WpbbredB5cCpLFGJEqYX40WUmxMkwhWCjw==", "cpu": [ "loong64" ], @@ -1897,9 +1897,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.28.1.tgz", - "integrity": "sha512-pTnTdBuC2+pt1Rmm2SV7JWRqzhYpEILML4PKODqLz+C7Ou2apEV52h19CR7es+u04KlqplggmN9sqZlekg3R1A==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.34.6.tgz", + "integrity": "sha512-Zsrtux3PuaxuBTX/zHdLaFmcofWGzaWW1scwLU3ZbW/X+hSsFbz9wDIp6XvnT7pzYRl9MezWqEqKy7ssmDEnuQ==", "cpu": [ "ppc64" ], @@ -1911,9 +1911,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.28.1.tgz", - "integrity": "sha512-vWXy1Nfg7TPBSuAncfInmAI/WZDd5vOklyLJDdIRKABcZWojNDY0NJwruY2AcnCLnRJKSaBgf/GiJfauu8cQZA==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.6.tgz", + "integrity": "sha512-aK+Zp+CRM55iPrlyKiU3/zyhgzWBxLVrw2mwiQSYJRobCURb781+XstzvA8Gkjg/hbdQFuDw44aUOxVQFycrAg==", "cpu": [ "riscv64" ], @@ -1925,9 +1925,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.28.1.tgz", - "integrity": "sha512-/yqC2Y53oZjb0yz8PVuGOQQNOTwxcizudunl/tFs1aLvObTclTwZ0JhXF2XcPT/zuaymemCDSuuUPXJJyqeDOg==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.6.tgz", + "integrity": "sha512-WoKLVrY9ogmaYPXwTH326+ErlCIgMmsoRSx6bO+l68YgJnlOXhygDYSZe/qbUJCSiCiZAQ+tKm88NcWuUXqOzw==", "cpu": [ "s390x" ], @@ -1939,9 +1939,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.28.1.tgz", - "integrity": "sha512-fzgeABz7rrAlKYB0y2kSEiURrI0691CSL0+KXwKwhxvj92VULEDQLpBYLHpF49MSiPG4sq5CK3qHMnb9tlCjBw==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.6.tgz", + "integrity": "sha512-Sht4aFvmA4ToHd2vFzwMFaQCiYm2lDFho5rPcvPBT5pCdC+GwHG6CMch4GQfmWTQ1SwRKS0dhDYb54khSrjDWw==", "cpu": [ "x64" ], @@ -1953,9 +1953,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.28.1.tgz", - "integrity": "sha512-xQTDVzSGiMlSshpJCtudbWyRfLaNiVPXt1WgdWTwWz9n0U12cI2ZVtWe/Jgwyv/6wjL7b66uu61Vg0POWVfz4g==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.6.tgz", + "integrity": "sha512-zmmpOQh8vXc2QITsnCiODCDGXFC8LMi64+/oPpPx5qz3pqv0s6x46ps4xoycfUiVZps5PFn1gksZzo4RGTKT+A==", "cpu": [ "x64" ], @@ -1967,9 +1967,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.28.1.tgz", - "integrity": "sha512-wSXmDRVupJstFP7elGMgv+2HqXelQhuNf+IS4V+nUpNVi/GUiBgDmfwD0UGN3pcAnWsgKG3I52wMOBnk1VHr/A==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.6.tgz", + "integrity": "sha512-3/q1qUsO/tLqGBaD4uXsB6coVGB3usxw3qyeVb59aArCgedSF66MPdgRStUd7vbZOsko/CgVaY5fo2vkvPLWiA==", "cpu": [ "arm64" ], @@ -1981,9 +1981,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.28.1.tgz", - "integrity": "sha512-ZkyTJ/9vkgrE/Rk9vhMXhf8l9D+eAhbAVbsGsXKy2ohmJaWg0LPQLnIxRdRp/bKyr8tXuPlXhIoGlEB5XpJnGA==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.6.tgz", + "integrity": "sha512-oLHxuyywc6efdKVTxvc0135zPrRdtYVjtVD5GUm55I3ODxhU/PwkQFD97z16Xzxa1Fz0AEe4W/2hzRtd+IfpOA==", "cpu": [ "ia32" ], @@ -1995,9 +1995,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.28.1.tgz", - "integrity": "sha512-ZvK2jBafvttJjoIdKm/Q/Bh7IJ1Ose9IBOwpOXcOvW3ikGTQGmKDgxTC6oCAzW6PynbkKP8+um1du81XJHZ0JA==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.6.tgz", + "integrity": "sha512-0PVwmgzZ8+TZ9oGBmdZoQVXflbvuwzN/HRclujpl4N/q3i+y0lqLw8n1bXA8ru3sApDjlmONaNAuYr38y1Kr9w==", "cpu": [ "x64" ], @@ -2042,9 +2042,9 @@ } }, "node_modules/@sveltejs/kit": { - "version": "2.16.0", - "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.16.0.tgz", - "integrity": "sha512-S9i1ZWKqluzoaJ6riYnEdbe+xJluMTMkhABouBa66GaWcAyCjW/jAc0NdJQJ/DXyK1CnP5quBW25e99MNyvLxA==", + "version": "2.17.1", + "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.17.1.tgz", + "integrity": "sha512-CpoGSLqE2MCmcQwA2CWJvOsZ9vW+p/1H3itrFykdgajUNAEyQPbsaSn7fZb6PLHQwe+07njxje9ss0fjZoCAyw==", "dev": true, "license": "MIT", "dependencies": { @@ -2357,9 +2357,9 @@ } }, "node_modules/@testing-library/user-event": { - "version": "14.6.0", - "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.6.0.tgz", - "integrity": "sha512-+jsfK7kVJbqnCYtLTln8Ja/NmVrZRwBJHmHR9IxIVccMWSOZ6Oy0FkDJNeyVu4QSpMNmRfy10Xb76ObRDlWWBQ==", + "version": "14.6.1", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.6.1.tgz", + "integrity": "sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw==", "dev": true, "license": "MIT", "engines": { @@ -2492,21 +2492,21 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.20.0.tgz", - "integrity": "sha512-naduuphVw5StFfqp4Gq4WhIBE2gN1GEmMUExpJYknZJdRnc+2gDzB8Z3+5+/Kv33hPQRDGzQO/0opHE72lZZ6A==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.23.0.tgz", + "integrity": "sha512-vBz65tJgRrA1Q5gWlRfvoH+w943dq9K1p1yDBY2pc+a1nbBLZp7fB9+Hk8DaALUbzjqlMfgaqlVPT1REJdkt/w==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.20.0", - "@typescript-eslint/type-utils": "8.20.0", - "@typescript-eslint/utils": "8.20.0", - "@typescript-eslint/visitor-keys": "8.20.0", + "@typescript-eslint/scope-manager": "8.23.0", + "@typescript-eslint/type-utils": "8.23.0", + "@typescript-eslint/utils": "8.23.0", + "@typescript-eslint/visitor-keys": "8.23.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", - "ts-api-utils": "^2.0.0" + "ts-api-utils": "^2.0.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2522,16 +2522,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.20.0.tgz", - "integrity": "sha512-gKXG7A5HMyjDIedBi6bUrDcun8GIjnI8qOwVLiY3rx6T/sHP/19XLJOnIq/FgQvWLHja5JN/LSE7eklNBr612g==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.23.0.tgz", + "integrity": "sha512-h2lUByouOXFAlMec2mILeELUbME5SZRN/7R9Cw2RD2lRQQY08MWMM+PmVVKKJNK1aIwqTo9t/0CvOxwPbRIE2Q==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.20.0", - "@typescript-eslint/types": "8.20.0", - "@typescript-eslint/typescript-estree": "8.20.0", - "@typescript-eslint/visitor-keys": "8.20.0", + "@typescript-eslint/scope-manager": "8.23.0", + "@typescript-eslint/types": "8.23.0", + "@typescript-eslint/typescript-estree": "8.23.0", + "@typescript-eslint/visitor-keys": "8.23.0", "debug": "^4.3.4" }, "engines": { @@ -2547,14 +2547,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.20.0.tgz", - "integrity": "sha512-J7+VkpeGzhOt3FeG1+SzhiMj9NzGD/M6KoGn9f4dbz3YzK9hvbhVTmLj/HiTp9DazIzJ8B4XcM80LrR9Dm1rJw==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.23.0.tgz", + "integrity": "sha512-OGqo7+dXHqI7Hfm+WqkZjKjsiRtFUQHPdGMXzk5mYXhJUedO7e/Y7i8AK3MyLMgZR93TX4bIzYrfyVjLC+0VSw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.20.0", - "@typescript-eslint/visitor-keys": "8.20.0" + "@typescript-eslint/types": "8.23.0", + "@typescript-eslint/visitor-keys": "8.23.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2565,16 +2565,16 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.20.0.tgz", - "integrity": "sha512-bPC+j71GGvA7rVNAHAtOjbVXbLN5PkwqMvy1cwGeaxUoRQXVuKCebRoLzm+IPW/NtFFpstn1ummSIasD5t60GA==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.23.0.tgz", + "integrity": "sha512-iIuLdYpQWZKbiH+RkCGc6iu+VwscP5rCtQ1lyQ7TYuKLrcZoeJVpcLiG8DliXVkUxirW/PWlmS+d6yD51L9jvA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.20.0", - "@typescript-eslint/utils": "8.20.0", + "@typescript-eslint/typescript-estree": "8.23.0", + "@typescript-eslint/utils": "8.23.0", "debug": "^4.3.4", - "ts-api-utils": "^2.0.0" + "ts-api-utils": "^2.0.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2589,9 +2589,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.20.0.tgz", - "integrity": "sha512-cqaMiY72CkP+2xZRrFt3ExRBu0WmVitN/rYPZErA80mHjHx/Svgp8yfbzkJmDoQ/whcytOPO9/IZXnOc+wigRA==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.23.0.tgz", + "integrity": "sha512-1sK4ILJbCmZOTt9k4vkoulT6/y5CHJ1qUYxqpF1K/DBAd8+ZUL4LlSCxOssuH5m4rUaaN0uS0HlVPvd45zjduQ==", "dev": true, "license": "MIT", "engines": { @@ -2603,20 +2603,20 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.20.0.tgz", - "integrity": "sha512-Y7ncuy78bJqHI35NwzWol8E0X7XkRVS4K4P4TCyzWkOJih5NDvtoRDW4Ba9YJJoB2igm9yXDdYI/+fkiiAxPzA==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.23.0.tgz", + "integrity": "sha512-LcqzfipsB8RTvH8FX24W4UUFk1bl+0yTOf9ZA08XngFwMg4Kj8A+9hwz8Cr/ZS4KwHrmo9PJiLZkOt49vPnuvQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.20.0", - "@typescript-eslint/visitor-keys": "8.20.0", + "@typescript-eslint/types": "8.23.0", + "@typescript-eslint/visitor-keys": "8.23.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", - "ts-api-utils": "^2.0.0" + "ts-api-utils": "^2.0.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2656,16 +2656,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.20.0.tgz", - "integrity": "sha512-dq70RUw6UK9ei7vxc4KQtBRk7qkHZv447OUZ6RPQMQl71I3NZxQJX/f32Smr+iqWrB02pHKn2yAdHBb0KNrRMA==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.23.0.tgz", + "integrity": "sha512-uB/+PSo6Exu02b5ZEiVtmY6RVYO7YU5xqgzTIVZwTHvvK3HsL8tZZHFaTLFtRG3CsV4A5mhOv+NZx5BlhXPyIA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.20.0", - "@typescript-eslint/types": "8.20.0", - "@typescript-eslint/typescript-estree": "8.20.0" + "@typescript-eslint/scope-manager": "8.23.0", + "@typescript-eslint/types": "8.23.0", + "@typescript-eslint/typescript-estree": "8.23.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2680,13 +2680,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.20.0.tgz", - "integrity": "sha512-v/BpkeeYAsPkKCkR8BDwcno0llhzWVqPOamQrAEMdpZav2Y9OVjd9dwJyBLJWwf335B5DmlifECIkZRJCaGaHA==", + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.23.0.tgz", + "integrity": "sha512-oWWhcWDLwDfu++BGTZcmXWqpwtkwb5o7fxUIGksMQQDSdPW9prsSnfIOZMlsj4vBOSrcnjIUZMiIjODgGosFhQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.20.0", + "@typescript-eslint/types": "8.23.0", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -2711,9 +2711,9 @@ } }, "node_modules/@vitest/coverage-v8": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.0.3.tgz", - "integrity": "sha512-uVbJ/xhImdNtzPnLyxCZJMTeTIYdgcC2nWtBBBpR1H6z0w8m7D+9/zrDIx2nNxgMg9r+X8+RY2qVpUDeW2b3nw==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.0.5.tgz", + "integrity": "sha512-zOOWIsj5fHh3jjGwQg+P+J1FW3s4jBu1Zqga0qW60yutsBtqEqNEJKWYh7cYn1yGD+1bdPsPdC/eL4eVK56xMg==", "dev": true, "license": "MIT", "dependencies": { @@ -2734,8 +2734,8 @@ "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "@vitest/browser": "3.0.3", - "vitest": "3.0.3" + "@vitest/browser": "3.0.5", + "vitest": "3.0.5" }, "peerDependenciesMeta": { "@vitest/browser": { @@ -2762,14 +2762,14 @@ } }, "node_modules/@vitest/expect": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.3.tgz", - "integrity": "sha512-SbRCHU4qr91xguu+dH3RUdI5dC86zm8aZWydbp961aIR7G8OYNN6ZiayFuf9WAngRbFOfdrLHCGgXTj3GtoMRQ==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.5.tgz", + "integrity": "sha512-nNIOqupgZ4v5jWuQx2DSlHLEs7Q4Oh/7AYwNyE+k0UQzG7tSmjPXShUikn1mpNGzYEN2jJbTvLejwShMitovBA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "3.0.3", - "@vitest/utils": "3.0.3", + "@vitest/spy": "3.0.5", + "@vitest/utils": "3.0.5", "chai": "^5.1.2", "tinyrainbow": "^2.0.0" }, @@ -2778,13 +2778,13 @@ } }, "node_modules/@vitest/mocker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.3.tgz", - "integrity": "sha512-XT2XBc4AN9UdaxJAeIlcSZ0ILi/GzmG5G8XSly4gaiqIvPV3HMTSIDZWJVX6QRJ0PX1m+W8Cy0K9ByXNb/bPIA==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.5.tgz", + "integrity": "sha512-CLPNBFBIE7x6aEGbIjaQAX03ZZlBMaWwAjBdMkIf/cAn6xzLTiM3zYqO/WAbieEjsAZir6tO71mzeHZoodThvw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "3.0.3", + "@vitest/spy": "3.0.5", "estree-walker": "^3.0.3", "magic-string": "^0.30.17" }, @@ -2805,9 +2805,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.3.tgz", - "integrity": "sha512-gCrM9F7STYdsDoNjGgYXKPq4SkSxwwIU5nkaQvdUxiQ0EcNlez+PdKOVIsUJvh9P9IeIFmjn4IIREWblOBpP2Q==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.5.tgz", + "integrity": "sha512-CjUtdmpOcm4RVtB+up8r2vVDLR16Mgm/bYdkGFe3Yj/scRfCpbSi2W/BDSDcFK7ohw8UXvjMbOp9H4fByd/cOA==", "dev": true, "license": "MIT", "dependencies": { @@ -2818,38 +2818,38 @@ } }, "node_modules/@vitest/runner": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.3.tgz", - "integrity": "sha512-Rgi2kOAk5ZxWZlwPguRJFOBmWs6uvvyAAR9k3MvjRvYrG7xYvKChZcmnnpJCS98311CBDMqsW9MzzRFsj2gX3g==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.5.tgz", + "integrity": "sha512-BAiZFityFexZQi2yN4OX3OkJC6scwRo8EhRB0Z5HIGGgd2q+Nq29LgHU/+ovCtd0fOfXj5ZI6pwdlUmC5bpi8A==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "3.0.3", - "pathe": "^2.0.1" + "@vitest/utils": "3.0.5", + "pathe": "^2.0.2" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/snapshot": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.3.tgz", - "integrity": "sha512-kNRcHlI4txBGztuJfPEJ68VezlPAXLRT1u5UCx219TU3kOG2DplNxhWLwDf2h6emwmTPogzLnGVwP6epDaJN6Q==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.5.tgz", + "integrity": "sha512-GJPZYcd7v8QNUJ7vRvLDmRwl+a1fGg4T/54lZXe+UOGy47F9yUfE18hRCtXL5aHN/AONu29NGzIXSVFh9K0feA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.0.3", + "@vitest/pretty-format": "3.0.5", "magic-string": "^0.30.17", - "pathe": "^2.0.1" + "pathe": "^2.0.2" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/spy": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.3.tgz", - "integrity": "sha512-7/dgux8ZBbF7lEIKNnEqQlyRaER9nkAL9eTmdKJkDO3hS8p59ATGwKOCUDHcBLKr7h/oi/6hP+7djQk8049T2A==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.5.tgz", + "integrity": "sha512-5fOzHj0WbUNqPK6blI/8VzZdkBlQLnT25knX0r4dbZI9qoZDf3qAdjoMmDcLG5A83W6oUUFJgUd0EYBc2P5xqg==", "dev": true, "license": "MIT", "dependencies": { @@ -2860,13 +2860,13 @@ } }, "node_modules/@vitest/utils": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.3.tgz", - "integrity": "sha512-f+s8CvyzPtMFY1eZKkIHGhPsQgYo5qCm6O8KZoim9qm1/jT64qBgGpO5tHscNH6BzRHM+edLNOP+3vO8+8pE/A==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.5.tgz", + "integrity": "sha512-N9AX0NUoUtVwKwy21JtwzaqR5L5R5A99GAbrHfCCXK1lp593i/3AZAXhSP43wRQuxYsflrdzEfXZFo1reR1Nkg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.0.3", + "@vitest/pretty-format": "3.0.5", "loupe": "^3.1.2", "tinyrainbow": "^2.0.0" }, @@ -3786,16 +3786,16 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/engine.io-client": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.4.tgz", - "integrity": "sha512-GeZeeRjpD2qf49cZQ0Wvh/8NJNfeXkXXcoGh+F77oEAgo9gUHwT1fCRxSNU+YEEaysOJTnsFHmM5oAcPy4ntvQ==", + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.3.tgz", + "integrity": "sha512-T0iLjnyNWahNyv/lcjS2y4oE358tVS/SYQNxYXGAJ9/GLgH4VCvOQ/mhTjqU88mLZCQgiG8RIegFHYCdVC+j5w==", "license": "MIT", "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1", "engine.io-parser": "~5.2.1", "ws": "~8.17.1", - "xmlhttprequest-ssl": "~2.0.0" + "xmlhttprequest-ssl": "~2.1.1" } }, "node_modules/engine.io-parser": { @@ -3946,9 +3946,9 @@ } }, "node_modules/eslint": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.18.0.tgz", - "integrity": "sha512-+waTfRWQlSbpt3KWE+CjrPPYnbq9kfZIYUqapc0uBXyjTp8aYXZDsUH16m39Ryq3NjAVP4tjuF7KaukeqoCoaA==", + "version": "9.19.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.19.0.tgz", + "integrity": "sha512-ug92j0LepKlbbEv6hD911THhoRHmbdXt2gX+VDABAW/Ir7D3nqKdv5Pf5vtlyY6HQMTEP2skXY43ueqTCWssEA==", "dev": true, "license": "MIT", "dependencies": { @@ -3957,7 +3957,7 @@ "@eslint/config-array": "^0.19.0", "@eslint/core": "^0.10.0", "@eslint/eslintrc": "^3.2.0", - "@eslint/js": "9.18.0", + "@eslint/js": "9.19.0", "@eslint/plugin-kit": "^0.2.5", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", @@ -5005,14 +5005,14 @@ } }, "node_modules/intl-messageformat": { - "version": "10.7.12", - "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-10.7.12.tgz", - "integrity": "sha512-4HBsPDJ61jZwNikauvm0mcLvs1AfCBbihiqOX2AGs1MX7SA1H0SNKJRSWxpZpToGoNzvoYLsJJ2pURkbEDg+Dw==", + "version": "10.7.14", + "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-10.7.14.tgz", + "integrity": "sha512-mMGnE4E1otdEutV5vLUdCxRJygHB5ozUBxsPB5qhitewssrS/qGruq9bmvIRkkGsNeK5ZWLfYRld18UHGTIifQ==", "license": "BSD-3-Clause", "dependencies": { "@formatjs/ecma402-abstract": "2.3.2", "@formatjs/fast-memoize": "2.2.6", - "@formatjs/icu-messageformat-parser": "2.10.0", + "@formatjs/icu-messageformat-parser": "2.11.0", "tslib": "2" } }, @@ -5479,9 +5479,9 @@ "dev": true }, "node_modules/loupe": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.2.tgz", - "integrity": "sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.3.tgz", + "integrity": "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==", "dev": true, "license": "MIT" }, @@ -6711,9 +6711,9 @@ } }, "node_modules/rollup": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.28.1.tgz", - "integrity": "sha512-61fXYl/qNVinKmGSTHAZ6Yy8I3YIJC/r2m9feHo6SwVAVcLT5MPwOUFe7EuURA/4m0NR8lXG4BBXuo/IZEsjMg==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.6.tgz", + "integrity": "sha512-wc2cBWqJgkU3Iz5oztRkQbfVkbxoz5EhnCGOrnJvnLnQ7O0WhQUYyv18qQI79O8L7DdHrrlJNeCHd4VGpnaXKQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6727,25 +6727,25 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.28.1", - "@rollup/rollup-android-arm64": "4.28.1", - "@rollup/rollup-darwin-arm64": "4.28.1", - "@rollup/rollup-darwin-x64": "4.28.1", - "@rollup/rollup-freebsd-arm64": "4.28.1", - "@rollup/rollup-freebsd-x64": "4.28.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.28.1", - "@rollup/rollup-linux-arm-musleabihf": "4.28.1", - "@rollup/rollup-linux-arm64-gnu": "4.28.1", - "@rollup/rollup-linux-arm64-musl": "4.28.1", - "@rollup/rollup-linux-loongarch64-gnu": "4.28.1", - "@rollup/rollup-linux-powerpc64le-gnu": "4.28.1", - "@rollup/rollup-linux-riscv64-gnu": "4.28.1", - "@rollup/rollup-linux-s390x-gnu": "4.28.1", - "@rollup/rollup-linux-x64-gnu": "4.28.1", - "@rollup/rollup-linux-x64-musl": "4.28.1", - "@rollup/rollup-win32-arm64-msvc": "4.28.1", - "@rollup/rollup-win32-ia32-msvc": "4.28.1", - "@rollup/rollup-win32-x64-msvc": "4.28.1", + "@rollup/rollup-android-arm-eabi": "4.34.6", + "@rollup/rollup-android-arm64": "4.34.6", + "@rollup/rollup-darwin-arm64": "4.34.6", + "@rollup/rollup-darwin-x64": "4.34.6", + "@rollup/rollup-freebsd-arm64": "4.34.6", + "@rollup/rollup-freebsd-x64": "4.34.6", + "@rollup/rollup-linux-arm-gnueabihf": "4.34.6", + "@rollup/rollup-linux-arm-musleabihf": "4.34.6", + "@rollup/rollup-linux-arm64-gnu": "4.34.6", + "@rollup/rollup-linux-arm64-musl": "4.34.6", + "@rollup/rollup-linux-loongarch64-gnu": "4.34.6", + "@rollup/rollup-linux-powerpc64le-gnu": "4.34.6", + "@rollup/rollup-linux-riscv64-gnu": "4.34.6", + "@rollup/rollup-linux-s390x-gnu": "4.34.6", + "@rollup/rollup-linux-x64-gnu": "4.34.6", + "@rollup/rollup-linux-x64-musl": "4.34.6", + "@rollup/rollup-win32-arm64-msvc": "4.34.6", + "@rollup/rollup-win32-ia32-msvc": "4.34.6", + "@rollup/rollup-win32-x64-msvc": "4.34.6", "fsevents": "~2.3.2" } }, @@ -7037,14 +7037,14 @@ } }, "node_modules/socket.io-client": { - "version": "4.7.5", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.5.tgz", - "integrity": "sha512-sJ/tqHOCe7Z50JCBCXrsY3I2k03iOiUe+tj1OmKeD2lXPiGH/RUCdTZFoqVyN7l1MnpIzPrGtLcijffmeouNlQ==", + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.8.1.tgz", + "integrity": "sha512-hJVXfu3E28NmzGk8o1sHhN3om52tRvwYeidbj7xKy2eIIse5IoKX3USlS6Tqt3BHAtflLIkCQBkzVrEEfWUyYQ==", "license": "MIT", "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.2", - "engine.io-client": "~6.5.2", + "engine.io-client": "~6.6.1", "socket.io-parser": "~4.2.4" }, "engines": { @@ -7338,9 +7338,9 @@ } }, "node_modules/svelte": { - "version": "5.19.0", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.19.0.tgz", - "integrity": "sha512-qvd2GvvYnJxS/MteQKFSMyq8cQrAAut28QZ39ySv9k3ggmhw4Au4Rfcsqva74i0xMys//OhbhVCNfXPrDzL/Bg==", + "version": "5.19.8", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.19.8.tgz", + "integrity": "sha512-56Vd/nwJrljV0w7RCV1A8sB4/yjSbWW5qrGDTAzp7q42OxwqEWT+6obWzDt41tHjIW+C9Fs2ygtejjJrXR+ZPA==", "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.3.0", @@ -8321,9 +8321,9 @@ } }, "node_modules/ts-api-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.0.tgz", - "integrity": "sha512-xCt/TOAc+EOHS1XPnijD3/yzpH6qg2xppZO1YDqGoVsNXfQfzHpOdNuXwrwOU8u4ITXJyDCTyt8w5g1sZv9ynQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.1.tgz", + "integrity": "sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w==", "dev": true, "license": "MIT", "engines": { @@ -8493,15 +8493,15 @@ } }, "node_modules/vite": { - "version": "6.0.11", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.0.11.tgz", - "integrity": "sha512-4VL9mQPKoHy4+FE0NnRE/kbY51TOfaknxAjt3fJbGJxhIpBZiqVzlZDEesWWsuREXHwNdAoOFZ9MkPEVXczHwg==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.1.0.tgz", + "integrity": "sha512-RjjMipCKVoR4hVfPY6GQTgveinjNuyLw+qruksLDvA5ktI1150VmcMBKmQaEWJhg/j6Uaf6dNCNA0AfdzUb/hQ==", "dev": true, "license": "MIT", "dependencies": { "esbuild": "^0.24.2", - "postcss": "^8.4.49", - "rollup": "^4.23.0" + "postcss": "^8.5.1", + "rollup": "^4.30.1" }, "bin": { "vite": "bin/vite.js" @@ -8578,16 +8578,16 @@ } }, "node_modules/vite-node": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.3.tgz", - "integrity": "sha512-0sQcwhwAEw/UJGojbhOrnq3HtiZ3tC7BzpAa0lx3QaTX0S3YX70iGcik25UBdB96pmdwjyY2uyKNYruxCDmiEg==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.5.tgz", + "integrity": "sha512-02JEJl7SbtwSDJdYS537nU6l+ktdvcREfLksk/NDAqtdKWGqHl+joXzEubHROmS3E6pip+Xgu2tFezMu75jH7A==", "dev": true, "license": "MIT", "dependencies": { "cac": "^6.7.14", "debug": "^4.4.0", "es-module-lexer": "^1.6.0", - "pathe": "^2.0.1", + "pathe": "^2.0.2", "vite": "^5.0.0 || ^6.0.0" }, "bin": { @@ -8638,31 +8638,31 @@ } }, "node_modules/vitest": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.3.tgz", - "integrity": "sha512-dWdwTFUW9rcnL0LyF2F+IfvNQWB0w9DERySCk8VMG75F8k25C7LsZoh6XfCjPvcR8Nb+Lqi9JKr6vnzH7HSrpQ==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.5.tgz", + "integrity": "sha512-4dof+HvqONw9bvsYxtkfUp2uHsTN9bV2CZIi1pWgoFpL1Lld8LA1ka9q/ONSsoScAKG7NVGf2stJTI7XRkXb2Q==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/expect": "3.0.3", - "@vitest/mocker": "3.0.3", - "@vitest/pretty-format": "^3.0.3", - "@vitest/runner": "3.0.3", - "@vitest/snapshot": "3.0.3", - "@vitest/spy": "3.0.3", - "@vitest/utils": "3.0.3", + "@vitest/expect": "3.0.5", + "@vitest/mocker": "3.0.5", + "@vitest/pretty-format": "^3.0.5", + "@vitest/runner": "3.0.5", + "@vitest/snapshot": "3.0.5", + "@vitest/spy": "3.0.5", + "@vitest/utils": "3.0.5", "chai": "^5.1.2", "debug": "^4.4.0", "expect-type": "^1.1.0", "magic-string": "^0.30.17", - "pathe": "^2.0.1", + "pathe": "^2.0.2", "std-env": "^3.8.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", "tinypool": "^1.0.2", "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0", - "vite-node": "3.0.3", + "vite-node": "3.0.5", "why-is-node-running": "^2.3.0" }, "bin": { @@ -8676,9 +8676,10 @@ }, "peerDependencies": { "@edge-runtime/vm": "*", + "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "@vitest/browser": "3.0.3", - "@vitest/ui": "3.0.3", + "@vitest/browser": "3.0.5", + "@vitest/ui": "3.0.5", "happy-dom": "*", "jsdom": "*" }, @@ -8686,6 +8687,9 @@ "@edge-runtime/vm": { "optional": true }, + "@types/debug": { + "optional": true + }, "@types/node": { "optional": true }, @@ -8969,9 +8973,9 @@ "peer": true }, "node_modules/xmlhttprequest-ssl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz", - "integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz", + "integrity": "sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==", "engines": { "node": ">=0.4.0" } diff --git a/web/package.json b/web/package.json index 47934ce7e24e4..d8e470d658715 100644 --- a/web/package.json +++ b/web/package.json @@ -67,7 +67,7 @@ "dependencies": { "@formatjs/icu-messageformat-parser": "^2.9.8", "@immich/sdk": "file:../open-api/typescript-sdk", - "@immich/ui": "^0.15.0", + "@immich/ui": "^0.16.0", "@mapbox/mapbox-gl-rtl-text": "0.2.3", "@mdi/js": "^7.4.47", "@photo-sphere-viewer/core": "^5.11.5", @@ -82,7 +82,7 @@ "justified-layout": "^4.1.0", "lodash-es": "^4.17.21", "luxon": "^3.4.4", - "socket.io-client": "~4.7.5", + "socket.io-client": "~4.8.0", "svelte-gestures": "^5.1.3", "svelte-i18n": "^4.0.1", "svelte-local-storage-store": "^0.6.4", diff --git a/web/src/lib/components/album-page/albums-controls.svelte b/web/src/lib/components/album-page/albums-controls.svelte index b518c56b662e9..1fff0c29a2ae2 100644 --- a/web/src/lib/components/album-page/albums-controls.svelte +++ b/web/src/lib/components/album-page/albums-controls.svelte @@ -175,6 +175,7 @@ color="secondary" shape="round" icon={mdiUnfoldMoreHorizontal} + aria-label={$t('expand_all')} /> @@ -187,6 +188,7 @@ color="secondary" shape="round" icon={mdiUnfoldLessHorizontal} + aria-label={$t('collapse_all')} /> diff --git a/web/src/lib/components/elements/buttons/button.svelte b/web/src/lib/components/elements/buttons/button.svelte index 7e8418e2f5da0..991bbaeceeb8e 100644 --- a/web/src/lib/components/elements/buttons/button.svelte +++ b/web/src/lib/components/elements/buttons/button.svelte @@ -109,7 +109,6 @@ ); - - @@ -86,6 +87,7 @@ color="secondary" shape="round" icon={mdiUnfoldLessHorizontal} + aria-label={$t('collapse_all')} /> diff --git a/web/src/lib/components/shared-components/navigation-bar/navigation-bar.svelte b/web/src/lib/components/shared-components/navigation-bar/navigation-bar.svelte index 2f615b7f3fc4e..10df5a6f0e0e7 100644 --- a/web/src/lib/components/shared-components/navigation-bar/navigation-bar.svelte +++ b/web/src/lib/components/shared-components/navigation-bar/navigation-bar.svelte @@ -94,6 +94,7 @@ title={$t('support_and_feedback')} icon={mdiHelpCircleOutline} onclick={() => (shouldShowHelpPanel = !shouldShowHelpPanel)} + aria-label={$t('support_and_feedback')} /> diff --git a/web/src/routes/(user)/utilities/duplicates/[[photos=photos]]/[[assetId=id]]/+page.svelte b/web/src/routes/(user)/utilities/duplicates/[[photos=photos]]/[[assetId=id]]/+page.svelte index 4627d981b68c3..d517dad943a50 100644 --- a/web/src/routes/(user)/utilities/duplicates/[[photos=photos]]/[[assetId=id]]/+page.svelte +++ b/web/src/routes/(user)/utilities/duplicates/[[photos=photos]]/[[assetId=id]]/+page.svelte @@ -190,6 +190,7 @@ icon={mdiKeyboard} title={$t('show_keyboard_shortcuts')} onclick={() => (isShowKeyboardShortcut = !isShowKeyboardShortcut)} + aria-label={$t('show_keyboard_shortcuts')} /> {/snippet} diff --git a/web/src/routes/admin/user-management/+page.svelte b/web/src/routes/admin/user-management/+page.svelte index 1ad56644f5582..aadbf3e949855 100644 --- a/web/src/routes/admin/user-management/+page.svelte +++ b/web/src/routes/admin/user-management/+page.svelte @@ -170,6 +170,7 @@ variant="ghost" onclick={() => copyToClipboard(newPassword)} title={$t('copy_password')} + aria-label={$t('copy_password')} /> @@ -225,6 +226,7 @@ icon={mdiPencilOutline} title={$t('edit_user')} onclick={() => editUserHandler(immichUser)} + aria-label={$t('edit_user')} /> {#if immichUser.id !== $user.id} deleteUserHandler(immichUser)} + aria-label={$t('delete_user')} /> {/if} {/if} @@ -245,6 +248,7 @@ values: { date: getDeleteDate(immichUser.deletedAt) }, })} onclick={() => restoreUserHandler(immichUser)} + aria-label={$t('admin.user_restore_scheduled_removal')} /> {/if} From 9d85272c2bc8c3470689ac561532dd5b5168bc5d Mon Sep 17 00:00:00 2001 From: Jason Rasmussen Date: Tue, 11 Feb 2025 14:08:13 -0500 Subject: [PATCH 2/5] refactor: repositories (#16036) --- server/src/cores/storage.core.spec.ts | 1 + server/src/cores/storage.core.ts | 24 +- server/src/dtos/asset.dto.ts | 2 +- server/src/dtos/partner.dto.ts | 2 +- server/src/dtos/time-bucket.dto.ts | 2 +- server/src/entities/asset.entity.ts | 4 +- server/src/enum.ts | 7 + server/src/interfaces/album.interface.ts | 35 --- server/src/interfaces/asset.interface.ts | 170 -------------- server/src/interfaces/crypto.interface.ts | 13 -- server/src/interfaces/database.interface.ts | 78 ------- server/src/interfaces/library.interface.ts | 17 -- server/src/interfaces/move.interface.ts | 15 -- server/src/interfaces/partner.interface.ts | 23 -- server/src/interfaces/person.interface.ts | 89 -------- server/src/interfaces/search.interface.ts | 213 ------------------ .../src/interfaces/shared-link.interface.ts | 19 -- server/src/interfaces/stack.interface.ts | 18 -- server/src/interfaces/storage.interface.ts | 57 ----- server/src/interfaces/tag.interface.ts | 21 -- server/src/interfaces/user.interface.ts | 45 ---- .../1700713994428-AddCLIPEmbeddingIndex.ts | 2 +- .../1700714033632-AddFaceEmbeddingIndex.ts | 2 +- .../1718486162779-AddFaceSearchRelation.ts | 2 +- server/src/repositories/album.repository.ts | 14 +- server/src/repositories/asset.repository.ts | 150 ++++++++++-- server/src/repositories/config.repository.ts | 4 +- server/src/repositories/crypto.repository.ts | 5 +- .../src/repositories/database.repository.ts | 64 +++++- server/src/repositories/index.ts | 42 ++-- server/src/repositories/library.repository.ts | 3 +- server/src/repositories/move.repository.ts | 5 +- server/src/repositories/partner.repository.ts | 13 +- server/src/repositories/person.repository.ts | 60 +++-- server/src/repositories/search.repository.ts | 204 +++++++++++++++-- .../repositories/shared-link.repository.ts | 8 +- server/src/repositories/stack.repository.ts | 8 +- server/src/repositories/storage.repository.ts | 36 ++- server/src/repositories/tag.repository.ts | 5 +- server/src/repositories/user.repository.ts | 27 ++- server/src/services/album.service.ts | 2 +- server/src/services/asset.service.spec.ts | 2 +- server/src/services/backup.service.ts | 2 +- server/src/services/base.service.ts | 55 +++-- server/src/services/database.service.spec.ts | 3 +- server/src/services/database.service.ts | 9 +- server/src/services/download.service.ts | 2 +- server/src/services/duplicate.service.spec.ts | 2 +- server/src/services/duplicate.service.ts | 4 +- server/src/services/library.service.ts | 2 +- server/src/services/media.service.spec.ts | 2 +- server/src/services/media.service.ts | 2 +- server/src/services/metadata.service.spec.ts | 2 +- server/src/services/metadata.service.ts | 4 +- server/src/services/partner.service.spec.ts | 2 +- server/src/services/partner.service.ts | 2 +- server/src/services/person.service.spec.ts | 4 +- server/src/services/person.service.ts | 4 +- server/src/services/search.service.ts | 6 +- server/src/services/server.service.ts | 2 +- .../src/services/smart-info.service.spec.ts | 2 +- server/src/services/smart-info.service.ts | 4 +- .../src/services/storage-template.service.ts | 2 +- server/src/services/storage.service.ts | 2 +- server/src/services/tag.service.ts | 2 +- server/src/services/timeline.service.spec.ts | 2 +- server/src/services/timeline.service.ts | 2 +- server/src/services/user-admin.service.ts | 2 +- server/src/services/user.service.ts | 2 +- server/src/services/version.service.ts | 2 +- server/src/utils/asset.util.ts | 8 +- server/src/utils/config.ts | 2 +- server/src/utils/file.ts | 2 +- server/src/utils/tag.ts | 4 +- .../repositories/album.repository.mock.ts | 5 +- .../repositories/asset.repository.mock.ts | 5 +- .../repositories/config.repository.mock.ts | 3 +- .../repositories/crypto.repository.mock.ts | 5 +- .../repositories/database.repository.mock.ts | 5 +- .../repositories/library.repository.mock.ts | 5 +- .../test/repositories/move.repository.mock.ts | 5 +- .../repositories/partner.repository.mock.ts | 5 +- .../repositories/person.repository.mock.ts | 5 +- .../repositories/search.repository.mock.ts | 5 +- .../shared-link.repository.mock.ts | 5 +- .../repositories/stack.repository.mock.ts | 5 +- .../repositories/storage.repository.mock.ts | 5 +- .../test/repositories/tag.repository.mock.ts | 5 +- .../test/repositories/user.repository.mock.ts | 5 +- server/test/utils.ts | 41 ++-- 90 files changed, 686 insertions(+), 1088 deletions(-) delete mode 100644 server/src/interfaces/album.interface.ts delete mode 100644 server/src/interfaces/asset.interface.ts delete mode 100644 server/src/interfaces/crypto.interface.ts delete mode 100644 server/src/interfaces/database.interface.ts delete mode 100644 server/src/interfaces/library.interface.ts delete mode 100644 server/src/interfaces/move.interface.ts delete mode 100644 server/src/interfaces/partner.interface.ts delete mode 100644 server/src/interfaces/person.interface.ts delete mode 100644 server/src/interfaces/search.interface.ts delete mode 100644 server/src/interfaces/shared-link.interface.ts delete mode 100644 server/src/interfaces/stack.interface.ts delete mode 100644 server/src/interfaces/storage.interface.ts delete mode 100644 server/src/interfaces/tag.interface.ts delete mode 100644 server/src/interfaces/user.interface.ts diff --git a/server/src/cores/storage.core.spec.ts b/server/src/cores/storage.core.spec.ts index a6636733066d8..7bb2cdb1bebed 100644 --- a/server/src/cores/storage.core.spec.ts +++ b/server/src/cores/storage.core.spec.ts @@ -5,6 +5,7 @@ vitest.mock('src/constants', () => ({ APP_MEDIA_LOCATION: '/photos', ADDED_IN_PREFIX: 'This property was added in ', DEPRECATED_IN_PREFIX: 'This property was deprecated in ', + IWorker: 'IWorker', })); describe('StorageCore', () => { diff --git a/server/src/cores/storage.core.ts b/server/src/cores/storage.core.ts index 86f7be9ffd4b6..3160331dd4722 100644 --- a/server/src/cores/storage.core.ts +++ b/server/src/cores/storage.core.ts @@ -4,13 +4,13 @@ import { APP_MEDIA_LOCATION } from 'src/constants'; import { AssetEntity } from 'src/entities/asset.entity'; import { PersonEntity } from 'src/entities/person.entity'; import { AssetFileType, AssetPathType, ImageFormat, PathType, PersonPathType, StorageFolder } from 'src/enum'; -import { IAssetRepository } from 'src/interfaces/asset.interface'; -import { IMoveRepository } from 'src/interfaces/move.interface'; -import { IPersonRepository } from 'src/interfaces/person.interface'; -import { IStorageRepository } from 'src/interfaces/storage.interface'; +import { AssetRepository } from 'src/repositories/asset.repository'; import { ConfigRepository } from 'src/repositories/config.repository'; import { CryptoRepository } from 'src/repositories/crypto.repository'; import { LoggingRepository } from 'src/repositories/logging.repository'; +import { MoveRepository } from 'src/repositories/move.repository'; +import { PersonRepository } from 'src/repositories/person.repository'; +import { StorageRepository } from 'src/repositories/storage.repository'; import { SystemMetadataRepository } from 'src/repositories/system-metadata.repository'; import { getAssetFiles } from 'src/utils/asset.util'; import { getConfig } from 'src/utils/config'; @@ -33,23 +33,23 @@ let instance: StorageCore | null; export class StorageCore { private constructor( - private assetRepository: IAssetRepository, + private assetRepository: AssetRepository, private configRepository: ConfigRepository, private cryptoRepository: CryptoRepository, - private moveRepository: IMoveRepository, - private personRepository: IPersonRepository, - private storageRepository: IStorageRepository, + private moveRepository: MoveRepository, + private personRepository: PersonRepository, + private storageRepository: StorageRepository, private systemMetadataRepository: SystemMetadataRepository, private logger: LoggingRepository, ) {} static create( - assetRepository: IAssetRepository, + assetRepository: AssetRepository, configRepository: ConfigRepository, cryptoRepository: CryptoRepository, - moveRepository: IMoveRepository, - personRepository: IPersonRepository, - storageRepository: IStorageRepository, + moveRepository: MoveRepository, + personRepository: PersonRepository, + storageRepository: StorageRepository, systemMetadataRepository: SystemMetadataRepository, logger: LoggingRepository, ) { diff --git a/server/src/dtos/asset.dto.ts b/server/src/dtos/asset.dto.ts index 8aa63f2f6924c..32b14055d5fb0 100644 --- a/server/src/dtos/asset.dto.ts +++ b/server/src/dtos/asset.dto.ts @@ -15,7 +15,7 @@ import { } from 'class-validator'; import { BulkIdsDto } from 'src/dtos/asset-ids.response.dto'; import { AssetType } from 'src/enum'; -import { AssetStats } from 'src/interfaces/asset.interface'; +import { AssetStats } from 'src/repositories/asset.repository'; import { Optional, ValidateBoolean, ValidateUUID } from 'src/validation'; export class DeviceIdDto { diff --git a/server/src/dtos/partner.dto.ts b/server/src/dtos/partner.dto.ts index 38573998d6bf9..9d86415dc3907 100644 --- a/server/src/dtos/partner.dto.ts +++ b/server/src/dtos/partner.dto.ts @@ -1,7 +1,7 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsEnum, IsNotEmpty } from 'class-validator'; import { UserResponseDto } from 'src/dtos/user.dto'; -import { PartnerDirection } from 'src/interfaces/partner.interface'; +import { PartnerDirection } from 'src/repositories/partner.repository'; export class UpdatePartnerDto { @IsNotEmpty() diff --git a/server/src/dtos/time-bucket.dto.ts b/server/src/dtos/time-bucket.dto.ts index dd7a01df356ef..a9dfa49a07ac4 100644 --- a/server/src/dtos/time-bucket.dto.ts +++ b/server/src/dtos/time-bucket.dto.ts @@ -1,7 +1,7 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsEnum, IsNotEmpty, IsString } from 'class-validator'; import { AssetOrder } from 'src/enum'; -import { TimeBucketSize } from 'src/interfaces/asset.interface'; +import { TimeBucketSize } from 'src/repositories/asset.repository'; import { Optional, ValidateBoolean, ValidateUUID } from 'src/validation'; export class TimeBucketDto { diff --git a/server/src/entities/asset.entity.ts b/server/src/entities/asset.entity.ts index 594dd17785ca7..a90236de84e34 100644 --- a/server/src/entities/asset.entity.ts +++ b/server/src/entities/asset.entity.ts @@ -13,8 +13,8 @@ import { StackEntity } from 'src/entities/stack.entity'; import { TagEntity } from 'src/entities/tag.entity'; import { UserEntity } from 'src/entities/user.entity'; import { AssetFileType, AssetStatus, AssetType } from 'src/enum'; -import { TimeBucketSize } from 'src/interfaces/asset.interface'; -import { AssetSearchBuilderOptions } from 'src/interfaces/search.interface'; +import { TimeBucketSize } from 'src/repositories/asset.repository'; +import { AssetSearchBuilderOptions } from 'src/repositories/search.repository'; import { anyUuid, asUuid } from 'src/utils/database'; import { Column, diff --git a/server/src/enum.ts b/server/src/enum.ts index 3440d45cee6d2..332ae50ee8d0e 100644 --- a/server/src/enum.ts +++ b/server/src/enum.ts @@ -384,3 +384,10 @@ export enum ExifOrientation { MirrorHorizontalRotate90CW = 7, Rotate270CW = 8, } + +export enum DatabaseExtension { + CUBE = 'cube', + EARTH_DISTANCE = 'earthdistance', + VECTOR = 'vector', + VECTORS = 'vectors', +} diff --git a/server/src/interfaces/album.interface.ts b/server/src/interfaces/album.interface.ts deleted file mode 100644 index 36a6d8a1d2676..0000000000000 --- a/server/src/interfaces/album.interface.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { Insertable, Updateable } from 'kysely'; -import { Albums } from 'src/db'; -import { AlbumUserCreateDto } from 'src/dtos/album.dto'; -import { AlbumEntity } from 'src/entities/album.entity'; -import { IBulkAsset } from 'src/utils/asset.util'; - -export const IAlbumRepository = 'IAlbumRepository'; - -export interface AlbumAssetCount { - albumId: string; - assetCount: number; - startDate: Date | null; - endDate: Date | null; -} - -export interface AlbumInfoOptions { - withAssets: boolean; -} - -export interface IAlbumRepository extends IBulkAsset { - getById(id: string, options: AlbumInfoOptions): Promise; - getByAssetId(ownerId: string, assetId: string): Promise; - removeAsset(assetId: string): Promise; - getMetadataForIds(ids: string[]): Promise; - getOwned(ownerId: string): Promise; - getShared(ownerId: string): Promise; - getNotShared(ownerId: string): Promise; - restoreAll(userId: string): Promise; - softDeleteAll(userId: string): Promise; - deleteAll(userId: string): Promise; - create(album: Insertable, assetIds: string[], albumUsers: AlbumUserCreateDto[]): Promise; - update(id: string, album: Updateable): Promise; - delete(id: string): Promise; - updateThumbnails(): Promise; -} diff --git a/server/src/interfaces/asset.interface.ts b/server/src/interfaces/asset.interface.ts deleted file mode 100644 index 5abaf9af26607..0000000000000 --- a/server/src/interfaces/asset.interface.ts +++ /dev/null @@ -1,170 +0,0 @@ -import { Insertable, Updateable } from 'kysely'; -import { AssetFiles, AssetJobStatus, Assets, Exif } from 'src/db'; -import { AssetEntity } from 'src/entities/asset.entity'; -import { AssetFileType, AssetOrder, AssetStatus, AssetType } from 'src/enum'; -import { AssetSearchOptions, SearchExploreItem } from 'src/interfaces/search.interface'; -import { Paginated, PaginationOptions } from 'src/utils/pagination'; - -export type AssetStats = Record; - -export interface AssetStatsOptions { - isFavorite?: boolean; - isArchived?: boolean; - isTrashed?: boolean; -} - -export interface LivePhotoSearchOptions { - ownerId: string; - libraryId?: string | null; - livePhotoCID: string; - otherAssetId: string; - type: AssetType; -} - -export enum WithoutProperty { - THUMBNAIL = 'thumbnail', - ENCODED_VIDEO = 'encoded-video', - EXIF = 'exif', - SMART_SEARCH = 'smart-search', - DUPLICATE = 'duplicate', - FACES = 'faces', - SIDECAR = 'sidecar', -} - -export enum WithProperty { - SIDECAR = 'sidecar', -} - -export enum TimeBucketSize { - DAY = 'DAY', - MONTH = 'MONTH', -} - -export interface AssetBuilderOptions { - isArchived?: boolean; - isFavorite?: boolean; - isTrashed?: boolean; - isDuplicate?: boolean; - albumId?: string; - tagId?: string; - personId?: string; - userIds?: string[]; - withStacked?: boolean; - exifInfo?: boolean; - status?: AssetStatus; - assetType?: AssetType; -} - -export interface TimeBucketOptions extends AssetBuilderOptions { - size: TimeBucketSize; - order?: AssetOrder; -} - -export interface TimeBucketItem { - timeBucket: string; - count: number; -} - -export interface MonthDay { - day: number; - month: number; -} - -export interface AssetExploreFieldOptions { - maxFields: number; - minAssetsPerField: number; -} - -export interface AssetFullSyncOptions { - ownerId: string; - lastId?: string; - updatedUntil: Date; - limit: number; -} - -export interface AssetDeltaSyncOptions { - userIds: string[]; - updatedAfter: Date; - limit: number; -} - -export interface AssetUpdateDuplicateOptions { - targetDuplicateId: string | null; - assetIds: string[]; - duplicateIds: string[]; -} - -export interface UpsertFileOptions { - assetId: string; - type: AssetFileType; - path: string; -} - -export interface AssetGetByChecksumOptions { - ownerId: string; - checksum: Buffer; - libraryId?: string; -} - -export type AssetPathEntity = Pick; - -export interface GetByIdsRelations { - exifInfo?: boolean; - faces?: { person?: boolean }; - files?: boolean; - library?: boolean; - owner?: boolean; - smartSearch?: boolean; - stack?: { assets?: boolean }; - tags?: boolean; -} - -export interface DuplicateGroup { - duplicateId: string; - assets: AssetEntity[]; -} - -export interface DayOfYearAssets { - yearsAgo: number; - assets: AssetEntity[]; -} - -export const IAssetRepository = 'IAssetRepository'; - -export interface IAssetRepository { - create(asset: Insertable): Promise; - getByIds(ids: string[], relations?: GetByIdsRelations): Promise; - getByIdsWithAllRelations(ids: string[]): Promise; - getByDayOfYear(ownerIds: string[], monthDay: MonthDay): Promise; - getByChecksum(options: AssetGetByChecksumOptions): Promise; - getByChecksums(userId: string, checksums: Buffer[]): Promise; - getUploadAssetIdByChecksum(ownerId: string, checksum: Buffer): Promise; - getByAlbumId(pagination: PaginationOptions, albumId: string): Paginated; - getByDeviceIds(ownerId: string, deviceId: string, deviceAssetIds: string[]): Promise; - getByUserId(pagination: PaginationOptions, userId: string, options?: AssetSearchOptions): Paginated; - getById(id: string, relations?: GetByIdsRelations): Promise; - getWithout(pagination: PaginationOptions, property: WithoutProperty): Paginated; - getRandom(userIds: string[], count: number): Promise; - getLastUpdatedAssetForAlbumId(albumId: string): Promise; - getByLibraryIdAndOriginalPath(libraryId: string, originalPath: string): Promise; - deleteAll(ownerId: string): Promise; - getAll(pagination: PaginationOptions, options?: AssetSearchOptions): Paginated; - getAllByDeviceId(userId: string, deviceId: string): Promise; - getLivePhotoCount(motionId: string): Promise; - updateAll(ids: string[], options: Updateable): Promise; - updateDuplicates(options: AssetUpdateDuplicateOptions): Promise; - update(asset: Updateable & { id: string }): Promise; - remove(asset: AssetEntity): Promise; - findLivePhotoMatch(options: LivePhotoSearchOptions): Promise; - getStatistics(ownerId: string, options: AssetStatsOptions): Promise; - getTimeBuckets(options: TimeBucketOptions): Promise; - getTimeBucket(timeBucket: string, options: TimeBucketOptions): Promise; - upsertExif(exif: Insertable): Promise; - upsertJobStatus(...jobStatus: Insertable[]): Promise; - getAssetIdByCity(userId: string, options: AssetExploreFieldOptions): Promise>; - getDuplicates(userId: string): Promise; - getAllForUserFullSync(options: AssetFullSyncOptions): Promise; - getChangedDeltaSync(options: AssetDeltaSyncOptions): Promise; - upsertFile(options: Insertable): Promise; - upsertFiles(options: Insertable[]): Promise; -} diff --git a/server/src/interfaces/crypto.interface.ts b/server/src/interfaces/crypto.interface.ts deleted file mode 100644 index c661695cf72f3..0000000000000 --- a/server/src/interfaces/crypto.interface.ts +++ /dev/null @@ -1,13 +0,0 @@ -export const ICryptoRepository = 'ICryptoRepository'; - -export interface ICryptoRepository { - randomBytes(size: number): Buffer; - randomUUID(): string; - hashFile(filePath: string | Buffer): Promise; - hashSha256(data: string): string; - verifySha256(data: string, encrypted: string, publicKey: string): boolean; - hashSha1(data: string | Buffer): Buffer; - hashBcrypt(data: string | Buffer, saltOrRounds: string | number): Promise; - compareBcrypt(data: string | Buffer, encrypted: string): boolean; - newPassword(bytes: number): string; -} diff --git a/server/src/interfaces/database.interface.ts b/server/src/interfaces/database.interface.ts deleted file mode 100644 index 8cfc040271433..0000000000000 --- a/server/src/interfaces/database.interface.ts +++ /dev/null @@ -1,78 +0,0 @@ -export enum DatabaseExtension { - CUBE = 'cube', - EARTH_DISTANCE = 'earthdistance', - VECTOR = 'vector', - VECTORS = 'vectors', -} - -export type VectorExtension = DatabaseExtension.VECTOR | DatabaseExtension.VECTORS; - -export type DatabaseConnectionURL = { - connectionType: 'url'; - url: string; -}; - -export type DatabaseConnectionParts = { - connectionType: 'parts'; - host: string; - port: number; - username: string; - password: string; - database: string; -}; - -export type DatabaseConnectionParams = DatabaseConnectionURL | DatabaseConnectionParts; - -export enum VectorIndex { - CLIP = 'clip_index', - FACE = 'face_index', -} - -export enum DatabaseLock { - GeodataImport = 100, - Migrations = 200, - SystemFileMounts = 300, - StorageTemplateMigration = 420, - VersionHistory = 500, - CLIPDimSize = 512, - Library = 1337, - GetSystemConfig = 69, - BackupDatabase = 42, -} - -export const EXTENSION_NAMES: Record = { - cube: 'cube', - earthdistance: 'earthdistance', - vector: 'pgvector', - vectors: 'pgvecto.rs', -} as const; - -export interface ExtensionVersion { - availableVersion: string | null; - installedVersion: string | null; -} - -export interface VectorUpdateResult { - restartRequired: boolean; -} - -export const IDatabaseRepository = 'IDatabaseRepository'; - -export interface IDatabaseRepository { - init(): void; - reconnect(): Promise; - shutdown(): Promise; - getExtensionVersion(extension: DatabaseExtension): Promise; - getExtensionVersionRange(extension: VectorExtension): string; - getPostgresVersion(): Promise; - getPostgresVersionRange(): string; - createExtension(extension: DatabaseExtension): Promise; - updateVectorExtension(extension: VectorExtension, version?: string): Promise; - reindex(index: VectorIndex): Promise; - shouldReindex(name: VectorIndex): Promise; - runMigrations(options?: { transaction?: 'all' | 'none' | 'each' }): Promise; - withLock(lock: DatabaseLock, callback: () => Promise): Promise; - tryLock(lock: DatabaseLock): Promise; - isBusy(lock: DatabaseLock): boolean; - wait(lock: DatabaseLock): Promise; -} diff --git a/server/src/interfaces/library.interface.ts b/server/src/interfaces/library.interface.ts deleted file mode 100644 index 66e9a7de29d7e..0000000000000 --- a/server/src/interfaces/library.interface.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { Insertable, Updateable } from 'kysely'; -import { Libraries } from 'src/db'; -import { LibraryStatsResponseDto } from 'src/dtos/library.dto'; -import { LibraryEntity } from 'src/entities/library.entity'; - -export const ILibraryRepository = 'ILibraryRepository'; - -export interface ILibraryRepository { - getAll(withDeleted?: boolean): Promise; - getAllDeleted(): Promise; - get(id: string, withDeleted?: boolean): Promise; - create(library: Insertable): Promise; - delete(id: string): Promise; - softDelete(id: string): Promise; - update(id: string, library: Updateable): Promise; - getStatistics(id: string): Promise; -} diff --git a/server/src/interfaces/move.interface.ts b/server/src/interfaces/move.interface.ts deleted file mode 100644 index 4356d9df8cc8d..0000000000000 --- a/server/src/interfaces/move.interface.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Insertable, Updateable } from 'kysely'; -import { MoveHistory } from 'src/db'; -import { MoveEntity } from 'src/entities/move.entity'; -import { PathType } from 'src/enum'; - -export const IMoveRepository = 'IMoveRepository'; - -export type MoveCreate = Pick & Partial; - -export interface IMoveRepository { - create(entity: Insertable): Promise; - getByEntity(entityId: string, pathType: PathType): Promise; - update(id: string, entity: Updateable): Promise; - delete(id: string): Promise; -} diff --git a/server/src/interfaces/partner.interface.ts b/server/src/interfaces/partner.interface.ts deleted file mode 100644 index a6f50178cae43..0000000000000 --- a/server/src/interfaces/partner.interface.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { Updateable } from 'kysely'; -import { Partners } from 'src/db'; -import { PartnerEntity } from 'src/entities/partner.entity'; - -export interface PartnerIds { - sharedById: string; - sharedWithId: string; -} - -export enum PartnerDirection { - SharedBy = 'shared-by', - SharedWith = 'shared-with', -} - -export const IPartnerRepository = 'IPartnerRepository'; - -export interface IPartnerRepository { - getAll(userId: string): Promise; - get(partner: PartnerIds): Promise; - create(partner: PartnerIds): Promise; - remove(partner: PartnerIds): Promise; - update(partner: PartnerIds, entity: Updateable): Promise; -} diff --git a/server/src/interfaces/person.interface.ts b/server/src/interfaces/person.interface.ts deleted file mode 100644 index 4719f047eca5c..0000000000000 --- a/server/src/interfaces/person.interface.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { Insertable, Selectable, Updateable } from 'kysely'; -import { AssetFaces, FaceSearch, Person } from 'src/db'; -import { AssetFaceEntity } from 'src/entities/asset-face.entity'; -import { PersonEntity } from 'src/entities/person.entity'; -import { SourceType } from 'src/enum'; -import { Paginated, PaginationOptions } from 'src/utils/pagination'; -import { FindOptionsRelations } from 'typeorm'; - -export const IPersonRepository = 'IPersonRepository'; - -export interface PersonSearchOptions { - minimumFaceCount: number; - withHidden: boolean; - closestFaceAssetId?: string; -} - -export interface PersonNameSearchOptions { - withHidden?: boolean; -} - -export interface PersonNameResponse { - id: string; - name: string; -} - -export interface AssetFaceId { - assetId: string; - personId: string; -} - -export interface UpdateFacesData { - oldPersonId?: string; - faceIds?: string[]; - newPersonId: string; -} - -export interface PersonStatistics { - assets: number; -} - -export interface PeopleStatistics { - total: number; - hidden: number; -} - -export interface DeleteFacesOptions { - sourceType: SourceType; -} - -export type UnassignFacesOptions = DeleteFacesOptions; - -export type SelectFaceOptions = (keyof Selectable)[]; - -export interface IPersonRepository { - getAll(options?: Partial): AsyncIterableIterator; - getAllForUser(pagination: PaginationOptions, userId: string, options: PersonSearchOptions): Paginated; - getAllWithoutFaces(): Promise; - getById(personId: string): Promise; - getByName(userId: string, personName: string, options: PersonNameSearchOptions): Promise; - getDistinctNames(userId: string, options: PersonNameSearchOptions): Promise; - - create(person: Insertable): Promise; - createAll(people: Insertable[]): Promise; - delete(entities: PersonEntity[]): Promise; - deleteFaces(options: DeleteFacesOptions): Promise; - refreshFaces( - facesToAdd: Insertable[], - faceIdsToRemove: string[], - embeddingsToAdd?: Insertable[], - ): Promise; - getAllFaces(options?: Partial): AsyncIterableIterator; - getFaceById(id: string): Promise; - getFaceByIdWithAssets( - id: string, - relations?: FindOptionsRelations, - select?: SelectFaceOptions, - ): Promise; - getFaces(assetId: string): Promise; - getFacesByIds(ids: AssetFaceId[]): Promise; - getRandomFace(personId: string): Promise; - getStatistics(personId: string): Promise; - reassignFace(assetFaceId: string, newPersonId: string): Promise; - getNumberOfPeople(userId: string): Promise; - reassignFaces(data: UpdateFacesData): Promise; - unassignFaces(options: UnassignFacesOptions): Promise; - update(person: Updateable & { id: string }): Promise; - updateAll(people: Insertable[]): Promise; - getLatestFaceDate(): Promise; -} diff --git a/server/src/interfaces/search.interface.ts b/server/src/interfaces/search.interface.ts deleted file mode 100644 index b9ae7b7194893..0000000000000 --- a/server/src/interfaces/search.interface.ts +++ /dev/null @@ -1,213 +0,0 @@ -import { AssetEntity } from 'src/entities/asset.entity'; -import { GeodataPlacesEntity } from 'src/entities/geodata-places.entity'; -import { AssetStatus, AssetType } from 'src/enum'; -import { Paginated } from 'src/utils/pagination'; - -export const ISearchRepository = 'ISearchRepository'; - -export interface SearchResult { - /** total matches */ - total: number; - /** collection size */ - count: number; - /** current page */ - page: number; - /** items for page */ - items: T[]; - /** score */ - distances: number[]; - facets: SearchFacet[]; -} - -export interface SearchFacet { - fieldName: string; - counts: Array<{ - count: number; - value: string; - }>; -} - -export type SearchExploreItemSet = Array<{ - value: string; - data: T; -}>; - -export interface SearchExploreItem { - fieldName: string; - items: SearchExploreItemSet; -} - -export interface SearchAssetIDOptions { - checksum?: Buffer; - deviceAssetId?: string; - id?: string; -} - -export interface SearchUserIdOptions { - deviceId?: string; - libraryId?: string | null; - userIds?: string[]; -} - -export type SearchIdOptions = SearchAssetIDOptions & SearchUserIdOptions; - -export interface SearchStatusOptions { - isArchived?: boolean; - isEncoded?: boolean; - isFavorite?: boolean; - isMotion?: boolean; - isOffline?: boolean; - isVisible?: boolean; - isNotInAlbum?: boolean; - type?: AssetType; - status?: AssetStatus; - withArchived?: boolean; - withDeleted?: boolean; -} - -export interface SearchOneToOneRelationOptions { - withExif?: boolean; - withStacked?: boolean; -} - -export interface SearchRelationOptions extends SearchOneToOneRelationOptions { - withFaces?: boolean; - withPeople?: boolean; -} - -export interface SearchDateOptions { - createdBefore?: Date; - createdAfter?: Date; - takenBefore?: Date; - takenAfter?: Date; - trashedBefore?: Date; - trashedAfter?: Date; - updatedBefore?: Date; - updatedAfter?: Date; -} - -export interface SearchPathOptions { - encodedVideoPath?: string; - originalFileName?: string; - originalPath?: string; - previewPath?: string; - thumbnailPath?: string; -} - -export interface SearchExifOptions { - city?: string | null; - country?: string | null; - lensModel?: string | null; - make?: string | null; - model?: string | null; - state?: string | null; - description?: string | null; -} - -export interface SearchEmbeddingOptions { - embedding: string; - userIds: string[]; -} - -export interface SearchPeopleOptions { - personIds?: string[]; -} - -export interface SearchTagOptions { - tagIds?: string[]; -} - -export interface SearchOrderOptions { - orderDirection?: 'asc' | 'desc'; -} - -export interface SearchPaginationOptions { - page: number; - size: number; -} - -type BaseAssetSearchOptions = SearchDateOptions & - SearchIdOptions & - SearchExifOptions & - SearchOrderOptions & - SearchPathOptions & - SearchStatusOptions & - SearchUserIdOptions & - SearchPeopleOptions & - SearchTagOptions; - -export type AssetSearchOptions = BaseAssetSearchOptions & SearchRelationOptions; - -export type AssetSearchOneToOneRelationOptions = BaseAssetSearchOptions & SearchOneToOneRelationOptions; - -export type AssetSearchBuilderOptions = Omit; - -export type SmartSearchOptions = SearchDateOptions & - SearchEmbeddingOptions & - SearchExifOptions & - SearchOneToOneRelationOptions & - SearchStatusOptions & - SearchUserIdOptions & - SearchPeopleOptions & - SearchTagOptions; - -export interface FaceEmbeddingSearch extends SearchEmbeddingOptions { - hasPerson?: boolean; - numResults: number; - maxDistance: number; -} - -export interface AssetDuplicateSearch { - assetId: string; - embedding: string; - maxDistance: number; - type: AssetType; - userIds: string[]; -} - -export interface FaceSearchResult { - distance: number; - id: string; - personId: string | null; -} - -export interface AssetDuplicateResult { - assetId: string; - duplicateId: string | null; - distance: number; -} - -export interface GetStatesOptions { - country?: string; -} - -export interface GetCitiesOptions extends GetStatesOptions { - state?: string; -} - -export interface GetCameraModelsOptions { - make?: string; -} - -export interface GetCameraMakesOptions { - model?: string; -} - -export interface ISearchRepository { - searchMetadata(pagination: SearchPaginationOptions, options: AssetSearchOptions): Paginated; - searchSmart(pagination: SearchPaginationOptions, options: SmartSearchOptions): Paginated; - searchDuplicates(options: AssetDuplicateSearch): Promise; - searchFaces(search: FaceEmbeddingSearch): Promise; - searchRandom(size: number, options: AssetSearchOptions): Promise; - upsert(assetId: string, embedding: string): Promise; - searchPlaces(placeName: string): Promise; - getAssetsByCity(userIds: string[]): Promise; - deleteAllSearchEmbeddings(): Promise; - getDimensionSize(): Promise; - setDimensionSize(dimSize: number): Promise; - getCountries(userIds: string[]): Promise>; - getStates(userIds: string[], options: GetStatesOptions): Promise>; - getCities(userIds: string[], options: GetCitiesOptions): Promise>; - getCameraMakes(userIds: string[], options: GetCameraMakesOptions): Promise>; - getCameraModels(userIds: string[], options: GetCameraModelsOptions): Promise>; -} diff --git a/server/src/interfaces/shared-link.interface.ts b/server/src/interfaces/shared-link.interface.ts deleted file mode 100644 index c030ceb736aec..0000000000000 --- a/server/src/interfaces/shared-link.interface.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { Insertable, Updateable } from 'kysely'; -import { SharedLinks } from 'src/db'; -import { SharedLinkEntity } from 'src/entities/shared-link.entity'; - -export const ISharedLinkRepository = 'ISharedLinkRepository'; - -export type SharedLinkSearchOptions = { - userId: string; - albumId?: string; -}; - -export interface ISharedLinkRepository { - getAll(options: SharedLinkSearchOptions): Promise; - get(userId: string, id: string): Promise; - getByKey(key: Buffer): Promise; - create(entity: Insertable & { assetIds?: string[] }): Promise; - update(entity: Updateable & { id: string; assetIds?: string[] }): Promise; - remove(entity: SharedLinkEntity): Promise; -} diff --git a/server/src/interfaces/stack.interface.ts b/server/src/interfaces/stack.interface.ts deleted file mode 100644 index a9fb8cec769cc..0000000000000 --- a/server/src/interfaces/stack.interface.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Updateable } from 'kysely'; -import { StackEntity } from 'src/entities/stack.entity'; - -export const IStackRepository = 'IStackRepository'; - -export interface StackSearch { - ownerId: string; - primaryAssetId?: string; -} - -export interface IStackRepository { - search(query: StackSearch): Promise; - create(stack: { ownerId: string; assetIds: string[] }): Promise; - update(id: string, entity: Updateable): Promise; - delete(id: string): Promise; - deleteAll(ids: string[]): Promise; - getById(id: string): Promise; -} diff --git a/server/src/interfaces/storage.interface.ts b/server/src/interfaces/storage.interface.ts deleted file mode 100644 index b304d94fefd2d..0000000000000 --- a/server/src/interfaces/storage.interface.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { WatchOptions } from 'chokidar'; -import { Stats } from 'node:fs'; -import { FileReadOptions } from 'node:fs/promises'; -import { Readable, Writable } from 'node:stream'; -import { CrawlOptionsDto, WalkOptionsDto } from 'src/dtos/library.dto'; - -export interface ImmichReadStream { - stream: Readable; - type?: string; - length?: number; -} - -export interface ImmichZipStream extends ImmichReadStream { - addFile: (inputPath: string, filename: string) => void; - finalize: () => Promise; -} - -export interface DiskUsage { - available: number; - free: number; - total: number; -} - -export const IStorageRepository = 'IStorageRepository'; - -export interface WatchEvents { - onReady(): void; - onAdd(path: string): void; - onChange(path: string): void; - onUnlink(path: string): void; - onError(error: Error): void; -} - -export interface IStorageRepository { - createZipStream(): ImmichZipStream; - createReadStream(filepath: string, mimeType?: string | null): Promise; - readFile(filepath: string, options?: FileReadOptions): Promise; - createFile(filepath: string, buffer: Buffer): Promise; - createWriteStream(filepath: string): Writable; - createOrOverwriteFile(filepath: string, buffer: Buffer): Promise; - overwriteFile(filepath: string, buffer: Buffer): Promise; - realpath(filepath: string): Promise; - unlink(filepath: string): Promise; - unlinkDir(folder: string, options?: { recursive?: boolean; force?: boolean }): Promise; - removeEmptyDirs(folder: string, self?: boolean): Promise; - checkFileExists(filepath: string, mode?: number): Promise; - mkdirSync(filepath: string): void; - checkDiskUsage(folder: string): Promise; - readdir(folder: string): Promise; - stat(filepath: string): Promise; - crawl(options: CrawlOptionsDto): Promise; - walk(options: WalkOptionsDto): AsyncGenerator; - copyFile(source: string, target: string): Promise; - rename(source: string, target: string): Promise; - watch(paths: string[], options: WatchOptions, events: Partial): () => Promise; - utimes(filepath: string, atime: Date, mtime: Date): Promise; -} diff --git a/server/src/interfaces/tag.interface.ts b/server/src/interfaces/tag.interface.ts deleted file mode 100644 index 16a34d6ac4960..0000000000000 --- a/server/src/interfaces/tag.interface.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { TagEntity } from 'src/entities/tag.entity'; -import { IBulkAsset } from 'src/utils/asset.util'; - -export const ITagRepository = 'ITagRepository'; - -export type AssetTagItem = { assetId: string; tagId: string }; - -export interface ITagRepository extends IBulkAsset { - getAll(userId: string): Promise; - getByValue(userId: string, value: string): Promise; - upsertValue(request: { userId: string; value: string; parent?: TagEntity }): Promise; - - create(tag: Partial): Promise; - get(id: string): Promise; - update(tag: { id: string } & Partial): Promise; - delete(id: string): Promise; - - upsertAssetTags({ assetId, tagIds }: { assetId: string; tagIds: string[] }): Promise; - upsertAssetIds(items: AssetTagItem[]): Promise; - deleteEmptyTags(): Promise; -} diff --git a/server/src/interfaces/user.interface.ts b/server/src/interfaces/user.interface.ts deleted file mode 100644 index f126b6eb34ace..0000000000000 --- a/server/src/interfaces/user.interface.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { Insertable, Updateable } from 'kysely'; -import { Users } from 'src/db'; -import { UserMetadata } from 'src/entities/user-metadata.entity'; -import { UserEntity } from 'src/entities/user.entity'; - -export interface UserListFilter { - withDeleted?: boolean; -} - -export interface UserStatsQueryResponse { - userId: string; - userName: string; - photos: number; - videos: number; - usage: number; - usagePhotos: number; - usageVideos: number; - quotaSizeInBytes: number | null; -} - -export interface UserFindOptions { - withDeleted?: boolean; -} - -export const IUserRepository = 'IUserRepository'; - -export interface IUserRepository { - get(id: string, options: UserFindOptions): Promise; - getAdmin(): Promise; - hasAdmin(): Promise; - getByEmail(email: string, withPassword?: boolean): Promise; - getByStorageLabel(storageLabel: string): Promise; - getByOAuthId(oauthId: string): Promise; - getDeletedUsers(): Promise; - getList(filter?: UserListFilter): Promise; - getUserStats(): Promise; - create(user: Insertable): Promise; - update(id: string, user: Updateable): Promise; - restore(id: string): Promise; - upsertMetadata(id: string, item: { key: T; value: UserMetadata[T] }): Promise; - deleteMetadata(id: string, key: T): Promise; - delete(user: UserEntity, hard?: boolean): Promise; - updateUsage(id: string, delta: number): Promise; - syncUsage(id?: string): Promise; -} diff --git a/server/src/migrations/1700713994428-AddCLIPEmbeddingIndex.ts b/server/src/migrations/1700713994428-AddCLIPEmbeddingIndex.ts index f9ea5a0dc3110..993e12f822e36 100644 --- a/server/src/migrations/1700713994428-AddCLIPEmbeddingIndex.ts +++ b/server/src/migrations/1700713994428-AddCLIPEmbeddingIndex.ts @@ -1,4 +1,4 @@ -import { DatabaseExtension } from 'src/interfaces/database.interface'; +import { DatabaseExtension } from 'src/enum'; import { ConfigRepository } from 'src/repositories/config.repository'; import { MigrationInterface, QueryRunner } from 'typeorm'; diff --git a/server/src/migrations/1700714033632-AddFaceEmbeddingIndex.ts b/server/src/migrations/1700714033632-AddFaceEmbeddingIndex.ts index d11e7b921e8f5..182aae4e4237b 100644 --- a/server/src/migrations/1700714033632-AddFaceEmbeddingIndex.ts +++ b/server/src/migrations/1700714033632-AddFaceEmbeddingIndex.ts @@ -1,4 +1,4 @@ -import { DatabaseExtension } from 'src/interfaces/database.interface'; +import { DatabaseExtension } from 'src/enum'; import { ConfigRepository } from 'src/repositories/config.repository'; import { MigrationInterface, QueryRunner } from 'typeorm'; diff --git a/server/src/migrations/1718486162779-AddFaceSearchRelation.ts b/server/src/migrations/1718486162779-AddFaceSearchRelation.ts index ae6d752c65da9..e08bcb8e25879 100644 --- a/server/src/migrations/1718486162779-AddFaceSearchRelation.ts +++ b/server/src/migrations/1718486162779-AddFaceSearchRelation.ts @@ -1,4 +1,4 @@ -import { DatabaseExtension } from 'src/interfaces/database.interface'; +import { DatabaseExtension } from 'src/enum'; import { ConfigRepository } from 'src/repositories/config.repository'; import { MigrationInterface, QueryRunner } from 'typeorm'; diff --git a/server/src/repositories/album.repository.ts b/server/src/repositories/album.repository.ts index c09a13750e0c7..1fe2938fcc0b7 100644 --- a/server/src/repositories/album.repository.ts +++ b/server/src/repositories/album.repository.ts @@ -6,7 +6,17 @@ import { Albums, DB } from 'src/db'; import { Chunked, ChunkedArray, ChunkedSet, DummyValue, GenerateSql } from 'src/decorators'; import { AlbumUserCreateDto } from 'src/dtos/album.dto'; import { AlbumEntity } from 'src/entities/album.entity'; -import { AlbumAssetCount, AlbumInfoOptions, IAlbumRepository } from 'src/interfaces/album.interface'; + +export interface AlbumAssetCount { + albumId: string; + assetCount: number; + startDate: Date | null; + endDate: Date | null; +} + +export interface AlbumInfoOptions { + withAssets: boolean; +} const userColumns = [ 'id', @@ -71,7 +81,7 @@ const withAssets = (eb: ExpressionBuilder) => { }; @Injectable() -export class AlbumRepository implements IAlbumRepository { +export class AlbumRepository { constructor(@InjectKysely() private db: Kysely) {} @GenerateSql({ params: [DummyValue.UUID, { withAssets: true }] }) diff --git a/server/src/repositories/asset.repository.ts b/server/src/repositories/asset.repository.ts index 2ac81bbf97e9e..bd82cc07248c0 100644 --- a/server/src/repositories/asset.repository.ts +++ b/server/src/repositories/asset.repository.ts @@ -21,34 +21,138 @@ import { withTagId, withTags, } from 'src/entities/asset.entity'; -import { AssetFileType, AssetStatus, AssetType } from 'src/enum'; -import { - AssetDeltaSyncOptions, - AssetExploreFieldOptions, - AssetFullSyncOptions, - AssetGetByChecksumOptions, - AssetStats, - AssetStatsOptions, - AssetUpdateDuplicateOptions, - DayOfYearAssets, - DuplicateGroup, - GetByIdsRelations, - IAssetRepository, - LivePhotoSearchOptions, - MonthDay, - TimeBucketItem, - TimeBucketOptions, - TimeBucketSize, - WithProperty, - WithoutProperty, -} from 'src/interfaces/asset.interface'; -import { AssetSearchOptions, SearchExploreItem, SearchExploreItemSet } from 'src/interfaces/search.interface'; +import { AssetFileType, AssetOrder, AssetStatus, AssetType } from 'src/enum'; import { MapMarker, MapMarkerSearchOptions } from 'src/repositories/map.repository'; +import { AssetSearchOptions, SearchExploreItem, SearchExploreItemSet } from 'src/repositories/search.repository'; import { anyUuid, asUuid, mapUpsertColumns } from 'src/utils/database'; import { Paginated, PaginationOptions, paginationHelper } from 'src/utils/pagination'; +export type AssetStats = Record; + +export interface AssetStatsOptions { + isFavorite?: boolean; + isArchived?: boolean; + isTrashed?: boolean; +} + +export interface LivePhotoSearchOptions { + ownerId: string; + libraryId?: string | null; + livePhotoCID: string; + otherAssetId: string; + type: AssetType; +} + +export enum WithoutProperty { + THUMBNAIL = 'thumbnail', + ENCODED_VIDEO = 'encoded-video', + EXIF = 'exif', + SMART_SEARCH = 'smart-search', + DUPLICATE = 'duplicate', + FACES = 'faces', + SIDECAR = 'sidecar', +} + +export enum WithProperty { + SIDECAR = 'sidecar', +} + +export enum TimeBucketSize { + DAY = 'DAY', + MONTH = 'MONTH', +} + +export interface AssetBuilderOptions { + isArchived?: boolean; + isFavorite?: boolean; + isTrashed?: boolean; + isDuplicate?: boolean; + albumId?: string; + tagId?: string; + personId?: string; + userIds?: string[]; + withStacked?: boolean; + exifInfo?: boolean; + status?: AssetStatus; + assetType?: AssetType; +} + +export interface TimeBucketOptions extends AssetBuilderOptions { + size: TimeBucketSize; + order?: AssetOrder; +} + +export interface TimeBucketItem { + timeBucket: string; + count: number; +} + +export interface MonthDay { + day: number; + month: number; +} + +export interface AssetExploreFieldOptions { + maxFields: number; + minAssetsPerField: number; +} + +export interface AssetFullSyncOptions { + ownerId: string; + lastId?: string; + updatedUntil: Date; + limit: number; +} + +export interface AssetDeltaSyncOptions { + userIds: string[]; + updatedAfter: Date; + limit: number; +} + +export interface AssetUpdateDuplicateOptions { + targetDuplicateId: string | null; + assetIds: string[]; + duplicateIds: string[]; +} + +export interface UpsertFileOptions { + assetId: string; + type: AssetFileType; + path: string; +} + +export interface AssetGetByChecksumOptions { + ownerId: string; + checksum: Buffer; + libraryId?: string; +} + +export type AssetPathEntity = Pick; + +export interface GetByIdsRelations { + exifInfo?: boolean; + faces?: { person?: boolean }; + files?: boolean; + library?: boolean; + owner?: boolean; + smartSearch?: boolean; + stack?: { assets?: boolean }; + tags?: boolean; +} + +export interface DuplicateGroup { + duplicateId: string; + assets: AssetEntity[]; +} + +export interface DayOfYearAssets { + yearsAgo: number; + assets: AssetEntity[]; +} + @Injectable() -export class AssetRepository implements IAssetRepository { +export class AssetRepository { constructor(@InjectKysely() private db: Kysely) {} async upsertExif(exif: Insertable): Promise { diff --git a/server/src/repositories/config.repository.ts b/server/src/repositories/config.repository.ts index 5b04914dac2a1..27c10bcdcc0f6 100644 --- a/server/src/repositories/config.repository.ts +++ b/server/src/repositories/config.repository.ts @@ -13,9 +13,9 @@ import { Notice } from 'postgres'; import { citiesFile, excludePaths, IWorker } from 'src/constants'; import { Telemetry } from 'src/decorators'; import { EnvDto } from 'src/dtos/env.dto'; -import { ImmichEnvironment, ImmichHeader, ImmichTelemetry, ImmichWorker, LogLevel } from 'src/enum'; -import { DatabaseConnectionParams, DatabaseExtension, VectorExtension } from 'src/interfaces/database.interface'; +import { DatabaseExtension, ImmichEnvironment, ImmichHeader, ImmichTelemetry, ImmichWorker, LogLevel } from 'src/enum'; import { QueueName } from 'src/interfaces/job.interface'; +import { DatabaseConnectionParams, VectorExtension } from 'src/repositories/database.repository'; import { setDifference } from 'src/utils/set'; import { PostgresConnectionOptions } from 'typeorm/driver/postgres/PostgresConnectionOptions.js'; diff --git a/server/src/repositories/crypto.repository.ts b/server/src/repositories/crypto.repository.ts index ee25609fecb72..e471ccb0312f9 100644 --- a/server/src/repositories/crypto.repository.ts +++ b/server/src/repositories/crypto.repository.ts @@ -2,11 +2,10 @@ import { Injectable } from '@nestjs/common'; import { compareSync, hash } from 'bcrypt'; import { createHash, createPublicKey, createVerify, randomBytes, randomUUID } from 'node:crypto'; import { createReadStream } from 'node:fs'; -import { ICryptoRepository } from 'src/interfaces/crypto.interface'; @Injectable() -export class CryptoRepository implements ICryptoRepository { - randomUUID() { +export class CryptoRepository { + randomUUID(): string { return randomUUID(); } diff --git a/server/src/repositories/database.repository.ts b/server/src/repositories/database.repository.ts index f7d52efd7a335..6edcedd13c92b 100644 --- a/server/src/repositories/database.repository.ts +++ b/server/src/repositories/database.repository.ts @@ -6,24 +6,66 @@ import { InjectKysely } from 'nestjs-kysely'; import semver from 'semver'; import { POSTGRES_VERSION_RANGE, VECTOR_VERSION_RANGE, VECTORS_VERSION_RANGE } from 'src/constants'; import { DB } from 'src/db'; -import { - DatabaseExtension, - DatabaseLock, - EXTENSION_NAMES, - ExtensionVersion, - IDatabaseRepository, - VectorExtension, - VectorIndex, - VectorUpdateResult, -} from 'src/interfaces/database.interface'; +import { DatabaseExtension } from 'src/enum'; import { ConfigRepository } from 'src/repositories/config.repository'; import { LoggingRepository } from 'src/repositories/logging.repository'; import { UPSERT_COLUMNS } from 'src/utils/database'; import { isValidInteger } from 'src/validation'; import { DataSource, EntityManager, EntityMetadata, QueryRunner } from 'typeorm'; +export type VectorExtension = DatabaseExtension.VECTOR | DatabaseExtension.VECTORS; + +export type DatabaseConnectionURL = { + connectionType: 'url'; + url: string; +}; + +export type DatabaseConnectionParts = { + connectionType: 'parts'; + host: string; + port: number; + username: string; + password: string; + database: string; +}; + +export type DatabaseConnectionParams = DatabaseConnectionURL | DatabaseConnectionParts; + +export enum VectorIndex { + CLIP = 'clip_index', + FACE = 'face_index', +} + +export enum DatabaseLock { + GeodataImport = 100, + Migrations = 200, + SystemFileMounts = 300, + StorageTemplateMigration = 420, + VersionHistory = 500, + CLIPDimSize = 512, + Library = 1337, + GetSystemConfig = 69, + BackupDatabase = 42, +} + +export const EXTENSION_NAMES: Record = { + cube: 'cube', + earthdistance: 'earthdistance', + vector: 'pgvector', + vectors: 'pgvecto.rs', +} as const; + +export interface ExtensionVersion { + availableVersion: string | null; + installedVersion: string | null; +} + +export interface VectorUpdateResult { + restartRequired: boolean; +} + @Injectable() -export class DatabaseRepository implements IDatabaseRepository { +export class DatabaseRepository { private vectorExtension: VectorExtension; private readonly asyncLock = new AsyncLock(); diff --git a/server/src/repositories/index.ts b/server/src/repositories/index.ts index cb870bd3395c6..d9ef84fc06a7d 100644 --- a/server/src/repositories/index.ts +++ b/server/src/repositories/index.ts @@ -1,20 +1,6 @@ -import { IAlbumRepository } from 'src/interfaces/album.interface'; -import { IAssetRepository } from 'src/interfaces/asset.interface'; -import { ICryptoRepository } from 'src/interfaces/crypto.interface'; -import { IDatabaseRepository } from 'src/interfaces/database.interface'; import { IEventRepository } from 'src/interfaces/event.interface'; import { IJobRepository } from 'src/interfaces/job.interface'; -import { ILibraryRepository } from 'src/interfaces/library.interface'; import { IMachineLearningRepository } from 'src/interfaces/machine-learning.interface'; -import { IMoveRepository } from 'src/interfaces/move.interface'; -import { IPartnerRepository } from 'src/interfaces/partner.interface'; -import { IPersonRepository } from 'src/interfaces/person.interface'; -import { ISearchRepository } from 'src/interfaces/search.interface'; -import { ISharedLinkRepository } from 'src/interfaces/shared-link.interface'; -import { IStackRepository } from 'src/interfaces/stack.interface'; -import { IStorageRepository } from 'src/interfaces/storage.interface'; -import { ITagRepository } from 'src/interfaces/tag.interface'; -import { IUserRepository } from 'src/interfaces/user.interface'; import { AccessRepository } from 'src/repositories/access.repository'; import { ActivityRepository } from 'src/repositories/activity.repository'; import { AlbumUserRepository } from 'src/repositories/album-user.repository'; @@ -58,44 +44,44 @@ import { ViewRepository } from 'src/repositories/view-repository'; export const repositories = [ AccessRepository, ActivityRepository, + AlbumRepository, AlbumUserRepository, AuditRepository, ApiKeyRepository, + AssetRepository, ConfigRepository, CronRepository, + CryptoRepository, + DatabaseRepository, + LibraryRepository, LoggingRepository, MapRepository, MediaRepository, MemoryRepository, MetadataRepository, + MoveRepository, NotificationRepository, OAuthRepository, + PartnerRepository, + PersonRepository, ProcessRepository, + SearchRepository, SessionRepository, ServerInfoRepository, + SharedLinkRepository, + StackRepository, + StorageRepository, SystemMetadataRepository, + TagRepository, TelemetryRepository, TrashRepository, + UserRepository, ViewRepository, VersionHistoryRepository, ]; export const providers = [ - { provide: IAlbumRepository, useClass: AlbumRepository }, - { provide: IAssetRepository, useClass: AssetRepository }, - { provide: ICryptoRepository, useClass: CryptoRepository }, - { provide: IDatabaseRepository, useClass: DatabaseRepository }, { provide: IEventRepository, useClass: EventRepository }, { provide: IJobRepository, useClass: JobRepository }, - { provide: ILibraryRepository, useClass: LibraryRepository }, { provide: IMachineLearningRepository, useClass: MachineLearningRepository }, - { provide: IMoveRepository, useClass: MoveRepository }, - { provide: IPartnerRepository, useClass: PartnerRepository }, - { provide: IPersonRepository, useClass: PersonRepository }, - { provide: ISearchRepository, useClass: SearchRepository }, - { provide: ISharedLinkRepository, useClass: SharedLinkRepository }, - { provide: IStackRepository, useClass: StackRepository }, - { provide: IStorageRepository, useClass: StorageRepository }, - { provide: ITagRepository, useClass: TagRepository }, - { provide: IUserRepository, useClass: UserRepository }, ]; diff --git a/server/src/repositories/library.repository.ts b/server/src/repositories/library.repository.ts index 0e1ec94c32f86..f748600fbb6ed 100644 --- a/server/src/repositories/library.repository.ts +++ b/server/src/repositories/library.repository.ts @@ -7,7 +7,6 @@ import { DummyValue, GenerateSql } from 'src/decorators'; import { LibraryStatsResponseDto } from 'src/dtos/library.dto'; import { LibraryEntity } from 'src/entities/library.entity'; import { AssetType } from 'src/enum'; -import { ILibraryRepository } from 'src/interfaces/library.interface'; const userColumns = [ 'users.id', @@ -34,7 +33,7 @@ const withOwner = (eb: ExpressionBuilder) => { }; @Injectable() -export class LibraryRepository implements ILibraryRepository { +export class LibraryRepository { constructor(@InjectKysely() private db: Kysely) {} @GenerateSql({ params: [DummyValue.UUID] }) diff --git a/server/src/repositories/move.repository.ts b/server/src/repositories/move.repository.ts index c0177f3f30f1a..c46259fa9b777 100644 --- a/server/src/repositories/move.repository.ts +++ b/server/src/repositories/move.repository.ts @@ -5,10 +5,11 @@ import { DB, MoveHistory } from 'src/db'; import { DummyValue, GenerateSql } from 'src/decorators'; import { MoveEntity } from 'src/entities/move.entity'; import { PathType } from 'src/enum'; -import { IMoveRepository } from 'src/interfaces/move.interface'; + +export type MoveCreate = Pick & Partial; @Injectable() -export class MoveRepository implements IMoveRepository { +export class MoveRepository { constructor(@InjectKysely() private db: Kysely) {} create(entity: Insertable): Promise { diff --git a/server/src/repositories/partner.repository.ts b/server/src/repositories/partner.repository.ts index 929c06a1f555b..f799ff56f2b9b 100644 --- a/server/src/repositories/partner.repository.ts +++ b/server/src/repositories/partner.repository.ts @@ -5,7 +5,16 @@ import { InjectKysely } from 'nestjs-kysely'; import { DB, Partners, Users } from 'src/db'; import { DummyValue, GenerateSql } from 'src/decorators'; import { PartnerEntity } from 'src/entities/partner.entity'; -import { IPartnerRepository, PartnerIds } from 'src/interfaces/partner.interface'; + +export interface PartnerIds { + sharedById: string; + sharedWithId: string; +} + +export enum PartnerDirection { + SharedBy = 'shared-by', + SharedWith = 'shared-with', +} const columns = ['id', 'name', 'email', 'profileImagePath', 'profileChangedAt'] as const; @@ -28,7 +37,7 @@ const withSharedWith = (eb: ExpressionBuilder) => { }; @Injectable() -export class PartnerRepository implements IPartnerRepository { +export class PartnerRepository { constructor(@InjectKysely() private db: Kysely) {} @GenerateSql({ params: [DummyValue.UUID] }) diff --git a/server/src/repositories/person.repository.ts b/server/src/repositories/person.repository.ts index 73fb8313d299e..b862d66f8abca 100644 --- a/server/src/repositories/person.repository.ts +++ b/server/src/repositories/person.repository.ts @@ -1,5 +1,5 @@ import { Injectable } from '@nestjs/common'; -import { ExpressionBuilder, Insertable, Kysely, sql } from 'kysely'; +import { ExpressionBuilder, Insertable, Kysely, Selectable, sql } from 'kysely'; import { jsonObjectFrom } from 'kysely/helpers/postgres'; import { InjectKysely } from 'nestjs-kysely'; import { AssetFaces, DB, FaceSearch, Person } from 'src/db'; @@ -7,23 +7,53 @@ import { ChunkedArray, DummyValue, GenerateSql } from 'src/decorators'; import { AssetFaceEntity } from 'src/entities/asset-face.entity'; import { PersonEntity } from 'src/entities/person.entity'; import { SourceType } from 'src/enum'; -import { - AssetFaceId, - DeleteFacesOptions, - IPersonRepository, - PeopleStatistics, - PersonNameResponse, - PersonNameSearchOptions, - PersonSearchOptions, - PersonStatistics, - SelectFaceOptions, - UnassignFacesOptions, - UpdateFacesData, -} from 'src/interfaces/person.interface'; import { mapUpsertColumns } from 'src/utils/database'; import { Paginated, PaginationOptions } from 'src/utils/pagination'; import { FindOptionsRelations } from 'typeorm'; +export interface PersonSearchOptions { + minimumFaceCount: number; + withHidden: boolean; + closestFaceAssetId?: string; +} + +export interface PersonNameSearchOptions { + withHidden?: boolean; +} + +export interface PersonNameResponse { + id: string; + name: string; +} + +export interface AssetFaceId { + assetId: string; + personId: string; +} + +export interface UpdateFacesData { + oldPersonId?: string; + faceIds?: string[]; + newPersonId: string; +} + +export interface PersonStatistics { + assets: number; +} + +export interface PeopleStatistics { + total: number; + hidden: number; +} + +export interface DeleteFacesOptions { + sourceType: SourceType; +} + +export type UnassignFacesOptions = DeleteFacesOptions; + +export type SelectFaceOptions = (keyof Selectable)[]; + const withPerson = (eb: ExpressionBuilder) => { return jsonObjectFrom( eb.selectFrom('person').selectAll('person').whereRef('person.id', '=', 'asset_faces.personId'), @@ -43,7 +73,7 @@ const withFaceSearch = (eb: ExpressionBuilder) => { }; @Injectable() -export class PersonRepository implements IPersonRepository { +export class PersonRepository { constructor(@InjectKysely() private db: Kysely) {} @GenerateSql({ params: [{ oldPersonId: DummyValue.UUID, newPersonId: DummyValue.UUID }] }) diff --git a/server/src/repositories/search.repository.ts b/server/src/repositories/search.repository.ts index 76b6653e3d73e..a6eb5c7a8502f 100644 --- a/server/src/repositories/search.repository.ts +++ b/server/src/repositories/search.repository.ts @@ -6,26 +6,202 @@ import { DB } from 'src/db'; import { DummyValue, GenerateSql } from 'src/decorators'; import { AssetEntity, searchAssetBuilder } from 'src/entities/asset.entity'; import { GeodataPlacesEntity } from 'src/entities/geodata-places.entity'; -import { AssetType } from 'src/enum'; -import { - AssetDuplicateSearch, - AssetSearchOptions, - FaceEmbeddingSearch, - GetCameraMakesOptions, - GetCameraModelsOptions, - GetCitiesOptions, - GetStatesOptions, - ISearchRepository, - SearchPaginationOptions, - SmartSearchOptions, -} from 'src/interfaces/search.interface'; +import { AssetStatus, AssetType } from 'src/enum'; import { LoggingRepository } from 'src/repositories/logging.repository'; import { anyUuid, asUuid } from 'src/utils/database'; import { Paginated } from 'src/utils/pagination'; import { isValidInteger } from 'src/validation'; +export interface SearchResult { + /** total matches */ + total: number; + /** collection size */ + count: number; + /** current page */ + page: number; + /** items for page */ + items: T[]; + /** score */ + distances: number[]; + facets: SearchFacet[]; +} + +export interface SearchFacet { + fieldName: string; + counts: Array<{ + count: number; + value: string; + }>; +} + +export type SearchExploreItemSet = Array<{ + value: string; + data: T; +}>; + +export interface SearchExploreItem { + fieldName: string; + items: SearchExploreItemSet; +} + +export interface SearchAssetIDOptions { + checksum?: Buffer; + deviceAssetId?: string; + id?: string; +} + +export interface SearchUserIdOptions { + deviceId?: string; + libraryId?: string | null; + userIds?: string[]; +} + +export type SearchIdOptions = SearchAssetIDOptions & SearchUserIdOptions; + +export interface SearchStatusOptions { + isArchived?: boolean; + isEncoded?: boolean; + isFavorite?: boolean; + isMotion?: boolean; + isOffline?: boolean; + isVisible?: boolean; + isNotInAlbum?: boolean; + type?: AssetType; + status?: AssetStatus; + withArchived?: boolean; + withDeleted?: boolean; +} + +export interface SearchOneToOneRelationOptions { + withExif?: boolean; + withStacked?: boolean; +} + +export interface SearchRelationOptions extends SearchOneToOneRelationOptions { + withFaces?: boolean; + withPeople?: boolean; +} + +export interface SearchDateOptions { + createdBefore?: Date; + createdAfter?: Date; + takenBefore?: Date; + takenAfter?: Date; + trashedBefore?: Date; + trashedAfter?: Date; + updatedBefore?: Date; + updatedAfter?: Date; +} + +export interface SearchPathOptions { + encodedVideoPath?: string; + originalFileName?: string; + originalPath?: string; + previewPath?: string; + thumbnailPath?: string; +} + +export interface SearchExifOptions { + city?: string | null; + country?: string | null; + lensModel?: string | null; + make?: string | null; + model?: string | null; + state?: string | null; + description?: string | null; +} + +export interface SearchEmbeddingOptions { + embedding: string; + userIds: string[]; +} + +export interface SearchPeopleOptions { + personIds?: string[]; +} + +export interface SearchTagOptions { + tagIds?: string[]; +} + +export interface SearchOrderOptions { + orderDirection?: 'asc' | 'desc'; +} + +export interface SearchPaginationOptions { + page: number; + size: number; +} + +type BaseAssetSearchOptions = SearchDateOptions & + SearchIdOptions & + SearchExifOptions & + SearchOrderOptions & + SearchPathOptions & + SearchStatusOptions & + SearchUserIdOptions & + SearchPeopleOptions & + SearchTagOptions; + +export type AssetSearchOptions = BaseAssetSearchOptions & SearchRelationOptions; + +export type AssetSearchOneToOneRelationOptions = BaseAssetSearchOptions & SearchOneToOneRelationOptions; + +export type AssetSearchBuilderOptions = Omit; + +export type SmartSearchOptions = SearchDateOptions & + SearchEmbeddingOptions & + SearchExifOptions & + SearchOneToOneRelationOptions & + SearchStatusOptions & + SearchUserIdOptions & + SearchPeopleOptions & + SearchTagOptions; + +export interface FaceEmbeddingSearch extends SearchEmbeddingOptions { + hasPerson?: boolean; + numResults: number; + maxDistance: number; +} + +export interface AssetDuplicateSearch { + assetId: string; + embedding: string; + maxDistance: number; + type: AssetType; + userIds: string[]; +} + +export interface FaceSearchResult { + distance: number; + id: string; + personId: string | null; +} + +export interface AssetDuplicateResult { + assetId: string; + duplicateId: string | null; + distance: number; +} + +export interface GetStatesOptions { + country?: string; +} + +export interface GetCitiesOptions extends GetStatesOptions { + state?: string; +} + +export interface GetCameraModelsOptions { + make?: string; +} + +export interface GetCameraMakesOptions { + model?: string; +} + @Injectable() -export class SearchRepository implements ISearchRepository { +export class SearchRepository { constructor( private logger: LoggingRepository, @InjectKysely() private db: Kysely, diff --git a/server/src/repositories/shared-link.repository.ts b/server/src/repositories/shared-link.repository.ts index 8e2e6976a5fd5..16dc48836a648 100644 --- a/server/src/repositories/shared-link.repository.ts +++ b/server/src/repositories/shared-link.repository.ts @@ -7,10 +7,14 @@ import { DB, SharedLinks } from 'src/db'; import { DummyValue, GenerateSql } from 'src/decorators'; import { SharedLinkEntity } from 'src/entities/shared-link.entity'; import { SharedLinkType } from 'src/enum'; -import { ISharedLinkRepository, SharedLinkSearchOptions } from 'src/interfaces/shared-link.interface'; + +export type SharedLinkSearchOptions = { + userId: string; + albumId?: string; +}; @Injectable() -export class SharedLinkRepository implements ISharedLinkRepository { +export class SharedLinkRepository { constructor(@InjectKysely() private db: Kysely) {} @GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID] }) diff --git a/server/src/repositories/stack.repository.ts b/server/src/repositories/stack.repository.ts index 018d7e77a459a..ae96005350fa8 100644 --- a/server/src/repositories/stack.repository.ts +++ b/server/src/repositories/stack.repository.ts @@ -5,9 +5,13 @@ import { InjectKysely } from 'nestjs-kysely'; import { DB } from 'src/db'; import { DummyValue, GenerateSql } from 'src/decorators'; import { StackEntity } from 'src/entities/stack.entity'; -import { IStackRepository, StackSearch } from 'src/interfaces/stack.interface'; import { asUuid } from 'src/utils/database'; +export interface StackSearch { + ownerId: string; + primaryAssetId?: string; +} + const withAssets = (eb: ExpressionBuilder, withTags = false) => { return jsonArrayFrom( eb @@ -35,7 +39,7 @@ const withAssets = (eb: ExpressionBuilder, withTags = false) }; @Injectable() -export class StackRepository implements IStackRepository { +export class StackRepository { constructor(@InjectKysely() private db: Kysely) {} @GenerateSql({ params: [{ ownerId: DummyValue.UUID }] }) diff --git a/server/src/repositories/storage.repository.ts b/server/src/repositories/storage.repository.ts index 6766f442b88cc..15b81e7106a44 100644 --- a/server/src/repositories/storage.repository.ts +++ b/server/src/repositories/storage.repository.ts @@ -5,20 +5,38 @@ import { escapePath, glob, globStream } from 'fast-glob'; import { constants, createReadStream, createWriteStream, existsSync, mkdirSync } from 'node:fs'; import fs from 'node:fs/promises'; import path from 'node:path'; -import { Writable } from 'node:stream'; +import { Readable, Writable } from 'node:stream'; import { CrawlOptionsDto, WalkOptionsDto } from 'src/dtos/library.dto'; -import { - DiskUsage, - IStorageRepository, - ImmichReadStream, - ImmichZipStream, - WatchEvents, -} from 'src/interfaces/storage.interface'; import { LoggingRepository } from 'src/repositories/logging.repository'; import { mimeTypes } from 'src/utils/mime-types'; +export interface WatchEvents { + onReady(): void; + onAdd(path: string): void; + onChange(path: string): void; + onUnlink(path: string): void; + onError(error: Error): void; +} + +export interface ImmichReadStream { + stream: Readable; + type?: string; + length?: number; +} + +export interface ImmichZipStream extends ImmichReadStream { + addFile: (inputPath: string, filename: string) => void; + finalize: () => Promise; +} + +export interface DiskUsage { + available: number; + free: number; + total: number; +} + @Injectable() -export class StorageRepository implements IStorageRepository { +export class StorageRepository { constructor(private logger: LoggingRepository) { this.logger.setContext(StorageRepository.name); } diff --git a/server/src/repositories/tag.repository.ts b/server/src/repositories/tag.repository.ts index 3489f436400a1..c5156e183733a 100644 --- a/server/src/repositories/tag.repository.ts +++ b/server/src/repositories/tag.repository.ts @@ -2,12 +2,13 @@ import { Injectable } from '@nestjs/common'; import { InjectDataSource, InjectRepository } from '@nestjs/typeorm'; import { Chunked, ChunkedSet, DummyValue, GenerateSql } from 'src/decorators'; import { TagEntity } from 'src/entities/tag.entity'; -import { AssetTagItem, ITagRepository } from 'src/interfaces/tag.interface'; import { LoggingRepository } from 'src/repositories/logging.repository'; import { DataSource, In, Repository } from 'typeorm'; +export type AssetTagItem = { assetId: string; tagId: string }; + @Injectable() -export class TagRepository implements ITagRepository { +export class TagRepository { constructor( @InjectDataSource() private dataSource: DataSource, @InjectRepository(TagEntity) private repository: Repository, diff --git a/server/src/repositories/user.repository.ts b/server/src/repositories/user.repository.ts index 417ee141f4d42..22a9ecad5c479 100644 --- a/server/src/repositories/user.repository.ts +++ b/server/src/repositories/user.repository.ts @@ -6,12 +6,6 @@ import { DummyValue, GenerateSql } from 'src/decorators'; import { UserMetadata } from 'src/entities/user-metadata.entity'; import { UserEntity, withMetadata } from 'src/entities/user.entity'; import { UserStatus } from 'src/enum'; -import { - IUserRepository, - UserFindOptions, - UserListFilter, - UserStatsQueryResponse, -} from 'src/interfaces/user.interface'; import { asUuid } from 'src/utils/database'; const columns = [ @@ -34,8 +28,27 @@ const columns = [ type Upsert = Insertable; +export interface UserListFilter { + withDeleted?: boolean; +} + +export interface UserStatsQueryResponse { + userId: string; + userName: string; + photos: number; + videos: number; + usage: number; + usagePhotos: number; + usageVideos: number; + quotaSizeInBytes: number | null; +} + +export interface UserFindOptions { + withDeleted?: boolean; +} + @Injectable() -export class UserRepository implements IUserRepository { +export class UserRepository { constructor(@InjectKysely() private db: Kysely) {} @GenerateSql({ params: [DummyValue.UUID, DummyValue.BOOLEAN] }) diff --git a/server/src/services/album.service.ts b/server/src/services/album.service.ts index 0286b387c35a5..722745ebd242e 100644 --- a/server/src/services/album.service.ts +++ b/server/src/services/album.service.ts @@ -16,7 +16,7 @@ import { AuthDto } from 'src/dtos/auth.dto'; import { AlbumUserEntity } from 'src/entities/album-user.entity'; import { AlbumEntity } from 'src/entities/album.entity'; import { Permission } from 'src/enum'; -import { AlbumAssetCount, AlbumInfoOptions } from 'src/interfaces/album.interface'; +import { AlbumAssetCount, AlbumInfoOptions } from 'src/repositories/album.repository'; import { BaseService } from 'src/services/base.service'; import { addAssets, removeAssets } from 'src/utils/asset.util'; diff --git a/server/src/services/asset.service.spec.ts b/server/src/services/asset.service.spec.ts index 9d64aacf10239..3c9cf3739fe5d 100755 --- a/server/src/services/asset.service.spec.ts +++ b/server/src/services/asset.service.spec.ts @@ -4,8 +4,8 @@ import { mapAsset } from 'src/dtos/asset-response.dto'; import { AssetJobName, AssetStatsResponseDto } from 'src/dtos/asset.dto'; import { AssetEntity } from 'src/entities/asset.entity'; import { AssetStatus, AssetType } from 'src/enum'; -import { AssetStats } from 'src/interfaces/asset.interface'; import { JobName, JobStatus } from 'src/interfaces/job.interface'; +import { AssetStats } from 'src/repositories/asset.repository'; import { AssetService } from 'src/services/asset.service'; import { assetStub } from 'test/fixtures/asset.stub'; import { authStub } from 'test/fixtures/auth.stub'; diff --git a/server/src/services/backup.service.ts b/server/src/services/backup.service.ts index 324bc4cc13232..d0a8ce69b674a 100644 --- a/server/src/services/backup.service.ts +++ b/server/src/services/backup.service.ts @@ -4,9 +4,9 @@ import semver from 'semver'; import { StorageCore } from 'src/cores/storage.core'; import { OnEvent, OnJob } from 'src/decorators'; import { ImmichWorker, StorageFolder } from 'src/enum'; -import { DatabaseLock } from 'src/interfaces/database.interface'; import { ArgOf } from 'src/interfaces/event.interface'; import { JobName, JobStatus, QueueName } from 'src/interfaces/job.interface'; +import { DatabaseLock } from 'src/repositories/database.repository'; import { BaseService } from 'src/services/base.service'; import { handlePromiseError } from 'src/utils/misc'; diff --git a/server/src/services/base.service.ts b/server/src/services/base.service.ts index 9285c69ced5c0..d0f00bd2ab367 100644 --- a/server/src/services/base.service.ts +++ b/server/src/services/base.service.ts @@ -6,44 +6,43 @@ import { SALT_ROUNDS } from 'src/constants'; import { StorageCore } from 'src/cores/storage.core'; import { Users } from 'src/db'; import { UserEntity } from 'src/entities/user.entity'; -import { IAlbumRepository } from 'src/interfaces/album.interface'; -import { IAssetRepository } from 'src/interfaces/asset.interface'; -import { ICryptoRepository } from 'src/interfaces/crypto.interface'; -import { IDatabaseRepository } from 'src/interfaces/database.interface'; import { IEventRepository } from 'src/interfaces/event.interface'; import { IJobRepository } from 'src/interfaces/job.interface'; -import { ILibraryRepository } from 'src/interfaces/library.interface'; import { IMachineLearningRepository } from 'src/interfaces/machine-learning.interface'; -import { IMoveRepository } from 'src/interfaces/move.interface'; -import { IPartnerRepository } from 'src/interfaces/partner.interface'; -import { IPersonRepository } from 'src/interfaces/person.interface'; -import { ISearchRepository } from 'src/interfaces/search.interface'; -import { ISharedLinkRepository } from 'src/interfaces/shared-link.interface'; -import { IStackRepository } from 'src/interfaces/stack.interface'; -import { IStorageRepository } from 'src/interfaces/storage.interface'; -import { ITagRepository } from 'src/interfaces/tag.interface'; -import { IUserRepository } from 'src/interfaces/user.interface'; import { AccessRepository } from 'src/repositories/access.repository'; import { ActivityRepository } from 'src/repositories/activity.repository'; import { AlbumUserRepository } from 'src/repositories/album-user.repository'; +import { AlbumRepository } from 'src/repositories/album.repository'; import { ApiKeyRepository } from 'src/repositories/api-key.repository'; +import { AssetRepository } from 'src/repositories/asset.repository'; import { AuditRepository } from 'src/repositories/audit.repository'; import { ConfigRepository } from 'src/repositories/config.repository'; import { CronRepository } from 'src/repositories/cron.repository'; import { CryptoRepository } from 'src/repositories/crypto.repository'; +import { DatabaseRepository } from 'src/repositories/database.repository'; +import { LibraryRepository } from 'src/repositories/library.repository'; import { LoggingRepository } from 'src/repositories/logging.repository'; import { MapRepository } from 'src/repositories/map.repository'; import { MediaRepository } from 'src/repositories/media.repository'; import { MemoryRepository } from 'src/repositories/memory.repository'; import { MetadataRepository } from 'src/repositories/metadata.repository'; +import { MoveRepository } from 'src/repositories/move.repository'; import { NotificationRepository } from 'src/repositories/notification.repository'; import { OAuthRepository } from 'src/repositories/oauth.repository'; +import { PartnerRepository } from 'src/repositories/partner.repository'; +import { PersonRepository } from 'src/repositories/person.repository'; import { ProcessRepository } from 'src/repositories/process.repository'; +import { SearchRepository } from 'src/repositories/search.repository'; import { ServerInfoRepository } from 'src/repositories/server-info.repository'; import { SessionRepository } from 'src/repositories/session.repository'; +import { SharedLinkRepository } from 'src/repositories/shared-link.repository'; +import { StackRepository } from 'src/repositories/stack.repository'; +import { StorageRepository } from 'src/repositories/storage.repository'; import { SystemMetadataRepository } from 'src/repositories/system-metadata.repository'; +import { TagRepository } from 'src/repositories/tag.repository'; import { TelemetryRepository } from 'src/repositories/telemetry.repository'; import { TrashRepository } from 'src/repositories/trash.repository'; +import { UserRepository } from 'src/repositories/user.repository'; import { VersionHistoryRepository } from 'src/repositories/version-history.repository'; import { ViewRepository } from 'src/repositories/view-repository'; import { AccessRequest, checkAccess, requireAccess } from 'src/utils/access'; @@ -57,39 +56,39 @@ export class BaseService { protected accessRepository: AccessRepository, protected activityRepository: ActivityRepository, protected auditRepository: AuditRepository, - @Inject(IAlbumRepository) protected albumRepository: IAlbumRepository, + protected albumRepository: AlbumRepository, protected albumUserRepository: AlbumUserRepository, - @Inject(IAssetRepository) protected assetRepository: IAssetRepository, + protected assetRepository: AssetRepository, protected configRepository: ConfigRepository, protected cronRepository: CronRepository, - @Inject(ICryptoRepository) protected cryptoRepository: CryptoRepository, - @Inject(IDatabaseRepository) protected databaseRepository: IDatabaseRepository, + protected cryptoRepository: CryptoRepository, + protected databaseRepository: DatabaseRepository, @Inject(IEventRepository) protected eventRepository: IEventRepository, @Inject(IJobRepository) protected jobRepository: IJobRepository, protected keyRepository: ApiKeyRepository, - @Inject(ILibraryRepository) protected libraryRepository: ILibraryRepository, + protected libraryRepository: LibraryRepository, @Inject(IMachineLearningRepository) protected machineLearningRepository: IMachineLearningRepository, protected mapRepository: MapRepository, protected mediaRepository: MediaRepository, protected memoryRepository: MemoryRepository, protected metadataRepository: MetadataRepository, - @Inject(IMoveRepository) protected moveRepository: IMoveRepository, + protected moveRepository: MoveRepository, protected notificationRepository: NotificationRepository, protected oauthRepository: OAuthRepository, - @Inject(IPartnerRepository) protected partnerRepository: IPartnerRepository, - @Inject(IPersonRepository) protected personRepository: IPersonRepository, + protected partnerRepository: PartnerRepository, + protected personRepository: PersonRepository, protected processRepository: ProcessRepository, - @Inject(ISearchRepository) protected searchRepository: ISearchRepository, + protected searchRepository: SearchRepository, protected serverInfoRepository: ServerInfoRepository, protected sessionRepository: SessionRepository, - @Inject(ISharedLinkRepository) protected sharedLinkRepository: ISharedLinkRepository, - @Inject(IStackRepository) protected stackRepository: IStackRepository, - @Inject(IStorageRepository) protected storageRepository: IStorageRepository, + protected sharedLinkRepository: SharedLinkRepository, + protected stackRepository: StackRepository, + protected storageRepository: StorageRepository, protected systemMetadataRepository: SystemMetadataRepository, - @Inject(ITagRepository) protected tagRepository: ITagRepository, + protected tagRepository: TagRepository, protected telemetryRepository: TelemetryRepository, protected trashRepository: TrashRepository, - @Inject(IUserRepository) protected userRepository: IUserRepository, + protected userRepository: UserRepository, protected versionRepository: VersionHistoryRepository, protected viewRepository: ViewRepository, ) { diff --git a/server/src/services/database.service.spec.ts b/server/src/services/database.service.spec.ts index 566cd32778b3b..d50b7facf6b0a 100644 --- a/server/src/services/database.service.spec.ts +++ b/server/src/services/database.service.spec.ts @@ -1,4 +1,5 @@ -import { DatabaseExtension, EXTENSION_NAMES, VectorExtension } from 'src/interfaces/database.interface'; +import { DatabaseExtension } from 'src/enum'; +import { EXTENSION_NAMES, VectorExtension } from 'src/repositories/database.repository'; import { DatabaseService } from 'src/services/database.service'; import { mockEnvData } from 'test/repositories/config.repository.mock'; import { newTestService, ServiceMocks } from 'test/utils'; diff --git a/server/src/services/database.service.ts b/server/src/services/database.service.ts index ec0075b11931d..eabb0b0091c8f 100644 --- a/server/src/services/database.service.ts +++ b/server/src/services/database.service.ts @@ -2,14 +2,9 @@ import { Injectable } from '@nestjs/common'; import { Duration } from 'luxon'; import semver from 'semver'; import { OnEvent } from 'src/decorators'; -import { - DatabaseExtension, - DatabaseLock, - EXTENSION_NAMES, - VectorExtension, - VectorIndex, -} from 'src/interfaces/database.interface'; +import { DatabaseExtension } from 'src/enum'; import { BootstrapEventPriority } from 'src/interfaces/event.interface'; +import { DatabaseLock, EXTENSION_NAMES, VectorExtension, VectorIndex } from 'src/repositories/database.repository'; import { BaseService } from 'src/services/base.service'; type CreateFailedArgs = { name: string; extension: string; otherName: string }; diff --git a/server/src/services/download.service.ts b/server/src/services/download.service.ts index 3d66f009cfb81..dd2430778a970 100644 --- a/server/src/services/download.service.ts +++ b/server/src/services/download.service.ts @@ -6,7 +6,7 @@ import { AuthDto } from 'src/dtos/auth.dto'; import { DownloadArchiveInfo, DownloadInfoDto, DownloadResponseDto } from 'src/dtos/download.dto'; import { AssetEntity } from 'src/entities/asset.entity'; import { Permission } from 'src/enum'; -import { ImmichReadStream } from 'src/interfaces/storage.interface'; +import { ImmichReadStream } from 'src/repositories/storage.repository'; import { BaseService } from 'src/services/base.service'; import { HumanReadableSize } from 'src/utils/bytes'; import { usePagination } from 'src/utils/pagination'; diff --git a/server/src/services/duplicate.service.spec.ts b/server/src/services/duplicate.service.spec.ts index 0451f1f2b360d..7a8b9ed27bf0c 100644 --- a/server/src/services/duplicate.service.spec.ts +++ b/server/src/services/duplicate.service.spec.ts @@ -1,5 +1,5 @@ -import { WithoutProperty } from 'src/interfaces/asset.interface'; import { JobName, JobStatus } from 'src/interfaces/job.interface'; +import { WithoutProperty } from 'src/repositories/asset.repository'; import { DuplicateService } from 'src/services/duplicate.service'; import { SearchService } from 'src/services/search.service'; import { assetStub } from 'test/fixtures/asset.stub'; diff --git a/server/src/services/duplicate.service.ts b/server/src/services/duplicate.service.ts index 7e8ea49991304..1b0d583cc3024 100644 --- a/server/src/services/duplicate.service.ts +++ b/server/src/services/duplicate.service.ts @@ -4,9 +4,9 @@ import { mapAsset } from 'src/dtos/asset-response.dto'; import { AuthDto } from 'src/dtos/auth.dto'; import { DuplicateResponseDto } from 'src/dtos/duplicate.dto'; import { AssetEntity } from 'src/entities/asset.entity'; -import { WithoutProperty } from 'src/interfaces/asset.interface'; import { JOBS_ASSET_PAGINATION_SIZE, JobName, JobOf, JobStatus, QueueName } from 'src/interfaces/job.interface'; -import { AssetDuplicateResult } from 'src/interfaces/search.interface'; +import { WithoutProperty } from 'src/repositories/asset.repository'; +import { AssetDuplicateResult } from 'src/repositories/search.repository'; import { BaseService } from 'src/services/base.service'; import { getAssetFiles } from 'src/utils/asset.util'; import { isDuplicateDetectionEnabled } from 'src/utils/misc'; diff --git a/server/src/services/library.service.ts b/server/src/services/library.service.ts index 59ac171ce6c86..5235b786e916d 100644 --- a/server/src/services/library.service.ts +++ b/server/src/services/library.service.ts @@ -17,9 +17,9 @@ import { import { AssetEntity } from 'src/entities/asset.entity'; import { LibraryEntity } from 'src/entities/library.entity'; import { AssetType, ImmichWorker } from 'src/enum'; -import { DatabaseLock } from 'src/interfaces/database.interface'; import { ArgOf } from 'src/interfaces/event.interface'; import { JobName, JobOf, JOBS_LIBRARY_PAGINATION_SIZE, JobStatus, QueueName } from 'src/interfaces/job.interface'; +import { DatabaseLock } from 'src/repositories/database.repository'; import { BaseService } from 'src/services/base.service'; import { mimeTypes } from 'src/utils/mime-types'; import { handlePromiseError } from 'src/utils/misc'; diff --git a/server/src/services/media.service.spec.ts b/server/src/services/media.service.spec.ts index 3f48d8534a4a9..52ccab1c9194c 100644 --- a/server/src/services/media.service.spec.ts +++ b/server/src/services/media.service.spec.ts @@ -13,8 +13,8 @@ import { TranscodePolicy, VideoCodec, } from 'src/enum'; -import { WithoutProperty } from 'src/interfaces/asset.interface'; import { JobCounts, JobName, JobStatus } from 'src/interfaces/job.interface'; +import { WithoutProperty } from 'src/repositories/asset.repository'; import { MediaService } from 'src/services/media.service'; import { RawImageInfo } from 'src/types'; import { assetStub } from 'test/fixtures/asset.stub'; diff --git a/server/src/services/media.service.ts b/server/src/services/media.service.ts index c22d124b63400..58621c1b196d5 100644 --- a/server/src/services/media.service.ts +++ b/server/src/services/media.service.ts @@ -18,7 +18,6 @@ import { VideoCodec, VideoContainer, } from 'src/enum'; -import { UpsertFileOptions, WithoutProperty } from 'src/interfaces/asset.interface'; import { JOBS_ASSET_PAGINATION_SIZE, JobItem, @@ -27,6 +26,7 @@ import { JobStatus, QueueName, } from 'src/interfaces/job.interface'; +import { UpsertFileOptions, WithoutProperty } from 'src/repositories/asset.repository'; import { BaseService } from 'src/services/base.service'; import { AudioStreamInfo, VideoFormat, VideoInterfaces, VideoStreamInfo } from 'src/types'; import { getAssetFiles } from 'src/utils/asset.util'; diff --git a/server/src/services/metadata.service.spec.ts b/server/src/services/metadata.service.spec.ts index 5657dd02b94b4..c7c675ab3ecb2 100644 --- a/server/src/services/metadata.service.spec.ts +++ b/server/src/services/metadata.service.spec.ts @@ -5,8 +5,8 @@ import { constants } from 'node:fs/promises'; import { AssetEntity } from 'src/entities/asset.entity'; import { ExifEntity } from 'src/entities/exif.entity'; import { AssetType, ExifOrientation, ImmichWorker, SourceType } from 'src/enum'; -import { WithoutProperty } from 'src/interfaces/asset.interface'; import { JobName, JobStatus } from 'src/interfaces/job.interface'; +import { WithoutProperty } from 'src/repositories/asset.repository'; import { ImmichTags } from 'src/repositories/metadata.repository'; import { MetadataService } from 'src/services/metadata.service'; import { assetStub } from 'test/fixtures/asset.stub'; diff --git a/server/src/services/metadata.service.ts b/server/src/services/metadata.service.ts index db3af9fca09e3..53110a20e0160 100644 --- a/server/src/services/metadata.service.ts +++ b/server/src/services/metadata.service.ts @@ -14,10 +14,10 @@ import { AssetFaceEntity } from 'src/entities/asset-face.entity'; import { AssetEntity } from 'src/entities/asset.entity'; import { PersonEntity } from 'src/entities/person.entity'; import { AssetType, ExifOrientation, ImmichWorker, SourceType } from 'src/enum'; -import { WithoutProperty } from 'src/interfaces/asset.interface'; -import { DatabaseLock } from 'src/interfaces/database.interface'; import { ArgOf } from 'src/interfaces/event.interface'; import { JobName, JobOf, JOBS_ASSET_PAGINATION_SIZE, JobStatus, QueueName } from 'src/interfaces/job.interface'; +import { WithoutProperty } from 'src/repositories/asset.repository'; +import { DatabaseLock } from 'src/repositories/database.repository'; import { ReverseGeocodeResult } from 'src/repositories/map.repository'; import { ImmichTags } from 'src/repositories/metadata.repository'; import { BaseService } from 'src/services/base.service'; diff --git a/server/src/services/partner.service.spec.ts b/server/src/services/partner.service.spec.ts index 02dff32a7211c..9c29afaeaa468 100644 --- a/server/src/services/partner.service.spec.ts +++ b/server/src/services/partner.service.spec.ts @@ -1,5 +1,5 @@ import { BadRequestException } from '@nestjs/common'; -import { PartnerDirection } from 'src/interfaces/partner.interface'; +import { PartnerDirection } from 'src/repositories/partner.repository'; import { PartnerService } from 'src/services/partner.service'; import { authStub } from 'test/fixtures/auth.stub'; import { partnerStub } from 'test/fixtures/partner.stub'; diff --git a/server/src/services/partner.service.ts b/server/src/services/partner.service.ts index f17bab24bab1e..32b3ae3d3f9e3 100644 --- a/server/src/services/partner.service.ts +++ b/server/src/services/partner.service.ts @@ -4,7 +4,7 @@ import { PartnerResponseDto, PartnerSearchDto, UpdatePartnerDto } from 'src/dtos import { mapUser } from 'src/dtos/user.dto'; import { PartnerEntity } from 'src/entities/partner.entity'; import { Permission } from 'src/enum'; -import { PartnerDirection, PartnerIds } from 'src/interfaces/partner.interface'; +import { PartnerDirection, PartnerIds } from 'src/repositories/partner.repository'; import { BaseService } from 'src/services/base.service'; @Injectable() diff --git a/server/src/services/person.service.spec.ts b/server/src/services/person.service.spec.ts index 0b3adec571994..ec2417c793b58 100644 --- a/server/src/services/person.service.spec.ts +++ b/server/src/services/person.service.spec.ts @@ -3,10 +3,10 @@ import { BulkIdErrorReason } from 'src/dtos/asset-ids.response.dto'; import { mapFaces, mapPerson, PersonResponseDto } from 'src/dtos/person.dto'; import { AssetFaceEntity } from 'src/entities/asset-face.entity'; import { CacheControl, Colorspace, ImageFormat, SourceType, SystemMetadataKey } from 'src/enum'; -import { WithoutProperty } from 'src/interfaces/asset.interface'; import { JobName, JobStatus } from 'src/interfaces/job.interface'; import { DetectedFaces } from 'src/interfaces/machine-learning.interface'; -import { FaceSearchResult } from 'src/interfaces/search.interface'; +import { WithoutProperty } from 'src/repositories/asset.repository'; +import { FaceSearchResult } from 'src/repositories/search.repository'; import { PersonService } from 'src/services/person.service'; import { ImmichFileResponse } from 'src/utils/file'; import { assetStub } from 'test/fixtures/asset.stub'; diff --git a/server/src/services/person.service.ts b/server/src/services/person.service.ts index 116d2ec6c85cc..2ae703afb3770 100644 --- a/server/src/services/person.service.ts +++ b/server/src/services/person.service.ts @@ -32,7 +32,6 @@ import { SourceType, SystemMetadataKey, } from 'src/enum'; -import { WithoutProperty } from 'src/interfaces/asset.interface'; import { JOBS_ASSET_PAGINATION_SIZE, JobItem, @@ -42,7 +41,8 @@ import { QueueName, } from 'src/interfaces/job.interface'; import { BoundingBox } from 'src/interfaces/machine-learning.interface'; -import { UpdateFacesData } from 'src/interfaces/person.interface'; +import { WithoutProperty } from 'src/repositories/asset.repository'; +import { UpdateFacesData } from 'src/repositories/person.repository'; import { BaseService } from 'src/services/base.service'; import { CropOptions, ImageDimensions, InputDimensions } from 'src/types'; import { getAssetFiles } from 'src/utils/asset.util'; diff --git a/server/src/services/search.service.ts b/server/src/services/search.service.ts index b74d3d3cbafde..e2ad9e7f99f04 100644 --- a/server/src/services/search.service.ts +++ b/server/src/services/search.service.ts @@ -16,7 +16,7 @@ import { } from 'src/dtos/search.dto'; import { AssetEntity } from 'src/entities/asset.entity'; import { AssetOrder } from 'src/enum'; -import { SearchExploreItem } from 'src/interfaces/search.interface'; +import { SearchExploreItem } from 'src/repositories/search.repository'; import { BaseService } from 'src/services/base.service'; import { getMyPartnerIds } from 'src/utils/asset.util'; import { isSmartSearchEnabled } from 'src/utils/misc'; @@ -109,7 +109,7 @@ export class SearchService extends BaseService { return suggestions; } - private getSuggestions(userIds: string[], dto: SearchSuggestionRequestDto) { + private getSuggestions(userIds: string[], dto: SearchSuggestionRequestDto): Promise> { switch (dto.type) { case SearchSuggestionType.COUNTRY: { return this.searchRepository.getCountries(userIds); @@ -127,7 +127,7 @@ export class SearchService extends BaseService { return this.searchRepository.getCameraModels(userIds, dto); } default: { - return [] as (string | null)[]; + return Promise.resolve([]); } } } diff --git a/server/src/services/server.service.ts b/server/src/services/server.service.ts index e9dd908a7c3ac..9112c40a17d85 100644 --- a/server/src/services/server.service.ts +++ b/server/src/services/server.service.ts @@ -14,7 +14,7 @@ import { UsageByUserDto, } from 'src/dtos/server.dto'; import { StorageFolder, SystemMetadataKey } from 'src/enum'; -import { UserStatsQueryResponse } from 'src/interfaces/user.interface'; +import { UserStatsQueryResponse } from 'src/repositories/user.repository'; import { BaseService } from 'src/services/base.service'; import { asHumanReadable } from 'src/utils/bytes'; import { mimeTypes } from 'src/utils/mime-types'; diff --git a/server/src/services/smart-info.service.spec.ts b/server/src/services/smart-info.service.spec.ts index 79e13ea7ab57a..403c6e9a6a65b 100644 --- a/server/src/services/smart-info.service.spec.ts +++ b/server/src/services/smart-info.service.spec.ts @@ -1,7 +1,7 @@ import { SystemConfig } from 'src/config'; import { ImmichWorker } from 'src/enum'; -import { WithoutProperty } from 'src/interfaces/asset.interface'; import { JobName, JobStatus } from 'src/interfaces/job.interface'; +import { WithoutProperty } from 'src/repositories/asset.repository'; import { SmartInfoService } from 'src/services/smart-info.service'; import { getCLIPModelInfo } from 'src/utils/misc'; import { assetStub } from 'test/fixtures/asset.stub'; diff --git a/server/src/services/smart-info.service.ts b/server/src/services/smart-info.service.ts index 8fef961fe1f32..ebf9e1d28794b 100644 --- a/server/src/services/smart-info.service.ts +++ b/server/src/services/smart-info.service.ts @@ -2,10 +2,10 @@ import { Injectable } from '@nestjs/common'; import { SystemConfig } from 'src/config'; import { OnEvent, OnJob } from 'src/decorators'; import { ImmichWorker } from 'src/enum'; -import { WithoutProperty } from 'src/interfaces/asset.interface'; -import { DatabaseLock } from 'src/interfaces/database.interface'; import { ArgOf } from 'src/interfaces/event.interface'; import { JOBS_ASSET_PAGINATION_SIZE, JobName, JobOf, JobStatus, QueueName } from 'src/interfaces/job.interface'; +import { WithoutProperty } from 'src/repositories/asset.repository'; +import { DatabaseLock } from 'src/repositories/database.repository'; import { BaseService } from 'src/services/base.service'; import { getAssetFiles } from 'src/utils/asset.util'; import { getCLIPModelInfo, isSmartSearchEnabled } from 'src/utils/misc'; diff --git a/server/src/services/storage-template.service.ts b/server/src/services/storage-template.service.ts index e8e4bd12a5569..6b0409de1de95 100644 --- a/server/src/services/storage-template.service.ts +++ b/server/src/services/storage-template.service.ts @@ -8,9 +8,9 @@ import { OnEvent, OnJob } from 'src/decorators'; import { SystemConfigTemplateStorageOptionDto } from 'src/dtos/system-config.dto'; import { AssetEntity } from 'src/entities/asset.entity'; import { AssetPathType, AssetType, StorageFolder } from 'src/enum'; -import { DatabaseLock } from 'src/interfaces/database.interface'; import { ArgOf } from 'src/interfaces/event.interface'; import { JobName, JobOf, JOBS_ASSET_PAGINATION_SIZE, JobStatus, QueueName } from 'src/interfaces/job.interface'; +import { DatabaseLock } from 'src/repositories/database.repository'; import { BaseService } from 'src/services/base.service'; import { getLivePhotoMotionFilename } from 'src/utils/file'; import { usePagination } from 'src/utils/pagination'; diff --git a/server/src/services/storage.service.ts b/server/src/services/storage.service.ts index ce26df486977e..6921d3356055a 100644 --- a/server/src/services/storage.service.ts +++ b/server/src/services/storage.service.ts @@ -4,8 +4,8 @@ import { StorageCore } from 'src/cores/storage.core'; import { OnEvent, OnJob } from 'src/decorators'; import { SystemFlags } from 'src/entities/system-metadata.entity'; import { StorageFolder, SystemMetadataKey } from 'src/enum'; -import { DatabaseLock } from 'src/interfaces/database.interface'; import { JobName, JobOf, JobStatus, QueueName } from 'src/interfaces/job.interface'; +import { DatabaseLock } from 'src/repositories/database.repository'; import { BaseService } from 'src/services/base.service'; import { ImmichStartupError } from 'src/utils/misc'; diff --git a/server/src/services/tag.service.ts b/server/src/services/tag.service.ts index 4c31790d72c5c..83d4b40340b3d 100644 --- a/server/src/services/tag.service.ts +++ b/server/src/services/tag.service.ts @@ -14,7 +14,7 @@ import { import { TagEntity } from 'src/entities/tag.entity'; import { Permission } from 'src/enum'; import { JobName, JobStatus, QueueName } from 'src/interfaces/job.interface'; -import { AssetTagItem } from 'src/interfaces/tag.interface'; +import { AssetTagItem } from 'src/repositories/tag.repository'; import { BaseService } from 'src/services/base.service'; import { addAssets, removeAssets } from 'src/utils/asset.util'; import { upsertTags } from 'src/utils/tag'; diff --git a/server/src/services/timeline.service.spec.ts b/server/src/services/timeline.service.spec.ts index 15dab6bc05b1a..749633998b33b 100644 --- a/server/src/services/timeline.service.spec.ts +++ b/server/src/services/timeline.service.spec.ts @@ -1,5 +1,5 @@ import { BadRequestException } from '@nestjs/common'; -import { TimeBucketSize } from 'src/interfaces/asset.interface'; +import { TimeBucketSize } from 'src/repositories/asset.repository'; import { TimelineService } from 'src/services/timeline.service'; import { assetStub } from 'test/fixtures/asset.stub'; import { authStub } from 'test/fixtures/auth.stub'; diff --git a/server/src/services/timeline.service.ts b/server/src/services/timeline.service.ts index 04fd206fe7cbe..bc4c7fad734ac 100644 --- a/server/src/services/timeline.service.ts +++ b/server/src/services/timeline.service.ts @@ -3,7 +3,7 @@ import { AssetResponseDto, SanitizedAssetResponseDto, mapAsset } from 'src/dtos/ import { AuthDto } from 'src/dtos/auth.dto'; import { TimeBucketAssetDto, TimeBucketDto, TimeBucketResponseDto } from 'src/dtos/time-bucket.dto'; import { Permission } from 'src/enum'; -import { TimeBucketOptions } from 'src/interfaces/asset.interface'; +import { TimeBucketOptions } from 'src/repositories/asset.repository'; import { BaseService } from 'src/services/base.service'; import { getMyPartnerIds } from 'src/utils/asset.util'; diff --git a/server/src/services/user-admin.service.ts b/server/src/services/user-admin.service.ts index 784c95954eaa7..3df9a218f334a 100644 --- a/server/src/services/user-admin.service.ts +++ b/server/src/services/user-admin.service.ts @@ -12,7 +12,7 @@ import { } from 'src/dtos/user.dto'; import { UserMetadataKey, UserStatus } from 'src/enum'; import { JobName } from 'src/interfaces/job.interface'; -import { UserFindOptions } from 'src/interfaces/user.interface'; +import { UserFindOptions } from 'src/repositories/user.repository'; import { BaseService } from 'src/services/base.service'; import { getPreferences, getPreferencesPartial, mergePreferences } from 'src/utils/preferences'; diff --git a/server/src/services/user.service.ts b/server/src/services/user.service.ts index f4ae42b5edd05..dfd9c7715f8c2 100644 --- a/server/src/services/user.service.ts +++ b/server/src/services/user.service.ts @@ -12,7 +12,7 @@ import { UserMetadataEntity } from 'src/entities/user-metadata.entity'; import { UserEntity } from 'src/entities/user.entity'; import { CacheControl, StorageFolder, UserMetadataKey } from 'src/enum'; import { JobName, JobOf, JobStatus, QueueName } from 'src/interfaces/job.interface'; -import { UserFindOptions } from 'src/interfaces/user.interface'; +import { UserFindOptions } from 'src/repositories/user.repository'; import { BaseService } from 'src/services/base.service'; import { ImmichFileResponse } from 'src/utils/file'; import { getPreferences, getPreferencesPartial, mergePreferences } from 'src/utils/preferences'; diff --git a/server/src/services/version.service.ts b/server/src/services/version.service.ts index ff4fa3c6bf636..ee36d30041844 100644 --- a/server/src/services/version.service.ts +++ b/server/src/services/version.service.ts @@ -6,9 +6,9 @@ import { OnEvent, OnJob } from 'src/decorators'; import { ReleaseNotification, ServerVersionResponseDto } from 'src/dtos/server.dto'; import { VersionCheckMetadata } from 'src/entities/system-metadata.entity'; import { ImmichEnvironment, SystemMetadataKey } from 'src/enum'; -import { DatabaseLock } from 'src/interfaces/database.interface'; import { ArgOf } from 'src/interfaces/event.interface'; import { JobName, JobStatus, QueueName } from 'src/interfaces/job.interface'; +import { DatabaseLock } from 'src/repositories/database.repository'; import { BaseService } from 'src/services/base.service'; const asNotification = ({ checkedAt, releaseVersion }: VersionCheckMetadata): ReleaseNotification => { diff --git a/server/src/utils/asset.util.ts b/server/src/utils/asset.util.ts index 39593a77f3e23..703fe2c3d76c5 100644 --- a/server/src/utils/asset.util.ts +++ b/server/src/utils/asset.util.ts @@ -5,12 +5,12 @@ import { UploadFieldName } from 'src/dtos/asset-media.dto'; import { AuthDto } from 'src/dtos/auth.dto'; import { AssetFileEntity } from 'src/entities/asset-files.entity'; import { AssetFileType, AssetType, Permission } from 'src/enum'; -import { IAssetRepository } from 'src/interfaces/asset.interface'; import { IEventRepository } from 'src/interfaces/event.interface'; -import { IPartnerRepository } from 'src/interfaces/partner.interface'; import { AuthRequest } from 'src/middleware/auth.guard'; import { ImmichFile } from 'src/middleware/file-upload.interceptor'; import { AccessRepository } from 'src/repositories/access.repository'; +import { AssetRepository } from 'src/repositories/asset.repository'; +import { PartnerRepository } from 'src/repositories/partner.repository'; import { UploadFile } from 'src/services/asset-media.service'; import { checkAccess } from 'src/utils/access'; @@ -111,7 +111,7 @@ export const removeAssets = async ( export type PartnerIdOptions = { userId: string; - repository: IPartnerRepository; + repository: PartnerRepository; /** only include partners with `inTimeline: true` */ timelineEnabled?: boolean; }; @@ -139,7 +139,7 @@ export const getMyPartnerIds = async ({ userId, repository, timelineEnabled }: P return [...partnerIds]; }; -export type AssetHookRepositories = { asset: IAssetRepository; event: IEventRepository }; +export type AssetHookRepositories = { asset: AssetRepository; event: IEventRepository }; export const onBeforeLink = async ( { asset: assetRepository, event: eventRepository }: AssetHookRepositories, diff --git a/server/src/utils/config.ts b/server/src/utils/config.ts index 056064c026f93..30f965c37f3d6 100644 --- a/server/src/utils/config.ts +++ b/server/src/utils/config.ts @@ -6,8 +6,8 @@ import * as _ from 'lodash'; import { SystemConfig, defaults } from 'src/config'; import { SystemConfigDto } from 'src/dtos/system-config.dto'; import { SystemMetadataKey } from 'src/enum'; -import { DatabaseLock } from 'src/interfaces/database.interface'; import { ConfigRepository } from 'src/repositories/config.repository'; +import { DatabaseLock } from 'src/repositories/database.repository'; import { LoggingRepository } from 'src/repositories/logging.repository'; import { SystemMetadataRepository } from 'src/repositories/system-metadata.repository'; import { DeepPartial } from 'src/types'; diff --git a/server/src/utils/file.ts b/server/src/utils/file.ts index d9c599169dbb3..915c60de2a9c7 100644 --- a/server/src/utils/file.ts +++ b/server/src/utils/file.ts @@ -4,8 +4,8 @@ import { access, constants } from 'node:fs/promises'; import { basename, extname, isAbsolute } from 'node:path'; import { promisify } from 'node:util'; import { CacheControl } from 'src/enum'; -import { ImmichReadStream } from 'src/interfaces/storage.interface'; import { LoggingRepository } from 'src/repositories/logging.repository'; +import { ImmichReadStream } from 'src/repositories/storage.repository'; import { isConnectionAborted } from 'src/utils/misc'; export function getFileNameWithoutExtension(path: string): string { diff --git a/server/src/utils/tag.ts b/server/src/utils/tag.ts index 027afcf040195..4b3b360a8bfc2 100644 --- a/server/src/utils/tag.ts +++ b/server/src/utils/tag.ts @@ -1,8 +1,8 @@ import { TagEntity } from 'src/entities/tag.entity'; -import { ITagRepository } from 'src/interfaces/tag.interface'; +import { TagRepository } from 'src/repositories/tag.repository'; type UpsertRequest = { userId: string; tags: string[] }; -export const upsertTags = async (repository: ITagRepository, { userId, tags }: UpsertRequest) => { +export const upsertTags = async (repository: TagRepository, { userId, tags }: UpsertRequest) => { tags = [...new Set(tags)]; const results: TagEntity[] = []; diff --git a/server/test/repositories/album.repository.mock.ts b/server/test/repositories/album.repository.mock.ts index dd5c3af6a8d9a..7a1ae68a52e98 100644 --- a/server/test/repositories/album.repository.mock.ts +++ b/server/test/repositories/album.repository.mock.ts @@ -1,7 +1,8 @@ -import { IAlbumRepository } from 'src/interfaces/album.interface'; +import { AlbumRepository } from 'src/repositories/album.repository'; +import { RepositoryInterface } from 'src/types'; import { Mocked, vitest } from 'vitest'; -export const newAlbumRepositoryMock = (): Mocked => { +export const newAlbumRepositoryMock = (): Mocked> => { return { getById: vitest.fn(), getByAssetId: vitest.fn(), diff --git a/server/test/repositories/asset.repository.mock.ts b/server/test/repositories/asset.repository.mock.ts index 928a7956c5f0c..a2baed7cce0a0 100644 --- a/server/test/repositories/asset.repository.mock.ts +++ b/server/test/repositories/asset.repository.mock.ts @@ -1,7 +1,8 @@ -import { IAssetRepository } from 'src/interfaces/asset.interface'; +import { AssetRepository } from 'src/repositories/asset.repository'; +import { RepositoryInterface } from 'src/types'; import { Mocked, vitest } from 'vitest'; -export const newAssetRepositoryMock = (): Mocked => { +export const newAssetRepositoryMock = (): Mocked> => { return { create: vitest.fn(), upsertExif: vitest.fn(), diff --git a/server/test/repositories/config.repository.mock.ts b/server/test/repositories/config.repository.mock.ts index 800d40642bb20..7c5450c36e888 100644 --- a/server/test/repositories/config.repository.mock.ts +++ b/server/test/repositories/config.repository.mock.ts @@ -1,5 +1,4 @@ -import { ImmichEnvironment, ImmichWorker } from 'src/enum'; -import { DatabaseExtension } from 'src/interfaces/database.interface'; +import { DatabaseExtension, ImmichEnvironment, ImmichWorker } from 'src/enum'; import { ConfigRepository, EnvData } from 'src/repositories/config.repository'; import { RepositoryInterface } from 'src/types'; import { Mocked, vitest } from 'vitest'; diff --git a/server/test/repositories/crypto.repository.mock.ts b/server/test/repositories/crypto.repository.mock.ts index e0b6fa2bb8c6e..9d32a889870df 100644 --- a/server/test/repositories/crypto.repository.mock.ts +++ b/server/test/repositories/crypto.repository.mock.ts @@ -1,7 +1,8 @@ -import { ICryptoRepository } from 'src/interfaces/crypto.interface'; +import { CryptoRepository } from 'src/repositories/crypto.repository'; +import { RepositoryInterface } from 'src/types'; import { Mocked, vitest } from 'vitest'; -export const newCryptoRepositoryMock = (): Mocked => { +export const newCryptoRepositoryMock = (): Mocked> => { return { randomUUID: vitest.fn().mockReturnValue('random-uuid'), randomBytes: vitest.fn().mockReturnValue(Buffer.from('random-bytes', 'utf8')), diff --git a/server/test/repositories/database.repository.mock.ts b/server/test/repositories/database.repository.mock.ts index c135772518681..fe954c725b3de 100644 --- a/server/test/repositories/database.repository.mock.ts +++ b/server/test/repositories/database.repository.mock.ts @@ -1,7 +1,8 @@ -import { IDatabaseRepository } from 'src/interfaces/database.interface'; +import { DatabaseRepository } from 'src/repositories/database.repository'; +import { RepositoryInterface } from 'src/types'; import { Mocked, vitest } from 'vitest'; -export const newDatabaseRepositoryMock = (): Mocked => { +export const newDatabaseRepositoryMock = (): Mocked> => { return { init: vitest.fn(), shutdown: vitest.fn(), diff --git a/server/test/repositories/library.repository.mock.ts b/server/test/repositories/library.repository.mock.ts index 83e97c7ffaa9b..5db9e18d33a19 100644 --- a/server/test/repositories/library.repository.mock.ts +++ b/server/test/repositories/library.repository.mock.ts @@ -1,7 +1,8 @@ -import { ILibraryRepository } from 'src/interfaces/library.interface'; +import { LibraryRepository } from 'src/repositories/library.repository'; +import { RepositoryInterface } from 'src/types'; import { Mocked, vitest } from 'vitest'; -export const newLibraryRepositoryMock = (): Mocked => { +export const newLibraryRepositoryMock = (): Mocked> => { return { get: vitest.fn(), create: vitest.fn(), diff --git a/server/test/repositories/move.repository.mock.ts b/server/test/repositories/move.repository.mock.ts index 1f982a048ddb7..cf304b591e944 100644 --- a/server/test/repositories/move.repository.mock.ts +++ b/server/test/repositories/move.repository.mock.ts @@ -1,7 +1,8 @@ -import { IMoveRepository } from 'src/interfaces/move.interface'; +import { MoveRepository } from 'src/repositories/move.repository'; +import { RepositoryInterface } from 'src/types'; import { Mocked, vitest } from 'vitest'; -export const newMoveRepositoryMock = (): Mocked => { +export const newMoveRepositoryMock = (): Mocked> => { return { create: vitest.fn(), getByEntity: vitest.fn(), diff --git a/server/test/repositories/partner.repository.mock.ts b/server/test/repositories/partner.repository.mock.ts index ec1f141075b8b..6f9d4a36befcc 100644 --- a/server/test/repositories/partner.repository.mock.ts +++ b/server/test/repositories/partner.repository.mock.ts @@ -1,7 +1,8 @@ -import { IPartnerRepository } from 'src/interfaces/partner.interface'; +import { PartnerRepository } from 'src/repositories/partner.repository'; +import { RepositoryInterface } from 'src/types'; import { Mocked, vitest } from 'vitest'; -export const newPartnerRepositoryMock = (): Mocked => { +export const newPartnerRepositoryMock = (): Mocked> => { return { create: vitest.fn(), remove: vitest.fn(), diff --git a/server/test/repositories/person.repository.mock.ts b/server/test/repositories/person.repository.mock.ts index d7b92d3eab498..52240aafa2697 100644 --- a/server/test/repositories/person.repository.mock.ts +++ b/server/test/repositories/person.repository.mock.ts @@ -1,7 +1,8 @@ -import { IPersonRepository } from 'src/interfaces/person.interface'; +import { PersonRepository } from 'src/repositories/person.repository'; +import { RepositoryInterface } from 'src/types'; import { Mocked, vitest } from 'vitest'; -export const newPersonRepositoryMock = (): Mocked => { +export const newPersonRepositoryMock = (): Mocked> => { return { getById: vitest.fn(), getAll: vitest.fn(), diff --git a/server/test/repositories/search.repository.mock.ts b/server/test/repositories/search.repository.mock.ts index be0e753e30577..520bf23b3eb94 100644 --- a/server/test/repositories/search.repository.mock.ts +++ b/server/test/repositories/search.repository.mock.ts @@ -1,7 +1,8 @@ -import { ISearchRepository } from 'src/interfaces/search.interface'; +import { SearchRepository } from 'src/repositories/search.repository'; +import { RepositoryInterface } from 'src/types'; import { Mocked, vitest } from 'vitest'; -export const newSearchRepositoryMock = (): Mocked => { +export const newSearchRepositoryMock = (): Mocked> => { return { searchMetadata: vitest.fn(), searchSmart: vitest.fn(), diff --git a/server/test/repositories/shared-link.repository.mock.ts b/server/test/repositories/shared-link.repository.mock.ts index 251b38d5d7a22..66044b9eedc5d 100644 --- a/server/test/repositories/shared-link.repository.mock.ts +++ b/server/test/repositories/shared-link.repository.mock.ts @@ -1,7 +1,8 @@ -import { ISharedLinkRepository } from 'src/interfaces/shared-link.interface'; +import { SharedLinkRepository } from 'src/repositories/shared-link.repository'; +import { RepositoryInterface } from 'src/types'; import { Mocked, vitest } from 'vitest'; -export const newSharedLinkRepositoryMock = (): Mocked => { +export const newSharedLinkRepositoryMock = (): Mocked> => { return { getAll: vitest.fn(), get: vitest.fn(), diff --git a/server/test/repositories/stack.repository.mock.ts b/server/test/repositories/stack.repository.mock.ts index 35d1614de7dd8..74fef6f4b190b 100644 --- a/server/test/repositories/stack.repository.mock.ts +++ b/server/test/repositories/stack.repository.mock.ts @@ -1,7 +1,8 @@ -import { IStackRepository } from 'src/interfaces/stack.interface'; +import { StackRepository } from 'src/repositories/stack.repository'; +import { RepositoryInterface } from 'src/types'; import { Mocked, vitest } from 'vitest'; -export const newStackRepositoryMock = (): Mocked => { +export const newStackRepositoryMock = (): Mocked> => { return { search: vitest.fn(), create: vitest.fn(), diff --git a/server/test/repositories/storage.repository.mock.ts b/server/test/repositories/storage.repository.mock.ts index 0af16a8d1756f..984785d5106e0 100644 --- a/server/test/repositories/storage.repository.mock.ts +++ b/server/test/repositories/storage.repository.mock.ts @@ -1,6 +1,7 @@ import { WatchOptions } from 'chokidar'; import { StorageCore } from 'src/cores/storage.core'; -import { IStorageRepository, WatchEvents } from 'src/interfaces/storage.interface'; +import { StorageRepository, WatchEvents } from 'src/repositories/storage.repository'; +import { RepositoryInterface } from 'src/types'; import { Mocked, vitest } from 'vitest'; interface MockWatcherOptions { @@ -39,7 +40,7 @@ export const makeMockWatcher = return () => Promise.resolve(); }; -export const newStorageRepositoryMock = (reset = true): Mocked => { +export const newStorageRepositoryMock = (reset = true): Mocked> => { if (reset) { StorageCore.reset(); } diff --git a/server/test/repositories/tag.repository.mock.ts b/server/test/repositories/tag.repository.mock.ts index acc2b59f6d686..7f6f1b6c53d85 100644 --- a/server/test/repositories/tag.repository.mock.ts +++ b/server/test/repositories/tag.repository.mock.ts @@ -1,7 +1,8 @@ -import { ITagRepository } from 'src/interfaces/tag.interface'; +import { TagRepository } from 'src/repositories/tag.repository'; +import { RepositoryInterface } from 'src/types'; import { Mocked, vitest } from 'vitest'; -export const newTagRepositoryMock = (): Mocked => { +export const newTagRepositoryMock = (): Mocked> => { return { getAll: vitest.fn(), getByValue: vitest.fn(), diff --git a/server/test/repositories/user.repository.mock.ts b/server/test/repositories/user.repository.mock.ts index e6e8c38184ad8..d7ebee09d828e 100644 --- a/server/test/repositories/user.repository.mock.ts +++ b/server/test/repositories/user.repository.mock.ts @@ -1,7 +1,8 @@ -import { IUserRepository } from 'src/interfaces/user.interface'; +import { UserRepository } from 'src/repositories/user.repository'; +import { RepositoryInterface } from 'src/types'; import { Mocked, vitest } from 'vitest'; -export const newUserRepositoryMock = (): Mocked => { +export const newUserRepositoryMock = (): Mocked> => { return { get: vitest.fn(), getAdmin: vitest.fn(), diff --git a/server/test/utils.ts b/server/test/utils.ts index c4fee8fe93439..9816266a210f6 100644 --- a/server/test/utils.ts +++ b/server/test/utils.ts @@ -2,16 +2,14 @@ import { ChildProcessWithoutNullStreams } from 'node:child_process'; import { Writable } from 'node:stream'; import { PNG } from 'pngjs'; import { ImmichWorker } from 'src/enum'; -import { IAlbumRepository } from 'src/interfaces/album.interface'; -import { IAssetRepository } from 'src/interfaces/asset.interface'; -import { ICryptoRepository } from 'src/interfaces/crypto.interface'; import { IEventRepository } from 'src/interfaces/event.interface'; import { IMachineLearningRepository } from 'src/interfaces/machine-learning.interface'; -import { IUserRepository } from 'src/interfaces/user.interface'; import { AccessRepository } from 'src/repositories/access.repository'; import { ActivityRepository } from 'src/repositories/activity.repository'; import { AlbumUserRepository } from 'src/repositories/album-user.repository'; +import { AlbumRepository } from 'src/repositories/album.repository'; import { ApiKeyRepository } from 'src/repositories/api-key.repository'; +import { AssetRepository } from 'src/repositories/asset.repository'; import { AuditRepository } from 'src/repositories/audit.repository'; import { ConfigRepository } from 'src/repositories/config.repository'; import { CronRepository } from 'src/repositories/cron.repository'; @@ -40,6 +38,7 @@ import { SystemMetadataRepository } from 'src/repositories/system-metadata.repos import { TagRepository } from 'src/repositories/tag.repository'; import { TelemetryRepository } from 'src/repositories/telemetry.repository'; import { TrashRepository } from 'src/repositories/trash.repository'; +import { UserRepository } from 'src/repositories/user.repository'; import { VersionHistoryRepository } from 'src/repositories/version-history.repository'; import { ViewRepository } from 'src/repositories/view-repository'; import { BaseService } from 'src/services/base.service'; @@ -100,14 +99,14 @@ type IAccessRepository = { [K in keyof AccessRepository]: RepositoryInterface>; - album: Mocked; + album: Mocked>; albumUser: Mocked>; apiKey: Mocked>; audit: Mocked>; - asset: Mocked; + asset: Mocked>; config: Mocked>; cron: Mocked>; - crypto: Mocked; + crypto: Mocked>; database: Mocked>; event: Mocked; job: Mocked>; @@ -134,7 +133,7 @@ export type ServiceMocks = { tag: Mocked>; telemetry: ITelemetryRepositoryMock; trash: Mocked>; - user: Mocked; + user: Mocked>; versionHistory: Mocked>; view: Mocked>; }; @@ -192,39 +191,39 @@ export const newTestService = ( accessMock as IAccessRepository as AccessRepository, activityMock as RepositoryInterface as ActivityRepository, auditMock as RepositoryInterface as AuditRepository, - albumMock, + albumMock as RepositoryInterface as AlbumRepository, albumUserMock as RepositoryInterface as AlbumUserRepository, - assetMock, + assetMock as RepositoryInterface as AssetRepository, configMock, cronMock as RepositoryInterface as CronRepository, cryptoMock as RepositoryInterface as CryptoRepository, - databaseMock, + databaseMock as RepositoryInterface as DatabaseRepository, eventMock, jobMock, apiKeyMock as RepositoryInterface as ApiKeyRepository, - libraryMock, + libraryMock as RepositoryInterface as LibraryRepository, machineLearningMock, mapMock as RepositoryInterface as MapRepository, mediaMock as RepositoryInterface as MediaRepository, memoryMock as RepositoryInterface as MemoryRepository, metadataMock as RepositoryInterface as MetadataRepository, - moveMock, + moveMock as RepositoryInterface as MoveRepository, notificationMock as RepositoryInterface as NotificationRepository, oauthMock as RepositoryInterface as OAuthRepository, - partnerMock, - personMock, + partnerMock as RepositoryInterface as PartnerRepository, + personMock as RepositoryInterface as PersonRepository, processMock as RepositoryInterface as ProcessRepository, - searchMock, + searchMock as RepositoryInterface as SearchRepository, serverInfoMock as RepositoryInterface as ServerInfoRepository, sessionMock as RepositoryInterface as SessionRepository, - sharedLinkMock, - stackMock, - storageMock, + sharedLinkMock as RepositoryInterface as SharedLinkRepository, + stackMock as RepositoryInterface as StackRepository, + storageMock as RepositoryInterface as StorageRepository, systemMock as RepositoryInterface as SystemMetadataRepository, - tagMock, + tagMock as RepositoryInterface as TagRepository, telemetryMock as unknown as TelemetryRepository, trashMock as RepositoryInterface as TrashRepository, - userMock, + userMock as RepositoryInterface as UserRepository, versionHistoryMock as RepositoryInterface as VersionHistoryRepository, viewMock as RepositoryInterface as ViewRepository, ); From 5f3a42a13219d95fad6327931b76171253b30066 Mon Sep 17 00:00:00 2001 From: Jason Rasmussen Date: Tue, 11 Feb 2025 15:12:31 -0500 Subject: [PATCH 3/5] refactor: repositories (#16038) --- server/src/app.module.ts | 14 +- server/src/decorators.ts | 2 +- server/src/enum.ts | 7 + server/src/interfaces/event.interface.ts | 114 ----------------- .../interfaces/machine-learning.interface.ts | 57 --------- server/src/repositories/event.repository.ts | 121 +++++++++++++++--- server/src/repositories/index.ts | 10 +- server/src/repositories/job.repository.ts | 6 +- .../machine-learning.repository.ts | 63 +++++++-- server/src/services/backup.service.ts | 2 +- server/src/services/base.service.ts | 8 +- server/src/services/database.service.ts | 3 +- server/src/services/job.service.ts | 2 +- server/src/services/library.service.ts | 2 +- server/src/services/metadata.service.ts | 2 +- server/src/services/notification.service.ts | 2 +- server/src/services/person.service.spec.ts | 2 +- server/src/services/person.service.ts | 2 +- server/src/services/smart-info.service.ts | 2 +- .../src/services/storage-template.service.ts | 2 +- server/src/services/system-config.service.ts | 3 +- server/src/services/version.service.ts | 2 +- server/src/utils/asset.util.ts | 4 +- .../repositories/event.repository.mock.ts | 9 +- .../machine-learning.repository.mock.ts | 5 +- server/test/utils.ts | 12 +- 26 files changed, 216 insertions(+), 242 deletions(-) delete mode 100644 server/src/interfaces/event.interface.ts delete mode 100644 server/src/interfaces/machine-learning.interface.ts diff --git a/server/src/app.module.ts b/server/src/app.module.ts index 0096cc6c26761..2d6d7878dcd8a 100644 --- a/server/src/app.module.ts +++ b/server/src/app.module.ts @@ -13,7 +13,6 @@ import { IWorker } from 'src/constants'; import { controllers } from 'src/controllers'; import { entities } from 'src/entities'; import { ImmichWorker } from 'src/enum'; -import { IEventRepository } from 'src/interfaces/event.interface'; import { IJobRepository } from 'src/interfaces/job.interface'; import { AuthGuard } from 'src/middleware/auth.guard'; import { ErrorInterceptor } from 'src/middleware/error.interceptor'; @@ -22,9 +21,11 @@ import { GlobalExceptionFilter } from 'src/middleware/global-exception.filter'; import { LoggingInterceptor } from 'src/middleware/logging.interceptor'; import { providers, repositories } from 'src/repositories'; import { ConfigRepository } from 'src/repositories/config.repository'; +import { EventRepository } from 'src/repositories/event.repository'; import { LoggingRepository } from 'src/repositories/logging.repository'; import { teardownTelemetry, TelemetryRepository } from 'src/repositories/telemetry.repository'; import { services } from 'src/services'; +import { AuthService } from 'src/services/auth.service'; import { CliService } from 'src/services/cli.service'; import { DatabaseService } from 'src/services/database.service'; @@ -78,9 +79,10 @@ class BaseModule implements OnModuleInit, OnModuleDestroy { constructor( @Inject(IWorker) private worker: ImmichWorker, logger: LoggingRepository, - @Inject(IEventRepository) private eventRepository: IEventRepository, + private eventRepository: EventRepository, @Inject(IJobRepository) private jobRepository: IJobRepository, private telemetryRepository: TelemetryRepository, + private authService: AuthService, ) { logger.setAppName(this.worker); } @@ -93,6 +95,14 @@ class BaseModule implements OnModuleInit, OnModuleDestroy { this.jobRepository.startWorkers(); } + this.eventRepository.setAuthFn(async (client) => + this.authService.authenticate({ + headers: client.request.headers, + queryParams: {}, + metadata: { adminRoute: false, sharedLinkRoute: false, uri: '/api/socket.io' }, + }), + ); + this.eventRepository.setup({ services }); await this.eventRepository.emit('app.bootstrap'); } diff --git a/server/src/decorators.ts b/server/src/decorators.ts index bb037ee097a80..7aab2e248aca1 100644 --- a/server/src/decorators.ts +++ b/server/src/decorators.ts @@ -3,8 +3,8 @@ import { ApiExtension, ApiOperation, ApiProperty, ApiTags } from '@nestjs/swagge import _ from 'lodash'; import { ADDED_IN_PREFIX, DEPRECATED_IN_PREFIX, LIFECYCLE_EXTENSION } from 'src/constants'; import { ImmichWorker, MetadataKey } from 'src/enum'; -import { EmitEvent } from 'src/interfaces/event.interface'; import { JobName, QueueName } from 'src/interfaces/job.interface'; +import { EmitEvent } from 'src/repositories/event.repository'; import { setUnion } from 'src/utils/set'; // PostgreSQL uses a 16-bit integer to indicate the number of bound parameters. This means that the diff --git a/server/src/enum.ts b/server/src/enum.ts index 332ae50ee8d0e..b887fbace3bb3 100644 --- a/server/src/enum.ts +++ b/server/src/enum.ts @@ -391,3 +391,10 @@ export enum DatabaseExtension { VECTOR = 'vector', VECTORS = 'vectors', } + +export enum BootstrapEventPriority { + // Database service should be initialized before anything else, most other services need database access + DatabaseService = -200, + // Initialise config after other bootstrap services, stop other services from using config on bootstrap + SystemConfig = 100, +} diff --git a/server/src/interfaces/event.interface.ts b/server/src/interfaces/event.interface.ts deleted file mode 100644 index 9a9e23cca0018..0000000000000 --- a/server/src/interfaces/event.interface.ts +++ /dev/null @@ -1,114 +0,0 @@ -import { ClassConstructor } from 'class-transformer'; -import { SystemConfig } from 'src/config'; -import { AssetResponseDto } from 'src/dtos/asset-response.dto'; -import { ReleaseNotification, ServerVersionResponseDto } from 'src/dtos/server.dto'; -import { JobItem, QueueName } from 'src/interfaces/job.interface'; - -export const IEventRepository = 'IEventRepository'; - -type EventMap = { - // app events - 'app.bootstrap': []; - 'app.shutdown': []; - - 'config.init': [{ newConfig: SystemConfig }]; - // config events - 'config.update': [ - { - newConfig: SystemConfig; - oldConfig: SystemConfig; - }, - ]; - 'config.validate': [{ newConfig: SystemConfig; oldConfig: SystemConfig }]; - - // album events - 'album.update': [{ id: string; recipientIds: string[] }]; - 'album.invite': [{ id: string; userId: string }]; - - // asset events - 'asset.tag': [{ assetId: string }]; - 'asset.untag': [{ assetId: string }]; - 'asset.hide': [{ assetId: string; userId: string }]; - 'asset.show': [{ assetId: string; userId: string }]; - 'asset.trash': [{ assetId: string; userId: string }]; - 'asset.delete': [{ assetId: string; userId: string }]; - - // asset bulk events - 'assets.trash': [{ assetIds: string[]; userId: string }]; - 'assets.delete': [{ assetIds: string[]; userId: string }]; - 'assets.restore': [{ assetIds: string[]; userId: string }]; - - 'job.start': [QueueName, JobItem]; - - // session events - 'session.delete': [{ sessionId: string }]; - - // stack events - 'stack.create': [{ stackId: string; userId: string }]; - 'stack.update': [{ stackId: string; userId: string }]; - 'stack.delete': [{ stackId: string; userId: string }]; - - // stack bulk events - 'stacks.delete': [{ stackIds: string[]; userId: string }]; - - // user events - 'user.signup': [{ notify: boolean; id: string; tempPassword?: string }]; - - // websocket events - 'websocket.connect': [{ userId: string }]; -}; - -export const serverEvents = ['config.update'] as const; -export type ServerEvents = (typeof serverEvents)[number]; - -export type EmitEvent = keyof EventMap; -export type EmitHandler = (...args: ArgsOf) => Promise | void; -export type ArgOf = EventMap[T][0]; -export type ArgsOf = EventMap[T]; - -export interface ClientEventMap { - on_upload_success: [AssetResponseDto]; - on_user_delete: [string]; - on_asset_delete: [string]; - on_asset_trash: [string[]]; - on_asset_update: [AssetResponseDto]; - on_asset_hidden: [string]; - on_asset_restore: [string[]]; - on_asset_stack_update: string[]; - on_person_thumbnail: [string]; - on_server_version: [ServerVersionResponseDto]; - on_config_update: []; - on_new_release: [ReleaseNotification]; - on_session_delete: [string]; -} - -export type EventItem = { - event: T; - handler: EmitHandler; - server: boolean; -}; - -export enum BootstrapEventPriority { - // Database service should be initialized before anything else, most other services need database access - DatabaseService = -200, - // Initialise config after other bootstrap services, stop other services from using config on bootstrap - SystemConfig = 100, -} - -export interface IEventRepository { - setup(options: { services: ClassConstructor[] }): void; - emit(event: T, ...args: ArgsOf): Promise; - - /** - * Send to connected clients for a specific user - */ - clientSend(event: E, room: string, ...data: ClientEventMap[E]): void; - /** - * Send to all connected clients - */ - clientBroadcast(event: E, ...data: ClientEventMap[E]): void; - /** - * Send to all connected servers - */ - serverSend(event: T, ...args: ArgsOf): void; -} diff --git a/server/src/interfaces/machine-learning.interface.ts b/server/src/interfaces/machine-learning.interface.ts deleted file mode 100644 index 934091ef8e3ff..0000000000000 --- a/server/src/interfaces/machine-learning.interface.ts +++ /dev/null @@ -1,57 +0,0 @@ -export const IMachineLearningRepository = 'IMachineLearningRepository'; - -export interface BoundingBox { - x1: number; - y1: number; - x2: number; - y2: number; -} - -export enum ModelTask { - FACIAL_RECOGNITION = 'facial-recognition', - SEARCH = 'clip', -} - -export enum ModelType { - DETECTION = 'detection', - PIPELINE = 'pipeline', - RECOGNITION = 'recognition', - TEXTUAL = 'textual', - VISUAL = 'visual', -} - -export type ModelPayload = { imagePath: string } | { text: string }; - -type ModelOptions = { modelName: string }; - -export type FaceDetectionOptions = ModelOptions & { minScore: number }; - -type VisualResponse = { imageHeight: number; imageWidth: number }; -export type ClipVisualRequest = { [ModelTask.SEARCH]: { [ModelType.VISUAL]: ModelOptions } }; -export type ClipVisualResponse = { [ModelTask.SEARCH]: string } & VisualResponse; - -export type ClipTextualRequest = { [ModelTask.SEARCH]: { [ModelType.TEXTUAL]: ModelOptions } }; -export type ClipTextualResponse = { [ModelTask.SEARCH]: string }; - -export type FacialRecognitionRequest = { - [ModelTask.FACIAL_RECOGNITION]: { - [ModelType.DETECTION]: ModelOptions & { options: { minScore: number } }; - [ModelType.RECOGNITION]: ModelOptions; - }; -}; - -export interface Face { - boundingBox: BoundingBox; - embedding: string; - score: number; -} - -export type FacialRecognitionResponse = { [ModelTask.FACIAL_RECOGNITION]: Face[] } & VisualResponse; -export type DetectedFaces = { faces: Face[] } & VisualResponse; -export type MachineLearningRequest = ClipVisualRequest | ClipTextualRequest | FacialRecognitionRequest; - -export interface IMachineLearningRepository { - encodeImage(urls: string[], imagePath: string, config: ModelOptions): Promise; - encodeText(urls: string[], text: string, config: ModelOptions): Promise; - detectFaces(urls: string[], imagePath: string, config: FaceDetectionOptions): Promise; -} diff --git a/server/src/repositories/event.repository.ts b/server/src/repositories/event.repository.ts index a443e0ed83d47..671b86f99c680 100644 --- a/server/src/repositories/event.repository.ts +++ b/server/src/repositories/event.repository.ts @@ -10,21 +10,15 @@ import { import { ClassConstructor } from 'class-transformer'; import _ from 'lodash'; import { Server, Socket } from 'socket.io'; +import { SystemConfig } from 'src/config'; import { EventConfig } from 'src/decorators'; +import { AssetResponseDto } from 'src/dtos/asset-response.dto'; +import { AuthDto } from 'src/dtos/auth.dto'; +import { ReleaseNotification, ServerVersionResponseDto } from 'src/dtos/server.dto'; import { ImmichWorker, MetadataKey } from 'src/enum'; -import { - ArgsOf, - ClientEventMap, - EmitEvent, - EmitHandler, - EventItem, - IEventRepository, - serverEvents, - ServerEvents, -} from 'src/interfaces/event.interface'; +import { JobItem, QueueName } from 'src/interfaces/job.interface'; import { ConfigRepository } from 'src/repositories/config.repository'; import { LoggingRepository } from 'src/repositories/logging.repository'; -import { AuthService } from 'src/services/auth.service'; import { handlePromiseError } from 'src/utils/misc'; type EmitHandlers = Partial<{ [T in EmitEvent]: Array> }>; @@ -37,14 +31,99 @@ type Item = { label: string; }; +type EventMap = { + // app events + 'app.bootstrap': []; + 'app.shutdown': []; + + 'config.init': [{ newConfig: SystemConfig }]; + // config events + 'config.update': [ + { + newConfig: SystemConfig; + oldConfig: SystemConfig; + }, + ]; + 'config.validate': [{ newConfig: SystemConfig; oldConfig: SystemConfig }]; + + // album events + 'album.update': [{ id: string; recipientIds: string[] }]; + 'album.invite': [{ id: string; userId: string }]; + + // asset events + 'asset.tag': [{ assetId: string }]; + 'asset.untag': [{ assetId: string }]; + 'asset.hide': [{ assetId: string; userId: string }]; + 'asset.show': [{ assetId: string; userId: string }]; + 'asset.trash': [{ assetId: string; userId: string }]; + 'asset.delete': [{ assetId: string; userId: string }]; + + // asset bulk events + 'assets.trash': [{ assetIds: string[]; userId: string }]; + 'assets.delete': [{ assetIds: string[]; userId: string }]; + 'assets.restore': [{ assetIds: string[]; userId: string }]; + + 'job.start': [QueueName, JobItem]; + + // session events + 'session.delete': [{ sessionId: string }]; + + // stack events + 'stack.create': [{ stackId: string; userId: string }]; + 'stack.update': [{ stackId: string; userId: string }]; + 'stack.delete': [{ stackId: string; userId: string }]; + + // stack bulk events + 'stacks.delete': [{ stackIds: string[]; userId: string }]; + + // user events + 'user.signup': [{ notify: boolean; id: string; tempPassword?: string }]; + + // websocket events + 'websocket.connect': [{ userId: string }]; +}; + +export const serverEvents = ['config.update'] as const; +export type ServerEvents = (typeof serverEvents)[number]; + +export type EmitEvent = keyof EventMap; +export type EmitHandler = (...args: ArgsOf) => Promise | void; +export type ArgOf = EventMap[T][0]; +export type ArgsOf = EventMap[T]; + +export interface ClientEventMap { + on_upload_success: [AssetResponseDto]; + on_user_delete: [string]; + on_asset_delete: [string]; + on_asset_trash: [string[]]; + on_asset_update: [AssetResponseDto]; + on_asset_hidden: [string]; + on_asset_restore: [string[]]; + on_asset_stack_update: string[]; + on_person_thumbnail: [string]; + on_server_version: [ServerVersionResponseDto]; + on_config_update: []; + on_new_release: [ReleaseNotification]; + on_session_delete: [string]; +} + +export type EventItem = { + event: T; + handler: EmitHandler; + server: boolean; +}; + +export type AuthFn = (client: Socket) => Promise; + @WebSocketGateway({ cors: true, path: '/api/socket.io', transports: ['websocket'], }) @Injectable() -export class EventRepository implements OnGatewayConnection, OnGatewayDisconnect, OnGatewayInit, IEventRepository { +export class EventRepository implements OnGatewayConnection, OnGatewayDisconnect, OnGatewayInit { private emitHandlers: EmitHandlers = {}; + private authFn?: AuthFn; @WebSocketServer() private server?: Server; @@ -122,11 +201,7 @@ export class EventRepository implements OnGatewayConnection, OnGatewayDisconnect async handleConnection(client: Socket) { try { this.logger.log(`Websocket Connect: ${client.id}`); - const auth = await this.moduleRef.get(AuthService).authenticate({ - headers: client.request.headers, - queryParams: {}, - metadata: { adminRoute: false, sharedLinkRoute: false, uri: '/api/socket.io' }, - }); + const auth = await this.authenticate(client); await client.join(auth.user.id); if (auth.session) { await client.join(auth.session.id); @@ -182,4 +257,16 @@ export class EventRepository implements OnGatewayConnection, OnGatewayDisconnect this.logger.debug(`Server event: ${event} (send)`); this.server?.serverSideEmit(event, ...args); } + + setAuthFn(fn: (client: Socket) => Promise) { + this.authFn = fn; + } + + private async authenticate(client: Socket) { + if (!this.authFn) { + throw new Error('Auth function not set'); + } + + return this.authFn(client); + } } diff --git a/server/src/repositories/index.ts b/server/src/repositories/index.ts index d9ef84fc06a7d..3c96f4c89127e 100644 --- a/server/src/repositories/index.ts +++ b/server/src/repositories/index.ts @@ -1,6 +1,4 @@ -import { IEventRepository } from 'src/interfaces/event.interface'; import { IJobRepository } from 'src/interfaces/job.interface'; -import { IMachineLearningRepository } from 'src/interfaces/machine-learning.interface'; import { AccessRepository } from 'src/repositories/access.repository'; import { ActivityRepository } from 'src/repositories/activity.repository'; import { AlbumUserRepository } from 'src/repositories/album-user.repository'; @@ -53,8 +51,10 @@ export const repositories = [ CronRepository, CryptoRepository, DatabaseRepository, + EventRepository, LibraryRepository, LoggingRepository, + MachineLearningRepository, MapRepository, MediaRepository, MemoryRepository, @@ -80,8 +80,4 @@ export const repositories = [ VersionHistoryRepository, ]; -export const providers = [ - { provide: IEventRepository, useClass: EventRepository }, - { provide: IJobRepository, useClass: JobRepository }, - { provide: IMachineLearningRepository, useClass: MachineLearningRepository }, -]; +export const providers = [{ provide: IJobRepository, useClass: JobRepository }]; diff --git a/server/src/repositories/job.repository.ts b/server/src/repositories/job.repository.ts index 9a5bf20df6143..d6693f67f3256 100644 --- a/server/src/repositories/job.repository.ts +++ b/server/src/repositories/job.repository.ts @@ -1,12 +1,11 @@ import { getQueueToken } from '@nestjs/bullmq'; -import { Inject, Injectable } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import { ModuleRef, Reflector } from '@nestjs/core'; import { JobsOptions, Queue, Worker } from 'bullmq'; import { ClassConstructor } from 'class-transformer'; import { setTimeout } from 'node:timers/promises'; import { JobConfig } from 'src/decorators'; import { MetadataKey } from 'src/enum'; -import { IEventRepository } from 'src/interfaces/event.interface'; import { IEntityJob, IJobRepository, @@ -20,6 +19,7 @@ import { QueueStatus, } from 'src/interfaces/job.interface'; import { ConfigRepository } from 'src/repositories/config.repository'; +import { EventRepository } from 'src/repositories/event.repository'; import { LoggingRepository } from 'src/repositories/logging.repository'; import { getKeyByValue, getMethodNames, ImmichStartupError } from 'src/utils/misc'; @@ -38,7 +38,7 @@ export class JobRepository implements IJobRepository { constructor( private moduleRef: ModuleRef, private configRepository: ConfigRepository, - @Inject(IEventRepository) private eventRepository: IEventRepository, + private eventRepository: EventRepository, private logger: LoggingRepository, ) { this.logger.setContext(JobRepository.name); diff --git a/server/src/repositories/machine-learning.repository.ts b/server/src/repositories/machine-learning.repository.ts index 6266314bfd8ab..8145bf315464e 100644 --- a/server/src/repositories/machine-learning.repository.ts +++ b/server/src/repositories/machine-learning.repository.ts @@ -1,21 +1,60 @@ import { Injectable } from '@nestjs/common'; import { readFile } from 'node:fs/promises'; import { CLIPConfig } from 'src/dtos/model-config.dto'; -import { - ClipTextualResponse, - ClipVisualResponse, - FaceDetectionOptions, - FacialRecognitionResponse, - IMachineLearningRepository, - MachineLearningRequest, - ModelPayload, - ModelTask, - ModelType, -} from 'src/interfaces/machine-learning.interface'; import { LoggingRepository } from 'src/repositories/logging.repository'; +export interface BoundingBox { + x1: number; + y1: number; + x2: number; + y2: number; +} + +export enum ModelTask { + FACIAL_RECOGNITION = 'facial-recognition', + SEARCH = 'clip', +} + +export enum ModelType { + DETECTION = 'detection', + PIPELINE = 'pipeline', + RECOGNITION = 'recognition', + TEXTUAL = 'textual', + VISUAL = 'visual', +} + +export type ModelPayload = { imagePath: string } | { text: string }; + +type ModelOptions = { modelName: string }; + +export type FaceDetectionOptions = ModelOptions & { minScore: number }; + +type VisualResponse = { imageHeight: number; imageWidth: number }; +export type ClipVisualRequest = { [ModelTask.SEARCH]: { [ModelType.VISUAL]: ModelOptions } }; +export type ClipVisualResponse = { [ModelTask.SEARCH]: string } & VisualResponse; + +export type ClipTextualRequest = { [ModelTask.SEARCH]: { [ModelType.TEXTUAL]: ModelOptions } }; +export type ClipTextualResponse = { [ModelTask.SEARCH]: string }; + +export type FacialRecognitionRequest = { + [ModelTask.FACIAL_RECOGNITION]: { + [ModelType.DETECTION]: ModelOptions & { options: { minScore: number } }; + [ModelType.RECOGNITION]: ModelOptions; + }; +}; + +export interface Face { + boundingBox: BoundingBox; + embedding: string; + score: number; +} + +export type FacialRecognitionResponse = { [ModelTask.FACIAL_RECOGNITION]: Face[] } & VisualResponse; +export type DetectedFaces = { faces: Face[] } & VisualResponse; +export type MachineLearningRequest = ClipVisualRequest | ClipTextualRequest | FacialRecognitionRequest; + @Injectable() -export class MachineLearningRepository implements IMachineLearningRepository { +export class MachineLearningRepository { constructor(private logger: LoggingRepository) { this.logger.setContext(MachineLearningRepository.name); } diff --git a/server/src/services/backup.service.ts b/server/src/services/backup.service.ts index d0a8ce69b674a..dee8113792f5a 100644 --- a/server/src/services/backup.service.ts +++ b/server/src/services/backup.service.ts @@ -4,9 +4,9 @@ import semver from 'semver'; import { StorageCore } from 'src/cores/storage.core'; import { OnEvent, OnJob } from 'src/decorators'; import { ImmichWorker, StorageFolder } from 'src/enum'; -import { ArgOf } from 'src/interfaces/event.interface'; import { JobName, JobStatus, QueueName } from 'src/interfaces/job.interface'; import { DatabaseLock } from 'src/repositories/database.repository'; +import { ArgOf } from 'src/repositories/event.repository'; import { BaseService } from 'src/services/base.service'; import { handlePromiseError } from 'src/utils/misc'; diff --git a/server/src/services/base.service.ts b/server/src/services/base.service.ts index d0f00bd2ab367..259248e49b6f9 100644 --- a/server/src/services/base.service.ts +++ b/server/src/services/base.service.ts @@ -6,9 +6,7 @@ import { SALT_ROUNDS } from 'src/constants'; import { StorageCore } from 'src/cores/storage.core'; import { Users } from 'src/db'; import { UserEntity } from 'src/entities/user.entity'; -import { IEventRepository } from 'src/interfaces/event.interface'; import { IJobRepository } from 'src/interfaces/job.interface'; -import { IMachineLearningRepository } from 'src/interfaces/machine-learning.interface'; import { AccessRepository } from 'src/repositories/access.repository'; import { ActivityRepository } from 'src/repositories/activity.repository'; import { AlbumUserRepository } from 'src/repositories/album-user.repository'; @@ -20,8 +18,10 @@ import { ConfigRepository } from 'src/repositories/config.repository'; import { CronRepository } from 'src/repositories/cron.repository'; import { CryptoRepository } from 'src/repositories/crypto.repository'; import { DatabaseRepository } from 'src/repositories/database.repository'; +import { EventRepository } from 'src/repositories/event.repository'; import { LibraryRepository } from 'src/repositories/library.repository'; import { LoggingRepository } from 'src/repositories/logging.repository'; +import { MachineLearningRepository } from 'src/repositories/machine-learning.repository'; import { MapRepository } from 'src/repositories/map.repository'; import { MediaRepository } from 'src/repositories/media.repository'; import { MemoryRepository } from 'src/repositories/memory.repository'; @@ -63,11 +63,11 @@ export class BaseService { protected cronRepository: CronRepository, protected cryptoRepository: CryptoRepository, protected databaseRepository: DatabaseRepository, - @Inject(IEventRepository) protected eventRepository: IEventRepository, + protected eventRepository: EventRepository, @Inject(IJobRepository) protected jobRepository: IJobRepository, protected keyRepository: ApiKeyRepository, protected libraryRepository: LibraryRepository, - @Inject(IMachineLearningRepository) protected machineLearningRepository: IMachineLearningRepository, + protected machineLearningRepository: MachineLearningRepository, protected mapRepository: MapRepository, protected mediaRepository: MediaRepository, protected memoryRepository: MemoryRepository, diff --git a/server/src/services/database.service.ts b/server/src/services/database.service.ts index eabb0b0091c8f..249b47c99cffb 100644 --- a/server/src/services/database.service.ts +++ b/server/src/services/database.service.ts @@ -2,8 +2,7 @@ import { Injectable } from '@nestjs/common'; import { Duration } from 'luxon'; import semver from 'semver'; import { OnEvent } from 'src/decorators'; -import { DatabaseExtension } from 'src/enum'; -import { BootstrapEventPriority } from 'src/interfaces/event.interface'; +import { BootstrapEventPriority, DatabaseExtension } from 'src/enum'; import { DatabaseLock, EXTENSION_NAMES, VectorExtension, VectorIndex } from 'src/repositories/database.repository'; import { BaseService } from 'src/services/base.service'; diff --git a/server/src/services/job.service.ts b/server/src/services/job.service.ts index c8ac8fc6bfb46..00d9a398fdc9c 100644 --- a/server/src/services/job.service.ts +++ b/server/src/services/job.service.ts @@ -4,7 +4,6 @@ import { OnEvent } from 'src/decorators'; import { mapAsset } from 'src/dtos/asset-response.dto'; import { AllJobStatusResponseDto, JobCommandDto, JobCreateDto, JobStatusDto } from 'src/dtos/job.dto'; import { AssetType, ImmichWorker, ManualJobName } from 'src/enum'; -import { ArgOf, ArgsOf } from 'src/interfaces/event.interface'; import { ConcurrentQueueName, JobCommand, @@ -14,6 +13,7 @@ import { QueueCleanType, QueueName, } from 'src/interfaces/job.interface'; +import { ArgOf, ArgsOf } from 'src/repositories/event.repository'; import { BaseService } from 'src/services/base.service'; const asJobItem = (dto: JobCreateDto): JobItem => { diff --git a/server/src/services/library.service.ts b/server/src/services/library.service.ts index 5235b786e916d..fb748276565c6 100644 --- a/server/src/services/library.service.ts +++ b/server/src/services/library.service.ts @@ -17,9 +17,9 @@ import { import { AssetEntity } from 'src/entities/asset.entity'; import { LibraryEntity } from 'src/entities/library.entity'; import { AssetType, ImmichWorker } from 'src/enum'; -import { ArgOf } from 'src/interfaces/event.interface'; import { JobName, JobOf, JOBS_LIBRARY_PAGINATION_SIZE, JobStatus, QueueName } from 'src/interfaces/job.interface'; import { DatabaseLock } from 'src/repositories/database.repository'; +import { ArgOf } from 'src/repositories/event.repository'; import { BaseService } from 'src/services/base.service'; import { mimeTypes } from 'src/utils/mime-types'; import { handlePromiseError } from 'src/utils/misc'; diff --git a/server/src/services/metadata.service.ts b/server/src/services/metadata.service.ts index 53110a20e0160..33db5d3149450 100644 --- a/server/src/services/metadata.service.ts +++ b/server/src/services/metadata.service.ts @@ -14,10 +14,10 @@ import { AssetFaceEntity } from 'src/entities/asset-face.entity'; import { AssetEntity } from 'src/entities/asset.entity'; import { PersonEntity } from 'src/entities/person.entity'; import { AssetType, ExifOrientation, ImmichWorker, SourceType } from 'src/enum'; -import { ArgOf } from 'src/interfaces/event.interface'; import { JobName, JobOf, JOBS_ASSET_PAGINATION_SIZE, JobStatus, QueueName } from 'src/interfaces/job.interface'; import { WithoutProperty } from 'src/repositories/asset.repository'; import { DatabaseLock } from 'src/repositories/database.repository'; +import { ArgOf } from 'src/repositories/event.repository'; import { ReverseGeocodeResult } from 'src/repositories/map.repository'; import { ImmichTags } from 'src/repositories/metadata.repository'; import { BaseService } from 'src/services/base.service'; diff --git a/server/src/services/notification.service.ts b/server/src/services/notification.service.ts index 85f72443d4baa..f9a2194088651 100644 --- a/server/src/services/notification.service.ts +++ b/server/src/services/notification.service.ts @@ -2,7 +2,6 @@ import { BadRequestException, Injectable } from '@nestjs/common'; import { OnEvent, OnJob } from 'src/decorators'; import { SystemConfigSmtpDto } from 'src/dtos/system-config.dto'; import { AlbumEntity } from 'src/entities/album.entity'; -import { ArgOf } from 'src/interfaces/event.interface'; import { IEntityJob, INotifyAlbumUpdateJob, @@ -12,6 +11,7 @@ import { JobStatus, QueueName, } from 'src/interfaces/job.interface'; +import { ArgOf } from 'src/repositories/event.repository'; import { EmailImageAttachment, EmailTemplate } from 'src/repositories/notification.repository'; import { BaseService } from 'src/services/base.service'; import { getAssetFiles } from 'src/utils/asset.util'; diff --git a/server/src/services/person.service.spec.ts b/server/src/services/person.service.spec.ts index ec2417c793b58..8e1cff302fdc9 100644 --- a/server/src/services/person.service.spec.ts +++ b/server/src/services/person.service.spec.ts @@ -4,8 +4,8 @@ import { mapFaces, mapPerson, PersonResponseDto } from 'src/dtos/person.dto'; import { AssetFaceEntity } from 'src/entities/asset-face.entity'; import { CacheControl, Colorspace, ImageFormat, SourceType, SystemMetadataKey } from 'src/enum'; import { JobName, JobStatus } from 'src/interfaces/job.interface'; -import { DetectedFaces } from 'src/interfaces/machine-learning.interface'; import { WithoutProperty } from 'src/repositories/asset.repository'; +import { DetectedFaces } from 'src/repositories/machine-learning.repository'; import { FaceSearchResult } from 'src/repositories/search.repository'; import { PersonService } from 'src/services/person.service'; import { ImmichFileResponse } from 'src/utils/file'; diff --git a/server/src/services/person.service.ts b/server/src/services/person.service.ts index 2ae703afb3770..e9933b421cb16 100644 --- a/server/src/services/person.service.ts +++ b/server/src/services/person.service.ts @@ -40,8 +40,8 @@ import { JobStatus, QueueName, } from 'src/interfaces/job.interface'; -import { BoundingBox } from 'src/interfaces/machine-learning.interface'; import { WithoutProperty } from 'src/repositories/asset.repository'; +import { BoundingBox } from 'src/repositories/machine-learning.repository'; import { UpdateFacesData } from 'src/repositories/person.repository'; import { BaseService } from 'src/services/base.service'; import { CropOptions, ImageDimensions, InputDimensions } from 'src/types'; diff --git a/server/src/services/smart-info.service.ts b/server/src/services/smart-info.service.ts index ebf9e1d28794b..0a03c27a55949 100644 --- a/server/src/services/smart-info.service.ts +++ b/server/src/services/smart-info.service.ts @@ -2,10 +2,10 @@ import { Injectable } from '@nestjs/common'; import { SystemConfig } from 'src/config'; import { OnEvent, OnJob } from 'src/decorators'; import { ImmichWorker } from 'src/enum'; -import { ArgOf } from 'src/interfaces/event.interface'; import { JOBS_ASSET_PAGINATION_SIZE, JobName, JobOf, JobStatus, QueueName } from 'src/interfaces/job.interface'; import { WithoutProperty } from 'src/repositories/asset.repository'; import { DatabaseLock } from 'src/repositories/database.repository'; +import { ArgOf } from 'src/repositories/event.repository'; import { BaseService } from 'src/services/base.service'; import { getAssetFiles } from 'src/utils/asset.util'; import { getCLIPModelInfo, isSmartSearchEnabled } from 'src/utils/misc'; diff --git a/server/src/services/storage-template.service.ts b/server/src/services/storage-template.service.ts index 6b0409de1de95..6fd139c10d1e4 100644 --- a/server/src/services/storage-template.service.ts +++ b/server/src/services/storage-template.service.ts @@ -8,9 +8,9 @@ import { OnEvent, OnJob } from 'src/decorators'; import { SystemConfigTemplateStorageOptionDto } from 'src/dtos/system-config.dto'; import { AssetEntity } from 'src/entities/asset.entity'; import { AssetPathType, AssetType, StorageFolder } from 'src/enum'; -import { ArgOf } from 'src/interfaces/event.interface'; import { JobName, JobOf, JOBS_ASSET_PAGINATION_SIZE, JobStatus, QueueName } from 'src/interfaces/job.interface'; import { DatabaseLock } from 'src/repositories/database.repository'; +import { ArgOf } from 'src/repositories/event.repository'; import { BaseService } from 'src/services/base.service'; import { getLivePhotoMotionFilename } from 'src/utils/file'; import { usePagination } from 'src/utils/pagination'; diff --git a/server/src/services/system-config.service.ts b/server/src/services/system-config.service.ts index b5ae42e0989d1..cc32ef0c341d6 100644 --- a/server/src/services/system-config.service.ts +++ b/server/src/services/system-config.service.ts @@ -4,7 +4,8 @@ import _ from 'lodash'; import { defaults } from 'src/config'; import { OnEvent } from 'src/decorators'; import { SystemConfigDto, mapConfig } from 'src/dtos/system-config.dto'; -import { ArgOf, BootstrapEventPriority } from 'src/interfaces/event.interface'; +import { BootstrapEventPriority } from 'src/enum'; +import { ArgOf } from 'src/repositories/event.repository'; import { BaseService } from 'src/services/base.service'; import { clearConfigCache } from 'src/utils/config'; import { toPlainObject } from 'src/utils/object'; diff --git a/server/src/services/version.service.ts b/server/src/services/version.service.ts index ee36d30041844..9679ac4b4b6c0 100644 --- a/server/src/services/version.service.ts +++ b/server/src/services/version.service.ts @@ -6,9 +6,9 @@ import { OnEvent, OnJob } from 'src/decorators'; import { ReleaseNotification, ServerVersionResponseDto } from 'src/dtos/server.dto'; import { VersionCheckMetadata } from 'src/entities/system-metadata.entity'; import { ImmichEnvironment, SystemMetadataKey } from 'src/enum'; -import { ArgOf } from 'src/interfaces/event.interface'; import { JobName, JobStatus, QueueName } from 'src/interfaces/job.interface'; import { DatabaseLock } from 'src/repositories/database.repository'; +import { ArgOf } from 'src/repositories/event.repository'; import { BaseService } from 'src/services/base.service'; const asNotification = ({ checkedAt, releaseVersion }: VersionCheckMetadata): ReleaseNotification => { diff --git a/server/src/utils/asset.util.ts b/server/src/utils/asset.util.ts index 703fe2c3d76c5..5183bb2164e50 100644 --- a/server/src/utils/asset.util.ts +++ b/server/src/utils/asset.util.ts @@ -5,11 +5,11 @@ import { UploadFieldName } from 'src/dtos/asset-media.dto'; import { AuthDto } from 'src/dtos/auth.dto'; import { AssetFileEntity } from 'src/entities/asset-files.entity'; import { AssetFileType, AssetType, Permission } from 'src/enum'; -import { IEventRepository } from 'src/interfaces/event.interface'; import { AuthRequest } from 'src/middleware/auth.guard'; import { ImmichFile } from 'src/middleware/file-upload.interceptor'; import { AccessRepository } from 'src/repositories/access.repository'; import { AssetRepository } from 'src/repositories/asset.repository'; +import { EventRepository } from 'src/repositories/event.repository'; import { PartnerRepository } from 'src/repositories/partner.repository'; import { UploadFile } from 'src/services/asset-media.service'; import { checkAccess } from 'src/utils/access'; @@ -139,7 +139,7 @@ export const getMyPartnerIds = async ({ userId, repository, timelineEnabled }: P return [...partnerIds]; }; -export type AssetHookRepositories = { asset: AssetRepository; event: IEventRepository }; +export type AssetHookRepositories = { asset: AssetRepository; event: EventRepository }; export const onBeforeLink = async ( { asset: assetRepository, event: eventRepository }: AssetHookRepositories, diff --git a/server/test/repositories/event.repository.mock.ts b/server/test/repositories/event.repository.mock.ts index a425ddef3a7bc..a253e93671d6a 100644 --- a/server/test/repositories/event.repository.mock.ts +++ b/server/test/repositories/event.repository.mock.ts @@ -1,12 +1,17 @@ -import { IEventRepository } from 'src/interfaces/event.interface'; +import { EventRepository } from 'src/repositories/event.repository'; +import { RepositoryInterface } from 'src/types'; import { Mocked, vitest } from 'vitest'; -export const newEventRepositoryMock = (): Mocked => { +export const newEventRepositoryMock = (): Mocked> => { return { setup: vitest.fn(), emit: vitest.fn() as any, clientSend: vitest.fn() as any, clientBroadcast: vitest.fn() as any, serverSend: vitest.fn(), + afterInit: vitest.fn(), + handleConnection: vitest.fn(), + handleDisconnect: vitest.fn(), + setAuthFn: vitest.fn(), }; }; diff --git a/server/test/repositories/machine-learning.repository.mock.ts b/server/test/repositories/machine-learning.repository.mock.ts index 9dd1bdca29736..229e8f92eca19 100644 --- a/server/test/repositories/machine-learning.repository.mock.ts +++ b/server/test/repositories/machine-learning.repository.mock.ts @@ -1,7 +1,8 @@ -import { IMachineLearningRepository } from 'src/interfaces/machine-learning.interface'; +import { MachineLearningRepository } from 'src/repositories/machine-learning.repository'; +import { RepositoryInterface } from 'src/types'; import { Mocked, vitest } from 'vitest'; -export const newMachineLearningRepositoryMock = (): Mocked => { +export const newMachineLearningRepositoryMock = (): Mocked> => { return { encodeImage: vitest.fn(), encodeText: vitest.fn(), diff --git a/server/test/utils.ts b/server/test/utils.ts index 9816266a210f6..fbff7ba00ddad 100644 --- a/server/test/utils.ts +++ b/server/test/utils.ts @@ -2,8 +2,6 @@ import { ChildProcessWithoutNullStreams } from 'node:child_process'; import { Writable } from 'node:stream'; import { PNG } from 'pngjs'; import { ImmichWorker } from 'src/enum'; -import { IEventRepository } from 'src/interfaces/event.interface'; -import { IMachineLearningRepository } from 'src/interfaces/machine-learning.interface'; import { AccessRepository } from 'src/repositories/access.repository'; import { ActivityRepository } from 'src/repositories/activity.repository'; import { AlbumUserRepository } from 'src/repositories/album-user.repository'; @@ -15,9 +13,11 @@ import { ConfigRepository } from 'src/repositories/config.repository'; import { CronRepository } from 'src/repositories/cron.repository'; import { CryptoRepository } from 'src/repositories/crypto.repository'; import { DatabaseRepository } from 'src/repositories/database.repository'; +import { EventRepository } from 'src/repositories/event.repository'; import { JobRepository } from 'src/repositories/job.repository'; import { LibraryRepository } from 'src/repositories/library.repository'; import { LoggingRepository } from 'src/repositories/logging.repository'; +import { MachineLearningRepository } from 'src/repositories/machine-learning.repository'; import { MapRepository } from 'src/repositories/map.repository'; import { MediaRepository } from 'src/repositories/media.repository'; import { MemoryRepository } from 'src/repositories/memory.repository'; @@ -108,11 +108,11 @@ export type ServiceMocks = { cron: Mocked>; crypto: Mocked>; database: Mocked>; - event: Mocked; + event: Mocked>; job: Mocked>; library: Mocked>; logger: Mocked; - machineLearning: Mocked; + machineLearning: Mocked>; map: Mocked>; media: Mocked>; memory: Mocked>; @@ -198,11 +198,11 @@ export const newTestService = ( cronMock as RepositoryInterface as CronRepository, cryptoMock as RepositoryInterface as CryptoRepository, databaseMock as RepositoryInterface as DatabaseRepository, - eventMock, + eventMock as RepositoryInterface as EventRepository, jobMock, apiKeyMock as RepositoryInterface as ApiKeyRepository, libraryMock as RepositoryInterface as LibraryRepository, - machineLearningMock, + machineLearningMock as RepositoryInterface as MachineLearningRepository, mapMock as RepositoryInterface as MapRepository, mediaMock as RepositoryInterface as MediaRepository, memoryMock as RepositoryInterface as MemoryRepository, From fa5aeaf539d2e521be940fc4288142ed89d04e8b Mon Sep 17 00:00:00 2001 From: Jason Rasmussen Date: Tue, 11 Feb 2025 17:15:56 -0500 Subject: [PATCH 4/5] refactor: last repository (#16042) --- server/src/app.module.ts | 10 +- server/src/bin/sync-sql.ts | 22 +- server/src/config.ts | 4 +- server/src/constants.ts | 12 +- .../src/controllers/asset-media.controller.ts | 3 +- server/src/decorators.ts | 3 +- server/src/dtos/job.dto.ts | 3 +- server/src/dtos/system-config.dto.ts | 3 +- server/src/enum.ts | 139 ++++++++ server/src/interfaces/job.interface.ts | 329 ------------------ .../src/middleware/file-upload.interceptor.ts | 14 +- server/src/repositories/config.repository.ts | 13 +- .../src/repositories/database.repository.ts | 56 +-- server/src/repositories/event.repository.ts | 4 +- server/src/repositories/index.ts | 4 +- server/src/repositories/job.repository.ts | 17 +- server/src/repositories/memory.repository.ts | 2 +- .../repositories/notification.repository.ts | 7 +- .../src/services/asset-media.service.spec.ts | 3 +- server/src/services/asset-media.service.ts | 15 +- server/src/services/asset.service.spec.ts | 3 +- server/src/services/asset.service.ts | 16 +- server/src/services/audit.service.spec.ts | 11 +- server/src/services/audit.service.ts | 6 +- server/src/services/backup.service.spec.ts | 3 +- server/src/services/backup.service.ts | 4 +- server/src/services/base.service.ts | 7 +- server/src/services/database.service.spec.ts | 3 +- server/src/services/database.service.ts | 5 +- server/src/services/duplicate.service.spec.ts | 2 +- server/src/services/duplicate.service.ts | 4 +- server/src/services/job.service.spec.ts | 4 +- server/src/services/job.service.ts | 9 +- server/src/services/library.service.spec.ts | 11 +- server/src/services/library.service.ts | 6 +- server/src/services/map.service.ts | 2 + server/src/services/media.service.spec.ts | 5 +- server/src/services/media.service.ts | 14 +- server/src/services/metadata.service.spec.ts | 3 +- server/src/services/metadata.service.ts | 15 +- .../src/services/notification.service.spec.ts | 4 +- server/src/services/notification.service.ts | 13 +- server/src/services/person.service.spec.ts | 3 +- server/src/services/person.service.ts | 15 +- server/src/services/session.service.spec.ts | 2 +- server/src/services/session.service.ts | 3 +- .../src/services/smart-info.service.spec.ts | 3 +- server/src/services/smart-info.service.ts | 6 +- .../services/storage-template.service.spec.ts | 3 +- .../src/services/storage-template.service.ts | 6 +- server/src/services/storage.service.ts | 5 +- server/src/services/sync.service.ts | 2 + .../services/system-config.service.spec.ts | 2 +- server/src/services/system-config.service.ts | 2 +- server/src/services/tag.service.spec.ts | 2 +- server/src/services/tag.service.ts | 3 +- server/src/services/timeline.service.ts | 3 +- server/src/services/trash.service.spec.ts | 2 +- server/src/services/trash.service.ts | 6 +- .../src/services/user-admin.service.spec.ts | 3 +- server/src/services/user-admin.service.ts | 3 +- server/src/services/user.service.spec.ts | 3 +- server/src/services/user.service.ts | 4 +- server/src/services/version.service.spec.ts | 3 +- server/src/services/version.service.ts | 4 +- server/src/services/view.service.ts | 2 + server/src/types.ts | 253 +++++++++++++- server/src/utils/asset.util.ts | 9 +- server/src/utils/config.ts | 3 +- .../test/repositories/job.repository.mock.ts | 5 +- server/test/utils.ts | 4 +- 71 files changed, 574 insertions(+), 603 deletions(-) delete mode 100644 server/src/interfaces/job.interface.ts diff --git a/server/src/app.module.ts b/server/src/app.module.ts index 2d6d7878dcd8a..a4518598a3678 100644 --- a/server/src/app.module.ts +++ b/server/src/app.module.ts @@ -13,15 +13,15 @@ import { IWorker } from 'src/constants'; import { controllers } from 'src/controllers'; import { entities } from 'src/entities'; import { ImmichWorker } from 'src/enum'; -import { IJobRepository } from 'src/interfaces/job.interface'; import { AuthGuard } from 'src/middleware/auth.guard'; import { ErrorInterceptor } from 'src/middleware/error.interceptor'; import { FileUploadInterceptor } from 'src/middleware/file-upload.interceptor'; import { GlobalExceptionFilter } from 'src/middleware/global-exception.filter'; import { LoggingInterceptor } from 'src/middleware/logging.interceptor'; -import { providers, repositories } from 'src/repositories'; +import { repositories } from 'src/repositories'; import { ConfigRepository } from 'src/repositories/config.repository'; import { EventRepository } from 'src/repositories/event.repository'; +import { JobRepository } from 'src/repositories/job.repository'; import { LoggingRepository } from 'src/repositories/logging.repository'; import { teardownTelemetry, TelemetryRepository } from 'src/repositories/telemetry.repository'; import { services } from 'src/services'; @@ -29,7 +29,7 @@ import { AuthService } from 'src/services/auth.service'; import { CliService } from 'src/services/cli.service'; import { DatabaseService } from 'src/services/database.service'; -const common = [...services, ...providers, ...repositories]; +const common = [...repositories, ...services]; const middleware = [ FileUploadInterceptor, @@ -80,7 +80,7 @@ class BaseModule implements OnModuleInit, OnModuleDestroy { @Inject(IWorker) private worker: ImmichWorker, logger: LoggingRepository, private eventRepository: EventRepository, - @Inject(IJobRepository) private jobRepository: IJobRepository, + private jobRepository: JobRepository, private telemetryRepository: TelemetryRepository, private authService: AuthService, ) { @@ -88,7 +88,7 @@ class BaseModule implements OnModuleInit, OnModuleDestroy { } async onModuleInit() { - this.telemetryRepository.setup({ repositories: [...providers.map(({ useClass }) => useClass), ...repositories] }); + this.telemetryRepository.setup({ repositories }); this.jobRepository.setup({ services }); if (this.worker === ImmichWorker.MICROSERVICES) { diff --git a/server/src/bin/sync-sql.ts b/server/src/bin/sync-sql.ts index e0d578d58f923..4765993643427 100644 --- a/server/src/bin/sync-sql.ts +++ b/server/src/bin/sync-sql.ts @@ -4,6 +4,7 @@ import { Reflector } from '@nestjs/core'; import { SchedulerRegistry } from '@nestjs/schedule'; import { Test } from '@nestjs/testing'; import { TypeOrmModule } from '@nestjs/typeorm'; +import { ClassConstructor } from 'class-transformer'; import { PostgresJSDialect } from 'kysely-postgres-js'; import { KyselyModule } from 'nestjs-kysely'; import { OpenTelemetryModule } from 'nestjs-otel'; @@ -13,7 +14,7 @@ import postgres from 'postgres'; import { format } from 'sql-formatter'; import { GENERATE_SQL_KEY, GenerateSqlQueries } from 'src/decorators'; import { entities } from 'src/entities'; -import { providers, repositories } from 'src/repositories'; +import { repositories } from 'src/repositories'; import { AccessRepository } from 'src/repositories/access.repository'; import { ConfigRepository } from 'src/repositories/config.repository'; import { LoggingRepository } from 'src/repositories/logging.repository'; @@ -45,8 +46,7 @@ export class SqlLogger implements Logger { const reflector = new Reflector(); -type Repository = (typeof providers)[0]['useClass']; -type Provider = { provide: any; useClass: Repository }; +type Repository = ClassConstructor; type SqlGeneratorOptions = { targetDir: string }; class SqlGenerator { @@ -59,15 +59,11 @@ class SqlGenerator { async run() { try { await this.setup(); - const targets = [ - ...providers, - ...repositories.map((repository) => ({ provide: repository, useClass: repository as any })), - ]; - for (const repository of targets) { - if (repository.provide === LoggingRepository) { + for (const Repository of repositories) { + if (Repository === LoggingRepository) { continue; } - await this.process(repository); + await this.process(Repository); } await this.write(); this.stats(); @@ -105,19 +101,19 @@ class SqlGenerator { TypeOrmModule.forFeature(entities), OpenTelemetryModule.forRoot(otel), ], - providers: [...providers, ...repositories, AuthService, SchedulerRegistry], + providers: [...repositories, AuthService, SchedulerRegistry], }).compile(); this.app = await moduleFixture.createNestApplication().init(); } - async process({ provide: token, useClass: Repository }: Provider) { + async process(Repository: Repository) { if (!this.app) { throw new Error('Not initialized'); } const data: string[] = [`-- NOTE: This file is auto generated by ./sql-generator`]; - const instance = this.app.get(token); + const instance = this.app.get(Repository); // normal repositories data.push(...(await this.runTargets(instance, `${Repository.name}`))); diff --git a/server/src/config.ts b/server/src/config.ts index 7dd015c0fa0ba..e7f3d4b8b6153 100644 --- a/server/src/config.ts +++ b/server/src/config.ts @@ -5,14 +5,14 @@ import { CQMode, ImageFormat, LogLevel, + QueueName, ToneMapping, TranscodeHWAccel, TranscodePolicy, VideoCodec, VideoContainer, } from 'src/enum'; -import { ConcurrentQueueName, QueueName } from 'src/interfaces/job.interface'; -import { ImageOptions } from 'src/types'; +import { ConcurrentQueueName, ImageOptions } from 'src/types'; export interface SystemConfig { backup: { diff --git a/server/src/constants.ts b/server/src/constants.ts index 050a7d06fab45..889ce81620b86 100644 --- a/server/src/constants.ts +++ b/server/src/constants.ts @@ -1,7 +1,7 @@ import { Duration } from 'luxon'; import { readFileSync } from 'node:fs'; import { SemVer } from 'semver'; -import { ExifOrientation } from 'src/enum'; +import { DatabaseExtension, ExifOrientation } from 'src/enum'; export const POSTGRES_VERSION_RANGE = '>=14.0.0'; export const VECTORS_VERSION_RANGE = '>=0.2 <0.4'; @@ -16,6 +16,16 @@ export const LIFECYCLE_EXTENSION = 'x-immich-lifecycle'; export const DEPRECATED_IN_PREFIX = 'This property was deprecated in '; export const ADDED_IN_PREFIX = 'This property was added in '; +export const JOBS_ASSET_PAGINATION_SIZE = 1000; +export const JOBS_LIBRARY_PAGINATION_SIZE = 10_000; + +export const EXTENSION_NAMES: Record = { + cube: 'cube', + earthdistance: 'earthdistance', + vector: 'pgvector', + vectors: 'pgvecto.rs', +} as const; + export const SALT_ROUNDS = 10; export const IWorker = 'IWorker'; diff --git a/server/src/controllers/asset-media.controller.ts b/server/src/controllers/asset-media.controller.ts index fd405b8928c7a..3d2845690d3f8 100644 --- a/server/src/controllers/asset-media.controller.ts +++ b/server/src/controllers/asset-media.controller.ts @@ -35,9 +35,10 @@ import { AuthDto } from 'src/dtos/auth.dto'; import { ImmichHeader, RouteKey } from 'src/enum'; import { AssetUploadInterceptor } from 'src/middleware/asset-upload.interceptor'; import { Auth, Authenticated, FileResponse } from 'src/middleware/auth.guard'; -import { FileUploadInterceptor, UploadFiles, getFiles } from 'src/middleware/file-upload.interceptor'; +import { FileUploadInterceptor, getFiles } from 'src/middleware/file-upload.interceptor'; import { LoggingRepository } from 'src/repositories/logging.repository'; import { AssetMediaService } from 'src/services/asset-media.service'; +import { UploadFiles } from 'src/types'; import { sendFile } from 'src/utils/file'; import { FileNotEmptyValidator, UUIDParamDto } from 'src/validation'; diff --git a/server/src/decorators.ts b/server/src/decorators.ts index 7aab2e248aca1..56efdd1c08db0 100644 --- a/server/src/decorators.ts +++ b/server/src/decorators.ts @@ -2,8 +2,7 @@ import { SetMetadata, applyDecorators } from '@nestjs/common'; import { ApiExtension, ApiOperation, ApiProperty, ApiTags } from '@nestjs/swagger'; import _ from 'lodash'; import { ADDED_IN_PREFIX, DEPRECATED_IN_PREFIX, LIFECYCLE_EXTENSION } from 'src/constants'; -import { ImmichWorker, MetadataKey } from 'src/enum'; -import { JobName, QueueName } from 'src/interfaces/job.interface'; +import { ImmichWorker, JobName, MetadataKey, QueueName } from 'src/enum'; import { EmitEvent } from 'src/repositories/event.repository'; import { setUnion } from 'src/utils/set'; diff --git a/server/src/dtos/job.dto.ts b/server/src/dtos/job.dto.ts index 31612bd8a4fb7..ce6aad4c066e7 100644 --- a/server/src/dtos/job.dto.ts +++ b/server/src/dtos/job.dto.ts @@ -1,7 +1,6 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsEnum, IsNotEmpty } from 'class-validator'; -import { ManualJobName } from 'src/enum'; -import { JobCommand, QueueName } from 'src/interfaces/job.interface'; +import { JobCommand, ManualJobName, QueueName } from 'src/enum'; import { ValidateBoolean } from 'src/validation'; export class JobIdParamDto { diff --git a/server/src/dtos/system-config.dto.ts b/server/src/dtos/system-config.dto.ts index 350918254542a..6b51c015b7201 100644 --- a/server/src/dtos/system-config.dto.ts +++ b/server/src/dtos/system-config.dto.ts @@ -25,13 +25,14 @@ import { Colorspace, ImageFormat, LogLevel, + QueueName, ToneMapping, TranscodeHWAccel, TranscodePolicy, VideoCodec, VideoContainer, } from 'src/enum'; -import { ConcurrentQueueName, QueueName } from 'src/interfaces/job.interface'; +import { ConcurrentQueueName } from 'src/types'; import { IsCronExpression, ValidateBoolean } from 'src/validation'; const isLibraryScanEnabled = (config: SystemConfigLibraryScanDto) => config.enabled; diff --git a/server/src/enum.ts b/server/src/enum.ts index b887fbace3bb3..0c1fb01a12310 100644 --- a/server/src/enum.ts +++ b/server/src/enum.ts @@ -398,3 +398,142 @@ export enum BootstrapEventPriority { // Initialise config after other bootstrap services, stop other services from using config on bootstrap SystemConfig = 100, } + +export enum QueueName { + THUMBNAIL_GENERATION = 'thumbnailGeneration', + METADATA_EXTRACTION = 'metadataExtraction', + VIDEO_CONVERSION = 'videoConversion', + FACE_DETECTION = 'faceDetection', + FACIAL_RECOGNITION = 'facialRecognition', + SMART_SEARCH = 'smartSearch', + DUPLICATE_DETECTION = 'duplicateDetection', + BACKGROUND_TASK = 'backgroundTask', + STORAGE_TEMPLATE_MIGRATION = 'storageTemplateMigration', + MIGRATION = 'migration', + SEARCH = 'search', + SIDECAR = 'sidecar', + LIBRARY = 'library', + NOTIFICATION = 'notifications', + BACKUP_DATABASE = 'backupDatabase', +} + +export enum JobName { + //backups + BACKUP_DATABASE = 'database-backup', + + // conversion + QUEUE_VIDEO_CONVERSION = 'queue-video-conversion', + VIDEO_CONVERSION = 'video-conversion', + + // thumbnails + QUEUE_GENERATE_THUMBNAILS = 'queue-generate-thumbnails', + GENERATE_THUMBNAILS = 'generate-thumbnails', + GENERATE_PERSON_THUMBNAIL = 'generate-person-thumbnail', + + // metadata + QUEUE_METADATA_EXTRACTION = 'queue-metadata-extraction', + METADATA_EXTRACTION = 'metadata-extraction', + LINK_LIVE_PHOTOS = 'link-live-photos', + + // user + USER_DELETION = 'user-deletion', + USER_DELETE_CHECK = 'user-delete-check', + USER_SYNC_USAGE = 'user-sync-usage', + + // asset + ASSET_DELETION = 'asset-deletion', + ASSET_DELETION_CHECK = 'asset-deletion-check', + + // storage template + STORAGE_TEMPLATE_MIGRATION = 'storage-template-migration', + STORAGE_TEMPLATE_MIGRATION_SINGLE = 'storage-template-migration-single', + + // tags + TAG_CLEANUP = 'tag-cleanup', + + // migration + QUEUE_MIGRATION = 'queue-migration', + MIGRATE_ASSET = 'migrate-asset', + MIGRATE_PERSON = 'migrate-person', + + // facial recognition + PERSON_CLEANUP = 'person-cleanup', + QUEUE_FACE_DETECTION = 'queue-face-detection', + FACE_DETECTION = 'face-detection', + QUEUE_FACIAL_RECOGNITION = 'queue-facial-recognition', + FACIAL_RECOGNITION = 'facial-recognition', + + // library management + LIBRARY_QUEUE_SYNC_FILES = 'library-queue-sync-files', + LIBRARY_QUEUE_SYNC_ASSETS = 'library-queue-sync-assets', + LIBRARY_SYNC_FILE = 'library-sync-file', + LIBRARY_SYNC_ASSET = 'library-sync-asset', + LIBRARY_DELETE = 'library-delete', + LIBRARY_QUEUE_SYNC_ALL = 'library-queue-sync-all', + LIBRARY_QUEUE_CLEANUP = 'library-queue-cleanup', + + // cleanup + DELETE_FILES = 'delete-files', + CLEAN_OLD_AUDIT_LOGS = 'clean-old-audit-logs', + CLEAN_OLD_SESSION_TOKENS = 'clean-old-session-tokens', + + // smart search + QUEUE_SMART_SEARCH = 'queue-smart-search', + SMART_SEARCH = 'smart-search', + + QUEUE_TRASH_EMPTY = 'queue-trash-empty', + + // duplicate detection + QUEUE_DUPLICATE_DETECTION = 'queue-duplicate-detection', + DUPLICATE_DETECTION = 'duplicate-detection', + + // XMP sidecars + QUEUE_SIDECAR = 'queue-sidecar', + SIDECAR_DISCOVERY = 'sidecar-discovery', + SIDECAR_SYNC = 'sidecar-sync', + SIDECAR_WRITE = 'sidecar-write', + + // Notification + NOTIFY_SIGNUP = 'notify-signup', + NOTIFY_ALBUM_INVITE = 'notify-album-invite', + NOTIFY_ALBUM_UPDATE = 'notify-album-update', + SEND_EMAIL = 'notification-send-email', + + // Version check + VERSION_CHECK = 'version-check', +} + +export enum JobCommand { + START = 'start', + PAUSE = 'pause', + RESUME = 'resume', + EMPTY = 'empty', + CLEAR_FAILED = 'clear-failed', +} + +export enum JobStatus { + SUCCESS = 'success', + FAILED = 'failed', + SKIPPED = 'skipped', +} + +export enum QueueCleanType { + FAILED = 'failed', +} + +export enum VectorIndex { + CLIP = 'clip_index', + FACE = 'face_index', +} + +export enum DatabaseLock { + GeodataImport = 100, + Migrations = 200, + SystemFileMounts = 300, + StorageTemplateMigration = 420, + VersionHistory = 500, + CLIPDimSize = 512, + Library = 1337, + GetSystemConfig = 69, + BackupDatabase = 42, +} diff --git a/server/src/interfaces/job.interface.ts b/server/src/interfaces/job.interface.ts deleted file mode 100644 index 1f2b92074ac19..0000000000000 --- a/server/src/interfaces/job.interface.ts +++ /dev/null @@ -1,329 +0,0 @@ -import { ClassConstructor } from 'class-transformer'; -import { EmailImageAttachment } from 'src/repositories/notification.repository'; - -export enum QueueName { - THUMBNAIL_GENERATION = 'thumbnailGeneration', - METADATA_EXTRACTION = 'metadataExtraction', - VIDEO_CONVERSION = 'videoConversion', - FACE_DETECTION = 'faceDetection', - FACIAL_RECOGNITION = 'facialRecognition', - SMART_SEARCH = 'smartSearch', - DUPLICATE_DETECTION = 'duplicateDetection', - BACKGROUND_TASK = 'backgroundTask', - STORAGE_TEMPLATE_MIGRATION = 'storageTemplateMigration', - MIGRATION = 'migration', - SEARCH = 'search', - SIDECAR = 'sidecar', - LIBRARY = 'library', - NOTIFICATION = 'notifications', - BACKUP_DATABASE = 'backupDatabase', -} - -export type ConcurrentQueueName = Exclude< - QueueName, - | QueueName.STORAGE_TEMPLATE_MIGRATION - | QueueName.FACIAL_RECOGNITION - | QueueName.DUPLICATE_DETECTION - | QueueName.BACKUP_DATABASE ->; - -export enum JobCommand { - START = 'start', - PAUSE = 'pause', - RESUME = 'resume', - EMPTY = 'empty', - CLEAR_FAILED = 'clear-failed', -} - -export enum JobName { - //backups - BACKUP_DATABASE = 'database-backup', - - // conversion - QUEUE_VIDEO_CONVERSION = 'queue-video-conversion', - VIDEO_CONVERSION = 'video-conversion', - - // thumbnails - QUEUE_GENERATE_THUMBNAILS = 'queue-generate-thumbnails', - GENERATE_THUMBNAILS = 'generate-thumbnails', - GENERATE_PERSON_THUMBNAIL = 'generate-person-thumbnail', - - // metadata - QUEUE_METADATA_EXTRACTION = 'queue-metadata-extraction', - METADATA_EXTRACTION = 'metadata-extraction', - LINK_LIVE_PHOTOS = 'link-live-photos', - - // user - USER_DELETION = 'user-deletion', - USER_DELETE_CHECK = 'user-delete-check', - USER_SYNC_USAGE = 'user-sync-usage', - - // asset - ASSET_DELETION = 'asset-deletion', - ASSET_DELETION_CHECK = 'asset-deletion-check', - - // storage template - STORAGE_TEMPLATE_MIGRATION = 'storage-template-migration', - STORAGE_TEMPLATE_MIGRATION_SINGLE = 'storage-template-migration-single', - - // tags - TAG_CLEANUP = 'tag-cleanup', - - // migration - QUEUE_MIGRATION = 'queue-migration', - MIGRATE_ASSET = 'migrate-asset', - MIGRATE_PERSON = 'migrate-person', - - // facial recognition - PERSON_CLEANUP = 'person-cleanup', - QUEUE_FACE_DETECTION = 'queue-face-detection', - FACE_DETECTION = 'face-detection', - QUEUE_FACIAL_RECOGNITION = 'queue-facial-recognition', - FACIAL_RECOGNITION = 'facial-recognition', - - // library management - LIBRARY_QUEUE_SYNC_FILES = 'library-queue-sync-files', - LIBRARY_QUEUE_SYNC_ASSETS = 'library-queue-sync-assets', - LIBRARY_SYNC_FILE = 'library-sync-file', - LIBRARY_SYNC_ASSET = 'library-sync-asset', - LIBRARY_DELETE = 'library-delete', - LIBRARY_QUEUE_SYNC_ALL = 'library-queue-sync-all', - LIBRARY_QUEUE_CLEANUP = 'library-queue-cleanup', - - // cleanup - DELETE_FILES = 'delete-files', - CLEAN_OLD_AUDIT_LOGS = 'clean-old-audit-logs', - CLEAN_OLD_SESSION_TOKENS = 'clean-old-session-tokens', - - // smart search - QUEUE_SMART_SEARCH = 'queue-smart-search', - SMART_SEARCH = 'smart-search', - - QUEUE_TRASH_EMPTY = 'queue-trash-empty', - - // duplicate detection - QUEUE_DUPLICATE_DETECTION = 'queue-duplicate-detection', - DUPLICATE_DETECTION = 'duplicate-detection', - - // XMP sidecars - QUEUE_SIDECAR = 'queue-sidecar', - SIDECAR_DISCOVERY = 'sidecar-discovery', - SIDECAR_SYNC = 'sidecar-sync', - SIDECAR_WRITE = 'sidecar-write', - - // Notification - NOTIFY_SIGNUP = 'notify-signup', - NOTIFY_ALBUM_INVITE = 'notify-album-invite', - NOTIFY_ALBUM_UPDATE = 'notify-album-update', - SEND_EMAIL = 'notification-send-email', - - // Version check - VERSION_CHECK = 'version-check', -} - -export const JOBS_ASSET_PAGINATION_SIZE = 1000; -export const JOBS_LIBRARY_PAGINATION_SIZE = 10_000; - -export interface IBaseJob { - force?: boolean; -} - -export interface IDelayedJob extends IBaseJob { - /** The minimum time to wait to execute this job, in milliseconds. */ - delay?: number; -} - -export interface IEntityJob extends IBaseJob { - id: string; - source?: 'upload' | 'sidecar-write' | 'copy'; - notify?: boolean; -} - -export interface IAssetDeleteJob extends IEntityJob { - deleteOnDisk: boolean; -} - -export interface ILibraryFileJob extends IEntityJob { - ownerId: string; - assetPath: string; -} - -export interface ILibraryAssetJob extends IEntityJob { - importPaths: string[]; - exclusionPatterns: string[]; -} - -export interface IBulkEntityJob extends IBaseJob { - ids: string[]; -} - -export interface IDeleteFilesJob extends IBaseJob { - files: Array; -} - -export interface ISidecarWriteJob extends IEntityJob { - description?: string; - dateTimeOriginal?: string; - latitude?: number; - longitude?: number; - rating?: number; - tags?: true; -} - -export interface IDeferrableJob extends IEntityJob { - deferred?: boolean; -} - -export interface INightlyJob extends IBaseJob { - nightly?: boolean; -} - -export interface IEmailJob { - to: string; - subject: string; - html: string; - text: string; - imageAttachments?: EmailImageAttachment[]; -} - -export interface INotifySignupJob extends IEntityJob { - tempPassword?: string; -} - -export interface INotifyAlbumInviteJob extends IEntityJob { - recipientId: string; -} - -export interface INotifyAlbumUpdateJob extends IEntityJob, IDelayedJob { - recipientIds: string[]; -} - -export interface JobCounts { - active: number; - completed: number; - failed: number; - delayed: number; - waiting: number; - paused: number; -} - -export interface QueueStatus { - isActive: boolean; - isPaused: boolean; -} - -export enum QueueCleanType { - FAILED = 'failed', -} - -export type JobItem = - // Backups - | { name: JobName.BACKUP_DATABASE; data?: IBaseJob } - - // Transcoding - | { name: JobName.QUEUE_VIDEO_CONVERSION; data: IBaseJob } - | { name: JobName.VIDEO_CONVERSION; data: IEntityJob } - - // Thumbnails - | { name: JobName.QUEUE_GENERATE_THUMBNAILS; data: IBaseJob } - | { name: JobName.GENERATE_THUMBNAILS; data: IEntityJob } - - // User - | { name: JobName.USER_DELETE_CHECK; data?: IBaseJob } - | { name: JobName.USER_DELETION; data: IEntityJob } - | { name: JobName.USER_SYNC_USAGE; data?: IBaseJob } - - // Storage Template - | { name: JobName.STORAGE_TEMPLATE_MIGRATION; data?: IBaseJob } - | { name: JobName.STORAGE_TEMPLATE_MIGRATION_SINGLE; data: IEntityJob } - - // Migration - | { name: JobName.QUEUE_MIGRATION; data?: IBaseJob } - | { name: JobName.MIGRATE_ASSET; data: IEntityJob } - | { name: JobName.MIGRATE_PERSON; data: IEntityJob } - - // Metadata Extraction - | { name: JobName.QUEUE_METADATA_EXTRACTION; data: IBaseJob } - | { name: JobName.METADATA_EXTRACTION; data: IEntityJob } - | { name: JobName.LINK_LIVE_PHOTOS; data: IEntityJob } - // Sidecar Scanning - | { name: JobName.QUEUE_SIDECAR; data: IBaseJob } - | { name: JobName.SIDECAR_DISCOVERY; data: IEntityJob } - | { name: JobName.SIDECAR_SYNC; data: IEntityJob } - | { name: JobName.SIDECAR_WRITE; data: ISidecarWriteJob } - - // Facial Recognition - | { name: JobName.QUEUE_FACE_DETECTION; data: IBaseJob } - | { name: JobName.FACE_DETECTION; data: IEntityJob } - | { name: JobName.QUEUE_FACIAL_RECOGNITION; data: INightlyJob } - | { name: JobName.FACIAL_RECOGNITION; data: IDeferrableJob } - | { name: JobName.GENERATE_PERSON_THUMBNAIL; data: IEntityJob } - - // Smart Search - | { name: JobName.QUEUE_SMART_SEARCH; data: IBaseJob } - | { name: JobName.SMART_SEARCH; data: IEntityJob } - | { name: JobName.QUEUE_TRASH_EMPTY; data?: IBaseJob } - - // Duplicate Detection - | { name: JobName.QUEUE_DUPLICATE_DETECTION; data: IBaseJob } - | { name: JobName.DUPLICATE_DETECTION; data: IEntityJob } - - // Filesystem - | { name: JobName.DELETE_FILES; data: IDeleteFilesJob } - - // Cleanup - | { name: JobName.CLEAN_OLD_AUDIT_LOGS; data?: IBaseJob } - | { name: JobName.CLEAN_OLD_SESSION_TOKENS; data?: IBaseJob } - - // Tags - | { name: JobName.TAG_CLEANUP; data?: IBaseJob } - - // Asset Deletion - | { name: JobName.PERSON_CLEANUP; data?: IBaseJob } - | { name: JobName.ASSET_DELETION; data: IAssetDeleteJob } - | { name: JobName.ASSET_DELETION_CHECK; data?: IBaseJob } - - // Library Management - | { name: JobName.LIBRARY_SYNC_FILE; data: ILibraryFileJob } - | { name: JobName.LIBRARY_QUEUE_SYNC_FILES; data: IEntityJob } - | { name: JobName.LIBRARY_QUEUE_SYNC_ASSETS; data: IEntityJob } - | { name: JobName.LIBRARY_SYNC_ASSET; data: ILibraryAssetJob } - | { name: JobName.LIBRARY_DELETE; data: IEntityJob } - | { name: JobName.LIBRARY_QUEUE_SYNC_ALL; data?: IBaseJob } - | { name: JobName.LIBRARY_QUEUE_CLEANUP; data: IBaseJob } - - // Notification - | { name: JobName.SEND_EMAIL; data: IEmailJob } - | { name: JobName.NOTIFY_ALBUM_INVITE; data: INotifyAlbumInviteJob } - | { name: JobName.NOTIFY_ALBUM_UPDATE; data: INotifyAlbumUpdateJob } - | { name: JobName.NOTIFY_SIGNUP; data: INotifySignupJob } - - // Version check - | { name: JobName.VERSION_CHECK; data: IBaseJob }; - -export enum JobStatus { - SUCCESS = 'success', - FAILED = 'failed', - SKIPPED = 'skipped', -} -export type Jobs = { [K in JobItem['name']]: (JobItem & { name: K })['data'] }; -export type JobOf = Jobs[T]; - -export const IJobRepository = 'IJobRepository'; - -export interface IJobRepository { - setup(options: { services: ClassConstructor[] }): void; - startWorkers(): void; - run(job: JobItem): Promise; - setConcurrency(queueName: QueueName, concurrency: number): void; - queue(item: JobItem): Promise; - queueAll(items: JobItem[]): Promise; - pause(name: QueueName): Promise; - resume(name: QueueName): Promise; - empty(name: QueueName): Promise; - clear(name: QueueName, type: QueueCleanType): Promise; - getQueueStatus(name: QueueName): Promise; - getJobCounts(name: QueueName): Promise; - waitForQueueCompletion(...queues: QueueName[]): Promise; - removeJob(jobId: string, name: JobName): Promise; -} diff --git a/server/src/middleware/file-upload.interceptor.ts b/server/src/middleware/file-upload.interceptor.ts index 743764ff7529e..6f6d9aaf43468 100644 --- a/server/src/middleware/file-upload.interceptor.ts +++ b/server/src/middleware/file-upload.interceptor.ts @@ -10,14 +10,10 @@ import { UploadFieldName } from 'src/dtos/asset-media.dto'; import { RouteKey } from 'src/enum'; import { AuthRequest } from 'src/middleware/auth.guard'; import { LoggingRepository } from 'src/repositories/logging.repository'; -import { AssetMediaService, UploadFile } from 'src/services/asset-media.service'; +import { AssetMediaService } from 'src/services/asset-media.service'; +import { ImmichFile, UploadFile, UploadFiles } from 'src/types'; import { asRequest, mapToUploadFile } from 'src/utils/asset.util'; -export interface UploadFiles { - assetData: ImmichFile[]; - sidecarData: ImmichFile[]; -} - export function getFile(files: UploadFiles, property: 'assetData' | 'sidecarData') { const file = files[property]?.[0]; return file ? mapToUploadFile(file) : file; @@ -30,12 +26,6 @@ export function getFiles(files: UploadFiles) { }; } -export interface ImmichFile extends Express.Multer.File { - /** sha1 hash of file */ - uuid: string; - checksum: Buffer; -} - type DiskStorageCallback = (error: Error | null, result: string) => void; type ImmichMulterFile = Express.Multer.File & { uuid: string }; diff --git a/server/src/repositories/config.repository.ts b/server/src/repositories/config.repository.ts index 27c10bcdcc0f6..2d5f2bc2e2b28 100644 --- a/server/src/repositories/config.repository.ts +++ b/server/src/repositories/config.repository.ts @@ -13,9 +13,16 @@ import { Notice } from 'postgres'; import { citiesFile, excludePaths, IWorker } from 'src/constants'; import { Telemetry } from 'src/decorators'; import { EnvDto } from 'src/dtos/env.dto'; -import { DatabaseExtension, ImmichEnvironment, ImmichHeader, ImmichTelemetry, ImmichWorker, LogLevel } from 'src/enum'; -import { QueueName } from 'src/interfaces/job.interface'; -import { DatabaseConnectionParams, VectorExtension } from 'src/repositories/database.repository'; +import { + DatabaseExtension, + ImmichEnvironment, + ImmichHeader, + ImmichTelemetry, + ImmichWorker, + LogLevel, + QueueName, +} from 'src/enum'; +import { DatabaseConnectionParams, VectorExtension } from 'src/types'; import { setDifference } from 'src/utils/set'; import { PostgresConnectionOptions } from 'typeorm/driver/postgres/PostgresConnectionOptions.js'; diff --git a/server/src/repositories/database.repository.ts b/server/src/repositories/database.repository.ts index 6edcedd13c92b..ef97147c61cfc 100644 --- a/server/src/repositories/database.repository.ts +++ b/server/src/repositories/database.repository.ts @@ -4,66 +4,16 @@ import AsyncLock from 'async-lock'; import { Kysely, sql } from 'kysely'; import { InjectKysely } from 'nestjs-kysely'; import semver from 'semver'; -import { POSTGRES_VERSION_RANGE, VECTOR_VERSION_RANGE, VECTORS_VERSION_RANGE } from 'src/constants'; +import { EXTENSION_NAMES, POSTGRES_VERSION_RANGE, VECTOR_VERSION_RANGE, VECTORS_VERSION_RANGE } from 'src/constants'; import { DB } from 'src/db'; -import { DatabaseExtension } from 'src/enum'; +import { DatabaseExtension, DatabaseLock, VectorIndex } from 'src/enum'; import { ConfigRepository } from 'src/repositories/config.repository'; import { LoggingRepository } from 'src/repositories/logging.repository'; +import { ExtensionVersion, VectorExtension, VectorUpdateResult } from 'src/types'; import { UPSERT_COLUMNS } from 'src/utils/database'; import { isValidInteger } from 'src/validation'; import { DataSource, EntityManager, EntityMetadata, QueryRunner } from 'typeorm'; -export type VectorExtension = DatabaseExtension.VECTOR | DatabaseExtension.VECTORS; - -export type DatabaseConnectionURL = { - connectionType: 'url'; - url: string; -}; - -export type DatabaseConnectionParts = { - connectionType: 'parts'; - host: string; - port: number; - username: string; - password: string; - database: string; -}; - -export type DatabaseConnectionParams = DatabaseConnectionURL | DatabaseConnectionParts; - -export enum VectorIndex { - CLIP = 'clip_index', - FACE = 'face_index', -} - -export enum DatabaseLock { - GeodataImport = 100, - Migrations = 200, - SystemFileMounts = 300, - StorageTemplateMigration = 420, - VersionHistory = 500, - CLIPDimSize = 512, - Library = 1337, - GetSystemConfig = 69, - BackupDatabase = 42, -} - -export const EXTENSION_NAMES: Record = { - cube: 'cube', - earthdistance: 'earthdistance', - vector: 'pgvector', - vectors: 'pgvecto.rs', -} as const; - -export interface ExtensionVersion { - availableVersion: string | null; - installedVersion: string | null; -} - -export interface VectorUpdateResult { - restartRequired: boolean; -} - @Injectable() export class DatabaseRepository { private vectorExtension: VectorExtension; diff --git a/server/src/repositories/event.repository.ts b/server/src/repositories/event.repository.ts index 671b86f99c680..3156804d09009 100644 --- a/server/src/repositories/event.repository.ts +++ b/server/src/repositories/event.repository.ts @@ -15,10 +15,10 @@ import { EventConfig } from 'src/decorators'; import { AssetResponseDto } from 'src/dtos/asset-response.dto'; import { AuthDto } from 'src/dtos/auth.dto'; import { ReleaseNotification, ServerVersionResponseDto } from 'src/dtos/server.dto'; -import { ImmichWorker, MetadataKey } from 'src/enum'; -import { JobItem, QueueName } from 'src/interfaces/job.interface'; +import { ImmichWorker, MetadataKey, QueueName } from 'src/enum'; import { ConfigRepository } from 'src/repositories/config.repository'; import { LoggingRepository } from 'src/repositories/logging.repository'; +import { JobItem } from 'src/types'; import { handlePromiseError } from 'src/utils/misc'; type EmitHandlers = Partial<{ [T in EmitEvent]: Array> }>; diff --git a/server/src/repositories/index.ts b/server/src/repositories/index.ts index 3c96f4c89127e..d3a8aeeb69ace 100644 --- a/server/src/repositories/index.ts +++ b/server/src/repositories/index.ts @@ -1,4 +1,3 @@ -import { IJobRepository } from 'src/interfaces/job.interface'; import { AccessRepository } from 'src/repositories/access.repository'; import { ActivityRepository } from 'src/repositories/activity.repository'; import { AlbumUserRepository } from 'src/repositories/album-user.repository'; @@ -52,6 +51,7 @@ export const repositories = [ CryptoRepository, DatabaseRepository, EventRepository, + JobRepository, LibraryRepository, LoggingRepository, MachineLearningRepository, @@ -79,5 +79,3 @@ export const repositories = [ ViewRepository, VersionHistoryRepository, ]; - -export const providers = [{ provide: IJobRepository, useClass: JobRepository }]; diff --git a/server/src/repositories/job.repository.ts b/server/src/repositories/job.repository.ts index d6693f67f3256..fd9f4c5363fb0 100644 --- a/server/src/repositories/job.repository.ts +++ b/server/src/repositories/job.repository.ts @@ -5,22 +5,11 @@ import { JobsOptions, Queue, Worker } from 'bullmq'; import { ClassConstructor } from 'class-transformer'; import { setTimeout } from 'node:timers/promises'; import { JobConfig } from 'src/decorators'; -import { MetadataKey } from 'src/enum'; -import { - IEntityJob, - IJobRepository, - JobCounts, - JobItem, - JobName, - JobOf, - JobStatus, - QueueCleanType, - QueueName, - QueueStatus, -} from 'src/interfaces/job.interface'; +import { JobName, JobStatus, MetadataKey, QueueCleanType, QueueName } from 'src/enum'; import { ConfigRepository } from 'src/repositories/config.repository'; import { EventRepository } from 'src/repositories/event.repository'; import { LoggingRepository } from 'src/repositories/logging.repository'; +import { IEntityJob, JobCounts, JobItem, JobOf, QueueStatus } from 'src/types'; import { getKeyByValue, getMethodNames, ImmichStartupError } from 'src/utils/misc'; type JobMapItem = { @@ -31,7 +20,7 @@ type JobMapItem = { }; @Injectable() -export class JobRepository implements IJobRepository { +export class JobRepository { private workers: Partial> = {}; private handlers: Partial> = {}; diff --git a/server/src/repositories/memory.repository.ts b/server/src/repositories/memory.repository.ts index 042738fe4c0f6..7af363012d6c3 100644 --- a/server/src/repositories/memory.repository.ts +++ b/server/src/repositories/memory.repository.ts @@ -4,7 +4,7 @@ import { jsonArrayFrom } from 'kysely/helpers/postgres'; import { InjectKysely } from 'nestjs-kysely'; import { DB, Memories } from 'src/db'; import { Chunked, ChunkedSet, DummyValue, GenerateSql } from 'src/decorators'; -import { IBulkAsset } from 'src/utils/asset.util'; +import { IBulkAsset } from 'src/types'; @Injectable() export class MemoryRepository implements IBulkAsset { diff --git a/server/src/repositories/notification.repository.ts b/server/src/repositories/notification.repository.ts index fdb74cfdb2c08..91f03b928bb1e 100644 --- a/server/src/repositories/notification.repository.ts +++ b/server/src/repositories/notification.repository.ts @@ -7,12 +7,7 @@ import { AlbumUpdateEmail } from 'src/emails/album-update.email'; import { TestEmail } from 'src/emails/test.email'; import { WelcomeEmail } from 'src/emails/welcome.email'; import { LoggingRepository } from 'src/repositories/logging.repository'; - -export type EmailImageAttachment = { - filename: string; - path: string; - cid: string; -}; +import { EmailImageAttachment } from 'src/types'; export type SendEmailOptions = { from: string; diff --git a/server/src/services/asset-media.service.spec.ts b/server/src/services/asset-media.service.spec.ts index e52f086df054a..97736b905c06a 100644 --- a/server/src/services/asset-media.service.spec.ts +++ b/server/src/services/asset-media.service.spec.ts @@ -9,8 +9,7 @@ import { AssetMediaStatus, AssetRejectReason, AssetUploadAction } from 'src/dtos import { AssetMediaCreateDto, AssetMediaReplaceDto, AssetMediaSize, UploadFieldName } from 'src/dtos/asset-media.dto'; import { AssetFileEntity } from 'src/entities/asset-files.entity'; import { ASSET_CHECKSUM_CONSTRAINT, AssetEntity } from 'src/entities/asset.entity'; -import { AssetFileType, AssetStatus, AssetType, CacheControl } from 'src/enum'; -import { JobName } from 'src/interfaces/job.interface'; +import { AssetFileType, AssetStatus, AssetType, CacheControl, JobName } from 'src/enum'; import { AuthRequest } from 'src/middleware/auth.guard'; import { AssetMediaService } from 'src/services/asset-media.service'; import { ImmichFileResponse } from 'src/utils/file'; diff --git a/server/src/services/asset-media.service.ts b/server/src/services/asset-media.service.ts index fab836db94b32..09ebd9db71547 100644 --- a/server/src/services/asset-media.service.ts +++ b/server/src/services/asset-media.service.ts @@ -21,29 +21,22 @@ import { } from 'src/dtos/asset-media.dto'; import { AuthDto } from 'src/dtos/auth.dto'; import { ASSET_CHECKSUM_CONSTRAINT, AssetEntity } from 'src/entities/asset.entity'; -import { AssetStatus, AssetType, CacheControl, Permission, StorageFolder } from 'src/enum'; -import { JobName } from 'src/interfaces/job.interface'; +import { AssetStatus, AssetType, CacheControl, JobName, Permission, StorageFolder } from 'src/enum'; import { AuthRequest } from 'src/middleware/auth.guard'; import { BaseService } from 'src/services/base.service'; +import { UploadFile } from 'src/types'; import { requireUploadAccess } from 'src/utils/access'; import { asRequest, getAssetFiles, onBeforeLink } from 'src/utils/asset.util'; import { getFilenameExtension, getFileNameWithoutExtension, ImmichFileResponse } from 'src/utils/file'; import { mimeTypes } from 'src/utils/mime-types'; import { fromChecksum } from 'src/utils/request'; -export interface UploadRequest { + +interface UploadRequest { auth: AuthDto | null; fieldName: UploadFieldName; file: UploadFile; } -export interface UploadFile { - uuid: string; - checksum: Buffer; - originalPath: string; - originalName: string; - size: number; -} - @Injectable() export class AssetMediaService extends BaseService { async getUploadAssetIdByChecksum(auth: AuthDto, checksum?: string): Promise { diff --git a/server/src/services/asset.service.spec.ts b/server/src/services/asset.service.spec.ts index 3c9cf3739fe5d..336c3ac8f0acd 100755 --- a/server/src/services/asset.service.spec.ts +++ b/server/src/services/asset.service.spec.ts @@ -3,8 +3,7 @@ import { DateTime } from 'luxon'; import { mapAsset } from 'src/dtos/asset-response.dto'; import { AssetJobName, AssetStatsResponseDto } from 'src/dtos/asset.dto'; import { AssetEntity } from 'src/entities/asset.entity'; -import { AssetStatus, AssetType } from 'src/enum'; -import { JobName, JobStatus } from 'src/interfaces/job.interface'; +import { AssetStatus, AssetType, JobName, JobStatus } from 'src/enum'; import { AssetStats } from 'src/repositories/asset.repository'; import { AssetService } from 'src/services/asset.service'; import { assetStub } from 'test/fixtures/asset.stub'; diff --git a/server/src/services/asset.service.ts b/server/src/services/asset.service.ts index 99ddbb29cc9da..a9b723c9f91a9 100644 --- a/server/src/services/asset.service.ts +++ b/server/src/services/asset.service.ts @@ -1,6 +1,7 @@ -import { BadRequestException } from '@nestjs/common'; +import { BadRequestException, Injectable } from '@nestjs/common'; import _ from 'lodash'; import { DateTime, Duration } from 'luxon'; +import { JOBS_ASSET_PAGINATION_SIZE } from 'src/constants'; import { OnJob } from 'src/decorators'; import { AssetResponseDto, @@ -20,20 +21,13 @@ import { import { AuthDto } from 'src/dtos/auth.dto'; import { MemoryLaneDto } from 'src/dtos/search.dto'; import { AssetEntity } from 'src/entities/asset.entity'; -import { AssetStatus, Permission } from 'src/enum'; -import { - ISidecarWriteJob, - JOBS_ASSET_PAGINATION_SIZE, - JobItem, - JobName, - JobOf, - JobStatus, - QueueName, -} from 'src/interfaces/job.interface'; +import { AssetStatus, JobName, JobStatus, Permission, QueueName } from 'src/enum'; import { BaseService } from 'src/services/base.service'; +import { ISidecarWriteJob, JobItem, JobOf } from 'src/types'; import { getAssetFiles, getMyPartnerIds, onAfterUnlink, onBeforeLink, onBeforeUnlink } from 'src/utils/asset.util'; import { usePagination } from 'src/utils/pagination'; +@Injectable() export class AssetService extends BaseService { async getMemoryLane(auth: AuthDto, dto: MemoryLaneDto): Promise { const partnerIds = await getMyPartnerIds({ diff --git a/server/src/services/audit.service.spec.ts b/server/src/services/audit.service.spec.ts index b459ecb473dde..c64f6f2071661 100644 --- a/server/src/services/audit.service.spec.ts +++ b/server/src/services/audit.service.spec.ts @@ -1,7 +1,14 @@ import { BadRequestException } from '@nestjs/common'; import { FileReportItemDto } from 'src/dtos/audit.dto'; -import { AssetFileType, AssetPathType, DatabaseAction, EntityType, PersonPathType, UserPathType } from 'src/enum'; -import { JobStatus } from 'src/interfaces/job.interface'; +import { + AssetFileType, + AssetPathType, + DatabaseAction, + EntityType, + JobStatus, + PersonPathType, + UserPathType, +} from 'src/enum'; import { AuditService } from 'src/services/audit.service'; import { auditStub } from 'test/fixtures/audit.stub'; import { authStub } from 'test/fixtures/auth.stub'; diff --git a/server/src/services/audit.service.ts b/server/src/services/audit.service.ts index 611f8f69d3488..a952a0e64f17a 100644 --- a/server/src/services/audit.service.ts +++ b/server/src/services/audit.service.ts @@ -1,7 +1,7 @@ import { BadRequestException, Injectable } from '@nestjs/common'; import { DateTime } from 'luxon'; import { resolve } from 'node:path'; -import { AUDIT_LOG_MAX_DURATION } from 'src/constants'; +import { AUDIT_LOG_MAX_DURATION, JOBS_ASSET_PAGINATION_SIZE } from 'src/constants'; import { StorageCore } from 'src/cores/storage.core'; import { OnJob } from 'src/decorators'; import { @@ -17,12 +17,14 @@ import { AssetFileType, AssetPathType, DatabaseAction, + JobName, + JobStatus, Permission, PersonPathType, + QueueName, StorageFolder, UserPathType, } from 'src/enum'; -import { JobName, JOBS_ASSET_PAGINATION_SIZE, JobStatus, QueueName } from 'src/interfaces/job.interface'; import { BaseService } from 'src/services/base.service'; import { getAssetFiles } from 'src/utils/asset.util'; import { usePagination } from 'src/utils/pagination'; diff --git a/server/src/services/backup.service.spec.ts b/server/src/services/backup.service.spec.ts index fbed87a6d33ef..567859ac010a7 100644 --- a/server/src/services/backup.service.spec.ts +++ b/server/src/services/backup.service.spec.ts @@ -1,8 +1,7 @@ import { PassThrough } from 'node:stream'; import { defaults, SystemConfig } from 'src/config'; import { StorageCore } from 'src/cores/storage.core'; -import { ImmichWorker, StorageFolder } from 'src/enum'; -import { JobStatus } from 'src/interfaces/job.interface'; +import { ImmichWorker, JobStatus, StorageFolder } from 'src/enum'; import { BackupService } from 'src/services/backup.service'; import { systemConfigStub } from 'test/fixtures/system-config.stub'; import { mockSpawn, newTestService, ServiceMocks } from 'test/utils'; diff --git a/server/src/services/backup.service.ts b/server/src/services/backup.service.ts index dee8113792f5a..e4fe791b190b5 100644 --- a/server/src/services/backup.service.ts +++ b/server/src/services/backup.service.ts @@ -3,9 +3,7 @@ import { default as path } from 'node:path'; import semver from 'semver'; import { StorageCore } from 'src/cores/storage.core'; import { OnEvent, OnJob } from 'src/decorators'; -import { ImmichWorker, StorageFolder } from 'src/enum'; -import { JobName, JobStatus, QueueName } from 'src/interfaces/job.interface'; -import { DatabaseLock } from 'src/repositories/database.repository'; +import { DatabaseLock, ImmichWorker, JobName, JobStatus, QueueName, StorageFolder } from 'src/enum'; import { ArgOf } from 'src/repositories/event.repository'; import { BaseService } from 'src/services/base.service'; import { handlePromiseError } from 'src/utils/misc'; diff --git a/server/src/services/base.service.ts b/server/src/services/base.service.ts index 259248e49b6f9..f476adba11391 100644 --- a/server/src/services/base.service.ts +++ b/server/src/services/base.service.ts @@ -1,4 +1,4 @@ -import { BadRequestException, Inject } from '@nestjs/common'; +import { BadRequestException, Injectable } from '@nestjs/common'; import { Insertable } from 'kysely'; import sanitize from 'sanitize-filename'; import { SystemConfig } from 'src/config'; @@ -6,7 +6,6 @@ import { SALT_ROUNDS } from 'src/constants'; import { StorageCore } from 'src/cores/storage.core'; import { Users } from 'src/db'; import { UserEntity } from 'src/entities/user.entity'; -import { IJobRepository } from 'src/interfaces/job.interface'; import { AccessRepository } from 'src/repositories/access.repository'; import { ActivityRepository } from 'src/repositories/activity.repository'; import { AlbumUserRepository } from 'src/repositories/album-user.repository'; @@ -19,6 +18,7 @@ import { CronRepository } from 'src/repositories/cron.repository'; import { CryptoRepository } from 'src/repositories/crypto.repository'; import { DatabaseRepository } from 'src/repositories/database.repository'; import { EventRepository } from 'src/repositories/event.repository'; +import { JobRepository } from 'src/repositories/job.repository'; import { LibraryRepository } from 'src/repositories/library.repository'; import { LoggingRepository } from 'src/repositories/logging.repository'; import { MachineLearningRepository } from 'src/repositories/machine-learning.repository'; @@ -48,6 +48,7 @@ import { ViewRepository } from 'src/repositories/view-repository'; import { AccessRequest, checkAccess, requireAccess } from 'src/utils/access'; import { getConfig, updateConfig } from 'src/utils/config'; +@Injectable() export class BaseService { protected storageCore: StorageCore; @@ -64,7 +65,7 @@ export class BaseService { protected cryptoRepository: CryptoRepository, protected databaseRepository: DatabaseRepository, protected eventRepository: EventRepository, - @Inject(IJobRepository) protected jobRepository: IJobRepository, + protected jobRepository: JobRepository, protected keyRepository: ApiKeyRepository, protected libraryRepository: LibraryRepository, protected machineLearningRepository: MachineLearningRepository, diff --git a/server/src/services/database.service.spec.ts b/server/src/services/database.service.spec.ts index d50b7facf6b0a..1314d5327e8e2 100644 --- a/server/src/services/database.service.spec.ts +++ b/server/src/services/database.service.spec.ts @@ -1,6 +1,7 @@ +import { EXTENSION_NAMES } from 'src/constants'; import { DatabaseExtension } from 'src/enum'; -import { EXTENSION_NAMES, VectorExtension } from 'src/repositories/database.repository'; import { DatabaseService } from 'src/services/database.service'; +import { VectorExtension } from 'src/types'; import { mockEnvData } from 'test/repositories/config.repository.mock'; import { newTestService, ServiceMocks } from 'test/utils'; diff --git a/server/src/services/database.service.ts b/server/src/services/database.service.ts index 249b47c99cffb..36f4c0917719e 100644 --- a/server/src/services/database.service.ts +++ b/server/src/services/database.service.ts @@ -1,10 +1,11 @@ import { Injectable } from '@nestjs/common'; import { Duration } from 'luxon'; import semver from 'semver'; +import { EXTENSION_NAMES } from 'src/constants'; import { OnEvent } from 'src/decorators'; -import { BootstrapEventPriority, DatabaseExtension } from 'src/enum'; -import { DatabaseLock, EXTENSION_NAMES, VectorExtension, VectorIndex } from 'src/repositories/database.repository'; +import { BootstrapEventPriority, DatabaseExtension, DatabaseLock, VectorIndex } from 'src/enum'; import { BaseService } from 'src/services/base.service'; +import { VectorExtension } from 'src/types'; type CreateFailedArgs = { name: string; extension: string; otherName: string }; type UpdateFailedArgs = { name: string; extension: string; availableVersion: string }; diff --git a/server/src/services/duplicate.service.spec.ts b/server/src/services/duplicate.service.spec.ts index 7a8b9ed27bf0c..30b8cd345185c 100644 --- a/server/src/services/duplicate.service.spec.ts +++ b/server/src/services/duplicate.service.spec.ts @@ -1,4 +1,4 @@ -import { JobName, JobStatus } from 'src/interfaces/job.interface'; +import { JobName, JobStatus } from 'src/enum'; import { WithoutProperty } from 'src/repositories/asset.repository'; import { DuplicateService } from 'src/services/duplicate.service'; import { SearchService } from 'src/services/search.service'; diff --git a/server/src/services/duplicate.service.ts b/server/src/services/duplicate.service.ts index 1b0d583cc3024..5600033b47520 100644 --- a/server/src/services/duplicate.service.ts +++ b/server/src/services/duplicate.service.ts @@ -1,13 +1,15 @@ import { Injectable } from '@nestjs/common'; +import { JOBS_ASSET_PAGINATION_SIZE } from 'src/constants'; import { OnJob } from 'src/decorators'; import { mapAsset } from 'src/dtos/asset-response.dto'; import { AuthDto } from 'src/dtos/auth.dto'; import { DuplicateResponseDto } from 'src/dtos/duplicate.dto'; import { AssetEntity } from 'src/entities/asset.entity'; -import { JOBS_ASSET_PAGINATION_SIZE, JobName, JobOf, JobStatus, QueueName } from 'src/interfaces/job.interface'; +import { JobName, JobStatus, QueueName } from 'src/enum'; import { WithoutProperty } from 'src/repositories/asset.repository'; import { AssetDuplicateResult } from 'src/repositories/search.repository'; import { BaseService } from 'src/services/base.service'; +import { JobOf } from 'src/types'; import { getAssetFiles } from 'src/utils/asset.util'; import { isDuplicateDetectionEnabled } from 'src/utils/misc'; import { usePagination } from 'src/utils/pagination'; diff --git a/server/src/services/job.service.spec.ts b/server/src/services/job.service.spec.ts index 8b0b5c408c55d..6797ffc396e23 100644 --- a/server/src/services/job.service.spec.ts +++ b/server/src/services/job.service.spec.ts @@ -1,8 +1,8 @@ import { BadRequestException } from '@nestjs/common'; import { defaults, SystemConfig } from 'src/config'; -import { ImmichWorker } from 'src/enum'; -import { JobCommand, JobItem, JobName, JobStatus, QueueName } from 'src/interfaces/job.interface'; +import { ImmichWorker, JobCommand, JobName, JobStatus, QueueName } from 'src/enum'; import { JobService } from 'src/services/job.service'; +import { JobItem } from 'src/types'; import { assetStub } from 'test/fixtures/asset.stub'; import { newTestService, ServiceMocks } from 'test/utils'; diff --git a/server/src/services/job.service.ts b/server/src/services/job.service.ts index 00d9a398fdc9c..8e3919a2b1a6e 100644 --- a/server/src/services/job.service.ts +++ b/server/src/services/job.service.ts @@ -3,18 +3,19 @@ import { snakeCase } from 'lodash'; import { OnEvent } from 'src/decorators'; import { mapAsset } from 'src/dtos/asset-response.dto'; import { AllJobStatusResponseDto, JobCommandDto, JobCreateDto, JobStatusDto } from 'src/dtos/job.dto'; -import { AssetType, ImmichWorker, ManualJobName } from 'src/enum'; import { - ConcurrentQueueName, + AssetType, + ImmichWorker, JobCommand, - JobItem, JobName, JobStatus, + ManualJobName, QueueCleanType, QueueName, -} from 'src/interfaces/job.interface'; +} from 'src/enum'; import { ArgOf, ArgsOf } from 'src/repositories/event.repository'; import { BaseService } from 'src/services/base.service'; +import { ConcurrentQueueName, JobItem } from 'src/types'; const asJobItem = (dto: JobCreateDto): JobItem => { switch (dto.name) { diff --git a/server/src/services/library.service.spec.ts b/server/src/services/library.service.spec.ts index 24b1265ae9667..ded7e0630a4ee 100644 --- a/server/src/services/library.service.spec.ts +++ b/server/src/services/library.service.spec.ts @@ -1,17 +1,12 @@ import { BadRequestException } from '@nestjs/common'; import { Stats } from 'node:fs'; import { defaults, SystemConfig } from 'src/config'; +import { JOBS_LIBRARY_PAGINATION_SIZE } from 'src/constants'; import { mapLibrary } from 'src/dtos/library.dto'; import { UserEntity } from 'src/entities/user.entity'; -import { AssetType, ImmichWorker } from 'src/enum'; -import { - ILibraryAssetJob, - ILibraryFileJob, - JobName, - JOBS_LIBRARY_PAGINATION_SIZE, - JobStatus, -} from 'src/interfaces/job.interface'; +import { AssetType, ImmichWorker, JobName, JobStatus } from 'src/enum'; import { LibraryService } from 'src/services/library.service'; +import { ILibraryAssetJob, ILibraryFileJob } from 'src/types'; import { assetStub } from 'test/fixtures/asset.stub'; import { authStub } from 'test/fixtures/auth.stub'; import { libraryStub } from 'test/fixtures/library.stub'; diff --git a/server/src/services/library.service.ts b/server/src/services/library.service.ts index fb748276565c6..4a9614e010237 100644 --- a/server/src/services/library.service.ts +++ b/server/src/services/library.service.ts @@ -2,6 +2,7 @@ import { BadRequestException, Injectable } from '@nestjs/common'; import { R_OK } from 'node:constants'; import path, { basename, isAbsolute, parse } from 'node:path'; import picomatch from 'picomatch'; +import { JOBS_LIBRARY_PAGINATION_SIZE } from 'src/constants'; import { StorageCore } from 'src/cores/storage.core'; import { OnEvent, OnJob } from 'src/decorators'; import { @@ -16,11 +17,10 @@ import { } from 'src/dtos/library.dto'; import { AssetEntity } from 'src/entities/asset.entity'; import { LibraryEntity } from 'src/entities/library.entity'; -import { AssetType, ImmichWorker } from 'src/enum'; -import { JobName, JobOf, JOBS_LIBRARY_PAGINATION_SIZE, JobStatus, QueueName } from 'src/interfaces/job.interface'; -import { DatabaseLock } from 'src/repositories/database.repository'; +import { AssetType, DatabaseLock, ImmichWorker, JobName, JobStatus, QueueName } from 'src/enum'; import { ArgOf } from 'src/repositories/event.repository'; import { BaseService } from 'src/services/base.service'; +import { JobOf } from 'src/types'; import { mimeTypes } from 'src/utils/mime-types'; import { handlePromiseError } from 'src/utils/misc'; import { usePagination } from 'src/utils/pagination'; diff --git a/server/src/services/map.service.ts b/server/src/services/map.service.ts index 860a782e79a0b..94eca77a60447 100644 --- a/server/src/services/map.service.ts +++ b/server/src/services/map.service.ts @@ -1,8 +1,10 @@ +import { Injectable } from '@nestjs/common'; import { AuthDto } from 'src/dtos/auth.dto'; import { MapMarkerDto, MapMarkerResponseDto, MapReverseGeocodeDto } from 'src/dtos/map.dto'; import { BaseService } from 'src/services/base.service'; import { getMyPartnerIds } from 'src/utils/asset.util'; +@Injectable() export class MapService extends BaseService { async getMapMarkers(auth: AuthDto, options: MapMarkerDto): Promise { const userIds = [auth.user.id]; diff --git a/server/src/services/media.service.spec.ts b/server/src/services/media.service.spec.ts index 52ccab1c9194c..d98cff866fc4d 100644 --- a/server/src/services/media.service.spec.ts +++ b/server/src/services/media.service.spec.ts @@ -9,14 +9,15 @@ import { AudioCodec, Colorspace, ImageFormat, + JobName, + JobStatus, TranscodeHWAccel, TranscodePolicy, VideoCodec, } from 'src/enum'; -import { JobCounts, JobName, JobStatus } from 'src/interfaces/job.interface'; import { WithoutProperty } from 'src/repositories/asset.repository'; import { MediaService } from 'src/services/media.service'; -import { RawImageInfo } from 'src/types'; +import { JobCounts, RawImageInfo } from 'src/types'; import { assetStub } from 'test/fixtures/asset.stub'; import { faceStub } from 'test/fixtures/face.stub'; import { probeStub } from 'test/fixtures/media.stub'; diff --git a/server/src/services/media.service.ts b/server/src/services/media.service.ts index 58621c1b196d5..54540dff66531 100644 --- a/server/src/services/media.service.ts +++ b/server/src/services/media.service.ts @@ -1,5 +1,6 @@ import { Injectable } from '@nestjs/common'; import { dirname } from 'node:path'; +import { JOBS_ASSET_PAGINATION_SIZE } from 'src/constants'; import { StorageCore } from 'src/cores/storage.core'; import { OnEvent, OnJob } from 'src/decorators'; import { SystemConfigFFmpegDto } from 'src/dtos/system-config.dto'; @@ -10,7 +11,10 @@ import { AssetType, AudioCodec, Colorspace, + JobName, + JobStatus, LogLevel, + QueueName, StorageFolder, TranscodeHWAccel, TranscodePolicy, @@ -18,17 +22,9 @@ import { VideoCodec, VideoContainer, } from 'src/enum'; -import { - JOBS_ASSET_PAGINATION_SIZE, - JobItem, - JobName, - JobOf, - JobStatus, - QueueName, -} from 'src/interfaces/job.interface'; import { UpsertFileOptions, WithoutProperty } from 'src/repositories/asset.repository'; import { BaseService } from 'src/services/base.service'; -import { AudioStreamInfo, VideoFormat, VideoInterfaces, VideoStreamInfo } from 'src/types'; +import { AudioStreamInfo, JobItem, JobOf, VideoFormat, VideoInterfaces, VideoStreamInfo } from 'src/types'; import { getAssetFiles } from 'src/utils/asset.util'; import { BaseConfig, ThumbnailConfig } from 'src/utils/media'; import { mimeTypes } from 'src/utils/mime-types'; diff --git a/server/src/services/metadata.service.spec.ts b/server/src/services/metadata.service.spec.ts index c7c675ab3ecb2..0e0c6546ca481 100644 --- a/server/src/services/metadata.service.spec.ts +++ b/server/src/services/metadata.service.spec.ts @@ -4,8 +4,7 @@ import { Stats } from 'node:fs'; import { constants } from 'node:fs/promises'; import { AssetEntity } from 'src/entities/asset.entity'; import { ExifEntity } from 'src/entities/exif.entity'; -import { AssetType, ExifOrientation, ImmichWorker, SourceType } from 'src/enum'; -import { JobName, JobStatus } from 'src/interfaces/job.interface'; +import { AssetType, ExifOrientation, ImmichWorker, JobName, JobStatus, SourceType } from 'src/enum'; import { WithoutProperty } from 'src/repositories/asset.repository'; import { ImmichTags } from 'src/repositories/metadata.repository'; import { MetadataService } from 'src/services/metadata.service'; diff --git a/server/src/services/metadata.service.ts b/server/src/services/metadata.service.ts index 33db5d3149450..8c2e3646a0243 100644 --- a/server/src/services/metadata.service.ts +++ b/server/src/services/metadata.service.ts @@ -7,20 +7,29 @@ import { Duration } from 'luxon'; import { constants } from 'node:fs/promises'; import path from 'node:path'; import { SystemConfig } from 'src/config'; +import { JOBS_ASSET_PAGINATION_SIZE } from 'src/constants'; import { StorageCore } from 'src/cores/storage.core'; import { Exif } from 'src/db'; import { OnEvent, OnJob } from 'src/decorators'; import { AssetFaceEntity } from 'src/entities/asset-face.entity'; import { AssetEntity } from 'src/entities/asset.entity'; import { PersonEntity } from 'src/entities/person.entity'; -import { AssetType, ExifOrientation, ImmichWorker, SourceType } from 'src/enum'; -import { JobName, JobOf, JOBS_ASSET_PAGINATION_SIZE, JobStatus, QueueName } from 'src/interfaces/job.interface'; +import { + AssetType, + DatabaseLock, + ExifOrientation, + ImmichWorker, + JobName, + JobStatus, + QueueName, + SourceType, +} from 'src/enum'; import { WithoutProperty } from 'src/repositories/asset.repository'; -import { DatabaseLock } from 'src/repositories/database.repository'; import { ArgOf } from 'src/repositories/event.repository'; import { ReverseGeocodeResult } from 'src/repositories/map.repository'; import { ImmichTags } from 'src/repositories/metadata.repository'; import { BaseService } from 'src/services/base.service'; +import { JobOf } from 'src/types'; import { isFaceImportEnabled } from 'src/utils/misc'; import { usePagination } from 'src/utils/pagination'; import { upsertTags } from 'src/utils/tag'; diff --git a/server/src/services/notification.service.spec.ts b/server/src/services/notification.service.spec.ts index 35f1601c728d6..038ab1180c8b7 100644 --- a/server/src/services/notification.service.spec.ts +++ b/server/src/services/notification.service.spec.ts @@ -3,10 +3,10 @@ import { defaults, SystemConfig } from 'src/config'; import { SystemConfigDto } from 'src/dtos/system-config.dto'; import { AlbumUserEntity } from 'src/entities/album-user.entity'; import { AssetFileEntity } from 'src/entities/asset-files.entity'; -import { AssetFileType, UserMetadataKey } from 'src/enum'; -import { INotifyAlbumUpdateJob, JobName, JobStatus } from 'src/interfaces/job.interface'; +import { AssetFileType, JobName, JobStatus, UserMetadataKey } from 'src/enum'; import { EmailTemplate } from 'src/repositories/notification.repository'; import { NotificationService } from 'src/services/notification.service'; +import { INotifyAlbumUpdateJob } from 'src/types'; import { albumStub } from 'test/fixtures/album.stub'; import { assetStub } from 'test/fixtures/asset.stub'; import { userStub } from 'test/fixtures/user.stub'; diff --git a/server/src/services/notification.service.ts b/server/src/services/notification.service.ts index f9a2194088651..003b320997d95 100644 --- a/server/src/services/notification.service.ts +++ b/server/src/services/notification.service.ts @@ -2,18 +2,11 @@ import { BadRequestException, Injectable } from '@nestjs/common'; import { OnEvent, OnJob } from 'src/decorators'; import { SystemConfigSmtpDto } from 'src/dtos/system-config.dto'; import { AlbumEntity } from 'src/entities/album.entity'; -import { - IEntityJob, - INotifyAlbumUpdateJob, - JobItem, - JobName, - JobOf, - JobStatus, - QueueName, -} from 'src/interfaces/job.interface'; +import { JobName, JobStatus, QueueName } from 'src/enum'; import { ArgOf } from 'src/repositories/event.repository'; -import { EmailImageAttachment, EmailTemplate } from 'src/repositories/notification.repository'; +import { EmailTemplate } from 'src/repositories/notification.repository'; import { BaseService } from 'src/services/base.service'; +import { EmailImageAttachment, IEntityJob, INotifyAlbumUpdateJob, JobItem, JobOf } from 'src/types'; import { getAssetFiles } from 'src/utils/asset.util'; import { getFilenameExtension } from 'src/utils/file'; import { getExternalDomain } from 'src/utils/misc'; diff --git a/server/src/services/person.service.spec.ts b/server/src/services/person.service.spec.ts index 8e1cff302fdc9..ba327ddae9a52 100644 --- a/server/src/services/person.service.spec.ts +++ b/server/src/services/person.service.spec.ts @@ -2,8 +2,7 @@ import { BadRequestException, NotFoundException } from '@nestjs/common'; import { BulkIdErrorReason } from 'src/dtos/asset-ids.response.dto'; import { mapFaces, mapPerson, PersonResponseDto } from 'src/dtos/person.dto'; import { AssetFaceEntity } from 'src/entities/asset-face.entity'; -import { CacheControl, Colorspace, ImageFormat, SourceType, SystemMetadataKey } from 'src/enum'; -import { JobName, JobStatus } from 'src/interfaces/job.interface'; +import { CacheControl, Colorspace, ImageFormat, JobName, JobStatus, SourceType, SystemMetadataKey } from 'src/enum'; import { WithoutProperty } from 'src/repositories/asset.repository'; import { DetectedFaces } from 'src/repositories/machine-learning.repository'; import { FaceSearchResult } from 'src/repositories/search.repository'; diff --git a/server/src/services/person.service.ts b/server/src/services/person.service.ts index e9933b421cb16..ecb8677f716db 100644 --- a/server/src/services/person.service.ts +++ b/server/src/services/person.service.ts @@ -1,5 +1,5 @@ import { BadRequestException, Injectable, NotFoundException } from '@nestjs/common'; -import { FACE_THUMBNAIL_SIZE } from 'src/constants'; +import { FACE_THUMBNAIL_SIZE, JOBS_ASSET_PAGINATION_SIZE } from 'src/constants'; import { StorageCore } from 'src/cores/storage.core'; import { OnJob } from 'src/decorators'; import { BulkIdErrorReason, BulkIdResponseDto } from 'src/dtos/asset-ids.response.dto'; @@ -27,24 +27,19 @@ import { AssetType, CacheControl, ImageFormat, + JobName, + JobStatus, Permission, PersonPathType, + QueueName, SourceType, SystemMetadataKey, } from 'src/enum'; -import { - JOBS_ASSET_PAGINATION_SIZE, - JobItem, - JobName, - JobOf, - JobStatus, - QueueName, -} from 'src/interfaces/job.interface'; import { WithoutProperty } from 'src/repositories/asset.repository'; import { BoundingBox } from 'src/repositories/machine-learning.repository'; import { UpdateFacesData } from 'src/repositories/person.repository'; import { BaseService } from 'src/services/base.service'; -import { CropOptions, ImageDimensions, InputDimensions } from 'src/types'; +import { CropOptions, ImageDimensions, InputDimensions, JobItem, JobOf } from 'src/types'; import { getAssetFiles } from 'src/utils/asset.util'; import { ImmichFileResponse } from 'src/utils/file'; import { mimeTypes } from 'src/utils/mime-types'; diff --git a/server/src/services/session.service.spec.ts b/server/src/services/session.service.spec.ts index c25c0feb82215..8c22abb7f0c8c 100644 --- a/server/src/services/session.service.spec.ts +++ b/server/src/services/session.service.spec.ts @@ -1,4 +1,4 @@ -import { JobStatus } from 'src/interfaces/job.interface'; +import { JobStatus } from 'src/enum'; import { SessionService } from 'src/services/session.service'; import { authStub } from 'test/fixtures/auth.stub'; import { sessionStub } from 'test/fixtures/session.stub'; diff --git a/server/src/services/session.service.ts b/server/src/services/session.service.ts index 68df7828ad784..6b0632cd447fc 100644 --- a/server/src/services/session.service.ts +++ b/server/src/services/session.service.ts @@ -3,8 +3,7 @@ import { DateTime } from 'luxon'; import { OnJob } from 'src/decorators'; import { AuthDto } from 'src/dtos/auth.dto'; import { SessionResponseDto, mapSession } from 'src/dtos/session.dto'; -import { Permission } from 'src/enum'; -import { JobName, JobStatus, QueueName } from 'src/interfaces/job.interface'; +import { JobName, JobStatus, Permission, QueueName } from 'src/enum'; import { BaseService } from 'src/services/base.service'; @Injectable() diff --git a/server/src/services/smart-info.service.spec.ts b/server/src/services/smart-info.service.spec.ts index 403c6e9a6a65b..aef83a813d560 100644 --- a/server/src/services/smart-info.service.spec.ts +++ b/server/src/services/smart-info.service.spec.ts @@ -1,6 +1,5 @@ import { SystemConfig } from 'src/config'; -import { ImmichWorker } from 'src/enum'; -import { JobName, JobStatus } from 'src/interfaces/job.interface'; +import { ImmichWorker, JobName, JobStatus } from 'src/enum'; import { WithoutProperty } from 'src/repositories/asset.repository'; import { SmartInfoService } from 'src/services/smart-info.service'; import { getCLIPModelInfo } from 'src/utils/misc'; diff --git a/server/src/services/smart-info.service.ts b/server/src/services/smart-info.service.ts index 0a03c27a55949..063bb0bd3b79f 100644 --- a/server/src/services/smart-info.service.ts +++ b/server/src/services/smart-info.service.ts @@ -1,12 +1,12 @@ import { Injectable } from '@nestjs/common'; import { SystemConfig } from 'src/config'; +import { JOBS_ASSET_PAGINATION_SIZE } from 'src/constants'; import { OnEvent, OnJob } from 'src/decorators'; -import { ImmichWorker } from 'src/enum'; -import { JOBS_ASSET_PAGINATION_SIZE, JobName, JobOf, JobStatus, QueueName } from 'src/interfaces/job.interface'; +import { DatabaseLock, ImmichWorker, JobName, JobStatus, QueueName } from 'src/enum'; import { WithoutProperty } from 'src/repositories/asset.repository'; -import { DatabaseLock } from 'src/repositories/database.repository'; import { ArgOf } from 'src/repositories/event.repository'; import { BaseService } from 'src/services/base.service'; +import { JobOf } from 'src/types'; import { getAssetFiles } from 'src/utils/asset.util'; import { getCLIPModelInfo, isSmartSearchEnabled } from 'src/utils/misc'; import { usePagination } from 'src/utils/pagination'; diff --git a/server/src/services/storage-template.service.spec.ts b/server/src/services/storage-template.service.spec.ts index cf272c7e5f261..0a055d0e6d6ae 100644 --- a/server/src/services/storage-template.service.spec.ts +++ b/server/src/services/storage-template.service.spec.ts @@ -1,8 +1,7 @@ import { Stats } from 'node:fs'; import { defaults, SystemConfig } from 'src/config'; import { AssetEntity } from 'src/entities/asset.entity'; -import { AssetPathType } from 'src/enum'; -import { JobStatus } from 'src/interfaces/job.interface'; +import { AssetPathType, JobStatus } from 'src/enum'; import { StorageTemplateService } from 'src/services/storage-template.service'; import { albumStub } from 'test/fixtures/album.stub'; import { assetStub } from 'test/fixtures/asset.stub'; diff --git a/server/src/services/storage-template.service.ts b/server/src/services/storage-template.service.ts index 6fd139c10d1e4..24a9fcd4594a5 100644 --- a/server/src/services/storage-template.service.ts +++ b/server/src/services/storage-template.service.ts @@ -3,15 +3,15 @@ import handlebar from 'handlebars'; import { DateTime } from 'luxon'; import path from 'node:path'; import sanitize from 'sanitize-filename'; +import { JOBS_ASSET_PAGINATION_SIZE } from 'src/constants'; import { StorageCore } from 'src/cores/storage.core'; import { OnEvent, OnJob } from 'src/decorators'; import { SystemConfigTemplateStorageOptionDto } from 'src/dtos/system-config.dto'; import { AssetEntity } from 'src/entities/asset.entity'; -import { AssetPathType, AssetType, StorageFolder } from 'src/enum'; -import { JobName, JobOf, JOBS_ASSET_PAGINATION_SIZE, JobStatus, QueueName } from 'src/interfaces/job.interface'; -import { DatabaseLock } from 'src/repositories/database.repository'; +import { AssetPathType, AssetType, DatabaseLock, JobName, JobStatus, QueueName, StorageFolder } from 'src/enum'; import { ArgOf } from 'src/repositories/event.repository'; import { BaseService } from 'src/services/base.service'; +import { JobOf } from 'src/types'; import { getLivePhotoMotionFilename } from 'src/utils/file'; import { usePagination } from 'src/utils/pagination'; diff --git a/server/src/services/storage.service.ts b/server/src/services/storage.service.ts index 6921d3356055a..c0c7a00ae7931 100644 --- a/server/src/services/storage.service.ts +++ b/server/src/services/storage.service.ts @@ -3,10 +3,9 @@ import { join } from 'node:path'; import { StorageCore } from 'src/cores/storage.core'; import { OnEvent, OnJob } from 'src/decorators'; import { SystemFlags } from 'src/entities/system-metadata.entity'; -import { StorageFolder, SystemMetadataKey } from 'src/enum'; -import { JobName, JobOf, JobStatus, QueueName } from 'src/interfaces/job.interface'; -import { DatabaseLock } from 'src/repositories/database.repository'; +import { DatabaseLock, JobName, JobStatus, QueueName, StorageFolder, SystemMetadataKey } from 'src/enum'; import { BaseService } from 'src/services/base.service'; +import { JobOf } from 'src/types'; import { ImmichStartupError } from 'src/utils/misc'; const docsMessage = `Please see https://immich.app/docs/administration/system-integrity#folder-checks for more information.`; diff --git a/server/src/services/sync.service.ts b/server/src/services/sync.service.ts index f85200db489fa..fe967e37e07b3 100644 --- a/server/src/services/sync.service.ts +++ b/server/src/services/sync.service.ts @@ -1,3 +1,4 @@ +import { Injectable } from '@nestjs/common'; import { DateTime } from 'luxon'; import { AUDIT_LOG_MAX_DURATION } from 'src/constants'; import { AssetResponseDto, mapAsset } from 'src/dtos/asset-response.dto'; @@ -10,6 +11,7 @@ import { setIsEqual } from 'src/utils/set'; const FULL_SYNC = { needsFullSync: true, deleted: [], upserted: [] }; +@Injectable() export class SyncService extends BaseService { async getFullSync(auth: AuthDto, dto: AssetFullSyncDto): Promise { // mobile implementation is faster if this is a single id diff --git a/server/src/services/system-config.service.spec.ts b/server/src/services/system-config.service.spec.ts index 027bcc1c157ba..8a06a883c2c82 100644 --- a/server/src/services/system-config.service.spec.ts +++ b/server/src/services/system-config.service.spec.ts @@ -6,13 +6,13 @@ import { CQMode, ImageFormat, LogLevel, + QueueName, ToneMapping, TranscodeHWAccel, TranscodePolicy, VideoCodec, VideoContainer, } from 'src/enum'; -import { QueueName } from 'src/interfaces/job.interface'; import { SystemConfigService } from 'src/services/system-config.service'; import { DeepPartial } from 'src/types'; import { mockEnvData } from 'test/repositories/config.repository.mock'; diff --git a/server/src/services/system-config.service.ts b/server/src/services/system-config.service.ts index cc32ef0c341d6..2dd8dcf0ee544 100644 --- a/server/src/services/system-config.service.ts +++ b/server/src/services/system-config.service.ts @@ -3,7 +3,7 @@ import { instanceToPlain } from 'class-transformer'; import _ from 'lodash'; import { defaults } from 'src/config'; import { OnEvent } from 'src/decorators'; -import { SystemConfigDto, mapConfig } from 'src/dtos/system-config.dto'; +import { mapConfig, SystemConfigDto } from 'src/dtos/system-config.dto'; import { BootstrapEventPriority } from 'src/enum'; import { ArgOf } from 'src/repositories/event.repository'; import { BaseService } from 'src/services/base.service'; diff --git a/server/src/services/tag.service.spec.ts b/server/src/services/tag.service.spec.ts index 48d1b0037994c..f1385eb8c8b09 100644 --- a/server/src/services/tag.service.spec.ts +++ b/server/src/services/tag.service.spec.ts @@ -1,6 +1,6 @@ import { BadRequestException } from '@nestjs/common'; import { BulkIdErrorReason } from 'src/dtos/asset-ids.response.dto'; -import { JobStatus } from 'src/interfaces/job.interface'; +import { JobStatus } from 'src/enum'; import { TagService } from 'src/services/tag.service'; import { authStub } from 'test/fixtures/auth.stub'; import { tagResponseStub, tagStub } from 'test/fixtures/tag.stub'; diff --git a/server/src/services/tag.service.ts b/server/src/services/tag.service.ts index 83d4b40340b3d..c241f59a80c10 100644 --- a/server/src/services/tag.service.ts +++ b/server/src/services/tag.service.ts @@ -12,8 +12,7 @@ import { mapTag, } from 'src/dtos/tag.dto'; import { TagEntity } from 'src/entities/tag.entity'; -import { Permission } from 'src/enum'; -import { JobName, JobStatus, QueueName } from 'src/interfaces/job.interface'; +import { JobName, JobStatus, Permission, QueueName } from 'src/enum'; import { AssetTagItem } from 'src/repositories/tag.repository'; import { BaseService } from 'src/services/base.service'; import { addAssets, removeAssets } from 'src/utils/asset.util'; diff --git a/server/src/services/timeline.service.ts b/server/src/services/timeline.service.ts index bc4c7fad734ac..4c2332afaa306 100644 --- a/server/src/services/timeline.service.ts +++ b/server/src/services/timeline.service.ts @@ -1,4 +1,4 @@ -import { BadRequestException } from '@nestjs/common'; +import { BadRequestException, Injectable } from '@nestjs/common'; import { AssetResponseDto, SanitizedAssetResponseDto, mapAsset } from 'src/dtos/asset-response.dto'; import { AuthDto } from 'src/dtos/auth.dto'; import { TimeBucketAssetDto, TimeBucketDto, TimeBucketResponseDto } from 'src/dtos/time-bucket.dto'; @@ -7,6 +7,7 @@ import { TimeBucketOptions } from 'src/repositories/asset.repository'; import { BaseService } from 'src/services/base.service'; import { getMyPartnerIds } from 'src/utils/asset.util'; +@Injectable() export class TimelineService extends BaseService { async getTimeBuckets(auth: AuthDto, dto: TimeBucketDto): Promise { await this.timeBucketChecks(auth, dto); diff --git a/server/src/services/trash.service.spec.ts b/server/src/services/trash.service.spec.ts index 536fb65f9a68b..e7eccd374cb13 100644 --- a/server/src/services/trash.service.spec.ts +++ b/server/src/services/trash.service.spec.ts @@ -1,5 +1,5 @@ import { BadRequestException } from '@nestjs/common'; -import { JobName, JobStatus } from 'src/interfaces/job.interface'; +import { JobName, JobStatus } from 'src/enum'; import { TrashService } from 'src/services/trash.service'; import { authStub } from 'test/fixtures/auth.stub'; import { newTestService, ServiceMocks } from 'test/utils'; diff --git a/server/src/services/trash.service.ts b/server/src/services/trash.service.ts index d66461ef94b0b..f33b24982360e 100644 --- a/server/src/services/trash.service.ts +++ b/server/src/services/trash.service.ts @@ -1,11 +1,13 @@ +import { Injectable } from '@nestjs/common'; +import { JOBS_ASSET_PAGINATION_SIZE } from 'src/constants'; import { OnEvent, OnJob } from 'src/decorators'; import { BulkIdsDto } from 'src/dtos/asset-ids.response.dto'; import { AuthDto } from 'src/dtos/auth.dto'; import { TrashResponseDto } from 'src/dtos/trash.dto'; -import { Permission } from 'src/enum'; -import { JOBS_ASSET_PAGINATION_SIZE, JobName, JobStatus, QueueName } from 'src/interfaces/job.interface'; +import { JobName, JobStatus, Permission, QueueName } from 'src/enum'; import { BaseService } from 'src/services/base.service'; +@Injectable() export class TrashService extends BaseService { async restoreAssets(auth: AuthDto, dto: BulkIdsDto): Promise { const { ids } = dto; diff --git a/server/src/services/user-admin.service.spec.ts b/server/src/services/user-admin.service.spec.ts index 604062c97adb5..3e613bc485c74 100644 --- a/server/src/services/user-admin.service.spec.ts +++ b/server/src/services/user-admin.service.spec.ts @@ -1,7 +1,6 @@ import { BadRequestException, ForbiddenException } from '@nestjs/common'; import { mapUserAdmin } from 'src/dtos/user.dto'; -import { UserStatus } from 'src/enum'; -import { JobName } from 'src/interfaces/job.interface'; +import { JobName, UserStatus } from 'src/enum'; import { UserAdminService } from 'src/services/user-admin.service'; import { authStub } from 'test/fixtures/auth.stub'; import { userStub } from 'test/fixtures/user.stub'; diff --git a/server/src/services/user-admin.service.ts b/server/src/services/user-admin.service.ts index 3df9a218f334a..37c3c1e004bd4 100644 --- a/server/src/services/user-admin.service.ts +++ b/server/src/services/user-admin.service.ts @@ -10,8 +10,7 @@ import { UserAdminUpdateDto, mapUserAdmin, } from 'src/dtos/user.dto'; -import { UserMetadataKey, UserStatus } from 'src/enum'; -import { JobName } from 'src/interfaces/job.interface'; +import { JobName, UserMetadataKey, UserStatus } from 'src/enum'; import { UserFindOptions } from 'src/repositories/user.repository'; import { BaseService } from 'src/services/base.service'; import { getPreferences, getPreferencesPartial, mergePreferences } from 'src/utils/preferences'; diff --git a/server/src/services/user.service.spec.ts b/server/src/services/user.service.spec.ts index 8762c7c766f32..06c928da149d2 100644 --- a/server/src/services/user.service.spec.ts +++ b/server/src/services/user.service.spec.ts @@ -1,7 +1,6 @@ import { BadRequestException, InternalServerErrorException, NotFoundException } from '@nestjs/common'; import { UserEntity } from 'src/entities/user.entity'; -import { CacheControl, UserMetadataKey } from 'src/enum'; -import { JobName } from 'src/interfaces/job.interface'; +import { CacheControl, JobName, UserMetadataKey } from 'src/enum'; import { UserService } from 'src/services/user.service'; import { ImmichFileResponse } from 'src/utils/file'; import { authStub } from 'test/fixtures/auth.stub'; diff --git a/server/src/services/user.service.ts b/server/src/services/user.service.ts index dfd9c7715f8c2..3ec6281009e13 100644 --- a/server/src/services/user.service.ts +++ b/server/src/services/user.service.ts @@ -10,10 +10,10 @@ import { CreateProfileImageResponseDto } from 'src/dtos/user-profile.dto'; import { UserAdminResponseDto, UserResponseDto, UserUpdateMeDto, mapUser, mapUserAdmin } from 'src/dtos/user.dto'; import { UserMetadataEntity } from 'src/entities/user-metadata.entity'; import { UserEntity } from 'src/entities/user.entity'; -import { CacheControl, StorageFolder, UserMetadataKey } from 'src/enum'; -import { JobName, JobOf, JobStatus, QueueName } from 'src/interfaces/job.interface'; +import { CacheControl, JobName, JobStatus, QueueName, StorageFolder, UserMetadataKey } from 'src/enum'; import { UserFindOptions } from 'src/repositories/user.repository'; import { BaseService } from 'src/services/base.service'; +import { JobOf } from 'src/types'; import { ImmichFileResponse } from 'src/utils/file'; import { getPreferences, getPreferencesPartial, mergePreferences } from 'src/utils/preferences'; diff --git a/server/src/services/version.service.spec.ts b/server/src/services/version.service.spec.ts index 32378c52df53f..500478e9e724e 100644 --- a/server/src/services/version.service.spec.ts +++ b/server/src/services/version.service.spec.ts @@ -1,8 +1,7 @@ import { DateTime } from 'luxon'; import { SemVer } from 'semver'; import { serverVersion } from 'src/constants'; -import { ImmichEnvironment, SystemMetadataKey } from 'src/enum'; -import { JobName, JobStatus } from 'src/interfaces/job.interface'; +import { ImmichEnvironment, JobName, JobStatus, SystemMetadataKey } from 'src/enum'; import { VersionService } from 'src/services/version.service'; import { mockEnvData } from 'test/repositories/config.repository.mock'; import { newTestService, ServiceMocks } from 'test/utils'; diff --git a/server/src/services/version.service.ts b/server/src/services/version.service.ts index 9679ac4b4b6c0..c5240b82c1b73 100644 --- a/server/src/services/version.service.ts +++ b/server/src/services/version.service.ts @@ -5,9 +5,7 @@ import { serverVersion } from 'src/constants'; import { OnEvent, OnJob } from 'src/decorators'; import { ReleaseNotification, ServerVersionResponseDto } from 'src/dtos/server.dto'; import { VersionCheckMetadata } from 'src/entities/system-metadata.entity'; -import { ImmichEnvironment, SystemMetadataKey } from 'src/enum'; -import { JobName, JobStatus, QueueName } from 'src/interfaces/job.interface'; -import { DatabaseLock } from 'src/repositories/database.repository'; +import { DatabaseLock, ImmichEnvironment, JobName, JobStatus, QueueName, SystemMetadataKey } from 'src/enum'; import { ArgOf } from 'src/repositories/event.repository'; import { BaseService } from 'src/services/base.service'; diff --git a/server/src/services/view.service.ts b/server/src/services/view.service.ts index f1ef40a810213..5871b04b32f54 100644 --- a/server/src/services/view.service.ts +++ b/server/src/services/view.service.ts @@ -1,8 +1,10 @@ +import { Injectable } from '@nestjs/common'; import { AssetResponseDto, mapAsset } from 'src/dtos/asset-response.dto'; import { AuthDto } from 'src/dtos/auth.dto'; import { AssetEntity } from 'src/entities/asset.entity'; import { BaseService } from 'src/services/base.service'; +@Injectable() export class ViewService extends BaseService { getUniqueOriginalPaths(auth: AuthDto): Promise { return this.viewRepository.getUniqueOriginalPaths(auth.user.id); diff --git a/server/src/types.ts b/server/src/types.ts index e0523333d8bba..47a6d207978a3 100644 --- a/server/src/types.ts +++ b/server/src/types.ts @@ -1,5 +1,14 @@ import { UserEntity } from 'src/entities/user.entity'; -import { ExifOrientation, ImageFormat, Permission, TranscodeTarget, VideoCodec } from 'src/enum'; +import { + DatabaseExtension, + ExifOrientation, + ImageFormat, + JobName, + Permission, + QueueName, + TranscodeTarget, + VideoCodec, +} from 'src/enum'; import { ActivityRepository } from 'src/repositories/activity.repository'; import { ApiKeyRepository } from 'src/repositories/api-key.repository'; import { MemoryRepository } from 'src/repositories/memory.repository'; @@ -167,3 +176,245 @@ export interface VideoInterfaces { dri: string[]; mali: boolean; } + +export type ConcurrentQueueName = Exclude< + QueueName, + | QueueName.STORAGE_TEMPLATE_MIGRATION + | QueueName.FACIAL_RECOGNITION + | QueueName.DUPLICATE_DETECTION + | QueueName.BACKUP_DATABASE +>; + +export type Jobs = { [K in JobItem['name']]: (JobItem & { name: K })['data'] }; +export type JobOf = Jobs[T]; + +export interface IBaseJob { + force?: boolean; +} + +export interface IDelayedJob extends IBaseJob { + /** The minimum time to wait to execute this job, in milliseconds. */ + delay?: number; +} + +export interface IEntityJob extends IBaseJob { + id: string; + source?: 'upload' | 'sidecar-write' | 'copy'; + notify?: boolean; +} + +export interface IAssetDeleteJob extends IEntityJob { + deleteOnDisk: boolean; +} + +export interface ILibraryFileJob extends IEntityJob { + ownerId: string; + assetPath: string; +} + +export interface ILibraryAssetJob extends IEntityJob { + importPaths: string[]; + exclusionPatterns: string[]; +} + +export interface IBulkEntityJob extends IBaseJob { + ids: string[]; +} + +export interface IDeleteFilesJob extends IBaseJob { + files: Array; +} + +export interface ISidecarWriteJob extends IEntityJob { + description?: string; + dateTimeOriginal?: string; + latitude?: number; + longitude?: number; + rating?: number; + tags?: true; +} + +export interface IDeferrableJob extends IEntityJob { + deferred?: boolean; +} + +export interface INightlyJob extends IBaseJob { + nightly?: boolean; +} + +export type EmailImageAttachment = { + filename: string; + path: string; + cid: string; +}; + +export interface IEmailJob { + to: string; + subject: string; + html: string; + text: string; + imageAttachments?: EmailImageAttachment[]; +} + +export interface INotifySignupJob extends IEntityJob { + tempPassword?: string; +} + +export interface INotifyAlbumInviteJob extends IEntityJob { + recipientId: string; +} + +export interface INotifyAlbumUpdateJob extends IEntityJob, IDelayedJob { + recipientIds: string[]; +} + +export interface JobCounts { + active: number; + completed: number; + failed: number; + delayed: number; + waiting: number; + paused: number; +} + +export interface QueueStatus { + isActive: boolean; + isPaused: boolean; +} + +export type JobItem = + // Backups + | { name: JobName.BACKUP_DATABASE; data?: IBaseJob } + + // Transcoding + | { name: JobName.QUEUE_VIDEO_CONVERSION; data: IBaseJob } + | { name: JobName.VIDEO_CONVERSION; data: IEntityJob } + + // Thumbnails + | { name: JobName.QUEUE_GENERATE_THUMBNAILS; data: IBaseJob } + | { name: JobName.GENERATE_THUMBNAILS; data: IEntityJob } + + // User + | { name: JobName.USER_DELETE_CHECK; data?: IBaseJob } + | { name: JobName.USER_DELETION; data: IEntityJob } + | { name: JobName.USER_SYNC_USAGE; data?: IBaseJob } + + // Storage Template + | { name: JobName.STORAGE_TEMPLATE_MIGRATION; data?: IBaseJob } + | { name: JobName.STORAGE_TEMPLATE_MIGRATION_SINGLE; data: IEntityJob } + + // Migration + | { name: JobName.QUEUE_MIGRATION; data?: IBaseJob } + | { name: JobName.MIGRATE_ASSET; data: IEntityJob } + | { name: JobName.MIGRATE_PERSON; data: IEntityJob } + + // Metadata Extraction + | { name: JobName.QUEUE_METADATA_EXTRACTION; data: IBaseJob } + | { name: JobName.METADATA_EXTRACTION; data: IEntityJob } + | { name: JobName.LINK_LIVE_PHOTOS; data: IEntityJob } + // Sidecar Scanning + | { name: JobName.QUEUE_SIDECAR; data: IBaseJob } + | { name: JobName.SIDECAR_DISCOVERY; data: IEntityJob } + | { name: JobName.SIDECAR_SYNC; data: IEntityJob } + | { name: JobName.SIDECAR_WRITE; data: ISidecarWriteJob } + + // Facial Recognition + | { name: JobName.QUEUE_FACE_DETECTION; data: IBaseJob } + | { name: JobName.FACE_DETECTION; data: IEntityJob } + | { name: JobName.QUEUE_FACIAL_RECOGNITION; data: INightlyJob } + | { name: JobName.FACIAL_RECOGNITION; data: IDeferrableJob } + | { name: JobName.GENERATE_PERSON_THUMBNAIL; data: IEntityJob } + + // Smart Search + | { name: JobName.QUEUE_SMART_SEARCH; data: IBaseJob } + | { name: JobName.SMART_SEARCH; data: IEntityJob } + | { name: JobName.QUEUE_TRASH_EMPTY; data?: IBaseJob } + + // Duplicate Detection + | { name: JobName.QUEUE_DUPLICATE_DETECTION; data: IBaseJob } + | { name: JobName.DUPLICATE_DETECTION; data: IEntityJob } + + // Filesystem + | { name: JobName.DELETE_FILES; data: IDeleteFilesJob } + + // Cleanup + | { name: JobName.CLEAN_OLD_AUDIT_LOGS; data?: IBaseJob } + | { name: JobName.CLEAN_OLD_SESSION_TOKENS; data?: IBaseJob } + + // Tags + | { name: JobName.TAG_CLEANUP; data?: IBaseJob } + + // Asset Deletion + | { name: JobName.PERSON_CLEANUP; data?: IBaseJob } + | { name: JobName.ASSET_DELETION; data: IAssetDeleteJob } + | { name: JobName.ASSET_DELETION_CHECK; data?: IBaseJob } + + // Library Management + | { name: JobName.LIBRARY_SYNC_FILE; data: ILibraryFileJob } + | { name: JobName.LIBRARY_QUEUE_SYNC_FILES; data: IEntityJob } + | { name: JobName.LIBRARY_QUEUE_SYNC_ASSETS; data: IEntityJob } + | { name: JobName.LIBRARY_SYNC_ASSET; data: ILibraryAssetJob } + | { name: JobName.LIBRARY_DELETE; data: IEntityJob } + | { name: JobName.LIBRARY_QUEUE_SYNC_ALL; data?: IBaseJob } + | { name: JobName.LIBRARY_QUEUE_CLEANUP; data: IBaseJob } + + // Notification + | { name: JobName.SEND_EMAIL; data: IEmailJob } + | { name: JobName.NOTIFY_ALBUM_INVITE; data: INotifyAlbumInviteJob } + | { name: JobName.NOTIFY_ALBUM_UPDATE; data: INotifyAlbumUpdateJob } + | { name: JobName.NOTIFY_SIGNUP; data: INotifySignupJob } + + // Version check + | { name: JobName.VERSION_CHECK; data: IBaseJob }; + +export type VectorExtension = DatabaseExtension.VECTOR | DatabaseExtension.VECTORS; + +export type DatabaseConnectionURL = { + connectionType: 'url'; + url: string; +}; + +export type DatabaseConnectionParts = { + connectionType: 'parts'; + host: string; + port: number; + username: string; + password: string; + database: string; +}; + +export type DatabaseConnectionParams = DatabaseConnectionURL | DatabaseConnectionParts; + +export interface ExtensionVersion { + availableVersion: string | null; + installedVersion: string | null; +} + +export interface VectorUpdateResult { + restartRequired: boolean; +} + +export interface ImmichFile extends Express.Multer.File { + /** sha1 hash of file */ + uuid: string; + checksum: Buffer; +} + +export interface UploadFile { + uuid: string; + checksum: Buffer; + originalPath: string; + originalName: string; + size: number; +} + +export interface UploadFiles { + assetData: ImmichFile[]; + sidecarData: ImmichFile[]; +} + +export interface IBulkAsset { + getAssetIds: (id: string, assetIds: string[]) => Promise>; + addAssetIds: (id: string, assetIds: string[]) => Promise; + removeAssetIds: (id: string, assetIds: string[]) => Promise; +} diff --git a/server/src/utils/asset.util.ts b/server/src/utils/asset.util.ts index 5183bb2164e50..de64720a82a31 100644 --- a/server/src/utils/asset.util.ts +++ b/server/src/utils/asset.util.ts @@ -6,20 +6,13 @@ import { AuthDto } from 'src/dtos/auth.dto'; import { AssetFileEntity } from 'src/entities/asset-files.entity'; import { AssetFileType, AssetType, Permission } from 'src/enum'; import { AuthRequest } from 'src/middleware/auth.guard'; -import { ImmichFile } from 'src/middleware/file-upload.interceptor'; import { AccessRepository } from 'src/repositories/access.repository'; import { AssetRepository } from 'src/repositories/asset.repository'; import { EventRepository } from 'src/repositories/event.repository'; import { PartnerRepository } from 'src/repositories/partner.repository'; -import { UploadFile } from 'src/services/asset-media.service'; +import { IBulkAsset, ImmichFile, UploadFile } from 'src/types'; import { checkAccess } from 'src/utils/access'; -export interface IBulkAsset { - getAssetIds: (id: string, assetIds: string[]) => Promise>; - addAssetIds: (id: string, assetIds: string[]) => Promise; - removeAssetIds: (id: string, assetIds: string[]) => Promise; -} - const getFileByType = (files: AssetFileEntity[] | undefined, type: AssetFileType) => { return (files || []).find((file) => file.type === type); }; diff --git a/server/src/utils/config.ts b/server/src/utils/config.ts index 30f965c37f3d6..4dee1c348e45b 100644 --- a/server/src/utils/config.ts +++ b/server/src/utils/config.ts @@ -5,9 +5,8 @@ import { load as loadYaml } from 'js-yaml'; import * as _ from 'lodash'; import { SystemConfig, defaults } from 'src/config'; import { SystemConfigDto } from 'src/dtos/system-config.dto'; -import { SystemMetadataKey } from 'src/enum'; +import { DatabaseLock, SystemMetadataKey } from 'src/enum'; import { ConfigRepository } from 'src/repositories/config.repository'; -import { DatabaseLock } from 'src/repositories/database.repository'; import { LoggingRepository } from 'src/repositories/logging.repository'; import { SystemMetadataRepository } from 'src/repositories/system-metadata.repository'; import { DeepPartial } from 'src/types'; diff --git a/server/test/repositories/job.repository.mock.ts b/server/test/repositories/job.repository.mock.ts index e9557af59bae7..f0f4fdda00918 100644 --- a/server/test/repositories/job.repository.mock.ts +++ b/server/test/repositories/job.repository.mock.ts @@ -1,7 +1,8 @@ -import { IJobRepository } from 'src/interfaces/job.interface'; +import { JobRepository } from 'src/repositories/job.repository'; +import { RepositoryInterface } from 'src/types'; import { Mocked, vitest } from 'vitest'; -export const newJobRepositoryMock = (): Mocked => { +export const newJobRepositoryMock = (): Mocked> => { return { setup: vitest.fn(), startWorkers: vitest.fn(), diff --git a/server/test/utils.ts b/server/test/utils.ts index fbff7ba00ddad..d1dda3eedf5df 100644 --- a/server/test/utils.ts +++ b/server/test/utils.ts @@ -194,12 +194,12 @@ export const newTestService = ( albumMock as RepositoryInterface as AlbumRepository, albumUserMock as RepositoryInterface as AlbumUserRepository, assetMock as RepositoryInterface as AssetRepository, - configMock, + configMock as RepositoryInterface as ConfigRepository, cronMock as RepositoryInterface as CronRepository, cryptoMock as RepositoryInterface as CryptoRepository, databaseMock as RepositoryInterface as DatabaseRepository, eventMock as RepositoryInterface as EventRepository, - jobMock, + jobMock as RepositoryInterface as JobRepository, apiKeyMock as RepositoryInterface as ApiKeyRepository, libraryMock as RepositoryInterface as LibraryRepository, machineLearningMock as RepositoryInterface as MachineLearningRepository, From 703361da1a290c61fe3206dae84d0d16b2a3642d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 11 Feb 2025 17:24:39 -0600 Subject: [PATCH 5/5] chore(deps): update dependency svelte to v5.19.9 (#16043) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- web/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/web/package-lock.json b/web/package-lock.json index 276fcb7b988fe..1ac9763ffebf3 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -7338,9 +7338,9 @@ } }, "node_modules/svelte": { - "version": "5.19.8", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.19.8.tgz", - "integrity": "sha512-56Vd/nwJrljV0w7RCV1A8sB4/yjSbWW5qrGDTAzp7q42OxwqEWT+6obWzDt41tHjIW+C9Fs2ygtejjJrXR+ZPA==", + "version": "5.19.9", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.19.9.tgz", + "integrity": "sha512-860s752/ZZxHIsii31ELkdKBOCeAuDsfb/AGUXJyQyzUVLRSt4oqEw/BV5+2+mNg8mbqmD3OK+vMvwWMPM6f8A==", "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.3.0",