diff --git a/.dockerignore b/.dockerignore
index 87d63b594..f7947202c 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -1,30 +1,31 @@
.vscode/
+.github/
+.git/
design/
docker/
docs/
+e2e/
fastlane/
machine-learning/
misc/
mobile/
-server/node_modules/
+cli/coverage/
+cli/dist/
+cli/node_modules/
+
+open-api/typescript-sdk/build/
+open-api/typescript-sdk/node_modules/
+
server/coverage/
-server/.reverse-geocoding-dump/
+server/node_modules/
server/upload/
server/dist/
+server/www/
+server/test/assets/
web/node_modules/
web/coverage/
web/.svelte-kit
web/build/
-
-cli/node_modules/
-cli/.reverse-geocoding-dump/
-cli/upload/
-cli/dist/
-
-e2e/
-
-open-api/typescript-sdk/node_modules/
-open-api/typescript-sdk/build/
diff --git a/.editorconfig b/.editorconfig
index 64cb41406..43e1c061c 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -16,4 +16,4 @@ max_line_length = off
trim_trailing_whitespace = false
[*.{yml,yaml}]
-quote_type = double
+quote_type = single
diff --git a/.gitattributes b/.gitattributes
index b0a7f5ccc..f89b54de5 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -8,8 +8,6 @@ mobile/openapi/.openapi-generator/FILES linguist-generated=true
mobile/lib/**/*.g.dart -diff -merge
mobile/lib/**/*.g.dart linguist-generated=true
-open-api/typescript-sdk/axios-client/**/* -diff -merge
-open-api/typescript-sdk/axios-client/**/* linguist-generated=true
open-api/typescript-sdk/fetch-client.ts -diff -merge
open-api/typescript-sdk/fetch-client.ts linguist-generated=true
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 121cd1d94..b6b17774e 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -35,7 +35,7 @@ jobs:
- name: Checkout code
uses: actions/checkout@v4
with:
- submodules: "recursive"
+ submodules: 'recursive'
- name: Run e2e tests
run: make server-e2e-jobs
@@ -184,7 +184,7 @@ jobs:
- name: Checkout code
uses: actions/checkout@v4
with:
- submodules: "recursive"
+ submodules: 'recursive'
- name: Setup Node
uses: actions/setup-node@v4
@@ -194,25 +194,40 @@ jobs:
- name: Run setup typescript-sdk
run: npm ci && npm run build
working-directory: ./open-api/typescript-sdk
+ if: ${{ !cancelled() }}
- name: Run setup cli
run: npm ci && npm run build
working-directory: ./cli
+ if: ${{ !cancelled() }}
- name: Install dependencies
run: npm ci
+ if: ${{ !cancelled() }}
+
+ - name: Run linter
+ run: npm run lint
+ if: ${{ !cancelled() }}
+
+ - name: Run formatter
+ run: npm run format
+ if: ${{ !cancelled() }}
- name: Install Playwright Browsers
- run: npx playwright install --with-deps
+ run: npx playwright install --with-deps chromium
+ if: ${{ !cancelled() }}
- name: Docker build
run: docker compose build
+ if: ${{ !cancelled() }}
- name: Run e2e tests (api & cli)
run: npm run test
+ if: ${{ !cancelled() }}
- name: Run e2e tests (web)
run: npx playwright test
+ if: ${{ !cancelled() }}
mobile-unit-tests:
name: Mobile
@@ -222,8 +237,8 @@ jobs:
- name: Setup Flutter SDK
uses: subosito/flutter-action@v2
with:
- channel: "stable"
- flutter-version: "3.16.9"
+ channel: 'stable'
+ flutter-version: '3.16.9'
- name: Run tests
working-directory: ./mobile
run: flutter test -j 1
@@ -241,7 +256,7 @@ jobs:
- uses: actions/setup-python@v5
with:
python-version: 3.11
- cache: "poetry"
+ cache: 'poetry'
- name: Install dependencies
run: |
poetry install --with dev --with cpu
@@ -279,7 +294,7 @@ jobs:
- name: Run API generation
run: make open-api
- name: Find file changes
- uses: tj-actions/verify-changed-files@v18
+ uses: tj-actions/verify-changed-files@v19
id: verify-changed-files
with:
files: |
@@ -334,7 +349,7 @@ jobs:
run: npm run typeorm:migrations:generate ./src/infra/migrations/TestMigration
- name: Find file changes
- uses: tj-actions/verify-changed-files@v18
+ uses: tj-actions/verify-changed-files@v19
id: verify-changed-files
with:
files: |
@@ -352,7 +367,7 @@ jobs:
DB_URL: postgres://postgres:postgres@localhost:5432/immich
- name: Find file changes
- uses: tj-actions/verify-changed-files@v18
+ uses: tj-actions/verify-changed-files@v19
id: verify-changed-sql-files
with:
files: |
diff --git a/cli/package-lock.json b/cli/package-lock.json
index f48f74d51..760d9863e 100644
--- a/cli/package-lock.json
+++ b/cli/package-lock.json
@@ -54,14 +54,6 @@
"@oazapfts/runtime": "^1.0.0",
"@types/node": "^20.11.0",
"typescript": "^5.3.3"
- },
- "peerDependencies": {
- "axios": "^1.6.7"
- },
- "peerDependenciesMeta": {
- "axios": {
- "optional": true
- }
}
},
"../server": {
diff --git a/docker/docker-compose.dev.yml b/docker/docker-compose.dev.yml
index 02e436644..d344329a5 100644
--- a/docker/docker-compose.dev.yml
+++ b/docker/docker-compose.dev.yml
@@ -2,7 +2,7 @@
# - https://immich.app/docs/developer/setup
# - https://immich.app/docs/developer/troubleshooting
-version: "3.8"
+version: '3.8'
name: immich-dev
@@ -30,7 +30,7 @@ x-server-build: &server-common
services:
immich-server:
container_name: immich_server
- command: [ "/usr/src/app/bin/immich-dev", "immich" ]
+ command: ['/usr/src/app/bin/immich-dev', 'immich']
<<: *server-common
ports:
- 3001:3001
@@ -41,7 +41,7 @@ services:
immich-microservices:
container_name: immich_microservices
- command: [ "/usr/src/app/bin/immich-dev", "microservices" ]
+ command: ['/usr/src/app/bin/immich-dev', 'microservices']
<<: *server-common
# extends:
# file: hwaccel.transcoding.yml
@@ -57,7 +57,7 @@ services:
image: immich-web-dev:latest
build:
context: ../web
- command: [ "/usr/src/app/bin/immich-web" ]
+ command: ['/usr/src/app/bin/immich-web']
env_file:
- .env
ports:
diff --git a/docker/docker-compose.prod.yml b/docker/docker-compose.prod.yml
index 352309671..b0a19274d 100644
--- a/docker/docker-compose.prod.yml
+++ b/docker/docker-compose.prod.yml
@@ -1,4 +1,4 @@
-version: "3.8"
+version: '3.8'
name: immich-prod
@@ -17,7 +17,7 @@ x-server-build: &server-common
services:
immich-server:
container_name: immich_server
- command: [ "start.sh", "immich" ]
+ command: ['start.sh', 'immich']
<<: *server-common
ports:
- 2283:3001
@@ -27,7 +27,7 @@ services:
immich-microservices:
container_name: immich_microservices
- command: [ "start.sh", "microservices" ]
+ command: ['start.sh', 'microservices']
<<: *server-common
# extends:
# file: hwaccel.transcoding.yml
diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml
index f1d16f7e6..46b4a44a8 100644
--- a/docker/docker-compose.yml
+++ b/docker/docker-compose.yml
@@ -1,4 +1,4 @@
-version: "3.8"
+version: '3.8'
#
# WARNING: Make sure to use the docker-compose.yml of the current release:
@@ -14,7 +14,7 @@ services:
immich-server:
container_name: immich_server
image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release}
- command: [ "start.sh", "immich" ]
+ command: ['start.sh', 'immich']
volumes:
- ${UPLOAD_LOCATION}:/usr/src/app/upload
- /etc/localtime:/etc/localtime:ro
@@ -33,7 +33,7 @@ services:
# extends: # uncomment this section for hardware acceleration - see https://immich.app/docs/features/hardware-transcoding
# file: hwaccel.transcoding.yml
# service: cpu # set to one of [nvenc, quicksync, rkmpp, vaapi, vaapi-wsl] for accelerated transcoding
- command: [ "start.sh", "microservices" ]
+ command: ['start.sh', 'microservices']
volumes:
- ${UPLOAD_LOCATION}:/usr/src/app/upload
- /etc/localtime:/etc/localtime:ro
@@ -60,12 +60,12 @@ services:
redis:
container_name: immich_redis
- image: redis:6.2-alpine@sha256:51d6c56749a4243096327e3fb964a48ed92254357108449cb6e23999c37773c5
+ image: registry.hub.docker.com/library/redis:6.2-alpine@sha256:51d6c56749a4243096327e3fb964a48ed92254357108449cb6e23999c37773c5
restart: always
database:
container_name: immich_postgres
- image: tensorchord/pgvecto-rs:pg14-v0.2.0@sha256:90724186f0a3517cf6914295b5ab410db9ce23190a2d9d0b9dd6463e3fa298f0
+ image: registry.hub.docker.com/tensorchord/pgvecto-rs:pg14-v0.2.0@sha256:90724186f0a3517cf6914295b5ab410db9ce23190a2d9d0b9dd6463e3fa298f0
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_USER: ${DB_USERNAME}
diff --git a/docs/docs/administration/oauth.md b/docs/docs/administration/oauth.md
index c1ac3c577..66a752f0b 100644
--- a/docs/docs/administration/oauth.md
+++ b/docs/docs/administration/oauth.md
@@ -67,9 +67,11 @@ Once you have a new OAuth client application configured, Immich can be configure
| Client Secret | string | (required) | Required. Client Secret (previous step) |
| Scope | string | openid email profile | Full list of scopes to send with the request (space delimited) |
| Signing Algorithm | string | RS256 | The algorithm used to sign the id token (examples: RS256, HS256) |
+| Storage Label Claim | string | preferred_username | Claim mapping for the user's storage label |
+| Storage Quota Claim | string | immich_quota | Claim mapping for the user's storage |
+| Default Storage Quota (GiB) | number | 0 | Default quota for user without storage quota claim (Enter 0 for unlimited quota) |
| Button Text | string | Login with OAuth | Text for the OAuth button on the web |
| Auto Register | boolean | true | When true, will automatically register a user the first time they sign in |
-| Storage Claim | string | preferred_username | Claim mapping for the user's storage label |
| [Auto Launch](#auto-launch) | boolean | false | When true, will skip the login page and automatically start the OAuth login process |
| [Mobile Redirect URI Override](#mobile-redirect-uri) | URL | (empty) | Http(s) alternative mobile redirect URI |
diff --git a/docs/docs/features/libraries.md b/docs/docs/features/libraries.md
index 995d65249..58dd707ea 100644
--- a/docs/docs/features/libraries.md
+++ b/docs/docs/features/libraries.md
@@ -88,10 +88,7 @@ Some basic examples:
This feature - currently hidden in the config file - is considered experimental and for advanced users only. If enabled, it will allow automatic watching of the filesystem which means new assets are automatically imported to Immich without needing to rescan. Deleted assets are, as always, marked as offline and can be removed with the "Remove offline files" button.
-If your photos are on a network drive you will likely have to enable filesystem polling. The performance hit for polling large libraries is currently unknown, feel free to test this feature and report back. In addition to the boolean feature flag, the configuration file allows customization of the following parameters, please see the [chokidar documentation](https://github.com/paulmillr/chokidar?tab=readme-ov-file#performance) for reference.
-
-- `usePolling` (default: `false`).
-- `interval`. (default: 10000). When using polling, this is how often (in milliseconds) the filesystem is polled.
+If your photos are on a network drive, automatic file watching likely won't work. In that case, you will have to rely on a periodic library refresh to pull in your changes.
### Nightly job
diff --git a/docs/docs/install/config-file.md b/docs/docs/install/config-file.md
index 755722d9e..8a7776a42 100644
--- a/docs/docs/install/config-file.md
+++ b/docs/docs/install/config-file.md
@@ -95,13 +95,16 @@ The default configuration looks like this:
"issuerUrl": "",
"clientId": "",
"clientSecret": "",
- "mobileOverrideEnabled": false,
- "mobileRedirectUri": "",
"scope": "openid email profile",
+ "signingAlgorithm": "RS256",
"storageLabelClaim": "preferred_username",
+ "storageQuotaClaim": "immich_quota",
+ "defaultStorageQuota": 0,
"buttonText": "Login with OAuth",
"autoRegister": true,
- "autoLaunch": false
+ "autoLaunch": false,
+ "mobileOverrideEnabled": false,
+ "mobileRedirectUri": ""
},
"passwordLogin": {
"enabled": true
diff --git a/docs/docs/install/environment-variables.md b/docs/docs/install/environment-variables.md
index 48d7219d1..2849c6054 100644
--- a/docs/docs/install/environment-variables.md
+++ b/docs/docs/install/environment-variables.md
@@ -67,7 +67,7 @@ These environment variables are used by the `docker-compose.yml` file and do **N
| `DB_PORT` | Database Port | `5432` | server, microservices |
| `DB_USERNAME` | Database User | `postgres` | server, microservices |
| `DB_PASSWORD` | Database Password | `postgres` | server, microservices |
-| `DB_DATABASE` | Database Name | `immich` | server, microservices |
+| `DB_DATABASE_NAME` | Database Name | `immich` | server, microservices |
| `DB_VECTOR_EXTENSION`\*1 | Database Vector Extension (one of [`pgvector`, `pgvecto.rs`]) | `pgvecto.rs` | server, microservices |
\*1: This setting cannot be changed after the server has successfully started up
diff --git a/docs/src/pages/milestones.tsx b/docs/src/pages/milestones.tsx
index 1670b9fc8..e672e0326 100644
--- a/docs/src/pages/milestones.tsx
+++ b/docs/src/pages/milestones.tsx
@@ -50,12 +50,22 @@ import {
mdiVectorCombine,
mdiVideo,
mdiWeb,
+ mdiScaleBalance,
} from '@mdi/js';
import Layout from '@theme/Layout';
import React from 'react';
import Timeline, { DateType, Item } from '../components/timeline';
const items: Item[] = [
+ {
+ icon: mdiScaleBalance,
+ description: 'Immich switches to AGPLv3 license',
+ title: 'AGPL License',
+ release: 'v1.95.0',
+ tag: 'v1.95.0',
+ date: new Date(2024, 1, 20),
+ dateType: DateType.RELEASE,
+ },
{
icon: mdiEyeRefreshOutline,
description: 'Automatically import files in external libraries when the operating system detects changes.',
diff --git a/e2e/.eslintrc.cjs b/e2e/.eslintrc.cjs
new file mode 100644
index 000000000..3989e86e5
--- /dev/null
+++ b/e2e/.eslintrc.cjs
@@ -0,0 +1,31 @@
+module.exports = {
+ parser: '@typescript-eslint/parser',
+ parserOptions: {
+ project: 'tsconfig.json',
+ sourceType: 'module',
+ tsconfigRootDir: __dirname,
+ },
+ plugins: ['@typescript-eslint/eslint-plugin'],
+ extends: ['plugin:@typescript-eslint/recommended', 'plugin:prettier/recommended', 'plugin:unicorn/recommended'],
+ root: true,
+ env: {
+ node: true,
+ },
+ ignorePatterns: ['.eslintrc.js'],
+ rules: {
+ '@typescript-eslint/interface-name-prefix': 'off',
+ '@typescript-eslint/explicit-function-return-type': 'off',
+ '@typescript-eslint/explicit-module-boundary-types': 'off',
+ '@typescript-eslint/no-explicit-any': 'off',
+ '@typescript-eslint/no-floating-promises': 'error',
+ 'unicorn/prefer-module': 'off',
+ curly: 2,
+ 'prettier/prettier': 0,
+ 'unicorn/prevent-abbreviations': 'off',
+ 'unicorn/filename-case': 'off',
+ 'unicorn/no-null': 'off',
+ 'unicorn/prefer-top-level-await': 'off',
+ 'unicorn/prefer-event-target': 'off',
+ 'unicorn/no-thenable': 'off',
+ },
+};
diff --git a/e2e/.prettierignore b/e2e/.prettierignore
new file mode 100644
index 000000000..c5b339bce
--- /dev/null
+++ b/e2e/.prettierignore
@@ -0,0 +1,16 @@
+.DS_Store
+node_modules
+/build
+/package
+.env
+.env.*
+!.env.example
+*.md
+*.json
+coverage
+dist
+
+# Ignore files for PNPM, NPM and YARN
+pnpm-lock.yaml
+package-lock.json
+yarn.lock
diff --git a/e2e/.prettierrc b/e2e/.prettierrc
new file mode 100644
index 000000000..b0daf15ef
--- /dev/null
+++ b/e2e/.prettierrc
@@ -0,0 +1,8 @@
+{
+ "singleQuote": true,
+ "trailingComma": "all",
+ "printWidth": 120,
+ "semi": true,
+ "organizeImportsSkipDestructiveCodeActions": true,
+ "plugins": ["prettier-plugin-organize-imports"]
+}
diff --git a/e2e/docker-compose.yml b/e2e/docker-compose.yml
index 8228ff289..6e2d4b78d 100644
--- a/e2e/docker-compose.yml
+++ b/e2e/docker-compose.yml
@@ -1,4 +1,4 @@
-version: "3.8"
+version: '3.8'
name: immich-e2e
@@ -16,6 +16,7 @@ x-server-build: &server-common
- IMMICH_MACHINE_LEARNING_ENABLED=false
volumes:
- upload:/usr/src/app/upload
+ - ../server/test/assets:/data/assets
depends_on:
- redis
- database
@@ -23,14 +24,14 @@ x-server-build: &server-common
services:
immich-server:
container_name: immich-e2e-server
- command: [ "./start.sh", "immich" ]
+ command: ['./start.sh', 'immich']
<<: *server-common
ports:
- 2283:3001
immich-microservices:
container_name: immich-e2e-microservices
- command: [ "./start.sh", "microservices" ]
+ command: ['./start.sh', 'microservices']
<<: *server-common
redis:
diff --git a/e2e/package-lock.json b/e2e/package-lock.json
index 954d1cc3f..7d013eeca 100644
--- a/e2e/package-lock.json
+++ b/e2e/package-lock.json
@@ -15,10 +15,21 @@
"@types/luxon": "^3.4.2",
"@types/node": "^20.11.17",
"@types/pg": "^8.11.0",
+ "@types/pngjs": "^6.0.4",
"@types/supertest": "^6.0.2",
+ "@typescript-eslint/eslint-plugin": "^7.1.0",
+ "@typescript-eslint/parser": "^7.1.0",
"@vitest/coverage-v8": "^1.3.0",
+ "eslint": "^8.57.0",
+ "eslint-config-prettier": "^9.1.0",
+ "eslint-plugin-prettier": "^5.1.3",
+ "eslint-plugin-unicorn": "^51.0.1",
+ "exiftool-vendored": "^24.5.0",
"luxon": "^3.4.4",
"pg": "^8.11.3",
+ "pngjs": "^7.0.0",
+ "prettier": "^3.2.5",
+ "prettier-plugin-organize-imports": "^3.2.4",
"socket.io-client": "^4.7.4",
"supertest": "^6.3.4",
"typescript": "^5.3.3",
@@ -69,21 +80,22 @@
},
"../open-api/typescript-sdk": {
"name": "@immich/sdk",
- "version": "1.92.1",
+ "version": "1.97.0",
"dev": true,
"license": "GNU Affero General Public License version 3",
"devDependencies": {
"@oazapfts/runtime": "^1.0.0",
"@types/node": "^20.11.0",
"typescript": "^5.3.3"
- },
- "peerDependencies": {
- "axios": "^1.6.7"
- },
- "peerDependenciesMeta": {
- "axios": {
- "optional": true
- }
+ }
+ },
+ "node_modules/@aashutoshrathi/word-wrap": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz",
+ "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
}
},
"node_modules/@ampproject/remapping": {
@@ -99,6 +111,90 @@
"node": ">=6.0.0"
}
},
+ "node_modules/@babel/code-frame": {
+ "version": "7.23.5",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz",
+ "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/highlight": "^7.23.4",
+ "chalk": "^2.4.2"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/code-frame/node_modules/ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^1.9.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/code-frame/node_modules/chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/code-frame/node_modules/color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "1.1.3"
+ }
+ },
+ "node_modules/@babel/code-frame/node_modules/color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
+ "dev": true
+ },
+ "node_modules/@babel/code-frame/node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/@babel/code-frame/node_modules/has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/code-frame/node_modules/supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/@babel/helper-string-parser": {
"version": "7.23.4",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz",
@@ -117,6 +213,97 @@
"node": ">=6.9.0"
}
},
+ "node_modules/@babel/highlight": {
+ "version": "7.23.4",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz",
+ "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.22.20",
+ "chalk": "^2.4.2",
+ "js-tokens": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^1.9.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "1.1.3"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
+ "dev": true
+ },
+ "node_modules/@babel/highlight/node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "dev": true
+ },
+ "node_modules/@babel/highlight/node_modules/supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/@babel/parser": {
"version": "7.23.9",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz",
@@ -517,6 +704,95 @@
"node": ">=12"
}
},
+ "node_modules/@eslint-community/eslint-utils": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
+ "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==",
+ "dev": true,
+ "dependencies": {
+ "eslint-visitor-keys": "^3.3.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
+ }
+ },
+ "node_modules/@eslint-community/regexpp": {
+ "version": "4.10.0",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz",
+ "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==",
+ "dev": true,
+ "engines": {
+ "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@eslint/eslintrc": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz",
+ "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==",
+ "dev": true,
+ "dependencies": {
+ "ajv": "^6.12.4",
+ "debug": "^4.3.2",
+ "espree": "^9.6.0",
+ "globals": "^13.19.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^4.1.0",
+ "minimatch": "^3.1.2",
+ "strip-json-comments": "^3.1.1"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint/js": {
+ "version": "8.57.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz",
+ "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@humanwhocodes/config-array": {
+ "version": "0.11.14",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz",
+ "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==",
+ "dev": true,
+ "dependencies": {
+ "@humanwhocodes/object-schema": "^2.0.2",
+ "debug": "^4.3.1",
+ "minimatch": "^3.0.5"
+ },
+ "engines": {
+ "node": ">=10.10.0"
+ }
+ },
+ "node_modules/@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12.22"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/object-schema": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz",
+ "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==",
+ "dev": true
+ },
"node_modules/@immich/cli": {
"resolved": "../cli",
"link": true
@@ -594,6 +870,59 @@
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
+ "node_modules/@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@photostructure/tz-lookup": {
+ "version": "9.0.2",
+ "resolved": "https://registry.npmjs.org/@photostructure/tz-lookup/-/tz-lookup-9.0.2.tgz",
+ "integrity": "sha512-H8+tTt7ilJNkFyb+QgPnLEGUjQzGwiMb9n7lwRZNBgSKL3VZs9AkjI1E//FcwPjNafwAH932U92+xTqJiF3Bbw==",
+ "dev": true
+ },
+ "node_modules/@pkgr/core": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz",
+ "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==",
+ "dev": true,
+ "engines": {
+ "node": "^12.20.0 || ^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/unts"
+ }
+ },
"node_modules/@playwright/test": {
"version": "1.41.2",
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.41.2.tgz",
@@ -808,6 +1137,12 @@
"integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==",
"dev": true
},
+ "node_modules/@types/json-schema": {
+ "version": "7.0.15",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
+ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
+ "dev": true
+ },
"node_modules/@types/luxon": {
"version": "3.4.2",
"resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-3.4.2.tgz",
@@ -821,18 +1156,24 @@
"dev": true
},
"node_modules/@types/node": {
- "version": "20.11.19",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.19.tgz",
- "integrity": "sha512-7xMnVEcZFu0DikYjWOlRq7NTPETrm7teqUT2WkQjrTIkEgUyyGdWsj/Zg8bEJt5TNklzbPD1X3fqfsHw3SpapQ==",
+ "version": "20.11.20",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.20.tgz",
+ "integrity": "sha512-7/rR21OS+fq8IyHTgtLkDK949uzsa6n8BkziAKtPVpugIkO6D+/ooXMvzXxDnZrmtXVfjb1bKQafYpb8s89LOg==",
"dev": true,
"dependencies": {
"undici-types": "~5.26.4"
}
},
+ "node_modules/@types/normalize-package-data": {
+ "version": "2.4.4",
+ "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz",
+ "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==",
+ "dev": true
+ },
"node_modules/@types/pg": {
- "version": "8.11.0",
- "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.11.0.tgz",
- "integrity": "sha512-sDAlRiBNthGjNFfvt0k6mtotoVYVQ63pA8R4EMWka7crawSR60waVYR0HAgmPRs/e2YaeJTD/43OoZ3PFw80pw==",
+ "version": "8.11.2",
+ "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.11.2.tgz",
+ "integrity": "sha512-G2Mjygf2jFMU/9hCaTYxJrwdObdcnuQde1gndooZSOHsNSaCehAuwc7EIuSA34Do8Jx2yZ19KtvW8P0j4EuUXw==",
"dev": true,
"dependencies": {
"@types/node": "*",
@@ -897,6 +1238,21 @@
"node": ">=12"
}
},
+ "node_modules/@types/pngjs": {
+ "version": "6.0.4",
+ "resolved": "https://registry.npmjs.org/@types/pngjs/-/pngjs-6.0.4.tgz",
+ "integrity": "sha512-atAK9xLKOnxiuArxcHovmnOUUGBZOQ3f0vCf43FnoKs6XnqiambT1kkJWmdo71IR+BoXSh+CueeFR0GfH3dTlQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/semver": {
+ "version": "7.5.8",
+ "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz",
+ "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==",
+ "dev": true
+ },
"node_modules/@types/superagent": {
"version": "8.1.3",
"resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-8.1.3.tgz",
@@ -918,6 +1274,226 @@
"@types/superagent": "^8.1.0"
}
},
+ "node_modules/@typescript-eslint/eslint-plugin": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.1.0.tgz",
+ "integrity": "sha512-j6vT/kCulhG5wBmGtstKeiVr1rdXE4nk+DT1k6trYkwlrvW9eOF5ZbgKnd/YR6PcM4uTEXa0h6Fcvf6X7Dxl0w==",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/regexpp": "^4.5.1",
+ "@typescript-eslint/scope-manager": "7.1.0",
+ "@typescript-eslint/type-utils": "7.1.0",
+ "@typescript-eslint/utils": "7.1.0",
+ "@typescript-eslint/visitor-keys": "7.1.0",
+ "debug": "^4.3.4",
+ "graphemer": "^1.4.0",
+ "ignore": "^5.2.4",
+ "natural-compare": "^1.4.0",
+ "semver": "^7.5.4",
+ "ts-api-utils": "^1.0.1"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "@typescript-eslint/parser": "^7.0.0",
+ "eslint": "^8.56.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/parser": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.1.0.tgz",
+ "integrity": "sha512-V1EknKUubZ1gWFjiOZhDSNToOjs63/9O0puCgGS8aDOgpZY326fzFu15QAUjwaXzRZjf/qdsdBrckYdv9YxB8w==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/scope-manager": "7.1.0",
+ "@typescript-eslint/types": "7.1.0",
+ "@typescript-eslint/typescript-estree": "7.1.0",
+ "@typescript-eslint/visitor-keys": "7.1.0",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.56.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/scope-manager": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.1.0.tgz",
+ "integrity": "sha512-6TmN4OJiohHfoOdGZ3huuLhpiUgOGTpgXNUPJgeZOZR3DnIpdSgtt83RS35OYNNXxM4TScVlpVKC9jyQSETR1A==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "7.1.0",
+ "@typescript-eslint/visitor-keys": "7.1.0"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.1.0.tgz",
+ "integrity": "sha512-UZIhv8G+5b5skkcuhgvxYWHjk7FW7/JP5lPASMEUoliAPwIH/rxoUSQPia2cuOj9AmDZmwUl1usKm85t5VUMew==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/typescript-estree": "7.1.0",
+ "@typescript-eslint/utils": "7.1.0",
+ "debug": "^4.3.4",
+ "ts-api-utils": "^1.0.1"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.56.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/types": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.1.0.tgz",
+ "integrity": "sha512-qTWjWieJ1tRJkxgZYXx6WUYtWlBc48YRxgY2JN1aGeVpkhmnopq+SUC8UEVGNXIvWH7XyuTjwALfG6bFEgCkQA==",
+ "dev": true,
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.1.0.tgz",
+ "integrity": "sha512-k7MyrbD6E463CBbSpcOnwa8oXRdHzH1WiVzOipK3L5KSML92ZKgUBrTlehdi7PEIMT8k0bQixHUGXggPAlKnOQ==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "7.1.0",
+ "@typescript-eslint/visitor-keys": "7.1.0",
+ "debug": "^4.3.4",
+ "globby": "^11.1.0",
+ "is-glob": "^4.0.3",
+ "minimatch": "9.0.3",
+ "semver": "^7.5.4",
+ "ts-api-utils": "^1.0.1"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": {
+ "version": "9.0.3",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
+ "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@typescript-eslint/utils": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.1.0.tgz",
+ "integrity": "sha512-WUFba6PZC5OCGEmbweGpnNJytJiLG7ZvDBJJoUcX4qZYf1mGZ97mO2Mps6O2efxJcJdRNpqweCistDbZMwIVHw==",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.4.0",
+ "@types/json-schema": "^7.0.12",
+ "@types/semver": "^7.5.0",
+ "@typescript-eslint/scope-manager": "7.1.0",
+ "@typescript-eslint/types": "7.1.0",
+ "@typescript-eslint/typescript-estree": "7.1.0",
+ "semver": "^7.5.4"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.56.0"
+ }
+ },
+ "node_modules/@typescript-eslint/visitor-keys": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.1.0.tgz",
+ "integrity": "sha512-FhUqNWluiGNzlvnDZiXad4mZRhtghdoKW6e98GoEOYSu5cND+E39rG5KwJMUzeENwm1ztYBRqof8wMLP+wNPIA==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "7.1.0",
+ "eslint-visitor-keys": "^3.4.1"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@ungap/structured-clone": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
+ "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==",
+ "dev": true
+ },
"node_modules/@vitest/coverage-v8": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-1.3.1.tgz",
@@ -1026,6 +1602,15 @@
"node": ">=0.4.0"
}
},
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
"node_modules/acorn-walk": {
"version": "8.3.2",
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz",
@@ -1035,6 +1620,31 @@
"node": ">=0.4.0"
}
},
+ "node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/ansi-styles": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
@@ -1047,6 +1657,21 @@
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true
+ },
+ "node_modules/array-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/asap": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
@@ -1074,6 +1699,15 @@
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"dev": true
},
+ "node_modules/batch-cluster": {
+ "version": "13.0.0",
+ "resolved": "https://registry.npmjs.org/batch-cluster/-/batch-cluster-13.0.0.tgz",
+ "integrity": "sha512-EreW0Vi8TwovhYUHBXXRA5tthuU2ynGsZFlboyMJHCCUXYa2AjgwnE3ubBOJs2xJLcuXFJbi6c/8pH5+FVj8Og==",
+ "dev": true,
+ "engines": {
+ "node": ">=14"
+ }
+ },
"node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -1084,6 +1718,50 @@
"concat-map": "0.0.1"
}
},
+ "node_modules/braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dev": true,
+ "dependencies": {
+ "fill-range": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/browserslist": {
+ "version": "4.23.0",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz",
+ "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "caniuse-lite": "^1.0.30001587",
+ "electron-to-chromium": "^1.4.668",
+ "node-releases": "^2.0.14",
+ "update-browserslist-db": "^1.0.13"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
"node_modules/buffer-writer": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz",
@@ -1093,6 +1771,18 @@
"node": ">=4"
}
},
+ "node_modules/builtin-modules": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz",
+ "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/cac": {
"version": "6.7.14",
"resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz",
@@ -1121,6 +1811,35 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001591",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001591.tgz",
+ "integrity": "sha512-PCzRMei/vXjJyL5mJtzNiUCKP59dm8Apqc3PH8gJkMnMXZGox93RbE76jHsmLwmIo6/3nsYIpJtx0O7u5PqFuQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ]
+ },
"node_modules/chai": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz",
@@ -1139,6 +1858,37 @@
"node": ">=4"
}
},
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/chalk/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
"node_modules/check-error": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz",
@@ -1151,6 +1901,60 @@
"node": "*"
}
},
+ "node_modules/ci-info": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.0.0.tgz",
+ "integrity": "sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
+ ],
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/clean-regexp": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/clean-regexp/-/clean-regexp-1.0.0.tgz",
+ "integrity": "sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==",
+ "dev": true,
+ "dependencies": {
+ "escape-string-regexp": "^1.0.5"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/clean-regexp/node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
@@ -1190,6 +1994,19 @@
"integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==",
"dev": true
},
+ "node_modules/core-js-compat": {
+ "version": "3.36.0",
+ "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.36.0.tgz",
+ "integrity": "sha512-iV9Pd/PsgjNWBXeq8XRtWVSgz2tKAfhfvBs7qxYty+RlRd+OCksaWmOnc4JKrTc1cToXL1N0s3l/vwlxPtdElw==",
+ "dev": true,
+ "dependencies": {
+ "browserslist": "^4.22.3"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/core-js"
+ }
+ },
"node_modules/cross-spawn": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
@@ -1233,6 +2050,12 @@
"node": ">=6"
}
},
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true
+ },
"node_modules/define-data-property": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
@@ -1278,6 +2101,36 @@
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
+ "node_modules/dir-glob": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+ "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+ "dev": true,
+ "dependencies": {
+ "path-type": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/doctrine": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+ "dev": true,
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/electron-to-chromium": {
+ "version": "1.4.687",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.687.tgz",
+ "integrity": "sha512-Ic85cOuXSP6h7KM0AIJ2hpJ98Bo4hyTUjc4yjMbkvD+8yTxEhfK9+8exT2KKYsSjnCn2tGsKVSZwE7ZgTORQCw==",
+ "dev": true
+ },
"node_modules/engine.io-client": {
"version": "6.5.3",
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.3.tgz",
@@ -1300,6 +2153,15 @@
"node": ">=10.0.0"
}
},
+ "node_modules/error-ex": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+ "dev": true,
+ "dependencies": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
"node_modules/es-define-property": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
@@ -1359,6 +2221,235 @@
"@esbuild/win32-x64": "0.19.12"
}
},
+ "node_modules/escalade": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz",
+ "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint": {
+ "version": "8.57.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz",
+ "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.2.0",
+ "@eslint-community/regexpp": "^4.6.1",
+ "@eslint/eslintrc": "^2.1.4",
+ "@eslint/js": "8.57.0",
+ "@humanwhocodes/config-array": "^0.11.14",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@nodelib/fs.walk": "^1.2.8",
+ "@ungap/structured-clone": "^1.2.0",
+ "ajv": "^6.12.4",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.2",
+ "debug": "^4.3.2",
+ "doctrine": "^3.0.0",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^7.2.2",
+ "eslint-visitor-keys": "^3.4.3",
+ "espree": "^9.6.1",
+ "esquery": "^1.4.2",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^6.0.1",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "globals": "^13.19.0",
+ "graphemer": "^1.4.0",
+ "ignore": "^5.2.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "is-path-inside": "^3.0.3",
+ "js-yaml": "^4.1.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "levn": "^0.4.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.3",
+ "strip-ansi": "^6.0.1",
+ "text-table": "^0.2.0"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-config-prettier": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz",
+ "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==",
+ "dev": true,
+ "bin": {
+ "eslint-config-prettier": "bin/cli.js"
+ },
+ "peerDependencies": {
+ "eslint": ">=7.0.0"
+ }
+ },
+ "node_modules/eslint-plugin-prettier": {
+ "version": "5.1.3",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz",
+ "integrity": "sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==",
+ "dev": true,
+ "dependencies": {
+ "prettier-linter-helpers": "^1.0.0",
+ "synckit": "^0.8.6"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint-plugin-prettier"
+ },
+ "peerDependencies": {
+ "@types/eslint": ">=8.0.0",
+ "eslint": ">=8.0.0",
+ "eslint-config-prettier": "*",
+ "prettier": ">=3.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/eslint": {
+ "optional": true
+ },
+ "eslint-config-prettier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-plugin-unicorn": {
+ "version": "51.0.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-51.0.1.tgz",
+ "integrity": "sha512-MuR/+9VuB0fydoI0nIn2RDA5WISRn4AsJyNSaNKLVwie9/ONvQhxOBbkfSICBPnzKrB77Fh6CZZXjgTt/4Latw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.22.20",
+ "@eslint-community/eslint-utils": "^4.4.0",
+ "@eslint/eslintrc": "^2.1.4",
+ "ci-info": "^4.0.0",
+ "clean-regexp": "^1.0.0",
+ "core-js-compat": "^3.34.0",
+ "esquery": "^1.5.0",
+ "indent-string": "^4.0.0",
+ "is-builtin-module": "^3.2.1",
+ "jsesc": "^3.0.2",
+ "pluralize": "^8.0.0",
+ "read-pkg-up": "^7.0.1",
+ "regexp-tree": "^0.1.27",
+ "regjsparser": "^0.10.0",
+ "semver": "^7.5.4",
+ "strip-indent": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=16"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/eslint-plugin-unicorn?sponsor=1"
+ },
+ "peerDependencies": {
+ "eslint": ">=8.56.0"
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "7.2.2",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
+ "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
+ "dev": true,
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/espree": {
+ "version": "9.6.1",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
+ "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
+ "dev": true,
+ "dependencies": {
+ "acorn": "^8.9.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^3.4.1"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/esquery": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
+ "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
"node_modules/estree-walker": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
@@ -1368,6 +2459,15 @@
"@types/estree": "^1.0.0"
}
},
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/execa": {
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz",
@@ -1391,12 +2491,170 @@
"url": "https://github.com/sindresorhus/execa?sponsor=1"
}
},
+ "node_modules/exiftool-vendored": {
+ "version": "24.5.0",
+ "resolved": "https://registry.npmjs.org/exiftool-vendored/-/exiftool-vendored-24.5.0.tgz",
+ "integrity": "sha512-uLGYfeshak3mYn2ucCsebXfNFdOpeAULlMb84wiJv+4B236n+ypgK/vr8bJgAcsIPSRJXFSz9WonvjjQYYqR3w==",
+ "dev": true,
+ "dependencies": {
+ "@photostructure/tz-lookup": "^9.0.1",
+ "@types/luxon": "^3.4.2",
+ "batch-cluster": "^13.0.0",
+ "he": "^1.2.0",
+ "luxon": "^3.4.4"
+ },
+ "optionalDependencies": {
+ "exiftool-vendored.exe": "12.76.0",
+ "exiftool-vendored.pl": "12.76.0"
+ }
+ },
+ "node_modules/exiftool-vendored.exe": {
+ "version": "12.76.0",
+ "resolved": "https://registry.npmjs.org/exiftool-vendored.exe/-/exiftool-vendored.exe-12.76.0.tgz",
+ "integrity": "sha512-lbKPPs31qpjnhFiMRaVxJX+iNcJ+p0NrRSFLHHaX6KTsfMba6e5i6NykSvU3wMiafzUTef1Fen3XQ+8n1tjjNw==",
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/exiftool-vendored.pl": {
+ "version": "12.76.0",
+ "resolved": "https://registry.npmjs.org/exiftool-vendored.pl/-/exiftool-vendored.pl-12.76.0.tgz",
+ "integrity": "sha512-4DxqgnvL71YziVoY27ZMgVfLAWDH3pQLljuV5+ffTnTPvz/BWeV+/bVFwRvDqCD3lkCWds0YfVcsycfJgbQ5fA==",
+ "dev": true,
+ "optional": true,
+ "os": [
+ "!win32"
+ ]
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true
+ },
+ "node_modules/fast-diff": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz",
+ "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==",
+ "dev": true
+ },
+ "node_modules/fast-glob": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
+ "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/fast-glob/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true
+ },
"node_modules/fast-safe-stringify": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz",
"integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==",
"dev": true
},
+ "node_modules/fastq": {
+ "version": "1.17.1",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
+ "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==",
+ "dev": true,
+ "dependencies": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "node_modules/file-entry-cache": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+ "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+ "dev": true,
+ "dependencies": {
+ "flat-cache": "^3.0.4"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "dev": true,
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/flat-cache": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz",
+ "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==",
+ "dev": true,
+ "dependencies": {
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.3",
+ "rimraf": "^3.0.2"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/flatted": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz",
+ "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==",
+ "dev": true
+ },
"node_modules/form-data": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
@@ -1515,6 +2773,53 @@
"url": "https://github.com/sponsors/isaacs"
}
},
+ "node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/globals": {
+ "version": "13.24.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
+ "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
+ "dev": true,
+ "dependencies": {
+ "type-fest": "^0.20.2"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/globby": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
+ "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
+ "dev": true,
+ "dependencies": {
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.2.9",
+ "ignore": "^5.2.0",
+ "merge2": "^1.4.1",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/gopd": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
@@ -1527,6 +2832,12 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/graphemer": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
+ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
+ "dev": true
+ },
"node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -1584,6 +2895,15 @@
"node": ">= 0.4"
}
},
+ "node_modules/he": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
+ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
+ "dev": true,
+ "bin": {
+ "he": "bin/he"
+ }
+ },
"node_modules/hexoid": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz",
@@ -1593,6 +2913,12 @@
"node": ">=8"
}
},
+ "node_modules/hosted-git-info": {
+ "version": "2.8.9",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
+ "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
+ "dev": true
+ },
"node_modules/html-escaper": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
@@ -1608,6 +2934,49 @@
"node": ">=16.17.0"
}
},
+ "node_modules/ignore": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz",
+ "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+ "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+ "dev": true,
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/indent-string": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
+ "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
@@ -1624,6 +2993,78 @@
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"dev": true
},
+ "node_modules/is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
+ "dev": true
+ },
+ "node_modules/is-builtin-module": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz",
+ "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==",
+ "dev": true,
+ "dependencies": {
+ "builtin-modules": "^3.3.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-core-module": {
+ "version": "2.13.1",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz",
+ "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==",
+ "dev": true,
+ "dependencies": {
+ "hasown": "^2.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-path-inside": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
+ "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/is-stream": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz",
@@ -1698,12 +3139,88 @@
"integrity": "sha512-UfJMcSJc+SEXEl9lH/VLHSZbThQyLpw1vLO1Lb+j4RWDvG3N2f7yj3PVQA3cmkTBNldJ9eFnM+xEXxHIXrYiJw==",
"dev": true
},
+ "node_modules/js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dev": true,
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "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==",
+ "dev": true,
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/json-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+ "dev": true
+ },
+ "node_modules/json-parse-even-better-errors": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
+ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
+ "dev": true
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "node_modules/json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true
+ },
"node_modules/jsonc-parser": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz",
"integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==",
"dev": true
},
+ "node_modules/keyv": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+ "dev": true,
+ "dependencies": {
+ "json-buffer": "3.0.1"
+ }
+ },
+ "node_modules/levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/lines-and-columns": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
+ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
+ "dev": true
+ },
"node_modules/local-pkg": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.0.tgz",
@@ -1720,6 +3237,27 @@
"url": "https://github.com/sponsors/antfu"
}
},
+ "node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true
+ },
"node_modules/loupe": {
"version": "2.3.7",
"resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz",
@@ -1794,6 +3332,15 @@
"integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
"dev": true
},
+ "node_modules/merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
"node_modules/methods": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
@@ -1803,6 +3350,19 @@
"node": ">= 0.6"
}
},
+ "node_modules/micromatch": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
+ "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+ "dev": true,
+ "dependencies": {
+ "braces": "^3.0.2",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
"node_modules/mime": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
@@ -1848,6 +3408,15 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/min-indent": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz",
+ "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
@@ -1896,6 +3465,39 @@
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true
+ },
+ "node_modules/node-releases": {
+ "version": "2.0.14",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz",
+ "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==",
+ "dev": true
+ },
+ "node_modules/normalize-package-data": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
+ "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
+ "dev": true,
+ "dependencies": {
+ "hosted-git-info": "^2.1.4",
+ "resolve": "^1.10.0",
+ "semver": "2 || 3 || 4 || 5",
+ "validate-npm-package-license": "^3.0.1"
+ }
+ },
+ "node_modules/normalize-package-data/node_modules/semver": {
+ "version": "5.7.2",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
+ "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver"
+ }
+ },
"node_modules/npm-run-path": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.2.0.tgz",
@@ -1962,6 +3564,23 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/optionator": {
+ "version": "0.9.3",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz",
+ "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==",
+ "dev": true,
+ "dependencies": {
+ "@aashutoshrathi/word-wrap": "^1.2.3",
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
"node_modules/p-limit": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-5.0.0.tgz",
@@ -1977,12 +3596,102 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate/node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate/node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/packet-reader": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz",
"integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==",
"dev": true
},
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/parse-json": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
+ "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.0.0",
+ "error-ex": "^1.3.1",
+ "json-parse-even-better-errors": "^2.3.0",
+ "lines-and-columns": "^1.1.6"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
@@ -2001,6 +3710,21 @@
"node": ">=8"
}
},
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "dev": true
+ },
+ "node_modules/path-type": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/pathe": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz",
@@ -2122,6 +3846,18 @@
"integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
"dev": true
},
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
"node_modules/pkg-types": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.0.3.tgz",
@@ -2163,6 +3899,24 @@
"node": ">=16"
}
},
+ "node_modules/pluralize": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz",
+ "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/pngjs": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-7.0.0.tgz",
+ "integrity": "sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow==",
+ "dev": true,
+ "engines": {
+ "node": ">=14.19.0"
+ }
+ },
"node_modules/postcss": {
"version": "8.4.35",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz",
@@ -2236,6 +3990,62 @@
"integrity": "sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w==",
"dev": true
},
+ "node_modules/prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/prettier": {
+ "version": "3.2.5",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz",
+ "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==",
+ "dev": true,
+ "bin": {
+ "prettier": "bin/prettier.cjs"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ },
+ "node_modules/prettier-linter-helpers": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz",
+ "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==",
+ "dev": true,
+ "dependencies": {
+ "fast-diff": "^1.1.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/prettier-plugin-organize-imports": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/prettier-plugin-organize-imports/-/prettier-plugin-organize-imports-3.2.4.tgz",
+ "integrity": "sha512-6m8WBhIp0dfwu0SkgfOxJqh+HpdyfqSSLfKKRZSFbDuEQXDDndb8fTpRWkUrX/uBenkex3MgnVk0J3b3Y5byog==",
+ "dev": true,
+ "peerDependencies": {
+ "@volar/vue-language-plugin-pug": "^1.0.4",
+ "@volar/vue-typescript": "^1.0.4",
+ "prettier": ">=2.0",
+ "typescript": ">=2.9"
+ },
+ "peerDependenciesMeta": {
+ "@volar/vue-language-plugin-pug": {
+ "optional": true
+ },
+ "@volar/vue-typescript": {
+ "optional": true
+ }
+ }
+ },
"node_modules/pretty-format": {
"version": "29.7.0",
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
@@ -2250,6 +4060,15 @@
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
+ "node_modules/punycode": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/qs": {
"version": "6.11.2",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz",
@@ -2265,12 +4084,215 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
"node_modules/react-is": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==",
"dev": true
},
+ "node_modules/read-pkg": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz",
+ "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==",
+ "dev": true,
+ "dependencies": {
+ "@types/normalize-package-data": "^2.4.0",
+ "normalize-package-data": "^2.5.0",
+ "parse-json": "^5.0.0",
+ "type-fest": "^0.6.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/read-pkg-up": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz",
+ "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==",
+ "dev": true,
+ "dependencies": {
+ "find-up": "^4.1.0",
+ "read-pkg": "^5.2.0",
+ "type-fest": "^0.8.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/read-pkg-up/node_modules/find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/read-pkg-up/node_modules/locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/read-pkg-up/node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/read-pkg-up/node_modules/p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/read-pkg-up/node_modules/type-fest": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
+ "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/read-pkg/node_modules/type-fest": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz",
+ "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/regexp-tree": {
+ "version": "0.1.27",
+ "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.27.tgz",
+ "integrity": "sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==",
+ "dev": true,
+ "bin": {
+ "regexp-tree": "bin/regexp-tree"
+ }
+ },
+ "node_modules/regjsparser": {
+ "version": "0.10.0",
+ "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.10.0.tgz",
+ "integrity": "sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==",
+ "dev": true,
+ "dependencies": {
+ "jsesc": "~0.5.0"
+ },
+ "bin": {
+ "regjsparser": "bin/parser"
+ }
+ },
+ "node_modules/regjsparser/node_modules/jsesc": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
+ "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==",
+ "dev": true,
+ "bin": {
+ "jsesc": "bin/jsesc"
+ }
+ },
+ "node_modules/resolve": {
+ "version": "1.22.8",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
+ "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
+ "dev": true,
+ "dependencies": {
+ "is-core-module": "^2.13.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "dev": true,
+ "engines": {
+ "iojs": ">=1.0.0",
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "dev": true,
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
"node_modules/rollup": {
"version": "4.12.0",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.12.0.tgz",
@@ -2303,6 +4325,29 @@
"fsevents": "~2.3.2"
}
},
+ "node_modules/run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
"node_modules/semver": {
"version": "7.6.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz",
@@ -2392,6 +4437,15 @@
"url": "https://github.com/sponsors/isaacs"
}
},
+ "node_modules/slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/socket.io-client": {
"version": "4.7.4",
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.4.tgz",
@@ -2438,6 +4492,38 @@
"node": ">=0.10.0"
}
},
+ "node_modules/spdx-correct": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz",
+ "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==",
+ "dev": true,
+ "dependencies": {
+ "spdx-expression-parse": "^3.0.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "node_modules/spdx-exceptions": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz",
+ "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==",
+ "dev": true
+ },
+ "node_modules/spdx-expression-parse": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
+ "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
+ "dev": true,
+ "dependencies": {
+ "spdx-exceptions": "^2.1.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "node_modules/spdx-license-ids": {
+ "version": "3.0.17",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.17.tgz",
+ "integrity": "sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==",
+ "dev": true
+ },
"node_modules/split2": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
@@ -2459,6 +4545,18 @@
"integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==",
"dev": true
},
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/strip-final-newline": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz",
@@ -2471,6 +4569,30 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/strip-indent": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz",
+ "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==",
+ "dev": true,
+ "dependencies": {
+ "min-indent": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/strip-literal": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-2.0.0.tgz",
@@ -2529,6 +4651,34 @@
"node": ">=8"
}
},
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/synckit": {
+ "version": "0.8.8",
+ "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz",
+ "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==",
+ "dev": true,
+ "dependencies": {
+ "@pkgr/core": "^0.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/unts"
+ }
+ },
"node_modules/test-exclude": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz",
@@ -2543,6 +4693,12 @@
"node": ">=8"
}
},
+ "node_modules/text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
+ "dev": true
+ },
"node_modules/tinybench": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.6.0.tgz",
@@ -2576,6 +4732,48 @@
"node": ">=4"
}
},
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/ts-api-utils": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.2.1.tgz",
+ "integrity": "sha512-RIYA36cJn2WiH9Hy77hdF9r7oEwxAtB/TS9/S4Qd90Ap4z5FSiin5zEiTL44OII1Y3IIlEvxwxFUVgrHSZ/UpA==",
+ "dev": true,
+ "engines": {
+ "node": ">=16"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.2.0"
+ }
+ },
+ "node_modules/tslib": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
+ "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==",
+ "dev": true
+ },
+ "node_modules/type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
"node_modules/type-detect": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
@@ -2585,6 +4783,18 @@
"node": ">=4"
}
},
+ "node_modules/type-fest": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/typescript": {
"version": "5.3.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz",
@@ -2610,6 +4820,45 @@
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
"dev": true
},
+ "node_modules/update-browserslist-db": {
+ "version": "1.0.13",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz",
+ "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "escalade": "^3.1.1",
+ "picocolors": "^1.0.0"
+ },
+ "bin": {
+ "update-browserslist-db": "cli.js"
+ },
+ "peerDependencies": {
+ "browserslist": ">= 4.21.0"
+ }
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
"node_modules/v8-to-istanbul": {
"version": "9.2.0",
"resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz",
@@ -2624,6 +4873,16 @@
"node": ">=10.12.0"
}
},
+ "node_modules/validate-npm-package-license": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
+ "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
+ "dev": true,
+ "dependencies": {
+ "spdx-correct": "^3.0.0",
+ "spdx-expression-parse": "^3.0.0"
+ }
+ },
"node_modules/vite": {
"version": "5.1.4",
"resolved": "https://registry.npmjs.org/vite/-/vite-5.1.4.tgz",
diff --git a/e2e/package.json b/e2e/package.json
index 7bbdfd1d9..9f231c9dd 100644
--- a/e2e/package.json
+++ b/e2e/package.json
@@ -7,7 +7,11 @@
"scripts": {
"test": "vitest --config vitest.config.ts",
"test:web": "npx playwright test",
- "start:web": "npx playwright test --ui"
+ "start:web": "npx playwright test --ui",
+ "format": "prettier --check .",
+ "format:fix": "prettier --write .",
+ "lint": "eslint \"src/**/*.ts\" --max-warnings 0",
+ "lint:fix": "npm run lint -- --fix"
},
"keywords": [],
"author": "",
@@ -19,10 +23,21 @@
"@types/luxon": "^3.4.2",
"@types/node": "^20.11.17",
"@types/pg": "^8.11.0",
+ "@types/pngjs": "^6.0.4",
"@types/supertest": "^6.0.2",
+ "@typescript-eslint/eslint-plugin": "^7.1.0",
+ "@typescript-eslint/parser": "^7.1.0",
"@vitest/coverage-v8": "^1.3.0",
+ "eslint": "^8.57.0",
+ "eslint-config-prettier": "^9.1.0",
+ "eslint-plugin-prettier": "^5.1.3",
+ "eslint-plugin-unicorn": "^51.0.1",
+ "exiftool-vendored": "^24.5.0",
"luxon": "^3.4.4",
"pg": "^8.11.3",
+ "pngjs": "^7.0.0",
+ "prettier": "^3.2.5",
+ "prettier-plugin-organize-imports": "^3.2.4",
"socket.io-client": "^4.7.4",
"supertest": "^6.3.4",
"typescript": "^5.3.3",
diff --git a/e2e/src/api/specs/activity.e2e-spec.ts b/e2e/src/api/specs/activity.e2e-spec.ts
index 39c075dba..365ad66dc 100644
--- a/e2e/src/api/specs/activity.e2e-spec.ts
+++ b/e2e/src/api/specs/activity.e2e-spec.ts
@@ -20,10 +20,7 @@ describe('/activity', () => {
let album: AlbumResponseDto;
const createActivity = (dto: ActivityCreateDto, accessToken?: string) =>
- create(
- { activityCreateDto: dto },
- { headers: asBearerAuth(accessToken || admin.accessToken) },
- );
+ create({ activityCreateDto: dto }, { headers: asBearerAuth(accessToken || admin.accessToken) });
beforeAll(async () => {
apiUtils.setup();
@@ -56,13 +53,9 @@ describe('/activity', () => {
});
it('should require an albumId', async () => {
- const { status, body } = await request(app)
- .get('/activity')
- .set('Authorization', `Bearer ${admin.accessToken}`);
+ const { status, body } = await request(app).get('/activity').set('Authorization', `Bearer ${admin.accessToken}`);
expect(status).toEqual(400);
- expect(body).toEqual(
- errorDto.badRequest(expect.arrayContaining(['albumId must be a UUID'])),
- );
+ expect(body).toEqual(errorDto.badRequest(expect.arrayContaining(['albumId must be a UUID'])));
});
it('should reject an invalid albumId', async () => {
@@ -71,9 +64,7 @@ describe('/activity', () => {
.query({ albumId: uuidDto.invalid })
.set('Authorization', `Bearer ${admin.accessToken}`);
expect(status).toEqual(400);
- expect(body).toEqual(
- errorDto.badRequest(expect.arrayContaining(['albumId must be a UUID'])),
- );
+ expect(body).toEqual(errorDto.badRequest(expect.arrayContaining(['albumId must be a UUID'])));
});
it('should reject an invalid assetId', async () => {
@@ -82,9 +73,7 @@ describe('/activity', () => {
.query({ albumId: uuidDto.notFound, assetId: uuidDto.invalid })
.set('Authorization', `Bearer ${admin.accessToken}`);
expect(status).toEqual(400);
- expect(body).toEqual(
- errorDto.badRequest(expect.arrayContaining(['assetId must be a UUID'])),
- );
+ expect(body).toEqual(errorDto.badRequest(expect.arrayContaining(['assetId must be a UUID'])));
});
it('should start off empty', async () => {
@@ -160,9 +149,7 @@ describe('/activity', () => {
});
it('should filter by userId', async () => {
- const [reaction] = await Promise.all([
- createActivity({ albumId: album.id, type: ReactionType.Like }),
- ]);
+ const [reaction] = await Promise.all([createActivity({ albumId: album.id, type: ReactionType.Like })]);
const response1 = await request(app)
.get('/activity')
@@ -215,9 +202,7 @@ describe('/activity', () => {
.set('Authorization', `Bearer ${admin.accessToken}`)
.send({ albumId: uuidDto.invalid });
expect(status).toEqual(400);
- expect(body).toEqual(
- errorDto.badRequest(expect.arrayContaining(['albumId must be a UUID'])),
- );
+ expect(body).toEqual(errorDto.badRequest(expect.arrayContaining(['albumId must be a UUID'])));
});
it('should require a comment when type is comment', async () => {
@@ -226,12 +211,7 @@ describe('/activity', () => {
.set('Authorization', `Bearer ${admin.accessToken}`)
.send({ albumId: uuidDto.notFound, type: 'comment', comment: null });
expect(status).toEqual(400);
- expect(body).toEqual(
- errorDto.badRequest([
- 'comment must be a string',
- 'comment should not be empty',
- ]),
- );
+ expect(body).toEqual(errorDto.badRequest(['comment must be a string', 'comment should not be empty']));
});
it('should add a comment to an album', async () => {
@@ -271,9 +251,7 @@ describe('/activity', () => {
});
it('should return a 200 for a duplicate like on the album', async () => {
- const [reaction] = await Promise.all([
- createActivity({ albumId: album.id, type: ReactionType.Like }),
- ]);
+ const [reaction] = await Promise.all([createActivity({ albumId: album.id, type: ReactionType.Like })]);
const { status, body } = await request(app)
.post('/activity')
@@ -356,9 +334,7 @@ describe('/activity', () => {
describe('DELETE /activity/:id', () => {
it('should require authentication', async () => {
- const { status, body } = await request(app).delete(
- `/activity/${uuidDto.notFound}`,
- );
+ const { status, body } = await request(app).delete(`/activity/${uuidDto.notFound}`);
expect(status).toBe(401);
expect(body).toEqual(errorDto.unauthorized);
});
@@ -420,9 +396,7 @@ describe('/activity', () => {
.set('Authorization', `Bearer ${nonOwner.accessToken}`);
expect(status).toBe(400);
- expect(body).toEqual(
- errorDto.badRequest('Not found or no activity.delete access'),
- );
+ expect(body).toEqual(errorDto.badRequest('Not found or no activity.delete access'));
});
it('should let a non-owner remove their own comment', async () => {
diff --git a/e2e/src/api/specs/album.e2e-spec.ts b/e2e/src/api/specs/album.e2e-spec.ts
index 3385e50f4..99a50106e 100644
--- a/e2e/src/api/specs/album.e2e-spec.ts
+++ b/e2e/src/api/specs/album.e2e-spec.ts
@@ -41,7 +41,7 @@ describe('/album', () => {
]);
[user1Asset1, user1Asset2] = await Promise.all([
- apiUtils.createAsset(user1.accessToken),
+ apiUtils.createAsset(user1.accessToken, { isFavorite: true }),
apiUtils.createAsset(user1.accessToken),
]);
@@ -93,10 +93,7 @@ describe('/album', () => {
}),
]);
- await deleteUser(
- { id: user3.userId },
- { headers: asBearerAuth(admin.accessToken) },
- );
+ await deleteUser({ id: user3.userId }, { headers: asBearerAuth(admin.accessToken) });
});
describe('GET /album', () => {
@@ -111,9 +108,7 @@ describe('/album', () => {
.get('/album?shared=invalid')
.set('Authorization', `Bearer ${user1.accessToken}`);
expect(status).toEqual(400);
- expect(body).toEqual(
- errorDto.badRequest(['shared must be a boolean value']),
- );
+ expect(body).toEqual(errorDto.badRequest(['shared must be a boolean value']));
});
it('should reject an invalid assetId param', async () => {
@@ -124,6 +119,17 @@ describe('/album', () => {
expect(body).toEqual(errorDto.badRequest(['assetId must be a UUID']));
});
+ it("should not show other users' favorites", async () => {
+ const { status, body } = await request(app)
+ .get(`/album/${user1Albums[0].id}?withoutAssets=false`)
+ .set('Authorization', `Bearer ${user2.accessToken}`);
+ expect(status).toEqual(200);
+ expect(body).toEqual({
+ ...user1Albums[0],
+ assets: [expect.objectContaining({ isFavorite: false })],
+ });
+ });
+
it('should not return shared albums with a deleted owner', async () => {
const { status, body } = await request(app)
.get('/album?shared=true')
@@ -153,9 +159,7 @@ describe('/album', () => {
});
it('should return the album collection including owned and shared', async () => {
- const { status, body } = await request(app)
- .get('/album')
- .set('Authorization', `Bearer ${user1.accessToken}`);
+ const { status, body } = await request(app).get('/album').set('Authorization', `Bearer ${user1.accessToken}`);
expect(status).toBe(200);
expect(body).toHaveLength(3);
expect(body).toEqual(
@@ -250,9 +254,7 @@ describe('/album', () => {
describe('GET /album/:id', () => {
it('should require authentication', async () => {
- const { status, body } = await request(app).get(
- `/album/${user1Albums[0].id}`,
- );
+ const { status, body } = await request(app).get(`/album/${user1Albums[0].id}`);
expect(status).toBe(401);
expect(body).toEqual(errorDto.unauthorized);
});
@@ -265,7 +267,7 @@ describe('/album', () => {
expect(status).toBe(200);
expect(body).toEqual({
...user1Albums[0],
- assets: [expect.objectContaining(user1Albums[0].assets[0])],
+ assets: [expect.objectContaining({ id: user1Albums[0].assets[0].id })],
});
});
@@ -277,7 +279,7 @@ describe('/album', () => {
expect(status).toBe(200);
expect(body).toEqual({
...user2Albums[0],
- assets: [expect.objectContaining(user2Albums[0].assets[0])],
+ assets: [expect.objectContaining({ id: user2Albums[0].assets[0].id })],
});
});
@@ -289,7 +291,7 @@ describe('/album', () => {
expect(status).toBe(200);
expect(body).toEqual({
...user1Albums[0],
- assets: [expect.objectContaining(user1Albums[0].assets[0])],
+ assets: [expect.objectContaining({ id: user1Albums[0].assets[0].id })],
});
});
@@ -326,9 +328,7 @@ describe('/album', () => {
describe('POST /album', () => {
it('should require authentication', async () => {
- const { status, body } = await request(app)
- .post('/album')
- .send({ albumName: 'New album' });
+ const { status, body } = await request(app).post('/album').send({ albumName: 'New album' });
expect(status).toBe(401);
expect(body).toEqual(errorDto.unauthorized);
});
@@ -360,9 +360,7 @@ describe('/album', () => {
describe('PUT /album/:id/assets', () => {
it('should require authentication', async () => {
- const { status, body } = await request(app).put(
- `/album/${user1Albums[0].id}/assets`,
- );
+ const { status, body } = await request(app).put(`/album/${user1Albums[0].id}/assets`);
expect(status).toBe(401);
expect(body).toEqual(errorDto.unauthorized);
});
@@ -375,9 +373,7 @@ describe('/album', () => {
.send({ ids: [asset.id] });
expect(status).toBe(200);
- expect(body).toEqual([
- expect.objectContaining({ id: asset.id, success: true }),
- ]);
+ expect(body).toEqual([expect.objectContaining({ id: asset.id, success: true })]);
});
it('should be able to add own asset to shared album', async () => {
@@ -388,9 +384,7 @@ describe('/album', () => {
.send({ ids: [asset.id] });
expect(status).toBe(200);
- expect(body).toEqual([
- expect.objectContaining({ id: asset.id, success: true }),
- ]);
+ expect(body).toEqual([expect.objectContaining({ id: asset.id, success: true })]);
});
});
@@ -473,9 +467,7 @@ describe('/album', () => {
.send({ ids: [user1Asset1.id] });
expect(status).toBe(200);
- expect(body).toEqual([
- expect.objectContaining({ id: user1Asset1.id, success: true }),
- ]);
+ expect(body).toEqual([expect.objectContaining({ id: user1Asset1.id, success: true })]);
});
it('should be able to remove own asset from shared album', async () => {
@@ -485,9 +477,7 @@ describe('/album', () => {
.send({ ids: [user1Asset1.id] });
expect(status).toBe(200);
- expect(body).toEqual([
- expect.objectContaining({ id: user1Asset1.id, success: true }),
- ]);
+ expect(body).toEqual([expect.objectContaining({ id: user1Asset1.id, success: true })]);
});
});
@@ -501,9 +491,7 @@ describe('/album', () => {
});
it('should require authentication', async () => {
- const { status, body } = await request(app)
- .put(`/album/${user1Albums[0].id}/users`)
- .send({ sharedUserIds: [] });
+ const { status, body } = await request(app).put(`/album/${user1Albums[0].id}/users`).send({ sharedUserIds: [] });
expect(status).toBe(401);
expect(body).toEqual(errorDto.unauthorized);
diff --git a/e2e/src/api/specs/asset.e2e-spec.ts b/e2e/src/api/specs/asset.e2e-spec.ts
index db1821260..2873bb0c3 100644
--- a/e2e/src/api/specs/asset.e2e-spec.ts
+++ b/e2e/src/api/specs/asset.e2e-spec.ts
@@ -1,16 +1,33 @@
import {
AssetFileUploadResponseDto,
AssetResponseDto,
+ AssetTypeEnum,
LoginResponseDto,
SharedLinkType,
} from '@immich/sdk';
+import { exiftool } from 'exiftool-vendored';
import { DateTime } from 'luxon';
+import { createHash } from 'node:crypto';
+import { readFile, writeFile } from 'node:fs/promises';
+import { basename, join } from 'node:path';
import { Socket } from 'socket.io-client';
import { createUserDto, uuidDto } from 'src/fixtures';
import { errorDto } from 'src/responses';
-import { apiUtils, app, dbUtils } from 'src/utils';
+import { apiUtils, app, dbUtils, tempDir, testAssetDir, wsUtils } from 'src/utils';
import request from 'supertest';
-import { beforeAll, describe, expect, it } from 'vitest';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
+
+const TEN_TIMES = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
+
+const locationAssetFilepath = `${testAssetDir}/metadata/gps-position/thompson-springs.jpg`;
+
+const sha1 = (bytes: Buffer) => createHash('sha1').update(bytes).digest('base64');
+
+const readTags = async (bytes: Buffer, filename: string) => {
+ const filepath = join(tempDir, filename);
+ await writeFile(filepath, bytes);
+ return exiftool.read(filepath);
+};
const today = DateTime.fromObject({
year: 2023,
@@ -24,67 +41,81 @@ describe('/asset', () => {
let user1: LoginResponseDto;
let user2: LoginResponseDto;
let userStats: LoginResponseDto;
- let asset1: AssetFileUploadResponseDto;
- let asset2: AssetFileUploadResponseDto;
- let asset3: AssetFileUploadResponseDto;
- let asset4: AssetFileUploadResponseDto; // user2 asset
- let asset5: AssetFileUploadResponseDto;
- let asset6: AssetFileUploadResponseDto;
+ let user1Assets: AssetFileUploadResponseDto[];
+ let user2Assets: AssetFileUploadResponseDto[];
+ let assetLocation: AssetFileUploadResponseDto;
let ws: Socket;
beforeAll(async () => {
apiUtils.setup();
await dbUtils.reset();
admin = await apiUtils.adminSetup({ onboarding: false });
- [user1, user2, userStats] = await Promise.all([
+
+ [ws, user1, user2, userStats] = await Promise.all([
+ wsUtils.connect(admin.accessToken),
apiUtils.userSetup(admin.accessToken, createUserDto.user1),
apiUtils.userSetup(admin.accessToken, createUserDto.user2),
apiUtils.userSetup(admin.accessToken, createUserDto.user3),
]);
- [asset1, asset2, asset3, asset4, asset5, asset6] = await Promise.all([
- apiUtils.createAsset(user1.accessToken),
- apiUtils.createAsset(user1.accessToken),
- apiUtils.createAsset(
- user1.accessToken,
- {
- isFavorite: true,
- isExternal: true,
- isReadOnly: true,
- fileCreatedAt: yesterday.toISO(),
- fileModifiedAt: yesterday.toISO(),
- },
- { filename: 'example.mp4' },
- ),
- apiUtils.createAsset(user2.accessToken),
- apiUtils.createAsset(user1.accessToken),
- apiUtils.createAsset(user1.accessToken),
+ // asset location
+ assetLocation = await apiUtils.createAsset(admin.accessToken, {
+ assetData: {
+ filename: 'thompson-springs.jpg',
+ bytes: await readFile(locationAssetFilepath),
+ },
+ });
+ await wsUtils.waitForEvent({ event: 'upload', assetId: assetLocation.id });
+
+ user1Assets = await Promise.all([
+ apiUtils.createAsset(user1.accessToken),
+ apiUtils.createAsset(user1.accessToken),
+ apiUtils.createAsset(user1.accessToken, {
+ isFavorite: true,
+ isReadOnly: true,
+ fileCreatedAt: yesterday.toISO(),
+ fileModifiedAt: yesterday.toISO(),
+ assetData: { filename: 'example.mp4' },
+ }),
+ apiUtils.createAsset(user1.accessToken),
+ apiUtils.createAsset(user1.accessToken),
+ ]);
+
+ user2Assets = await Promise.all([apiUtils.createAsset(user2.accessToken)]);
+
+ for (const asset of [...user1Assets, ...user2Assets]) {
+ expect(asset.duplicate).toBe(false);
+ }
+
+ await Promise.all([
// stats
apiUtils.createAsset(userStats.accessToken),
apiUtils.createAsset(userStats.accessToken, { isFavorite: true }),
apiUtils.createAsset(userStats.accessToken, { isArchived: true }),
- apiUtils.createAsset(
- userStats.accessToken,
- {
- isArchived: true,
- isFavorite: true,
- },
- { filename: 'example.mp4' },
- ),
+ apiUtils.createAsset(userStats.accessToken, {
+ isArchived: true,
+ isFavorite: true,
+ assetData: { filename: 'example.mp4' },
+ }),
]);
const person1 = await apiUtils.createPerson(user1.accessToken, {
name: 'Test Person',
});
- await dbUtils.createFace({ assetId: asset1.id, personId: person1.id });
+ await dbUtils.createFace({
+ assetId: user1Assets[0].id,
+ personId: person1.id,
+ });
+ }, 30_000);
+
+ afterAll(() => {
+ wsUtils.disconnect(ws);
});
describe('GET /asset/:id', () => {
it('should require authentication', async () => {
- const { status, body } = await request(app).get(
- `/asset/${uuidDto.notFound}`,
- );
+ const { status, body } = await request(app).get(`/asset/${uuidDto.notFound}`);
expect(body).toEqual(errorDto.unauthorized);
expect(status).toBe(401);
});
@@ -99,7 +130,7 @@ describe('/asset', () => {
it('should require access', async () => {
const { status, body } = await request(app)
- .get(`/asset/${asset4.id}`)
+ .get(`/asset/${user2Assets[0].id}`)
.set('Authorization', `Bearer ${user1.accessToken}`);
expect(status).toBe(400);
expect(body).toEqual(errorDto.noPermission);
@@ -107,33 +138,31 @@ describe('/asset', () => {
it('should get the asset info', async () => {
const { status, body } = await request(app)
- .get(`/asset/${asset1.id}`)
+ .get(`/asset/${user1Assets[0].id}`)
.set('Authorization', `Bearer ${user1.accessToken}`);
expect(status).toBe(200);
- expect(body).toMatchObject({ id: asset1.id });
+ expect(body).toMatchObject({ id: user1Assets[0].id });
});
it('should work with a shared link', async () => {
const sharedLink = await apiUtils.createSharedLink(user1.accessToken, {
type: SharedLinkType.Individual,
- assetIds: [asset1.id],
+ assetIds: [user1Assets[0].id],
});
- const { status, body } = await request(app).get(
- `/asset/${asset1.id}?key=${sharedLink.key}`,
- );
+ const { status, body } = await request(app).get(`/asset/${user1Assets[0].id}?key=${sharedLink.key}`);
expect(status).toBe(200);
- expect(body).toMatchObject({ id: asset1.id });
+ expect(body).toMatchObject({ id: user1Assets[0].id });
});
it('should not send people data for shared links for un-authenticated users', async () => {
const { status, body } = await request(app)
- .get(`/asset/${asset1.id}`)
+ .get(`/asset/${user1Assets[0].id}`)
.set('Authorization', `Bearer ${user1.accessToken}`);
expect(status).toEqual(200);
expect(body).toMatchObject({
- id: asset1.id,
+ id: user1Assets[0].id,
isFavorite: false,
people: [
{
@@ -148,12 +177,10 @@ describe('/asset', () => {
const sharedLink = await apiUtils.createSharedLink(user1.accessToken, {
type: SharedLinkType.Individual,
- assetIds: [asset1.id],
+ assetIds: [user1Assets[0].id],
});
- const data = await request(app).get(
- `/asset/${asset1.id}?key=${sharedLink.key}`,
- );
+ const data = await request(app).get(`/asset/${user1Assets[0].id}?key=${sharedLink.key}`);
expect(data.status).toBe(200);
expect(data.body).toMatchObject({ people: [] });
});
@@ -236,7 +263,7 @@ describe('/asset', () => {
expect(body).toEqual(errorDto.unauthorized);
});
- it.each(Array(10))('should return 1 random assets', async () => {
+ it.each(TEN_TIMES)('should return 1 random assets', async () => {
const { status, body } = await request(app)
.get('/asset/random')
.set('Authorization', `Bearer ${user1.accessToken}`);
@@ -246,14 +273,9 @@ describe('/asset', () => {
const assets: AssetResponseDto[] = body;
expect(assets.length).toBe(1);
expect(assets[0].ownerId).toBe(user1.userId);
- //
- // assets owned by user2
- expect(assets[0].id).not.toBe(asset4.id);
- // assets owned by user1
- expect([asset1.id, asset2.id, asset3.id]).toContain(assets[0].id);
});
- it.each(Array(10))('should return 2 random assets', async () => {
+ it.each(TEN_TIMES)('should return 2 random assets', async () => {
const { status, body } = await request(app)
.get('/asset/random?count=2')
.set('Authorization', `Bearer ${user1.accessToken}`);
@@ -265,22 +287,18 @@ describe('/asset', () => {
for (const asset of assets) {
expect(asset.ownerId).toBe(user1.userId);
- // assets owned by user1
- expect([asset1.id, asset2.id, asset3.id]).toContain(asset.id);
- // assets owned by user2
- expect(asset.id).not.toBe(asset4.id);
}
});
- it.each(Array(10))(
+ it.each(TEN_TIMES)(
'should return 1 asset if there are 10 assets in the database but user 2 only has 1',
async () => {
const { status, body } = await request(app)
- .get('/[]asset/random')
+ .get('/asset/random')
.set('Authorization', `Bearer ${user2.accessToken}`);
expect(status).toBe(200);
- expect(body).toEqual([expect.objectContaining({ id: asset4.id })]);
+ expect(body).toEqual([expect.objectContaining({ id: user2Assets[0].id })]);
},
);
@@ -295,9 +313,7 @@ describe('/asset', () => {
describe('PUT /asset/:id', () => {
it('should require authentication', async () => {
- const { status, body } = await request(app).put(
- `/asset/:${uuidDto.notFound}`,
- );
+ const { status, body } = await request(app).put(`/asset/:${uuidDto.notFound}`);
expect(status).toBe(401);
expect(body).toEqual(errorDto.unauthorized);
});
@@ -312,44 +328,44 @@ describe('/asset', () => {
it('should require access', async () => {
const { status, body } = await request(app)
- .put(`/asset/${asset4.id}`)
+ .put(`/asset/${user2Assets[0].id}`)
.set('Authorization', `Bearer ${user1.accessToken}`);
expect(status).toBe(400);
expect(body).toEqual(errorDto.noPermission);
});
it('should favorite an asset', async () => {
- const before = await apiUtils.getAssetInfo(user1.accessToken, asset1.id);
+ const before = await apiUtils.getAssetInfo(user1.accessToken, user1Assets[0].id);
expect(before.isFavorite).toBe(false);
const { status, body } = await request(app)
- .put(`/asset/${asset1.id}`)
+ .put(`/asset/${user1Assets[0].id}`)
.set('Authorization', `Bearer ${user1.accessToken}`)
.send({ isFavorite: true });
- expect(body).toMatchObject({ id: asset1.id, isFavorite: true });
+ expect(body).toMatchObject({ id: user1Assets[0].id, isFavorite: true });
expect(status).toEqual(200);
});
it('should archive an asset', async () => {
- const before = await apiUtils.getAssetInfo(user1.accessToken, asset1.id);
+ const before = await apiUtils.getAssetInfo(user1.accessToken, user1Assets[0].id);
expect(before.isArchived).toBe(false);
const { status, body } = await request(app)
- .put(`/asset/${asset1.id}`)
+ .put(`/asset/${user1Assets[0].id}`)
.set('Authorization', `Bearer ${user1.accessToken}`)
.send({ isArchived: true });
- expect(body).toMatchObject({ id: asset1.id, isArchived: true });
+ expect(body).toMatchObject({ id: user1Assets[0].id, isArchived: true });
expect(status).toEqual(200);
});
it('should update date time original', async () => {
const { status, body } = await request(app)
- .put(`/asset/${asset1.id}`)
+ .put(`/asset/${user1Assets[0].id}`)
.set('Authorization', `Bearer ${user1.accessToken}`)
.send({ dateTimeOriginal: '2023-11-19T18:11:00.000-07:00' });
expect(body).toMatchObject({
- id: asset1.id,
+ id: user1Assets[0].id,
exifInfo: expect.objectContaining({
dateTimeOriginal: '2023-11-20T01:11:00.000Z',
}),
@@ -371,7 +387,7 @@ describe('/asset', () => {
{ latitude: 12, longitude: 181 },
]) {
const { status, body } = await request(app)
- .put(`/asset/${asset1.id}`)
+ .put(`/asset/${user1Assets[0].id}`)
.send(test)
.set('Authorization', `Bearer ${user1.accessToken}`);
expect(status).toBe(400);
@@ -381,12 +397,12 @@ describe('/asset', () => {
it('should update gps data', async () => {
const { status, body } = await request(app)
- .put(`/asset/${asset1.id}`)
+ .put(`/asset/${user1Assets[0].id}`)
.set('Authorization', `Bearer ${user1.accessToken}`)
.send({ latitude: 12, longitude: 12 });
expect(body).toMatchObject({
- id: asset1.id,
+ id: user1Assets[0].id,
exifInfo: expect.objectContaining({ latitude: 12, longitude: 12 }),
});
expect(status).toEqual(200);
@@ -394,11 +410,11 @@ describe('/asset', () => {
it('should set the description', async () => {
const { status, body } = await request(app)
- .put(`/asset/${asset1.id}`)
+ .put(`/asset/${user1Assets[0].id}`)
.set('Authorization', `Bearer ${user1.accessToken}`)
.send({ description: 'Test asset description' });
expect(body).toMatchObject({
- id: asset1.id,
+ id: user1Assets[0].id,
exifInfo: expect.objectContaining({
description: 'Test asset description',
}),
@@ -408,12 +424,12 @@ describe('/asset', () => {
it('should return tagged people', async () => {
const { status, body } = await request(app)
- .put(`/asset/${asset1.id}`)
+ .put(`/asset/${user1Assets[0].id}`)
.set('Authorization', `Bearer ${user1.accessToken}`)
.send({ isFavorite: true });
expect(status).toEqual(200);
expect(body).toMatchObject({
- id: asset1.id,
+ id: user1Assets[0].id,
isFavorite: true,
people: [
{
@@ -445,9 +461,7 @@ describe('/asset', () => {
.set('Authorization', `Bearer ${admin.accessToken}`);
expect(status).toBe(400);
- expect(body).toEqual(
- errorDto.badRequest(['each value in ids must be a UUID']),
- );
+ expect(body).toEqual(errorDto.badRequest(['each value in ids must be a UUID']));
});
it('should throw an error when the id is not found', async () => {
@@ -457,9 +471,7 @@ describe('/asset', () => {
.set('Authorization', `Bearer ${admin.accessToken}`);
expect(status).toBe(400);
- expect(body).toEqual(
- errorDto.badRequest('Not found or no asset.delete access'),
- );
+ expect(body).toEqual(errorDto.badRequest('Not found or no asset.delete access'));
});
it('should move an asset to the trash', async () => {
@@ -478,4 +490,260 @@ describe('/asset', () => {
expect(after.isTrashed).toBe(true);
});
});
+
+ describe('POST /asset/upload', () => {
+ const tests = [
+ {
+ input: 'formats/jpg/el_torcal_rocks.jpg',
+ expected: {
+ type: AssetTypeEnum.Image,
+ originalFileName: 'el_torcal_rocks',
+ resized: true,
+ exifInfo: {
+ dateTimeOriginal: '2012-08-05T11:39:59.000Z',
+ exifImageWidth: 512,
+ exifImageHeight: 341,
+ latitude: null,
+ longitude: null,
+ focalLength: 75,
+ iso: 200,
+ fNumber: 11,
+ exposureTime: '1/160',
+ fileSizeInByte: 53_493,
+ make: 'SONY',
+ model: 'DSLR-A550',
+ orientation: null,
+ description: 'SONY DSC',
+ },
+ },
+ },
+ {
+ input: 'formats/heic/IMG_2682.heic',
+ expected: {
+ type: AssetTypeEnum.Image,
+ originalFileName: 'IMG_2682',
+ resized: true,
+ fileCreatedAt: '2019-03-21T16:04:22.348Z',
+ exifInfo: {
+ dateTimeOriginal: '2019-03-21T16:04:22.348Z',
+ exifImageWidth: 4032,
+ exifImageHeight: 3024,
+ latitude: 41.2203,
+ longitude: -96.071_625,
+ make: 'Apple',
+ model: 'iPhone 7',
+ lensModel: 'iPhone 7 back camera 3.99mm f/1.8',
+ fileSizeInByte: 880_703,
+ exposureTime: '1/887',
+ iso: 20,
+ focalLength: 3.99,
+ fNumber: 1.8,
+ timeZone: 'America/Chicago',
+ },
+ },
+ },
+ {
+ input: 'formats/png/density_plot.png',
+ expected: {
+ type: AssetTypeEnum.Image,
+ originalFileName: 'density_plot',
+ resized: true,
+ exifInfo: {
+ exifImageWidth: 800,
+ exifImageHeight: 800,
+ latitude: null,
+ longitude: null,
+ fileSizeInByte: 25_408,
+ },
+ },
+ },
+ {
+ input: 'formats/raw/Nikon/D80/glarus.nef',
+ expected: {
+ type: AssetTypeEnum.Image,
+ originalFileName: 'glarus',
+ resized: true,
+ fileCreatedAt: '2010-07-20T17:27:12.000Z',
+ exifInfo: {
+ make: 'NIKON CORPORATION',
+ model: 'NIKON D80',
+ exposureTime: '1/200',
+ fNumber: 10,
+ focalLength: 18,
+ iso: 100,
+ fileSizeInByte: 9_057_784,
+ dateTimeOriginal: '2010-07-20T17:27:12.000Z',
+ latitude: null,
+ longitude: null,
+ orientation: '1',
+ },
+ },
+ },
+ {
+ input: 'formats/raw/Nikon/D700/philadelphia.nef',
+ expected: {
+ type: AssetTypeEnum.Image,
+ originalFileName: 'philadelphia',
+ resized: true,
+ fileCreatedAt: '2016-09-22T22:10:29.060Z',
+ exifInfo: {
+ make: 'NIKON CORPORATION',
+ model: 'NIKON D700',
+ exposureTime: '1/400',
+ fNumber: 11,
+ focalLength: 85,
+ iso: 200,
+ fileSizeInByte: 15_856_335,
+ dateTimeOriginal: '2016-09-22T22:10:29.060Z',
+ latitude: null,
+ longitude: null,
+ orientation: '1',
+ timeZone: 'UTC-5',
+ },
+ },
+ },
+ ];
+
+ for (const { input, expected } of tests) {
+ it(`should generate a thumbnail for ${input}`, async () => {
+ const filepath = join(testAssetDir, input);
+ const { id, duplicate } = await apiUtils.createAsset(admin.accessToken, {
+ assetData: { bytes: await readFile(filepath), filename: basename(filepath) },
+ });
+
+ expect(duplicate).toBe(false);
+
+ await wsUtils.waitForEvent({ event: 'upload', assetId: id });
+
+ const asset = await apiUtils.getAssetInfo(admin.accessToken, id);
+
+ expect(asset.exifInfo).toBeDefined();
+ expect(asset.exifInfo).toMatchObject(expected.exifInfo);
+ expect(asset).toMatchObject(expected);
+ });
+ }
+
+ it('should handle a duplicate', async () => {
+ const filepath = 'formats/jpeg/el_torcal_rocks.jpeg';
+ const { duplicate } = await apiUtils.createAsset(admin.accessToken, {
+ assetData: {
+ bytes: await readFile(join(testAssetDir, filepath)),
+ filename: basename(filepath),
+ },
+ });
+
+ expect(duplicate).toBe(true);
+ });
+
+ // These hashes were created by copying the image files to a Samsung phone,
+ // exporting the video from Samsung's stock Gallery app, and hashing them locally.
+ // This ensures that immich+exiftool are extracting the videos the same way Samsung does.
+ // DO NOT assume immich+exiftool are doing things correctly and just copy whatever hash it gives
+ // into the test here.
+ const motionTests = [
+ {
+ filepath: 'formats/motionphoto/Samsung One UI 5.jpg',
+ checksum: 'fr14niqCq6N20HB8rJYEvpsUVtI=',
+ },
+ {
+ filepath: 'formats/motionphoto/Samsung One UI 6.jpg',
+ checksum: 'lT9Uviw/FFJYCjfIxAGPTjzAmmw=',
+ },
+ {
+ filepath: 'formats/motionphoto/Samsung One UI 6.heic',
+ checksum: '/ejgzywvgvzvVhUYVfvkLzFBAF0=',
+ },
+ ];
+
+ for (const { filepath, checksum } of motionTests) {
+ it(`should extract motionphoto video from ${filepath}`, async () => {
+ const response = await apiUtils.createAsset(admin.accessToken, {
+ assetData: {
+ bytes: await readFile(join(testAssetDir, filepath)),
+ filename: basename(filepath),
+ },
+ });
+
+ await wsUtils.waitForEvent({ event: 'upload', assetId: response.id });
+
+ expect(response.duplicate).toBe(false);
+
+ const asset = await apiUtils.getAssetInfo(admin.accessToken, response.id);
+ expect(asset.livePhotoVideoId).toBeDefined();
+
+ const video = await apiUtils.getAssetInfo(admin.accessToken, asset.livePhotoVideoId as string);
+ expect(video.checksum).toStrictEqual(checksum);
+ });
+ }
+ });
+
+ describe('GET /asset/thumbnail/:id', () => {
+ it('should require authentication', async () => {
+ const { status, body } = await request(app).get(`/asset/thumbnail/${assetLocation.id}`);
+
+ expect(status).toBe(401);
+ expect(body).toEqual(errorDto.unauthorized);
+ });
+
+ it('should not include gps data for webp thumbnails', async () => {
+ const { status, body, type } = await request(app)
+ .get(`/asset/thumbnail/${assetLocation.id}?format=WEBP`)
+ .set('Authorization', `Bearer ${admin.accessToken}`);
+
+ await wsUtils.waitForEvent({
+ event: 'upload',
+ assetId: assetLocation.id,
+ });
+
+ expect(status).toBe(200);
+ expect(body).toBeDefined();
+ expect(type).toBe('image/webp');
+
+ const exifData = await readTags(body, 'thumbnail.webp');
+ expect(exifData).not.toHaveProperty('GPSLongitude');
+ expect(exifData).not.toHaveProperty('GPSLatitude');
+ });
+
+ it('should not include gps data for jpeg thumbnails', async () => {
+ const { status, body, type } = await request(app)
+ .get(`/asset/thumbnail/${assetLocation.id}?format=JPEG`)
+ .set('Authorization', `Bearer ${admin.accessToken}`);
+
+ expect(status).toBe(200);
+ expect(body).toBeDefined();
+ expect(type).toBe('image/jpeg');
+
+ const exifData = await readTags(body, 'thumbnail.jpg');
+ expect(exifData).not.toHaveProperty('GPSLongitude');
+ expect(exifData).not.toHaveProperty('GPSLatitude');
+ });
+ });
+
+ describe('GET /asset/file/:id', () => {
+ it('should require authentication', async () => {
+ const { status, body } = await request(app).get(`/asset/thumbnail/${assetLocation.id}`);
+
+ expect(status).toBe(401);
+ expect(body).toEqual(errorDto.unauthorized);
+ });
+
+ it('should download the original', async () => {
+ const { status, body, type } = await request(app)
+ .get(`/asset/file/${assetLocation.id}`)
+ .set('Authorization', `Bearer ${admin.accessToken}`);
+
+ expect(status).toBe(200);
+ expect(body).toBeDefined();
+ expect(type).toBe('image/jpeg');
+
+ const asset = await apiUtils.getAssetInfo(admin.accessToken, assetLocation.id);
+
+ const original = await readFile(locationAssetFilepath);
+ const originalChecksum = sha1(original);
+ const downloadChecksum = sha1(body);
+
+ expect(originalChecksum).toBe(downloadChecksum);
+ expect(downloadChecksum).toBe(asset.checksum);
+ });
+ });
});
diff --git a/e2e/src/api/specs/audit.e2e-spec.ts b/e2e/src/api/specs/audit.e2e-spec.ts
index 073106e72..13c753039 100644
--- a/e2e/src/api/specs/audit.e2e-spec.ts
+++ b/e2e/src/api/specs/audit.e2e-spec.ts
@@ -1,9 +1,4 @@
-import {
- deleteAssets,
- getAuditFiles,
- updateAsset,
- type LoginResponseDto,
-} from '@immich/sdk';
+import { deleteAssets, getAuditFiles, updateAsset, type LoginResponseDto } from '@immich/sdk';
import { apiUtils, asBearerAuth, dbUtils, fileUtils } from 'src/utils';
import { beforeAll, describe, expect, it } from 'vitest';
@@ -20,23 +15,20 @@ describe('/audit', () => {
describe('GET :/file-report', () => {
it('excludes assets without issues from report', async () => {
- const [trashedAsset, archivedAsset, _] = await Promise.all([
+ const [trashedAsset, archivedAsset] = await Promise.all([
apiUtils.createAsset(admin.accessToken),
apiUtils.createAsset(admin.accessToken),
apiUtils.createAsset(admin.accessToken),
]);
await Promise.all([
- deleteAssets(
- { assetBulkDeleteDto: { ids: [trashedAsset.id] } },
- { headers: asBearerAuth(admin.accessToken) }
- ),
+ deleteAssets({ assetBulkDeleteDto: { ids: [trashedAsset.id] } }, { headers: asBearerAuth(admin.accessToken) }),
updateAsset(
{
id: archivedAsset.id,
updateAssetDto: { isArchived: true },
},
- { headers: asBearerAuth(admin.accessToken) }
+ { headers: asBearerAuth(admin.accessToken) },
),
]);
diff --git a/e2e/src/api/specs/auth.e2e-spec.ts b/e2e/src/api/specs/auth.e2e-spec.ts
index 20eb6a276..a58e21571 100644
--- a/e2e/src/api/specs/auth.e2e-spec.ts
+++ b/e2e/src/api/specs/auth.e2e-spec.ts
@@ -1,16 +1,6 @@
-import {
- LoginResponseDto,
- getAuthDevices,
- login,
- signUpAdmin,
-} from '@immich/sdk';
+import { LoginResponseDto, getAuthDevices, login, signUpAdmin } from '@immich/sdk';
import { loginDto, signupDto, uuidDto } from 'src/fixtures';
-import {
- deviceDto,
- errorDto,
- loginResponseDto,
- signupResponseDto,
-} from 'src/responses';
+import { deviceDto, errorDto, loginResponseDto, signupResponseDto } from 'src/responses';
import { apiUtils, app, asBearerAuth, dbUtils } from 'src/utils';
import request from 'supertest';
import { beforeAll, beforeEach, describe, expect, it } from 'vitest';
@@ -48,18 +38,14 @@ describe(`/auth/admin-sign-up`, () => {
for (const { should, data } of invalid) {
it(`should ${should}`, async () => {
- const { status, body } = await request(app)
- .post('/auth/admin-sign-up')
- .send(data);
+ const { status, body } = await request(app).post('/auth/admin-sign-up').send(data);
expect(status).toEqual(400);
expect(body).toEqual(errorDto.badRequest());
});
}
it(`should sign up the admin`, async () => {
- const { status, body } = await request(app)
- .post('/auth/admin-sign-up')
- .send(signupDto.admin);
+ const { status, body } = await request(app).post('/auth/admin-sign-up').send(signupDto.admin);
expect(status).toBe(201);
expect(body).toEqual(signupResponseDto.admin);
});
@@ -86,9 +72,7 @@ describe(`/auth/admin-sign-up`, () => {
it('should not allow a second admin to sign up', async () => {
await signUpAdmin({ signUpDto: signupDto.admin });
- const { status, body } = await request(app)
- .post('/auth/admin-sign-up')
- .send(signupDto.admin);
+ const { status, body } = await request(app).post('/auth/admin-sign-up').send(signupDto.admin);
expect(status).toBe(400);
expect(body).toEqual(errorDto.alreadyHasAdmin);
@@ -107,9 +91,7 @@ describe('/auth/*', () => {
describe(`POST /auth/login`, () => {
it('should reject an incorrect password', async () => {
- const { status, body } = await request(app)
- .post('/auth/login')
- .send({ email, password: 'incorrect' });
+ const { status, body } = await request(app).post('/auth/login').send({ email, password: 'incorrect' });
expect(status).toBe(401);
expect(body).toEqual(errorDto.incorrectLogin);
});
@@ -125,9 +107,7 @@ describe('/auth/*', () => {
}
it('should accept a correct password', async () => {
- const { status, body, headers } = await request(app)
- .post('/auth/login')
- .send({ email, password });
+ const { status, body, headers } = await request(app).post('/auth/login').send({ email, password });
expect(status).toBe(201);
expect(body).toEqual(loginResponseDto.admin);
@@ -136,15 +116,9 @@ describe('/auth/*', () => {
const cookies = headers['set-cookie'];
expect(cookies).toHaveLength(3);
- expect(cookies[0]).toEqual(
- `immich_access_token=${token}; HttpOnly; Path=/; Max-Age=34560000; SameSite=Lax;`
- );
- expect(cookies[1]).toEqual(
- 'immich_auth_type=password; HttpOnly; Path=/; Max-Age=34560000; SameSite=Lax;'
- );
- expect(cookies[2]).toEqual(
- 'immich_is_authenticated=true; Path=/; Max-Age=34560000; SameSite=Lax;'
- );
+ expect(cookies[0]).toEqual(`immich_access_token=${token}; HttpOnly; Path=/; Max-Age=34560000; SameSite=Lax;`);
+ expect(cookies[1]).toEqual('immich_auth_type=password; HttpOnly; Path=/; Max-Age=34560000; SameSite=Lax;');
+ expect(cookies[2]).toEqual('immich_is_authenticated=true; Path=/; Max-Age=34560000; SameSite=Lax;');
});
});
@@ -176,18 +150,12 @@ describe('/auth/*', () => {
await login({ loginCredentialDto: loginDto.admin });
}
- await expect(
- getAuthDevices({ headers: asBearerAuth(admin.accessToken) })
- ).resolves.toHaveLength(6);
+ await expect(getAuthDevices({ headers: asBearerAuth(admin.accessToken) })).resolves.toHaveLength(6);
- const { status } = await request(app)
- .delete(`/auth/devices`)
- .set('Authorization', `Bearer ${admin.accessToken}`);
+ const { status } = await request(app).delete(`/auth/devices`).set('Authorization', `Bearer ${admin.accessToken}`);
expect(status).toBe(204);
- await expect(
- getAuthDevices({ headers: asBearerAuth(admin.accessToken) })
- ).resolves.toHaveLength(1);
+ await expect(getAuthDevices({ headers: asBearerAuth(admin.accessToken) })).resolves.toHaveLength(1);
});
it('should throw an error for a non-existent device id', async () => {
@@ -195,9 +163,7 @@ describe('/auth/*', () => {
.delete(`/auth/devices/${uuidDto.notFound}`)
.set('Authorization', `Bearer ${admin.accessToken}`);
expect(status).toBe(400);
- expect(body).toEqual(
- errorDto.badRequest('Not found or no authDevice.delete access')
- );
+ expect(body).toEqual(errorDto.badRequest('Not found or no authDevice.delete access'));
});
it('should logout a device', async () => {
@@ -219,9 +185,7 @@ describe('/auth/*', () => {
describe('POST /auth/validateToken', () => {
it('should reject an invalid token', async () => {
- const { status, body } = await request(app)
- .post(`/auth/validateToken`)
- .set('Authorization', 'Bearer 123');
+ const { status, body } = await request(app).post(`/auth/validateToken`).set('Authorization', 'Bearer 123');
expect(status).toBe(401);
expect(body).toEqual(errorDto.invalidToken);
});
diff --git a/e2e/src/api/specs/download.e2e-spec.ts b/e2e/src/api/specs/download.e2e-spec.ts
index 22d66baf0..cf4aae3e0 100644
--- a/e2e/src/api/specs/download.e2e-spec.ts
+++ b/e2e/src/api/specs/download.e2e-spec.ts
@@ -42,9 +42,7 @@ describe('/download', () => {
describe('POST /download/asset/:id', () => {
it('should require authentication', async () => {
- const { status, body } = await request(app).post(
- `/download/asset/${asset1.id}`,
- );
+ const { status, body } = await request(app).post(`/download/asset/${asset1.id}`);
expect(status).toBe(401);
expect(body).toEqual(errorDto.unauthorized);
@@ -56,7 +54,7 @@ describe('/download', () => {
.set('Authorization', `Bearer ${admin.accessToken}`);
expect(response.status).toBe(200);
- expect(response.headers['content-type']).toEqual('image/jpeg');
+ expect(response.headers['content-type']).toEqual('image/png');
});
});
});
diff --git a/e2e/src/api/specs/library.e2e-spec.ts b/e2e/src/api/specs/library.e2e-spec.ts
new file mode 100644
index 000000000..8213cc86e
--- /dev/null
+++ b/e2e/src/api/specs/library.e2e-spec.ts
@@ -0,0 +1,456 @@
+import { LibraryResponseDto, LibraryType, LoginResponseDto, getAllLibraries } from '@immich/sdk';
+import { userDto, uuidDto } from 'src/fixtures';
+import { errorDto } from 'src/responses';
+import { apiUtils, app, asBearerAuth, dbUtils, testAssetDirInternal } from 'src/utils';
+import request from 'supertest';
+import { beforeAll, describe, expect, it } from 'vitest';
+
+describe('/library', () => {
+ let admin: LoginResponseDto;
+ let user: LoginResponseDto;
+ let library: LibraryResponseDto;
+
+ beforeAll(async () => {
+ apiUtils.setup();
+ await dbUtils.reset();
+ admin = await apiUtils.adminSetup();
+ user = await apiUtils.userSetup(admin.accessToken, userDto.user1);
+ library = await apiUtils.createLibrary(admin.accessToken, { type: LibraryType.External });
+ });
+
+ describe('GET /library', () => {
+ it('should require authentication', async () => {
+ const { status, body } = await request(app).get('/library');
+ expect(status).toBe(401);
+ expect(body).toEqual(errorDto.unauthorized);
+ });
+
+ it('should start with a default upload library', async () => {
+ const { status, body } = await request(app).get('/library').set('Authorization', `Bearer ${admin.accessToken}`);
+ expect(status).toBe(200);
+ expect(body).toEqual(
+ expect.arrayContaining([
+ expect.objectContaining({
+ ownerId: admin.userId,
+ type: LibraryType.Upload,
+ name: 'Default Library',
+ refreshedAt: null,
+ assetCount: 0,
+ importPaths: [],
+ exclusionPatterns: [],
+ }),
+ ]),
+ );
+ });
+ });
+
+ describe('POST /library', () => {
+ it('should require authentication', async () => {
+ const { status, body } = await request(app).post('/library').send({});
+ expect(status).toBe(401);
+ expect(body).toEqual(errorDto.unauthorized);
+ });
+
+ it('should require admin authentication', async () => {
+ const { status, body } = await request(app)
+ .post('/library')
+ .set('Authorization', `Bearer ${user.accessToken}`)
+ .send({ type: LibraryType.External });
+
+ expect(status).toBe(403);
+ expect(body).toEqual(errorDto.forbidden);
+ });
+
+ it('should create an external library with defaults', async () => {
+ const { status, body } = await request(app)
+ .post('/library')
+ .set('Authorization', `Bearer ${admin.accessToken}`)
+ .send({ type: LibraryType.External });
+
+ expect(status).toBe(201);
+ expect(body).toEqual(
+ expect.objectContaining({
+ ownerId: admin.userId,
+ type: LibraryType.External,
+ name: 'New External Library',
+ refreshedAt: null,
+ assetCount: 0,
+ importPaths: [],
+ exclusionPatterns: [],
+ }),
+ );
+ });
+
+ it('should create an external library with options', async () => {
+ const { status, body } = await request(app)
+ .post('/library')
+ .set('Authorization', `Bearer ${admin.accessToken}`)
+ .send({
+ type: LibraryType.External,
+ name: 'My Awesome Library',
+ importPaths: ['/path/to/import'],
+ exclusionPatterns: ['**/Raw/**'],
+ });
+
+ expect(status).toBe(201);
+ expect(body).toEqual(
+ expect.objectContaining({
+ name: 'My Awesome Library',
+ importPaths: ['/path/to/import'],
+ }),
+ );
+ });
+
+ it('should not create an external library with duplicate import paths', async () => {
+ const { status, body } = await request(app)
+ .post('/library')
+ .set('Authorization', `Bearer ${admin.accessToken}`)
+ .send({
+ type: LibraryType.External,
+ name: 'My Awesome Library',
+ importPaths: ['/path', '/path'],
+ exclusionPatterns: ['**/Raw/**'],
+ });
+
+ expect(status).toBe(400);
+ expect(body).toEqual(errorDto.badRequest(["All importPaths's elements must be unique"]));
+ });
+
+ it('should not create an external library with duplicate exclusion patterns', async () => {
+ const { status, body } = await request(app)
+ .post('/library')
+ .set('Authorization', `Bearer ${admin.accessToken}`)
+ .send({
+ type: LibraryType.External,
+ name: 'My Awesome Library',
+ importPaths: ['/path/to/import'],
+ exclusionPatterns: ['**/Raw/**', '**/Raw/**'],
+ });
+
+ expect(status).toBe(400);
+ expect(body).toEqual(errorDto.badRequest(["All exclusionPatterns's elements must be unique"]));
+ });
+
+ it('should create an upload library with defaults', async () => {
+ const { status, body } = await request(app)
+ .post('/library')
+ .set('Authorization', `Bearer ${admin.accessToken}`)
+ .send({ type: LibraryType.Upload });
+
+ expect(status).toBe(201);
+ expect(body).toEqual(
+ expect.objectContaining({
+ ownerId: admin.userId,
+ type: LibraryType.Upload,
+ name: 'New Upload Library',
+ refreshedAt: null,
+ assetCount: 0,
+ importPaths: [],
+ exclusionPatterns: [],
+ }),
+ );
+ });
+
+ it('should create an upload library with options', async () => {
+ const { status, body } = await request(app)
+ .post('/library')
+ .set('Authorization', `Bearer ${admin.accessToken}`)
+ .send({ type: LibraryType.Upload, name: 'My Awesome Library' });
+
+ expect(status).toBe(201);
+ expect(body).toEqual(
+ expect.objectContaining({
+ name: 'My Awesome Library',
+ }),
+ );
+ });
+
+ it('should not allow upload libraries to have import paths', async () => {
+ const { status, body } = await request(app)
+ .post('/library')
+ .set('Authorization', `Bearer ${admin.accessToken}`)
+ .send({ type: LibraryType.Upload, importPaths: ['/path/to/import'] });
+
+ expect(status).toBe(400);
+ expect(body).toEqual(errorDto.badRequest('Upload libraries cannot have import paths'));
+ });
+
+ it('should not allow upload libraries to have exclusion patterns', async () => {
+ const { status, body } = await request(app)
+ .post('/library')
+ .set('Authorization', `Bearer ${admin.accessToken}`)
+ .send({ type: LibraryType.Upload, exclusionPatterns: ['**/Raw/**'] });
+
+ expect(status).toBe(400);
+ expect(body).toEqual(errorDto.badRequest('Upload libraries cannot have exclusion patterns'));
+ });
+ });
+
+ describe('PUT /library/:id', () => {
+ it('should require authentication', async () => {
+ const { status, body } = await request(app).put(`/library/${uuidDto.notFound}`).send({});
+ expect(status).toBe(401);
+ expect(body).toEqual(errorDto.unauthorized);
+ });
+
+ it('should change the library name', async () => {
+ const { status, body } = await request(app)
+ .put(`/library/${library.id}`)
+ .set('Authorization', `Bearer ${admin.accessToken}`)
+ .send({ name: 'New Library Name' });
+
+ expect(status).toBe(200);
+ expect(body).toEqual(
+ expect.objectContaining({
+ name: 'New Library Name',
+ }),
+ );
+ });
+
+ it('should not set an empty name', async () => {
+ const { status, body } = await request(app)
+ .put(`/library/${library.id}`)
+ .set('Authorization', `Bearer ${admin.accessToken}`)
+ .send({ name: '' });
+
+ expect(status).toBe(400);
+ expect(body).toEqual(errorDto.badRequest(['name should not be empty']));
+ });
+
+ it('should change the import paths', async () => {
+ const { status, body } = await request(app)
+ .put(`/library/${library.id}`)
+ .set('Authorization', `Bearer ${admin.accessToken}`)
+ .send({ importPaths: [testAssetDirInternal] });
+
+ expect(status).toBe(200);
+ expect(body).toEqual(
+ expect.objectContaining({
+ importPaths: [testAssetDirInternal],
+ }),
+ );
+ });
+
+ it('should reject an empty import path', async () => {
+ const { status, body } = await request(app)
+ .put(`/library/${library.id}`)
+ .set('Authorization', `Bearer ${admin.accessToken}`)
+ .send({ importPaths: [''] });
+
+ expect(status).toBe(400);
+ expect(body).toEqual(errorDto.badRequest(['each value in importPaths should not be empty']));
+ });
+
+ it('should reject duplicate import paths', async () => {
+ const { status, body } = await request(app)
+ .put(`/library/${library.id}`)
+ .set('Authorization', `Bearer ${admin.accessToken}`)
+ .send({ importPaths: ['/path', '/path'] });
+
+ expect(status).toBe(400);
+ expect(body).toEqual(errorDto.badRequest(["All importPaths's elements must be unique"]));
+ });
+
+ it('should change the exclusion pattern', async () => {
+ const { status, body } = await request(app)
+ .put(`/library/${library.id}`)
+ .set('Authorization', `Bearer ${admin.accessToken}`)
+ .send({ exclusionPatterns: ['**/Raw/**'] });
+
+ expect(status).toBe(200);
+ expect(body).toEqual(
+ expect.objectContaining({
+ exclusionPatterns: ['**/Raw/**'],
+ }),
+ );
+ });
+
+ it('should reject duplicate exclusion patterns', async () => {
+ const { status, body } = await request(app)
+ .put(`/library/${library.id}`)
+ .set('Authorization', `Bearer ${admin.accessToken}`)
+ .send({ exclusionPatterns: ['**/*.jpg', '**/*.jpg'] });
+
+ expect(status).toBe(400);
+ expect(body).toEqual(errorDto.badRequest(["All exclusionPatterns's elements must be unique"]));
+ });
+
+ it('should reject an empty exclusion pattern', async () => {
+ const { status, body } = await request(app)
+ .put(`/library/${library.id}`)
+ .set('Authorization', `Bearer ${admin.accessToken}`)
+ .send({ exclusionPatterns: [''] });
+
+ expect(status).toBe(400);
+ expect(body).toEqual(errorDto.badRequest(['each value in exclusionPatterns should not be empty']));
+ });
+ });
+
+ describe('GET /library/:id', () => {
+ it('should require authentication', async () => {
+ const { status, body } = await request(app).get(`/library/${uuidDto.notFound}`);
+
+ expect(status).toBe(401);
+ expect(body).toEqual(errorDto.unauthorized);
+ });
+
+ it('should require admin access', async () => {
+ const { status, body } = await request(app)
+ .get(`/library/${uuidDto.notFound}`)
+ .set('Authorization', `Bearer ${user.accessToken}`);
+ expect(status).toBe(403);
+ expect(body).toEqual(errorDto.forbidden);
+ });
+
+ it('should get library by id', async () => {
+ const library = await apiUtils.createLibrary(admin.accessToken, { type: LibraryType.External });
+
+ const { status, body } = await request(app)
+ .get(`/library/${library.id}`)
+ .set('Authorization', `Bearer ${admin.accessToken}`);
+
+ expect(status).toBe(200);
+ expect(body).toEqual(
+ expect.objectContaining({
+ ownerId: admin.userId,
+ type: LibraryType.External,
+ name: 'New External Library',
+ refreshedAt: null,
+ assetCount: 0,
+ importPaths: [],
+ exclusionPatterns: [],
+ }),
+ );
+ });
+ });
+
+ describe('DELETE /library/:id', () => {
+ it('should require authentication', async () => {
+ const { status, body } = await request(app).delete(`/library/${uuidDto.notFound}`);
+
+ expect(status).toBe(401);
+ expect(body).toEqual(errorDto.unauthorized);
+ });
+
+ it('should not delete the last upload library', async () => {
+ const libraries = await getAllLibraries(
+ { $type: LibraryType.Upload },
+ { headers: asBearerAuth(admin.accessToken) },
+ );
+
+ const adminLibraries = libraries.filter((library) => library.ownerId === admin.userId);
+ expect(adminLibraries.length).toBeGreaterThanOrEqual(1);
+ const lastLibrary = adminLibraries.pop() as LibraryResponseDto;
+
+ // delete all but the last upload library
+ for (const library of adminLibraries) {
+ const { status } = await request(app)
+ .delete(`/library/${library.id}`)
+ .set('Authorization', `Bearer ${admin.accessToken}`);
+ expect(status).toBe(204);
+ }
+
+ const { status, body } = await request(app)
+ .delete(`/library/${lastLibrary.id}`)
+ .set('Authorization', `Bearer ${admin.accessToken}`);
+
+ expect(body).toEqual(errorDto.noDeleteUploadLibrary);
+ expect(status).toBe(400);
+ });
+
+ it('should delete an external library', async () => {
+ const library = await apiUtils.createLibrary(admin.accessToken, { type: LibraryType.External });
+
+ const { status, body } = await request(app)
+ .delete(`/library/${library.id}`)
+ .set('Authorization', `Bearer ${admin.accessToken}`);
+
+ expect(status).toBe(204);
+ expect(body).toEqual({});
+
+ const libraries = await getAllLibraries({}, { headers: asBearerAuth(admin.accessToken) });
+ expect(libraries).not.toEqual(
+ expect.arrayContaining([
+ expect.objectContaining({
+ id: library.id,
+ }),
+ ]),
+ );
+ });
+ });
+
+ describe('GET /library/:id/statistics', () => {
+ it('should require authentication', async () => {
+ const { status, body } = await request(app).get(`/library/${uuidDto.notFound}/statistics`);
+
+ expect(status).toBe(401);
+ expect(body).toEqual(errorDto.unauthorized);
+ });
+ });
+
+ describe('POST /library/:id/scan', () => {
+ it('should require authentication', async () => {
+ const { status, body } = await request(app).post(`/library/${uuidDto.notFound}/scan`).send({});
+
+ expect(status).toBe(401);
+ expect(body).toEqual(errorDto.unauthorized);
+ });
+ });
+
+ describe('POST /library/:id/removeOffline', () => {
+ it('should require authentication', async () => {
+ const { status, body } = await request(app).post(`/library/${uuidDto.notFound}/removeOffline`).send({});
+
+ expect(status).toBe(401);
+ expect(body).toEqual(errorDto.unauthorized);
+ });
+ });
+
+ describe('POST /library/:id/validate', () => {
+ it('should require authentication', async () => {
+ const { status, body } = await request(app).post(`/library/${uuidDto.notFound}/validate`).send({});
+
+ expect(status).toBe(401);
+ expect(body).toEqual(errorDto.unauthorized);
+ });
+
+ it('should pass with no import paths', async () => {
+ const response = await apiUtils.validateLibrary(admin.accessToken, library.id, { importPaths: [] });
+ expect(response.importPaths).toEqual([]);
+ });
+
+ it('should fail if path does not exist', async () => {
+ const pathToTest = `${testAssetDirInternal}/does/not/exist`;
+
+ const response = await apiUtils.validateLibrary(admin.accessToken, library.id, {
+ importPaths: [pathToTest],
+ });
+
+ expect(response.importPaths?.length).toEqual(1);
+ const pathResponse = response?.importPaths?.at(0);
+
+ expect(pathResponse).toEqual({
+ importPath: pathToTest,
+ isValid: false,
+ message: `Path does not exist (ENOENT)`,
+ });
+ });
+
+ it('should fail if path is a file', async () => {
+ const pathToTest = `${testAssetDirInternal}/albums/nature/el_torcal_rocks.jpg`;
+
+ const response = await apiUtils.validateLibrary(admin.accessToken, library.id, {
+ importPaths: [pathToTest],
+ });
+
+ expect(response.importPaths?.length).toEqual(1);
+ const pathResponse = response?.importPaths?.at(0);
+
+ expect(pathResponse).toEqual({
+ importPath: pathToTest,
+ isValid: false,
+ message: `Not a directory`,
+ });
+ });
+ });
+});
diff --git a/e2e/src/api/specs/oauth.e2e-spec.ts b/e2e/src/api/specs/oauth.e2e-spec.ts
index b09b6e521..1324d3fa7 100644
--- a/e2e/src/api/specs/oauth.e2e-spec.ts
+++ b/e2e/src/api/specs/oauth.e2e-spec.ts
@@ -15,16 +15,9 @@ describe(`/oauth`, () => {
describe('POST /oauth/authorize', () => {
it(`should throw an error if a redirect uri is not provided`, async () => {
- const { status, body } = await request(app)
- .post('/oauth/authorize')
- .send({});
+ const { status, body } = await request(app).post('/oauth/authorize').send({});
expect(status).toBe(400);
- expect(body).toEqual(
- errorDto.badRequest([
- 'redirectUri must be a string',
- 'redirectUri should not be empty',
- ])
- );
+ expect(body).toEqual(errorDto.badRequest(['redirectUri must be a string', 'redirectUri should not be empty']));
});
});
});
diff --git a/e2e/src/api/specs/partner.e2e-spec.ts b/e2e/src/api/specs/partner.e2e-spec.ts
index 5b441b767..2c88391bd 100644
--- a/e2e/src/api/specs/partner.e2e-spec.ts
+++ b/e2e/src/api/specs/partner.e2e-spec.ts
@@ -24,14 +24,8 @@ describe('/partner', () => {
]);
await Promise.all([
- createPartner(
- { id: user2.userId },
- { headers: asBearerAuth(user1.accessToken) }
- ),
- createPartner(
- { id: user1.userId },
- { headers: asBearerAuth(user2.accessToken) }
- ),
+ createPartner({ id: user2.userId }, { headers: asBearerAuth(user1.accessToken) }),
+ createPartner({ id: user1.userId }, { headers: asBearerAuth(user2.accessToken) }),
]);
});
@@ -66,9 +60,7 @@ describe('/partner', () => {
describe('POST /partner/:id', () => {
it('should require authentication', async () => {
- const { status, body } = await request(app).post(
- `/partner/${user3.userId}`
- );
+ const { status, body } = await request(app).post(`/partner/${user3.userId}`);
expect(status).toBe(401);
expect(body).toEqual(errorDto.unauthorized);
@@ -89,17 +81,13 @@ describe('/partner', () => {
.set('Authorization', `Bearer ${user1.accessToken}`);
expect(status).toBe(400);
- expect(body).toEqual(
- expect.objectContaining({ message: 'Partner already exists' })
- );
+ expect(body).toEqual(expect.objectContaining({ message: 'Partner already exists' }));
});
});
describe('PUT /partner/:id', () => {
it('should require authentication', async () => {
- const { status, body } = await request(app).put(
- `/partner/${user2.userId}`
- );
+ const { status, body } = await request(app).put(`/partner/${user2.userId}`);
expect(status).toBe(401);
expect(body).toEqual(errorDto.unauthorized);
@@ -112,17 +100,13 @@ describe('/partner', () => {
.send({ inTimeline: false });
expect(status).toBe(200);
- expect(body).toEqual(
- expect.objectContaining({ id: user2.userId, inTimeline: false })
- );
+ expect(body).toEqual(expect.objectContaining({ id: user2.userId, inTimeline: false }));
});
});
describe('DELETE /partner/:id', () => {
it('should require authentication', async () => {
- const { status, body } = await request(app).delete(
- `/partner/${user3.userId}`
- );
+ const { status, body } = await request(app).delete(`/partner/${user3.userId}`);
expect(status).toBe(401);
expect(body).toEqual(errorDto.unauthorized);
@@ -142,9 +126,7 @@ describe('/partner', () => {
.set('Authorization', `Bearer ${user1.accessToken}`);
expect(status).toBe(400);
- expect(body).toEqual(
- expect.objectContaining({ message: 'Partner not found' })
- );
+ expect(body).toEqual(expect.objectContaining({ message: 'Partner not found' }));
});
});
});
diff --git a/e2e/src/api/specs/person.e2e-spec.ts b/e2e/src/api/specs/person.e2e-spec.ts
index 3f17eac22..77a10b343 100644
--- a/e2e/src/api/specs/person.e2e-spec.ts
+++ b/e2e/src/api/specs/person.e2e-spec.ts
@@ -65,9 +65,7 @@ describe('/activity', () => {
});
it('should return only visible people', async () => {
- const { status, body } = await request(app)
- .get('/person')
- .set('Authorization', `Bearer ${admin.accessToken}`);
+ const { status, body } = await request(app).get('/person').set('Authorization', `Bearer ${admin.accessToken}`);
expect(status).toBe(200);
expect(body).toEqual({
@@ -80,9 +78,7 @@ describe('/activity', () => {
describe('GET /person/:id', () => {
it('should require authentication', async () => {
- const { status, body } = await request(app).get(
- `/person/${uuidDto.notFound}`
- );
+ const { status, body } = await request(app).get(`/person/${uuidDto.notFound}`);
expect(status).toBe(401);
expect(body).toEqual(errorDto.unauthorized);
@@ -109,9 +105,7 @@ describe('/activity', () => {
describe('PUT /person/:id', () => {
it('should require authentication', async () => {
- const { status, body } = await request(app).put(
- `/person/${uuidDto.notFound}`
- );
+ const { status, body } = await request(app).put(`/person/${uuidDto.notFound}`);
expect(status).toBe(401);
expect(body).toEqual(errorDto.unauthorized);
});
@@ -139,7 +133,7 @@ describe('/activity', () => {
birthDate: '123567',
response: 'Not found or no person.write access',
},
- { birthDate: 123567, response: 'Not found or no person.write access' },
+ { birthDate: 123_567, response: 'Not found or no person.write access' },
]) {
const { status, body } = await request(app)
.put(`/person/${uuidDto.notFound}`)
diff --git a/e2e/src/api/specs/server-info.e2e-spec.ts b/e2e/src/api/specs/server-info.e2e-spec.ts
index d5092ad4f..7c8c45709 100644
--- a/e2e/src/api/specs/server-info.e2e-spec.ts
+++ b/e2e/src/api/specs/server-info.e2e-spec.ts
@@ -97,9 +97,7 @@ describe('/server-info', () => {
describe('GET /server-info/statistics', () => {
it('should require authentication', async () => {
- const { status, body } = await request(app).get(
- '/server-info/statistics'
- );
+ const { status, body } = await request(app).get('/server-info/statistics');
expect(status).toBe(401);
expect(body).toEqual(errorDto.unauthorized);
});
@@ -145,9 +143,7 @@ describe('/server-info', () => {
describe('GET /server-info/media-types', () => {
it('should return accepted media types', async () => {
- const { status, body } = await request(app).get(
- '/server-info/media-types'
- );
+ const { status, body } = await request(app).get('/server-info/media-types');
expect(status).toBe(200);
expect(body).toEqual({
sidecar: ['.xmp'],
diff --git a/e2e/src/api/specs/shared-link.e2e-spec.ts b/e2e/src/api/specs/shared-link.e2e-spec.ts
index 0bb760fbc..f2e5b0186 100644
--- a/e2e/src/api/specs/shared-link.e2e-spec.ts
+++ b/e2e/src/api/specs/shared-link.e2e-spec.ts
@@ -46,14 +46,8 @@ describe('/shared-link', () => {
]);
[album, deletedAlbum, metadataAlbum] = await Promise.all([
- createAlbum(
- { createAlbumDto: { albumName: 'album' } },
- { headers: asBearerAuth(user1.accessToken) },
- ),
- createAlbum(
- { createAlbumDto: { albumName: 'deleted album' } },
- { headers: asBearerAuth(user2.accessToken) },
- ),
+ createAlbum({ createAlbumDto: { albumName: 'album' } }, { headers: asBearerAuth(user1.accessToken) }),
+ createAlbum({ createAlbumDto: { albumName: 'deleted album' } }, { headers: asBearerAuth(user2.accessToken) }),
createAlbum(
{
createAlbumDto: {
@@ -65,47 +59,38 @@ describe('/shared-link', () => {
),
]);
- [
- linkWithDeletedAlbum,
- linkWithAlbum,
- linkWithAssets,
- linkWithPassword,
- linkWithMetadata,
- linkWithoutMetadata,
- ] = await Promise.all([
- apiUtils.createSharedLink(user2.accessToken, {
- type: SharedLinkType.Album,
- albumId: deletedAlbum.id,
- }),
- apiUtils.createSharedLink(user1.accessToken, {
- type: SharedLinkType.Album,
- albumId: album.id,
- }),
- apiUtils.createSharedLink(user1.accessToken, {
- type: SharedLinkType.Individual,
- assetIds: [asset1.id],
- }),
- apiUtils.createSharedLink(user1.accessToken, {
- type: SharedLinkType.Album,
- albumId: album.id,
- password: 'foo',
- }),
- apiUtils.createSharedLink(user1.accessToken, {
- type: SharedLinkType.Album,
- albumId: metadataAlbum.id,
- showMetadata: true,
- }),
- apiUtils.createSharedLink(user1.accessToken, {
- type: SharedLinkType.Album,
- albumId: metadataAlbum.id,
- showMetadata: false,
- }),
- ]);
+ [linkWithDeletedAlbum, linkWithAlbum, linkWithAssets, linkWithPassword, linkWithMetadata, linkWithoutMetadata] =
+ await Promise.all([
+ apiUtils.createSharedLink(user2.accessToken, {
+ type: SharedLinkType.Album,
+ albumId: deletedAlbum.id,
+ }),
+ apiUtils.createSharedLink(user1.accessToken, {
+ type: SharedLinkType.Album,
+ albumId: album.id,
+ }),
+ apiUtils.createSharedLink(user1.accessToken, {
+ type: SharedLinkType.Individual,
+ assetIds: [asset1.id],
+ }),
+ apiUtils.createSharedLink(user1.accessToken, {
+ type: SharedLinkType.Album,
+ albumId: album.id,
+ password: 'foo',
+ }),
+ apiUtils.createSharedLink(user1.accessToken, {
+ type: SharedLinkType.Album,
+ albumId: metadataAlbum.id,
+ showMetadata: true,
+ }),
+ apiUtils.createSharedLink(user1.accessToken, {
+ type: SharedLinkType.Album,
+ albumId: metadataAlbum.id,
+ showMetadata: false,
+ }),
+ ]);
- await deleteUser(
- { id: user2.userId },
- { headers: asBearerAuth(admin.accessToken) },
- );
+ await deleteUser({ id: user2.userId }, { headers: asBearerAuth(admin.accessToken) });
});
describe('GET /shared-link', () => {
@@ -146,17 +131,13 @@ describe('/shared-link', () => {
describe('GET /shared-link/me', () => {
it('should not require admin authentication', async () => {
- const { status } = await request(app)
- .get('/shared-link/me')
- .set('Authorization', `Bearer ${admin.accessToken}`);
+ const { status } = await request(app).get('/shared-link/me').set('Authorization', `Bearer ${admin.accessToken}`);
expect(status).toBe(403);
});
it('should get data for correct shared link', async () => {
- const { status, body } = await request(app)
- .get('/shared-link/me')
- .query({ key: linkWithAlbum.key });
+ const { status, body } = await request(app).get('/shared-link/me').query({ key: linkWithAlbum.key });
expect(status).toBe(200);
expect(body).toEqual(
@@ -178,18 +159,14 @@ describe('/shared-link', () => {
});
it('should return unauthorized if target has been soft deleted', async () => {
- const { status, body } = await request(app)
- .get('/shared-link/me')
- .query({ key: linkWithDeletedAlbum.key });
+ const { status, body } = await request(app).get('/shared-link/me').query({ key: linkWithDeletedAlbum.key });
expect(status).toBe(401);
expect(body).toEqual(errorDto.invalidShareKey);
});
it('should return unauthorized for password protected link', async () => {
- const { status, body } = await request(app)
- .get('/shared-link/me')
- .query({ key: linkWithPassword.key });
+ const { status, body } = await request(app).get('/shared-link/me').query({ key: linkWithPassword.key });
expect(status).toBe(401);
expect(body).toEqual(errorDto.invalidSharePassword);
@@ -211,9 +188,7 @@ describe('/shared-link', () => {
});
it('should return metadata for album shared link', async () => {
- const { status, body } = await request(app)
- .get('/shared-link/me')
- .query({ key: linkWithMetadata.key });
+ const { status, body } = await request(app).get('/shared-link/me').query({ key: linkWithMetadata.key });
expect(status).toBe(200);
expect(body.assets).toHaveLength(1);
@@ -229,9 +204,7 @@ describe('/shared-link', () => {
});
it('should not return metadata for album shared link without metadata', async () => {
- const { status, body } = await request(app)
- .get('/shared-link/me')
- .query({ key: linkWithoutMetadata.key });
+ const { status, body } = await request(app).get('/shared-link/me').query({ key: linkWithoutMetadata.key });
expect(status).toBe(200);
expect(body.assets).toHaveLength(1);
@@ -247,9 +220,7 @@ describe('/shared-link', () => {
describe('GET /shared-link/:id', () => {
it('should require authentication', async () => {
- const { status, body } = await request(app).get(
- `/shared-link/${linkWithAlbum.id}`,
- );
+ const { status, body } = await request(app).get(`/shared-link/${linkWithAlbum.id}`);
expect(status).toBe(401);
expect(body).toEqual(errorDto.unauthorized);
@@ -276,9 +247,7 @@ describe('/shared-link', () => {
.set('Authorization', `Bearer ${admin.accessToken}`);
expect(status).toBe(400);
- expect(body).toEqual(
- expect.objectContaining({ message: 'Shared link not found' }),
- );
+ expect(body).toEqual(expect.objectContaining({ message: 'Shared link not found' }));
});
});
@@ -308,9 +277,7 @@ describe('/shared-link', () => {
.send({ type: SharedLinkType.Album });
expect(status).toBe(400);
- expect(body).toEqual(
- expect.objectContaining({ message: 'Invalid albumId' }),
- );
+ expect(body).toEqual(expect.objectContaining({ message: 'Invalid albumId' }));
});
it('should require a valid asset id', async () => {
@@ -320,9 +287,7 @@ describe('/shared-link', () => {
.send({ type: SharedLinkType.Individual, assetId: uuidDto.notFound });
expect(status).toBe(400);
- expect(body).toEqual(
- expect.objectContaining({ message: 'Invalid assetIds' }),
- );
+ expect(body).toEqual(expect.objectContaining({ message: 'Invalid assetIds' }));
});
it('should create a shared link', async () => {
@@ -424,9 +389,7 @@ describe('/shared-link', () => {
describe('DELETE /shared-link/:id', () => {
it('should require authentication', async () => {
- const { status, body } = await request(app).delete(
- `/shared-link/${linkWithAlbum.id}`,
- );
+ const { status, body } = await request(app).delete(`/shared-link/${linkWithAlbum.id}`);
expect(status).toBe(401);
expect(body).toEqual(errorDto.unauthorized);
diff --git a/e2e/src/api/specs/system-config.e2e-spec.ts b/e2e/src/api/specs/system-config.e2e-spec.ts
index 8d293b3d2..6d8880d3f 100644
--- a/e2e/src/api/specs/system-config.e2e-spec.ts
+++ b/e2e/src/api/specs/system-config.e2e-spec.ts
@@ -18,9 +18,7 @@ describe('/system-config', () => {
describe('GET /system-config/map/style.json', () => {
it('should require authentication', async () => {
- const { status, body } = await request(app).get(
- '/system-config/map/style.json'
- );
+ const { status, body } = await request(app).get('/system-config/map/style.json');
expect(status).toBe(401);
expect(body).toEqual(errorDto.unauthorized);
});
@@ -32,11 +30,7 @@ describe('/system-config', () => {
.query({ theme })
.set('Authorization', `Bearer ${admin.accessToken}`);
expect(status).toBe(400);
- expect(body).toEqual(
- errorDto.badRequest([
- 'theme must be one of the following values: light, dark',
- ])
- );
+ expect(body).toEqual(errorDto.badRequest(['theme must be one of the following values: light, dark']));
}
});
diff --git a/e2e/src/api/specs/trash.e2e-spec.ts b/e2e/src/api/specs/trash.e2e-spec.ts
index 2de838f98..60ed75f11 100644
--- a/e2e/src/api/specs/trash.e2e-spec.ts
+++ b/e2e/src/api/specs/trash.e2e-spec.ts
@@ -32,24 +32,16 @@ describe('/trash', () => {
const { id: assetId } = await apiUtils.createAsset(admin.accessToken);
await apiUtils.deleteAssets(admin.accessToken, [assetId]);
- const before = await getAllAssets(
- {},
- { headers: asBearerAuth(admin.accessToken) },
- );
+ const before = await getAllAssets({}, { headers: asBearerAuth(admin.accessToken) });
expect(before.length).toBeGreaterThanOrEqual(1);
- const { status } = await request(app)
- .post('/trash/empty')
- .set('Authorization', `Bearer ${admin.accessToken}`);
+ const { status } = await request(app).post('/trash/empty').set('Authorization', `Bearer ${admin.accessToken}`);
expect(status).toBe(204);
- await wsUtils.once(ws, 'on_asset_delete');
+ await wsUtils.waitForEvent({ event: 'delete', assetId });
- const after = await getAllAssets(
- {},
- { headers: asBearerAuth(admin.accessToken) },
- );
+ const after = await getAllAssets({}, { headers: asBearerAuth(admin.accessToken) });
expect(after.length).toBe(0);
});
});
@@ -69,9 +61,7 @@ describe('/trash', () => {
const before = await apiUtils.getAssetInfo(admin.accessToken, assetId);
expect(before.isTrashed).toBe(true);
- const { status } = await request(app)
- .post('/trash/restore')
- .set('Authorization', `Bearer ${admin.accessToken}`);
+ const { status } = await request(app).post('/trash/restore').set('Authorization', `Bearer ${admin.accessToken}`);
expect(status).toBe(204);
const after = await apiUtils.getAssetInfo(admin.accessToken, assetId);
diff --git a/e2e/src/api/specs/user.e2e-spec.ts b/e2e/src/api/specs/user.e2e-spec.ts
index 9bfb47284..e47e1d531 100644
--- a/e2e/src/api/specs/user.e2e-spec.ts
+++ b/e2e/src/api/specs/user.e2e-spec.ts
@@ -22,10 +22,7 @@ describe('/server-info', () => {
apiUtils.userSetup(admin.accessToken, createUserDto.user3),
]);
- await deleteUser(
- { id: deletedUser.userId },
- { headers: asBearerAuth(admin.accessToken) }
- );
+ await deleteUser({ id: deletedUser.userId }, { headers: asBearerAuth(admin.accessToken) });
});
describe('GET /user', () => {
@@ -36,9 +33,7 @@ describe('/server-info', () => {
});
it('should get users', async () => {
- const { status, body } = await request(app)
- .get('/user')
- .set('Authorization', `Bearer ${admin.accessToken}`);
+ const { status, body } = await request(app).get('/user').set('Authorization', `Bearer ${admin.accessToken}`);
expect(status).toEqual(200);
expect(body).toHaveLength(4);
expect(body).toEqual(
@@ -47,7 +42,7 @@ describe('/server-info', () => {
expect.objectContaining({ email: 'user1@immich.cloud' }),
expect.objectContaining({ email: 'user2@immich.cloud' }),
expect.objectContaining({ email: 'user3@immich.cloud' }),
- ])
+ ]),
);
});
@@ -63,7 +58,7 @@ describe('/server-info', () => {
expect.objectContaining({ email: 'admin@immich.cloud' }),
expect.objectContaining({ email: 'user2@immich.cloud' }),
expect.objectContaining({ email: 'user3@immich.cloud' }),
- ])
+ ]),
);
});
@@ -81,7 +76,7 @@ describe('/server-info', () => {
expect.objectContaining({ email: 'user1@immich.cloud' }),
expect.objectContaining({ email: 'user2@immich.cloud' }),
expect.objectContaining({ email: 'user3@immich.cloud' }),
- ])
+ ]),
);
});
});
@@ -112,9 +107,7 @@ describe('/server-info', () => {
});
it('should get my info', async () => {
- const { status, body } = await request(app)
- .get(`/user/me`)
- .set('Authorization', `Bearer ${admin.accessToken}`);
+ const { status, body } = await request(app).get(`/user/me`).set('Authorization', `Bearer ${admin.accessToken}`);
expect(status).toBe(200);
expect(body).toMatchObject({
id: admin.userId,
@@ -125,9 +118,7 @@ describe('/server-info', () => {
describe('POST /user', () => {
it('should require authentication', async () => {
- const { status, body } = await request(app)
- .post(`/user`)
- .send(createUserDto.user1);
+ const { status, body } = await request(app).post(`/user`).send(createUserDto.user1);
expect(status).toBe(401);
expect(body).toEqual(errorDto.unauthorized);
});
@@ -181,9 +172,7 @@ describe('/server-info', () => {
describe('DELETE /user/:id', () => {
it('should require authentication', async () => {
- const { status, body } = await request(app).delete(
- `/user/${userToDelete.userId}`
- );
+ const { status, body } = await request(app).delete(`/user/${userToDelete.userId}`);
expect(status).toBe(401);
expect(body).toEqual(errorDto.unauthorized);
});
@@ -241,10 +230,7 @@ describe('/server-info', () => {
});
it('should ignore updates to createdAt, updatedAt and deletedAt', async () => {
- const before = await getUserById(
- { id: admin.userId },
- { headers: asBearerAuth(admin.accessToken) }
- );
+ const before = await getUserById({ id: admin.userId }, { headers: asBearerAuth(admin.accessToken) });
const { status, body } = await request(app)
.put(`/user`)
@@ -261,10 +247,7 @@ describe('/server-info', () => {
});
it('should update first and last name', async () => {
- const before = await getUserById(
- { id: admin.userId },
- { headers: asBearerAuth(admin.accessToken) }
- );
+ const before = await getUserById({ id: admin.userId }, { headers: asBearerAuth(admin.accessToken) });
const { status, body } = await request(app)
.put(`/user`)
@@ -284,10 +267,7 @@ describe('/server-info', () => {
});
it('should update memories enabled', async () => {
- const before = await getUserById(
- { id: admin.userId },
- { headers: asBearerAuth(admin.accessToken) }
- );
+ const before = await getUserById({ id: admin.userId }, { headers: asBearerAuth(admin.accessToken) });
const { status, body } = await request(app)
.put(`/user`)
.send({
diff --git a/e2e/src/cli/specs/login.e2e-spec.ts b/e2e/src/cli/specs/login.e2e-spec.ts
index ef811a867..e3140ecea 100644
--- a/e2e/src/cli/specs/login.e2e-spec.ts
+++ b/e2e/src/cli/specs/login.e2e-spec.ts
@@ -1,6 +1,6 @@
import { stat } from 'node:fs/promises';
import { apiUtils, app, dbUtils, immichCli } from 'src/utils';
-import { beforeEach, beforeAll, describe, expect, it } from 'vitest';
+import { beforeAll, beforeEach, describe, expect, it } from 'vitest';
describe(`immich login-key`, () => {
beforeAll(() => {
@@ -24,25 +24,15 @@ describe(`immich login-key`, () => {
});
it('should require a valid key', async () => {
- const { stderr, exitCode } = await immichCli([
- 'login-key',
- app,
- 'immich-is-so-cool',
- ]);
- expect(stderr).toContain(
- 'Failed to connect to server http://127.0.0.1:2283/api: Error: 401'
- );
+ const { stderr, exitCode } = await immichCli(['login-key', app, 'immich-is-so-cool']);
+ expect(stderr).toContain('Failed to connect to server http://127.0.0.1:2283/api: Error: 401');
expect(exitCode).toBe(1);
});
it('should login', async () => {
const admin = await apiUtils.adminSetup();
const key = await apiUtils.createApiKey(admin.accessToken);
- const { stdout, stderr, exitCode } = await immichCli([
- 'login-key',
- app,
- `${key.secret}`,
- ]);
+ const { stdout, stderr, exitCode } = await immichCli(['login-key', app, `${key.secret}`]);
expect(stdout.split('\n')).toEqual([
'Logging in...',
'Logged in as admin@immich.cloud',
diff --git a/e2e/src/cli/specs/upload.e2e-spec.ts b/e2e/src/cli/specs/upload.e2e-spec.ts
index 908118d77..bda625241 100644
--- a/e2e/src/cli/specs/upload.e2e-spec.ts
+++ b/e2e/src/cli/specs/upload.e2e-spec.ts
@@ -1,13 +1,6 @@
import { getAllAlbums, getAllAssets } from '@immich/sdk';
-import { mkdir, readdir, rm, symlink } from 'fs/promises';
-import {
- apiUtils,
- asKeyAuth,
- cliUtils,
- dbUtils,
- immichCli,
- testAssetDir,
-} from 'src/utils';
+import { mkdir, readdir, rm, symlink } from 'node:fs/promises';
+import { apiUtils, asKeyAuth, cliUtils, dbUtils, immichCli, testAssetDir } from 'src/utils';
import { beforeAll, beforeEach, describe, expect, it } from 'vitest';
describe(`immich upload`, () => {
@@ -25,16 +18,10 @@ describe(`immich upload`, () => {
describe('immich upload --recursive', () => {
it('should upload a folder recursively', async () => {
- const { stderr, stdout, exitCode } = await immichCli([
- 'upload',
- `${testAssetDir}/albums/nature/`,
- '--recursive',
- ]);
+ const { stderr, stdout, exitCode } = await immichCli(['upload', `${testAssetDir}/albums/nature/`, '--recursive']);
expect(stderr).toBe('');
expect(stdout.split('\n')).toEqual(
- expect.arrayContaining([
- expect.stringContaining('Successfully uploaded 9 assets'),
- ]),
+ expect.arrayContaining([expect.stringContaining('Successfully uploaded 9 assets')]),
);
expect(exitCode).toBe(0);
@@ -70,15 +57,9 @@ describe(`immich upload`, () => {
});
it('should add existing assets to albums', async () => {
- const response1 = await immichCli([
- 'upload',
- `${testAssetDir}/albums/nature/`,
- '--recursive',
- ]);
+ const response1 = await immichCli(['upload', `${testAssetDir}/albums/nature/`, '--recursive']);
expect(response1.stdout.split('\n')).toEqual(
- expect.arrayContaining([
- expect.stringContaining('Successfully uploaded 9 assets'),
- ]),
+ expect.arrayContaining([expect.stringContaining('Successfully uploaded 9 assets')]),
);
expect(response1.stderr).toBe('');
expect(response1.exitCode).toBe(0);
@@ -89,17 +70,10 @@ describe(`immich upload`, () => {
const albums1 = await getAllAlbums({}, { headers: asKeyAuth(key) });
expect(albums1.length).toBe(0);
- const response2 = await immichCli([
- 'upload',
- `${testAssetDir}/albums/nature/`,
- '--recursive',
- '--album',
- ]);
+ const response2 = await immichCli(['upload', `${testAssetDir}/albums/nature/`, '--recursive', '--album']);
expect(response2.stdout.split('\n')).toEqual(
expect.arrayContaining([
- expect.stringContaining(
- 'All assets were already uploaded, nothing to do.',
- ),
+ expect.stringContaining('All assets were already uploaded, nothing to do.'),
expect.stringContaining('Successfully updated 9 assets'),
]),
);
@@ -147,17 +121,10 @@ describe(`immich upload`, () => {
await mkdir(`/tmp/albums/nature`, { recursive: true });
const filesToLink = await readdir(`${testAssetDir}/albums/nature`);
for (const file of filesToLink) {
- await symlink(
- `${testAssetDir}/albums/nature/${file}`,
- `/tmp/albums/nature/${file}`,
- );
+ await symlink(`${testAssetDir}/albums/nature/${file}`, `/tmp/albums/nature/${file}`);
}
- const { stderr, stdout, exitCode } = await immichCli([
- 'upload',
- `/tmp/albums/nature`,
- '--delete',
- ]);
+ const { stderr, stdout, exitCode } = await immichCli(['upload', `/tmp/albums/nature`, '--delete']);
const files = await readdir(`/tmp/albums/nature`);
await rm(`/tmp/albums/nature`, { recursive: true });
diff --git a/e2e/src/fixtures.ts b/e2e/src/fixtures.ts
index 309ba6b93..6a1a1b396 100644
--- a/e2e/src/fixtures.ts
+++ b/e2e/src/fixtures.ts
@@ -44,7 +44,6 @@ export const userDto = {
email: signupDto.admin.email,
password: signupDto.admin.password,
storageLabel: 'admin',
- externalPath: null,
oauthId: '',
shouldChangePassword: false,
profileImagePath: '',
@@ -63,7 +62,6 @@ export const userDto = {
email: createUserDto.user1.email,
password: createUserDto.user1.password,
storageLabel: null,
- externalPath: null,
oauthId: '',
shouldChangePassword: false,
profileImagePath: '',
diff --git a/e2e/src/generators.ts b/e2e/src/generators.ts
new file mode 100644
index 000000000..c87427cea
--- /dev/null
+++ b/e2e/src/generators.ts
@@ -0,0 +1,31 @@
+import { PNG } from 'pngjs';
+
+const createPNG = (r: number, g: number, b: number) => {
+ const image = new PNG({ width: 1, height: 1 });
+ image.data[0] = r;
+ image.data[1] = g;
+ image.data[2] = b;
+ image.data[3] = 255;
+ return PNG.sync.write(image);
+};
+
+function* newPngFactory() {
+ for (let r = 0; r < 255; r++) {
+ for (let g = 0; g < 255; g++) {
+ for (let b = 0; b < 255; b++) {
+ yield createPNG(r, g, b);
+ }
+ }
+ }
+}
+
+const pngFactory = newPngFactory();
+
+export const makeRandomImage = () => {
+ const { value } = pngFactory.next();
+ if (!value) {
+ throw new Error('Ran out of random asset data');
+ }
+
+ return value;
+};
diff --git a/e2e/src/responses.ts b/e2e/src/responses.ts
index 5e6a01eda..76e289ade 100644
--- a/e2e/src/responses.ts
+++ b/e2e/src/responses.ts
@@ -65,7 +65,6 @@ export const signupResponseDto = {
name: 'Immich Admin',
email: 'admin@immich.cloud',
storageLabel: 'admin',
- externalPath: null,
profileImagePath: '',
// why? lol
shouldChangePassword: true,
diff --git a/e2e/src/setup.ts b/e2e/src/setup.ts
index b560a2bbb..e0ff44356 100644
--- a/e2e/src/setup.ts
+++ b/e2e/src/setup.ts
@@ -1,26 +1,24 @@
-import { spawn, exec } from 'child_process';
+import { exec, spawn } from 'node:child_process';
export default async () => {
let _resolve: () => unknown;
- const promise = new Promise((resolve) => (_resolve = resolve));
+ const ready = new Promise((resolve) => (_resolve = resolve));
const child = spawn('docker', ['compose', 'up'], { stdio: 'pipe' });
child.stdout.on('data', (data) => {
const input = data.toString();
console.log(input);
- if (input.includes('Immich Server is listening')) {
+ if (input.includes('Immich Microservices is listening')) {
_resolve();
}
});
child.stderr.on('data', (data) => console.log(data.toString()));
- await promise;
+ await ready;
return async () => {
- await new Promise((resolve) =>
- exec('docker compose down', () => resolve())
- );
+ await new Promise((resolve) => exec('docker compose down', () => resolve()));
};
};
diff --git a/e2e/src/utils.ts b/e2e/src/utils.ts
index 428c88b45..34f25e396 100644
--- a/e2e/src/utils.ts
+++ b/e2e/src/utils.ts
@@ -1,12 +1,16 @@
import {
AssetFileUploadResponseDto,
+ AssetResponseDto,
CreateAlbumDto,
CreateAssetDto,
+ CreateLibraryDto,
CreateUserDto,
PersonUpdateDto,
SharedLinkCreateDto,
+ ValidateLibraryDto,
createAlbum,
createApiKey,
+ createLibrary,
createPerson,
createSharedLink,
createUser,
@@ -17,16 +21,18 @@ import {
setAdminOnboarding,
signUpAdmin,
updatePerson,
+ validate,
} from '@immich/sdk';
import { BrowserContext } from '@playwright/test';
-import { exec, spawn } from 'child_process';
-import { randomBytes } from 'node:crypto';
+import { exec, spawn } from 'node:child_process';
import { access } from 'node:fs/promises';
+import { tmpdir } from 'node:os';
import path from 'node:path';
import { promisify } from 'node:util';
import pg from 'pg';
import { io, type Socket } from 'socket.io-client';
import { loginDto, signupDto } from 'src/fixtures';
+import { makeRandomImage } from 'src/generators';
import request from 'supertest';
const execPromise = promisify(exec);
@@ -40,6 +46,8 @@ const directoryExists = (directory: string) =>
// TODO move test assets into e2e/assets
export const testAssetDir = path.resolve(`./../server/test/assets/`);
+export const testAssetDirInternal = '/data/assets';
+export const tempDir = tmpdir();
const serverContainerName = 'immich-e2e-server';
const mediaDir = '/usr/src/app/upload';
@@ -47,6 +55,7 @@ const dirs = [
`"${mediaDir}/thumbs"`,
`"${mediaDir}/upload"`,
`"${mediaDir}/library"`,
+ `"${mediaDir}/encoded-video"`,
].join(' ');
if (!(await directoryExists(`${testAssetDir}/albums`))) {
@@ -65,20 +74,12 @@ let client: pg.Client | null = null;
export const fileUtils = {
reset: async () => {
- await execPromise(
- `docker exec -i "${serverContainerName}" /bin/bash -c "rm -rf ${dirs} && mkdir ${dirs}"`,
- );
+ await execPromise(`docker exec -i "${serverContainerName}" /bin/bash -c "rm -rf ${dirs} && mkdir ${dirs}"`);
},
};
export const dbUtils = {
- createFace: async ({
- assetId,
- personId,
- }: {
- assetId: string;
- personId: string;
- }) => {
+ createFace: async ({ assetId, personId }: { assetId: string; personId: string }) => {
if (!client) {
return;
}
@@ -86,31 +87,28 @@ export const dbUtils = {
const vector = Array.from({ length: 512 }, Math.random);
const embedding = `[${vector.join(',')}]`;
- await client.query(
- 'INSERT INTO asset_faces ("assetId", "personId", "embedding") VALUES ($1, $2, $3)',
- [assetId, personId, embedding],
- );
+ await client.query('INSERT INTO asset_faces ("assetId", "personId", "embedding") VALUES ($1, $2, $3)', [
+ assetId,
+ personId,
+ embedding,
+ ]);
},
setPersonThumbnail: async (personId: string) => {
if (!client) {
return;
}
- await client.query(
- `UPDATE "person" set "thumbnailPath" = '/my/awesome/thumbnail.jpg' where "id" = $1`,
- [personId],
- );
+ await client.query(`UPDATE "person" set "thumbnailPath" = '/my/awesome/thumbnail.jpg' where "id" = $1`, [personId]);
},
reset: async (tables?: string[]) => {
try {
if (!client) {
- client = new pg.Client(
- 'postgres://postgres:postgres@127.0.0.1:5433/immich',
- );
+ client = new pg.Client('postgres://postgres:postgres@127.0.0.1:5433/immich');
await client.connect();
}
tables = tables || [
+ 'libraries',
'shared_links',
'person',
'albums',
@@ -177,37 +175,80 @@ export interface AdminSetupOptions {
onboarding?: boolean;
}
+export enum SocketEvent {
+ UPLOAD = 'upload',
+ DELETE = 'delete',
+}
+
+export type EventType = 'upload' | 'delete';
+export interface WaitOptions {
+ event: EventType;
+ assetId: string;
+ timeout?: number;
+}
+
+const events: Record> = {
+ upload: new Set(),
+ delete: new Set(),
+};
+
+const callbacks: Record void> = {};
+
+const onEvent = ({ event, assetId }: { event: EventType; assetId: string }) => {
+ events[event].add(assetId);
+ const callback = callbacks[assetId];
+ if (callback) {
+ callback();
+ delete callbacks[assetId];
+ }
+};
+
export const wsUtils = {
connect: async (accessToken: string) => {
const websocket = io('http://127.0.0.1:2283', {
path: '/api/socket.io',
transports: ['websocket'],
extraHeaders: { Authorization: `Bearer ${accessToken}` },
- autoConnect: false,
+ autoConnect: true,
forceNew: true,
});
return new Promise((resolve) => {
- websocket.on('connect', () => resolve(websocket));
- websocket.connect();
+ websocket
+ .on('connect', () => resolve(websocket))
+ .on('on_upload_success', (data: AssetResponseDto) => onEvent({ event: 'upload', assetId: data.id }))
+ .on('on_asset_delete', (assetId: string) => onEvent({ event: 'delete', assetId }))
+ .connect();
});
},
disconnect: (ws: Socket) => {
if (ws?.connected) {
ws.disconnect();
}
+
+ for (const set of Object.values(events)) {
+ set.clear();
+ }
},
- once: (ws: Socket, event: string): Promise => {
- return new Promise((resolve, reject) => {
- const timeout = setTimeout(() => reject(new Error('Timeout')), 4000);
- ws.once(event, (data: T) => {
+ waitForEvent: async ({ event, assetId, timeout: ms }: WaitOptions): Promise => {
+ const set = events[event];
+ if (set.has(assetId)) {
+ return;
+ }
+
+ return new Promise((resolve, reject) => {
+ const timeout = setTimeout(() => reject(new Error(`Timed out waiting for ${event} event`)), ms || 5000);
+
+ callbacks[assetId] = () => {
clearTimeout(timeout);
- resolve(data);
- });
+ resolve();
+ };
});
},
};
+type AssetData = { bytes?: Buffer; filename: string };
+
export const apiUtils = {
setup: () => {
defaults.baseUrl = app;
@@ -224,86 +265,64 @@ export const apiUtils = {
return response;
},
userSetup: async (accessToken: string, dto: CreateUserDto) => {
- await createUser(
- { createUserDto: dto },
- { headers: asBearerAuth(accessToken) },
- );
+ await createUser({ createUserDto: dto }, { headers: asBearerAuth(accessToken) });
return login({
loginCredentialDto: { email: dto.email, password: dto.password },
});
},
createApiKey: (accessToken: string) => {
- return createApiKey(
- { apiKeyCreateDto: { name: 'e2e' } },
- { headers: asBearerAuth(accessToken) },
- );
+ return createApiKey({ apiKeyCreateDto: { name: 'e2e' } }, { headers: asBearerAuth(accessToken) });
},
createAlbum: (accessToken: string, dto: CreateAlbumDto) =>
- createAlbum(
- { createAlbumDto: dto },
- { headers: asBearerAuth(accessToken) },
- ),
+ createAlbum({ createAlbumDto: dto }, { headers: asBearerAuth(accessToken) }),
createAsset: async (
accessToken: string,
- dto?: Partial>,
- data?: {
- bytes?: Buffer;
- filename?: string;
- },
+ dto?: Partial> & { assetData?: AssetData },
) => {
const _dto = {
deviceAssetId: 'test-1',
deviceId: 'test',
fileCreatedAt: new Date().toISOString(),
fileModifiedAt: new Date().toISOString(),
- ...(dto || {}),
+ ...dto,
};
- const _assetData = {
- bytes: randomBytes(32),
- filename: 'example.jpg',
- ...(data || {}),
- };
+ const assetData = dto?.assetData?.bytes || makeRandomImage();
+ const filename = dto?.assetData?.filename || 'example.png';
const builder = request(app)
.post(`/asset/upload`)
- .attach('assetData', _assetData.bytes, _assetData.filename)
+ .attach('assetData', assetData, filename)
.set('Authorization', `Bearer ${accessToken}`);
for (const [key, value] of Object.entries(_dto)) {
- builder.field(key, String(value));
+ void builder.field(key, String(value));
}
const { body } = await builder;
return body as AssetFileUploadResponseDto;
},
- getAssetInfo: (accessToken: string, id: string) =>
- getAssetInfo({ id }, { headers: asBearerAuth(accessToken) }),
+ getAssetInfo: (accessToken: string, id: string) => getAssetInfo({ id }, { headers: asBearerAuth(accessToken) }),
deleteAssets: (accessToken: string, ids: string[]) =>
- deleteAssets(
- { assetBulkDeleteDto: { ids } },
- { headers: asBearerAuth(accessToken) },
- ),
+ deleteAssets({ assetBulkDeleteDto: { ids } }, { headers: asBearerAuth(accessToken) }),
createPerson: async (accessToken: string, dto?: PersonUpdateDto) => {
// TODO fix createPerson to accept a body
- let person = await createPerson({ headers: asBearerAuth(accessToken) });
+ const person = await createPerson({ headers: asBearerAuth(accessToken) });
await dbUtils.setPersonThumbnail(person.id);
if (!dto) {
return person;
}
- return updatePerson(
- { id: person.id, personUpdateDto: dto },
- { headers: asBearerAuth(accessToken) },
- );
+ return updatePerson({ id: person.id, personUpdateDto: dto }, { headers: asBearerAuth(accessToken) });
},
createSharedLink: (accessToken: string, dto: SharedLinkCreateDto) =>
- createSharedLink(
- { sharedLinkCreateDto: dto },
- { headers: asBearerAuth(accessToken) },
- ),
+ createSharedLink({ sharedLinkCreateDto: dto }, { headers: asBearerAuth(accessToken) }),
+ createLibrary: (accessToken: string, dto: CreateLibraryDto) =>
+ createLibrary({ createLibraryDto: dto }, { headers: asBearerAuth(accessToken) }),
+ validateLibrary: (accessToken: string, id: string, dto: ValidateLibraryDto) =>
+ validate({ id, validateLibraryDto: dto }, { headers: asBearerAuth(accessToken) }),
};
export const cliUtils = {
@@ -323,7 +342,7 @@ export const webUtils = {
value: accessToken,
domain: '127.0.0.1',
path: '/',
- expires: 1742402728,
+ expires: 1_742_402_728,
httpOnly: true,
secure: false,
sameSite: 'Lax',
@@ -333,7 +352,7 @@ export const webUtils = {
value: 'password',
domain: '127.0.0.1',
path: '/',
- expires: 1742402728,
+ expires: 1_742_402_728,
httpOnly: true,
secure: false,
sameSite: 'Lax',
@@ -343,7 +362,7 @@ export const webUtils = {
value: 'true',
domain: '127.0.0.1',
path: '/',
- expires: 1742402728,
+ expires: 1_742_402_728,
httpOnly: false,
secure: false,
sameSite: 'Lax',
diff --git a/e2e/src/web/specs/auth.e2e-spec.ts b/e2e/src/web/specs/auth.e2e-spec.ts
index ac95a76da..23210205a 100644
--- a/e2e/src/web/specs/auth.e2e-spec.ts
+++ b/e2e/src/web/specs/auth.e2e-spec.ts
@@ -1,4 +1,4 @@
-import { test, expect } from '@playwright/test';
+import { expect, test } from '@playwright/test';
import { apiUtils, dbUtils, webUtils } from 'src/utils';
test.describe('Registration', () => {
@@ -68,7 +68,7 @@ test.describe('Registration', () => {
await page.getByRole('button', { name: 'Login' }).click();
// change password
- expect(page.getByRole('heading')).toHaveText('Change Password');
+ await expect(page.getByRole('heading')).toHaveText('Change Password');
await expect(page).toHaveURL('/auth/change-password');
await page.getByLabel('New Password').fill('new-password');
await page.getByLabel('Confirm Password').fill('new-password');
diff --git a/e2e/src/web/specs/shared-link.e2e-spec.ts b/e2e/src/web/specs/shared-link.e2e-spec.ts
index ce79ed545..6b2dbad95 100644
--- a/e2e/src/web/specs/shared-link.e2e-spec.ts
+++ b/e2e/src/web/specs/shared-link.e2e-spec.ts
@@ -1,18 +1,17 @@
import {
AlbumResponseDto,
- AssetResponseDto,
+ AssetFileUploadResponseDto,
LoginResponseDto,
SharedLinkResponseDto,
SharedLinkType,
createAlbum,
- createSharedLink,
} from '@immich/sdk';
import { test } from '@playwright/test';
import { apiUtils, asBearerAuth, dbUtils } from 'src/utils';
test.describe('Shared Links', () => {
let admin: LoginResponseDto;
- let asset: AssetResponseDto;
+ let asset: AssetFileUploadResponseDto;
let album: AlbumResponseDto;
let sharedLink: SharedLinkResponseDto;
let sharedLinkPassword: SharedLinkResponseDto;
@@ -29,7 +28,7 @@ test.describe('Shared Links', () => {
assetIds: [asset.id],
},
},
- { headers: asBearerAuth(admin.accessToken) }
+ { headers: asBearerAuth(admin.accessToken) },
);
sharedLink = await apiUtils.createSharedLink(admin.accessToken, {
type: SharedLinkType.Album,
@@ -53,7 +52,7 @@ test.describe('Shared Links', () => {
await page.waitForSelector('#asset-group-by-date svg');
await page.getByRole('checkbox').click();
await page.getByRole('button', { name: 'Download' }).click();
- await page.getByText('DOWNLOADING').waitFor();
+ await page.getByText('DOWNLOADING', { exact: true }).waitFor();
});
test('enter password for a shared link', async ({ page }) => {
diff --git a/e2e/tsconfig.json b/e2e/tsconfig.json
index a73444454..341d2ba18 100644
--- a/e2e/tsconfig.json
+++ b/e2e/tsconfig.json
@@ -18,5 +18,6 @@
"rootDirs": ["src"],
"baseUrl": "./"
},
+ "include": ["src/**/*.ts"],
"exclude": ["dist", "node_modules"]
}
diff --git a/e2e/vitest.config.ts b/e2e/vitest.config.ts
index 72c126a89..b8cc098dd 100644
--- a/e2e/vitest.config.ts
+++ b/e2e/vitest.config.ts
@@ -1,9 +1,17 @@
import { defineConfig } from 'vitest/config';
+// skip `docker compose up` if `make e2e` was already run
+const globalSetup: string[] = [];
+try {
+ await fetch('http://127.0.0.1:2283/api/server-info/ping');
+} catch {
+ globalSetup.push('src/setup.ts');
+}
+
export default defineConfig({
test: {
include: ['src/{api,cli}/specs/*.e2e-spec.ts'],
- globalSetup: ['src/setup.ts'],
+ globalSetup,
poolOptions: {
threads: {
singleThread: true,
diff --git a/machine-learning/Dockerfile b/machine-learning/Dockerfile
index d317a5298..c0a1a2030 100644
--- a/machine-learning/Dockerfile
+++ b/machine-learning/Dockerfile
@@ -39,7 +39,7 @@ FROM python:3.11-slim-bookworm@sha256:ce81dc539f0aedc9114cae640f8352fad83d37461c
FROM openvino/ubuntu22_runtime:2023.1.0@sha256:002842a9005ba01543b7169ff6f14ecbec82287f09c4d1dd37717f0a8e8754a7 as prod-openvino
USER root
-FROM nvidia/cuda:11.8.0-cudnn8-runtime-ubuntu22.04@sha256:85fb7ac694079fff1061a0140fd5b5a641997880e12112d92589c3bbb1e8b7ca as prod-cuda
+FROM nvidia/cuda:12.2.2-cudnn8-runtime-ubuntu22.04@sha256:8b51b1fe922964d73c482a267b5b519e990d90bf744ec7a40419923737caff6d as prod-cuda
COPY --from=builder-cuda /usr/local/bin/python3 /usr/local/bin/python3
COPY --from=builder-cuda /usr/local/lib/python3.11 /usr/local/lib/python3.11
diff --git a/machine-learning/poetry.lock b/machine-learning/poetry.lock
index d7cff9c10..d3bb8578d 100644
--- a/machine-learning/poetry.lock
+++ b/machine-learning/poetry.lock
@@ -1,4 +1,4 @@
-# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand.
+# This file is automatically @generated by Poetry 1.8.1 and should not be changed by hand.
[[package]]
name = "aiocache"
@@ -2030,21 +2030,21 @@ sympy = "*"
[[package]]
name = "onnxruntime-gpu"
-version = "1.17.0"
+version = "1.17.1"
description = "ONNX Runtime is a runtime accelerator for Machine Learning models"
optional = false
python-versions = "*"
files = [
- {file = "onnxruntime_gpu-1.17.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:1f2a4e0468ac0bd8246996c3d5dbba92cbbaca874bcd7f9cee4e99ce6eb27f5b"},
- {file = "onnxruntime_gpu-1.17.0-cp310-cp310-win_amd64.whl", hash = "sha256:0721b7930d7abed3730b2335e639e60d94ec411bb4d35a0347cc9c8b52c34540"},
- {file = "onnxruntime_gpu-1.17.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:be0314afe399943904de7c1ca797cbcc63e6fad60eb85d3df6422f81dd94e79e"},
- {file = "onnxruntime_gpu-1.17.0-cp311-cp311-win_amd64.whl", hash = "sha256:52125c24b21406d1431e43de1c98cea29c21e0cceba80db530b7e4c9216d86ea"},
- {file = "onnxruntime_gpu-1.17.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:bb802d8033885c412269f8bc8877d8779b0dc874df6fb9df8b796cba7276ad66"},
- {file = "onnxruntime_gpu-1.17.0-cp312-cp312-win_amd64.whl", hash = "sha256:8c43533e3e5335eaa78059fb86b849a4faded513a00c1feaaa205ca5af51c40f"},
- {file = "onnxruntime_gpu-1.17.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:1d461455bba160836d6c11c648c8fd4e4500d5c17096a13e6c2c9d22a4abd436"},
- {file = "onnxruntime_gpu-1.17.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4398f2175a92f4b35d95279a6294a89c462f24de058a2736ee1d498bab5a16"},
- {file = "onnxruntime_gpu-1.17.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:1d0e3805cd1c024aba7f4ae576fd08545fc27530a2aaad2b3c8ac0ee889fbd05"},
- {file = "onnxruntime_gpu-1.17.0-cp39-cp39-win_amd64.whl", hash = "sha256:fc1da5b93363ee600b5b220b04eeec51ad2c2b3e96f0b7615b16b8a173c88001"},
+ {file = "onnxruntime_gpu-1.17.1-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:e34ecb2b527ee1265135ae74cd99ea198ff344b8221929a920596a1e461e2bbb"},
+ {file = "onnxruntime_gpu-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:37786c0f225be90da0a66ca413fe125a925a0900263301cc4dbcad4ff0404673"},
+ {file = "onnxruntime_gpu-1.17.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:3bde190a683ec84ecf61bd390f3c275d388efe72404633df374c52c557ce6d4d"},
+ {file = "onnxruntime_gpu-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:5206c84caa770efcc2ca819f71ec007a244ed748ca04e7ff76b86df1a096d2c8"},
+ {file = "onnxruntime_gpu-1.17.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:0396ec73de565a64509d96dff154f531f8da8023c191f771ceba47a3f4efc266"},
+ {file = "onnxruntime_gpu-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:8531d4a833c8e978c5ff1de7b3bcc4126bbe58ea71fae54ddce58fe8777cb136"},
+ {file = "onnxruntime_gpu-1.17.1-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:7b831f9eafd626f3d44955420a4b1b84f9ffcb987712a0ab6a37d1ee9f2f7a45"},
+ {file = "onnxruntime_gpu-1.17.1-cp38-cp38-win_amd64.whl", hash = "sha256:a389334d3797519d4b12077db32b8764f1ce54374d0f89235edc04efe8bc192c"},
+ {file = "onnxruntime_gpu-1.17.1-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:27aeaa36385e459b3867577ed7f68c1756de79aa68f57141d4ae2a31c84f6a33"},
+ {file = "onnxruntime_gpu-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:8b46094ea348aff6c6494402ac4260e2d2aba0522ae13e1ae29d98a29384ed70"},
]
[package.dependencies]
@@ -2055,6 +2055,11 @@ packaging = "*"
protobuf = "*"
sympy = "*"
+[package.source]
+type = "legacy"
+url = "https://aiinfra.pkgs.visualstudio.com/PublicPackages/_packaging/onnxruntime-cuda-12/pypi/simple"
+reference = "cuda12"
+
[[package]]
name = "onnxruntime-openvino"
version = "1.15.0"
@@ -2628,7 +2633,6 @@ files = [
{file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"},
{file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"},
{file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"},
- {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"},
{file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"},
{file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"},
{file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"},
@@ -3619,4 +3623,4 @@ testing = ["coverage (>=5.0.3)", "zope.event", "zope.testing"]
[metadata]
lock-version = "2.0"
python-versions = ">=3.10,<3.12"
-content-hash = "c982d5c5fee76ca102d823010a538f287ac98583f330ebee3c0775c5f42f117d"
+content-hash = "c947090d326e81179054b7ce4dded311df8b7ca5a56680d5e9459cf8ca18df1a"
diff --git a/machine-learning/pyproject.toml b/machine-learning/pyproject.toml
index fec5c7213..0fffde12b 100644
--- a/machine-learning/pyproject.toml
+++ b/machine-learning/pyproject.toml
@@ -1,6 +1,6 @@
[tool.poetry]
name = "machine-learning"
-version = "1.95.1"
+version = "1.97.0"
description = ""
authors = ["Hau Tran "]
readme = "README.md"
@@ -45,7 +45,7 @@ onnxruntime = "^1.15.0"
optional = true
[tool.poetry.group.cuda.dependencies]
-onnxruntime-gpu = "^1.15.0"
+onnxruntime-gpu = {version = "^1.17.0", source = "cuda12"}
[tool.poetry.group.openvino]
optional = true
@@ -59,6 +59,11 @@ optional = true
[tool.poetry.group.armnn.dependencies]
onnxruntime = "^1.15.0"
+[[tool.poetry.source]]
+name = "cuda12"
+url = "https://aiinfra.pkgs.visualstudio.com/PublicPackages/_packaging/onnxruntime-cuda-12/pypi/simple/"
+priority = "explicit"
+
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
diff --git a/misc/release/pump-version.sh b/misc/release/pump-version.sh
index 0cd4e5b47..7d3f268f3 100755
--- a/misc/release/pump-version.sh
+++ b/misc/release/pump-version.sh
@@ -63,6 +63,7 @@ if [ "$CURRENT_SERVER" != "$NEXT_SERVER" ]; then
echo "Pumping Server: $CURRENT_SERVER => $NEXT_SERVER"
npm --prefix server version "$SERVER_PUMP"
npm --prefix web version "$SERVER_PUMP"
+ npm --prefix open-api/typescript-sdk version "$SERVER_PUMP"
make open-api
poetry --directory machine-learning version "$SERVER_PUMP"
fi
diff --git a/mobile/android/fastlane/Fastfile b/mobile/android/fastlane/Fastfile
index fc6399051..6e051103d 100644
--- a/mobile/android/fastlane/Fastfile
+++ b/mobile/android/fastlane/Fastfile
@@ -35,8 +35,8 @@ platform :android do
task: 'bundle',
build_type: 'Release',
properties: {
- "android.injected.version.code" => 123,
- "android.injected.version.name" => "1.95.1",
+ "android.injected.version.code" => 125,
+ "android.injected.version.name" => "1.97.0",
}
)
upload_to_play_store(skip_upload_apk: true, skip_upload_images: true, skip_upload_screenshots: true, aab: '../build/app/outputs/bundle/release/app-release.aab')
diff --git a/mobile/android/fastlane/report.xml b/mobile/android/fastlane/report.xml
index 585549fdb..575edaa4e 100644
--- a/mobile/android/fastlane/report.xml
+++ b/mobile/android/fastlane/report.xml
@@ -5,17 +5,17 @@
-
+
-
+
-
+
diff --git a/mobile/ios/Runner.xcodeproj/project.pbxproj b/mobile/ios/Runner.xcodeproj/project.pbxproj
index e9c5dda27..457160ad3 100644
--- a/mobile/ios/Runner.xcodeproj/project.pbxproj
+++ b/mobile/ios/Runner.xcodeproj/project.pbxproj
@@ -379,7 +379,7 @@
CODE_SIGN_ENTITLEMENTS = Runner/RunnerProfile.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 139;
+ CURRENT_PROJECT_VERSION = 141;
DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
@@ -515,7 +515,7 @@
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 139;
+ CURRENT_PROJECT_VERSION = 141;
DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
@@ -543,7 +543,7 @@
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 139;
+ CURRENT_PROJECT_VERSION = 141;
DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
diff --git a/mobile/ios/Runner/Info.plist b/mobile/ios/Runner/Info.plist
index 30ec0055c..6d745e984 100644
--- a/mobile/ios/Runner/Info.plist
+++ b/mobile/ios/Runner/Info.plist
@@ -55,11 +55,11 @@
CFBundlePackageType
APPL
CFBundleShortVersionString
- 1.95.0
+ 1.97.0
CFBundleSignature
????
CFBundleVersion
- 139
+ 141
FLTEnableImpeller
ITSAppUsesNonExemptEncryption
diff --git a/mobile/ios/fastlane/Fastfile b/mobile/ios/fastlane/Fastfile
index d5a42ad48..caf1dd8e6 100644
--- a/mobile/ios/fastlane/Fastfile
+++ b/mobile/ios/fastlane/Fastfile
@@ -19,7 +19,7 @@ platform :ios do
desc "iOS Beta"
lane :beta do
increment_version_number(
- version_number: "1.95.1"
+ version_number: "1.97.0"
)
increment_build_number(
build_number: latest_testflight_build_number + 1,
diff --git a/mobile/ios/fastlane/report.xml b/mobile/ios/fastlane/report.xml
index 7e27b4085..129dddb34 100644
--- a/mobile/ios/fastlane/report.xml
+++ b/mobile/ios/fastlane/report.xml
@@ -5,32 +5,32 @@
-
+
-
+
-
+
-
+
-
+
-
+
diff --git a/mobile/lib/modules/asset_viewer/views/gallery_viewer.dart b/mobile/lib/modules/asset_viewer/views/gallery_viewer.dart
index 48eb778c1..dfdfb3284 100644
--- a/mobile/lib/modules/asset_viewer/views/gallery_viewer.dart
+++ b/mobile/lib/modules/asset_viewer/views/gallery_viewer.dart
@@ -1,3 +1,4 @@
+import 'dart:async';
import 'dart:io';
import 'dart:math';
import 'dart:ui' as ui;
@@ -132,7 +133,7 @@ class GalleryViewerPage extends HookConsumerWidget {
void toggleFavorite(Asset asset) =>
ref.read(assetProvider.notifier).toggleFavorite([asset]);
- void precacheNextImage(int index) {
+ Future precacheNextImage(int index) async {
void onError(Object exception, StackTrace? stackTrace) {
// swallow error silently
debugPrint('Error precaching next image: $exception, $stackTrace');
@@ -140,7 +141,7 @@ class GalleryViewerPage extends HookConsumerWidget {
if (index < totalAssets && index >= 0) {
final asset = loadAsset(index);
- precacheImage(
+ await precacheImage(
ImmichImage.imageProvider(asset: asset),
context,
onError: onError,
@@ -711,6 +712,21 @@ class GalleryViewerPage extends HookConsumerWidget {
[],
);
+ useEffect(
+ () {
+ // No need to await this
+ unawaited(
+ // Delay this a bit so we can finish loading the page
+ Future.delayed(const Duration(milliseconds: 400)).then(
+ // Precache the next image
+ (_) => precacheNextImage(currentIndex.value + 1),
+ ),
+ );
+ return null;
+ },
+ [],
+ );
+
ref.listen(showControlsProvider, (_, show) {
if (show) {
SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
@@ -735,14 +751,21 @@ class GalleryViewerPage extends HookConsumerWidget {
isZoomed.value = state != PhotoViewScaleState.initial;
ref.read(showControlsProvider.notifier).show = !isZoomed.value;
},
- loadingBuilder: (context, event, index) => ImageFiltered(
- imageFilter: ui.ImageFilter.blur(
- sigmaX: 1,
- sigmaY: 1,
- ),
- child: ImmichThumbnail(
- asset: asset(),
- fit: BoxFit.contain,
+ loadingBuilder: (context, event, index) => ClipRect(
+ child: Stack(
+ fit: StackFit.expand,
+ children: [
+ BackdropFilter(
+ filter: ui.ImageFilter.blur(
+ sigmaX: 10,
+ sigmaY: 10,
+ ),
+ ),
+ ImmichThumbnail(
+ asset: asset(),
+ fit: BoxFit.contain,
+ ),
+ ],
),
),
pageController: controller,
@@ -754,12 +777,16 @@ class GalleryViewerPage extends HookConsumerWidget {
),
itemCount: totalAssets,
scrollDirection: Axis.horizontal,
- onPageChanged: (value) {
+ onPageChanged: (value) async {
final next = currentIndex.value < value ? value + 1 : value - 1;
- precacheNextImage(next);
+ HapticFeedback.selectionClick();
currentIndex.value = value;
stackIndex.value = -1;
- HapticFeedback.selectionClick();
+
+ // Wait for page change animation to finish
+ await Future.delayed(const Duration(milliseconds: 400));
+ // Then precache the next image
+ unawaited(precacheNextImage(next));
},
builder: (context, index) {
final a =
@@ -818,7 +845,7 @@ class GalleryViewerPage extends HookConsumerWidget {
isMotionVideo: isPlayingMotionVideo.value,
placeholder: Image(
image: provider,
- fit: BoxFit.fitWidth,
+ fit: BoxFit.contain,
height: context.height,
width: context.width,
alignment: Alignment.center,
diff --git a/mobile/lib/modules/asset_viewer/views/video_viewer_page.dart b/mobile/lib/modules/asset_viewer/views/video_viewer_page.dart
index eb125f27f..0da2bc52d 100644
--- a/mobile/lib/modules/asset_viewer/views/video_viewer_page.dart
+++ b/mobile/lib/modules/asset_viewer/views/video_viewer_page.dart
@@ -40,7 +40,7 @@ class VideoViewerPage extends HookWidget {
controlsSafeAreaMinimum: const EdgeInsets.only(
bottom: 100,
),
- placeholder: SizedBox.expand(child: placeholder),
+ placeholder: placeholder,
showControls: showControls && !isMotionVideo,
hideControlsTimer: hideControlsTimer,
customControls: const VideoPlayerControls(),
@@ -58,9 +58,13 @@ class VideoViewerPage extends HookWidget {
if (controller == null) {
return Stack(
children: [
- if (placeholder != null) SizedBox.expand(child: placeholder!),
- const DelayedLoadingIndicator(
- fadeInDuration: Duration(milliseconds: 500),
+ if (placeholder != null) placeholder!,
+ const Positioned.fill(
+ child: Center(
+ child: DelayedLoadingIndicator(
+ fadeInDuration: Duration(milliseconds: 500),
+ ),
+ ),
),
],
);
diff --git a/mobile/lib/modules/home/ui/control_bottom_app_bar.dart b/mobile/lib/modules/home/ui/control_bottom_app_bar.dart
index 78a348281..2a2843089 100644
--- a/mobile/lib/modules/home/ui/control_bottom_app_bar.dart
+++ b/mobile/lib/modules/home/ui/control_bottom_app_bar.dart
@@ -226,7 +226,7 @@ class ControlBottomAppBar extends ConsumerWidget {
if (selectionAssetState.hasLocal)
ControlBoxButton(
iconData: Icons.backup_outlined,
- label: "Upload",
+ label: "control_bottom_app_bar_upload".tr(),
onPressed: enabled
? () => showDialog(
context: context,
diff --git a/mobile/lib/modules/memories/views/memory_page.dart b/mobile/lib/modules/memories/views/memory_page.dart
index 9308e812d..d06bb959e 100644
--- a/mobile/lib/modules/memories/views/memory_page.dart
+++ b/mobile/lib/modules/memories/views/memory_page.dart
@@ -124,11 +124,14 @@ class MemoryPage extends HookConsumerWidget {
.then((_) => precacheAsset(1));
}
- onAssetChanged(int otherIndex) {
+ Future onAssetChanged(int otherIndex) async {
HapticFeedback.selectionClick();
currentAssetPage.value = otherIndex;
- precacheAsset(otherIndex + 1);
updateProgressText();
+ // Wait for page change animation to finish
+ await Future.delayed(const Duration(milliseconds: 400));
+ // And then precache the next asset
+ await precacheAsset(otherIndex + 1);
}
/* Notification listener is used instead of OnPageChanged callback since OnPageChanged is called
diff --git a/mobile/lib/shared/ui/delayed_loading_indicator.dart b/mobile/lib/shared/ui/delayed_loading_indicator.dart
index b4d9f4c80..e009b660c 100644
--- a/mobile/lib/shared/ui/delayed_loading_indicator.dart
+++ b/mobile/lib/shared/ui/delayed_loading_indicator.dart
@@ -20,21 +20,24 @@ class DelayedLoadingIndicator extends StatelessWidget {
@override
Widget build(BuildContext context) {
- return AnimatedSwitcher(
- duration: fadeInDuration ?? Duration.zero,
- child: FutureBuilder(
- future: Future.delayed(delay),
- builder: (context, snapshot) {
- if (snapshot.connectionState == ConnectionState.done) {
- return child ??
- const ImmichLoadingIndicator(
- key: ValueKey('loading'),
- );
- }
+ return FutureBuilder(
+ future: Future.delayed(delay),
+ builder: (context, snapshot) {
+ late Widget c;
+ if (snapshot.connectionState == ConnectionState.done) {
+ c = child ??
+ const ImmichLoadingIndicator(
+ key: ValueKey('loading'),
+ );
+ } else {
+ c = Container(key: const ValueKey('hiding'));
+ }
- return Container(key: const ValueKey('hiding'));
- },
- ),
+ return AnimatedSwitcher(
+ duration: fadeInDuration ?? Duration.zero,
+ child: c,
+ );
+ },
);
}
}
diff --git a/mobile/lib/shared/ui/immich_image.dart b/mobile/lib/shared/ui/immich_image.dart
index 3137f6301..f06f1726a 100644
--- a/mobile/lib/shared/ui/immich_image.dart
+++ b/mobile/lib/shared/ui/immich_image.dart
@@ -58,9 +58,11 @@ class ImmichImage extends StatelessWidget {
}
}
+ // Whether to use the local asset image provider or a remote one
static bool useLocal(Asset asset) =>
!asset.isRemote ||
asset.isLocal && !Store.get(StoreKey.preferRemoteImage, false);
+
@override
Widget build(BuildContext context) {
if (asset == null) {
diff --git a/mobile/lib/shared/ui/immich_thumbnail.dart b/mobile/lib/shared/ui/immich_thumbnail.dart
index fe35bdaac..77827348d 100644
--- a/mobile/lib/shared/ui/immich_thumbnail.dart
+++ b/mobile/lib/shared/ui/immich_thumbnail.dart
@@ -6,6 +6,7 @@ import 'package:immich_mobile/modules/asset_viewer/image_providers/immich_local_
import 'package:immich_mobile/modules/asset_viewer/image_providers/immich_remote_image_provider.dart';
import 'package:immich_mobile/shared/models/asset.dart';
import 'package:immich_mobile/shared/ui/hooks/blurhash_hook.dart';
+import 'package:immich_mobile/shared/ui/immich_image.dart';
import 'package:immich_mobile/shared/ui/thumbhash_placeholder.dart';
import 'package:octo_image/octo_image.dart';
@@ -43,7 +44,7 @@ class ImmichThumbnail extends HookWidget {
);
}
- if (useLocal(asset)) {
+ if (ImmichImage.useLocal(asset)) {
return ImmichLocalThumbnailProvider(
asset: asset,
height: thumbnailSize,
@@ -57,8 +58,6 @@ class ImmichThumbnail extends HookWidget {
}
}
- static bool useLocal(Asset asset) => !asset.isRemote || asset.isLocal;
-
@override
Widget build(BuildContext context) {
Uint8List? blurhash = useBlurHashRef(asset).value;
diff --git a/mobile/openapi/README.md b/mobile/openapi/README.md
index 41e65ee8b..b8548c79e 100644
--- a/mobile/openapi/README.md
+++ b/mobile/openapi/README.md
@@ -3,7 +3,7 @@ Immich API
This Dart package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
-- API version: 1.95.1
+- API version: 1.97.0
- Build package: org.openapitools.codegen.languages.DartClientCodegen
## Requirements
@@ -135,8 +135,8 @@ Class | Method | HTTP request | Description
*JobApi* | [**sendJobCommand**](doc//JobApi.md#sendjobcommand) | **PUT** /jobs/{id} |
*LibraryApi* | [**createLibrary**](doc//LibraryApi.md#createlibrary) | **POST** /library |
*LibraryApi* | [**deleteLibrary**](doc//LibraryApi.md#deletelibrary) | **DELETE** /library/{id} |
-*LibraryApi* | [**getLibraries**](doc//LibraryApi.md#getlibraries) | **GET** /library |
-*LibraryApi* | [**getLibraryInfo**](doc//LibraryApi.md#getlibraryinfo) | **GET** /library/{id} |
+*LibraryApi* | [**getAllLibraries**](doc//LibraryApi.md#getalllibraries) | **GET** /library |
+*LibraryApi* | [**getLibrary**](doc//LibraryApi.md#getlibrary) | **GET** /library/{id} |
*LibraryApi* | [**getLibraryStatistics**](doc//LibraryApi.md#getlibrarystatistics) | **GET** /library/{id}/statistics |
*LibraryApi* | [**removeOfflineFiles**](doc//LibraryApi.md#removeofflinefiles) | **POST** /library/{id}/removeOffline |
*LibraryApi* | [**scanLibrary**](doc//LibraryApi.md#scanlibrary) | **POST** /library/{id}/scan |
diff --git a/mobile/openapi/doc/AssetApi.md b/mobile/openapi/doc/AssetApi.md
index 93b758a59..c65e6a605 100644
--- a/mobile/openapi/doc/AssetApi.md
+++ b/mobile/openapi/doc/AssetApi.md
@@ -1401,7 +1401,7 @@ void (empty response body)
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **uploadFile**
-> AssetFileUploadResponseDto uploadFile(assetData, deviceAssetId, deviceId, fileCreatedAt, fileModifiedAt, key, duration, isArchived, isExternal, isFavorite, isOffline, isReadOnly, isVisible, libraryId, livePhotoData, sidecarData)
+> AssetFileUploadResponseDto uploadFile(assetData, deviceAssetId, deviceId, fileCreatedAt, fileModifiedAt, key, duration, isArchived, isFavorite, isOffline, isReadOnly, isVisible, libraryId, livePhotoData, sidecarData)
@@ -1432,7 +1432,6 @@ final fileModifiedAt = 2013-10-20T19:20:30+01:00; // DateTime |
final key = key_example; // String |
final duration = duration_example; // String |
final isArchived = true; // bool |
-final isExternal = true; // bool |
final isFavorite = true; // bool |
final isOffline = true; // bool |
final isReadOnly = true; // bool |
@@ -1442,7 +1441,7 @@ final livePhotoData = BINARY_DATA_HERE; // MultipartFile |
final sidecarData = BINARY_DATA_HERE; // MultipartFile |
try {
- final result = api_instance.uploadFile(assetData, deviceAssetId, deviceId, fileCreatedAt, fileModifiedAt, key, duration, isArchived, isExternal, isFavorite, isOffline, isReadOnly, isVisible, libraryId, livePhotoData, sidecarData);
+ final result = api_instance.uploadFile(assetData, deviceAssetId, deviceId, fileCreatedAt, fileModifiedAt, key, duration, isArchived, isFavorite, isOffline, isReadOnly, isVisible, libraryId, livePhotoData, sidecarData);
print(result);
} catch (e) {
print('Exception when calling AssetApi->uploadFile: $e\n');
@@ -1461,7 +1460,6 @@ Name | Type | Description | Notes
**key** | **String**| | [optional]
**duration** | **String**| | [optional]
**isArchived** | **bool**| | [optional]
- **isExternal** | **bool**| | [optional]
**isFavorite** | **bool**| | [optional]
**isOffline** | **bool**| | [optional]
**isReadOnly** | **bool**| | [optional]
diff --git a/mobile/openapi/doc/CreateLibraryDto.md b/mobile/openapi/doc/CreateLibraryDto.md
index 9e4859cee..e0caf1c8a 100644
--- a/mobile/openapi/doc/CreateLibraryDto.md
+++ b/mobile/openapi/doc/CreateLibraryDto.md
@@ -13,6 +13,7 @@ Name | Type | Description | Notes
**isVisible** | **bool** | | [optional]
**isWatched** | **bool** | | [optional]
**name** | **String** | | [optional]
+**ownerId** | **String** | | [optional]
**type** | [**LibraryType**](LibraryType.md) | |
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
diff --git a/mobile/openapi/doc/CreateUserDto.md b/mobile/openapi/doc/CreateUserDto.md
index 716571752..0dcc8eca1 100644
--- a/mobile/openapi/doc/CreateUserDto.md
+++ b/mobile/openapi/doc/CreateUserDto.md
@@ -9,7 +9,6 @@ import 'package:openapi/api.dart';
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**email** | **String** | |
-**externalPath** | **String** | | [optional]
**memoriesEnabled** | **bool** | | [optional]
**name** | **String** | |
**password** | **String** | |
diff --git a/mobile/openapi/doc/LibraryApi.md b/mobile/openapi/doc/LibraryApi.md
index ecaa73d86..8a204788b 100644
--- a/mobile/openapi/doc/LibraryApi.md
+++ b/mobile/openapi/doc/LibraryApi.md
@@ -11,8 +11,8 @@ Method | HTTP request | Description
------------- | ------------- | -------------
[**createLibrary**](LibraryApi.md#createlibrary) | **POST** /library |
[**deleteLibrary**](LibraryApi.md#deletelibrary) | **DELETE** /library/{id} |
-[**getLibraries**](LibraryApi.md#getlibraries) | **GET** /library |
-[**getLibraryInfo**](LibraryApi.md#getlibraryinfo) | **GET** /library/{id} |
+[**getAllLibraries**](LibraryApi.md#getalllibraries) | **GET** /library |
+[**getLibrary**](LibraryApi.md#getlibrary) | **GET** /library/{id} |
[**getLibraryStatistics**](LibraryApi.md#getlibrarystatistics) | **GET** /library/{id}/statistics |
[**removeOfflineFiles**](LibraryApi.md#removeofflinefiles) | **POST** /library/{id}/removeOffline |
[**scanLibrary**](LibraryApi.md#scanlibrary) | **POST** /library/{id}/scan |
@@ -129,8 +129,8 @@ void (empty response body)
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
-# **getLibraries**
-> List getLibraries()
+# **getAllLibraries**
+> List getAllLibraries(type)
@@ -153,17 +153,21 @@ import 'package:openapi/api.dart';
//defaultApiClient.getAuthentication('bearer').setAccessToken(yourTokenGeneratorFunction);
final api_instance = LibraryApi();
+final type = ; // LibraryType |
try {
- final result = api_instance.getLibraries();
+ final result = api_instance.getAllLibraries(type);
print(result);
} catch (e) {
- print('Exception when calling LibraryApi->getLibraries: $e\n');
+ print('Exception when calling LibraryApi->getAllLibraries: $e\n');
}
```
### Parameters
-This endpoint does not need any parameter.
+
+Name | Type | Description | Notes
+------------- | ------------- | ------------- | -------------
+ **type** | [**LibraryType**](.md)| | [optional]
### Return type
@@ -180,8 +184,8 @@ This endpoint does not need any parameter.
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
-# **getLibraryInfo**
-> LibraryResponseDto getLibraryInfo(id)
+# **getLibrary**
+> LibraryResponseDto getLibrary(id)
@@ -207,10 +211,10 @@ final api_instance = LibraryApi();
final id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
try {
- final result = api_instance.getLibraryInfo(id);
+ final result = api_instance.getLibrary(id);
print(result);
} catch (e) {
- print('Exception when calling LibraryApi->getLibraryInfo: $e\n');
+ print('Exception when calling LibraryApi->getLibrary: $e\n');
}
```
diff --git a/mobile/openapi/doc/PartnerResponseDto.md b/mobile/openapi/doc/PartnerResponseDto.md
index 46d16e6b2..ce45b3259 100644
--- a/mobile/openapi/doc/PartnerResponseDto.md
+++ b/mobile/openapi/doc/PartnerResponseDto.md
@@ -12,7 +12,6 @@ Name | Type | Description | Notes
**createdAt** | [**DateTime**](DateTime.md) | |
**deletedAt** | [**DateTime**](DateTime.md) | |
**email** | **String** | |
-**externalPath** | **String** | |
**id** | **String** | |
**inTimeline** | **bool** | | [optional]
**isAdmin** | **bool** | |
diff --git a/mobile/openapi/doc/SmartSearchDto.md b/mobile/openapi/doc/SmartSearchDto.md
index d4ec1a70f..d5f4c4025 100644
--- a/mobile/openapi/doc/SmartSearchDto.md
+++ b/mobile/openapi/doc/SmartSearchDto.md
@@ -27,6 +27,7 @@ Name | Type | Description | Notes
**make** | **String** | | [optional]
**model** | **String** | | [optional]
**page** | **num** | | [optional]
+**personIds** | **List** | | [optional] [default to const []]
**query** | **String** | |
**size** | **num** | | [optional]
**state** | **String** | | [optional]
diff --git a/mobile/openapi/doc/SystemConfigLibraryWatchDto.md b/mobile/openapi/doc/SystemConfigLibraryWatchDto.md
index baa0be6b0..43b975e21 100644
--- a/mobile/openapi/doc/SystemConfigLibraryWatchDto.md
+++ b/mobile/openapi/doc/SystemConfigLibraryWatchDto.md
@@ -9,8 +9,6 @@ import 'package:openapi/api.dart';
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**enabled** | **bool** | |
-**interval** | **int** | |
-**usePolling** | **bool** | |
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
diff --git a/mobile/openapi/doc/SystemConfigOAuthDto.md b/mobile/openapi/doc/SystemConfigOAuthDto.md
index c02dae9b7..43694f6fc 100644
--- a/mobile/openapi/doc/SystemConfigOAuthDto.md
+++ b/mobile/openapi/doc/SystemConfigOAuthDto.md
@@ -13,6 +13,7 @@ Name | Type | Description | Notes
**buttonText** | **String** | |
**clientId** | **String** | |
**clientSecret** | **String** | |
+**defaultStorageQuota** | **num** | |
**enabled** | **bool** | |
**issuerUrl** | **String** | |
**mobileOverrideEnabled** | **bool** | |
@@ -20,6 +21,7 @@ Name | Type | Description | Notes
**scope** | **String** | |
**signingAlgorithm** | **String** | |
**storageLabelClaim** | **String** | |
+**storageQuotaClaim** | **String** | |
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
diff --git a/mobile/openapi/doc/UpdateUserDto.md b/mobile/openapi/doc/UpdateUserDto.md
index 8c0572d1d..ef4ebf869 100644
--- a/mobile/openapi/doc/UpdateUserDto.md
+++ b/mobile/openapi/doc/UpdateUserDto.md
@@ -10,7 +10,6 @@ Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**avatarColor** | [**UserAvatarColor**](UserAvatarColor.md) | | [optional]
**email** | **String** | | [optional]
-**externalPath** | **String** | | [optional]
**id** | **String** | |
**isAdmin** | **bool** | | [optional]
**memoriesEnabled** | **bool** | | [optional]
diff --git a/mobile/openapi/doc/UserResponseDto.md b/mobile/openapi/doc/UserResponseDto.md
index 4ea44bb0c..700a5b849 100644
--- a/mobile/openapi/doc/UserResponseDto.md
+++ b/mobile/openapi/doc/UserResponseDto.md
@@ -12,7 +12,6 @@ Name | Type | Description | Notes
**createdAt** | [**DateTime**](DateTime.md) | |
**deletedAt** | [**DateTime**](DateTime.md) | |
**email** | **String** | |
-**externalPath** | **String** | |
**id** | **String** | |
**isAdmin** | **bool** | |
**memoriesEnabled** | **bool** | | [optional]
diff --git a/mobile/openapi/lib/api/asset_api.dart b/mobile/openapi/lib/api/asset_api.dart
index bdcb87409..786129b45 100644
--- a/mobile/openapi/lib/api/asset_api.dart
+++ b/mobile/openapi/lib/api/asset_api.dart
@@ -1676,8 +1676,6 @@ class AssetApi {
///
/// * [bool] isArchived:
///
- /// * [bool] isExternal:
- ///
/// * [bool] isFavorite:
///
/// * [bool] isOffline:
@@ -1691,7 +1689,7 @@ class AssetApi {
/// * [MultipartFile] livePhotoData:
///
/// * [MultipartFile] sidecarData:
- Future uploadFileWithHttpInfo(MultipartFile assetData, String deviceAssetId, String deviceId, DateTime fileCreatedAt, DateTime fileModifiedAt, { String? key, String? duration, bool? isArchived, bool? isExternal, bool? isFavorite, bool? isOffline, bool? isReadOnly, bool? isVisible, String? libraryId, MultipartFile? livePhotoData, MultipartFile? sidecarData, }) async {
+ Future uploadFileWithHttpInfo(MultipartFile assetData, String deviceAssetId, String deviceId, DateTime fileCreatedAt, DateTime fileModifiedAt, { String? key, String? duration, bool? isArchived, bool? isFavorite, bool? isOffline, bool? isReadOnly, bool? isVisible, String? libraryId, MultipartFile? livePhotoData, MultipartFile? sidecarData, }) async {
// ignore: prefer_const_declarations
final path = r'/asset/upload';
@@ -1739,10 +1737,6 @@ class AssetApi {
hasFields = true;
mp.fields[r'isArchived'] = parameterToString(isArchived);
}
- if (isExternal != null) {
- hasFields = true;
- mp.fields[r'isExternal'] = parameterToString(isExternal);
- }
if (isFavorite != null) {
hasFields = true;
mp.fields[r'isFavorite'] = parameterToString(isFavorite);
@@ -1806,8 +1800,6 @@ class AssetApi {
///
/// * [bool] isArchived:
///
- /// * [bool] isExternal:
- ///
/// * [bool] isFavorite:
///
/// * [bool] isOffline:
@@ -1821,8 +1813,8 @@ class AssetApi {
/// * [MultipartFile] livePhotoData:
///
/// * [MultipartFile] sidecarData:
- Future uploadFile(MultipartFile assetData, String deviceAssetId, String deviceId, DateTime fileCreatedAt, DateTime fileModifiedAt, { String? key, String? duration, bool? isArchived, bool? isExternal, bool? isFavorite, bool? isOffline, bool? isReadOnly, bool? isVisible, String? libraryId, MultipartFile? livePhotoData, MultipartFile? sidecarData, }) async {
- final response = await uploadFileWithHttpInfo(assetData, deviceAssetId, deviceId, fileCreatedAt, fileModifiedAt, key: key, duration: duration, isArchived: isArchived, isExternal: isExternal, isFavorite: isFavorite, isOffline: isOffline, isReadOnly: isReadOnly, isVisible: isVisible, libraryId: libraryId, livePhotoData: livePhotoData, sidecarData: sidecarData, );
+ Future uploadFile(MultipartFile assetData, String deviceAssetId, String deviceId, DateTime fileCreatedAt, DateTime fileModifiedAt, { String? key, String? duration, bool? isArchived, bool? isFavorite, bool? isOffline, bool? isReadOnly, bool? isVisible, String? libraryId, MultipartFile? livePhotoData, MultipartFile? sidecarData, }) async {
+ final response = await uploadFileWithHttpInfo(assetData, deviceAssetId, deviceId, fileCreatedAt, fileModifiedAt, key: key, duration: duration, isArchived: isArchived, isFavorite: isFavorite, isOffline: isOffline, isReadOnly: isReadOnly, isVisible: isVisible, libraryId: libraryId, livePhotoData: livePhotoData, sidecarData: sidecarData, );
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}
diff --git a/mobile/openapi/lib/api/library_api.dart b/mobile/openapi/lib/api/library_api.dart
index 21cec23eb..befd0aeef 100644
--- a/mobile/openapi/lib/api/library_api.dart
+++ b/mobile/openapi/lib/api/library_api.dart
@@ -104,7 +104,10 @@ class LibraryApi {
}
/// Performs an HTTP 'GET /library' operation and returns the [Response].
- Future getLibrariesWithHttpInfo() async {
+ /// Parameters:
+ ///
+ /// * [LibraryType] type:
+ Future getAllLibrariesWithHttpInfo({ LibraryType? type, }) async {
// ignore: prefer_const_declarations
final path = r'/library';
@@ -115,6 +118,10 @@ class LibraryApi {
final headerParams = {};
final formParams = {};
+ if (type != null) {
+ queryParams.addAll(_queryParams('', 'type', type));
+ }
+
const contentTypes = [];
@@ -129,8 +136,11 @@ class LibraryApi {
);
}
- Future?> getLibraries() async {
- final response = await getLibrariesWithHttpInfo();
+ /// Parameters:
+ ///
+ /// * [LibraryType] type:
+ Future?> getAllLibraries({ LibraryType? type, }) async {
+ final response = await getAllLibrariesWithHttpInfo( type: type, );
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}
@@ -151,7 +161,7 @@ class LibraryApi {
/// Parameters:
///
/// * [String] id (required):
- Future getLibraryInfoWithHttpInfo(String id,) async {
+ Future getLibraryWithHttpInfo(String id,) async {
// ignore: prefer_const_declarations
final path = r'/library/{id}'
.replaceAll('{id}', id);
@@ -180,8 +190,8 @@ class LibraryApi {
/// Parameters:
///
/// * [String] id (required):
- Future getLibraryInfo(String id,) async {
- final response = await getLibraryInfoWithHttpInfo(id,);
+ Future getLibrary(String id,) async {
+ final response = await getLibraryWithHttpInfo(id,);
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}
diff --git a/mobile/openapi/lib/model/create_library_dto.dart b/mobile/openapi/lib/model/create_library_dto.dart
index ca4217dcf..ef656ea2a 100644
--- a/mobile/openapi/lib/model/create_library_dto.dart
+++ b/mobile/openapi/lib/model/create_library_dto.dart
@@ -18,6 +18,7 @@ class CreateLibraryDto {
this.isVisible,
this.isWatched,
this.name,
+ this.ownerId,
required this.type,
});
@@ -49,6 +50,14 @@ class CreateLibraryDto {
///
String? name;
+ ///
+ /// Please note: This property should have been non-nullable! Since the specification file
+ /// does not include a default value (using the "default:" property), however, the generated
+ /// source code must fall back to having a nullable type.
+ /// Consider adding a "default:" property in the specification file to hide this note.
+ ///
+ String? ownerId;
+
LibraryType type;
@override
@@ -58,6 +67,7 @@ class CreateLibraryDto {
other.isVisible == isVisible &&
other.isWatched == isWatched &&
other.name == name &&
+ other.ownerId == ownerId &&
other.type == type;
@override
@@ -68,10 +78,11 @@ class CreateLibraryDto {
(isVisible == null ? 0 : isVisible!.hashCode) +
(isWatched == null ? 0 : isWatched!.hashCode) +
(name == null ? 0 : name!.hashCode) +
+ (ownerId == null ? 0 : ownerId!.hashCode) +
(type.hashCode);
@override
- String toString() => 'CreateLibraryDto[exclusionPatterns=$exclusionPatterns, importPaths=$importPaths, isVisible=$isVisible, isWatched=$isWatched, name=$name, type=$type]';
+ String toString() => 'CreateLibraryDto[exclusionPatterns=$exclusionPatterns, importPaths=$importPaths, isVisible=$isVisible, isWatched=$isWatched, name=$name, ownerId=$ownerId, type=$type]';
Map toJson() {
final json = {};
@@ -91,6 +102,11 @@ class CreateLibraryDto {
json[r'name'] = this.name;
} else {
// json[r'name'] = null;
+ }
+ if (this.ownerId != null) {
+ json[r'ownerId'] = this.ownerId;
+ } else {
+ // json[r'ownerId'] = null;
}
json[r'type'] = this.type;
return json;
@@ -113,6 +129,7 @@ class CreateLibraryDto {
isVisible: mapValueOfType(json, r'isVisible'),
isWatched: mapValueOfType(json, r'isWatched'),
name: mapValueOfType(json, r'name'),
+ ownerId: mapValueOfType(json, r'ownerId'),
type: LibraryType.fromJson(json[r'type'])!,
);
}
diff --git a/mobile/openapi/lib/model/create_user_dto.dart b/mobile/openapi/lib/model/create_user_dto.dart
index bfa26622f..f272842cb 100644
--- a/mobile/openapi/lib/model/create_user_dto.dart
+++ b/mobile/openapi/lib/model/create_user_dto.dart
@@ -14,7 +14,6 @@ class CreateUserDto {
/// Returns a new [CreateUserDto] instance.
CreateUserDto({
required this.email,
- this.externalPath,
this.memoriesEnabled,
required this.name,
required this.password,
@@ -24,8 +23,6 @@ class CreateUserDto {
String email;
- String? externalPath;
-
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
@@ -45,7 +42,6 @@ class CreateUserDto {
@override
bool operator ==(Object other) => identical(this, other) || other is CreateUserDto &&
other.email == email &&
- other.externalPath == externalPath &&
other.memoriesEnabled == memoriesEnabled &&
other.name == name &&
other.password == password &&
@@ -56,7 +52,6 @@ class CreateUserDto {
int get hashCode =>
// ignore: unnecessary_parenthesis
(email.hashCode) +
- (externalPath == null ? 0 : externalPath!.hashCode) +
(memoriesEnabled == null ? 0 : memoriesEnabled!.hashCode) +
(name.hashCode) +
(password.hashCode) +
@@ -64,16 +59,11 @@ class CreateUserDto {
(storageLabel == null ? 0 : storageLabel!.hashCode);
@override
- String toString() => 'CreateUserDto[email=$email, externalPath=$externalPath, memoriesEnabled=$memoriesEnabled, name=$name, password=$password, quotaSizeInBytes=$quotaSizeInBytes, storageLabel=$storageLabel]';
+ String toString() => 'CreateUserDto[email=$email, memoriesEnabled=$memoriesEnabled, name=$name, password=$password, quotaSizeInBytes=$quotaSizeInBytes, storageLabel=$storageLabel]';
Map toJson() {
final json = {};
json[r'email'] = this.email;
- if (this.externalPath != null) {
- json[r'externalPath'] = this.externalPath;
- } else {
- // json[r'externalPath'] = null;
- }
if (this.memoriesEnabled != null) {
json[r'memoriesEnabled'] = this.memoriesEnabled;
} else {
@@ -103,7 +93,6 @@ class CreateUserDto {
return CreateUserDto(
email: mapValueOfType(json, r'email')!,
- externalPath: mapValueOfType(json, r'externalPath'),
memoriesEnabled: mapValueOfType(json, r'memoriesEnabled'),
name: mapValueOfType(json, r'name')!,
password: mapValueOfType(json, r'password')!,
diff --git a/mobile/openapi/lib/model/partner_response_dto.dart b/mobile/openapi/lib/model/partner_response_dto.dart
index aa96f764b..008e0c4f2 100644
--- a/mobile/openapi/lib/model/partner_response_dto.dart
+++ b/mobile/openapi/lib/model/partner_response_dto.dart
@@ -17,7 +17,6 @@ class PartnerResponseDto {
required this.createdAt,
required this.deletedAt,
required this.email,
- required this.externalPath,
required this.id,
this.inTimeline,
required this.isAdmin,
@@ -40,8 +39,6 @@ class PartnerResponseDto {
String email;
- String? externalPath;
-
String id;
///
@@ -84,7 +81,6 @@ class PartnerResponseDto {
other.createdAt == createdAt &&
other.deletedAt == deletedAt &&
other.email == email &&
- other.externalPath == externalPath &&
other.id == id &&
other.inTimeline == inTimeline &&
other.isAdmin == isAdmin &&
@@ -105,7 +101,6 @@ class PartnerResponseDto {
(createdAt.hashCode) +
(deletedAt == null ? 0 : deletedAt!.hashCode) +
(email.hashCode) +
- (externalPath == null ? 0 : externalPath!.hashCode) +
(id.hashCode) +
(inTimeline == null ? 0 : inTimeline!.hashCode) +
(isAdmin.hashCode) +
@@ -120,7 +115,7 @@ class PartnerResponseDto {
(updatedAt.hashCode);
@override
- String toString() => 'PartnerResponseDto[avatarColor=$avatarColor, createdAt=$createdAt, deletedAt=$deletedAt, email=$email, externalPath=$externalPath, id=$id, inTimeline=$inTimeline, isAdmin=$isAdmin, memoriesEnabled=$memoriesEnabled, name=$name, oauthId=$oauthId, profileImagePath=$profileImagePath, quotaSizeInBytes=$quotaSizeInBytes, quotaUsageInBytes=$quotaUsageInBytes, shouldChangePassword=$shouldChangePassword, storageLabel=$storageLabel, updatedAt=$updatedAt]';
+ String toString() => 'PartnerResponseDto[avatarColor=$avatarColor, createdAt=$createdAt, deletedAt=$deletedAt, email=$email, id=$id, inTimeline=$inTimeline, isAdmin=$isAdmin, memoriesEnabled=$memoriesEnabled, name=$name, oauthId=$oauthId, profileImagePath=$profileImagePath, quotaSizeInBytes=$quotaSizeInBytes, quotaUsageInBytes=$quotaUsageInBytes, shouldChangePassword=$shouldChangePassword, storageLabel=$storageLabel, updatedAt=$updatedAt]';
Map toJson() {
final json = {};
@@ -132,11 +127,6 @@ class PartnerResponseDto {
// json[r'deletedAt'] = null;
}
json[r'email'] = this.email;
- if (this.externalPath != null) {
- json[r'externalPath'] = this.externalPath;
- } else {
- // json[r'externalPath'] = null;
- }
json[r'id'] = this.id;
if (this.inTimeline != null) {
json[r'inTimeline'] = this.inTimeline;
@@ -184,7 +174,6 @@ class PartnerResponseDto {
createdAt: mapDateTime(json, r'createdAt', r'')!,
deletedAt: mapDateTime(json, r'deletedAt', r''),
email: mapValueOfType(json, r'email')!,
- externalPath: mapValueOfType(json, r'externalPath'),
id: mapValueOfType(json, r'id')!,
inTimeline: mapValueOfType(json, r'inTimeline'),
isAdmin: mapValueOfType(json, r'isAdmin')!,
@@ -248,7 +237,6 @@ class PartnerResponseDto {
'createdAt',
'deletedAt',
'email',
- 'externalPath',
'id',
'isAdmin',
'name',
diff --git a/mobile/openapi/lib/model/smart_search_dto.dart b/mobile/openapi/lib/model/smart_search_dto.dart
index 664850db8..0b99acdd6 100644
--- a/mobile/openapi/lib/model/smart_search_dto.dart
+++ b/mobile/openapi/lib/model/smart_search_dto.dart
@@ -32,6 +32,7 @@ class SmartSearchDto {
this.make,
this.model,
this.page,
+ this.personIds = const [],
required this.query,
this.size,
this.state,
@@ -199,6 +200,8 @@ class SmartSearchDto {
///
num? page;
+ List personIds;
+
String query;
///
@@ -312,6 +315,7 @@ class SmartSearchDto {
other.make == make &&
other.model == model &&
other.page == page &&
+ _deepEquality.equals(other.personIds, personIds) &&
other.query == query &&
other.size == size &&
other.state == state &&
@@ -348,6 +352,7 @@ class SmartSearchDto {
(make == null ? 0 : make!.hashCode) +
(model == null ? 0 : model!.hashCode) +
(page == null ? 0 : page!.hashCode) +
+ (personIds.hashCode) +
(query.hashCode) +
(size == null ? 0 : size!.hashCode) +
(state == null ? 0 : state!.hashCode) +
@@ -363,7 +368,7 @@ class SmartSearchDto {
(withExif == null ? 0 : withExif!.hashCode);
@override
- String toString() => 'SmartSearchDto[city=$city, country=$country, createdAfter=$createdAfter, createdBefore=$createdBefore, deviceId=$deviceId, isArchived=$isArchived, isEncoded=$isEncoded, isExternal=$isExternal, isFavorite=$isFavorite, isMotion=$isMotion, isNotInAlbum=$isNotInAlbum, isOffline=$isOffline, isReadOnly=$isReadOnly, isVisible=$isVisible, lensModel=$lensModel, libraryId=$libraryId, make=$make, model=$model, page=$page, query=$query, size=$size, state=$state, takenAfter=$takenAfter, takenBefore=$takenBefore, trashedAfter=$trashedAfter, trashedBefore=$trashedBefore, type=$type, updatedAfter=$updatedAfter, updatedBefore=$updatedBefore, withArchived=$withArchived, withDeleted=$withDeleted, withExif=$withExif]';
+ String toString() => 'SmartSearchDto[city=$city, country=$country, createdAfter=$createdAfter, createdBefore=$createdBefore, deviceId=$deviceId, isArchived=$isArchived, isEncoded=$isEncoded, isExternal=$isExternal, isFavorite=$isFavorite, isMotion=$isMotion, isNotInAlbum=$isNotInAlbum, isOffline=$isOffline, isReadOnly=$isReadOnly, isVisible=$isVisible, lensModel=$lensModel, libraryId=$libraryId, make=$make, model=$model, page=$page, personIds=$personIds, query=$query, size=$size, state=$state, takenAfter=$takenAfter, takenBefore=$takenBefore, trashedAfter=$trashedAfter, trashedBefore=$trashedBefore, type=$type, updatedAfter=$updatedAfter, updatedBefore=$updatedBefore, withArchived=$withArchived, withDeleted=$withDeleted, withExif=$withExif]';
Map toJson() {
final json = {};
@@ -462,6 +467,7 @@ class SmartSearchDto {
} else {
// json[r'page'] = null;
}
+ json[r'personIds'] = this.personIds;
json[r'query'] = this.query;
if (this.size != null) {
json[r'size'] = this.size;
@@ -549,6 +555,9 @@ class SmartSearchDto {
make: mapValueOfType(json, r'make'),
model: mapValueOfType(json, r'model'),
page: num.parse('${json[r'page']}'),
+ personIds: json[r'personIds'] is Iterable
+ ? (json[r'personIds'] as Iterable).cast().toList(growable: false)
+ : const [],
query: mapValueOfType(json, r'query')!,
size: num.parse('${json[r'size']}'),
state: mapValueOfType(json, r'state'),
diff --git a/mobile/openapi/lib/model/system_config_library_watch_dto.dart b/mobile/openapi/lib/model/system_config_library_watch_dto.dart
index 795fd15fd..0bcb6f177 100644
--- a/mobile/openapi/lib/model/system_config_library_watch_dto.dart
+++ b/mobile/openapi/lib/model/system_config_library_watch_dto.dart
@@ -14,37 +14,25 @@ class SystemConfigLibraryWatchDto {
/// Returns a new [SystemConfigLibraryWatchDto] instance.
SystemConfigLibraryWatchDto({
required this.enabled,
- required this.interval,
- required this.usePolling,
});
bool enabled;
- int interval;
-
- bool usePolling;
-
@override
bool operator ==(Object other) => identical(this, other) || other is SystemConfigLibraryWatchDto &&
- other.enabled == enabled &&
- other.interval == interval &&
- other.usePolling == usePolling;
+ other.enabled == enabled;
@override
int get hashCode =>
// ignore: unnecessary_parenthesis
- (enabled.hashCode) +
- (interval.hashCode) +
- (usePolling.hashCode);
+ (enabled.hashCode);
@override
- String toString() => 'SystemConfigLibraryWatchDto[enabled=$enabled, interval=$interval, usePolling=$usePolling]';
+ String toString() => 'SystemConfigLibraryWatchDto[enabled=$enabled]';
Map toJson() {
final json = {};
json[r'enabled'] = this.enabled;
- json[r'interval'] = this.interval;
- json[r'usePolling'] = this.usePolling;
return json;
}
@@ -57,8 +45,6 @@ class SystemConfigLibraryWatchDto {
return SystemConfigLibraryWatchDto(
enabled: mapValueOfType(json, r'enabled')!,
- interval: mapValueOfType(json, r'interval')!,
- usePolling: mapValueOfType(json, r'usePolling')!,
);
}
return null;
@@ -107,8 +93,6 @@ class SystemConfigLibraryWatchDto {
/// The list of required keys that must be present in a JSON.
static const requiredKeys = {
'enabled',
- 'interval',
- 'usePolling',
};
}
diff --git a/mobile/openapi/lib/model/system_config_o_auth_dto.dart b/mobile/openapi/lib/model/system_config_o_auth_dto.dart
index 603ff8a95..1e7fe7f00 100644
--- a/mobile/openapi/lib/model/system_config_o_auth_dto.dart
+++ b/mobile/openapi/lib/model/system_config_o_auth_dto.dart
@@ -18,6 +18,7 @@ class SystemConfigOAuthDto {
required this.buttonText,
required this.clientId,
required this.clientSecret,
+ required this.defaultStorageQuota,
required this.enabled,
required this.issuerUrl,
required this.mobileOverrideEnabled,
@@ -25,6 +26,7 @@ class SystemConfigOAuthDto {
required this.scope,
required this.signingAlgorithm,
required this.storageLabelClaim,
+ required this.storageQuotaClaim,
});
bool autoLaunch;
@@ -37,6 +39,8 @@ class SystemConfigOAuthDto {
String clientSecret;
+ num defaultStorageQuota;
+
bool enabled;
String issuerUrl;
@@ -51,6 +55,8 @@ class SystemConfigOAuthDto {
String storageLabelClaim;
+ String storageQuotaClaim;
+
@override
bool operator ==(Object other) => identical(this, other) || other is SystemConfigOAuthDto &&
other.autoLaunch == autoLaunch &&
@@ -58,13 +64,15 @@ class SystemConfigOAuthDto {
other.buttonText == buttonText &&
other.clientId == clientId &&
other.clientSecret == clientSecret &&
+ other.defaultStorageQuota == defaultStorageQuota &&
other.enabled == enabled &&
other.issuerUrl == issuerUrl &&
other.mobileOverrideEnabled == mobileOverrideEnabled &&
other.mobileRedirectUri == mobileRedirectUri &&
other.scope == scope &&
other.signingAlgorithm == signingAlgorithm &&
- other.storageLabelClaim == storageLabelClaim;
+ other.storageLabelClaim == storageLabelClaim &&
+ other.storageQuotaClaim == storageQuotaClaim;
@override
int get hashCode =>
@@ -74,16 +82,18 @@ class SystemConfigOAuthDto {
(buttonText.hashCode) +
(clientId.hashCode) +
(clientSecret.hashCode) +
+ (defaultStorageQuota.hashCode) +
(enabled.hashCode) +
(issuerUrl.hashCode) +
(mobileOverrideEnabled.hashCode) +
(mobileRedirectUri.hashCode) +
(scope.hashCode) +
(signingAlgorithm.hashCode) +
- (storageLabelClaim.hashCode);
+ (storageLabelClaim.hashCode) +
+ (storageQuotaClaim.hashCode);
@override
- String toString() => 'SystemConfigOAuthDto[autoLaunch=$autoLaunch, autoRegister=$autoRegister, buttonText=$buttonText, clientId=$clientId, clientSecret=$clientSecret, enabled=$enabled, issuerUrl=$issuerUrl, mobileOverrideEnabled=$mobileOverrideEnabled, mobileRedirectUri=$mobileRedirectUri, scope=$scope, signingAlgorithm=$signingAlgorithm, storageLabelClaim=$storageLabelClaim]';
+ String toString() => 'SystemConfigOAuthDto[autoLaunch=$autoLaunch, autoRegister=$autoRegister, buttonText=$buttonText, clientId=$clientId, clientSecret=$clientSecret, defaultStorageQuota=$defaultStorageQuota, enabled=$enabled, issuerUrl=$issuerUrl, mobileOverrideEnabled=$mobileOverrideEnabled, mobileRedirectUri=$mobileRedirectUri, scope=$scope, signingAlgorithm=$signingAlgorithm, storageLabelClaim=$storageLabelClaim, storageQuotaClaim=$storageQuotaClaim]';
Map toJson() {
final json = {};
@@ -92,6 +102,7 @@ class SystemConfigOAuthDto {
json[r'buttonText'] = this.buttonText;
json[r'clientId'] = this.clientId;
json[r'clientSecret'] = this.clientSecret;
+ json[r'defaultStorageQuota'] = this.defaultStorageQuota;
json[r'enabled'] = this.enabled;
json[r'issuerUrl'] = this.issuerUrl;
json[r'mobileOverrideEnabled'] = this.mobileOverrideEnabled;
@@ -99,6 +110,7 @@ class SystemConfigOAuthDto {
json[r'scope'] = this.scope;
json[r'signingAlgorithm'] = this.signingAlgorithm;
json[r'storageLabelClaim'] = this.storageLabelClaim;
+ json[r'storageQuotaClaim'] = this.storageQuotaClaim;
return json;
}
@@ -115,6 +127,7 @@ class SystemConfigOAuthDto {
buttonText: mapValueOfType(json, r'buttonText')!,
clientId: mapValueOfType(json, r'clientId')!,
clientSecret: mapValueOfType(json, r'clientSecret')!,
+ defaultStorageQuota: num.parse('${json[r'defaultStorageQuota']}'),
enabled: mapValueOfType(json, r'enabled')!,
issuerUrl: mapValueOfType(json, r'issuerUrl')!,
mobileOverrideEnabled: mapValueOfType(json, r'mobileOverrideEnabled')!,
@@ -122,6 +135,7 @@ class SystemConfigOAuthDto {
scope: mapValueOfType(json, r'scope')!,
signingAlgorithm: mapValueOfType(json, r'signingAlgorithm')!,
storageLabelClaim: mapValueOfType(json, r'storageLabelClaim')!,
+ storageQuotaClaim: mapValueOfType(json, r'storageQuotaClaim')!,
);
}
return null;
@@ -174,6 +188,7 @@ class SystemConfigOAuthDto {
'buttonText',
'clientId',
'clientSecret',
+ 'defaultStorageQuota',
'enabled',
'issuerUrl',
'mobileOverrideEnabled',
@@ -181,6 +196,7 @@ class SystemConfigOAuthDto {
'scope',
'signingAlgorithm',
'storageLabelClaim',
+ 'storageQuotaClaim',
};
}
diff --git a/mobile/openapi/lib/model/update_user_dto.dart b/mobile/openapi/lib/model/update_user_dto.dart
index 520240178..8fc85b486 100644
--- a/mobile/openapi/lib/model/update_user_dto.dart
+++ b/mobile/openapi/lib/model/update_user_dto.dart
@@ -15,7 +15,6 @@ class UpdateUserDto {
UpdateUserDto({
this.avatarColor,
this.email,
- this.externalPath,
required this.id,
this.isAdmin,
this.memoriesEnabled,
@@ -42,14 +41,6 @@ class UpdateUserDto {
///
String? email;
- ///
- /// Please note: This property should have been non-nullable! Since the specification file
- /// does not include a default value (using the "default:" property), however, the generated
- /// source code must fall back to having a nullable type.
- /// Consider adding a "default:" property in the specification file to hide this note.
- ///
- String? externalPath;
-
String id;
///
@@ -106,7 +97,6 @@ class UpdateUserDto {
bool operator ==(Object other) => identical(this, other) || other is UpdateUserDto &&
other.avatarColor == avatarColor &&
other.email == email &&
- other.externalPath == externalPath &&
other.id == id &&
other.isAdmin == isAdmin &&
other.memoriesEnabled == memoriesEnabled &&
@@ -121,7 +111,6 @@ class UpdateUserDto {
// ignore: unnecessary_parenthesis
(avatarColor == null ? 0 : avatarColor!.hashCode) +
(email == null ? 0 : email!.hashCode) +
- (externalPath == null ? 0 : externalPath!.hashCode) +
(id.hashCode) +
(isAdmin == null ? 0 : isAdmin!.hashCode) +
(memoriesEnabled == null ? 0 : memoriesEnabled!.hashCode) +
@@ -132,7 +121,7 @@ class UpdateUserDto {
(storageLabel == null ? 0 : storageLabel!.hashCode);
@override
- String toString() => 'UpdateUserDto[avatarColor=$avatarColor, email=$email, externalPath=$externalPath, id=$id, isAdmin=$isAdmin, memoriesEnabled=$memoriesEnabled, name=$name, password=$password, quotaSizeInBytes=$quotaSizeInBytes, shouldChangePassword=$shouldChangePassword, storageLabel=$storageLabel]';
+ String toString() => 'UpdateUserDto[avatarColor=$avatarColor, email=$email, id=$id, isAdmin=$isAdmin, memoriesEnabled=$memoriesEnabled, name=$name, password=$password, quotaSizeInBytes=$quotaSizeInBytes, shouldChangePassword=$shouldChangePassword, storageLabel=$storageLabel]';
Map toJson() {
final json = {};
@@ -145,11 +134,6 @@ class UpdateUserDto {
json[r'email'] = this.email;
} else {
// json[r'email'] = null;
- }
- if (this.externalPath != null) {
- json[r'externalPath'] = this.externalPath;
- } else {
- // json[r'externalPath'] = null;
}
json[r'id'] = this.id;
if (this.isAdmin != null) {
@@ -200,7 +184,6 @@ class UpdateUserDto {
return UpdateUserDto(
avatarColor: UserAvatarColor.fromJson(json[r'avatarColor']),
email: mapValueOfType(json, r'email'),
- externalPath: mapValueOfType(json, r'externalPath'),
id: mapValueOfType(json, r'id')!,
isAdmin: mapValueOfType(json, r'isAdmin'),
memoriesEnabled: mapValueOfType(json, r'memoriesEnabled'),
diff --git a/mobile/openapi/lib/model/user_response_dto.dart b/mobile/openapi/lib/model/user_response_dto.dart
index 9da67392b..d4e0bf07d 100644
--- a/mobile/openapi/lib/model/user_response_dto.dart
+++ b/mobile/openapi/lib/model/user_response_dto.dart
@@ -17,7 +17,6 @@ class UserResponseDto {
required this.createdAt,
required this.deletedAt,
required this.email,
- required this.externalPath,
required this.id,
required this.isAdmin,
this.memoriesEnabled,
@@ -39,8 +38,6 @@ class UserResponseDto {
String email;
- String? externalPath;
-
String id;
bool isAdmin;
@@ -75,7 +72,6 @@ class UserResponseDto {
other.createdAt == createdAt &&
other.deletedAt == deletedAt &&
other.email == email &&
- other.externalPath == externalPath &&
other.id == id &&
other.isAdmin == isAdmin &&
other.memoriesEnabled == memoriesEnabled &&
@@ -95,7 +91,6 @@ class UserResponseDto {
(createdAt.hashCode) +
(deletedAt == null ? 0 : deletedAt!.hashCode) +
(email.hashCode) +
- (externalPath == null ? 0 : externalPath!.hashCode) +
(id.hashCode) +
(isAdmin.hashCode) +
(memoriesEnabled == null ? 0 : memoriesEnabled!.hashCode) +
@@ -109,7 +104,7 @@ class UserResponseDto {
(updatedAt.hashCode);
@override
- String toString() => 'UserResponseDto[avatarColor=$avatarColor, createdAt=$createdAt, deletedAt=$deletedAt, email=$email, externalPath=$externalPath, id=$id, isAdmin=$isAdmin, memoriesEnabled=$memoriesEnabled, name=$name, oauthId=$oauthId, profileImagePath=$profileImagePath, quotaSizeInBytes=$quotaSizeInBytes, quotaUsageInBytes=$quotaUsageInBytes, shouldChangePassword=$shouldChangePassword, storageLabel=$storageLabel, updatedAt=$updatedAt]';
+ String toString() => 'UserResponseDto[avatarColor=$avatarColor, createdAt=$createdAt, deletedAt=$deletedAt, email=$email, id=$id, isAdmin=$isAdmin, memoriesEnabled=$memoriesEnabled, name=$name, oauthId=$oauthId, profileImagePath=$profileImagePath, quotaSizeInBytes=$quotaSizeInBytes, quotaUsageInBytes=$quotaUsageInBytes, shouldChangePassword=$shouldChangePassword, storageLabel=$storageLabel, updatedAt=$updatedAt]';
Map toJson() {
final json = {};
@@ -121,11 +116,6 @@ class UserResponseDto {
// json[r'deletedAt'] = null;
}
json[r'email'] = this.email;
- if (this.externalPath != null) {
- json[r'externalPath'] = this.externalPath;
- } else {
- // json[r'externalPath'] = null;
- }
json[r'id'] = this.id;
json[r'isAdmin'] = this.isAdmin;
if (this.memoriesEnabled != null) {
@@ -168,7 +158,6 @@ class UserResponseDto {
createdAt: mapDateTime(json, r'createdAt', r'')!,
deletedAt: mapDateTime(json, r'deletedAt', r''),
email: mapValueOfType(json, r'email')!,
- externalPath: mapValueOfType(json, r'externalPath'),
id: mapValueOfType(json, r'id')!,
isAdmin: mapValueOfType(json, r'isAdmin')!,
memoriesEnabled: mapValueOfType(json, r'memoriesEnabled'),
@@ -231,7 +220,6 @@ class UserResponseDto {
'createdAt',
'deletedAt',
'email',
- 'externalPath',
'id',
'isAdmin',
'name',
diff --git a/mobile/openapi/test/asset_api_test.dart b/mobile/openapi/test/asset_api_test.dart
index 06375c6b4..846a5998c 100644
--- a/mobile/openapi/test/asset_api_test.dart
+++ b/mobile/openapi/test/asset_api_test.dart
@@ -135,7 +135,7 @@ void main() {
// TODO
});
- //Future uploadFile(MultipartFile assetData, String deviceAssetId, String deviceId, DateTime fileCreatedAt, DateTime fileModifiedAt, { String key, String duration, bool isArchived, bool isExternal, bool isFavorite, bool isOffline, bool isReadOnly, bool isVisible, String libraryId, MultipartFile livePhotoData, MultipartFile sidecarData }) async
+ //Future uploadFile(MultipartFile assetData, String deviceAssetId, String deviceId, DateTime fileCreatedAt, DateTime fileModifiedAt, { String key, String duration, bool isArchived, bool isFavorite, bool isOffline, bool isReadOnly, bool isVisible, String libraryId, MultipartFile livePhotoData, MultipartFile sidecarData }) async
test('test uploadFile', () async {
// TODO
});
diff --git a/mobile/openapi/test/create_library_dto_test.dart b/mobile/openapi/test/create_library_dto_test.dart
index dea1d4e63..88911249e 100644
--- a/mobile/openapi/test/create_library_dto_test.dart
+++ b/mobile/openapi/test/create_library_dto_test.dart
@@ -41,6 +41,11 @@ void main() {
// TODO
});
+ // String ownerId
+ test('to test the property `ownerId`', () async {
+ // TODO
+ });
+
// LibraryType type
test('to test the property `type`', () async {
// TODO
diff --git a/mobile/openapi/test/create_user_dto_test.dart b/mobile/openapi/test/create_user_dto_test.dart
index 6614b54a6..9658c02c8 100644
--- a/mobile/openapi/test/create_user_dto_test.dart
+++ b/mobile/openapi/test/create_user_dto_test.dart
@@ -21,11 +21,6 @@ void main() {
// TODO
});
- // String externalPath
- test('to test the property `externalPath`', () async {
- // TODO
- });
-
// bool memoriesEnabled
test('to test the property `memoriesEnabled`', () async {
// TODO
diff --git a/mobile/openapi/test/library_api_test.dart b/mobile/openapi/test/library_api_test.dart
index 20abcffe7..21afeff54 100644
--- a/mobile/openapi/test/library_api_test.dart
+++ b/mobile/openapi/test/library_api_test.dart
@@ -27,13 +27,13 @@ void main() {
// TODO
});
- //Future> getLibraries() async
- test('test getLibraries', () async {
+ //Future> getAllLibraries({ LibraryType type }) async
+ test('test getAllLibraries', () async {
// TODO
});
- //Future getLibraryInfo(String id) async
- test('test getLibraryInfo', () async {
+ //Future getLibrary(String id) async
+ test('test getLibrary', () async {
// TODO
});
diff --git a/mobile/openapi/test/partner_response_dto_test.dart b/mobile/openapi/test/partner_response_dto_test.dart
index d6b7769ab..7fce31d5e 100644
--- a/mobile/openapi/test/partner_response_dto_test.dart
+++ b/mobile/openapi/test/partner_response_dto_test.dart
@@ -36,11 +36,6 @@ void main() {
// TODO
});
- // String externalPath
- test('to test the property `externalPath`', () async {
- // TODO
- });
-
// String id
test('to test the property `id`', () async {
// TODO
diff --git a/mobile/openapi/test/smart_search_dto_test.dart b/mobile/openapi/test/smart_search_dto_test.dart
index 4db3ac080..5263f7bb6 100644
--- a/mobile/openapi/test/smart_search_dto_test.dart
+++ b/mobile/openapi/test/smart_search_dto_test.dart
@@ -111,6 +111,11 @@ void main() {
// TODO
});
+ // List personIds (default value: const [])
+ test('to test the property `personIds`', () async {
+ // TODO
+ });
+
// String query
test('to test the property `query`', () async {
// TODO
diff --git a/mobile/openapi/test/system_config_library_watch_dto_test.dart b/mobile/openapi/test/system_config_library_watch_dto_test.dart
index 74ab53d65..19b5de05f 100644
--- a/mobile/openapi/test/system_config_library_watch_dto_test.dart
+++ b/mobile/openapi/test/system_config_library_watch_dto_test.dart
@@ -21,16 +21,6 @@ void main() {
// TODO
});
- // int interval
- test('to test the property `interval`', () async {
- // TODO
- });
-
- // bool usePolling
- test('to test the property `usePolling`', () async {
- // TODO
- });
-
});
diff --git a/mobile/openapi/test/system_config_o_auth_dto_test.dart b/mobile/openapi/test/system_config_o_auth_dto_test.dart
index 2bcbb64ef..e855ff960 100644
--- a/mobile/openapi/test/system_config_o_auth_dto_test.dart
+++ b/mobile/openapi/test/system_config_o_auth_dto_test.dart
@@ -41,6 +41,11 @@ void main() {
// TODO
});
+ // num defaultStorageQuota
+ test('to test the property `defaultStorageQuota`', () async {
+ // TODO
+ });
+
// bool enabled
test('to test the property `enabled`', () async {
// TODO
@@ -76,6 +81,11 @@ void main() {
// TODO
});
+ // String storageQuotaClaim
+ test('to test the property `storageQuotaClaim`', () async {
+ // TODO
+ });
+
});
diff --git a/mobile/openapi/test/update_user_dto_test.dart b/mobile/openapi/test/update_user_dto_test.dart
index aaacfa7cb..10c506666 100644
--- a/mobile/openapi/test/update_user_dto_test.dart
+++ b/mobile/openapi/test/update_user_dto_test.dart
@@ -26,11 +26,6 @@ void main() {
// TODO
});
- // String externalPath
- test('to test the property `externalPath`', () async {
- // TODO
- });
-
// String id
test('to test the property `id`', () async {
// TODO
diff --git a/mobile/openapi/test/user_response_dto_test.dart b/mobile/openapi/test/user_response_dto_test.dart
index bef6c812e..d0fdf97e1 100644
--- a/mobile/openapi/test/user_response_dto_test.dart
+++ b/mobile/openapi/test/user_response_dto_test.dart
@@ -36,11 +36,6 @@ void main() {
// TODO
});
- // String externalPath
- test('to test the property `externalPath`', () async {
- // TODO
- });
-
// String id
test('to test the property `id`', () async {
// TODO
diff --git a/mobile/pubspec.lock b/mobile/pubspec.lock
index 9e379d465..f27351898 100644
--- a/mobile/pubspec.lock
+++ b/mobile/pubspec.lock
@@ -413,10 +413,10 @@ packages:
dependency: transitive
description:
name: file
- sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c"
+ sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d"
url: "https://pub.dev"
source: hosted
- version: "7.0.0"
+ version: "6.1.4"
file_selector_linux:
dependency: transitive
description:
@@ -860,30 +860,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "4.8.1"
- leak_tracker:
- dependency: transitive
- description:
- name: leak_tracker
- sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa"
- url: "https://pub.dev"
- source: hosted
- version: "10.0.0"
- leak_tracker_flutter_testing:
- dependency: transitive
- description:
- name: leak_tracker_flutter_testing
- sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0
- url: "https://pub.dev"
- source: hosted
- version: "2.0.1"
- leak_tracker_testing:
- dependency: transitive
- description:
- name: leak_tracker_testing
- sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47
- url: "https://pub.dev"
- source: hosted
- version: "2.0.1"
lints:
dependency: transitive
description:
@@ -931,18 +907,18 @@ packages:
dependency: transitive
description:
name: matcher
- sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
+ sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
url: "https://pub.dev"
source: hosted
- version: "0.12.16+1"
+ version: "0.12.16"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
- sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a"
+ sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
url: "https://pub.dev"
source: hosted
- version: "0.8.0"
+ version: "0.5.0"
meta:
dependency: "direct overridden"
description:
@@ -1026,10 +1002,10 @@ packages:
dependency: "direct main"
description:
name: path
- sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
+ sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917"
url: "https://pub.dev"
source: hosted
- version: "1.9.0"
+ version: "1.8.3"
path_provider:
dependency: "direct main"
description:
@@ -1162,10 +1138,10 @@ packages:
dependency: transitive
description:
name: platform
- sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec"
+ sha256: ae68c7bfcd7383af3629daafb32fb4e8681c7154428da4febcff06200585f102
url: "https://pub.dev"
source: hosted
- version: "3.1.4"
+ version: "3.1.2"
plugin_platform_interface:
dependency: transitive
description:
@@ -1194,10 +1170,10 @@ packages:
dependency: transitive
description:
name: process
- sha256: "21e54fd2faf1b5bdd5102afd25012184a6793927648ea81eea80552ac9405b32"
+ sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09"
url: "https://pub.dev"
source: hosted
- version: "5.0.2"
+ version: "4.2.4"
provider:
dependency: transitive
description:
@@ -1663,10 +1639,10 @@ packages:
dependency: transitive
description:
name: vm_service
- sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957
+ sha256: c538be99af830f478718b51630ec1b6bee5e74e52c8a802d328d9e71d35d2583
url: "https://pub.dev"
source: hosted
- version: "13.0.0"
+ version: "11.10.0"
wakelock_plus:
dependency: "direct main"
description:
@@ -1711,10 +1687,10 @@ packages:
dependency: transitive
description:
name: webdriver
- sha256: "003d7da9519e1e5f329422b36c4dcdf18d7d2978d1ba099ea4e45ba490ed845e"
+ sha256: "3c923e918918feeb90c4c9fdf1fe39220fa4c0e8e2c0fffaded174498ef86c49"
url: "https://pub.dev"
source: hosted
- version: "3.0.3"
+ version: "3.0.2"
win32:
dependency: transitive
description:
diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml
index 50d170904..04056977a 100644
--- a/mobile/pubspec.yaml
+++ b/mobile/pubspec.yaml
@@ -2,7 +2,7 @@ name: immich_mobile
description: Immich - selfhosted backup media file on mobile phone
publish_to: "none"
-version: 1.95.1+123
+version: 1.97.0+125
isar_version: &isar_version 3.1.0+1
environment:
diff --git a/open-api/bin/generate-open-api.sh b/open-api/bin/generate-open-api.sh
index f0a211abe..ba62bfd9e 100755
--- a/open-api/bin/generate-open-api.sh
+++ b/open-api/bin/generate-open-api.sh
@@ -17,9 +17,7 @@ function dart {
}
function typescript {
- rm -rf ./typescript-sdk/client
- npx --yes @openapitools/openapi-generator-cli generate -g typescript-axios -i ./immich-openapi-specs.json -o ./typescript-sdk/axios-client --additional-properties=useSingleRequestParameter=true,supportsES6=true
- npx --yes oazapfts --optimistic --argumentStyle=object --useEnumType immich-openapi-specs.json typescript-sdk/fetch-client.ts
+ npx --yes oazapfts --optimistic --argumentStyle=object --useEnumType immich-openapi-specs.json typescript-sdk/src/fetch-client.ts
npm --prefix typescript-sdk ci && npm --prefix typescript-sdk run build
}
diff --git a/open-api/immich-openapi-specs.json b/open-api/immich-openapi-specs.json
index 8fec89327..4010336fd 100644
--- a/open-api/immich-openapi-specs.json
+++ b/open-api/immich-openapi-specs.json
@@ -3299,8 +3299,17 @@
},
"/library": {
"get": {
- "operationId": "getLibraries",
- "parameters": [],
+ "operationId": "getAllLibraries",
+ "parameters": [
+ {
+ "name": "type",
+ "required": false,
+ "in": "query",
+ "schema": {
+ "$ref": "#/components/schemas/LibraryType"
+ }
+ }
+ ],
"responses": {
"200": {
"content": {
@@ -3387,7 +3396,7 @@
}
],
"responses": {
- "200": {
+ "204": {
"description": ""
}
},
@@ -3407,7 +3416,7 @@
]
},
"get": {
- "operationId": "getLibraryInfo",
+ "operationId": "getLibrary",
"parameters": [
{
"name": "id",
@@ -3512,7 +3521,7 @@
}
],
"responses": {
- "201": {
+ "204": {
"description": ""
}
},
@@ -3557,7 +3566,7 @@
"required": true
},
"responses": {
- "201": {
+ "204": {
"description": ""
}
},
@@ -6458,7 +6467,7 @@
"info": {
"title": "Immich",
"description": "Immich API",
- "version": "1.95.1",
+ "version": "1.97.0",
"contact": {}
},
"tags": [],
@@ -7532,9 +7541,6 @@
"isArchived": {
"type": "boolean"
},
- "isExternal": {
- "type": "boolean"
- },
"isFavorite": {
"type": "boolean"
},
@@ -7592,6 +7598,10 @@
"name": {
"type": "string"
},
+ "ownerId": {
+ "format": "uuid",
+ "type": "string"
+ },
"type": {
"$ref": "#/components/schemas/LibraryType"
}
@@ -7648,10 +7658,6 @@
"email": {
"type": "string"
},
- "externalPath": {
- "nullable": true,
- "type": "string"
- },
"memoriesEnabled": {
"type": "boolean"
},
@@ -8549,10 +8555,6 @@
"email": {
"type": "string"
},
- "externalPath": {
- "nullable": true,
- "type": "string"
- },
"id": {
"type": "string"
},
@@ -8601,7 +8603,6 @@
"createdAt",
"deletedAt",
"email",
- "externalPath",
"id",
"isAdmin",
"name",
@@ -9538,6 +9539,12 @@
"page": {
"type": "number"
},
+ "personIds": {
+ "items": {
+ "type": "string"
+ },
+ "type": "array"
+ },
"query": {
"type": "string"
},
@@ -9831,18 +9838,10 @@
"properties": {
"enabled": {
"type": "boolean"
- },
- "interval": {
- "type": "integer"
- },
- "usePolling": {
- "type": "boolean"
}
},
"required": [
- "enabled",
- "interval",
- "usePolling"
+ "enabled"
],
"type": "object"
},
@@ -9931,6 +9930,9 @@
"clientSecret": {
"type": "string"
},
+ "defaultStorageQuota": {
+ "type": "number"
+ },
"enabled": {
"type": "boolean"
},
@@ -9951,6 +9953,9 @@
},
"storageLabelClaim": {
"type": "string"
+ },
+ "storageQuotaClaim": {
+ "type": "string"
}
},
"required": [
@@ -9959,13 +9964,15 @@
"buttonText",
"clientId",
"clientSecret",
+ "defaultStorageQuota",
"enabled",
"issuerUrl",
"mobileOverrideEnabled",
"mobileRedirectUri",
"scope",
"signingAlgorithm",
- "storageLabelClaim"
+ "storageLabelClaim",
+ "storageQuotaClaim"
],
"type": "object"
},
@@ -10334,9 +10341,6 @@
"email": {
"type": "string"
},
- "externalPath": {
- "type": "string"
- },
"id": {
"format": "uuid",
"type": "string"
@@ -10463,10 +10467,6 @@
"email": {
"type": "string"
},
- "externalPath": {
- "nullable": true,
- "type": "string"
- },
"id": {
"type": "string"
},
@@ -10512,7 +10512,6 @@
"createdAt",
"deletedAt",
"email",
- "externalPath",
"id",
"isAdmin",
"name",
diff --git a/open-api/typescript-sdk/axios-client/.gitignore b/open-api/typescript-sdk/axios-client/.gitignore
deleted file mode 100644
index 149b57654..000000000
--- a/open-api/typescript-sdk/axios-client/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-wwwroot/*.js
-node_modules
-typings
-dist
diff --git a/open-api/typescript-sdk/axios-client/.npmignore b/open-api/typescript-sdk/axios-client/.npmignore
deleted file mode 100644
index 999d88df6..000000000
--- a/open-api/typescript-sdk/axios-client/.npmignore
+++ /dev/null
@@ -1 +0,0 @@
-# empty npmignore to ensure all required files (e.g., in the dist folder) are published by npm
\ No newline at end of file
diff --git a/open-api/typescript-sdk/axios-client/.openapi-generator-ignore b/open-api/typescript-sdk/axios-client/.openapi-generator-ignore
deleted file mode 100644
index 7484ee590..000000000
--- a/open-api/typescript-sdk/axios-client/.openapi-generator-ignore
+++ /dev/null
@@ -1,23 +0,0 @@
-# OpenAPI Generator Ignore
-# Generated by openapi-generator https://github.com/openapitools/openapi-generator
-
-# Use this file to prevent files from being overwritten by the generator.
-# The patterns follow closely to .gitignore or .dockerignore.
-
-# As an example, the C# client generator defines ApiClient.cs.
-# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
-#ApiClient.cs
-
-# You can match any string of characters against a directory, file or extension with a single asterisk (*):
-#foo/*/qux
-# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
-
-# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
-#foo/**/qux
-# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
-
-# You can also negate patterns with an exclamation (!).
-# For example, you can ignore all files in a docs folder with the file extension .md:
-#docs/*.md
-# Then explicitly reverse the ignore rule for a single file:
-#!docs/README.md
diff --git a/open-api/typescript-sdk/axios-client/.openapi-generator/FILES b/open-api/typescript-sdk/axios-client/.openapi-generator/FILES
deleted file mode 100644
index a80cd4f07..000000000
--- a/open-api/typescript-sdk/axios-client/.openapi-generator/FILES
+++ /dev/null
@@ -1,8 +0,0 @@
-.gitignore
-.npmignore
-api.ts
-base.ts
-common.ts
-configuration.ts
-git_push.sh
-index.ts
diff --git a/open-api/typescript-sdk/axios-client/.openapi-generator/VERSION b/open-api/typescript-sdk/axios-client/.openapi-generator/VERSION
deleted file mode 100644
index 4b49d9bb6..000000000
--- a/open-api/typescript-sdk/axios-client/.openapi-generator/VERSION
+++ /dev/null
@@ -1 +0,0 @@
-7.2.0
\ No newline at end of file
diff --git a/open-api/typescript-sdk/axios-client/api.ts b/open-api/typescript-sdk/axios-client/api.ts
deleted file mode 100644
index ad36bb493..000000000
--- a/open-api/typescript-sdk/axios-client/api.ts
+++ /dev/null
@@ -1,19795 +0,0 @@
-/* tslint:disable */
-/* eslint-disable */
-/**
- * Immich
- * Immich API
- *
- * The version of the OpenAPI document: 1.95.1
- *
- *
- * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
- * https://openapi-generator.tech
- * Do not edit the class manually.
- */
-
-
-import type { Configuration } from './configuration';
-import type { AxiosPromise, AxiosInstance, RawAxiosRequestConfig } from 'axios';
-import globalAxios from 'axios';
-// Some imports not used depending on template conditions
-// @ts-ignore
-import { DUMMY_BASE_URL, assertParamExists, setApiKeyToObject, setBasicAuthToObject, setBearerAuthToObject, setOAuthToObject, setSearchParams, serializeDataIfNeeded, toPathString, createRequestFunction } from './common';
-import type { RequestArgs } from './base';
-// @ts-ignore
-import { BASE_PATH, COLLECTION_FORMATS, BaseAPI, RequiredError, operationServerMap } from './base';
-
-/**
- *
- * @export
- * @interface APIKeyCreateDto
- */
-export interface APIKeyCreateDto {
- /**
- *
- * @type {string}
- * @memberof APIKeyCreateDto
- */
- 'name'?: string;
-}
-/**
- *
- * @export
- * @interface APIKeyCreateResponseDto
- */
-export interface APIKeyCreateResponseDto {
- /**
- *
- * @type {APIKeyResponseDto}
- * @memberof APIKeyCreateResponseDto
- */
- 'apiKey': APIKeyResponseDto;
- /**
- *
- * @type {string}
- * @memberof APIKeyCreateResponseDto
- */
- 'secret': string;
-}
-/**
- *
- * @export
- * @interface APIKeyResponseDto
- */
-export interface APIKeyResponseDto {
- /**
- *
- * @type {string}
- * @memberof APIKeyResponseDto
- */
- 'createdAt': string;
- /**
- *
- * @type {string}
- * @memberof APIKeyResponseDto
- */
- 'id': string;
- /**
- *
- * @type {string}
- * @memberof APIKeyResponseDto
- */
- 'name': string;
- /**
- *
- * @type {string}
- * @memberof APIKeyResponseDto
- */
- 'updatedAt': string;
-}
-/**
- *
- * @export
- * @interface APIKeyUpdateDto
- */
-export interface APIKeyUpdateDto {
- /**
- *
- * @type {string}
- * @memberof APIKeyUpdateDto
- */
- 'name': string;
-}
-/**
- *
- * @export
- * @interface ActivityCreateDto
- */
-export interface ActivityCreateDto {
- /**
- *
- * @type {string}
- * @memberof ActivityCreateDto
- */
- 'albumId': string;
- /**
- *
- * @type {string}
- * @memberof ActivityCreateDto
- */
- 'assetId'?: string;
- /**
- *
- * @type {string}
- * @memberof ActivityCreateDto
- */
- 'comment'?: string;
- /**
- *
- * @type {ReactionType}
- * @memberof ActivityCreateDto
- */
- 'type': ReactionType;
-}
-
-
-/**
- *
- * @export
- * @interface ActivityResponseDto
- */
-export interface ActivityResponseDto {
- /**
- *
- * @type {string}
- * @memberof ActivityResponseDto
- */
- 'assetId': string | null;
- /**
- *
- * @type {string}
- * @memberof ActivityResponseDto
- */
- 'comment'?: string | null;
- /**
- *
- * @type {string}
- * @memberof ActivityResponseDto
- */
- 'createdAt': string;
- /**
- *
- * @type {string}
- * @memberof ActivityResponseDto
- */
- 'id': string;
- /**
- *
- * @type {string}
- * @memberof ActivityResponseDto
- */
- 'type': ActivityResponseDtoTypeEnum;
- /**
- *
- * @type {UserDto}
- * @memberof ActivityResponseDto
- */
- 'user': UserDto;
-}
-
-export const ActivityResponseDtoTypeEnum = {
- Comment: 'comment',
- Like: 'like'
-} as const;
-
-export type ActivityResponseDtoTypeEnum = typeof ActivityResponseDtoTypeEnum[keyof typeof ActivityResponseDtoTypeEnum];
-
-/**
- *
- * @export
- * @interface ActivityStatisticsResponseDto
- */
-export interface ActivityStatisticsResponseDto {
- /**
- *
- * @type {number}
- * @memberof ActivityStatisticsResponseDto
- */
- 'comments': number;
-}
-/**
- *
- * @export
- * @interface AddUsersDto
- */
-export interface AddUsersDto {
- /**
- *
- * @type {Array}
- * @memberof AddUsersDto
- */
- 'sharedUserIds': Array;
-}
-/**
- *
- * @export
- * @interface AlbumCountResponseDto
- */
-export interface AlbumCountResponseDto {
- /**
- *
- * @type {number}
- * @memberof AlbumCountResponseDto
- */
- 'notShared': number;
- /**
- *
- * @type {number}
- * @memberof AlbumCountResponseDto
- */
- 'owned': number;
- /**
- *
- * @type {number}
- * @memberof AlbumCountResponseDto
- */
- 'shared': number;
-}
-/**
- *
- * @export
- * @interface AlbumResponseDto
- */
-export interface AlbumResponseDto {
- /**
- *
- * @type {string}
- * @memberof AlbumResponseDto
- */
- 'albumName': string;
- /**
- *
- * @type {string}
- * @memberof AlbumResponseDto
- */
- 'albumThumbnailAssetId': string | null;
- /**
- *
- * @type {number}
- * @memberof AlbumResponseDto
- */
- 'assetCount': number;
- /**
- *
- * @type {Array}
- * @memberof AlbumResponseDto
- */
- 'assets': Array;
- /**
- *
- * @type {string}
- * @memberof AlbumResponseDto
- */
- 'createdAt': string;
- /**
- *
- * @type {string}
- * @memberof AlbumResponseDto
- */
- 'description': string;
- /**
- *
- * @type {string}
- * @memberof AlbumResponseDto
- */
- 'endDate'?: string;
- /**
- *
- * @type {boolean}
- * @memberof AlbumResponseDto
- */
- 'hasSharedLink': boolean;
- /**
- *
- * @type {string}
- * @memberof AlbumResponseDto
- */
- 'id': string;
- /**
- *
- * @type {boolean}
- * @memberof AlbumResponseDto
- */
- 'isActivityEnabled': boolean;
- /**
- *
- * @type {string}
- * @memberof AlbumResponseDto
- */
- 'lastModifiedAssetTimestamp'?: string;
- /**
- *
- * @type {UserResponseDto}
- * @memberof AlbumResponseDto
- */
- 'owner': UserResponseDto;
- /**
- *
- * @type {string}
- * @memberof AlbumResponseDto
- */
- 'ownerId': string;
- /**
- *
- * @type {boolean}
- * @memberof AlbumResponseDto
- */
- 'shared': boolean;
- /**
- *
- * @type {Array}
- * @memberof AlbumResponseDto
- */
- 'sharedUsers': Array;
- /**
- *
- * @type {string}
- * @memberof AlbumResponseDto
- */
- 'startDate'?: string;
- /**
- *
- * @type {string}
- * @memberof AlbumResponseDto
- */
- 'updatedAt': string;
-}
-/**
- *
- * @export
- * @interface AllJobStatusResponseDto
- */
-export interface AllJobStatusResponseDto {
- /**
- *
- * @type {JobStatusDto}
- * @memberof AllJobStatusResponseDto
- */
- 'backgroundTask': JobStatusDto;
- /**
- *
- * @type {JobStatusDto}
- * @memberof AllJobStatusResponseDto
- */
- 'faceDetection': JobStatusDto;
- /**
- *
- * @type {JobStatusDto}
- * @memberof AllJobStatusResponseDto
- */
- 'facialRecognition': JobStatusDto;
- /**
- *
- * @type {JobStatusDto}
- * @memberof AllJobStatusResponseDto
- */
- 'library': JobStatusDto;
- /**
- *
- * @type {JobStatusDto}
- * @memberof AllJobStatusResponseDto
- */
- 'metadataExtraction': JobStatusDto;
- /**
- *
- * @type {JobStatusDto}
- * @memberof AllJobStatusResponseDto
- */
- 'migration': JobStatusDto;
- /**
- *
- * @type {JobStatusDto}
- * @memberof AllJobStatusResponseDto
- */
- 'search': JobStatusDto;
- /**
- *
- * @type {JobStatusDto}
- * @memberof AllJobStatusResponseDto
- */
- 'sidecar': JobStatusDto;
- /**
- *
- * @type {JobStatusDto}
- * @memberof AllJobStatusResponseDto
- */
- 'smartSearch': JobStatusDto;
- /**
- *
- * @type {JobStatusDto}
- * @memberof AllJobStatusResponseDto
- */
- 'storageTemplateMigration': JobStatusDto;
- /**
- *
- * @type {JobStatusDto}
- * @memberof AllJobStatusResponseDto
- */
- 'thumbnailGeneration': JobStatusDto;
- /**
- *
- * @type {JobStatusDto}
- * @memberof AllJobStatusResponseDto
- */
- 'videoConversion': JobStatusDto;
-}
-/**
- *
- * @export
- * @interface AssetBulkDeleteDto
- */
-export interface AssetBulkDeleteDto {
- /**
- *
- * @type {boolean}
- * @memberof AssetBulkDeleteDto
- */
- 'force'?: boolean;
- /**
- *
- * @type {Array}
- * @memberof AssetBulkDeleteDto
- */
- 'ids': Array;
-}
-/**
- *
- * @export
- * @interface AssetBulkUpdateDto
- */
-export interface AssetBulkUpdateDto {
- /**
- *
- * @type {string}
- * @memberof AssetBulkUpdateDto
- */
- 'dateTimeOriginal'?: string;
- /**
- *
- * @type {Array}
- * @memberof AssetBulkUpdateDto
- */
- 'ids': Array;
- /**
- *
- * @type {boolean}
- * @memberof AssetBulkUpdateDto
- */
- 'isArchived'?: boolean;
- /**
- *
- * @type {boolean}
- * @memberof AssetBulkUpdateDto
- */
- 'isFavorite'?: boolean;
- /**
- *
- * @type {number}
- * @memberof AssetBulkUpdateDto
- */
- 'latitude'?: number;
- /**
- *
- * @type {number}
- * @memberof AssetBulkUpdateDto
- */
- 'longitude'?: number;
- /**
- *
- * @type {boolean}
- * @memberof AssetBulkUpdateDto
- */
- 'removeParent'?: boolean;
- /**
- *
- * @type {string}
- * @memberof AssetBulkUpdateDto
- */
- 'stackParentId'?: string;
-}
-/**
- *
- * @export
- * @interface AssetBulkUploadCheckDto
- */
-export interface AssetBulkUploadCheckDto {
- /**
- *
- * @type {Array}
- * @memberof AssetBulkUploadCheckDto
- */
- 'assets': Array;
-}
-/**
- *
- * @export
- * @interface AssetBulkUploadCheckItem
- */
-export interface AssetBulkUploadCheckItem {
- /**
- * base64 or hex encoded sha1 hash
- * @type {string}
- * @memberof AssetBulkUploadCheckItem
- */
- 'checksum': string;
- /**
- *
- * @type {string}
- * @memberof AssetBulkUploadCheckItem
- */
- 'id': string;
-}
-/**
- *
- * @export
- * @interface AssetBulkUploadCheckResponseDto
- */
-export interface AssetBulkUploadCheckResponseDto {
- /**
- *
- * @type {Array}
- * @memberof AssetBulkUploadCheckResponseDto
- */
- 'results': Array;
-}
-/**
- *
- * @export
- * @interface AssetBulkUploadCheckResult
- */
-export interface AssetBulkUploadCheckResult {
- /**
- *
- * @type {string}
- * @memberof AssetBulkUploadCheckResult
- */
- 'action': AssetBulkUploadCheckResultActionEnum;
- /**
- *
- * @type {string}
- * @memberof AssetBulkUploadCheckResult
- */
- 'assetId'?: string;
- /**
- *
- * @type {string}
- * @memberof AssetBulkUploadCheckResult
- */
- 'id': string;
- /**
- *
- * @type {string}
- * @memberof AssetBulkUploadCheckResult
- */
- 'reason'?: AssetBulkUploadCheckResultReasonEnum;
-}
-
-export const AssetBulkUploadCheckResultActionEnum = {
- Accept: 'accept',
- Reject: 'reject'
-} as const;
-
-export type AssetBulkUploadCheckResultActionEnum = typeof AssetBulkUploadCheckResultActionEnum[keyof typeof AssetBulkUploadCheckResultActionEnum];
-export const AssetBulkUploadCheckResultReasonEnum = {
- Duplicate: 'duplicate',
- UnsupportedFormat: 'unsupported-format'
-} as const;
-
-export type AssetBulkUploadCheckResultReasonEnum = typeof AssetBulkUploadCheckResultReasonEnum[keyof typeof AssetBulkUploadCheckResultReasonEnum];
-
-/**
- *
- * @export
- * @interface AssetFaceResponseDto
- */
-export interface AssetFaceResponseDto {
- /**
- *
- * @type {number}
- * @memberof AssetFaceResponseDto
- */
- 'boundingBoxX1': number;
- /**
- *
- * @type {number}
- * @memberof AssetFaceResponseDto
- */
- 'boundingBoxX2': number;
- /**
- *
- * @type {number}
- * @memberof AssetFaceResponseDto
- */
- 'boundingBoxY1': number;
- /**
- *
- * @type {number}
- * @memberof AssetFaceResponseDto
- */
- 'boundingBoxY2': number;
- /**
- *
- * @type {string}
- * @memberof AssetFaceResponseDto
- */
- 'id': string;
- /**
- *
- * @type {number}
- * @memberof AssetFaceResponseDto
- */
- 'imageHeight': number;
- /**
- *
- * @type {number}
- * @memberof AssetFaceResponseDto
- */
- 'imageWidth': number;
- /**
- *
- * @type {PersonResponseDto}
- * @memberof AssetFaceResponseDto
- */
- 'person': PersonResponseDto | null;
-}
-/**
- *
- * @export
- * @interface AssetFaceUpdateDto
- */
-export interface AssetFaceUpdateDto {
- /**
- *
- * @type {Array}
- * @memberof AssetFaceUpdateDto
- */
- 'data': Array;
-}
-/**
- *
- * @export
- * @interface AssetFaceUpdateItem
- */
-export interface AssetFaceUpdateItem {
- /**
- *
- * @type {string}
- * @memberof AssetFaceUpdateItem
- */
- 'assetId': string;
- /**
- *
- * @type {string}
- * @memberof AssetFaceUpdateItem
- */
- 'personId': string;
-}
-/**
- *
- * @export
- * @interface AssetFaceWithoutPersonResponseDto
- */
-export interface AssetFaceWithoutPersonResponseDto {
- /**
- *
- * @type {number}
- * @memberof AssetFaceWithoutPersonResponseDto
- */
- 'boundingBoxX1': number;
- /**
- *
- * @type {number}
- * @memberof AssetFaceWithoutPersonResponseDto
- */
- 'boundingBoxX2': number;
- /**
- *
- * @type {number}
- * @memberof AssetFaceWithoutPersonResponseDto
- */
- 'boundingBoxY1': number;
- /**
- *
- * @type {number}
- * @memberof AssetFaceWithoutPersonResponseDto
- */
- 'boundingBoxY2': number;
- /**
- *
- * @type {string}
- * @memberof AssetFaceWithoutPersonResponseDto
- */
- 'id': string;
- /**
- *
- * @type {number}
- * @memberof AssetFaceWithoutPersonResponseDto
- */
- 'imageHeight': number;
- /**
- *
- * @type {number}
- * @memberof AssetFaceWithoutPersonResponseDto
- */
- 'imageWidth': number;
-}
-/**
- *
- * @export
- * @interface AssetFileUploadResponseDto
- */
-export interface AssetFileUploadResponseDto {
- /**
- *
- * @type {boolean}
- * @memberof AssetFileUploadResponseDto
- */
- 'duplicate': boolean;
- /**
- *
- * @type {string}
- * @memberof AssetFileUploadResponseDto
- */
- 'id': string;
-}
-/**
- *
- * @export
- * @interface AssetIdsDto
- */
-export interface AssetIdsDto {
- /**
- *
- * @type {Array}
- * @memberof AssetIdsDto
- */
- 'assetIds': Array;
-}
-/**
- *
- * @export
- * @interface AssetIdsResponseDto
- */
-export interface AssetIdsResponseDto {
- /**
- *
- * @type {string}
- * @memberof AssetIdsResponseDto
- */
- 'assetId': string;
- /**
- *
- * @type {string}
- * @memberof AssetIdsResponseDto
- */
- 'error'?: AssetIdsResponseDtoErrorEnum;
- /**
- *
- * @type {boolean}
- * @memberof AssetIdsResponseDto
- */
- 'success': boolean;
-}
-
-export const AssetIdsResponseDtoErrorEnum = {
- Duplicate: 'duplicate',
- NoPermission: 'no_permission',
- NotFound: 'not_found'
-} as const;
-
-export type AssetIdsResponseDtoErrorEnum = typeof AssetIdsResponseDtoErrorEnum[keyof typeof AssetIdsResponseDtoErrorEnum];
-
-/**
- *
- * @export
- * @enum {string}
- */
-
-export const AssetJobName = {
- RegenerateThumbnail: 'regenerate-thumbnail',
- RefreshMetadata: 'refresh-metadata',
- TranscodeVideo: 'transcode-video'
-} as const;
-
-export type AssetJobName = typeof AssetJobName[keyof typeof AssetJobName];
-
-
-/**
- *
- * @export
- * @interface AssetJobsDto
- */
-export interface AssetJobsDto {
- /**
- *
- * @type {Array}
- * @memberof AssetJobsDto
- */
- 'assetIds': Array;
- /**
- *
- * @type {AssetJobName}
- * @memberof AssetJobsDto
- */
- 'name': AssetJobName;
-}
-
-
-/**
- *
- * @export
- * @enum {string}
- */
-
-export const AssetOrder = {
- Asc: 'asc',
- Desc: 'desc'
-} as const;
-
-export type AssetOrder = typeof AssetOrder[keyof typeof AssetOrder];
-
-
-/**
- *
- * @export
- * @interface AssetResponseDto
- */
-export interface AssetResponseDto {
- /**
- * base64 encoded sha1 hash
- * @type {string}
- * @memberof AssetResponseDto
- */
- 'checksum': string;
- /**
- *
- * @type {string}
- * @memberof AssetResponseDto
- */
- 'deviceAssetId': string;
- /**
- *
- * @type {string}
- * @memberof AssetResponseDto
- */
- 'deviceId': string;
- /**
- *
- * @type {string}
- * @memberof AssetResponseDto
- */
- 'duration': string;
- /**
- *
- * @type {ExifResponseDto}
- * @memberof AssetResponseDto
- */
- 'exifInfo'?: ExifResponseDto;
- /**
- *
- * @type {string}
- * @memberof AssetResponseDto
- */
- 'fileCreatedAt': string;
- /**
- *
- * @type {string}
- * @memberof AssetResponseDto
- */
- 'fileModifiedAt': string;
- /**
- *
- * @type {boolean}
- * @memberof AssetResponseDto
- */
- 'hasMetadata': boolean;
- /**
- *
- * @type {string}
- * @memberof AssetResponseDto
- */
- 'id': string;
- /**
- *
- * @type {boolean}
- * @memberof AssetResponseDto
- */
- 'isArchived': boolean;
- /**
- *
- * @type {boolean}
- * @memberof AssetResponseDto
- */
- 'isExternal': boolean;
- /**
- *
- * @type {boolean}
- * @memberof AssetResponseDto
- */
- 'isFavorite': boolean;
- /**
- *
- * @type {boolean}
- * @memberof AssetResponseDto
- */
- 'isOffline': boolean;
- /**
- *
- * @type {boolean}
- * @memberof AssetResponseDto
- */
- 'isReadOnly': boolean;
- /**
- *
- * @type {boolean}
- * @memberof AssetResponseDto
- */
- 'isTrashed': boolean;
- /**
- *
- * @type {string}
- * @memberof AssetResponseDto
- */
- 'libraryId': string;
- /**
- *
- * @type {string}
- * @memberof AssetResponseDto
- */
- 'livePhotoVideoId'?: string | null;
- /**
- *
- * @type {string}
- * @memberof AssetResponseDto
- */
- 'localDateTime': string;
- /**
- *
- * @type {string}
- * @memberof AssetResponseDto
- */
- 'originalFileName': string;
- /**
- *
- * @type {string}
- * @memberof AssetResponseDto
- */
- 'originalPath': string;
- /**
- *
- * @type {UserResponseDto}
- * @memberof AssetResponseDto
- */
- 'owner'?: UserResponseDto;
- /**
- *
- * @type {string}
- * @memberof AssetResponseDto
- */
- 'ownerId': string;
- /**
- *
- * @type {Array}
- * @memberof AssetResponseDto
- */
- 'people'?: Array;
- /**
- *
- * @type {boolean}
- * @memberof AssetResponseDto
- */
- 'resized': boolean;
- /**
- *
- * @type {SmartInfoResponseDto}
- * @memberof AssetResponseDto
- */
- 'smartInfo'?: SmartInfoResponseDto;
- /**
- *
- * @type {Array}
- * @memberof AssetResponseDto
- */
- 'stack'?: Array;
- /**
- *
- * @type {number}
- * @memberof AssetResponseDto
- */
- 'stackCount': number | null;
- /**
- *
- * @type {string}
- * @memberof AssetResponseDto
- */
- 'stackParentId'?: string | null;
- /**
- *
- * @type {Array}
- * @memberof AssetResponseDto
- */
- 'tags'?: Array;
- /**
- *
- * @type {string}
- * @memberof AssetResponseDto
- */
- 'thumbhash': string | null;
- /**
- *
- * @type {AssetTypeEnum}
- * @memberof AssetResponseDto
- */
- 'type': AssetTypeEnum;
- /**
- *
- * @type {string}
- * @memberof AssetResponseDto
- */
- 'updatedAt': string;
-}
-
-
-/**
- *
- * @export
- * @interface AssetStatsResponseDto
- */
-export interface AssetStatsResponseDto {
- /**
- *
- * @type {number}
- * @memberof AssetStatsResponseDto
- */
- 'images': number;
- /**
- *
- * @type {number}
- * @memberof AssetStatsResponseDto
- */
- 'total': number;
- /**
- *
- * @type {number}
- * @memberof AssetStatsResponseDto
- */
- 'videos': number;
-}
-/**
- *
- * @export
- * @enum {string}
- */
-
-export const AssetTypeEnum = {
- Image: 'IMAGE',
- Video: 'VIDEO',
- Audio: 'AUDIO',
- Other: 'OTHER'
-} as const;
-
-export type AssetTypeEnum = typeof AssetTypeEnum[keyof typeof AssetTypeEnum];
-
-
-/**
- *
- * @export
- * @enum {string}
- */
-
-export const AudioCodec = {
- Mp3: 'mp3',
- Aac: 'aac',
- Libopus: 'libopus'
-} as const;
-
-export type AudioCodec = typeof AudioCodec[keyof typeof AudioCodec];
-
-
-/**
- *
- * @export
- * @interface AuditDeletesResponseDto
- */
-export interface AuditDeletesResponseDto {
- /**
- *
- * @type {Array}
- * @memberof AuditDeletesResponseDto
- */
- 'ids': Array;
- /**
- *
- * @type {boolean}
- * @memberof AuditDeletesResponseDto
- */
- 'needsFullSync': boolean;
-}
-/**
- *
- * @export
- * @interface AuthDeviceResponseDto
- */
-export interface AuthDeviceResponseDto {
- /**
- *
- * @type {string}
- * @memberof AuthDeviceResponseDto
- */
- 'createdAt': string;
- /**
- *
- * @type {boolean}
- * @memberof AuthDeviceResponseDto
- */
- 'current': boolean;
- /**
- *
- * @type {string}
- * @memberof AuthDeviceResponseDto
- */
- 'deviceOS': string;
- /**
- *
- * @type {string}
- * @memberof AuthDeviceResponseDto
- */
- 'deviceType': string;
- /**
- *
- * @type {string}
- * @memberof AuthDeviceResponseDto
- */
- 'id': string;
- /**
- *
- * @type {string}
- * @memberof AuthDeviceResponseDto
- */
- 'updatedAt': string;
-}
-/**
- *
- * @export
- * @interface BulkIdResponseDto
- */
-export interface BulkIdResponseDto {
- /**
- *
- * @type {string}
- * @memberof BulkIdResponseDto
- */
- 'error'?: BulkIdResponseDtoErrorEnum;
- /**
- *
- * @type {string}
- * @memberof BulkIdResponseDto
- */
- 'id': string;
- /**
- *
- * @type {boolean}
- * @memberof BulkIdResponseDto
- */
- 'success': boolean;
-}
-
-export const BulkIdResponseDtoErrorEnum = {
- Duplicate: 'duplicate',
- NoPermission: 'no_permission',
- NotFound: 'not_found',
- Unknown: 'unknown'
-} as const;
-
-export type BulkIdResponseDtoErrorEnum = typeof BulkIdResponseDtoErrorEnum[keyof typeof BulkIdResponseDtoErrorEnum];
-
-/**
- *
- * @export
- * @interface BulkIdsDto
- */
-export interface BulkIdsDto {
- /**
- *
- * @type {Array}
- * @memberof BulkIdsDto
- */
- 'ids': Array;
-}
-/**
- *
- * @export
- * @interface CLIPConfig
- */
-export interface CLIPConfig {
- /**
- *
- * @type {boolean}
- * @memberof CLIPConfig
- */
- 'enabled': boolean;
- /**
- *
- * @type {CLIPMode}
- * @memberof CLIPConfig
- */
- 'mode'?: CLIPMode;
- /**
- *
- * @type {string}
- * @memberof CLIPConfig
- */
- 'modelName': string;
- /**
- *
- * @type {ModelType}
- * @memberof CLIPConfig
- */
- 'modelType'?: ModelType;
-}
-
-
-/**
- *
- * @export
- * @enum {string}
- */
-
-export const CLIPMode = {
- Vision: 'vision',
- Text: 'text'
-} as const;
-
-export type CLIPMode = typeof CLIPMode[keyof typeof CLIPMode];
-
-
-/**
- *
- * @export
- * @enum {string}
- */
-
-export const CQMode = {
- Auto: 'auto',
- Cqp: 'cqp',
- Icq: 'icq'
-} as const;
-
-export type CQMode = typeof CQMode[keyof typeof CQMode];
-
-
-/**
- *
- * @export
- * @interface ChangePasswordDto
- */
-export interface ChangePasswordDto {
- /**
- *
- * @type {string}
- * @memberof ChangePasswordDto
- */
- 'newPassword': string;
- /**
- *
- * @type {string}
- * @memberof ChangePasswordDto
- */
- 'password': string;
-}
-/**
- *
- * @export
- * @interface CheckExistingAssetsDto
- */
-export interface CheckExistingAssetsDto {
- /**
- *
- * @type {Array}
- * @memberof CheckExistingAssetsDto
- */
- 'deviceAssetIds': Array;
- /**
- *
- * @type {string}
- * @memberof CheckExistingAssetsDto
- */
- 'deviceId': string;
-}
-/**
- *
- * @export
- * @interface CheckExistingAssetsResponseDto
- */
-export interface CheckExistingAssetsResponseDto {
- /**
- *
- * @type {Array}
- * @memberof CheckExistingAssetsResponseDto
- */
- 'existingIds': Array;
-}
-/**
- *
- * @export
- * @enum {string}
- */
-
-export const Colorspace = {
- Srgb: 'srgb',
- P3: 'p3'
-} as const;
-
-export type Colorspace = typeof Colorspace[keyof typeof Colorspace];
-
-
-/**
- *
- * @export
- * @interface CreateAlbumDto
- */
-export interface CreateAlbumDto {
- /**
- *
- * @type {string}
- * @memberof CreateAlbumDto
- */
- 'albumName': string;
- /**
- *
- * @type {Array}
- * @memberof CreateAlbumDto
- */
- 'assetIds'?: Array;
- /**
- *
- * @type {string}
- * @memberof CreateAlbumDto
- */
- 'description'?: string;
- /**
- *
- * @type {Array}
- * @memberof CreateAlbumDto
- */
- 'sharedWithUserIds'?: Array;
-}
-/**
- *
- * @export
- * @interface CreateLibraryDto
- */
-export interface CreateLibraryDto {
- /**
- *
- * @type {Array}
- * @memberof CreateLibraryDto
- */
- 'exclusionPatterns'?: Array;
- /**
- *
- * @type {Array}
- * @memberof CreateLibraryDto
- */
- 'importPaths'?: Array;
- /**
- *
- * @type {boolean}
- * @memberof CreateLibraryDto
- */
- 'isVisible'?: boolean;
- /**
- *
- * @type {boolean}
- * @memberof CreateLibraryDto
- */
- 'isWatched'?: boolean;
- /**
- *
- * @type {string}
- * @memberof CreateLibraryDto
- */
- 'name'?: string;
- /**
- *
- * @type {LibraryType}
- * @memberof CreateLibraryDto
- */
- 'type': LibraryType;
-}
-
-
-/**
- *
- * @export
- * @interface CreateProfileImageResponseDto
- */
-export interface CreateProfileImageResponseDto {
- /**
- *
- * @type {string}
- * @memberof CreateProfileImageResponseDto
- */
- 'profileImagePath': string;
- /**
- *
- * @type {string}
- * @memberof CreateProfileImageResponseDto
- */
- 'userId': string;
-}
-/**
- *
- * @export
- * @interface CreateTagDto
- */
-export interface CreateTagDto {
- /**
- *
- * @type {string}
- * @memberof CreateTagDto
- */
- 'name': string;
- /**
- *
- * @type {TagTypeEnum}
- * @memberof CreateTagDto
- */
- 'type': TagTypeEnum;
-}
-
-
-/**
- *
- * @export
- * @interface CreateUserDto
- */
-export interface CreateUserDto {
- /**
- *
- * @type {string}
- * @memberof CreateUserDto
- */
- 'email': string;
- /**
- *
- * @type {string}
- * @memberof CreateUserDto
- */
- 'externalPath'?: string | null;
- /**
- *
- * @type {boolean}
- * @memberof CreateUserDto
- */
- 'memoriesEnabled'?: boolean;
- /**
- *
- * @type {string}
- * @memberof CreateUserDto
- */
- 'name': string;
- /**
- *
- * @type {string}
- * @memberof CreateUserDto
- */
- 'password': string;
- /**
- *
- * @type {number}
- * @memberof CreateUserDto
- */
- 'quotaSizeInBytes'?: number | null;
- /**
- *
- * @type {string}
- * @memberof CreateUserDto
- */
- 'storageLabel'?: string | null;
-}
-/**
- *
- * @export
- * @interface CuratedLocationsResponseDto
- */
-export interface CuratedLocationsResponseDto {
- /**
- *
- * @type {string}
- * @memberof CuratedLocationsResponseDto
- */
- 'city': string;
- /**
- *
- * @type {string}
- * @memberof CuratedLocationsResponseDto
- */
- 'deviceAssetId': string;
- /**
- *
- * @type {string}
- * @memberof CuratedLocationsResponseDto
- */
- 'deviceId': string;
- /**
- *
- * @type {string}
- * @memberof CuratedLocationsResponseDto
- */
- 'id': string;
- /**
- *
- * @type {string}
- * @memberof CuratedLocationsResponseDto
- */
- 'resizePath': string;
-}
-/**
- *
- * @export
- * @interface CuratedObjectsResponseDto
- */
-export interface CuratedObjectsResponseDto {
- /**
- *
- * @type {string}
- * @memberof CuratedObjectsResponseDto
- */
- 'deviceAssetId': string;
- /**
- *
- * @type {string}
- * @memberof CuratedObjectsResponseDto
- */
- 'deviceId': string;
- /**
- *
- * @type {string}
- * @memberof CuratedObjectsResponseDto
- */
- 'id': string;
- /**
- *
- * @type {string}
- * @memberof CuratedObjectsResponseDto
- */
- 'object': string;
- /**
- *
- * @type {string}
- * @memberof CuratedObjectsResponseDto
- */
- 'resizePath': string;
-}
-/**
- *
- * @export
- * @interface DownloadArchiveInfo
- */
-export interface DownloadArchiveInfo {
- /**
- *
- * @type {Array}
- * @memberof DownloadArchiveInfo
- */
- 'assetIds': Array;
- /**
- *
- * @type {number}
- * @memberof DownloadArchiveInfo
- */
- 'size': number;
-}
-/**
- *
- * @export
- * @interface DownloadInfoDto
- */
-export interface DownloadInfoDto {
- /**
- *
- * @type {string}
- * @memberof DownloadInfoDto
- */
- 'albumId'?: string;
- /**
- *
- * @type {number}
- * @memberof DownloadInfoDto
- */
- 'archiveSize'?: number;
- /**
- *
- * @type {Array}
- * @memberof DownloadInfoDto
- */
- 'assetIds'?: Array;
- /**
- *
- * @type {string}
- * @memberof DownloadInfoDto
- */
- 'userId'?: string;
-}
-/**
- *
- * @export
- * @interface DownloadResponseDto
- */
-export interface DownloadResponseDto {
- /**
- *
- * @type {Array}
- * @memberof DownloadResponseDto
- */
- 'archives': Array;
- /**
- *
- * @type {number}
- * @memberof DownloadResponseDto
- */
- 'totalSize': number;
-}
-/**
- *
- * @export
- * @enum {string}
- */
-
-export const EntityType = {
- Asset: 'ASSET',
- Album: 'ALBUM'
-} as const;
-
-export type EntityType = typeof EntityType[keyof typeof EntityType];
-
-
-/**
- *
- * @export
- * @interface ExifResponseDto
- */
-export interface ExifResponseDto {
- /**
- *
- * @type {string}
- * @memberof ExifResponseDto
- */
- 'city'?: string | null;
- /**
- *
- * @type {string}
- * @memberof ExifResponseDto
- */
- 'country'?: string | null;
- /**
- *
- * @type {string}
- * @memberof ExifResponseDto
- */
- 'dateTimeOriginal'?: string | null;
- /**
- *
- * @type {string}
- * @memberof ExifResponseDto
- */
- 'description'?: string | null;
- /**
- *
- * @type {number}
- * @memberof ExifResponseDto
- */
- 'exifImageHeight'?: number | null;
- /**
- *
- * @type {number}
- * @memberof ExifResponseDto
- */
- 'exifImageWidth'?: number | null;
- /**
- *
- * @type {string}
- * @memberof ExifResponseDto
- */
- 'exposureTime'?: string | null;
- /**
- *
- * @type {number}
- * @memberof ExifResponseDto
- */
- 'fNumber'?: number | null;
- /**
- *
- * @type {number}
- * @memberof ExifResponseDto
- */
- 'fileSizeInByte'?: number | null;
- /**
- *
- * @type {number}
- * @memberof ExifResponseDto
- */
- 'focalLength'?: number | null;
- /**
- *
- * @type {number}
- * @memberof ExifResponseDto
- */
- 'iso'?: number | null;
- /**
- *
- * @type {number}
- * @memberof ExifResponseDto
- */
- 'latitude'?: number | null;
- /**
- *
- * @type {string}
- * @memberof ExifResponseDto
- */
- 'lensModel'?: string | null;
- /**
- *
- * @type {number}
- * @memberof ExifResponseDto
- */
- 'longitude'?: number | null;
- /**
- *
- * @type {string}
- * @memberof ExifResponseDto
- */
- 'make'?: string | null;
- /**
- *
- * @type {string}
- * @memberof ExifResponseDto
- */
- 'model'?: string | null;
- /**
- *
- * @type {string}
- * @memberof ExifResponseDto
- */
- 'modifyDate'?: string | null;
- /**
- *
- * @type {string}
- * @memberof ExifResponseDto
- */
- 'orientation'?: string | null;
- /**
- *
- * @type {string}
- * @memberof ExifResponseDto
- */
- 'projectionType'?: string | null;
- /**
- *
- * @type {string}
- * @memberof ExifResponseDto
- */
- 'state'?: string | null;
- /**
- *
- * @type {string}
- * @memberof ExifResponseDto
- */
- 'timeZone'?: string | null;
-}
-/**
- *
- * @export
- * @interface FaceDto
- */
-export interface FaceDto {
- /**
- *
- * @type {string}
- * @memberof FaceDto
- */
- 'id': string;
-}
-/**
- *
- * @export
- * @interface FileChecksumDto
- */
-export interface FileChecksumDto {
- /**
- *
- * @type {Array}
- * @memberof FileChecksumDto
- */
- 'filenames': Array;
-}
-/**
- *
- * @export
- * @interface FileChecksumResponseDto
- */
-export interface FileChecksumResponseDto {
- /**
- *
- * @type {string}
- * @memberof FileChecksumResponseDto
- */
- 'checksum': string;
- /**
- *
- * @type {string}
- * @memberof FileChecksumResponseDto
- */
- 'filename': string;
-}
-/**
- *
- * @export
- * @interface FileReportDto
- */
-export interface FileReportDto {
- /**
- *
- * @type {Array}
- * @memberof FileReportDto
- */
- 'extras': Array;
- /**
- *
- * @type {Array}
- * @memberof FileReportDto
- */
- 'orphans': Array;
-}
-/**
- *
- * @export
- * @interface FileReportFixDto
- */
-export interface FileReportFixDto {
- /**
- *
- * @type {Array}
- * @memberof FileReportFixDto
- */
- 'items': Array;
-}
-/**
- *
- * @export
- * @interface FileReportItemDto
- */
-export interface FileReportItemDto {
- /**
- *
- * @type {string}
- * @memberof FileReportItemDto
- */
- 'checksum'?: string;
- /**
- *
- * @type {string}
- * @memberof FileReportItemDto
- */
- 'entityId': string;
- /**
- *
- * @type {PathEntityType}
- * @memberof FileReportItemDto
- */
- 'entityType': PathEntityType;
- /**
- *
- * @type {PathType}
- * @memberof FileReportItemDto
- */
- 'pathType': PathType;
- /**
- *
- * @type {string}
- * @memberof FileReportItemDto
- */
- 'pathValue': string;
-}
-
-
-/**
- *
- * @export
- * @enum {string}
- */
-
-export const JobCommand = {
- Start: 'start',
- Pause: 'pause',
- Resume: 'resume',
- Empty: 'empty',
- ClearFailed: 'clear-failed'
-} as const;
-
-export type JobCommand = typeof JobCommand[keyof typeof JobCommand];
-
-
-/**
- *
- * @export
- * @interface JobCommandDto
- */
-export interface JobCommandDto {
- /**
- *
- * @type {JobCommand}
- * @memberof JobCommandDto
- */
- 'command': JobCommand;
- /**
- *
- * @type {boolean}
- * @memberof JobCommandDto
- */
- 'force': boolean;
-}
-
-
-/**
- *
- * @export
- * @interface JobCountsDto
- */
-export interface JobCountsDto {
- /**
- *
- * @type {number}
- * @memberof JobCountsDto
- */
- 'active': number;
- /**
- *
- * @type {number}
- * @memberof JobCountsDto
- */
- 'completed': number;
- /**
- *
- * @type {number}
- * @memberof JobCountsDto
- */
- 'delayed': number;
- /**
- *
- * @type {number}
- * @memberof JobCountsDto
- */
- 'failed': number;
- /**
- *
- * @type {number}
- * @memberof JobCountsDto
- */
- 'paused': number;
- /**
- *
- * @type {number}
- * @memberof JobCountsDto
- */
- 'waiting': number;
-}
-/**
- *
- * @export
- * @enum {string}
- */
-
-export const JobName = {
- ThumbnailGeneration: 'thumbnailGeneration',
- MetadataExtraction: 'metadataExtraction',
- VideoConversion: 'videoConversion',
- FaceDetection: 'faceDetection',
- FacialRecognition: 'facialRecognition',
- SmartSearch: 'smartSearch',
- BackgroundTask: 'backgroundTask',
- StorageTemplateMigration: 'storageTemplateMigration',
- Migration: 'migration',
- Search: 'search',
- Sidecar: 'sidecar',
- Library: 'library'
-} as const;
-
-export type JobName = typeof JobName[keyof typeof JobName];
-
-
-/**
- *
- * @export
- * @interface JobSettingsDto
- */
-export interface JobSettingsDto {
- /**
- *
- * @type {number}
- * @memberof JobSettingsDto
- */
- 'concurrency': number;
-}
-/**
- *
- * @export
- * @interface JobStatusDto
- */
-export interface JobStatusDto {
- /**
- *
- * @type {JobCountsDto}
- * @memberof JobStatusDto
- */
- 'jobCounts': JobCountsDto;
- /**
- *
- * @type {QueueStatusDto}
- * @memberof JobStatusDto
- */
- 'queueStatus': QueueStatusDto;
-}
-/**
- *
- * @export
- * @interface LibraryResponseDto
- */
-export interface LibraryResponseDto {
- /**
- *
- * @type {number}
- * @memberof LibraryResponseDto
- */
- 'assetCount': number;
- /**
- *
- * @type {string}
- * @memberof LibraryResponseDto
- */
- 'createdAt': string;
- /**
- *
- * @type {Array}
- * @memberof LibraryResponseDto
- */
- 'exclusionPatterns': Array;
- /**
- *
- * @type {string}
- * @memberof LibraryResponseDto
- */
- 'id': string;
- /**
- *
- * @type {Array}
- * @memberof LibraryResponseDto
- */
- 'importPaths': Array;
- /**
- *
- * @type {string}
- * @memberof LibraryResponseDto
- */
- 'name': string;
- /**
- *
- * @type {string}
- * @memberof LibraryResponseDto
- */
- 'ownerId': string;
- /**
- *
- * @type {string}
- * @memberof LibraryResponseDto
- */
- 'refreshedAt': string | null;
- /**
- *
- * @type {LibraryType}
- * @memberof LibraryResponseDto
- */
- 'type': LibraryType;
- /**
- *
- * @type {string}
- * @memberof LibraryResponseDto
- */
- 'updatedAt': string;
-}
-
-
-/**
- *
- * @export
- * @interface LibraryStatsResponseDto
- */
-export interface LibraryStatsResponseDto {
- /**
- *
- * @type {number}
- * @memberof LibraryStatsResponseDto
- */
- 'photos': number;
- /**
- *
- * @type {number}
- * @memberof LibraryStatsResponseDto
- */
- 'total': number;
- /**
- *
- * @type {number}
- * @memberof LibraryStatsResponseDto
- */
- 'usage': number;
- /**
- *
- * @type {number}
- * @memberof LibraryStatsResponseDto
- */
- 'videos': number;
-}
-/**
- *
- * @export
- * @enum {string}
- */
-
-export const LibraryType = {
- Upload: 'UPLOAD',
- External: 'EXTERNAL'
-} as const;
-
-export type LibraryType = typeof LibraryType[keyof typeof LibraryType];
-
-
-/**
- *
- * @export
- * @enum {string}
- */
-
-export const LogLevel = {
- Verbose: 'verbose',
- Debug: 'debug',
- Log: 'log',
- Warn: 'warn',
- Error: 'error',
- Fatal: 'fatal'
-} as const;
-
-export type LogLevel = typeof LogLevel[keyof typeof LogLevel];
-
-
-/**
- *
- * @export
- * @interface LoginCredentialDto
- */
-export interface LoginCredentialDto {
- /**
- *
- * @type {string}
- * @memberof LoginCredentialDto
- */
- 'email': string;
- /**
- *
- * @type {string}
- * @memberof LoginCredentialDto
- */
- 'password': string;
-}
-/**
- *
- * @export
- * @interface LoginResponseDto
- */
-export interface LoginResponseDto {
- /**
- *
- * @type {string}
- * @memberof LoginResponseDto
- */
- 'accessToken': string;
- /**
- *
- * @type {boolean}
- * @memberof LoginResponseDto
- */
- 'isAdmin': boolean;
- /**
- *
- * @type {string}
- * @memberof LoginResponseDto
- */
- 'name': string;
- /**
- *
- * @type {string}
- * @memberof LoginResponseDto
- */
- 'profileImagePath': string;
- /**
- *
- * @type {boolean}
- * @memberof LoginResponseDto
- */
- 'shouldChangePassword': boolean;
- /**
- *
- * @type {string}
- * @memberof LoginResponseDto
- */
- 'userEmail': string;
- /**
- *
- * @type {string}
- * @memberof LoginResponseDto
- */
- 'userId': string;
-}
-/**
- *
- * @export
- * @interface LogoutResponseDto
- */
-export interface LogoutResponseDto {
- /**
- *
- * @type {string}
- * @memberof LogoutResponseDto
- */
- 'redirectUri': string;
- /**
- *
- * @type {boolean}
- * @memberof LogoutResponseDto
- */
- 'successful': boolean;
-}
-/**
- *
- * @export
- * @interface MapMarkerResponseDto
- */
-export interface MapMarkerResponseDto {
- /**
- *
- * @type {string}
- * @memberof MapMarkerResponseDto
- */
- 'id': string;
- /**
- *
- * @type {number}
- * @memberof MapMarkerResponseDto
- */
- 'lat': number;
- /**
- *
- * @type {number}
- * @memberof MapMarkerResponseDto
- */
- 'lon': number;
-}
-/**
- *
- * @export
- * @enum {string}
- */
-
-export const MapTheme = {
- Light: 'light',
- Dark: 'dark'
-} as const;
-
-export type MapTheme = typeof MapTheme[keyof typeof MapTheme];
-
-
-/**
- *
- * @export
- * @interface MemoryLaneResponseDto
- */
-export interface MemoryLaneResponseDto {
- /**
- *
- * @type {Array}
- * @memberof MemoryLaneResponseDto
- */
- 'assets': Array;
- /**
- *
- * @type {string}
- * @memberof MemoryLaneResponseDto
- */
- 'title': string;
-}
-/**
- *
- * @export
- * @interface MergePersonDto
- */
-export interface MergePersonDto {
- /**
- *
- * @type {Array}
- * @memberof MergePersonDto
- */
- 'ids': Array;
-}
-/**
- *
- * @export
- * @interface MetadataSearchDto
- */
-export interface MetadataSearchDto {
- /**
- *
- * @type {string}
- * @memberof MetadataSearchDto
- */
- 'checksum'?: string;
- /**
- *
- * @type {string}
- * @memberof MetadataSearchDto
- */
- 'city'?: string;
- /**
- *
- * @type {string}
- * @memberof MetadataSearchDto
- */
- 'country'?: string;
- /**
- *
- * @type {string}
- * @memberof MetadataSearchDto
- */
- 'createdAfter'?: string;
- /**
- *
- * @type {string}
- * @memberof MetadataSearchDto
- */
- 'createdBefore'?: string;
- /**
- *
- * @type {string}
- * @memberof MetadataSearchDto
- */
- 'deviceAssetId'?: string;
- /**
- *
- * @type {string}
- * @memberof MetadataSearchDto
- */
- 'deviceId'?: string;
- /**
- *
- * @type {string}
- * @memberof MetadataSearchDto
- */
- 'encodedVideoPath'?: string;
- /**
- *
- * @type {string}
- * @memberof MetadataSearchDto
- */
- 'id'?: string;
- /**
- *
- * @type {boolean}
- * @memberof MetadataSearchDto
- */
- 'isArchived'?: boolean;
- /**
- *
- * @type {boolean}
- * @memberof MetadataSearchDto
- */
- 'isEncoded'?: boolean;
- /**
- *
- * @type {boolean}
- * @memberof MetadataSearchDto
- */
- 'isExternal'?: boolean;
- /**
- *
- * @type {boolean}
- * @memberof MetadataSearchDto
- */
- 'isFavorite'?: boolean;
- /**
- *
- * @type {boolean}
- * @memberof MetadataSearchDto
- */
- 'isMotion'?: boolean;
- /**
- *
- * @type {boolean}
- * @memberof MetadataSearchDto
- */
- 'isNotInAlbum'?: boolean;
- /**
- *
- * @type {boolean}
- * @memberof MetadataSearchDto
- */
- 'isOffline'?: boolean;
- /**
- *
- * @type {boolean}
- * @memberof MetadataSearchDto
- */
- 'isReadOnly'?: boolean;
- /**
- *
- * @type {boolean}
- * @memberof MetadataSearchDto
- */
- 'isVisible'?: boolean;
- /**
- *
- * @type {string}
- * @memberof MetadataSearchDto
- */
- 'lensModel'?: string;
- /**
- *
- * @type {string}
- * @memberof MetadataSearchDto
- */
- 'libraryId'?: string;
- /**
- *
- * @type {string}
- * @memberof MetadataSearchDto
- */
- 'make'?: string;
- /**
- *
- * @type {string}
- * @memberof MetadataSearchDto
- */
- 'model'?: string;
- /**
- *
- * @type {AssetOrder}
- * @memberof MetadataSearchDto
- */
- 'order'?: AssetOrder;
- /**
- *
- * @type {string}
- * @memberof MetadataSearchDto
- */
- 'originalFileName'?: string;
- /**
- *
- * @type {string}
- * @memberof MetadataSearchDto
- */
- 'originalPath'?: string;
- /**
- *
- * @type {number}
- * @memberof MetadataSearchDto
- */
- 'page'?: number;
- /**
- *
- * @type {Array}
- * @memberof MetadataSearchDto
- */
- 'personIds'?: Array;
- /**
- *
- * @type {string}
- * @memberof MetadataSearchDto
- */
- 'resizePath'?: string;
- /**
- *
- * @type {number}
- * @memberof MetadataSearchDto
- */
- 'size'?: number;
- /**
- *
- * @type {string}
- * @memberof MetadataSearchDto
- */
- 'state'?: string;
- /**
- *
- * @type {string}
- * @memberof MetadataSearchDto
- */
- 'takenAfter'?: string;
- /**
- *
- * @type {string}
- * @memberof MetadataSearchDto
- */
- 'takenBefore'?: string;
- /**
- *
- * @type {string}
- * @memberof MetadataSearchDto
- */
- 'trashedAfter'?: string;
- /**
- *
- * @type {string}
- * @memberof MetadataSearchDto
- */
- 'trashedBefore'?: string;
- /**
- *
- * @type {AssetTypeEnum}
- * @memberof MetadataSearchDto
- */
- 'type'?: AssetTypeEnum;
- /**
- *
- * @type {string}
- * @memberof MetadataSearchDto
- */
- 'updatedAfter'?: string;
- /**
- *
- * @type {string}
- * @memberof MetadataSearchDto
- */
- 'updatedBefore'?: string;
- /**
- *
- * @type {string}
- * @memberof MetadataSearchDto
- */
- 'webpPath'?: string;
- /**
- *
- * @type {boolean}
- * @memberof MetadataSearchDto
- */
- 'withArchived'?: boolean;
- /**
- *
- * @type {boolean}
- * @memberof MetadataSearchDto
- */
- 'withDeleted'?: boolean;
- /**
- *
- * @type {boolean}
- * @memberof MetadataSearchDto
- */
- 'withExif'?: boolean;
- /**
- *
- * @type {boolean}
- * @memberof MetadataSearchDto
- */
- 'withPeople'?: boolean;
- /**
- *
- * @type {boolean}
- * @memberof MetadataSearchDto
- */
- 'withStacked'?: boolean;
-}
-
-
-/**
- *
- * @export
- * @enum {string}
- */
-
-export const ModelType = {
- FacialRecognition: 'facial-recognition',
- Clip: 'clip'
-} as const;
-
-export type ModelType = typeof ModelType[keyof typeof ModelType];
-
-
-/**
- *
- * @export
- * @interface OAuthAuthorizeResponseDto
- */
-export interface OAuthAuthorizeResponseDto {
- /**
- *
- * @type {string}
- * @memberof OAuthAuthorizeResponseDto
- */
- 'url': string;
-}
-/**
- *
- * @export
- * @interface OAuthCallbackDto
- */
-export interface OAuthCallbackDto {
- /**
- *
- * @type {string}
- * @memberof OAuthCallbackDto
- */
- 'url': string;
-}
-/**
- *
- * @export
- * @interface OAuthConfigDto
- */
-export interface OAuthConfigDto {
- /**
- *
- * @type {string}
- * @memberof OAuthConfigDto
- */
- 'redirectUri': string;
-}
-/**
- *
- * @export
- * @interface PartnerResponseDto
- */
-export interface PartnerResponseDto {
- /**
- *
- * @type {UserAvatarColor}
- * @memberof PartnerResponseDto
- */
- 'avatarColor': UserAvatarColor;
- /**
- *
- * @type {string}
- * @memberof PartnerResponseDto
- */
- 'createdAt': string;
- /**
- *
- * @type {string}
- * @memberof PartnerResponseDto
- */
- 'deletedAt': string | null;
- /**
- *
- * @type {string}
- * @memberof PartnerResponseDto
- */
- 'email': string;
- /**
- *
- * @type {string}
- * @memberof PartnerResponseDto
- */
- 'externalPath': string | null;
- /**
- *
- * @type {string}
- * @memberof PartnerResponseDto
- */
- 'id': string;
- /**
- *
- * @type {boolean}
- * @memberof PartnerResponseDto
- */
- 'inTimeline'?: boolean;
- /**
- *
- * @type {boolean}
- * @memberof PartnerResponseDto
- */
- 'isAdmin': boolean;
- /**
- *
- * @type {boolean}
- * @memberof PartnerResponseDto
- */
- 'memoriesEnabled'?: boolean;
- /**
- *
- * @type {string}
- * @memberof PartnerResponseDto
- */
- 'name': string;
- /**
- *
- * @type {string}
- * @memberof PartnerResponseDto
- */
- 'oauthId': string;
- /**
- *
- * @type {string}
- * @memberof PartnerResponseDto
- */
- 'profileImagePath': string;
- /**
- *
- * @type {number}
- * @memberof PartnerResponseDto
- */
- 'quotaSizeInBytes': number | null;
- /**
- *
- * @type {number}
- * @memberof PartnerResponseDto
- */
- 'quotaUsageInBytes': number | null;
- /**
- *
- * @type {boolean}
- * @memberof PartnerResponseDto
- */
- 'shouldChangePassword': boolean;
- /**
- *
- * @type {string}
- * @memberof PartnerResponseDto
- */
- 'storageLabel': string | null;
- /**
- *
- * @type {string}
- * @memberof PartnerResponseDto
- */
- 'updatedAt': string;
-}
-
-
-/**
- *
- * @export
- * @enum {string}
- */
-
-export const PathEntityType = {
- Asset: 'asset',
- Person: 'person',
- User: 'user'
-} as const;
-
-export type PathEntityType = typeof PathEntityType[keyof typeof PathEntityType];
-
-
-/**
- *
- * @export
- * @enum {string}
- */
-
-export const PathType = {
- Original: 'original',
- JpegThumbnail: 'jpeg_thumbnail',
- WebpThumbnail: 'webp_thumbnail',
- EncodedVideo: 'encoded_video',
- Sidecar: 'sidecar',
- Face: 'face',
- Profile: 'profile'
-} as const;
-
-export type PathType = typeof PathType[keyof typeof PathType];
-
-
-/**
- *
- * @export
- * @interface PeopleResponseDto
- */
-export interface PeopleResponseDto {
- /**
- *
- * @type {number}
- * @memberof PeopleResponseDto
- */
- 'hidden': number;
- /**
- *
- * @type {Array}
- * @memberof PeopleResponseDto
- */
- 'people': Array;
- /**
- *
- * @type {number}
- * @memberof PeopleResponseDto
- */
- 'total': number;
-}
-/**
- *
- * @export
- * @interface PeopleUpdateDto
- */
-export interface PeopleUpdateDto {
- /**
- *
- * @type {Array}
- * @memberof PeopleUpdateDto
- */
- 'people': Array;
-}
-/**
- *
- * @export
- * @interface PeopleUpdateItem
- */
-export interface PeopleUpdateItem {
- /**
- * Person date of birth. Note: the mobile app cannot currently set the birth date to null.
- * @type {string}
- * @memberof PeopleUpdateItem
- */
- 'birthDate'?: string | null;
- /**
- * Asset is used to get the feature face thumbnail.
- * @type {string}
- * @memberof PeopleUpdateItem
- */
- 'featureFaceAssetId'?: string;
- /**
- * Person id.
- * @type {string}
- * @memberof PeopleUpdateItem
- */
- 'id': string;
- /**
- * Person visibility
- * @type {boolean}
- * @memberof PeopleUpdateItem
- */
- 'isHidden'?: boolean;
- /**
- * Person name.
- * @type {string}
- * @memberof PeopleUpdateItem
- */
- 'name'?: string;
-}
-/**
- *
- * @export
- * @interface PersonResponseDto
- */
-export interface PersonResponseDto {
- /**
- *
- * @type {string}
- * @memberof PersonResponseDto
- */
- 'birthDate': string | null;
- /**
- *
- * @type {string}
- * @memberof PersonResponseDto
- */
- 'id': string;
- /**
- *
- * @type {boolean}
- * @memberof PersonResponseDto
- */
- 'isHidden': boolean;
- /**
- *
- * @type {string}
- * @memberof PersonResponseDto
- */
- 'name': string;
- /**
- *
- * @type {string}
- * @memberof PersonResponseDto
- */
- 'thumbnailPath': string;
-}
-/**
- *
- * @export
- * @interface PersonStatisticsResponseDto
- */
-export interface PersonStatisticsResponseDto {
- /**
- *
- * @type {number}
- * @memberof PersonStatisticsResponseDto
- */
- 'assets': number;
-}
-/**
- *
- * @export
- * @interface PersonUpdateDto
- */
-export interface PersonUpdateDto {
- /**
- * Person date of birth. Note: the mobile app cannot currently set the birth date to null.
- * @type {string}
- * @memberof PersonUpdateDto
- */
- 'birthDate'?: string | null;
- /**
- * Asset is used to get the feature face thumbnail.
- * @type {string}
- * @memberof PersonUpdateDto
- */
- 'featureFaceAssetId'?: string;
- /**
- * Person visibility
- * @type {boolean}
- * @memberof PersonUpdateDto
- */
- 'isHidden'?: boolean;
- /**
- * Person name.
- * @type {string}
- * @memberof PersonUpdateDto
- */
- 'name'?: string;
-}
-/**
- *
- * @export
- * @interface PersonWithFacesResponseDto
- */
-export interface PersonWithFacesResponseDto {
- /**
- *
- * @type {string}
- * @memberof PersonWithFacesResponseDto
- */
- 'birthDate': string | null;
- /**
- *
- * @type {Array}
- * @memberof PersonWithFacesResponseDto
- */
- 'faces': Array;
- /**
- *
- * @type {string}
- * @memberof PersonWithFacesResponseDto
- */
- 'id': string;
- /**
- *
- * @type {boolean}
- * @memberof PersonWithFacesResponseDto
- */
- 'isHidden': boolean;
- /**
- *
- * @type {string}
- * @memberof PersonWithFacesResponseDto
- */
- 'name': string;
- /**
- *
- * @type {string}
- * @memberof PersonWithFacesResponseDto
- */
- 'thumbnailPath': string;
-}
-/**
- *
- * @export
- * @interface PlacesResponseDto
- */
-export interface PlacesResponseDto {
- /**
- *
- * @type {string}
- * @memberof PlacesResponseDto
- */
- 'admin1name'?: string;
- /**
- *
- * @type {string}
- * @memberof PlacesResponseDto
- */
- 'admin2name'?: string;
- /**
- *
- * @type {number}
- * @memberof PlacesResponseDto
- */
- 'latitude': number;
- /**
- *
- * @type {number}
- * @memberof PlacesResponseDto
- */
- 'longitude': number;
- /**
- *
- * @type {string}
- * @memberof PlacesResponseDto
- */
- 'name': string;
-}
-/**
- *
- * @export
- * @interface QueueStatusDto
- */
-export interface QueueStatusDto {
- /**
- *
- * @type {boolean}
- * @memberof QueueStatusDto
- */
- 'isActive': boolean;
- /**
- *
- * @type {boolean}
- * @memberof QueueStatusDto
- */
- 'isPaused': boolean;
-}
-/**
- *
- * @export
- * @enum {string}
- */
-
-export const ReactionLevel = {
- Album: 'album',
- Asset: 'asset'
-} as const;
-
-export type ReactionLevel = typeof ReactionLevel[keyof typeof ReactionLevel];
-
-
-/**
- *
- * @export
- * @enum {string}
- */
-
-export const ReactionType = {
- Comment: 'comment',
- Like: 'like'
-} as const;
-
-export type ReactionType = typeof ReactionType[keyof typeof ReactionType];
-
-
-/**
- *
- * @export
- * @interface RecognitionConfig
- */
-export interface RecognitionConfig {
- /**
- *
- * @type {boolean}
- * @memberof RecognitionConfig
- */
- 'enabled': boolean;
- /**
- *
- * @type {number}
- * @memberof RecognitionConfig
- */
- 'maxDistance': number;
- /**
- *
- * @type {number}
- * @memberof RecognitionConfig
- */
- 'minFaces': number;
- /**
- *
- * @type {number}
- * @memberof RecognitionConfig
- */
- 'minScore': number;
- /**
- *
- * @type {string}
- * @memberof RecognitionConfig
- */
- 'modelName': string;
- /**
- *
- * @type {ModelType}
- * @memberof RecognitionConfig
- */
- 'modelType'?: ModelType;
-}
-
-
-/**
- *
- * @export
- * @interface ScanLibraryDto
- */
-export interface ScanLibraryDto {
- /**
- *
- * @type {boolean}
- * @memberof ScanLibraryDto
- */
- 'refreshAllFiles'?: boolean;
- /**
- *
- * @type {boolean}
- * @memberof ScanLibraryDto
- */
- 'refreshModifiedFiles'?: boolean;
-}
-/**
- *
- * @export
- * @interface SearchAlbumResponseDto
- */
-export interface SearchAlbumResponseDto {
- /**
- *
- * @type {number}
- * @memberof SearchAlbumResponseDto
- */
- 'count': number;
- /**
- *
- * @type {Array}
- * @memberof SearchAlbumResponseDto
- */
- 'facets': Array;
- /**
- *
- * @type {Array}
- * @memberof SearchAlbumResponseDto
- */
- 'items': Array;
- /**
- *
- * @type {number}
- * @memberof SearchAlbumResponseDto
- */
- 'total': number;
-}
-/**
- *
- * @export
- * @interface SearchAssetResponseDto
- */
-export interface SearchAssetResponseDto {
- /**
- *
- * @type {number}
- * @memberof SearchAssetResponseDto
- */
- 'count': number;
- /**
- *
- * @type {Array}
- * @memberof SearchAssetResponseDto
- */
- 'facets': Array;
- /**
- *
- * @type {Array}
- * @memberof SearchAssetResponseDto
- */
- 'items': Array;
- /**
- *
- * @type {string}
- * @memberof SearchAssetResponseDto
- */
- 'nextPage': string | null;
- /**
- *
- * @type {number}
- * @memberof SearchAssetResponseDto
- */
- 'total': number;
-}
-/**
- *
- * @export
- * @interface SearchExploreItem
- */
-export interface SearchExploreItem {
- /**
- *
- * @type {AssetResponseDto}
- * @memberof SearchExploreItem
- */
- 'data': AssetResponseDto;
- /**
- *
- * @type {string}
- * @memberof SearchExploreItem
- */
- 'value': string;
-}
-/**
- *
- * @export
- * @interface SearchExploreResponseDto
- */
-export interface SearchExploreResponseDto {
- /**
- *
- * @type {string}
- * @memberof SearchExploreResponseDto
- */
- 'fieldName': string;
- /**
- *
- * @type {Array}
- * @memberof SearchExploreResponseDto
- */
- 'items': Array;
-}
-/**
- *
- * @export
- * @interface SearchFacetCountResponseDto
- */
-export interface SearchFacetCountResponseDto {
- /**
- *
- * @type {number}
- * @memberof SearchFacetCountResponseDto
- */
- 'count': number;
- /**
- *
- * @type {string}
- * @memberof SearchFacetCountResponseDto
- */
- 'value': string;
-}
-/**
- *
- * @export
- * @interface SearchFacetResponseDto
- */
-export interface SearchFacetResponseDto {
- /**
- *
- * @type {Array}
- * @memberof SearchFacetResponseDto
- */
- 'counts': Array;
- /**
- *
- * @type {string}
- * @memberof SearchFacetResponseDto
- */
- 'fieldName': string;
-}
-/**
- *
- * @export
- * @interface SearchResponseDto
- */
-export interface SearchResponseDto {
- /**
- *
- * @type {SearchAlbumResponseDto}
- * @memberof SearchResponseDto
- */
- 'albums': SearchAlbumResponseDto;
- /**
- *
- * @type {SearchAssetResponseDto}
- * @memberof SearchResponseDto
- */
- 'assets': SearchAssetResponseDto;
-}
-/**
- *
- * @export
- * @enum {string}
- */
-
-export const SearchSuggestionType = {
- Country: 'country',
- State: 'state',
- City: 'city',
- CameraMake: 'camera-make',
- CameraModel: 'camera-model'
-} as const;
-
-export type SearchSuggestionType = typeof SearchSuggestionType[keyof typeof SearchSuggestionType];
-
-
-/**
- *
- * @export
- * @interface ServerConfigDto
- */
-export interface ServerConfigDto {
- /**
- *
- * @type {string}
- * @memberof ServerConfigDto
- */
- 'externalDomain': string;
- /**
- *
- * @type {boolean}
- * @memberof ServerConfigDto
- */
- 'isInitialized': boolean;
- /**
- *
- * @type {boolean}
- * @memberof ServerConfigDto
- */
- 'isOnboarded': boolean;
- /**
- *
- * @type {string}
- * @memberof ServerConfigDto
- */
- 'loginPageMessage': string;
- /**
- *
- * @type {string}
- * @memberof ServerConfigDto
- */
- 'oauthButtonText': string;
- /**
- *
- * @type {number}
- * @memberof ServerConfigDto
- */
- 'trashDays': number;
-}
-/**
- *
- * @export
- * @interface ServerFeaturesDto
- */
-export interface ServerFeaturesDto {
- /**
- *
- * @type {boolean}
- * @memberof ServerFeaturesDto
- */
- 'configFile': boolean;
- /**
- *
- * @type {boolean}
- * @memberof ServerFeaturesDto
- */
- 'facialRecognition': boolean;
- /**
- *
- * @type {boolean}
- * @memberof ServerFeaturesDto
- */
- 'map': boolean;
- /**
- *
- * @type {boolean}
- * @memberof ServerFeaturesDto
- */
- 'oauth': boolean;
- /**
- *
- * @type {boolean}
- * @memberof ServerFeaturesDto
- */
- 'oauthAutoLaunch': boolean;
- /**
- *
- * @type {boolean}
- * @memberof ServerFeaturesDto
- */
- 'passwordLogin': boolean;
- /**
- *
- * @type {boolean}
- * @memberof ServerFeaturesDto
- */
- 'reverseGeocoding': boolean;
- /**
- *
- * @type {boolean}
- * @memberof ServerFeaturesDto
- */
- 'search': boolean;
- /**
- *
- * @type {boolean}
- * @memberof ServerFeaturesDto
- */
- 'sidecar': boolean;
- /**
- *
- * @type {boolean}
- * @memberof ServerFeaturesDto
- */
- 'smartSearch': boolean;
- /**
- *
- * @type {boolean}
- * @memberof ServerFeaturesDto
- */
- 'trash': boolean;
-}
-/**
- *
- * @export
- * @interface ServerInfoResponseDto
- */
-export interface ServerInfoResponseDto {
- /**
- *
- * @type {string}
- * @memberof ServerInfoResponseDto
- */
- 'diskAvailable': string;
- /**
- *
- * @type {number}
- * @memberof ServerInfoResponseDto
- */
- 'diskAvailableRaw': number;
- /**
- *
- * @type {string}
- * @memberof ServerInfoResponseDto
- */
- 'diskSize': string;
- /**
- *
- * @type {number}
- * @memberof ServerInfoResponseDto
- */
- 'diskSizeRaw': number;
- /**
- *
- * @type {number}
- * @memberof ServerInfoResponseDto
- */
- 'diskUsagePercentage': number;
- /**
- *
- * @type {string}
- * @memberof ServerInfoResponseDto
- */
- 'diskUse': string;
- /**
- *
- * @type {number}
- * @memberof ServerInfoResponseDto
- */
- 'diskUseRaw': number;
-}
-/**
- *
- * @export
- * @interface ServerMediaTypesResponseDto
- */
-export interface ServerMediaTypesResponseDto {
- /**
- *
- * @type {Array}
- * @memberof ServerMediaTypesResponseDto
- */
- 'image': Array;
- /**
- *
- * @type {Array}
- * @memberof ServerMediaTypesResponseDto
- */
- 'sidecar': Array;
- /**
- *
- * @type {Array}
- * @memberof ServerMediaTypesResponseDto
- */
- 'video': Array;
-}
-/**
- *
- * @export
- * @interface ServerPingResponse
- */
-export interface ServerPingResponse {
- /**
- *
- * @type {string}
- * @memberof ServerPingResponse
- */
- 'res': string;
-}
-/**
- *
- * @export
- * @interface ServerStatsResponseDto
- */
-export interface ServerStatsResponseDto {
- /**
- *
- * @type {number}
- * @memberof ServerStatsResponseDto
- */
- 'photos': number;
- /**
- *
- * @type {number}
- * @memberof ServerStatsResponseDto
- */
- 'usage': number;
- /**
- *
- * @type {Array}
- * @memberof ServerStatsResponseDto
- */
- 'usageByUser': Array;
- /**
- *
- * @type {number}
- * @memberof ServerStatsResponseDto
- */
- 'videos': number;
-}
-/**
- *
- * @export
- * @interface ServerThemeDto
- */
-export interface ServerThemeDto {
- /**
- *
- * @type {string}
- * @memberof ServerThemeDto
- */
- 'customCss': string;
-}
-/**
- *
- * @export
- * @interface ServerVersionResponseDto
- */
-export interface ServerVersionResponseDto {
- /**
- *
- * @type {number}
- * @memberof ServerVersionResponseDto
- */
- 'major': number;
- /**
- *
- * @type {number}
- * @memberof ServerVersionResponseDto
- */
- 'minor': number;
- /**
- *
- * @type {number}
- * @memberof ServerVersionResponseDto
- */
- 'patch': number;
-}
-/**
- *
- * @export
- * @interface SharedLinkCreateDto
- */
-export interface SharedLinkCreateDto {
- /**
- *
- * @type {string}
- * @memberof SharedLinkCreateDto
- */
- 'albumId'?: string;
- /**
- *
- * @type {boolean}
- * @memberof SharedLinkCreateDto
- */
- 'allowDownload'?: boolean;
- /**
- *
- * @type {boolean}
- * @memberof SharedLinkCreateDto
- */
- 'allowUpload'?: boolean;
- /**
- *
- * @type {Array}
- * @memberof SharedLinkCreateDto
- */
- 'assetIds'?: Array;
- /**
- *
- * @type {string}
- * @memberof SharedLinkCreateDto
- */
- 'description'?: string;
- /**
- *
- * @type {string}
- * @memberof SharedLinkCreateDto
- */
- 'expiresAt'?: string | null;
- /**
- *
- * @type {string}
- * @memberof SharedLinkCreateDto
- */
- 'password'?: string;
- /**
- *
- * @type {boolean}
- * @memberof SharedLinkCreateDto
- */
- 'showMetadata'?: boolean;
- /**
- *
- * @type {SharedLinkType}
- * @memberof SharedLinkCreateDto
- */
- 'type': SharedLinkType;
-}
-
-
-/**
- *
- * @export
- * @interface SharedLinkEditDto
- */
-export interface SharedLinkEditDto {
- /**
- *
- * @type {boolean}
- * @memberof SharedLinkEditDto
- */
- 'allowDownload'?: boolean;
- /**
- *
- * @type {boolean}
- * @memberof SharedLinkEditDto
- */
- 'allowUpload'?: boolean;
- /**
- * Few clients cannot send null to set the expiryTime to never. Setting this flag and not sending expiryAt is considered as null instead. Clients that can send null values can ignore this.
- * @type {boolean}
- * @memberof SharedLinkEditDto
- */
- 'changeExpiryTime'?: boolean;
- /**
- *
- * @type {string}
- * @memberof SharedLinkEditDto
- */
- 'description'?: string;
- /**
- *
- * @type {string}
- * @memberof SharedLinkEditDto
- */
- 'expiresAt'?: string | null;
- /**
- *
- * @type {string}
- * @memberof SharedLinkEditDto
- */
- 'password'?: string;
- /**
- *
- * @type {boolean}
- * @memberof SharedLinkEditDto
- */
- 'showMetadata'?: boolean;
-}
-/**
- *
- * @export
- * @interface SharedLinkResponseDto
- */
-export interface SharedLinkResponseDto {
- /**
- *
- * @type {AlbumResponseDto}
- * @memberof SharedLinkResponseDto
- */
- 'album'?: AlbumResponseDto;
- /**
- *
- * @type {boolean}
- * @memberof SharedLinkResponseDto
- */
- 'allowDownload': boolean;
- /**
- *
- * @type {boolean}
- * @memberof SharedLinkResponseDto
- */
- 'allowUpload': boolean;
- /**
- *
- * @type {Array}
- * @memberof SharedLinkResponseDto
- */
- 'assets': Array;
- /**
- *
- * @type {string}
- * @memberof SharedLinkResponseDto
- */
- 'createdAt': string;
- /**
- *
- * @type {string}
- * @memberof SharedLinkResponseDto
- */
- 'description': string | null;
- /**
- *
- * @type {string}
- * @memberof SharedLinkResponseDto
- */
- 'expiresAt': string | null;
- /**
- *
- * @type {string}
- * @memberof SharedLinkResponseDto
- */
- 'id': string;
- /**
- *
- * @type {string}
- * @memberof SharedLinkResponseDto
- */
- 'key': string;
- /**
- *
- * @type {string}
- * @memberof SharedLinkResponseDto
- */
- 'password': string | null;
- /**
- *
- * @type {boolean}
- * @memberof SharedLinkResponseDto
- */
- 'showMetadata': boolean;
- /**
- *
- * @type {string}
- * @memberof SharedLinkResponseDto
- */
- 'token'?: string | null;
- /**
- *
- * @type {SharedLinkType}
- * @memberof SharedLinkResponseDto
- */
- 'type': SharedLinkType;
- /**
- *
- * @type {string}
- * @memberof SharedLinkResponseDto
- */
- 'userId': string;
-}
-
-
-/**
- *
- * @export
- * @enum {string}
- */
-
-export const SharedLinkType = {
- Album: 'ALBUM',
- Individual: 'INDIVIDUAL'
-} as const;
-
-export type SharedLinkType = typeof SharedLinkType[keyof typeof SharedLinkType];
-
-
-/**
- *
- * @export
- * @interface SignUpDto
- */
-export interface SignUpDto {
- /**
- *
- * @type {string}
- * @memberof SignUpDto
- */
- 'email': string;
- /**
- *
- * @type {string}
- * @memberof SignUpDto
- */
- 'name': string;
- /**
- *
- * @type {string}
- * @memberof SignUpDto
- */
- 'password': string;
-}
-/**
- *
- * @export
- * @interface SmartInfoResponseDto
- */
-export interface SmartInfoResponseDto {
- /**
- *
- * @type {Array}
- * @memberof SmartInfoResponseDto
- */
- 'objects'?: Array | null;
- /**
- *
- * @type {Array}
- * @memberof SmartInfoResponseDto
- */
- 'tags'?: Array | null;
-}
-/**
- *
- * @export
- * @interface SmartSearchDto
- */
-export interface SmartSearchDto {
- /**
- *
- * @type {string}
- * @memberof SmartSearchDto
- */
- 'city'?: string;
- /**
- *
- * @type {string}
- * @memberof SmartSearchDto
- */
- 'country'?: string;
- /**
- *
- * @type {string}
- * @memberof SmartSearchDto
- */
- 'createdAfter'?: string;
- /**
- *
- * @type {string}
- * @memberof SmartSearchDto
- */
- 'createdBefore'?: string;
- /**
- *
- * @type {string}
- * @memberof SmartSearchDto
- */
- 'deviceId'?: string;
- /**
- *
- * @type {boolean}
- * @memberof SmartSearchDto
- */
- 'isArchived'?: boolean;
- /**
- *
- * @type {boolean}
- * @memberof SmartSearchDto
- */
- 'isEncoded'?: boolean;
- /**
- *
- * @type {boolean}
- * @memberof SmartSearchDto
- */
- 'isExternal'?: boolean;
- /**
- *
- * @type {boolean}
- * @memberof SmartSearchDto
- */
- 'isFavorite'?: boolean;
- /**
- *
- * @type {boolean}
- * @memberof SmartSearchDto
- */
- 'isMotion'?: boolean;
- /**
- *
- * @type {boolean}
- * @memberof SmartSearchDto
- */
- 'isNotInAlbum'?: boolean;
- /**
- *
- * @type {boolean}
- * @memberof SmartSearchDto
- */
- 'isOffline'?: boolean;
- /**
- *
- * @type {boolean}
- * @memberof SmartSearchDto
- */
- 'isReadOnly'?: boolean;
- /**
- *
- * @type {boolean}
- * @memberof SmartSearchDto
- */
- 'isVisible'?: boolean;
- /**
- *
- * @type {string}
- * @memberof SmartSearchDto
- */
- 'lensModel'?: string;
- /**
- *
- * @type {string}
- * @memberof SmartSearchDto
- */
- 'libraryId'?: string;
- /**
- *
- * @type {string}
- * @memberof SmartSearchDto
- */
- 'make'?: string;
- /**
- *
- * @type {string}
- * @memberof SmartSearchDto
- */
- 'model'?: string;
- /**
- *
- * @type {number}
- * @memberof SmartSearchDto
- */
- 'page'?: number;
- /**
- *
- * @type {string}
- * @memberof SmartSearchDto
- */
- 'query': string;
- /**
- *
- * @type {number}
- * @memberof SmartSearchDto
- */
- 'size'?: number;
- /**
- *
- * @type {string}
- * @memberof SmartSearchDto
- */
- 'state'?: string;
- /**
- *
- * @type {string}
- * @memberof SmartSearchDto
- */
- 'takenAfter'?: string;
- /**
- *
- * @type {string}
- * @memberof SmartSearchDto
- */
- 'takenBefore'?: string;
- /**
- *
- * @type {string}
- * @memberof SmartSearchDto
- */
- 'trashedAfter'?: string;
- /**
- *
- * @type {string}
- * @memberof SmartSearchDto
- */
- 'trashedBefore'?: string;
- /**
- *
- * @type {AssetTypeEnum}
- * @memberof SmartSearchDto
- */
- 'type'?: AssetTypeEnum;
- /**
- *
- * @type {string}
- * @memberof SmartSearchDto
- */
- 'updatedAfter'?: string;
- /**
- *
- * @type {string}
- * @memberof SmartSearchDto
- */
- 'updatedBefore'?: string;
- /**
- *
- * @type {boolean}
- * @memberof SmartSearchDto
- */
- 'withArchived'?: boolean;
- /**
- *
- * @type {boolean}
- * @memberof SmartSearchDto
- */
- 'withDeleted'?: boolean;
- /**
- *
- * @type {boolean}
- * @memberof SmartSearchDto
- */
- 'withExif'?: boolean;
-}
-
-
-/**
- *
- * @export
- * @interface SystemConfigDto
- */
-export interface SystemConfigDto {
- /**
- *
- * @type {SystemConfigFFmpegDto}
- * @memberof SystemConfigDto
- */
- 'ffmpeg': SystemConfigFFmpegDto;
- /**
- *
- * @type {SystemConfigJobDto}
- * @memberof SystemConfigDto
- */
- 'job': SystemConfigJobDto;
- /**
- *
- * @type {SystemConfigLibraryDto}
- * @memberof SystemConfigDto
- */
- 'library': SystemConfigLibraryDto;
- /**
- *
- * @type {SystemConfigLoggingDto}
- * @memberof SystemConfigDto
- */
- 'logging': SystemConfigLoggingDto;
- /**
- *
- * @type {SystemConfigMachineLearningDto}
- * @memberof SystemConfigDto
- */
- 'machineLearning': SystemConfigMachineLearningDto;
- /**
- *
- * @type {SystemConfigMapDto}
- * @memberof SystemConfigDto
- */
- 'map': SystemConfigMapDto;
- /**
- *
- * @type {SystemConfigNewVersionCheckDto}
- * @memberof SystemConfigDto
- */
- 'newVersionCheck': SystemConfigNewVersionCheckDto;
- /**
- *
- * @type {SystemConfigOAuthDto}
- * @memberof SystemConfigDto
- */
- 'oauth': SystemConfigOAuthDto;
- /**
- *
- * @type {SystemConfigPasswordLoginDto}
- * @memberof SystemConfigDto
- */
- 'passwordLogin': SystemConfigPasswordLoginDto;
- /**
- *
- * @type {SystemConfigReverseGeocodingDto}
- * @memberof SystemConfigDto
- */
- 'reverseGeocoding': SystemConfigReverseGeocodingDto;
- /**
- *
- * @type {SystemConfigServerDto}
- * @memberof SystemConfigDto
- */
- 'server': SystemConfigServerDto;
- /**
- *
- * @type {SystemConfigStorageTemplateDto}
- * @memberof SystemConfigDto
- */
- 'storageTemplate': SystemConfigStorageTemplateDto;
- /**
- *
- * @type {SystemConfigThemeDto}
- * @memberof SystemConfigDto
- */
- 'theme': SystemConfigThemeDto;
- /**
- *
- * @type {SystemConfigThumbnailDto}
- * @memberof SystemConfigDto
- */
- 'thumbnail': SystemConfigThumbnailDto;
- /**
- *
- * @type {SystemConfigTrashDto}
- * @memberof SystemConfigDto
- */
- 'trash': SystemConfigTrashDto;
-}
-/**
- *
- * @export
- * @interface SystemConfigFFmpegDto
- */
-export interface SystemConfigFFmpegDto {
- /**
- *
- * @type {TranscodeHWAccel}
- * @memberof SystemConfigFFmpegDto
- */
- 'accel': TranscodeHWAccel;
- /**
- *
- * @type {Array}
- * @memberof SystemConfigFFmpegDto
- */
- 'acceptedAudioCodecs': Array;
- /**
- *
- * @type {Array}
- * @memberof SystemConfigFFmpegDto
- */
- 'acceptedVideoCodecs': Array;
- /**
- *
- * @type {number}
- * @memberof SystemConfigFFmpegDto
- */
- 'bframes': number;
- /**
- *
- * @type {CQMode}
- * @memberof SystemConfigFFmpegDto
- */
- 'cqMode': CQMode;
- /**
- *
- * @type {number}
- * @memberof SystemConfigFFmpegDto
- */
- 'crf': number;
- /**
- *
- * @type {number}
- * @memberof SystemConfigFFmpegDto
- */
- 'gopSize': number;
- /**
- *
- * @type {string}
- * @memberof SystemConfigFFmpegDto
- */
- 'maxBitrate': string;
- /**
- *
- * @type {number}
- * @memberof SystemConfigFFmpegDto
- */
- 'npl': number;
- /**
- *
- * @type {string}
- * @memberof SystemConfigFFmpegDto
- */
- 'preferredHwDevice': string;
- /**
- *
- * @type {string}
- * @memberof SystemConfigFFmpegDto
- */
- 'preset': string;
- /**
- *
- * @type {number}
- * @memberof SystemConfigFFmpegDto
- */
- 'refs': number;
- /**
- *
- * @type {AudioCodec}
- * @memberof SystemConfigFFmpegDto
- */
- 'targetAudioCodec': AudioCodec;
- /**
- *
- * @type {string}
- * @memberof SystemConfigFFmpegDto
- */
- 'targetResolution': string;
- /**
- *
- * @type {VideoCodec}
- * @memberof SystemConfigFFmpegDto
- */
- 'targetVideoCodec': VideoCodec;
- /**
- *
- * @type {boolean}
- * @memberof SystemConfigFFmpegDto
- */
- 'temporalAQ': boolean;
- /**
- *
- * @type {number}
- * @memberof SystemConfigFFmpegDto
- */
- 'threads': number;
- /**
- *
- * @type {ToneMapping}
- * @memberof SystemConfigFFmpegDto
- */
- 'tonemap': ToneMapping;
- /**
- *
- * @type {TranscodePolicy}
- * @memberof SystemConfigFFmpegDto
- */
- 'transcode': TranscodePolicy;
- /**
- *
- * @type {boolean}
- * @memberof SystemConfigFFmpegDto
- */
- 'twoPass': boolean;
-}
-
-
-/**
- *
- * @export
- * @interface SystemConfigJobDto
- */
-export interface SystemConfigJobDto {
- /**
- *
- * @type {JobSettingsDto}
- * @memberof SystemConfigJobDto
- */
- 'backgroundTask': JobSettingsDto;
- /**
- *
- * @type {JobSettingsDto}
- * @memberof SystemConfigJobDto
- */
- 'faceDetection': JobSettingsDto;
- /**
- *
- * @type {JobSettingsDto}
- * @memberof SystemConfigJobDto
- */
- 'library': JobSettingsDto;
- /**
- *
- * @type {JobSettingsDto}
- * @memberof SystemConfigJobDto
- */
- 'metadataExtraction': JobSettingsDto;
- /**
- *
- * @type {JobSettingsDto}
- * @memberof SystemConfigJobDto
- */
- 'migration': JobSettingsDto;
- /**
- *
- * @type {JobSettingsDto}
- * @memberof SystemConfigJobDto
- */
- 'search': JobSettingsDto;
- /**
- *
- * @type {JobSettingsDto}
- * @memberof SystemConfigJobDto
- */
- 'sidecar': JobSettingsDto;
- /**
- *
- * @type {JobSettingsDto}
- * @memberof SystemConfigJobDto
- */
- 'smartSearch': JobSettingsDto;
- /**
- *
- * @type {JobSettingsDto}
- * @memberof SystemConfigJobDto
- */
- 'thumbnailGeneration': JobSettingsDto;
- /**
- *
- * @type {JobSettingsDto}
- * @memberof SystemConfigJobDto
- */
- 'videoConversion': JobSettingsDto;
-}
-/**
- *
- * @export
- * @interface SystemConfigLibraryDto
- */
-export interface SystemConfigLibraryDto {
- /**
- *
- * @type {SystemConfigLibraryScanDto}
- * @memberof SystemConfigLibraryDto
- */
- 'scan': SystemConfigLibraryScanDto;
- /**
- *
- * @type {SystemConfigLibraryWatchDto}
- * @memberof SystemConfigLibraryDto
- */
- 'watch': SystemConfigLibraryWatchDto;
-}
-/**
- *
- * @export
- * @interface SystemConfigLibraryScanDto
- */
-export interface SystemConfigLibraryScanDto {
- /**
- *
- * @type {string}
- * @memberof SystemConfigLibraryScanDto
- */
- 'cronExpression': string;
- /**
- *
- * @type {boolean}
- * @memberof SystemConfigLibraryScanDto
- */
- 'enabled': boolean;
-}
-/**
- *
- * @export
- * @interface SystemConfigLibraryWatchDto
- */
-export interface SystemConfigLibraryWatchDto {
- /**
- *
- * @type {boolean}
- * @memberof SystemConfigLibraryWatchDto
- */
- 'enabled': boolean;
- /**
- *
- * @type {number}
- * @memberof SystemConfigLibraryWatchDto
- */
- 'interval': number;
- /**
- *
- * @type {boolean}
- * @memberof SystemConfigLibraryWatchDto
- */
- 'usePolling': boolean;
-}
-/**
- *
- * @export
- * @interface SystemConfigLoggingDto
- */
-export interface SystemConfigLoggingDto {
- /**
- *
- * @type {boolean}
- * @memberof SystemConfigLoggingDto
- */
- 'enabled': boolean;
- /**
- *
- * @type {LogLevel}
- * @memberof SystemConfigLoggingDto
- */
- 'level': LogLevel;
-}
-
-
-/**
- *
- * @export
- * @interface SystemConfigMachineLearningDto
- */
-export interface SystemConfigMachineLearningDto {
- /**
- *
- * @type {CLIPConfig}
- * @memberof SystemConfigMachineLearningDto
- */
- 'clip': CLIPConfig;
- /**
- *
- * @type {boolean}
- * @memberof SystemConfigMachineLearningDto
- */
- 'enabled': boolean;
- /**
- *
- * @type {RecognitionConfig}
- * @memberof SystemConfigMachineLearningDto
- */
- 'facialRecognition': RecognitionConfig;
- /**
- *
- * @type {string}
- * @memberof SystemConfigMachineLearningDto
- */
- 'url': string;
-}
-/**
- *
- * @export
- * @interface SystemConfigMapDto
- */
-export interface SystemConfigMapDto {
- /**
- *
- * @type {string}
- * @memberof SystemConfigMapDto
- */
- 'darkStyle': string;
- /**
- *
- * @type {boolean}
- * @memberof SystemConfigMapDto
- */
- 'enabled': boolean;
- /**
- *
- * @type {string}
- * @memberof SystemConfigMapDto
- */
- 'lightStyle': string;
-}
-/**
- *
- * @export
- * @interface SystemConfigNewVersionCheckDto
- */
-export interface SystemConfigNewVersionCheckDto {
- /**
- *
- * @type {boolean}
- * @memberof SystemConfigNewVersionCheckDto
- */
- 'enabled': boolean;
-}
-/**
- *
- * @export
- * @interface SystemConfigOAuthDto
- */
-export interface SystemConfigOAuthDto {
- /**
- *
- * @type {boolean}
- * @memberof SystemConfigOAuthDto
- */
- 'autoLaunch': boolean;
- /**
- *
- * @type {boolean}
- * @memberof SystemConfigOAuthDto
- */
- 'autoRegister': boolean;
- /**
- *
- * @type {string}
- * @memberof SystemConfigOAuthDto
- */
- 'buttonText': string;
- /**
- *
- * @type {string}
- * @memberof SystemConfigOAuthDto
- */
- 'clientId': string;
- /**
- *
- * @type {string}
- * @memberof SystemConfigOAuthDto
- */
- 'clientSecret': string;
- /**
- *
- * @type {boolean}
- * @memberof SystemConfigOAuthDto
- */
- 'enabled': boolean;
- /**
- *
- * @type {string}
- * @memberof SystemConfigOAuthDto
- */
- 'issuerUrl': string;
- /**
- *
- * @type {boolean}
- * @memberof SystemConfigOAuthDto
- */
- 'mobileOverrideEnabled': boolean;
- /**
- *
- * @type {string}
- * @memberof SystemConfigOAuthDto
- */
- 'mobileRedirectUri': string;
- /**
- *
- * @type {string}
- * @memberof SystemConfigOAuthDto
- */
- 'scope': string;
- /**
- *
- * @type {string}
- * @memberof SystemConfigOAuthDto
- */
- 'signingAlgorithm': string;
- /**
- *
- * @type {string}
- * @memberof SystemConfigOAuthDto
- */
- 'storageLabelClaim': string;
-}
-/**
- *
- * @export
- * @interface SystemConfigPasswordLoginDto
- */
-export interface SystemConfigPasswordLoginDto {
- /**
- *
- * @type {boolean}
- * @memberof SystemConfigPasswordLoginDto
- */
- 'enabled': boolean;
-}
-/**
- *
- * @export
- * @interface SystemConfigReverseGeocodingDto
- */
-export interface SystemConfigReverseGeocodingDto {
- /**
- *
- * @type {boolean}
- * @memberof SystemConfigReverseGeocodingDto
- */
- 'enabled': boolean;
-}
-/**
- *
- * @export
- * @interface SystemConfigServerDto
- */
-export interface SystemConfigServerDto {
- /**
- *
- * @type {string}
- * @memberof SystemConfigServerDto
- */
- 'externalDomain': string;
- /**
- *
- * @type {string}
- * @memberof SystemConfigServerDto
- */
- 'loginPageMessage': string;
-}
-/**
- *
- * @export
- * @interface SystemConfigStorageTemplateDto
- */
-export interface SystemConfigStorageTemplateDto {
- /**
- *
- * @type {boolean}
- * @memberof SystemConfigStorageTemplateDto
- */
- 'enabled': boolean;
- /**
- *
- * @type {boolean}
- * @memberof SystemConfigStorageTemplateDto
- */
- 'hashVerificationEnabled': boolean;
- /**
- *
- * @type {string}
- * @memberof SystemConfigStorageTemplateDto
- */
- 'template': string;
-}
-/**
- *
- * @export
- * @interface SystemConfigTemplateStorageOptionDto
- */
-export interface SystemConfigTemplateStorageOptionDto {
- /**
- *
- * @type {Array}
- * @memberof SystemConfigTemplateStorageOptionDto
- */
- 'dayOptions': Array;
- /**
- *
- * @type {Array}
- * @memberof SystemConfigTemplateStorageOptionDto
- */
- 'hourOptions': Array;
- /**
- *
- * @type {Array}
- * @memberof SystemConfigTemplateStorageOptionDto
- */
- 'minuteOptions': Array;
- /**
- *
- * @type {Array}
- * @memberof SystemConfigTemplateStorageOptionDto
- */
- 'monthOptions': Array;
- /**
- *
- * @type {Array}
- * @memberof SystemConfigTemplateStorageOptionDto
- */
- 'presetOptions': Array;
- /**
- *
- * @type {Array}
- * @memberof SystemConfigTemplateStorageOptionDto
- */
- 'secondOptions': Array;
- /**
- *
- * @type {Array}
- * @memberof SystemConfigTemplateStorageOptionDto
- */
- 'weekOptions': Array;
- /**
- *
- * @type {Array}
- * @memberof SystemConfigTemplateStorageOptionDto
- */
- 'yearOptions': Array;
-}
-/**
- *
- * @export
- * @interface SystemConfigThemeDto
- */
-export interface SystemConfigThemeDto {
- /**
- *
- * @type {string}
- * @memberof SystemConfigThemeDto
- */
- 'customCss': string;
-}
-/**
- *
- * @export
- * @interface SystemConfigThumbnailDto
- */
-export interface SystemConfigThumbnailDto {
- /**
- *
- * @type {Colorspace}
- * @memberof SystemConfigThumbnailDto
- */
- 'colorspace': Colorspace;
- /**
- *
- * @type {number}
- * @memberof SystemConfigThumbnailDto
- */
- 'jpegSize': number;
- /**
- *
- * @type {number}
- * @memberof SystemConfigThumbnailDto
- */
- 'quality': number;
- /**
- *
- * @type {number}
- * @memberof SystemConfigThumbnailDto
- */
- 'webpSize': number;
-}
-
-
-/**
- *
- * @export
- * @interface SystemConfigTrashDto
- */
-export interface SystemConfigTrashDto {
- /**
- *
- * @type {number}
- * @memberof SystemConfigTrashDto
- */
- 'days': number;
- /**
- *
- * @type {boolean}
- * @memberof SystemConfigTrashDto
- */
- 'enabled': boolean;
-}
-/**
- *
- * @export
- * @interface TagResponseDto
- */
-export interface TagResponseDto {
- /**
- *
- * @type {string}
- * @memberof TagResponseDto
- */
- 'id': string;
- /**
- *
- * @type {string}
- * @memberof TagResponseDto
- */
- 'name': string;
- /**
- *
- * @type {TagTypeEnum}
- * @memberof TagResponseDto
- */
- 'type': TagTypeEnum;
- /**
- *
- * @type {string}
- * @memberof TagResponseDto
- */
- 'userId': string;
-}
-
-
-/**
- *
- * @export
- * @enum {string}
- */
-
-export const TagTypeEnum = {
- Object: 'OBJECT',
- Face: 'FACE',
- Custom: 'CUSTOM'
-} as const;
-
-export type TagTypeEnum = typeof TagTypeEnum[keyof typeof TagTypeEnum];
-
-
-/**
- *
- * @export
- * @enum {string}
- */
-
-export const ThumbnailFormat = {
- Jpeg: 'JPEG',
- Webp: 'WEBP'
-} as const;
-
-export type ThumbnailFormat = typeof ThumbnailFormat[keyof typeof ThumbnailFormat];
-
-
-/**
- *
- * @export
- * @interface TimeBucketResponseDto
- */
-export interface TimeBucketResponseDto {
- /**
- *
- * @type {number}
- * @memberof TimeBucketResponseDto
- */
- 'count': number;
- /**
- *
- * @type {string}
- * @memberof TimeBucketResponseDto
- */
- 'timeBucket': string;
-}
-/**
- *
- * @export
- * @enum {string}
- */
-
-export const TimeBucketSize = {
- Day: 'DAY',
- Month: 'MONTH'
-} as const;
-
-export type TimeBucketSize = typeof TimeBucketSize[keyof typeof TimeBucketSize];
-
-
-/**
- *
- * @export
- * @enum {string}
- */
-
-export const ToneMapping = {
- Hable: 'hable',
- Mobius: 'mobius',
- Reinhard: 'reinhard',
- Disabled: 'disabled'
-} as const;
-
-export type ToneMapping = typeof ToneMapping[keyof typeof ToneMapping];
-
-
-/**
- *
- * @export
- * @enum {string}
- */
-
-export const TranscodeHWAccel = {
- Nvenc: 'nvenc',
- Qsv: 'qsv',
- Vaapi: 'vaapi',
- Rkmpp: 'rkmpp',
- Disabled: 'disabled'
-} as const;
-
-export type TranscodeHWAccel = typeof TranscodeHWAccel[keyof typeof TranscodeHWAccel];
-
-
-/**
- *
- * @export
- * @enum {string}
- */
-
-export const TranscodePolicy = {
- All: 'all',
- Optimal: 'optimal',
- Bitrate: 'bitrate',
- Required: 'required',
- Disabled: 'disabled'
-} as const;
-
-export type TranscodePolicy = typeof TranscodePolicy[keyof typeof TranscodePolicy];
-
-
-/**
- *
- * @export
- * @interface UpdateAlbumDto
- */
-export interface UpdateAlbumDto {
- /**
- *
- * @type {string}
- * @memberof UpdateAlbumDto
- */
- 'albumName'?: string;
- /**
- *
- * @type {string}
- * @memberof UpdateAlbumDto
- */
- 'albumThumbnailAssetId'?: string;
- /**
- *
- * @type {string}
- * @memberof UpdateAlbumDto
- */
- 'description'?: string;
- /**
- *
- * @type {boolean}
- * @memberof UpdateAlbumDto
- */
- 'isActivityEnabled'?: boolean;
-}
-/**
- *
- * @export
- * @interface UpdateAssetDto
- */
-export interface UpdateAssetDto {
- /**
- *
- * @type {string}
- * @memberof UpdateAssetDto
- */
- 'dateTimeOriginal'?: string;
- /**
- *
- * @type {string}
- * @memberof UpdateAssetDto
- */
- 'description'?: string;
- /**
- *
- * @type {boolean}
- * @memberof UpdateAssetDto
- */
- 'isArchived'?: boolean;
- /**
- *
- * @type {boolean}
- * @memberof UpdateAssetDto
- */
- 'isFavorite'?: boolean;
- /**
- *
- * @type {number}
- * @memberof UpdateAssetDto
- */
- 'latitude'?: number;
- /**
- *
- * @type {number}
- * @memberof UpdateAssetDto
- */
- 'longitude'?: number;
-}
-/**
- *
- * @export
- * @interface UpdateLibraryDto
- */
-export interface UpdateLibraryDto {
- /**
- *
- * @type {Array}
- * @memberof UpdateLibraryDto
- */
- 'exclusionPatterns'?: Array;
- /**
- *
- * @type {Array}
- * @memberof UpdateLibraryDto
- */
- 'importPaths'?: Array;
- /**
- *
- * @type {boolean}
- * @memberof UpdateLibraryDto
- */
- 'isVisible'?: boolean;
- /**
- *
- * @type {string}
- * @memberof UpdateLibraryDto
- */
- 'name'?: string;
-}
-/**
- *
- * @export
- * @interface UpdatePartnerDto
- */
-export interface UpdatePartnerDto {
- /**
- *
- * @type {boolean}
- * @memberof UpdatePartnerDto
- */
- 'inTimeline': boolean;
-}
-/**
- *
- * @export
- * @interface UpdateStackParentDto
- */
-export interface UpdateStackParentDto {
- /**
- *
- * @type {string}
- * @memberof UpdateStackParentDto
- */
- 'newParentId': string;
- /**
- *
- * @type {string}
- * @memberof UpdateStackParentDto
- */
- 'oldParentId': string;
-}
-/**
- *
- * @export
- * @interface UpdateTagDto
- */
-export interface UpdateTagDto {
- /**
- *
- * @type {string}
- * @memberof UpdateTagDto
- */
- 'name'?: string;
-}
-/**
- *
- * @export
- * @interface UpdateUserDto
- */
-export interface UpdateUserDto {
- /**
- *
- * @type {UserAvatarColor}
- * @memberof UpdateUserDto
- */
- 'avatarColor'?: UserAvatarColor;
- /**
- *
- * @type {string}
- * @memberof UpdateUserDto
- */
- 'email'?: string;
- /**
- *
- * @type {string}
- * @memberof UpdateUserDto
- */
- 'externalPath'?: string;
- /**
- *
- * @type {string}
- * @memberof UpdateUserDto
- */
- 'id': string;
- /**
- *
- * @type {boolean}
- * @memberof UpdateUserDto
- */
- 'isAdmin'?: boolean;
- /**
- *
- * @type {boolean}
- * @memberof UpdateUserDto
- */
- 'memoriesEnabled'?: boolean;
- /**
- *
- * @type {string}
- * @memberof UpdateUserDto
- */
- 'name'?: string;
- /**
- *
- * @type {string}
- * @memberof UpdateUserDto
- */
- 'password'?: string;
- /**
- *
- * @type {number}
- * @memberof UpdateUserDto
- */
- 'quotaSizeInBytes'?: number | null;
- /**
- *
- * @type {boolean}
- * @memberof UpdateUserDto
- */
- 'shouldChangePassword'?: boolean;
- /**
- *
- * @type {string}
- * @memberof UpdateUserDto
- */
- 'storageLabel'?: string;
-}
-
-
-/**
- *
- * @export
- * @interface UsageByUserDto
- */
-export interface UsageByUserDto {
- /**
- *
- * @type {number}
- * @memberof UsageByUserDto
- */
- 'photos': number;
- /**
- *
- * @type {number}
- * @memberof UsageByUserDto
- */
- 'quotaSizeInBytes': number | null;
- /**
- *
- * @type {number}
- * @memberof UsageByUserDto
- */
- 'usage': number;
- /**
- *
- * @type {string}
- * @memberof UsageByUserDto
- */
- 'userId': string;
- /**
- *
- * @type {string}
- * @memberof UsageByUserDto
- */
- 'userName': string;
- /**
- *
- * @type {number}
- * @memberof UsageByUserDto
- */
- 'videos': number;
-}
-/**
- *
- * @export
- * @enum {string}
- */
-
-export const UserAvatarColor = {
- Primary: 'primary',
- Pink: 'pink',
- Red: 'red',
- Yellow: 'yellow',
- Blue: 'blue',
- Green: 'green',
- Purple: 'purple',
- Orange: 'orange',
- Gray: 'gray',
- Amber: 'amber'
-} as const;
-
-export type UserAvatarColor = typeof UserAvatarColor[keyof typeof UserAvatarColor];
-
-
-/**
- *
- * @export
- * @interface UserDto
- */
-export interface UserDto {
- /**
- *
- * @type {UserAvatarColor}
- * @memberof UserDto
- */
- 'avatarColor': UserAvatarColor;
- /**
- *
- * @type {string}
- * @memberof UserDto
- */
- 'email': string;
- /**
- *
- * @type {string}
- * @memberof UserDto
- */
- 'id': string;
- /**
- *
- * @type {string}
- * @memberof UserDto
- */
- 'name': string;
- /**
- *
- * @type {string}
- * @memberof UserDto
- */
- 'profileImagePath': string;
-}
-
-
-/**
- *
- * @export
- * @interface UserResponseDto
- */
-export interface UserResponseDto {
- /**
- *
- * @type {UserAvatarColor}
- * @memberof UserResponseDto
- */
- 'avatarColor': UserAvatarColor;
- /**
- *
- * @type {string}
- * @memberof UserResponseDto
- */
- 'createdAt': string;
- /**
- *
- * @type {string}
- * @memberof UserResponseDto
- */
- 'deletedAt': string | null;
- /**
- *
- * @type {string}
- * @memberof UserResponseDto
- */
- 'email': string;
- /**
- *
- * @type {string}
- * @memberof UserResponseDto
- */
- 'externalPath': string | null;
- /**
- *
- * @type {string}
- * @memberof UserResponseDto
- */
- 'id': string;
- /**
- *
- * @type {boolean}
- * @memberof UserResponseDto
- */
- 'isAdmin': boolean;
- /**
- *
- * @type {boolean}
- * @memberof UserResponseDto
- */
- 'memoriesEnabled'?: boolean;
- /**
- *
- * @type {string}
- * @memberof UserResponseDto
- */
- 'name': string;
- /**
- *
- * @type {string}
- * @memberof UserResponseDto
- */
- 'oauthId': string;
- /**
- *
- * @type {string}
- * @memberof UserResponseDto
- */
- 'profileImagePath': string;
- /**
- *
- * @type {number}
- * @memberof UserResponseDto
- */
- 'quotaSizeInBytes': number | null;
- /**
- *
- * @type {number}
- * @memberof UserResponseDto
- */
- 'quotaUsageInBytes': number | null;
- /**
- *
- * @type {boolean}
- * @memberof UserResponseDto
- */
- 'shouldChangePassword': boolean;
- /**
- *
- * @type {string}
- * @memberof UserResponseDto
- */
- 'storageLabel': string | null;
- /**
- *
- * @type {string}
- * @memberof UserResponseDto
- */
- 'updatedAt': string;
-}
-
-
-/**
- *
- * @export
- * @interface ValidateAccessTokenResponseDto
- */
-export interface ValidateAccessTokenResponseDto {
- /**
- *
- * @type {boolean}
- * @memberof ValidateAccessTokenResponseDto
- */
- 'authStatus': boolean;
-}
-/**
- *
- * @export
- * @interface ValidateLibraryDto
- */
-export interface ValidateLibraryDto {
- /**
- *
- * @type {Array}
- * @memberof ValidateLibraryDto
- */
- 'exclusionPatterns'?: Array;
- /**
- *
- * @type {Array}
- * @memberof ValidateLibraryDto
- */
- 'importPaths'?: Array;
-}
-/**
- *
- * @export
- * @interface ValidateLibraryImportPathResponseDto
- */
-export interface ValidateLibraryImportPathResponseDto {
- /**
- *
- * @type {string}
- * @memberof ValidateLibraryImportPathResponseDto
- */
- 'importPath': string;
- /**
- *
- * @type {boolean}
- * @memberof ValidateLibraryImportPathResponseDto
- */
- 'isValid'?: boolean;
- /**
- *
- * @type {string}
- * @memberof ValidateLibraryImportPathResponseDto
- */
- 'message'?: string;
-}
-/**
- *
- * @export
- * @interface ValidateLibraryResponseDto
- */
-export interface ValidateLibraryResponseDto {
- /**
- *
- * @type {Array}
- * @memberof ValidateLibraryResponseDto
- */
- 'importPaths'?: Array;
-}
-/**
- *
- * @export
- * @enum {string}
- */
-
-export const VideoCodec = {
- H264: 'h264',
- Hevc: 'hevc',
- Vp9: 'vp9'
-} as const;
-
-export type VideoCodec = typeof VideoCodec[keyof typeof VideoCodec];
-
-
-
-/**
- * APIKeyApi - axios parameter creator
- * @export
- */
-export const APIKeyApiAxiosParamCreator = function (configuration?: Configuration) {
- return {
- /**
- *
- * @param {APIKeyCreateDto} aPIKeyCreateDto
- * @param {*} [options] Override http request option.
- * @throws {RequiredError}
- */
- createApiKey: async (aPIKeyCreateDto: APIKeyCreateDto, options: RawAxiosRequestConfig = {}): Promise => {
- // verify required parameter 'aPIKeyCreateDto' is not null or undefined
- assertParamExists('createApiKey', 'aPIKeyCreateDto', aPIKeyCreateDto)
- const localVarPath = `/api-key`;
- // use dummy base URL string because the URL constructor only accepts absolute URLs.
- const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
- let baseOptions;
- if (configuration) {
- baseOptions = configuration.baseOptions;
- }
-
- const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options};
- const localVarHeaderParameter = {} as any;
- const localVarQueryParameter = {} as any;
-
- // authentication cookie required
-
- // authentication api_key required
- await setApiKeyToObject(localVarHeaderParameter, "x-api-key", configuration)
-
- // authentication bearer required
- // http bearer authentication required
- await setBearerAuthToObject(localVarHeaderParameter, configuration)
-
-
-
- localVarHeaderParameter['Content-Type'] = 'application/json';
-
- setSearchParams(localVarUrlObj, localVarQueryParameter);
- let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
- localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
- localVarRequestOptions.data = serializeDataIfNeeded(aPIKeyCreateDto, localVarRequestOptions, configuration)
-
- return {
- url: toPathString(localVarUrlObj),
- options: localVarRequestOptions,
- };
- },
- /**
- *
- * @param {string} id
- * @param {*} [options] Override http request option.
- * @throws {RequiredError}
- */
- deleteApiKey: async (id: string, options: RawAxiosRequestConfig = {}): Promise => {
- // verify required parameter 'id' is not null or undefined
- assertParamExists('deleteApiKey', 'id', id)
- const localVarPath = `/api-key/{id}`
- .replace(`{${"id"}}`, encodeURIComponent(String(id)));
- // use dummy base URL string because the URL constructor only accepts absolute URLs.
- const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
- let baseOptions;
- if (configuration) {
- baseOptions = configuration.baseOptions;
- }
-
- const localVarRequestOptions = { method: 'DELETE', ...baseOptions, ...options};
- const localVarHeaderParameter = {} as any;
- const localVarQueryParameter = {} as any;
-
- // authentication cookie required
-
- // authentication api_key required
- await setApiKeyToObject(localVarHeaderParameter, "x-api-key", configuration)
-
- // authentication bearer required
- // http bearer authentication required
- await setBearerAuthToObject(localVarHeaderParameter, configuration)
-
-
-
- setSearchParams(localVarUrlObj, localVarQueryParameter);
- let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
- localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
-
- return {
- url: toPathString(localVarUrlObj),
- options: localVarRequestOptions,
- };
- },
- /**
- *
- * @param {string} id
- * @param {*} [options] Override http request option.
- * @throws {RequiredError}
- */
- getApiKey: async (id: string, options: RawAxiosRequestConfig = {}): Promise => {
- // verify required parameter 'id' is not null or undefined
- assertParamExists('getApiKey', 'id', id)
- const localVarPath = `/api-key/{id}`
- .replace(`{${"id"}}`, encodeURIComponent(String(id)));
- // use dummy base URL string because the URL constructor only accepts absolute URLs.
- const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
- let baseOptions;
- if (configuration) {
- baseOptions = configuration.baseOptions;
- }
-
- const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options};
- const localVarHeaderParameter = {} as any;
- const localVarQueryParameter = {} as any;
-
- // authentication cookie required
-
- // authentication api_key required
- await setApiKeyToObject(localVarHeaderParameter, "x-api-key", configuration)
-
- // authentication bearer required
- // http bearer authentication required
- await setBearerAuthToObject(localVarHeaderParameter, configuration)
-
-
-
- setSearchParams(localVarUrlObj, localVarQueryParameter);
- let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
- localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
-
- return {
- url: toPathString(localVarUrlObj),
- options: localVarRequestOptions,
- };
- },
- /**
- *
- * @param {*} [options] Override http request option.
- * @throws {RequiredError}
- */
- getApiKeys: async (options: RawAxiosRequestConfig = {}): Promise => {
- const localVarPath = `/api-key`;
- // use dummy base URL string because the URL constructor only accepts absolute URLs.
- const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
- let baseOptions;
- if (configuration) {
- baseOptions = configuration.baseOptions;
- }
-
- const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options};
- const localVarHeaderParameter = {} as any;
- const localVarQueryParameter = {} as any;
-
- // authentication cookie required
-
- // authentication api_key required
- await setApiKeyToObject(localVarHeaderParameter, "x-api-key", configuration)
-
- // authentication bearer required
- // http bearer authentication required
- await setBearerAuthToObject(localVarHeaderParameter, configuration)
-
-
-
- setSearchParams(localVarUrlObj, localVarQueryParameter);
- let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
- localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
-
- return {
- url: toPathString(localVarUrlObj),
- options: localVarRequestOptions,
- };
- },
- /**
- *
- * @param {string} id
- * @param {APIKeyUpdateDto} aPIKeyUpdateDto
- * @param {*} [options] Override http request option.
- * @throws {RequiredError}
- */
- updateApiKey: async (id: string, aPIKeyUpdateDto: APIKeyUpdateDto, options: RawAxiosRequestConfig = {}): Promise => {
- // verify required parameter 'id' is not null or undefined
- assertParamExists('updateApiKey', 'id', id)
- // verify required parameter 'aPIKeyUpdateDto' is not null or undefined
- assertParamExists('updateApiKey', 'aPIKeyUpdateDto', aPIKeyUpdateDto)
- const localVarPath = `/api-key/{id}`
- .replace(`{${"id"}}`, encodeURIComponent(String(id)));
- // use dummy base URL string because the URL constructor only accepts absolute URLs.
- const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
- let baseOptions;
- if (configuration) {
- baseOptions = configuration.baseOptions;
- }
-
- const localVarRequestOptions = { method: 'PUT', ...baseOptions, ...options};
- const localVarHeaderParameter = {} as any;
- const localVarQueryParameter = {} as any;
-
- // authentication cookie required
-
- // authentication api_key required
- await setApiKeyToObject(localVarHeaderParameter, "x-api-key", configuration)
-
- // authentication bearer required
- // http bearer authentication required
- await setBearerAuthToObject(localVarHeaderParameter, configuration)
-
-
-
- localVarHeaderParameter['Content-Type'] = 'application/json';
-
- setSearchParams(localVarUrlObj, localVarQueryParameter);
- let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
- localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
- localVarRequestOptions.data = serializeDataIfNeeded(aPIKeyUpdateDto, localVarRequestOptions, configuration)
-
- return {
- url: toPathString(localVarUrlObj),
- options: localVarRequestOptions,
- };
- },
- }
-};
-
-/**
- * APIKeyApi - functional programming interface
- * @export
- */
-export const APIKeyApiFp = function(configuration?: Configuration) {
- const localVarAxiosParamCreator = APIKeyApiAxiosParamCreator(configuration)
- return {
- /**
- *
- * @param {APIKeyCreateDto} aPIKeyCreateDto
- * @param {*} [options] Override http request option.
- * @throws {RequiredError}
- */
- async createApiKey(aPIKeyCreateDto: APIKeyCreateDto, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> {
- const localVarAxiosArgs = await localVarAxiosParamCreator.createApiKey(aPIKeyCreateDto, options);
- const index = configuration?.serverIndex ?? 0;
- const operationBasePath = operationServerMap['APIKeyApi.createApiKey']?.[index]?.url;
- return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath);
- },
- /**
- *
- * @param {string} id
- * @param {*} [options] Override http request option.
- * @throws {RequiredError}
- */
- async deleteApiKey(id: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> {
- const localVarAxiosArgs = await localVarAxiosParamCreator.deleteApiKey(id, options);
- const index = configuration?.serverIndex ?? 0;
- const operationBasePath = operationServerMap['APIKeyApi.deleteApiKey']?.[index]?.url;
- return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath);
- },
- /**
- *
- * @param {string} id
- * @param {*} [options] Override http request option.
- * @throws {RequiredError}
- */
- async getApiKey(id: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> {
- const localVarAxiosArgs = await localVarAxiosParamCreator.getApiKey(id, options);
- const index = configuration?.serverIndex ?? 0;
- const operationBasePath = operationServerMap['APIKeyApi.getApiKey']?.[index]?.url;
- return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath);
- },
- /**
- *
- * @param {*} [options] Override http request option.
- * @throws {RequiredError}
- */
- async getApiKeys(options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise>> {
- const localVarAxiosArgs = await localVarAxiosParamCreator.getApiKeys(options);
- const index = configuration?.serverIndex ?? 0;
- const operationBasePath = operationServerMap['APIKeyApi.getApiKeys']?.[index]?.url;
- return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath);
- },
- /**
- *
- * @param {string} id
- * @param {APIKeyUpdateDto} aPIKeyUpdateDto
- * @param {*} [options] Override http request option.
- * @throws {RequiredError}
- */
- async updateApiKey(id: string, aPIKeyUpdateDto: APIKeyUpdateDto, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> {
- const localVarAxiosArgs = await localVarAxiosParamCreator.updateApiKey(id, aPIKeyUpdateDto, options);
- const index = configuration?.serverIndex ?? 0;
- const operationBasePath = operationServerMap['APIKeyApi.updateApiKey']?.[index]?.url;
- return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath);
- },
- }
-};
-
-/**
- * APIKeyApi - factory interface
- * @export
- */
-export const APIKeyApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) {
- const localVarFp = APIKeyApiFp(configuration)
- return {
- /**
- *
- * @param {APIKeyApiCreateApiKeyRequest} requestParameters Request parameters.
- * @param {*} [options] Override http request option.
- * @throws {RequiredError}
- */
- createApiKey(requestParameters: APIKeyApiCreateApiKeyRequest, options?: RawAxiosRequestConfig): AxiosPromise