Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6a4f48204d | |||
| 9cd0871178 | |||
| dbbefde98d | |||
| 5407a28533 | |||
| f5edc87e4d | |||
| bf16b61d43 | |||
| 8c882b54cd | |||
| 2d7c333c8c | |||
| 7c821dd205 | |||
| 703361da1a | |||
| fa5aeaf539 | |||
| 5f3a42a132 | |||
| 9d85272c2b | |||
| d2575d8f00 | |||
| f0a4c945bd | |||
| a3766b879e | |||
| 1a190c33a0 | |||
| 17a63e37b2 | |||
| bf1f8da884 | |||
| 2271984dbd | |||
| b40963ec52 | |||
| 735f8d661e |
@@ -56,10 +56,10 @@ jobs:
|
|||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v3.3.0
|
uses: docker/setup-qemu-action@v3.4.0
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3.8.0
|
uses: docker/setup-buildx-action@v3.9.0
|
||||||
|
|
||||||
- name: Login to GitHub Container Registry
|
- name: Login to GitHub Container Registry
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v3
|
||||||
@@ -88,7 +88,7 @@ jobs:
|
|||||||
type=raw,value=latest,enable=${{ github.event_name == 'release' }}
|
type=raw,value=latest,enable=${{ github.event_name == 'release' }}
|
||||||
|
|
||||||
- name: Build and push image
|
- name: Build and push image
|
||||||
uses: docker/build-push-action@v6.12.0
|
uses: docker/build-push-action@v6.13.0
|
||||||
with:
|
with:
|
||||||
file: cli/Dockerfile
|
file: cli/Dockerfile
|
||||||
platforms: linux/amd64,linux/arm64
|
platforms: linux/amd64,linux/arm64
|
||||||
|
|||||||
@@ -87,7 +87,6 @@ jobs:
|
|||||||
TAG_NEW=${{ github.event.number == 0 && github.ref_name || format('pr-{0}', github.event.number) }}${{ matrix.suffix }}
|
TAG_NEW=${{ github.event.number == 0 && github.ref_name || format('pr-{0}', github.event.number) }}${{ matrix.suffix }}
|
||||||
docker buildx imagetools create -t $REGISTRY_NAME/$REPOSITORY:$TAG_NEW $REGISTRY_NAME/$REPOSITORY:$TAG_OLD
|
docker buildx imagetools create -t $REGISTRY_NAME/$REPOSITORY:$TAG_NEW $REGISTRY_NAME/$REPOSITORY:$TAG_OLD
|
||||||
|
|
||||||
|
|
||||||
build_and_push_ml:
|
build_and_push_ml:
|
||||||
name: Build and Push ML
|
name: Build and Push ML
|
||||||
needs: pre-job
|
needs: pre-job
|
||||||
@@ -122,10 +121,10 @@ jobs:
|
|||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v3.3.0
|
uses: docker/setup-qemu-action@v3.4.0
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3.8.0
|
uses: docker/setup-buildx-action@v3.9.0
|
||||||
|
|
||||||
- name: Login to Docker Hub
|
- name: Login to Docker Hub
|
||||||
# Only push to Docker Hub when making a release
|
# Only push to Docker Hub when making a release
|
||||||
@@ -174,7 +173,7 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Build and push image
|
- name: Build and push image
|
||||||
uses: docker/build-push-action@v6.12.0
|
uses: docker/build-push-action@v6.13.0
|
||||||
with:
|
with:
|
||||||
context: ${{ env.context }}
|
context: ${{ env.context }}
|
||||||
file: ${{ env.file }}
|
file: ${{ env.file }}
|
||||||
@@ -195,33 +194,38 @@ jobs:
|
|||||||
|
|
||||||
build_and_push_server:
|
build_and_push_server:
|
||||||
name: Build and Push Server
|
name: Build and Push Server
|
||||||
runs-on: ubuntu-latest
|
runs-on: ${{ matrix.runner }}
|
||||||
needs: pre-job
|
needs: pre-job
|
||||||
if: ${{ needs.pre-job.outputs.should_run_server == 'true' }}
|
if: ${{ needs.pre-job.outputs.should_run_server == 'true' }}
|
||||||
env:
|
env:
|
||||||
image: immich-server
|
image: immich-server
|
||||||
context: .
|
context: .
|
||||||
file: server/Dockerfile
|
file: server/Dockerfile
|
||||||
|
GHCR_REPO: ghcr.io/${{ github.repository_owner }}/immich-server
|
||||||
|
DOCKER_REPO: altran1502/immich-server
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- platforms: linux/amd64,linux/arm64
|
- platform: linux/amd64
|
||||||
device: cpu
|
runner: ubuntu-latest
|
||||||
|
- platform: linux/arm64
|
||||||
|
runner: ubuntu-24.04-arm
|
||||||
steps:
|
steps:
|
||||||
|
- name: Prepare
|
||||||
|
run: |
|
||||||
|
platform=${{ matrix.platform }}
|
||||||
|
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set up QEMU
|
|
||||||
uses: docker/setup-qemu-action@v3.3.0
|
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3.8.0
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
- name: Login to Docker Hub
|
- name: Login to Docker Hub
|
||||||
# Only push to Docker Hub when making a release
|
|
||||||
if: ${{ github.event_name == 'release' }}
|
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v3
|
||||||
|
if: ${{ !github.event.pull_request.head.repo.fork }}
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
@@ -235,16 +239,81 @@ jobs:
|
|||||||
username: ${{ github.repository_owner }}
|
username: ${{ github.repository_owner }}
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Build and push image
|
||||||
|
id: build
|
||||||
|
uses: docker/build-push-action@v6.13.0
|
||||||
|
with:
|
||||||
|
context: ${{ env.context }}
|
||||||
|
file: ${{ env.file }}
|
||||||
|
platforms: ${{ matrix.platform }}
|
||||||
|
# Skip pushing when PR from a fork
|
||||||
|
push: ${{ !github.event.pull_request.head.repo.fork }}
|
||||||
|
labels: ${{ steps.metadata.outputs.labels }}
|
||||||
|
outputs: type=image,"name=${{ env.GHCR_REPO }},${{ env.DOCKER_REPO }}",push-by-digest=true,name-canonical=true,push=true
|
||||||
|
build-args: |
|
||||||
|
DEVICE=cpu
|
||||||
|
BUILD_ID=${{ github.run_id }}
|
||||||
|
BUILD_IMAGE=${{ github.event_name == 'release' && github.ref_name || steps.metadata.outputs.tags }}
|
||||||
|
BUILD_SOURCE_REF=${{ github.ref_name }}
|
||||||
|
BUILD_SOURCE_COMMIT=${{ github.sha }}
|
||||||
|
|
||||||
|
- name: Export digest
|
||||||
|
run: |
|
||||||
|
mkdir -p ${{ runner.temp }}/digests
|
||||||
|
digest="${{ steps.build.outputs.digest }}"
|
||||||
|
touch "${{ runner.temp }}/digests/${digest#sha256:}"
|
||||||
|
|
||||||
|
- name: Upload digest
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: digests-${{ env.PLATFORM_PAIR }}
|
||||||
|
path: ${{ runner.temp }}/digests/*
|
||||||
|
if-no-files-found: error
|
||||||
|
retention-days: 1
|
||||||
|
|
||||||
|
merge_server:
|
||||||
|
name: Merge & Push Server
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: ${{ needs.pre-job.outputs.should_run_server == 'true' && !github.event.pull_request.head.repo.fork }}
|
||||||
|
env:
|
||||||
|
GHCR_REPO: ghcr.io/${{ github.repository_owner }}/immich-server
|
||||||
|
DOCKER_REPO: altran1502/immich-server
|
||||||
|
needs:
|
||||||
|
- build_and_push_server
|
||||||
|
steps:
|
||||||
|
- name: Download digests
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
path: ${{ runner.temp }}/digests
|
||||||
|
pattern: digests-*
|
||||||
|
merge-multiple: true
|
||||||
|
|
||||||
|
- name: Login to Docker Hub
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Login to GHCR
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.repository_owner }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
- name: Generate docker image tags
|
- name: Generate docker image tags
|
||||||
id: metadata
|
id: meta
|
||||||
uses: docker/metadata-action@v5
|
uses: docker/metadata-action@v5
|
||||||
with:
|
with:
|
||||||
flavor: |
|
flavor: |
|
||||||
# Disable latest tag
|
# Disable latest tag
|
||||||
latest=false
|
latest=false
|
||||||
images: |
|
images: |
|
||||||
name=ghcr.io/${{ github.repository_owner }}/${{env.image}}
|
name=${{ env.GHCR_REPO }}
|
||||||
name=altran1502/${{env.image}},enable=${{ github.event_name == 'release' }}
|
name=${{ env.DOCKER_REPO }},enable=${{ github.event_name == 'release' }}
|
||||||
tags: |
|
tags: |
|
||||||
# Tag with branch name
|
# Tag with branch name
|
||||||
type=ref,event=branch,suffix=${{ matrix.suffix }}
|
type=ref,event=branch,suffix=${{ matrix.suffix }}
|
||||||
@@ -254,38 +323,16 @@ jobs:
|
|||||||
type=ref,event=tag,suffix=${{ matrix.suffix }}
|
type=ref,event=tag,suffix=${{ matrix.suffix }}
|
||||||
type=raw,value=release,enable=${{ github.event_name == 'release' }},suffix=${{ matrix.suffix }}
|
type=raw,value=release,enable=${{ github.event_name == 'release' }},suffix=${{ matrix.suffix }}
|
||||||
|
|
||||||
- name: Determine build cache output
|
- name: Create manifest list and push
|
||||||
id: cache-target
|
working-directory: ${{ runner.temp }}/digests
|
||||||
run: |
|
run: |
|
||||||
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
|
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
|
||||||
# Essentially just ignore the cache output (PR can't write to registry cache)
|
$(printf '${{ env.GHCR_REPO }}@sha256:%s ' *) \
|
||||||
echo "cache-to=type=local,dest=/tmp/discard,ignore-error=true" >> $GITHUB_OUTPUT
|
$(printf '${{ env.DOCKER_REPO }}@sha256:%s ' *)
|
||||||
else
|
|
||||||
echo "cache-to=type=registry,mode=max,ref=ghcr.io/${{ github.repository_owner }}/immich-build-cache:${{ env.image }}" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Build and push image
|
|
||||||
uses: docker/build-push-action@v6.12.0
|
|
||||||
with:
|
|
||||||
context: ${{ env.context }}
|
|
||||||
file: ${{ env.file }}
|
|
||||||
platforms: ${{ matrix.platforms }}
|
|
||||||
# Skip pushing when PR from a fork
|
|
||||||
push: ${{ !github.event.pull_request.head.repo.fork }}
|
|
||||||
cache-from: type=registry,ref=ghcr.io/${{ github.repository_owner }}/immich-build-cache:${{env.image}}
|
|
||||||
cache-to: ${{ steps.cache-target.outputs.cache-to }}
|
|
||||||
tags: ${{ steps.metadata.outputs.tags }}
|
|
||||||
labels: ${{ steps.metadata.outputs.labels }}
|
|
||||||
build-args: |
|
|
||||||
DEVICE=${{ matrix.device }}
|
|
||||||
BUILD_ID=${{ github.run_id }}
|
|
||||||
BUILD_IMAGE=${{ github.event_name == 'release' && github.ref_name || steps.metadata.outputs.tags }}
|
|
||||||
BUILD_SOURCE_REF=${{ github.ref_name }}
|
|
||||||
BUILD_SOURCE_COMMIT=${{ github.sha }}
|
|
||||||
|
|
||||||
success-check-server:
|
success-check-server:
|
||||||
name: Docker Build & Push Server Success
|
name: Docker Build & Push Server Success
|
||||||
needs: [build_and_push_server, retag_server]
|
needs: [merge_server, retag_server]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: always()
|
if: always()
|
||||||
steps:
|
steps:
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
name: Preview comment
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
types: [labeled]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
comment-status:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: ${{ github.event.label.name == 'preview' }}
|
||||||
|
permissions:
|
||||||
|
pull-requests: write
|
||||||
|
steps:
|
||||||
|
- uses: mshick/add-pr-comment@v2
|
||||||
|
with:
|
||||||
|
message-id: "preview-status"
|
||||||
|
message: "Deploying preview environment to https://pr-${{ github.event.pull_request.number }}.preview.internal.immich.cloud/"
|
||||||
Generated
+133
-129
@@ -24,7 +24,7 @@
|
|||||||
"@types/cli-progress": "^3.11.0",
|
"@types/cli-progress": "^3.11.0",
|
||||||
"@types/lodash-es": "^4.17.12",
|
"@types/lodash-es": "^4.17.12",
|
||||||
"@types/mock-fs": "^4.13.1",
|
"@types/mock-fs": "^4.13.1",
|
||||||
"@types/node": "^22.10.9",
|
"@types/node": "^22.13.1",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.15.0",
|
"@typescript-eslint/eslint-plugin": "^8.15.0",
|
||||||
"@typescript-eslint/parser": "^8.15.0",
|
"@typescript-eslint/parser": "^8.15.0",
|
||||||
"@vitest/coverage-v8": "^3.0.0",
|
"@vitest/coverage-v8": "^3.0.0",
|
||||||
@@ -59,7 +59,7 @@
|
|||||||
"@oazapfts/runtime": "^1.0.2"
|
"@oazapfts/runtime": "^1.0.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^22.10.9",
|
"@types/node": "^22.13.1",
|
||||||
"typescript": "^5.3.3"
|
"typescript": "^5.3.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -881,9 +881,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@eslint/js": {
|
"node_modules/@eslint/js": {
|
||||||
"version": "9.18.0",
|
"version": "9.19.0",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.18.0.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.19.0.tgz",
|
||||||
"integrity": "sha512-fK6L7rxcq6/z+AaQMtiFTkvbHkBLNlwyRxHpKawP0x3u9+NC6MQTnFW+AdpwC6gfHTW0051cokQgtTN2FqlxQA==",
|
"integrity": "sha512-rbq9/g38qjfqFLOVPvwjIvFFdNziEC5S65jmjPw5r6A//QH+W91akh9irMwjDN8zKUTak6W9EsAv4m/7Wnw0UQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -1482,9 +1482,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/node": {
|
"node_modules/@types/node": {
|
||||||
"version": "22.10.9",
|
"version": "22.13.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.9.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.1.tgz",
|
||||||
"integrity": "sha512-Ir6hwgsKyNESl/gLOcEz3krR4CBGgliDqBQ2ma4wIhEx0w+xnoeTq3tdrNw15kU3SxogDjOgv9sqdtLW8mIHaw==",
|
"integrity": "sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -1498,21 +1498,21 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||||
"version": "8.20.0",
|
"version": "8.23.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.20.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.23.0.tgz",
|
||||||
"integrity": "sha512-naduuphVw5StFfqp4Gq4WhIBE2gN1GEmMUExpJYknZJdRnc+2gDzB8Z3+5+/Kv33hPQRDGzQO/0opHE72lZZ6A==",
|
"integrity": "sha512-vBz65tJgRrA1Q5gWlRfvoH+w943dq9K1p1yDBY2pc+a1nbBLZp7fB9+Hk8DaALUbzjqlMfgaqlVPT1REJdkt/w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/regexpp": "^4.10.0",
|
"@eslint-community/regexpp": "^4.10.0",
|
||||||
"@typescript-eslint/scope-manager": "8.20.0",
|
"@typescript-eslint/scope-manager": "8.23.0",
|
||||||
"@typescript-eslint/type-utils": "8.20.0",
|
"@typescript-eslint/type-utils": "8.23.0",
|
||||||
"@typescript-eslint/utils": "8.20.0",
|
"@typescript-eslint/utils": "8.23.0",
|
||||||
"@typescript-eslint/visitor-keys": "8.20.0",
|
"@typescript-eslint/visitor-keys": "8.23.0",
|
||||||
"graphemer": "^1.4.0",
|
"graphemer": "^1.4.0",
|
||||||
"ignore": "^5.3.1",
|
"ignore": "^5.3.1",
|
||||||
"natural-compare": "^1.4.0",
|
"natural-compare": "^1.4.0",
|
||||||
"ts-api-utils": "^2.0.0"
|
"ts-api-utils": "^2.0.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
@@ -1528,16 +1528,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/parser": {
|
"node_modules/@typescript-eslint/parser": {
|
||||||
"version": "8.20.0",
|
"version": "8.23.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.20.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.23.0.tgz",
|
||||||
"integrity": "sha512-gKXG7A5HMyjDIedBi6bUrDcun8GIjnI8qOwVLiY3rx6T/sHP/19XLJOnIq/FgQvWLHja5JN/LSE7eklNBr612g==",
|
"integrity": "sha512-h2lUByouOXFAlMec2mILeELUbME5SZRN/7R9Cw2RD2lRQQY08MWMM+PmVVKKJNK1aIwqTo9t/0CvOxwPbRIE2Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/scope-manager": "8.20.0",
|
"@typescript-eslint/scope-manager": "8.23.0",
|
||||||
"@typescript-eslint/types": "8.20.0",
|
"@typescript-eslint/types": "8.23.0",
|
||||||
"@typescript-eslint/typescript-estree": "8.20.0",
|
"@typescript-eslint/typescript-estree": "8.23.0",
|
||||||
"@typescript-eslint/visitor-keys": "8.20.0",
|
"@typescript-eslint/visitor-keys": "8.23.0",
|
||||||
"debug": "^4.3.4"
|
"debug": "^4.3.4"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -1553,14 +1553,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/scope-manager": {
|
"node_modules/@typescript-eslint/scope-manager": {
|
||||||
"version": "8.20.0",
|
"version": "8.23.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.20.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.23.0.tgz",
|
||||||
"integrity": "sha512-J7+VkpeGzhOt3FeG1+SzhiMj9NzGD/M6KoGn9f4dbz3YzK9hvbhVTmLj/HiTp9DazIzJ8B4XcM80LrR9Dm1rJw==",
|
"integrity": "sha512-OGqo7+dXHqI7Hfm+WqkZjKjsiRtFUQHPdGMXzk5mYXhJUedO7e/Y7i8AK3MyLMgZR93TX4bIzYrfyVjLC+0VSw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/types": "8.20.0",
|
"@typescript-eslint/types": "8.23.0",
|
||||||
"@typescript-eslint/visitor-keys": "8.20.0"
|
"@typescript-eslint/visitor-keys": "8.23.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
@@ -1571,16 +1571,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/type-utils": {
|
"node_modules/@typescript-eslint/type-utils": {
|
||||||
"version": "8.20.0",
|
"version": "8.23.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.20.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.23.0.tgz",
|
||||||
"integrity": "sha512-bPC+j71GGvA7rVNAHAtOjbVXbLN5PkwqMvy1cwGeaxUoRQXVuKCebRoLzm+IPW/NtFFpstn1ummSIasD5t60GA==",
|
"integrity": "sha512-iIuLdYpQWZKbiH+RkCGc6iu+VwscP5rCtQ1lyQ7TYuKLrcZoeJVpcLiG8DliXVkUxirW/PWlmS+d6yD51L9jvA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/typescript-estree": "8.20.0",
|
"@typescript-eslint/typescript-estree": "8.23.0",
|
||||||
"@typescript-eslint/utils": "8.20.0",
|
"@typescript-eslint/utils": "8.23.0",
|
||||||
"debug": "^4.3.4",
|
"debug": "^4.3.4",
|
||||||
"ts-api-utils": "^2.0.0"
|
"ts-api-utils": "^2.0.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
@@ -1595,9 +1595,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/types": {
|
"node_modules/@typescript-eslint/types": {
|
||||||
"version": "8.20.0",
|
"version": "8.23.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.20.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.23.0.tgz",
|
||||||
"integrity": "sha512-cqaMiY72CkP+2xZRrFt3ExRBu0WmVitN/rYPZErA80mHjHx/Svgp8yfbzkJmDoQ/whcytOPO9/IZXnOc+wigRA==",
|
"integrity": "sha512-1sK4ILJbCmZOTt9k4vkoulT6/y5CHJ1qUYxqpF1K/DBAd8+ZUL4LlSCxOssuH5m4rUaaN0uS0HlVPvd45zjduQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -1609,20 +1609,20 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/typescript-estree": {
|
"node_modules/@typescript-eslint/typescript-estree": {
|
||||||
"version": "8.20.0",
|
"version": "8.23.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.20.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.23.0.tgz",
|
||||||
"integrity": "sha512-Y7ncuy78bJqHI35NwzWol8E0X7XkRVS4K4P4TCyzWkOJih5NDvtoRDW4Ba9YJJoB2igm9yXDdYI/+fkiiAxPzA==",
|
"integrity": "sha512-LcqzfipsB8RTvH8FX24W4UUFk1bl+0yTOf9ZA08XngFwMg4Kj8A+9hwz8Cr/ZS4KwHrmo9PJiLZkOt49vPnuvQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/types": "8.20.0",
|
"@typescript-eslint/types": "8.23.0",
|
||||||
"@typescript-eslint/visitor-keys": "8.20.0",
|
"@typescript-eslint/visitor-keys": "8.23.0",
|
||||||
"debug": "^4.3.4",
|
"debug": "^4.3.4",
|
||||||
"fast-glob": "^3.3.2",
|
"fast-glob": "^3.3.2",
|
||||||
"is-glob": "^4.0.3",
|
"is-glob": "^4.0.3",
|
||||||
"minimatch": "^9.0.4",
|
"minimatch": "^9.0.4",
|
||||||
"semver": "^7.6.0",
|
"semver": "^7.6.0",
|
||||||
"ts-api-utils": "^2.0.0"
|
"ts-api-utils": "^2.0.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
@@ -1636,16 +1636,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/utils": {
|
"node_modules/@typescript-eslint/utils": {
|
||||||
"version": "8.20.0",
|
"version": "8.23.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.20.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.23.0.tgz",
|
||||||
"integrity": "sha512-dq70RUw6UK9ei7vxc4KQtBRk7qkHZv447OUZ6RPQMQl71I3NZxQJX/f32Smr+iqWrB02pHKn2yAdHBb0KNrRMA==",
|
"integrity": "sha512-uB/+PSo6Exu02b5ZEiVtmY6RVYO7YU5xqgzTIVZwTHvvK3HsL8tZZHFaTLFtRG3CsV4A5mhOv+NZx5BlhXPyIA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/eslint-utils": "^4.4.0",
|
"@eslint-community/eslint-utils": "^4.4.0",
|
||||||
"@typescript-eslint/scope-manager": "8.20.0",
|
"@typescript-eslint/scope-manager": "8.23.0",
|
||||||
"@typescript-eslint/types": "8.20.0",
|
"@typescript-eslint/types": "8.23.0",
|
||||||
"@typescript-eslint/typescript-estree": "8.20.0"
|
"@typescript-eslint/typescript-estree": "8.23.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
@@ -1660,13 +1660,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/visitor-keys": {
|
"node_modules/@typescript-eslint/visitor-keys": {
|
||||||
"version": "8.20.0",
|
"version": "8.23.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.20.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.23.0.tgz",
|
||||||
"integrity": "sha512-v/BpkeeYAsPkKCkR8BDwcno0llhzWVqPOamQrAEMdpZav2Y9OVjd9dwJyBLJWwf335B5DmlifECIkZRJCaGaHA==",
|
"integrity": "sha512-oWWhcWDLwDfu++BGTZcmXWqpwtkwb5o7fxUIGksMQQDSdPW9prsSnfIOZMlsj4vBOSrcnjIUZMiIjODgGosFhQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/types": "8.20.0",
|
"@typescript-eslint/types": "8.23.0",
|
||||||
"eslint-visitor-keys": "^4.2.0"
|
"eslint-visitor-keys": "^4.2.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -1691,9 +1691,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vitest/coverage-v8": {
|
"node_modules/@vitest/coverage-v8": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.0.5.tgz",
|
||||||
"integrity": "sha512-uVbJ/xhImdNtzPnLyxCZJMTeTIYdgcC2nWtBBBpR1H6z0w8m7D+9/zrDIx2nNxgMg9r+X8+RY2qVpUDeW2b3nw==",
|
"integrity": "sha512-zOOWIsj5fHh3jjGwQg+P+J1FW3s4jBu1Zqga0qW60yutsBtqEqNEJKWYh7cYn1yGD+1bdPsPdC/eL4eVK56xMg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -1714,8 +1714,8 @@
|
|||||||
"url": "https://opencollective.com/vitest"
|
"url": "https://opencollective.com/vitest"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@vitest/browser": "3.0.3",
|
"@vitest/browser": "3.0.5",
|
||||||
"vitest": "3.0.3"
|
"vitest": "3.0.5"
|
||||||
},
|
},
|
||||||
"peerDependenciesMeta": {
|
"peerDependenciesMeta": {
|
||||||
"@vitest/browser": {
|
"@vitest/browser": {
|
||||||
@@ -1724,14 +1724,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vitest/expect": {
|
"node_modules/@vitest/expect": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.5.tgz",
|
||||||
"integrity": "sha512-SbRCHU4qr91xguu+dH3RUdI5dC86zm8aZWydbp961aIR7G8OYNN6ZiayFuf9WAngRbFOfdrLHCGgXTj3GtoMRQ==",
|
"integrity": "sha512-nNIOqupgZ4v5jWuQx2DSlHLEs7Q4Oh/7AYwNyE+k0UQzG7tSmjPXShUikn1mpNGzYEN2jJbTvLejwShMitovBA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vitest/spy": "3.0.3",
|
"@vitest/spy": "3.0.5",
|
||||||
"@vitest/utils": "3.0.3",
|
"@vitest/utils": "3.0.5",
|
||||||
"chai": "^5.1.2",
|
"chai": "^5.1.2",
|
||||||
"tinyrainbow": "^2.0.0"
|
"tinyrainbow": "^2.0.0"
|
||||||
},
|
},
|
||||||
@@ -1740,13 +1740,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vitest/mocker": {
|
"node_modules/@vitest/mocker": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.5.tgz",
|
||||||
"integrity": "sha512-XT2XBc4AN9UdaxJAeIlcSZ0ILi/GzmG5G8XSly4gaiqIvPV3HMTSIDZWJVX6QRJ0PX1m+W8Cy0K9ByXNb/bPIA==",
|
"integrity": "sha512-CLPNBFBIE7x6aEGbIjaQAX03ZZlBMaWwAjBdMkIf/cAn6xzLTiM3zYqO/WAbieEjsAZir6tO71mzeHZoodThvw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vitest/spy": "3.0.3",
|
"@vitest/spy": "3.0.5",
|
||||||
"estree-walker": "^3.0.3",
|
"estree-walker": "^3.0.3",
|
||||||
"magic-string": "^0.30.17"
|
"magic-string": "^0.30.17"
|
||||||
},
|
},
|
||||||
@@ -1767,9 +1767,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vitest/pretty-format": {
|
"node_modules/@vitest/pretty-format": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.5.tgz",
|
||||||
"integrity": "sha512-gCrM9F7STYdsDoNjGgYXKPq4SkSxwwIU5nkaQvdUxiQ0EcNlez+PdKOVIsUJvh9P9IeIFmjn4IIREWblOBpP2Q==",
|
"integrity": "sha512-CjUtdmpOcm4RVtB+up8r2vVDLR16Mgm/bYdkGFe3Yj/scRfCpbSi2W/BDSDcFK7ohw8UXvjMbOp9H4fByd/cOA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -1780,38 +1780,38 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vitest/runner": {
|
"node_modules/@vitest/runner": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.5.tgz",
|
||||||
"integrity": "sha512-Rgi2kOAk5ZxWZlwPguRJFOBmWs6uvvyAAR9k3MvjRvYrG7xYvKChZcmnnpJCS98311CBDMqsW9MzzRFsj2gX3g==",
|
"integrity": "sha512-BAiZFityFexZQi2yN4OX3OkJC6scwRo8EhRB0Z5HIGGgd2q+Nq29LgHU/+ovCtd0fOfXj5ZI6pwdlUmC5bpi8A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vitest/utils": "3.0.3",
|
"@vitest/utils": "3.0.5",
|
||||||
"pathe": "^2.0.1"
|
"pathe": "^2.0.2"
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://opencollective.com/vitest"
|
"url": "https://opencollective.com/vitest"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vitest/snapshot": {
|
"node_modules/@vitest/snapshot": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.5.tgz",
|
||||||
"integrity": "sha512-kNRcHlI4txBGztuJfPEJ68VezlPAXLRT1u5UCx219TU3kOG2DplNxhWLwDf2h6emwmTPogzLnGVwP6epDaJN6Q==",
|
"integrity": "sha512-GJPZYcd7v8QNUJ7vRvLDmRwl+a1fGg4T/54lZXe+UOGy47F9yUfE18hRCtXL5aHN/AONu29NGzIXSVFh9K0feA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vitest/pretty-format": "3.0.3",
|
"@vitest/pretty-format": "3.0.5",
|
||||||
"magic-string": "^0.30.17",
|
"magic-string": "^0.30.17",
|
||||||
"pathe": "^2.0.1"
|
"pathe": "^2.0.2"
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://opencollective.com/vitest"
|
"url": "https://opencollective.com/vitest"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vitest/spy": {
|
"node_modules/@vitest/spy": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.5.tgz",
|
||||||
"integrity": "sha512-7/dgux8ZBbF7lEIKNnEqQlyRaER9nkAL9eTmdKJkDO3hS8p59ATGwKOCUDHcBLKr7h/oi/6hP+7djQk8049T2A==",
|
"integrity": "sha512-5fOzHj0WbUNqPK6blI/8VzZdkBlQLnT25knX0r4dbZI9qoZDf3qAdjoMmDcLG5A83W6oUUFJgUd0EYBc2P5xqg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -1822,13 +1822,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vitest/utils": {
|
"node_modules/@vitest/utils": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.5.tgz",
|
||||||
"integrity": "sha512-f+s8CvyzPtMFY1eZKkIHGhPsQgYo5qCm6O8KZoim9qm1/jT64qBgGpO5tHscNH6BzRHM+edLNOP+3vO8+8pE/A==",
|
"integrity": "sha512-N9AX0NUoUtVwKwy21JtwzaqR5L5R5A99GAbrHfCCXK1lp593i/3AZAXhSP43wRQuxYsflrdzEfXZFo1reR1Nkg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vitest/pretty-format": "3.0.3",
|
"@vitest/pretty-format": "3.0.5",
|
||||||
"loupe": "^3.1.2",
|
"loupe": "^3.1.2",
|
||||||
"tinyrainbow": "^2.0.0"
|
"tinyrainbow": "^2.0.0"
|
||||||
},
|
},
|
||||||
@@ -2334,9 +2334,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint": {
|
"node_modules/eslint": {
|
||||||
"version": "9.18.0",
|
"version": "9.19.0",
|
||||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.18.0.tgz",
|
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.19.0.tgz",
|
||||||
"integrity": "sha512-+waTfRWQlSbpt3KWE+CjrPPYnbq9kfZIYUqapc0uBXyjTp8aYXZDsUH16m39Ryq3NjAVP4tjuF7KaukeqoCoaA==",
|
"integrity": "sha512-ug92j0LepKlbbEv6hD911THhoRHmbdXt2gX+VDABAW/Ir7D3nqKdv5Pf5vtlyY6HQMTEP2skXY43ueqTCWssEA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -2345,7 +2345,7 @@
|
|||||||
"@eslint/config-array": "^0.19.0",
|
"@eslint/config-array": "^0.19.0",
|
||||||
"@eslint/core": "^0.10.0",
|
"@eslint/core": "^0.10.0",
|
||||||
"@eslint/eslintrc": "^3.2.0",
|
"@eslint/eslintrc": "^3.2.0",
|
||||||
"@eslint/js": "9.18.0",
|
"@eslint/js": "9.19.0",
|
||||||
"@eslint/plugin-kit": "^0.2.5",
|
"@eslint/plugin-kit": "^0.2.5",
|
||||||
"@humanfs/node": "^0.16.6",
|
"@humanfs/node": "^0.16.6",
|
||||||
"@humanwhocodes/module-importer": "^1.0.1",
|
"@humanwhocodes/module-importer": "^1.0.1",
|
||||||
@@ -2407,9 +2407,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint-plugin-prettier": {
|
"node_modules/eslint-plugin-prettier": {
|
||||||
"version": "5.2.2",
|
"version": "5.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.3.tgz",
|
||||||
"integrity": "sha512-1yI3/hf35wmlq66C8yOyrujQnel+v5l1Vop5Cl2I6ylyNTT1JbuUUnV3/41PzwTzcyDp/oF0jWE3HXvcH5AQOQ==",
|
"integrity": "sha512-qJ+y0FfCp/mQYQ/vWQ3s7eUlFEL4PyKfAJxsnYTJ4YT73nsJBWqmEpFryxV9OeUiqmsTsYJ5Y+KDNaeP31wrRw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -2685,9 +2685,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/fastq": {
|
"node_modules/fastq": {
|
||||||
"version": "1.18.0",
|
"version": "1.19.0",
|
||||||
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.18.0.tgz",
|
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.0.tgz",
|
||||||
"integrity": "sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==",
|
"integrity": "sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA==",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"reusify": "^1.0.4"
|
"reusify": "^1.0.4"
|
||||||
@@ -3180,9 +3180,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/loupe": {
|
"node_modules/loupe": {
|
||||||
"version": "3.1.2",
|
"version": "3.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.3.tgz",
|
||||||
"integrity": "sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==",
|
"integrity": "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
@@ -3285,9 +3285,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/mock-fs": {
|
"node_modules/mock-fs": {
|
||||||
"version": "5.4.1",
|
"version": "5.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-5.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-5.5.0.tgz",
|
||||||
"integrity": "sha512-sz/Q8K1gXXXHR+qr0GZg2ysxCRr323kuN10O7CtQjraJsFDJ4SJ+0I5MzALz7aRp9lHk8Cc/YdsT95h9Ka1aFw==",
|
"integrity": "sha512-d/P1M/RacgM3dB0sJ8rjeRNXxtapkPCUnMGmIN0ixJ16F/E4GUZCvWcSGfWGz8eaXYvn1s9baUwNjI4LOPEjiA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -4166,9 +4166,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/ts-api-utils": {
|
"node_modules/ts-api-utils": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.1.tgz",
|
||||||
"integrity": "sha512-xCt/TOAc+EOHS1XPnijD3/yzpH6qg2xppZO1YDqGoVsNXfQfzHpOdNuXwrwOU8u4ITXJyDCTyt8w5g1sZv9ynQ==",
|
"integrity": "sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -4288,15 +4288,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vite": {
|
"node_modules/vite": {
|
||||||
"version": "6.0.11",
|
"version": "6.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/vite/-/vite-6.0.11.tgz",
|
"resolved": "https://registry.npmjs.org/vite/-/vite-6.1.0.tgz",
|
||||||
"integrity": "sha512-4VL9mQPKoHy4+FE0NnRE/kbY51TOfaknxAjt3fJbGJxhIpBZiqVzlZDEesWWsuREXHwNdAoOFZ9MkPEVXczHwg==",
|
"integrity": "sha512-RjjMipCKVoR4hVfPY6GQTgveinjNuyLw+qruksLDvA5ktI1150VmcMBKmQaEWJhg/j6Uaf6dNCNA0AfdzUb/hQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"esbuild": "^0.24.2",
|
"esbuild": "^0.24.2",
|
||||||
"postcss": "^8.4.49",
|
"postcss": "^8.5.1",
|
||||||
"rollup": "^4.23.0"
|
"rollup": "^4.30.1"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"vite": "bin/vite.js"
|
"vite": "bin/vite.js"
|
||||||
@@ -4360,16 +4360,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vite-node": {
|
"node_modules/vite-node": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.5.tgz",
|
||||||
"integrity": "sha512-0sQcwhwAEw/UJGojbhOrnq3HtiZ3tC7BzpAa0lx3QaTX0S3YX70iGcik25UBdB96pmdwjyY2uyKNYruxCDmiEg==",
|
"integrity": "sha512-02JEJl7SbtwSDJdYS537nU6l+ktdvcREfLksk/NDAqtdKWGqHl+joXzEubHROmS3E6pip+Xgu2tFezMu75jH7A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cac": "^6.7.14",
|
"cac": "^6.7.14",
|
||||||
"debug": "^4.4.0",
|
"debug": "^4.4.0",
|
||||||
"es-module-lexer": "^1.6.0",
|
"es-module-lexer": "^1.6.0",
|
||||||
"pathe": "^2.0.1",
|
"pathe": "^2.0.2",
|
||||||
"vite": "^5.0.0 || ^6.0.0"
|
"vite": "^5.0.0 || ^6.0.0"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
@@ -4403,31 +4403,31 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vitest": {
|
"node_modules/vitest": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.5.tgz",
|
||||||
"integrity": "sha512-dWdwTFUW9rcnL0LyF2F+IfvNQWB0w9DERySCk8VMG75F8k25C7LsZoh6XfCjPvcR8Nb+Lqi9JKr6vnzH7HSrpQ==",
|
"integrity": "sha512-4dof+HvqONw9bvsYxtkfUp2uHsTN9bV2CZIi1pWgoFpL1Lld8LA1ka9q/ONSsoScAKG7NVGf2stJTI7XRkXb2Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vitest/expect": "3.0.3",
|
"@vitest/expect": "3.0.5",
|
||||||
"@vitest/mocker": "3.0.3",
|
"@vitest/mocker": "3.0.5",
|
||||||
"@vitest/pretty-format": "^3.0.3",
|
"@vitest/pretty-format": "^3.0.5",
|
||||||
"@vitest/runner": "3.0.3",
|
"@vitest/runner": "3.0.5",
|
||||||
"@vitest/snapshot": "3.0.3",
|
"@vitest/snapshot": "3.0.5",
|
||||||
"@vitest/spy": "3.0.3",
|
"@vitest/spy": "3.0.5",
|
||||||
"@vitest/utils": "3.0.3",
|
"@vitest/utils": "3.0.5",
|
||||||
"chai": "^5.1.2",
|
"chai": "^5.1.2",
|
||||||
"debug": "^4.4.0",
|
"debug": "^4.4.0",
|
||||||
"expect-type": "^1.1.0",
|
"expect-type": "^1.1.0",
|
||||||
"magic-string": "^0.30.17",
|
"magic-string": "^0.30.17",
|
||||||
"pathe": "^2.0.1",
|
"pathe": "^2.0.2",
|
||||||
"std-env": "^3.8.0",
|
"std-env": "^3.8.0",
|
||||||
"tinybench": "^2.9.0",
|
"tinybench": "^2.9.0",
|
||||||
"tinyexec": "^0.3.2",
|
"tinyexec": "^0.3.2",
|
||||||
"tinypool": "^1.0.2",
|
"tinypool": "^1.0.2",
|
||||||
"tinyrainbow": "^2.0.0",
|
"tinyrainbow": "^2.0.0",
|
||||||
"vite": "^5.0.0 || ^6.0.0",
|
"vite": "^5.0.0 || ^6.0.0",
|
||||||
"vite-node": "3.0.3",
|
"vite-node": "3.0.5",
|
||||||
"why-is-node-running": "^2.3.0"
|
"why-is-node-running": "^2.3.0"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
@@ -4441,9 +4441,10 @@
|
|||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@edge-runtime/vm": "*",
|
"@edge-runtime/vm": "*",
|
||||||
|
"@types/debug": "^4.1.12",
|
||||||
"@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
|
"@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
|
||||||
"@vitest/browser": "3.0.3",
|
"@vitest/browser": "3.0.5",
|
||||||
"@vitest/ui": "3.0.3",
|
"@vitest/ui": "3.0.5",
|
||||||
"happy-dom": "*",
|
"happy-dom": "*",
|
||||||
"jsdom": "*"
|
"jsdom": "*"
|
||||||
},
|
},
|
||||||
@@ -4451,6 +4452,9 @@
|
|||||||
"@edge-runtime/vm": {
|
"@edge-runtime/vm": {
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
|
"@types/debug": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
"@types/node": {
|
"@types/node": {
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
|
|||||||
+1
-1
@@ -20,7 +20,7 @@
|
|||||||
"@types/cli-progress": "^3.11.0",
|
"@types/cli-progress": "^3.11.0",
|
||||||
"@types/lodash-es": "^4.17.12",
|
"@types/lodash-es": "^4.17.12",
|
||||||
"@types/mock-fs": "^4.13.1",
|
"@types/mock-fs": "^4.13.1",
|
||||||
"@types/node": "^22.10.9",
|
"@types/node": "^22.13.1",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.15.0",
|
"@typescript-eslint/eslint-plugin": "^8.15.0",
|
||||||
"@typescript-eslint/parser": "^8.15.0",
|
"@typescript-eslint/parser": "^8.15.0",
|
||||||
"@vitest/coverage-v8": "^3.0.0",
|
"@vitest/coverage-v8": "^3.0.0",
|
||||||
|
|||||||
@@ -77,9 +77,7 @@ docker start immich_postgres # Start Postgres server
|
|||||||
sleep 10 # Wait for Postgres server to start up
|
sleep 10 # Wait for Postgres server to start up
|
||||||
docker exec -it immich_postgres bash # Enter the Docker shell and run the following command
|
docker exec -it immich_postgres bash # Enter the Docker shell and run the following command
|
||||||
# Check the database user if you deviated from the default. If your backup ends in `.gz`, replace `cat` with `gunzip`
|
# Check the database user if you deviated from the default. If your backup ends in `.gz`, replace `cat` with `gunzip`
|
||||||
cat < "/dump.sql" \
|
cat < "/dump.sql" | sed "s/SELECT pg_catalog.set_config('search_path', '', false);/SELECT pg_catalog.set_config('search_path', 'public, pg_catalog', true);/g" | psql --dbname=postgres --username=<DB_USERNAME>
|
||||||
| sed "s/SELECT pg_catalog.set_config('search_path', '', false);/SELECT pg_catalog.set_config('search_path', 'public, pg_catalog', true);/g" \
|
|
||||||
| psql --dbname=postgres --username=<DB_USERNAME> # Restore Backup
|
|
||||||
exit # Exit the Docker shell
|
exit # Exit the Docker shell
|
||||||
docker compose up -d # Start remainder of Immich apps
|
docker compose up -d # Start remainder of Immich apps
|
||||||
```
|
```
|
||||||
|
|||||||
Generated
+444
-358
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -25,7 +25,7 @@
|
|||||||
"@immich/sdk": "file:../open-api/typescript-sdk",
|
"@immich/sdk": "file:../open-api/typescript-sdk",
|
||||||
"@playwright/test": "^1.44.1",
|
"@playwright/test": "^1.44.1",
|
||||||
"@types/luxon": "^3.4.2",
|
"@types/luxon": "^3.4.2",
|
||||||
"@types/node": "^22.10.9",
|
"@types/node": "^22.13.1",
|
||||||
"@types/oidc-provider": "^8.5.1",
|
"@types/oidc-provider": "^8.5.1",
|
||||||
"@types/pg": "^8.11.0",
|
"@types/pg": "^8.11.0",
|
||||||
"@types/pngjs": "^6.0.4",
|
"@types/pngjs": "^6.0.4",
|
||||||
|
|||||||
@@ -298,6 +298,7 @@ describe('/libraries', () => {
|
|||||||
expect(status).toBe(204);
|
expect(status).toBe(204);
|
||||||
|
|
||||||
await utils.waitForQueueFinish(admin.accessToken, 'library');
|
await utils.waitForQueueFinish(admin.accessToken, 'library');
|
||||||
|
await utils.waitForQueueFinish(admin.accessToken, 'metadataExtraction');
|
||||||
|
|
||||||
const { assets } = await utils.searchAssets(admin.accessToken, {
|
const { assets } = await utils.searchAssets(admin.accessToken, {
|
||||||
originalPath: `${testAssetDirInternal}/temp/directoryA/assetA.png`,
|
originalPath: `${testAssetDirInternal}/temp/directoryA/assetA.png`,
|
||||||
|
|||||||
@@ -602,6 +602,8 @@
|
|||||||
"enable": "Enable",
|
"enable": "Enable",
|
||||||
"enabled": "Enabled",
|
"enabled": "Enabled",
|
||||||
"end_date": "End date",
|
"end_date": "End date",
|
||||||
|
"rotate_left": "Rotate left",
|
||||||
|
"rotate_right": "Rotate right",
|
||||||
"error": "Error",
|
"error": "Error",
|
||||||
"error_loading_image": "Error loading image",
|
"error_loading_image": "Error loading image",
|
||||||
"error_title": "Error - Something went wrong",
|
"error_title": "Error - Something went wrong",
|
||||||
@@ -644,6 +646,7 @@
|
|||||||
"quota_higher_than_disk_size": "You set a quota higher than the disk size",
|
"quota_higher_than_disk_size": "You set a quota higher than the disk size",
|
||||||
"repair_unable_to_check_items": "Unable to check {count, select, one {item} other {items}}",
|
"repair_unable_to_check_items": "Unable to check {count, select, one {item} other {items}}",
|
||||||
"unable_to_add_album_users": "Unable to add users to album",
|
"unable_to_add_album_users": "Unable to add users to album",
|
||||||
|
"unable_to_rotate_image": "Unable to rotate image",
|
||||||
"unable_to_add_assets_to_shared_link": "Unable to add assets to shared link",
|
"unable_to_add_assets_to_shared_link": "Unable to add assets to shared link",
|
||||||
"unable_to_add_comment": "Unable to add comment",
|
"unable_to_add_comment": "Unable to add comment",
|
||||||
"unable_to_add_exclusion_pattern": "Unable to add exclusion pattern",
|
"unable_to_add_exclusion_pattern": "Unable to add exclusion pattern",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
ARG DEVICE=cpu
|
ARG DEVICE=cpu
|
||||||
|
|
||||||
FROM python:3.11-bookworm@sha256:adb581d8ed80edd03efd4dcad66db115b9ce8de8522b01720b9f3e6146f0884c AS builder-cpu
|
FROM python:3.11-bookworm@sha256:14b4620f59a90f163dfa6bd252b68743f9a41d494a9fde935f9d7669d98094bb AS builder-cpu
|
||||||
|
|
||||||
FROM builder-cpu AS builder-openvino
|
FROM builder-cpu AS builder-openvino
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@ RUN python3 -m venv /opt/venv
|
|||||||
COPY poetry.lock pyproject.toml ./
|
COPY poetry.lock pyproject.toml ./
|
||||||
RUN poetry install --sync --no-interaction --no-ansi --no-root --with ${DEVICE} --without dev
|
RUN poetry install --sync --no-interaction --no-ansi --no-root --with ${DEVICE} --without dev
|
||||||
|
|
||||||
FROM python:3.11-slim-bookworm@sha256:6ed5bff4d7d377e2a27d9285553b8c21cfccc4f00881de1b24c9bc8d90016e82 AS prod-cpu
|
FROM python:3.11-slim-bookworm@sha256:42420f737ba91d509fc60d5ed65ed0492678a90c561e1fa08786ae8ba8b52eda AS prod-cpu
|
||||||
|
|
||||||
FROM prod-cpu AS prod-openvino
|
FROM prod-cpu AS prod-openvino
|
||||||
|
|
||||||
|
|||||||
Generated
+156
-158
@@ -758,23 +758,23 @@ test = ["pytest (>=6)"]
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fastapi"
|
name = "fastapi"
|
||||||
version = "0.115.6"
|
version = "0.115.8"
|
||||||
description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production"
|
description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
{file = "fastapi-0.115.6-py3-none-any.whl", hash = "sha256:e9240b29e36fa8f4bb7290316988e90c381e5092e0cbe84e7818cc3713bcf305"},
|
{file = "fastapi-0.115.8-py3-none-any.whl", hash = "sha256:753a96dd7e036b34eeef8babdfcfe3f28ff79648f86551eb36bfc1b0bf4a8cbf"},
|
||||||
{file = "fastapi-0.115.6.tar.gz", hash = "sha256:9ec46f7addc14ea472958a96aae5b5de65f39721a46aaf5705c480d9a8b76654"},
|
{file = "fastapi-0.115.8.tar.gz", hash = "sha256:0ce9111231720190473e222cdf0f07f7206ad7e53ea02beb1d2dc36e2f0741e9"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<2.1.0 || >2.1.0,<3.0.0"
|
pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<2.1.0 || >2.1.0,<3.0.0"
|
||||||
starlette = ">=0.40.0,<0.42.0"
|
starlette = ">=0.40.0,<0.46.0"
|
||||||
typing-extensions = ">=4.8.0"
|
typing-extensions = ">=4.8.0"
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
all = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.5)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.7)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"]
|
all = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.5)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=3.1.5)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.18)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"]
|
||||||
standard = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.5)", "httpx (>=0.23.0)", "jinja2 (>=2.11.2)", "python-multipart (>=0.0.7)", "uvicorn[standard] (>=0.12.0)"]
|
standard = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.5)", "httpx (>=0.23.0)", "jinja2 (>=3.1.5)", "python-multipart (>=0.0.18)", "uvicorn[standard] (>=0.12.0)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "filelock"
|
name = "filelock"
|
||||||
@@ -1331,13 +1331,13 @@ zstd = ["zstandard (>=0.18.0)"]
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "huggingface-hub"
|
name = "huggingface-hub"
|
||||||
version = "0.27.1"
|
version = "0.28.1"
|
||||||
description = "Client library to download and publish models, datasets and other repos on the huggingface.co hub"
|
description = "Client library to download and publish models, datasets and other repos on the huggingface.co hub"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8.0"
|
python-versions = ">=3.8.0"
|
||||||
files = [
|
files = [
|
||||||
{file = "huggingface_hub-0.27.1-py3-none-any.whl", hash = "sha256:1c5155ca7d60b60c2e2fc38cbb3ffb7f7c3adf48f824015b219af9061771daec"},
|
{file = "huggingface_hub-0.28.1-py3-none-any.whl", hash = "sha256:aa6b9a3ffdae939b72c464dbb0d7f99f56e649b55c3d52406f49e0a5a620c0a7"},
|
||||||
{file = "huggingface_hub-0.27.1.tar.gz", hash = "sha256:c004463ca870283909d715d20f066ebd6968c2207dae9393fdffb3c1d4d8f98b"},
|
{file = "huggingface_hub-0.28.1.tar.gz", hash = "sha256:893471090c98e3b6efbdfdacafe4052b20b84d59866fb6f54c33d9af18c303ae"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
@@ -1350,13 +1350,13 @@ tqdm = ">=4.42.1"
|
|||||||
typing-extensions = ">=3.7.4.3"
|
typing-extensions = ">=3.7.4.3"
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
all = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio (>=4.0.0)", "jedi", "libcst (==1.4.0)", "mypy (==1.5.1)", "numpy", "pytest (>=8.1.1,<8.2.2)", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-mock", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.5.0)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"]
|
all = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio (>=4.0.0)", "jedi", "libcst (==1.4.0)", "mypy (==1.5.1)", "numpy", "pytest (>=8.1.1,<8.2.2)", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-mock", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.9.0)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"]
|
||||||
cli = ["InquirerPy (==0.3.4)"]
|
cli = ["InquirerPy (==0.3.4)"]
|
||||||
dev = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio (>=4.0.0)", "jedi", "libcst (==1.4.0)", "mypy (==1.5.1)", "numpy", "pytest (>=8.1.1,<8.2.2)", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-mock", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.5.0)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"]
|
dev = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio (>=4.0.0)", "jedi", "libcst (==1.4.0)", "mypy (==1.5.1)", "numpy", "pytest (>=8.1.1,<8.2.2)", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-mock", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.9.0)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"]
|
||||||
fastai = ["fastai (>=2.4)", "fastcore (>=1.3.27)", "toml"]
|
fastai = ["fastai (>=2.4)", "fastcore (>=1.3.27)", "toml"]
|
||||||
hf-transfer = ["hf-transfer (>=0.1.4)"]
|
hf-transfer = ["hf-transfer (>=0.1.4)"]
|
||||||
inference = ["aiohttp"]
|
inference = ["aiohttp"]
|
||||||
quality = ["libcst (==1.4.0)", "mypy (==1.5.1)", "ruff (>=0.5.0)"]
|
quality = ["libcst (==1.4.0)", "mypy (==1.5.1)", "ruff (>=0.9.0)"]
|
||||||
tensorflow = ["graphviz", "pydot", "tensorflow"]
|
tensorflow = ["graphviz", "pydot", "tensorflow"]
|
||||||
tensorflow-testing = ["keras (<3.0)", "tensorflow"]
|
tensorflow-testing = ["keras (<3.0)", "tensorflow"]
|
||||||
testing = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio (>=4.0.0)", "jedi", "numpy", "pytest (>=8.1.1,<8.2.2)", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-mock", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "soundfile", "urllib3 (<2.0)"]
|
testing = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio (>=4.0.0)", "jedi", "numpy", "pytest (>=8.1.1,<8.2.2)", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-mock", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "soundfile", "urllib3 (<2.0)"]
|
||||||
@@ -1625,13 +1625,13 @@ test = ["pytest (>=7.4)", "pytest-cov (>=4.1)"]
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "locust"
|
name = "locust"
|
||||||
version = "2.32.6"
|
version = "2.32.9"
|
||||||
description = "Developer-friendly load testing framework"
|
description = "Developer-friendly load testing framework"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.9"
|
python-versions = ">=3.9"
|
||||||
files = [
|
files = [
|
||||||
{file = "locust-2.32.6-py3-none-any.whl", hash = "sha256:d5c0e4f73134415d250087034431cf3ea42ca695d3dee7f10812287cacb6c4ef"},
|
{file = "locust-2.32.9-py3-none-any.whl", hash = "sha256:d9447c26d2bbaec5a0ace7cadefa1a31820ed392234257b309965a43d5e8d26f"},
|
||||||
{file = "locust-2.32.6.tar.gz", hash = "sha256:6600cc308398e724764aacc56ccddf6cfcd0127c4c92dedd5c4979dd37ef5b15"},
|
{file = "locust-2.32.9.tar.gz", hash = "sha256:4c297afa5cdc3de15dfa79279576e5f33c1d69dd70006b51d079dcbd212201cc"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
@@ -1649,8 +1649,8 @@ psutil = ">=5.9.1"
|
|||||||
pywin32 = {version = "*", markers = "sys_platform == \"win32\""}
|
pywin32 = {version = "*", markers = "sys_platform == \"win32\""}
|
||||||
pyzmq = ">=25.0.0"
|
pyzmq = ">=25.0.0"
|
||||||
requests = [
|
requests = [
|
||||||
{version = ">=2.32.2", markers = "python_full_version > \"3.11.0\""},
|
|
||||||
{version = ">=2.26.0", markers = "python_full_version <= \"3.11.0\""},
|
{version = ">=2.26.0", markers = "python_full_version <= \"3.11.0\""},
|
||||||
|
{version = ">=2.32.2", markers = "python_full_version > \"3.11.0\""},
|
||||||
]
|
]
|
||||||
setuptools = ">=70.0.0"
|
setuptools = ">=70.0.0"
|
||||||
tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
|
tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
|
||||||
@@ -1893,49 +1893,43 @@ files = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mypy"
|
name = "mypy"
|
||||||
version = "1.14.1"
|
version = "1.15.0"
|
||||||
description = "Optional static typing for Python"
|
description = "Optional static typing for Python"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.9"
|
||||||
files = [
|
files = [
|
||||||
{file = "mypy-1.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:52686e37cf13d559f668aa398dd7ddf1f92c5d613e4f8cb262be2fb4fedb0fcb"},
|
{file = "mypy-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:979e4e1a006511dacf628e36fadfecbcc0160a8af6ca7dad2f5025529e082c13"},
|
||||||
{file = "mypy-1.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1fb545ca340537d4b45d3eecdb3def05e913299ca72c290326be19b3804b39c0"},
|
{file = "mypy-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c4bb0e1bd29f7d34efcccd71cf733580191e9a264a2202b0239da95984c5b559"},
|
||||||
{file = "mypy-1.14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:90716d8b2d1f4cd503309788e51366f07c56635a3309b0f6a32547eaaa36a64d"},
|
{file = "mypy-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:be68172e9fd9ad8fb876c6389f16d1c1b5f100ffa779f77b1fb2176fcc9ab95b"},
|
||||||
{file = "mypy-1.14.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2ae753f5c9fef278bcf12e1a564351764f2a6da579d4a81347e1d5a15819997b"},
|
{file = "mypy-1.15.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c7be1e46525adfa0d97681432ee9fcd61a3964c2446795714699a998d193f1a3"},
|
||||||
{file = "mypy-1.14.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e0fe0f5feaafcb04505bcf439e991c6d8f1bf8b15f12b05feeed96e9e7bf1427"},
|
{file = "mypy-1.15.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2e2c2e6d3593f6451b18588848e66260ff62ccca522dd231cd4dd59b0160668b"},
|
||||||
{file = "mypy-1.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:7d54bd85b925e501c555a3227f3ec0cfc54ee8b6930bd6141ec872d1c572f81f"},
|
{file = "mypy-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:6983aae8b2f653e098edb77f893f7b6aca69f6cffb19b2cc7443f23cce5f4828"},
|
||||||
{file = "mypy-1.14.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f995e511de847791c3b11ed90084a7a0aafdc074ab88c5a9711622fe4751138c"},
|
{file = "mypy-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2922d42e16d6de288022e5ca321cd0618b238cfc5570e0263e5ba0a77dbef56f"},
|
||||||
{file = "mypy-1.14.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d64169ec3b8461311f8ce2fd2eb5d33e2d0f2c7b49116259c51d0d96edee48d1"},
|
{file = "mypy-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2ee2d57e01a7c35de00f4634ba1bbf015185b219e4dc5909e281016df43f5ee5"},
|
||||||
{file = "mypy-1.14.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ba24549de7b89b6381b91fbc068d798192b1b5201987070319889e93038967a8"},
|
{file = "mypy-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:973500e0774b85d9689715feeffcc980193086551110fd678ebe1f4342fb7c5e"},
|
||||||
{file = "mypy-1.14.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:183cf0a45457d28ff9d758730cd0210419ac27d4d3f285beda038c9083363b1f"},
|
{file = "mypy-1.15.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a95fb17c13e29d2d5195869262f8125dfdb5c134dc8d9a9d0aecf7525b10c2c"},
|
||||||
{file = "mypy-1.14.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f2a0ecc86378f45347f586e4163d1769dd81c5a223d577fe351f26b179e148b1"},
|
{file = "mypy-1.15.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1905f494bfd7d85a23a88c5d97840888a7bd516545fc5aaedff0267e0bb54e2f"},
|
||||||
{file = "mypy-1.14.1-cp311-cp311-win_amd64.whl", hash = "sha256:ad3301ebebec9e8ee7135d8e3109ca76c23752bac1e717bc84cd3836b4bf3eae"},
|
{file = "mypy-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:c9817fa23833ff189db061e6d2eff49b2f3b6ed9856b4a0a73046e41932d744f"},
|
||||||
{file = "mypy-1.14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:30ff5ef8519bbc2e18b3b54521ec319513a26f1bba19a7582e7b1f58a6e69f14"},
|
{file = "mypy-1.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:aea39e0583d05124836ea645f412e88a5c7d0fd77a6d694b60d9b6b2d9f184fd"},
|
||||||
{file = "mypy-1.14.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cb9f255c18052343c70234907e2e532bc7e55a62565d64536dbc7706a20b78b9"},
|
{file = "mypy-1.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2f2147ab812b75e5b5499b01ade1f4a81489a147c01585cda36019102538615f"},
|
||||||
{file = "mypy-1.14.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b4e3413e0bddea671012b063e27591b953d653209e7a4fa5e48759cda77ca11"},
|
{file = "mypy-1.15.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce436f4c6d218a070048ed6a44c0bbb10cd2cc5e272b29e7845f6a2f57ee4464"},
|
||||||
{file = "mypy-1.14.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:553c293b1fbdebb6c3c4030589dab9fafb6dfa768995a453d8a5d3b23784af2e"},
|
{file = "mypy-1.15.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8023ff13985661b50a5928fc7a5ca15f3d1affb41e5f0a9952cb68ef090b31ee"},
|
||||||
{file = "mypy-1.14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fad79bfe3b65fe6a1efaed97b445c3d37f7be9fdc348bdb2d7cac75579607c89"},
|
{file = "mypy-1.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1124a18bc11a6a62887e3e137f37f53fbae476dc36c185d549d4f837a2a6a14e"},
|
||||||
{file = "mypy-1.14.1-cp312-cp312-win_amd64.whl", hash = "sha256:8fa2220e54d2946e94ab6dbb3ba0a992795bd68b16dc852db33028df2b00191b"},
|
{file = "mypy-1.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:171a9ca9a40cd1843abeca0e405bc1940cd9b305eaeea2dda769ba096932bb22"},
|
||||||
{file = "mypy-1.14.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:92c3ed5afb06c3a8e188cb5da4984cab9ec9a77ba956ee419c68a388b4595255"},
|
{file = "mypy-1.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:93faf3fdb04768d44bf28693293f3904bbb555d076b781ad2530214ee53e3445"},
|
||||||
{file = "mypy-1.14.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:dbec574648b3e25f43d23577309b16534431db4ddc09fda50841f1e34e64ed34"},
|
{file = "mypy-1.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:811aeccadfb730024c5d3e326b2fbe9249bb7413553f15499a4050f7c30e801d"},
|
||||||
{file = "mypy-1.14.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8c6d94b16d62eb3e947281aa7347d78236688e21081f11de976376cf010eb31a"},
|
{file = "mypy-1.15.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:98b7b9b9aedb65fe628c62a6dc57f6d5088ef2dfca37903a7d9ee374d03acca5"},
|
||||||
{file = "mypy-1.14.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d4b19b03fdf54f3c5b2fa474c56b4c13c9dbfb9a2db4370ede7ec11a2c5927d9"},
|
{file = "mypy-1.15.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c43a7682e24b4f576d93072216bf56eeff70d9140241f9edec0c104d0c515036"},
|
||||||
{file = "mypy-1.14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0c911fde686394753fff899c409fd4e16e9b294c24bfd5e1ea4675deae1ac6fd"},
|
{file = "mypy-1.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:baefc32840a9f00babd83251560e0ae1573e2f9d1b067719479bfb0e987c6357"},
|
||||||
{file = "mypy-1.14.1-cp313-cp313-win_amd64.whl", hash = "sha256:8b21525cb51671219f5307be85f7e646a153e5acc656e5cebf64bfa076c50107"},
|
{file = "mypy-1.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:b9378e2c00146c44793c98b8d5a61039a048e31f429fb0eb546d93f4b000bedf"},
|
||||||
{file = "mypy-1.14.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7084fb8f1128c76cd9cf68fe5971b37072598e7c31b2f9f95586b65c741a9d31"},
|
{file = "mypy-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e601a7fa172c2131bff456bb3ee08a88360760d0d2f8cbd7a75a65497e2df078"},
|
||||||
{file = "mypy-1.14.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8f845a00b4f420f693f870eaee5f3e2692fa84cc8514496114649cfa8fd5e2c6"},
|
{file = "mypy-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:712e962a6357634fef20412699a3655c610110e01cdaa6180acec7fc9f8513ba"},
|
||||||
{file = "mypy-1.14.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:44bf464499f0e3a2d14d58b54674dee25c031703b2ffc35064bd0df2e0fac319"},
|
{file = "mypy-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f95579473af29ab73a10bada2f9722856792a36ec5af5399b653aa28360290a5"},
|
||||||
{file = "mypy-1.14.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c99f27732c0b7dc847adb21c9d47ce57eb48fa33a17bc6d7d5c5e9f9e7ae5bac"},
|
{file = "mypy-1.15.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8f8722560a14cde92fdb1e31597760dc35f9f5524cce17836c0d22841830fd5b"},
|
||||||
{file = "mypy-1.14.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:bce23c7377b43602baa0bd22ea3265c49b9ff0b76eb315d6c34721af4cdf1d9b"},
|
{file = "mypy-1.15.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1fbb8da62dc352133d7d7ca90ed2fb0e9d42bb1a32724c287d3c76c58cbaa9c2"},
|
||||||
{file = "mypy-1.14.1-cp38-cp38-win_amd64.whl", hash = "sha256:8edc07eeade7ebc771ff9cf6b211b9a7d93687ff892150cb5692e4f4272b0837"},
|
{file = "mypy-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:d10d994b41fb3497719bbf866f227b3489048ea4bbbb5015357db306249f7980"},
|
||||||
{file = "mypy-1.14.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3888a1816d69f7ab92092f785a462944b3ca16d7c470d564165fe703b0970c35"},
|
{file = "mypy-1.15.0-py3-none-any.whl", hash = "sha256:5469affef548bd1895d86d3bf10ce2b44e33d86923c29e4d675b3e323437ea3e"},
|
||||||
{file = "mypy-1.14.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:46c756a444117c43ee984bd055db99e498bc613a70bbbc120272bd13ca579fbc"},
|
{file = "mypy-1.15.0.tar.gz", hash = "sha256:404534629d51d3efea5c800ee7c42b72a6554d6c400e6a79eafe15d11341fd43"},
|
||||||
{file = "mypy-1.14.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:27fc248022907e72abfd8e22ab1f10e903915ff69961174784a3900a8cba9ad9"},
|
|
||||||
{file = "mypy-1.14.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:499d6a72fb7e5de92218db961f1a66d5f11783f9ae549d214617edab5d4dbdbb"},
|
|
||||||
{file = "mypy-1.14.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:57961db9795eb566dc1d1b4e9139ebc4c6b0cb6e7254ecde69d1552bf7613f60"},
|
|
||||||
{file = "mypy-1.14.1-cp39-cp39-win_amd64.whl", hash = "sha256:07ba89fdcc9451f2ebb02853deb6aaaa3d2239a236669a63ab3801bbf923ef5c"},
|
|
||||||
{file = "mypy-1.14.1-py3-none-any.whl", hash = "sha256:b66a60cc4073aeb8ae00057f9c1f64d49e90f918fbcef9a977eb121da8b8f1d1"},
|
|
||||||
{file = "mypy-1.14.1.tar.gz", hash = "sha256:7ec88144fe9b510e8475ec2f5f251992690fcf89ccb4500b214b4226abcd32d6"},
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
@@ -2181,94 +2175,98 @@ files = [
|
|||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
numpy = [
|
numpy = [
|
||||||
{version = ">=1.26.0", markers = "python_version >= \"3.12\""},
|
|
||||||
{version = ">=1.23.5", markers = "python_version >= \"3.11\" and python_version < \"3.12\""},
|
{version = ">=1.23.5", markers = "python_version >= \"3.11\" and python_version < \"3.12\""},
|
||||||
{version = ">=1.21.4", markers = "python_version >= \"3.10\" and platform_system == \"Darwin\" and python_version < \"3.11\""},
|
{version = ">=1.21.4", markers = "python_version >= \"3.10\" and platform_system == \"Darwin\" and python_version < \"3.11\""},
|
||||||
{version = ">=1.21.2", markers = "platform_system != \"Darwin\" and python_version >= \"3.10\" and python_version < \"3.11\""},
|
{version = ">=1.21.2", markers = "platform_system != \"Darwin\" and python_version >= \"3.10\" and python_version < \"3.11\""},
|
||||||
|
{version = ">=1.26.0", markers = "python_version >= \"3.12\""},
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "orjson"
|
name = "orjson"
|
||||||
version = "3.10.14"
|
version = "3.10.15"
|
||||||
description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy"
|
description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
{file = "orjson-3.10.14-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:849ea7845a55f09965826e816cdc7689d6cf74fe9223d79d758c714af955bcb6"},
|
{file = "orjson-3.10.15-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:552c883d03ad185f720d0c09583ebde257e41b9521b74ff40e08b7dec4559c04"},
|
||||||
{file = "orjson-3.10.14-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5947b139dfa33f72eecc63f17e45230a97e741942955a6c9e650069305eb73d"},
|
{file = "orjson-3.10.15-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:616e3e8d438d02e4854f70bfdc03a6bcdb697358dbaa6bcd19cbe24d24ece1f8"},
|
||||||
{file = "orjson-3.10.14-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cde6d76910d3179dae70f164466692f4ea36da124d6fb1a61399ca589e81d69a"},
|
{file = "orjson-3.10.15-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7c2c79fa308e6edb0ffab0a31fd75a7841bf2a79a20ef08a3c6e3b26814c8ca8"},
|
||||||
{file = "orjson-3.10.14-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c6dfbaeb7afa77ca608a50e2770a0461177b63a99520d4928e27591b142c74b1"},
|
{file = "orjson-3.10.15-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:73cb85490aa6bf98abd20607ab5c8324c0acb48d6da7863a51be48505646c814"},
|
||||||
{file = "orjson-3.10.14-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fa45e489ef80f28ff0e5ba0a72812b8cfc7c1ef8b46a694723807d1b07c89ebb"},
|
{file = "orjson-3.10.15-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:763dadac05e4e9d2bc14938a45a2d0560549561287d41c465d3c58aec818b164"},
|
||||||
{file = "orjson-3.10.14-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f5007abfdbb1d866e2aa8990bd1c465f0f6da71d19e695fc278282be12cffa5"},
|
{file = "orjson-3.10.15-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a330b9b4734f09a623f74a7490db713695e13b67c959713b78369f26b3dee6bf"},
|
||||||
{file = "orjson-3.10.14-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1b49e2af011c84c3f2d541bb5cd1e3c7c2df672223e7e3ea608f09cf295e5f8a"},
|
{file = "orjson-3.10.15-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a61a4622b7ff861f019974f73d8165be1bd9a0855e1cad18ee167acacabeb061"},
|
||||||
{file = "orjson-3.10.14-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:164ac155109226b3a2606ee6dda899ccfbe6e7e18b5bdc3fbc00f79cc074157d"},
|
{file = "orjson-3.10.15-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:acd271247691574416b3228db667b84775c497b245fa275c6ab90dc1ffbbd2b3"},
|
||||||
{file = "orjson-3.10.14-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:6b1225024cf0ef5d15934b5ffe9baf860fe8bc68a796513f5ea4f5056de30bca"},
|
{file = "orjson-3.10.15-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:e4759b109c37f635aa5c5cc93a1b26927bfde24b254bcc0e1149a9fada253d2d"},
|
||||||
{file = "orjson-3.10.14-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:d6546e8073dc382e60fcae4a001a5a1bc46da5eab4a4878acc2d12072d6166d5"},
|
{file = "orjson-3.10.15-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:9e992fd5cfb8b9f00bfad2fd7a05a4299db2bbe92e6440d9dd2fab27655b3182"},
|
||||||
{file = "orjson-3.10.14-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:9f1d2942605c894162252d6259b0121bf1cb493071a1ea8cb35d79cb3e6ac5bc"},
|
{file = "orjson-3.10.15-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f95fb363d79366af56c3f26b71df40b9a583b07bbaaf5b317407c4d58497852e"},
|
||||||
{file = "orjson-3.10.14-cp310-cp310-win32.whl", hash = "sha256:397083806abd51cf2b3bbbf6c347575374d160331a2d33c5823e22249ad3118b"},
|
{file = "orjson-3.10.15-cp310-cp310-win32.whl", hash = "sha256:f9875f5fea7492da8ec2444839dcc439b0ef298978f311103d0b7dfd775898ab"},
|
||||||
{file = "orjson-3.10.14-cp310-cp310-win_amd64.whl", hash = "sha256:fa18f949d3183a8d468367056be989666ac2bef3a72eece0bade9cdb733b3c28"},
|
{file = "orjson-3.10.15-cp310-cp310-win_amd64.whl", hash = "sha256:17085a6aa91e1cd70ca8533989a18b5433e15d29c574582f76f821737c8d5806"},
|
||||||
{file = "orjson-3.10.14-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:f506fd666dd1ecd15a832bebc66c4df45c1902fd47526292836c339f7ba665a9"},
|
{file = "orjson-3.10.15-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:c4cc83960ab79a4031f3119cc4b1a1c627a3dc09df125b27c4201dff2af7eaa6"},
|
||||||
{file = "orjson-3.10.14-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:efe5fd254cfb0eeee13b8ef7ecb20f5d5a56ddda8a587f3852ab2cedfefdb5f6"},
|
{file = "orjson-3.10.15-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ddbeef2481d895ab8be5185f2432c334d6dec1f5d1933a9c83014d188e102cef"},
|
||||||
{file = "orjson-3.10.14-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4ddc8c866d7467f5ee2991397d2ea94bcf60d0048bdd8ca555740b56f9042725"},
|
{file = "orjson-3.10.15-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9e590a0477b23ecd5b0ac865b1b907b01b3c5535f5e8a8f6ab0e503efb896334"},
|
||||||
{file = "orjson-3.10.14-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3af8e42ae4363773658b8d578d56dedffb4f05ceeb4d1d4dd3fb504950b45526"},
|
{file = "orjson-3.10.15-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a6be38bd103d2fd9bdfa31c2720b23b5d47c6796bcb1d1b598e3924441b4298d"},
|
||||||
{file = "orjson-3.10.14-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:84dd83110503bc10e94322bf3ffab8bc49150176b49b4984dc1cce4c0a993bf9"},
|
{file = "orjson-3.10.15-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ff4f6edb1578960ed628a3b998fa54d78d9bb3e2eb2cfc5c2a09732431c678d0"},
|
||||||
{file = "orjson-3.10.14-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36f5bfc0399cd4811bf10ec7a759c7ab0cd18080956af8ee138097d5b5296a95"},
|
{file = "orjson-3.10.15-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b0482b21d0462eddd67e7fce10b89e0b6ac56570424662b685a0d6fccf581e13"},
|
||||||
{file = "orjson-3.10.14-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:868943660fb2a1e6b6b965b74430c16a79320b665b28dd4511d15ad5038d37d5"},
|
{file = "orjson-3.10.15-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bb5cc3527036ae3d98b65e37b7986a918955f85332c1ee07f9d3f82f3a6899b5"},
|
||||||
{file = "orjson-3.10.14-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:33449c67195969b1a677533dee9d76e006001213a24501333624623e13c7cc8e"},
|
{file = "orjson-3.10.15-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d569c1c462912acdd119ccbf719cf7102ea2c67dd03b99edcb1a3048651ac96b"},
|
||||||
{file = "orjson-3.10.14-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:e4c9f60f9fb0b5be66e416dcd8c9d94c3eabff3801d875bdb1f8ffc12cf86905"},
|
{file = "orjson-3.10.15-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:1e6d33efab6b71d67f22bf2962895d3dc6f82a6273a965fab762e64fa90dc399"},
|
||||||
{file = "orjson-3.10.14-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:0de4d6315cfdbd9ec803b945c23b3a68207fd47cbe43626036d97e8e9561a436"},
|
{file = "orjson-3.10.15-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:c33be3795e299f565681d69852ac8c1bc5c84863c0b0030b2b3468843be90388"},
|
||||||
{file = "orjson-3.10.14-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:83adda3db595cb1a7e2237029b3249c85afbe5c747d26b41b802e7482cb3933e"},
|
{file = "orjson-3.10.15-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:eea80037b9fae5339b214f59308ef0589fc06dc870578b7cce6d71eb2096764c"},
|
||||||
{file = "orjson-3.10.14-cp311-cp311-win32.whl", hash = "sha256:998019ef74a4997a9d741b1473533cdb8faa31373afc9849b35129b4b8ec048d"},
|
{file = "orjson-3.10.15-cp311-cp311-win32.whl", hash = "sha256:d5ac11b659fd798228a7adba3e37c010e0152b78b1982897020a8e019a94882e"},
|
||||||
{file = "orjson-3.10.14-cp311-cp311-win_amd64.whl", hash = "sha256:9d034abdd36f0f0f2240f91492684e5043d46f290525d1117712d5b8137784eb"},
|
{file = "orjson-3.10.15-cp311-cp311-win_amd64.whl", hash = "sha256:cf45e0214c593660339ef63e875f32ddd5aa3b4adc15e662cdb80dc49e194f8e"},
|
||||||
{file = "orjson-3.10.14-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:2ad4b7e367efba6dc3f119c9a0fcd41908b7ec0399a696f3cdea7ec477441b09"},
|
{file = "orjson-3.10.15-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9d11c0714fc85bfcf36ada1179400862da3288fc785c30e8297844c867d7505a"},
|
||||||
{file = "orjson-3.10.14-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f496286fc85e93ce0f71cc84fc1c42de2decf1bf494094e188e27a53694777a7"},
|
{file = "orjson-3.10.15-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dba5a1e85d554e3897fa9fe6fbcff2ed32d55008973ec9a2b992bd9a65d2352d"},
|
||||||
{file = "orjson-3.10.14-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c7f189bbfcded40e41a6969c1068ba305850ba016665be71a217918931416fbf"},
|
{file = "orjson-3.10.15-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7723ad949a0ea502df656948ddd8b392780a5beaa4c3b5f97e525191b102fff0"},
|
||||||
{file = "orjson-3.10.14-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8cc8204f0b75606869c707da331058ddf085de29558b516fc43c73ee5ee2aadb"},
|
{file = "orjson-3.10.15-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6fd9bc64421e9fe9bd88039e7ce8e58d4fead67ca88e3a4014b143cec7684fd4"},
|
||||||
{file = "orjson-3.10.14-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:deaa2899dff7f03ab667e2ec25842d233e2a6a9e333efa484dfe666403f3501c"},
|
{file = "orjson-3.10.15-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dadba0e7b6594216c214ef7894c4bd5f08d7c0135f4dd0145600be4fbcc16767"},
|
||||||
{file = "orjson-3.10.14-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f1c3ea52642c9714dc6e56de8a451a066f6d2707d273e07fe8a9cc1ba073813d"},
|
{file = "orjson-3.10.15-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b48f59114fe318f33bbaee8ebeda696d8ccc94c9e90bc27dbe72153094e26f41"},
|
||||||
{file = "orjson-3.10.14-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9d3f9ed72e7458ded9a1fb1b4d4ed4c4fdbaf82030ce3f9274b4dc1bff7ace2b"},
|
{file = "orjson-3.10.15-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:035fb83585e0f15e076759b6fedaf0abb460d1765b6a36f48018a52858443514"},
|
||||||
{file = "orjson-3.10.14-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:07520685d408a2aba514c17ccc16199ff2934f9f9e28501e676c557f454a37fe"},
|
{file = "orjson-3.10.15-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d13b7fe322d75bf84464b075eafd8e7dd9eae05649aa2a5354cfa32f43c59f17"},
|
||||||
{file = "orjson-3.10.14-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:76344269b550ea01488d19a2a369ab572c1ac4449a72e9f6ac0d70eb1cbfb953"},
|
{file = "orjson-3.10.15-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:7066b74f9f259849629e0d04db6609db4cf5b973248f455ba5d3bd58a4daaa5b"},
|
||||||
{file = "orjson-3.10.14-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e2979d0f2959990620f7e62da6cd954e4620ee815539bc57a8ae46e2dacf90e3"},
|
{file = "orjson-3.10.15-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:88dc3f65a026bd3175eb157fea994fca6ac7c4c8579fc5a86fc2114ad05705b7"},
|
||||||
{file = "orjson-3.10.14-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:03f61ca3674555adcb1aa717b9fc87ae936aa7a63f6aba90a474a88701278780"},
|
{file = "orjson-3.10.15-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b342567e5465bd99faa559507fe45e33fc76b9fb868a63f1642c6bc0735ad02a"},
|
||||||
{file = "orjson-3.10.14-cp312-cp312-win32.whl", hash = "sha256:d5075c54edf1d6ad81d4c6523ce54a748ba1208b542e54b97d8a882ecd810fd1"},
|
{file = "orjson-3.10.15-cp312-cp312-win32.whl", hash = "sha256:0a4f27ea5617828e6b58922fdbec67b0aa4bb844e2d363b9244c47fa2180e665"},
|
||||||
{file = "orjson-3.10.14-cp312-cp312-win_amd64.whl", hash = "sha256:175cafd322e458603e8ce73510a068d16b6e6f389c13f69bf16de0e843d7d406"},
|
{file = "orjson-3.10.15-cp312-cp312-win_amd64.whl", hash = "sha256:ef5b87e7aa9545ddadd2309efe6824bd3dd64ac101c15dae0f2f597911d46eaa"},
|
||||||
{file = "orjson-3.10.14-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:0905ca08a10f7e0e0c97d11359609300eb1437490a7f32bbaa349de757e2e0c7"},
|
{file = "orjson-3.10.15-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:bae0e6ec2b7ba6895198cd981b7cca95d1487d0147c8ed751e5632ad16f031a6"},
|
||||||
{file = "orjson-3.10.14-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:92d13292249f9f2a3e418cbc307a9fbbef043c65f4bd8ba1eb620bc2aaba3d15"},
|
{file = "orjson-3.10.15-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f93ce145b2db1252dd86af37d4165b6faa83072b46e3995ecc95d4b2301b725a"},
|
||||||
{file = "orjson-3.10.14-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90937664e776ad316d64251e2fa2ad69265e4443067668e4727074fe39676414"},
|
{file = "orjson-3.10.15-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7c203f6f969210128af3acae0ef9ea6aab9782939f45f6fe02d05958fe761ef9"},
|
||||||
{file = "orjson-3.10.14-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9ed3d26c4cb4f6babaf791aa46a029265850e80ec2a566581f5c2ee1a14df4f1"},
|
{file = "orjson-3.10.15-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8918719572d662e18b8af66aef699d8c21072e54b6c82a3f8f6404c1f5ccd5e0"},
|
||||||
{file = "orjson-3.10.14-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:56ee546c2bbe9599aba78169f99d1dc33301853e897dbaf642d654248280dc6e"},
|
{file = "orjson-3.10.15-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f71eae9651465dff70aa80db92586ad5b92df46a9373ee55252109bb6b703307"},
|
||||||
{file = "orjson-3.10.14-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:901e826cb2f1bdc1fcef3ef59adf0c451e8f7c0b5deb26c1a933fb66fb505eae"},
|
{file = "orjson-3.10.15-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e117eb299a35f2634e25ed120c37c641398826c2f5a3d3cc39f5993b96171b9e"},
|
||||||
{file = "orjson-3.10.14-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:26336c0d4b2d44636e1e1e6ed1002f03c6aae4a8a9329561c8883f135e9ff010"},
|
{file = "orjson-3.10.15-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:13242f12d295e83c2955756a574ddd6741c81e5b99f2bef8ed8d53e47a01e4b7"},
|
||||||
{file = "orjson-3.10.14-cp313-cp313-win32.whl", hash = "sha256:e2bc525e335a8545c4e48f84dd0328bc46158c9aaeb8a1c2276546e94540ea3d"},
|
{file = "orjson-3.10.15-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7946922ada8f3e0b7b958cc3eb22cfcf6c0df83d1fe5521b4a100103e3fa84c8"},
|
||||||
{file = "orjson-3.10.14-cp313-cp313-win_amd64.whl", hash = "sha256:eca04dfd792cedad53dc9a917da1a522486255360cb4e77619343a20d9f35364"},
|
{file = "orjson-3.10.15-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:b7155eb1623347f0f22c38c9abdd738b287e39b9982e1da227503387b81b34ca"},
|
||||||
{file = "orjson-3.10.14-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9a0fba3b8a587a54c18585f077dcab6dd251c170d85cfa4d063d5746cd595a0f"},
|
{file = "orjson-3.10.15-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:208beedfa807c922da4e81061dafa9c8489c6328934ca2a562efa707e049e561"},
|
||||||
{file = "orjson-3.10.14-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:175abf3d20e737fec47261d278f95031736a49d7832a09ab684026528c4d96db"},
|
{file = "orjson-3.10.15-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eca81f83b1b8c07449e1d6ff7074e82e3fd6777e588f1a6632127f286a968825"},
|
||||||
{file = "orjson-3.10.14-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:29ca1a93e035d570e8b791b6c0feddd403c6a5388bfe870bf2aa6bba1b9d9b8e"},
|
{file = "orjson-3.10.15-cp313-cp313-win32.whl", hash = "sha256:c03cd6eea1bd3b949d0d007c8d57049aa2b39bd49f58b4b2af571a5d3833d890"},
|
||||||
{file = "orjson-3.10.14-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f77202c80e8ab5a1d1e9faf642343bee5aaf332061e1ada4e9147dbd9eb00c46"},
|
{file = "orjson-3.10.15-cp313-cp313-win_amd64.whl", hash = "sha256:fd56a26a04f6ba5fb2045b0acc487a63162a958ed837648c5781e1fe3316cfbf"},
|
||||||
{file = "orjson-3.10.14-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6e2ec73b7099b6a29b40a62e08a23b936423bd35529f8f55c42e27acccde7954"},
|
{file = "orjson-3.10.15-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:5e8afd6200e12771467a1a44e5ad780614b86abb4b11862ec54861a82d677746"},
|
||||||
{file = "orjson-3.10.14-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a2d1679df9f9cd9504f8dff24555c1eaabba8aad7f5914f28dab99e3c2552c9d"},
|
{file = "orjson-3.10.15-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da9a18c500f19273e9e104cca8c1f0b40a6470bcccfc33afcc088045d0bf5ea6"},
|
||||||
{file = "orjson-3.10.14-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:691ab9a13834310a263664313e4f747ceb93662d14a8bdf20eb97d27ed488f16"},
|
{file = "orjson-3.10.15-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bb00b7bfbdf5d34a13180e4805d76b4567025da19a197645ca746fc2fb536586"},
|
||||||
{file = "orjson-3.10.14-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:b11ed82054fce82fb74cea33247d825d05ad6a4015ecfc02af5fbce442fbf361"},
|
{file = "orjson-3.10.15-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:33aedc3d903378e257047fee506f11e0833146ca3e57a1a1fb0ddb789876c1e1"},
|
||||||
{file = "orjson-3.10.14-cp38-cp38-musllinux_1_2_armv7l.whl", hash = "sha256:e70a1d62b8288677d48f3bea66c21586a5f999c64ecd3878edb7393e8d1b548d"},
|
{file = "orjson-3.10.15-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dd0099ae6aed5eb1fc84c9eb72b95505a3df4267e6962eb93cdd5af03be71c98"},
|
||||||
{file = "orjson-3.10.14-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:16642f10c1ca5611251bd835de9914a4b03095e28a34c8ba6a5500b5074338bd"},
|
{file = "orjson-3.10.15-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c864a80a2d467d7786274fce0e4f93ef2a7ca4ff31f7fc5634225aaa4e9e98c"},
|
||||||
{file = "orjson-3.10.14-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:3871bad546aa66c155e3f36f99c459780c2a392d502a64e23fb96d9abf338511"},
|
{file = "orjson-3.10.15-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c25774c9e88a3e0013d7d1a6c8056926b607a61edd423b50eb5c88fd7f2823ae"},
|
||||||
{file = "orjson-3.10.14-cp38-cp38-win32.whl", hash = "sha256:0293a88815e9bb5c90af4045f81ed364d982f955d12052d989d844d6c4e50945"},
|
{file = "orjson-3.10.15-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:e78c211d0074e783d824ce7bb85bf459f93a233eb67a5b5003498232ddfb0e8a"},
|
||||||
{file = "orjson-3.10.14-cp38-cp38-win_amd64.whl", hash = "sha256:6169d3868b190d6b21adc8e61f64e3db30f50559dfbdef34a1cd6c738d409dfc"},
|
{file = "orjson-3.10.15-cp38-cp38-musllinux_1_2_armv7l.whl", hash = "sha256:43e17289ffdbbac8f39243916c893d2ae41a2ea1a9cbb060a56a4d75286351ae"},
|
||||||
{file = "orjson-3.10.14-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:06d4ec218b1ec1467d8d64da4e123b4794c781b536203c309ca0f52819a16c03"},
|
{file = "orjson-3.10.15-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:781d54657063f361e89714293c095f506c533582ee40a426cb6489c48a637b81"},
|
||||||
{file = "orjson-3.10.14-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:962c2ec0dcaf22b76dee9831fdf0c4a33d4bf9a257a2bc5d4adc00d5c8ad9034"},
|
{file = "orjson-3.10.15-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:6875210307d36c94873f553786a808af2788e362bd0cf4c8e66d976791e7b528"},
|
||||||
{file = "orjson-3.10.14-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:21d3be4132f71ef1360385770474f29ea1538a242eef72ac4934fe142800e37f"},
|
{file = "orjson-3.10.15-cp38-cp38-win32.whl", hash = "sha256:305b38b2b8f8083cc3d618927d7f424349afce5975b316d33075ef0f73576b60"},
|
||||||
{file = "orjson-3.10.14-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c28ed60597c149a9e3f5ad6dd9cebaee6fb2f0e3f2d159a4a2b9b862d4748860"},
|
{file = "orjson-3.10.15-cp38-cp38-win_amd64.whl", hash = "sha256:5dd9ef1639878cc3efffed349543cbf9372bdbd79f478615a1c633fe4e4180d1"},
|
||||||
{file = "orjson-3.10.14-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7e947f70167fe18469f2023644e91ab3d24f9aed69a5e1c78e2c81b9cea553fb"},
|
{file = "orjson-3.10.15-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:ffe19f3e8d68111e8644d4f4e267a069ca427926855582ff01fc012496d19969"},
|
||||||
{file = "orjson-3.10.14-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64410696c97a35af2432dea7bdc4ce32416458159430ef1b4beb79fd30093ad6"},
|
{file = "orjson-3.10.15-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d433bf32a363823863a96561a555227c18a522a8217a6f9400f00ddc70139ae2"},
|
||||||
{file = "orjson-3.10.14-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8050a5d81c022561ee29cd2739de5b4445f3c72f39423fde80a63299c1892c52"},
|
{file = "orjson-3.10.15-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:da03392674f59a95d03fa5fb9fe3a160b0511ad84b7a3914699ea5a1b3a38da2"},
|
||||||
{file = "orjson-3.10.14-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:b49a28e30d3eca86db3fe6f9b7f4152fcacbb4a467953cd1b42b94b479b77956"},
|
{file = "orjson-3.10.15-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3a63bb41559b05360ded9132032239e47983a39b151af1201f07ec9370715c82"},
|
||||||
{file = "orjson-3.10.14-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:ca041ad20291a65d853a9523744eebc3f5a4b2f7634e99f8fe88320695ddf766"},
|
{file = "orjson-3.10.15-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3766ac4702f8f795ff3fa067968e806b4344af257011858cc3d6d8721588b53f"},
|
||||||
{file = "orjson-3.10.14-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:d313a2998b74bb26e9e371851a173a9b9474764916f1fc7971095699b3c6e964"},
|
{file = "orjson-3.10.15-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a1c73dcc8fadbd7c55802d9aa093b36878d34a3b3222c41052ce6b0fc65f8e8"},
|
||||||
{file = "orjson-3.10.14-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7796692136a67b3e301ef9052bde6fe8e7bd5200da766811a3a608ffa62aaff0"},
|
{file = "orjson-3.10.15-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b299383825eafe642cbab34be762ccff9fd3408d72726a6b2a4506d410a71ab3"},
|
||||||
{file = "orjson-3.10.14-cp39-cp39-win32.whl", hash = "sha256:eee4bc767f348fba485ed9dc576ca58b0a9eac237f0e160f7a59bce628ed06b3"},
|
{file = "orjson-3.10.15-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:abc7abecdbf67a173ef1316036ebbf54ce400ef2300b4e26a7b843bd446c2480"},
|
||||||
{file = "orjson-3.10.14-cp39-cp39-win_amd64.whl", hash = "sha256:96a1c0ee30fb113b3ae3c748fd75ca74a157ff4c58476c47db4d61518962a011"},
|
{file = "orjson-3.10.15-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:3614ea508d522a621384c1d6639016a5a2e4f027f3e4a1c93a51867615d28829"},
|
||||||
{file = "orjson-3.10.14.tar.gz", hash = "sha256:cf31f6f071a6b8e7aa1ead1fa27b935b48d00fbfa6a28ce856cfff2d5dd68eed"},
|
{file = "orjson-3.10.15-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:295c70f9dc154307777ba30fe29ff15c1bcc9dfc5c48632f37d20a607e9ba85a"},
|
||||||
|
{file = "orjson-3.10.15-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:63309e3ff924c62404923c80b9e2048c1f74ba4b615e7584584389ada50ed428"},
|
||||||
|
{file = "orjson-3.10.15-cp39-cp39-win32.whl", hash = "sha256:a2f708c62d026fb5340788ba94a55c23df4e1869fec74be455e0b2f5363b8507"},
|
||||||
|
{file = "orjson-3.10.15-cp39-cp39-win_amd64.whl", hash = "sha256:efcf6c735c3d22ef60c4aa27a5238f1a477df85e9b15f2142f9d669beb2d13fd"},
|
||||||
|
{file = "orjson-3.10.15.tar.gz", hash = "sha256:05ca7fe452a2e9d8d9d706a2984c95b9c2ebc5db417ce0b7a49b91d50642a23e"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2498,13 +2496,13 @@ files = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pydantic"
|
name = "pydantic"
|
||||||
version = "2.10.5"
|
version = "2.10.6"
|
||||||
description = "Data validation using Python type hints"
|
description = "Data validation using Python type hints"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
{file = "pydantic-2.10.5-py3-none-any.whl", hash = "sha256:4dd4e322dbe55472cb7ca7e73f4b63574eecccf2835ffa2af9021ce113c83c53"},
|
{file = "pydantic-2.10.6-py3-none-any.whl", hash = "sha256:427d664bf0b8a2b34ff5dd0f5a18df00591adcee7198fbd71981054cef37b584"},
|
||||||
{file = "pydantic-2.10.5.tar.gz", hash = "sha256:278b38dbbaec562011d659ee05f63346951b3a248a6f3642e1bc68894ea2b4ff"},
|
{file = "pydantic-2.10.6.tar.gz", hash = "sha256:ca5daa827cce33de7a42be142548b0096bf05a7e7b365aebfa5f8eeec7128236"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
@@ -2712,13 +2710,13 @@ dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pytest-asyncio"
|
name = "pytest-asyncio"
|
||||||
version = "0.25.2"
|
version = "0.25.3"
|
||||||
description = "Pytest support for asyncio"
|
description = "Pytest support for asyncio"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.9"
|
python-versions = ">=3.9"
|
||||||
files = [
|
files = [
|
||||||
{file = "pytest_asyncio-0.25.2-py3-none-any.whl", hash = "sha256:0d0bb693f7b99da304a0634afc0a4b19e49d5e0de2d670f38dc4bfa5727c5075"},
|
{file = "pytest_asyncio-0.25.3-py3-none-any.whl", hash = "sha256:9e89518e0f9bd08928f97a3482fdc4e244df17529460bc038291ccaf8f85c7c3"},
|
||||||
{file = "pytest_asyncio-0.25.2.tar.gz", hash = "sha256:3f8ef9a98f45948ea91a0ed3dc4268b5326c0e7bce73892acc654df4262ad45f"},
|
{file = "pytest_asyncio-0.25.3.tar.gz", hash = "sha256:fc1da2cf9f125ada7e710b4ddad05518d4cee187ae9412e9ac9271003497f07a"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
@@ -3049,29 +3047,29 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"]
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ruff"
|
name = "ruff"
|
||||||
version = "0.9.2"
|
version = "0.9.6"
|
||||||
description = "An extremely fast Python linter and code formatter, written in Rust."
|
description = "An extremely fast Python linter and code formatter, written in Rust."
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
{file = "ruff-0.9.2-py3-none-linux_armv6l.whl", hash = "sha256:80605a039ba1454d002b32139e4970becf84b5fee3a3c3bf1c2af6f61a784347"},
|
{file = "ruff-0.9.6-py3-none-linux_armv6l.whl", hash = "sha256:2f218f356dd2d995839f1941322ff021c72a492c470f0b26a34f844c29cdf5ba"},
|
||||||
{file = "ruff-0.9.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b9aab82bb20afd5f596527045c01e6ae25a718ff1784cb92947bff1f83068b00"},
|
{file = "ruff-0.9.6-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b908ff4df65dad7b251c9968a2e4560836d8f5487c2f0cc238321ed951ea0504"},
|
||||||
{file = "ruff-0.9.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:fbd337bac1cfa96be615f6efcd4bc4d077edbc127ef30e2b8ba2a27e18c054d4"},
|
{file = "ruff-0.9.6-py3-none-macosx_11_0_arm64.whl", hash = "sha256:b109c0ad2ececf42e75fa99dc4043ff72a357436bb171900714a9ea581ddef83"},
|
||||||
{file = "ruff-0.9.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82b35259b0cbf8daa22a498018e300b9bb0174c2bbb7bcba593935158a78054d"},
|
{file = "ruff-0.9.6-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1de4367cca3dac99bcbd15c161404e849bb0bfd543664db39232648dc00112dc"},
|
||||||
{file = "ruff-0.9.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8b6a9701d1e371bf41dca22015c3f89769da7576884d2add7317ec1ec8cb9c3c"},
|
{file = "ruff-0.9.6-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac3ee4d7c2c92ddfdaedf0bf31b2b176fa7aa8950efc454628d477394d35638b"},
|
||||||
{file = "ruff-0.9.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9cc53e68b3c5ae41e8faf83a3b89f4a5d7b2cb666dff4b366bb86ed2a85b481f"},
|
{file = "ruff-0.9.6-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5dc1edd1775270e6aa2386119aea692039781429f0be1e0949ea5884e011aa8e"},
|
||||||
{file = "ruff-0.9.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:8efd9da7a1ee314b910da155ca7e8953094a7c10d0c0a39bfde3fcfd2a015684"},
|
{file = "ruff-0.9.6-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:4a091729086dffa4bd070aa5dab7e39cc6b9d62eb2bef8f3d91172d30d599666"},
|
||||||
{file = "ruff-0.9.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3292c5a22ea9a5f9a185e2d131dc7f98f8534a32fb6d2ee7b9944569239c648d"},
|
{file = "ruff-0.9.6-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d1bbc6808bf7b15796cef0815e1dfb796fbd383e7dbd4334709642649625e7c5"},
|
||||||
{file = "ruff-0.9.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1a605fdcf6e8b2d39f9436d343d1f0ff70c365a1e681546de0104bef81ce88df"},
|
{file = "ruff-0.9.6-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:589d1d9f25b5754ff230dce914a174a7c951a85a4e9270613a2b74231fdac2f5"},
|
||||||
{file = "ruff-0.9.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c547f7f256aa366834829a08375c297fa63386cbe5f1459efaf174086b564247"},
|
{file = "ruff-0.9.6-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc61dd5131742e21103fbbdcad683a8813be0e3c204472d520d9a5021ca8b217"},
|
||||||
{file = "ruff-0.9.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:d18bba3d3353ed916e882521bc3e0af403949dbada344c20c16ea78f47af965e"},
|
{file = "ruff-0.9.6-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:5e2d9126161d0357e5c8f30b0bd6168d2c3872372f14481136d13de9937f79b6"},
|
||||||
{file = "ruff-0.9.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:b338edc4610142355ccf6b87bd356729b62bf1bc152a2fad5b0c7dc04af77bfe"},
|
{file = "ruff-0.9.6-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:68660eab1a8e65babb5229a1f97b46e3120923757a68b5413d8561f8a85d4897"},
|
||||||
{file = "ruff-0.9.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:492a5e44ad9b22a0ea98cf72e40305cbdaf27fac0d927f8bc9e1df316dcc96eb"},
|
{file = "ruff-0.9.6-py3-none-musllinux_1_2_i686.whl", hash = "sha256:c4cae6c4cc7b9b4017c71114115db0445b00a16de3bcde0946273e8392856f08"},
|
||||||
{file = "ruff-0.9.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:af1e9e9fe7b1f767264d26b1075ac4ad831c7db976911fa362d09b2d0356426a"},
|
{file = "ruff-0.9.6-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:19f505b643228b417c1111a2a536424ddde0db4ef9023b9e04a46ed8a1cb4656"},
|
||||||
{file = "ruff-0.9.2-py3-none-win32.whl", hash = "sha256:71cbe22e178c5da20e1514e1e01029c73dc09288a8028a5d3446e6bba87a5145"},
|
{file = "ruff-0.9.6-py3-none-win32.whl", hash = "sha256:194d8402bceef1b31164909540a597e0d913c0e4952015a5b40e28c146121b5d"},
|
||||||
{file = "ruff-0.9.2-py3-none-win_amd64.whl", hash = "sha256:c5e1d6abc798419cf46eed03f54f2e0c3adb1ad4b801119dedf23fcaf69b55b5"},
|
{file = "ruff-0.9.6-py3-none-win_amd64.whl", hash = "sha256:03482d5c09d90d4ee3f40d97578423698ad895c87314c4de39ed2af945633caa"},
|
||||||
{file = "ruff-0.9.2-py3-none-win_arm64.whl", hash = "sha256:a1b63fa24149918f8b37cef2ee6fff81f24f0d74b6f0bdc37bc3e1f2143e41c6"},
|
{file = "ruff-0.9.6-py3-none-win_arm64.whl", hash = "sha256:0e2bb706a2be7ddfea4a4af918562fdc1bcb16df255e5fa595bbd800ce322a5a"},
|
||||||
{file = "ruff-0.9.2.tar.gz", hash = "sha256:b5eceb334d55fae5f316f783437392642ae18e16dcf4f1858d55d3c2a0f8f5d0"},
|
{file = "ruff-0.9.6.tar.gz", hash = "sha256:81761592f72b620ec8fa1068a6fd00e98a5ebee342a3642efd84454f3031dca9"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
@@ -541,7 +541,7 @@
|
|||||||
CODE_SIGN_ENTITLEMENTS = Runner/RunnerProfile.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Runner/RunnerProfile.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 193;
|
CURRENT_PROJECT_VERSION = 194;
|
||||||
CUSTOM_GROUP_ID = group.app.immich.share;
|
CUSTOM_GROUP_ID = group.app.immich.share;
|
||||||
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
@@ -685,7 +685,7 @@
|
|||||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 193;
|
CURRENT_PROJECT_VERSION = 194;
|
||||||
CUSTOM_GROUP_ID = group.app.immich.share;
|
CUSTOM_GROUP_ID = group.app.immich.share;
|
||||||
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
@@ -715,7 +715,7 @@
|
|||||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 193;
|
CURRENT_PROJECT_VERSION = 194;
|
||||||
CUSTOM_GROUP_ID = group.app.immich.share;
|
CUSTOM_GROUP_ID = group.app.immich.share;
|
||||||
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
@@ -748,7 +748,7 @@
|
|||||||
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
|
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 193;
|
CURRENT_PROJECT_VERSION = 194;
|
||||||
CUSTOM_GROUP_ID = group.app.immich.share;
|
CUSTOM_GROUP_ID = group.app.immich.share;
|
||||||
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
||||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||||
@@ -791,7 +791,7 @@
|
|||||||
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
|
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 193;
|
CURRENT_PROJECT_VERSION = 194;
|
||||||
CUSTOM_GROUP_ID = group.app.immich.share;
|
CUSTOM_GROUP_ID = group.app.immich.share;
|
||||||
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
||||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||||
@@ -831,7 +831,7 @@
|
|||||||
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
|
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 193;
|
CURRENT_PROJECT_VERSION = 194;
|
||||||
CUSTOM_GROUP_ID = group.app.immich.share;
|
CUSTOM_GROUP_ID = group.app.immich.share;
|
||||||
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
||||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||||
|
|||||||
@@ -78,7 +78,7 @@
|
|||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>1.126.0</string>
|
<string>1.126.1</string>
|
||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>????</string>
|
<string>????</string>
|
||||||
<key>CFBundleURLTypes</key>
|
<key>CFBundleURLTypes</key>
|
||||||
@@ -93,7 +93,7 @@
|
|||||||
</dict>
|
</dict>
|
||||||
</array>
|
</array>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>193</string>
|
<string>194</string>
|
||||||
<key>FLTEnableImpeller</key>
|
<key>FLTEnableImpeller</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>ITSAppUsesNonExemptEncryption</key>
|
<key>ITSAppUsesNonExemptEncryption</key>
|
||||||
|
|||||||
@@ -59,9 +59,10 @@ class MapBottomSheet extends HookConsumerWidget {
|
|||||||
child: DraggableScrollableSheet(
|
child: DraggableScrollableSheet(
|
||||||
controller: sheetController,
|
controller: sheetController,
|
||||||
minChildSize: sheetMinExtent,
|
minChildSize: sheetMinExtent,
|
||||||
maxChildSize: 0.5,
|
maxChildSize: 0.8,
|
||||||
initialChildSize: sheetMinExtent,
|
initialChildSize: sheetMinExtent,
|
||||||
snap: true,
|
snap: true,
|
||||||
|
snapSizes: [sheetMinExtent, 0.5, 0.8],
|
||||||
shouldCloseOnMinExtent: false,
|
shouldCloseOnMinExtent: false,
|
||||||
builder: (ctx, scrollController) => MapAssetGrid(
|
builder: (ctx, scrollController) => MapAssetGrid(
|
||||||
controller: scrollController,
|
controller: scrollController,
|
||||||
@@ -78,18 +79,23 @@ class MapBottomSheet extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
ValueListenableBuilder(
|
ValueListenableBuilder(
|
||||||
valueListenable: bottomSheetOffset,
|
valueListenable: bottomSheetOffset,
|
||||||
builder: (ctx, value, child) => Positioned(
|
builder: (context, value, child) {
|
||||||
right: 0,
|
return Positioned(
|
||||||
bottom: context.height * (value + 0.02),
|
right: 0,
|
||||||
child: child!,
|
bottom: context.height * (value + 0.02),
|
||||||
),
|
child: AnimatedOpacity(
|
||||||
child: ElevatedButton(
|
opacity: value < 0.8 ? 1 : 0,
|
||||||
onPressed: onZoomToLocation,
|
duration: const Duration(milliseconds: 150),
|
||||||
style: ElevatedButton.styleFrom(
|
child: ElevatedButton(
|
||||||
shape: const CircleBorder(),
|
onPressed: onZoomToLocation,
|
||||||
),
|
style: ElevatedButton.styleFrom(
|
||||||
child: const Icon(Icons.my_location),
|
shape: const CircleBorder(),
|
||||||
),
|
),
|
||||||
|
child: const Icon(Icons.my_location),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|||||||
+104
-1
@@ -20,6 +20,7 @@ class AssetBulkUpdateDto {
|
|||||||
this.isFavorite,
|
this.isFavorite,
|
||||||
this.latitude,
|
this.latitude,
|
||||||
this.longitude,
|
this.longitude,
|
||||||
|
this.orientation,
|
||||||
this.rating,
|
this.rating,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -67,6 +68,8 @@ class AssetBulkUpdateDto {
|
|||||||
///
|
///
|
||||||
num? longitude;
|
num? longitude;
|
||||||
|
|
||||||
|
AssetBulkUpdateDtoOrientationEnum? orientation;
|
||||||
|
|
||||||
/// Minimum value: -1
|
/// Minimum value: -1
|
||||||
/// Maximum value: 5
|
/// Maximum value: 5
|
||||||
///
|
///
|
||||||
@@ -86,6 +89,7 @@ class AssetBulkUpdateDto {
|
|||||||
other.isFavorite == isFavorite &&
|
other.isFavorite == isFavorite &&
|
||||||
other.latitude == latitude &&
|
other.latitude == latitude &&
|
||||||
other.longitude == longitude &&
|
other.longitude == longitude &&
|
||||||
|
other.orientation == orientation &&
|
||||||
other.rating == rating;
|
other.rating == rating;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -98,10 +102,11 @@ class AssetBulkUpdateDto {
|
|||||||
(isFavorite == null ? 0 : isFavorite!.hashCode) +
|
(isFavorite == null ? 0 : isFavorite!.hashCode) +
|
||||||
(latitude == null ? 0 : latitude!.hashCode) +
|
(latitude == null ? 0 : latitude!.hashCode) +
|
||||||
(longitude == null ? 0 : longitude!.hashCode) +
|
(longitude == null ? 0 : longitude!.hashCode) +
|
||||||
|
(orientation == null ? 0 : orientation!.hashCode) +
|
||||||
(rating == null ? 0 : rating!.hashCode);
|
(rating == null ? 0 : rating!.hashCode);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() => 'AssetBulkUpdateDto[dateTimeOriginal=$dateTimeOriginal, duplicateId=$duplicateId, ids=$ids, isArchived=$isArchived, isFavorite=$isFavorite, latitude=$latitude, longitude=$longitude, rating=$rating]';
|
String toString() => 'AssetBulkUpdateDto[dateTimeOriginal=$dateTimeOriginal, duplicateId=$duplicateId, ids=$ids, isArchived=$isArchived, isFavorite=$isFavorite, latitude=$latitude, longitude=$longitude, orientation=$orientation, rating=$rating]';
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
final json = <String, dynamic>{};
|
final json = <String, dynamic>{};
|
||||||
@@ -136,6 +141,11 @@ class AssetBulkUpdateDto {
|
|||||||
} else {
|
} else {
|
||||||
// json[r'longitude'] = null;
|
// json[r'longitude'] = null;
|
||||||
}
|
}
|
||||||
|
if (this.orientation != null) {
|
||||||
|
json[r'orientation'] = this.orientation;
|
||||||
|
} else {
|
||||||
|
// json[r'orientation'] = null;
|
||||||
|
}
|
||||||
if (this.rating != null) {
|
if (this.rating != null) {
|
||||||
json[r'rating'] = this.rating;
|
json[r'rating'] = this.rating;
|
||||||
} else {
|
} else {
|
||||||
@@ -162,6 +172,7 @@ class AssetBulkUpdateDto {
|
|||||||
isFavorite: mapValueOfType<bool>(json, r'isFavorite'),
|
isFavorite: mapValueOfType<bool>(json, r'isFavorite'),
|
||||||
latitude: num.parse('${json[r'latitude']}'),
|
latitude: num.parse('${json[r'latitude']}'),
|
||||||
longitude: num.parse('${json[r'longitude']}'),
|
longitude: num.parse('${json[r'longitude']}'),
|
||||||
|
orientation: AssetBulkUpdateDtoOrientationEnum.fromJson(json[r'orientation']),
|
||||||
rating: num.parse('${json[r'rating']}'),
|
rating: num.parse('${json[r'rating']}'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -214,3 +225,95 @@ class AssetBulkUpdateDto {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class AssetBulkUpdateDtoOrientationEnum {
|
||||||
|
/// Instantiate a new enum with the provided [value].
|
||||||
|
const AssetBulkUpdateDtoOrientationEnum._(this.value);
|
||||||
|
|
||||||
|
/// The underlying value of this enum member.
|
||||||
|
final int value;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => value.toString();
|
||||||
|
|
||||||
|
int toJson() => value;
|
||||||
|
|
||||||
|
static const number1 = AssetBulkUpdateDtoOrientationEnum._(1);
|
||||||
|
static const number2 = AssetBulkUpdateDtoOrientationEnum._(2);
|
||||||
|
static const number3 = AssetBulkUpdateDtoOrientationEnum._(3);
|
||||||
|
static const number4 = AssetBulkUpdateDtoOrientationEnum._(4);
|
||||||
|
static const number5 = AssetBulkUpdateDtoOrientationEnum._(5);
|
||||||
|
static const number6 = AssetBulkUpdateDtoOrientationEnum._(6);
|
||||||
|
static const number7 = AssetBulkUpdateDtoOrientationEnum._(7);
|
||||||
|
static const number8 = AssetBulkUpdateDtoOrientationEnum._(8);
|
||||||
|
|
||||||
|
/// List of all possible values in this [enum][AssetBulkUpdateDtoOrientationEnum].
|
||||||
|
static const values = <AssetBulkUpdateDtoOrientationEnum>[
|
||||||
|
number1,
|
||||||
|
number2,
|
||||||
|
number3,
|
||||||
|
number4,
|
||||||
|
number5,
|
||||||
|
number6,
|
||||||
|
number7,
|
||||||
|
number8,
|
||||||
|
];
|
||||||
|
|
||||||
|
static AssetBulkUpdateDtoOrientationEnum? fromJson(dynamic value) => AssetBulkUpdateDtoOrientationEnumTypeTransformer().decode(value);
|
||||||
|
|
||||||
|
static List<AssetBulkUpdateDtoOrientationEnum> listFromJson(dynamic json, {bool growable = false,}) {
|
||||||
|
final result = <AssetBulkUpdateDtoOrientationEnum>[];
|
||||||
|
if (json is List && json.isNotEmpty) {
|
||||||
|
for (final row in json) {
|
||||||
|
final value = AssetBulkUpdateDtoOrientationEnum.fromJson(row);
|
||||||
|
if (value != null) {
|
||||||
|
result.add(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.toList(growable: growable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Transformation class that can [encode] an instance of [AssetBulkUpdateDtoOrientationEnum] to int,
|
||||||
|
/// and [decode] dynamic data back to [AssetBulkUpdateDtoOrientationEnum].
|
||||||
|
class AssetBulkUpdateDtoOrientationEnumTypeTransformer {
|
||||||
|
factory AssetBulkUpdateDtoOrientationEnumTypeTransformer() => _instance ??= const AssetBulkUpdateDtoOrientationEnumTypeTransformer._();
|
||||||
|
|
||||||
|
const AssetBulkUpdateDtoOrientationEnumTypeTransformer._();
|
||||||
|
|
||||||
|
int encode(AssetBulkUpdateDtoOrientationEnum data) => data.value;
|
||||||
|
|
||||||
|
/// Decodes a [dynamic value][data] to a AssetBulkUpdateDtoOrientationEnum.
|
||||||
|
///
|
||||||
|
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||||
|
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||||
|
/// cannot be decoded successfully, then an [UnimplementedError] is thrown.
|
||||||
|
///
|
||||||
|
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||||
|
/// and users are still using an old app with the old code.
|
||||||
|
AssetBulkUpdateDtoOrientationEnum? decode(dynamic data, {bool allowNull = true}) {
|
||||||
|
if (data != null) {
|
||||||
|
switch (data) {
|
||||||
|
case 1: return AssetBulkUpdateDtoOrientationEnum.number1;
|
||||||
|
case 2: return AssetBulkUpdateDtoOrientationEnum.number2;
|
||||||
|
case 3: return AssetBulkUpdateDtoOrientationEnum.number3;
|
||||||
|
case 4: return AssetBulkUpdateDtoOrientationEnum.number4;
|
||||||
|
case 5: return AssetBulkUpdateDtoOrientationEnum.number5;
|
||||||
|
case 6: return AssetBulkUpdateDtoOrientationEnum.number6;
|
||||||
|
case 7: return AssetBulkUpdateDtoOrientationEnum.number7;
|
||||||
|
case 8: return AssetBulkUpdateDtoOrientationEnum.number8;
|
||||||
|
default:
|
||||||
|
if (!allowNull) {
|
||||||
|
throw ArgumentError('Unknown enum value to decode: $data');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Singleton [AssetBulkUpdateDtoOrientationEnumTypeTransformer] instance.
|
||||||
|
static AssetBulkUpdateDtoOrientationEnumTypeTransformer? _instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+104
-1
@@ -20,6 +20,7 @@ class UpdateAssetDto {
|
|||||||
this.latitude,
|
this.latitude,
|
||||||
this.livePhotoVideoId,
|
this.livePhotoVideoId,
|
||||||
this.longitude,
|
this.longitude,
|
||||||
|
this.orientation,
|
||||||
this.rating,
|
this.rating,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -73,6 +74,8 @@ class UpdateAssetDto {
|
|||||||
///
|
///
|
||||||
num? longitude;
|
num? longitude;
|
||||||
|
|
||||||
|
UpdateAssetDtoOrientationEnum? orientation;
|
||||||
|
|
||||||
/// Minimum value: -1
|
/// Minimum value: -1
|
||||||
/// Maximum value: 5
|
/// Maximum value: 5
|
||||||
///
|
///
|
||||||
@@ -92,6 +95,7 @@ class UpdateAssetDto {
|
|||||||
other.latitude == latitude &&
|
other.latitude == latitude &&
|
||||||
other.livePhotoVideoId == livePhotoVideoId &&
|
other.livePhotoVideoId == livePhotoVideoId &&
|
||||||
other.longitude == longitude &&
|
other.longitude == longitude &&
|
||||||
|
other.orientation == orientation &&
|
||||||
other.rating == rating;
|
other.rating == rating;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -104,10 +108,11 @@ class UpdateAssetDto {
|
|||||||
(latitude == null ? 0 : latitude!.hashCode) +
|
(latitude == null ? 0 : latitude!.hashCode) +
|
||||||
(livePhotoVideoId == null ? 0 : livePhotoVideoId!.hashCode) +
|
(livePhotoVideoId == null ? 0 : livePhotoVideoId!.hashCode) +
|
||||||
(longitude == null ? 0 : longitude!.hashCode) +
|
(longitude == null ? 0 : longitude!.hashCode) +
|
||||||
|
(orientation == null ? 0 : orientation!.hashCode) +
|
||||||
(rating == null ? 0 : rating!.hashCode);
|
(rating == null ? 0 : rating!.hashCode);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() => 'UpdateAssetDto[dateTimeOriginal=$dateTimeOriginal, description=$description, isArchived=$isArchived, isFavorite=$isFavorite, latitude=$latitude, livePhotoVideoId=$livePhotoVideoId, longitude=$longitude, rating=$rating]';
|
String toString() => 'UpdateAssetDto[dateTimeOriginal=$dateTimeOriginal, description=$description, isArchived=$isArchived, isFavorite=$isFavorite, latitude=$latitude, livePhotoVideoId=$livePhotoVideoId, longitude=$longitude, orientation=$orientation, rating=$rating]';
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
final json = <String, dynamic>{};
|
final json = <String, dynamic>{};
|
||||||
@@ -146,6 +151,11 @@ class UpdateAssetDto {
|
|||||||
} else {
|
} else {
|
||||||
// json[r'longitude'] = null;
|
// json[r'longitude'] = null;
|
||||||
}
|
}
|
||||||
|
if (this.orientation != null) {
|
||||||
|
json[r'orientation'] = this.orientation;
|
||||||
|
} else {
|
||||||
|
// json[r'orientation'] = null;
|
||||||
|
}
|
||||||
if (this.rating != null) {
|
if (this.rating != null) {
|
||||||
json[r'rating'] = this.rating;
|
json[r'rating'] = this.rating;
|
||||||
} else {
|
} else {
|
||||||
@@ -170,6 +180,7 @@ class UpdateAssetDto {
|
|||||||
latitude: num.parse('${json[r'latitude']}'),
|
latitude: num.parse('${json[r'latitude']}'),
|
||||||
livePhotoVideoId: mapValueOfType<String>(json, r'livePhotoVideoId'),
|
livePhotoVideoId: mapValueOfType<String>(json, r'livePhotoVideoId'),
|
||||||
longitude: num.parse('${json[r'longitude']}'),
|
longitude: num.parse('${json[r'longitude']}'),
|
||||||
|
orientation: UpdateAssetDtoOrientationEnum.fromJson(json[r'orientation']),
|
||||||
rating: num.parse('${json[r'rating']}'),
|
rating: num.parse('${json[r'rating']}'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -221,3 +232,95 @@ class UpdateAssetDto {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class UpdateAssetDtoOrientationEnum {
|
||||||
|
/// Instantiate a new enum with the provided [value].
|
||||||
|
const UpdateAssetDtoOrientationEnum._(this.value);
|
||||||
|
|
||||||
|
/// The underlying value of this enum member.
|
||||||
|
final int value;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => value.toString();
|
||||||
|
|
||||||
|
int toJson() => value;
|
||||||
|
|
||||||
|
static const number1 = UpdateAssetDtoOrientationEnum._(1);
|
||||||
|
static const number2 = UpdateAssetDtoOrientationEnum._(2);
|
||||||
|
static const number3 = UpdateAssetDtoOrientationEnum._(3);
|
||||||
|
static const number4 = UpdateAssetDtoOrientationEnum._(4);
|
||||||
|
static const number5 = UpdateAssetDtoOrientationEnum._(5);
|
||||||
|
static const number6 = UpdateAssetDtoOrientationEnum._(6);
|
||||||
|
static const number7 = UpdateAssetDtoOrientationEnum._(7);
|
||||||
|
static const number8 = UpdateAssetDtoOrientationEnum._(8);
|
||||||
|
|
||||||
|
/// List of all possible values in this [enum][UpdateAssetDtoOrientationEnum].
|
||||||
|
static const values = <UpdateAssetDtoOrientationEnum>[
|
||||||
|
number1,
|
||||||
|
number2,
|
||||||
|
number3,
|
||||||
|
number4,
|
||||||
|
number5,
|
||||||
|
number6,
|
||||||
|
number7,
|
||||||
|
number8,
|
||||||
|
];
|
||||||
|
|
||||||
|
static UpdateAssetDtoOrientationEnum? fromJson(dynamic value) => UpdateAssetDtoOrientationEnumTypeTransformer().decode(value);
|
||||||
|
|
||||||
|
static List<UpdateAssetDtoOrientationEnum> listFromJson(dynamic json, {bool growable = false,}) {
|
||||||
|
final result = <UpdateAssetDtoOrientationEnum>[];
|
||||||
|
if (json is List && json.isNotEmpty) {
|
||||||
|
for (final row in json) {
|
||||||
|
final value = UpdateAssetDtoOrientationEnum.fromJson(row);
|
||||||
|
if (value != null) {
|
||||||
|
result.add(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.toList(growable: growable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Transformation class that can [encode] an instance of [UpdateAssetDtoOrientationEnum] to int,
|
||||||
|
/// and [decode] dynamic data back to [UpdateAssetDtoOrientationEnum].
|
||||||
|
class UpdateAssetDtoOrientationEnumTypeTransformer {
|
||||||
|
factory UpdateAssetDtoOrientationEnumTypeTransformer() => _instance ??= const UpdateAssetDtoOrientationEnumTypeTransformer._();
|
||||||
|
|
||||||
|
const UpdateAssetDtoOrientationEnumTypeTransformer._();
|
||||||
|
|
||||||
|
int encode(UpdateAssetDtoOrientationEnum data) => data.value;
|
||||||
|
|
||||||
|
/// Decodes a [dynamic value][data] to a UpdateAssetDtoOrientationEnum.
|
||||||
|
///
|
||||||
|
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||||
|
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||||
|
/// cannot be decoded successfully, then an [UnimplementedError] is thrown.
|
||||||
|
///
|
||||||
|
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||||
|
/// and users are still using an old app with the old code.
|
||||||
|
UpdateAssetDtoOrientationEnum? decode(dynamic data, {bool allowNull = true}) {
|
||||||
|
if (data != null) {
|
||||||
|
switch (data) {
|
||||||
|
case 1: return UpdateAssetDtoOrientationEnum.number1;
|
||||||
|
case 2: return UpdateAssetDtoOrientationEnum.number2;
|
||||||
|
case 3: return UpdateAssetDtoOrientationEnum.number3;
|
||||||
|
case 4: return UpdateAssetDtoOrientationEnum.number4;
|
||||||
|
case 5: return UpdateAssetDtoOrientationEnum.number5;
|
||||||
|
case 6: return UpdateAssetDtoOrientationEnum.number6;
|
||||||
|
case 7: return UpdateAssetDtoOrientationEnum.number7;
|
||||||
|
case 8: return UpdateAssetDtoOrientationEnum.number8;
|
||||||
|
default:
|
||||||
|
if (!allowNull) {
|
||||||
|
throw ArgumentError('Unknown enum value to decode: $data');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Singleton [UpdateAssetDtoOrientationEnumTypeTransformer] instance.
|
||||||
|
static UpdateAssetDtoOrientationEnumTypeTransformer? _instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -7963,6 +7963,21 @@
|
|||||||
"longitude": {
|
"longitude": {
|
||||||
"type": "number"
|
"type": "number"
|
||||||
},
|
},
|
||||||
|
"orientation": {
|
||||||
|
"enum": [
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
5,
|
||||||
|
6,
|
||||||
|
7,
|
||||||
|
8
|
||||||
|
],
|
||||||
|
"maximum": 8,
|
||||||
|
"minimum": 1,
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
"rating": {
|
"rating": {
|
||||||
"maximum": 5,
|
"maximum": 5,
|
||||||
"minimum": -1,
|
"minimum": -1,
|
||||||
@@ -12880,6 +12895,21 @@
|
|||||||
"longitude": {
|
"longitude": {
|
||||||
"type": "number"
|
"type": "number"
|
||||||
},
|
},
|
||||||
|
"orientation": {
|
||||||
|
"enum": [
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
5,
|
||||||
|
6,
|
||||||
|
7,
|
||||||
|
8
|
||||||
|
],
|
||||||
|
"maximum": 8,
|
||||||
|
"minimum": 1,
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
"rating": {
|
"rating": {
|
||||||
"maximum": 5,
|
"maximum": 5,
|
||||||
"minimum": -1,
|
"minimum": -1,
|
||||||
|
|||||||
+4
-4
@@ -12,7 +12,7 @@
|
|||||||
"@oazapfts/runtime": "^1.0.2"
|
"@oazapfts/runtime": "^1.0.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^22.10.9",
|
"@types/node": "^22.13.1",
|
||||||
"typescript": "^5.3.3"
|
"typescript": "^5.3.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -22,9 +22,9 @@
|
|||||||
"integrity": "sha512-8tKiYffhwTGHSHYGnZ3oneLGCjX0po/XAXQ5Ng9fqKkvIdl/xz8+Vh8i+6xjzZqvZ2pLVpUcuSfnvNI/x67L0g=="
|
"integrity": "sha512-8tKiYffhwTGHSHYGnZ3oneLGCjX0po/XAXQ5Ng9fqKkvIdl/xz8+Vh8i+6xjzZqvZ2pLVpUcuSfnvNI/x67L0g=="
|
||||||
},
|
},
|
||||||
"node_modules/@types/node": {
|
"node_modules/@types/node": {
|
||||||
"version": "22.10.9",
|
"version": "22.13.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.9.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.1.tgz",
|
||||||
"integrity": "sha512-Ir6hwgsKyNESl/gLOcEz3krR4CBGgliDqBQ2ma4wIhEx0w+xnoeTq3tdrNw15kU3SxogDjOgv9sqdtLW8mIHaw==",
|
"integrity": "sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
"@oazapfts/runtime": "^1.0.2"
|
"@oazapfts/runtime": "^1.0.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^22.10.9",
|
"@types/node": "^22.13.1",
|
||||||
"typescript": "^5.3.3"
|
"typescript": "^5.3.3"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|||||||
@@ -391,6 +391,7 @@ export type AssetBulkUpdateDto = {
|
|||||||
isFavorite?: boolean;
|
isFavorite?: boolean;
|
||||||
latitude?: number;
|
latitude?: number;
|
||||||
longitude?: number;
|
longitude?: number;
|
||||||
|
orientation?: Orientation;
|
||||||
rating?: number;
|
rating?: number;
|
||||||
};
|
};
|
||||||
export type AssetBulkUploadCheckItem = {
|
export type AssetBulkUploadCheckItem = {
|
||||||
@@ -439,6 +440,7 @@ export type UpdateAssetDto = {
|
|||||||
latitude?: number;
|
latitude?: number;
|
||||||
livePhotoVideoId?: string | null;
|
livePhotoVideoId?: string | null;
|
||||||
longitude?: number;
|
longitude?: number;
|
||||||
|
orientation?: Orientation;
|
||||||
rating?: number;
|
rating?: number;
|
||||||
};
|
};
|
||||||
export type AssetMediaReplaceDto = {
|
export type AssetMediaReplaceDto = {
|
||||||
@@ -3481,6 +3483,16 @@ export enum AssetMediaStatus {
|
|||||||
Replaced = "replaced",
|
Replaced = "replaced",
|
||||||
Duplicate = "duplicate"
|
Duplicate = "duplicate"
|
||||||
}
|
}
|
||||||
|
export enum Orientation {
|
||||||
|
$1 = 1,
|
||||||
|
$2 = 2,
|
||||||
|
$3 = 3,
|
||||||
|
$4 = 4,
|
||||||
|
$5 = 5,
|
||||||
|
$6 = 6,
|
||||||
|
$7 = 7,
|
||||||
|
$8 = 8
|
||||||
|
}
|
||||||
export enum Action {
|
export enum Action {
|
||||||
Accept = "accept",
|
Accept = "accept",
|
||||||
Reject = "reject"
|
Reject = "reject"
|
||||||
|
|||||||
+2
-2
@@ -1,5 +1,5 @@
|
|||||||
# dev build
|
# dev build
|
||||||
FROM ghcr.io/immich-app/base-server-dev:20250204@sha256:8b203f19f4d5cf4619b60ee5f50d6d4b5ea3745747f5e5170d1b7404ebeb0792 AS dev
|
FROM ghcr.io/immich-app/base-server-dev:20250211@sha256:6ae577a6518e1ccca973db16955f4d79b01cac3ae122759ccb1c17bf6c330ba9 AS dev
|
||||||
|
|
||||||
RUN apt-get install --no-install-recommends -yqq tini
|
RUN apt-get install --no-install-recommends -yqq tini
|
||||||
WORKDIR /usr/src/app
|
WORKDIR /usr/src/app
|
||||||
@@ -42,7 +42,7 @@ RUN npm run build
|
|||||||
|
|
||||||
|
|
||||||
# prod build
|
# prod build
|
||||||
FROM ghcr.io/immich-app/base-server-prod:20250204@sha256:2af3da713d5ab3ccca23b216b747557ea6016117e72deac101e35069ccaf9b5e
|
FROM ghcr.io/immich-app/base-server-prod:20250211@sha256:879cfe3d2afd4b7bdb211f694f99b6c0679a8bbd3e96964ad6c878f8471d63ea
|
||||||
|
|
||||||
WORKDIR /usr/src/app
|
WORKDIR /usr/src/app
|
||||||
ENV NODE_ENV=production \
|
ENV NODE_ENV=production \
|
||||||
|
|||||||
Generated
+244
-249
@@ -19,7 +19,7 @@
|
|||||||
"@nestjs/swagger": "^11.0.2",
|
"@nestjs/swagger": "^11.0.2",
|
||||||
"@nestjs/typeorm": "^11.0.0",
|
"@nestjs/typeorm": "^11.0.0",
|
||||||
"@nestjs/websockets": "^11.0.4",
|
"@nestjs/websockets": "^11.0.4",
|
||||||
"@opentelemetry/auto-instrumentations-node": "^0.55.0",
|
"@opentelemetry/auto-instrumentations-node": "^0.56.0",
|
||||||
"@opentelemetry/context-async-hooks": "^1.24.0",
|
"@opentelemetry/context-async-hooks": "^1.24.0",
|
||||||
"@opentelemetry/exporter-prometheus": "^0.57.0",
|
"@opentelemetry/exporter-prometheus": "^0.57.0",
|
||||||
"@opentelemetry/sdk-node": "^0.57.0",
|
"@opentelemetry/sdk-node": "^0.57.0",
|
||||||
@@ -86,7 +86,7 @@
|
|||||||
"@types/lodash": "^4.14.197",
|
"@types/lodash": "^4.14.197",
|
||||||
"@types/mock-fs": "^4.13.1",
|
"@types/mock-fs": "^4.13.1",
|
||||||
"@types/multer": "^1.4.7",
|
"@types/multer": "^1.4.7",
|
||||||
"@types/node": "^22.10.9",
|
"@types/node": "^22.13.1",
|
||||||
"@types/nodemailer": "^6.4.14",
|
"@types/nodemailer": "^6.4.14",
|
||||||
"@types/picomatch": "^3.0.0",
|
"@types/picomatch": "^3.0.0",
|
||||||
"@types/pngjs": "^6.0.5",
|
"@types/pngjs": "^6.0.5",
|
||||||
@@ -1178,9 +1178,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@eslint/js": {
|
"node_modules/@eslint/js": {
|
||||||
"version": "9.18.0",
|
"version": "9.19.0",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.18.0.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.19.0.tgz",
|
||||||
"integrity": "sha512-fK6L7rxcq6/z+AaQMtiFTkvbHkBLNlwyRxHpKawP0x3u9+NC6MQTnFW+AdpwC6gfHTW0051cokQgtTN2FqlxQA==",
|
"integrity": "sha512-rbq9/g38qjfqFLOVPvwjIvFFdNziEC5S65jmjPw5r6A//QH+W91akh9irMwjDN8zKUTak6W9EsAv4m/7Wnw0UQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -2310,9 +2310,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@nestjs/bull-shared": {
|
"node_modules/@nestjs/bull-shared": {
|
||||||
"version": "11.0.1",
|
"version": "11.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@nestjs/bull-shared/-/bull-shared-11.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@nestjs/bull-shared/-/bull-shared-11.0.2.tgz",
|
||||||
"integrity": "sha512-FqpmIjhCONaYo+5AjtggPdo2lRIM/fv1VHiEq7YwFZBTNSPW0eOvcT96JDb5q4OuvLvADxgpnwP7rmzZywMMiw==",
|
"integrity": "sha512-dFlttJvBqIFD6M8JVFbkrR4Feb39OTAJPJpFVILU50NOJCM4qziRw3dSNG84Q3v+7/M6xUGMFdZRRGvBBKxoSA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"tslib": "2.8.1"
|
"tslib": "2.8.1"
|
||||||
@@ -2323,12 +2323,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@nestjs/bullmq": {
|
"node_modules/@nestjs/bullmq": {
|
||||||
"version": "11.0.1",
|
"version": "11.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@nestjs/bullmq/-/bullmq-11.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@nestjs/bullmq/-/bullmq-11.0.2.tgz",
|
||||||
"integrity": "sha512-BntU0Zfiyk4R5hlasUV22n1HuqmWWKvsx3knSR5A9/5vce808pmHOmHrtm4GZDs/8Pw9X8UGY8zdLe4a36S6KQ==",
|
"integrity": "sha512-Lq6lGpKkETsm0RDcUktlzsthFoE3A5QTMp2FwPi1eztKqKD6/90KS1TcnC9CJFzjpUaYnQzIMrlNs55e+/wsHA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nestjs/bull-shared": "^11.0.1",
|
"@nestjs/bull-shared": "^11.0.2",
|
||||||
"tslib": "2.8.1"
|
"tslib": "2.8.1"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
@@ -2577,9 +2577,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@nestjs/common": {
|
"node_modules/@nestjs/common": {
|
||||||
"version": "11.0.6",
|
"version": "11.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/@nestjs/common/-/common-11.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/@nestjs/common/-/common-11.0.8.tgz",
|
||||||
"integrity": "sha512-j+M3WOU6loZPNirIHDiZ1LxXRXVNb62XicgLBqdgyrDBFCJrAZaq0lfERUEPlN0/j4GBFnTSPg+CNsoGTBW1zQ==",
|
"integrity": "sha512-IB6wEl8RgT/vWzb6p3cmBwTY3R0qfQWvO8lW0PfIv4DTJfUiVqNNEikonGuH/6TX8KvRXNhXHCaQZrUN00Xe6g==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"iterare": "1.2.1",
|
"iterare": "1.2.1",
|
||||||
@@ -2606,9 +2606,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@nestjs/core": {
|
"node_modules/@nestjs/core": {
|
||||||
"version": "11.0.6",
|
"version": "11.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/@nestjs/core/-/core-11.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/@nestjs/core/-/core-11.0.8.tgz",
|
||||||
"integrity": "sha512-Xf33bwc3waAJ/faJBW06+Dwq3m15p3wbFOc/CcK8ua5EZna4sMjIjXXAb6bQmEjR1KfTXV5z595UD2vwp6cyHg==",
|
"integrity": "sha512-GQLLdZnjZOmV4Q+TzQ8YuHvEYOneRhzsDbSJRkKdFFAVuoVh+q1nWZy+bZNeTxdWZFGL2Rve70X5jc4MoSXJqQ==",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -2680,9 +2680,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@nestjs/platform-express": {
|
"node_modules/@nestjs/platform-express": {
|
||||||
"version": "11.0.6",
|
"version": "11.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-11.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-11.0.8.tgz",
|
||||||
"integrity": "sha512-fP6vrpqDIBaf1FNfFtBeJm/BwtGtueatI4FHxaBgw93XxKmIOV4G4ZO7ouQKqfgyIxV2mkYr/Fhg7hwRmizIjw==",
|
"integrity": "sha512-Ru7seOYYglKNGQFzNALE5ilLqkdtX/ge6AJDKLMt+WI7iElZ7lXjT40fE3+HVUiZODunmeKQ7jVxcQyZwLafVA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cors": "2.8.5",
|
"cors": "2.8.5",
|
||||||
@@ -2701,9 +2701,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@nestjs/platform-socket.io": {
|
"node_modules/@nestjs/platform-socket.io": {
|
||||||
"version": "11.0.6",
|
"version": "11.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/@nestjs/platform-socket.io/-/platform-socket.io-11.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/@nestjs/platform-socket.io/-/platform-socket.io-11.0.8.tgz",
|
||||||
"integrity": "sha512-80r6hp0p+YK/+D5srjPTE/fc1w0aTM6ecqprJr8bFlzTPJbtYtpfHqMbEg0UfRKTsZ0krEgpv8fb0K4dSYzW0w==",
|
"integrity": "sha512-DUpfRSDgxu+z9czB6ddFdQFawSAIr7jEbNOvpjpjYErvDitUdos57FhTw9IJxIm2EAOHoiCk4g3tN59GfjdwfQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"socket.io": "4.8.1",
|
"socket.io": "4.8.1",
|
||||||
@@ -2720,9 +2720,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@nestjs/schedule": {
|
"node_modules/@nestjs/schedule": {
|
||||||
"version": "5.0.0",
|
"version": "5.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@nestjs/schedule/-/schedule-5.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@nestjs/schedule/-/schedule-5.0.1.tgz",
|
||||||
"integrity": "sha512-RHqJIOo3AQvdeq0WuIFDqa5N0CkgxgqwmWRla96S6GmFV6qkQD1//EeH4k19MeCu4Ac9PzZ2y/Hu0zK9f//BQg==",
|
"integrity": "sha512-kFoel84I4RyS2LNPH6yHYTKxB16tb3auAEciFuc788C3ph6nABkUfzX5IE+unjVaRX+3GuruJwurNepMlHXpQg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cron": "3.5.0"
|
"cron": "3.5.0"
|
||||||
@@ -2916,9 +2916,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@nestjs/testing": {
|
"node_modules/@nestjs/testing": {
|
||||||
"version": "11.0.6",
|
"version": "11.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-11.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-11.0.8.tgz",
|
||||||
"integrity": "sha512-RZDWdnOncOQ1vT3630VlRzKee2P21ZJoF1+NAY+nzYUuYuYAaBdjrTZQGwymmiZQcrM+TQaViSjSPUmcJXdKyA==",
|
"integrity": "sha512-5Reqec4MQSm4nFasKE5Pd799cAx3MmjkweF17Wgj/EJNWhFgVdv6N9OUIWXbU8nc8Pjso1fJmv0KJyN6h51qOA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -2957,9 +2957,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@nestjs/websockets": {
|
"node_modules/@nestjs/websockets": {
|
||||||
"version": "11.0.6",
|
"version": "11.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/@nestjs/websockets/-/websockets-11.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/@nestjs/websockets/-/websockets-11.0.8.tgz",
|
||||||
"integrity": "sha512-bsYZnmIXmZTYWzLJ3LbusH72kdppKSQLKUe9cfuUPXuTF+FaAX6TvErP11dJJ0W0S1Iwufr+LERTK211Txs8Eg==",
|
"integrity": "sha512-wyS512+QWhWhE8NU1DgbAPkCaaOSNK1xBIgRlgpYg5/tKuhu4lc5r8iMdZAQn6xay++ELlOqsSlyuj0J2BixOA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"iterare": "1.2.1",
|
"iterare": "1.2.1",
|
||||||
@@ -3186,9 +3186,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@opentelemetry/auto-instrumentations-node": {
|
"node_modules/@opentelemetry/auto-instrumentations-node": {
|
||||||
"version": "0.55.3",
|
"version": "0.56.0",
|
||||||
"resolved": "https://registry.npmjs.org/@opentelemetry/auto-instrumentations-node/-/auto-instrumentations-node-0.55.3.tgz",
|
"resolved": "https://registry.npmjs.org/@opentelemetry/auto-instrumentations-node/-/auto-instrumentations-node-0.56.0.tgz",
|
||||||
"integrity": "sha512-tX5k3ZG8Nk6f1DHAF0K1ClP/OiW2hNuSeCVqDHNMcJ58dZSiad0XO2mwrvSipo77/DPXXUl0j9MxqmUVITdujQ==",
|
"integrity": "sha512-d1X3DQY0+VmhNUir/3U3JO6Uh0FOSm8G91zsPzVVKc6NGDwmHP6Dn7PMVH70O6FZ0yErzlHqRx8vkNiAsTWt5A==",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@opentelemetry/instrumentation": "^0.57.0",
|
"@opentelemetry/instrumentation": "^0.57.0",
|
||||||
@@ -3198,7 +3198,7 @@
|
|||||||
"@opentelemetry/instrumentation-bunyan": "^0.45.0",
|
"@opentelemetry/instrumentation-bunyan": "^0.45.0",
|
||||||
"@opentelemetry/instrumentation-cassandra-driver": "^0.45.0",
|
"@opentelemetry/instrumentation-cassandra-driver": "^0.45.0",
|
||||||
"@opentelemetry/instrumentation-connect": "^0.43.0",
|
"@opentelemetry/instrumentation-connect": "^0.43.0",
|
||||||
"@opentelemetry/instrumentation-cucumber": "^0.13.0",
|
"@opentelemetry/instrumentation-cucumber": "^0.14.0",
|
||||||
"@opentelemetry/instrumentation-dataloader": "^0.16.0",
|
"@opentelemetry/instrumentation-dataloader": "^0.16.0",
|
||||||
"@opentelemetry/instrumentation-dns": "^0.43.0",
|
"@opentelemetry/instrumentation-dns": "^0.43.0",
|
||||||
"@opentelemetry/instrumentation-express": "^0.47.0",
|
"@opentelemetry/instrumentation-express": "^0.47.0",
|
||||||
@@ -3218,10 +3218,10 @@
|
|||||||
"@opentelemetry/instrumentation-mongodb": "^0.51.0",
|
"@opentelemetry/instrumentation-mongodb": "^0.51.0",
|
||||||
"@opentelemetry/instrumentation-mongoose": "^0.46.0",
|
"@opentelemetry/instrumentation-mongoose": "^0.46.0",
|
||||||
"@opentelemetry/instrumentation-mysql": "^0.45.0",
|
"@opentelemetry/instrumentation-mysql": "^0.45.0",
|
||||||
"@opentelemetry/instrumentation-mysql2": "^0.45.0",
|
"@opentelemetry/instrumentation-mysql2": "^0.45.1",
|
||||||
"@opentelemetry/instrumentation-nestjs-core": "^0.44.0",
|
"@opentelemetry/instrumentation-nestjs-core": "^0.44.0",
|
||||||
"@opentelemetry/instrumentation-net": "^0.43.0",
|
"@opentelemetry/instrumentation-net": "^0.43.0",
|
||||||
"@opentelemetry/instrumentation-pg": "^0.50.0",
|
"@opentelemetry/instrumentation-pg": "^0.51.0",
|
||||||
"@opentelemetry/instrumentation-pino": "^0.46.0",
|
"@opentelemetry/instrumentation-pino": "^0.46.0",
|
||||||
"@opentelemetry/instrumentation-redis": "^0.46.0",
|
"@opentelemetry/instrumentation-redis": "^0.46.0",
|
||||||
"@opentelemetry/instrumentation-redis-4": "^0.46.0",
|
"@opentelemetry/instrumentation-redis-4": "^0.46.0",
|
||||||
@@ -3626,9 +3626,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@opentelemetry/instrumentation-cucumber": {
|
"node_modules/@opentelemetry/instrumentation-cucumber": {
|
||||||
"version": "0.13.0",
|
"version": "0.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-cucumber/-/instrumentation-cucumber-0.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-cucumber/-/instrumentation-cucumber-0.14.0.tgz",
|
||||||
"integrity": "sha512-ZBswBKONU2g7mhjEKF4vkTXxezq16QdvGaD5W4o01/t5KzvCZGQ6hYPsB34miJIj/hh6UrFLRDAjqb7nur5I3Q==",
|
"integrity": "sha512-i/GlurL1IM+CnbmItW8kx59YxAp0wu/YQkzQQRU/YGmUjym5g+/dOVjnk/K46lAU49Nn1XyFd7S3ZNf83PHL2Q==",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@opentelemetry/instrumentation": "^0.57.0",
|
"@opentelemetry/instrumentation": "^0.57.0",
|
||||||
@@ -3952,9 +3952,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@opentelemetry/instrumentation-mysql2": {
|
"node_modules/@opentelemetry/instrumentation-mysql2": {
|
||||||
"version": "0.45.0",
|
"version": "0.45.1",
|
||||||
"resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql2/-/instrumentation-mysql2-0.45.0.tgz",
|
"resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql2/-/instrumentation-mysql2-0.45.1.tgz",
|
||||||
"integrity": "sha512-qLslv/EPuLj0IXFvcE3b0EqhWI8LKmrgRPIa4gUd8DllbBpqJAvLNJSv3cC6vWwovpbSI3bagNO/3Q2SuXv2xA==",
|
"integrity": "sha512-9R/vxEc02vlSqyQSmXRTvFMZVht8vgSJokKhiWA3z8Idu0mmdKFKeHiuW5yRGxM/WOi+7DWqQfYM7zw/cJc3sA==",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@opentelemetry/instrumentation": "^0.57.0",
|
"@opentelemetry/instrumentation": "^0.57.0",
|
||||||
@@ -4001,14 +4001,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@opentelemetry/instrumentation-pg": {
|
"node_modules/@opentelemetry/instrumentation-pg": {
|
||||||
"version": "0.50.0",
|
"version": "0.51.0",
|
||||||
"resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-pg/-/instrumentation-pg-0.50.0.tgz",
|
"resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-pg/-/instrumentation-pg-0.51.0.tgz",
|
||||||
"integrity": "sha512-TtLxDdYZmBhFswm8UIsrDjh/HFBeDXd4BLmE8h2MxirNHewLJ0VS9UUddKKEverb5Sm2qFVjqRjcU+8Iw4FJ3w==",
|
"integrity": "sha512-/NStIcUWUofc11dL7tSgMk25NqvhtbHDCncgm+yc4iJF8Ste2Q/lwUitjfxqj4qWM280uFmBEtcmtMMjbjRU7Q==",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@opentelemetry/core": "^1.26.0",
|
"@opentelemetry/core": "^1.26.0",
|
||||||
"@opentelemetry/instrumentation": "^0.57.0",
|
"@opentelemetry/instrumentation": "^0.57.0",
|
||||||
"@opentelemetry/semantic-conventions": "1.27.0",
|
"@opentelemetry/semantic-conventions": "^1.27.0",
|
||||||
"@opentelemetry/sql-common": "^0.40.1",
|
"@opentelemetry/sql-common": "^0.40.1",
|
||||||
"@types/pg": "8.6.1",
|
"@types/pg": "8.6.1",
|
||||||
"@types/pg-pool": "2.0.6"
|
"@types/pg-pool": "2.0.6"
|
||||||
@@ -4020,15 +4020,6 @@
|
|||||||
"@opentelemetry/api": "^1.3.0"
|
"@opentelemetry/api": "^1.3.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@opentelemetry/instrumentation-pg/node_modules/@opentelemetry/semantic-conventions": {
|
|
||||||
"version": "1.27.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.27.0.tgz",
|
|
||||||
"integrity": "sha512-sAay1RrB+ONOem0OZanAR1ZI/k7yDpnOQSQmTMuGImUQb2y8EbSaCJ94FQluM74xoU03vlb2d2U90hZluL6nQg==",
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=14"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@opentelemetry/instrumentation-pino": {
|
"node_modules/@opentelemetry/instrumentation-pino": {
|
||||||
"version": "0.46.0",
|
"version": "0.46.0",
|
||||||
"resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-pino/-/instrumentation-pino-0.46.0.tgz",
|
"resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-pino/-/instrumentation-pino-0.46.0.tgz",
|
||||||
@@ -5270,9 +5261,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@swc/core": {
|
"node_modules/@swc/core": {
|
||||||
"version": "1.10.7",
|
"version": "1.10.14",
|
||||||
"resolved": "https://registry.npmjs.org/@swc/core/-/core-1.10.7.tgz",
|
"resolved": "https://registry.npmjs.org/@swc/core/-/core-1.10.14.tgz",
|
||||||
"integrity": "sha512-py91kjI1jV5D5W/Q+PurBdGsdU5TFbrzamP7zSCqLdMcHkKi3rQEM5jkQcZr0MXXSJTaayLxS3MWYTBIkzPDrg==",
|
"integrity": "sha512-WSrnE6JRnH20ZYjOOgSS4aOaPv9gxlkI2KRkN24kagbZnPZMnN8bZZyzw1rrLvwgpuRGv17Uz+hflosbR+SP6w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
@@ -5288,16 +5279,16 @@
|
|||||||
"url": "https://opencollective.com/swc"
|
"url": "https://opencollective.com/swc"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@swc/core-darwin-arm64": "1.10.7",
|
"@swc/core-darwin-arm64": "1.10.14",
|
||||||
"@swc/core-darwin-x64": "1.10.7",
|
"@swc/core-darwin-x64": "1.10.14",
|
||||||
"@swc/core-linux-arm-gnueabihf": "1.10.7",
|
"@swc/core-linux-arm-gnueabihf": "1.10.14",
|
||||||
"@swc/core-linux-arm64-gnu": "1.10.7",
|
"@swc/core-linux-arm64-gnu": "1.10.14",
|
||||||
"@swc/core-linux-arm64-musl": "1.10.7",
|
"@swc/core-linux-arm64-musl": "1.10.14",
|
||||||
"@swc/core-linux-x64-gnu": "1.10.7",
|
"@swc/core-linux-x64-gnu": "1.10.14",
|
||||||
"@swc/core-linux-x64-musl": "1.10.7",
|
"@swc/core-linux-x64-musl": "1.10.14",
|
||||||
"@swc/core-win32-arm64-msvc": "1.10.7",
|
"@swc/core-win32-arm64-msvc": "1.10.14",
|
||||||
"@swc/core-win32-ia32-msvc": "1.10.7",
|
"@swc/core-win32-ia32-msvc": "1.10.14",
|
||||||
"@swc/core-win32-x64-msvc": "1.10.7"
|
"@swc/core-win32-x64-msvc": "1.10.14"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@swc/helpers": "*"
|
"@swc/helpers": "*"
|
||||||
@@ -5309,9 +5300,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@swc/core-darwin-arm64": {
|
"node_modules/@swc/core-darwin-arm64": {
|
||||||
"version": "1.10.7",
|
"version": "1.10.14",
|
||||||
"resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.10.7.tgz",
|
"resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.10.14.tgz",
|
||||||
"integrity": "sha512-SI0OFg987P6hcyT0Dbng3YRISPS9uhLX1dzW4qRrfqQdb0i75lPJ2YWe9CN47HBazrIA5COuTzrD2Dc0TcVsSQ==",
|
"integrity": "sha512-Dh4VyrhDDb05tdRmqJ/MucOPMTnrB4pRJol18HVyLlqu1HOT5EzonUniNTCdQbUXjgdv5UVJSTE1lYTzrp+myA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -5326,9 +5317,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@swc/core-darwin-x64": {
|
"node_modules/@swc/core-darwin-x64": {
|
||||||
"version": "1.10.7",
|
"version": "1.10.14",
|
||||||
"resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.10.7.tgz",
|
"resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.10.14.tgz",
|
||||||
"integrity": "sha512-RFIAmWVicD/l3RzxgHW0R/G1ya/6nyMspE2cAeDcTbjHi0I5qgdhBWd6ieXOaqwEwiCd0Mot1g2VZrLGoBLsjQ==",
|
"integrity": "sha512-KpzotL/I0O12RE3tF8NmQErINv0cQe/0mnN/Q50ESFzB5kU6bLgp2HMnnwDTm/XEZZRJCNe0oc9WJ5rKbAJFRQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -5343,9 +5334,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@swc/core-linux-arm-gnueabihf": {
|
"node_modules/@swc/core-linux-arm-gnueabihf": {
|
||||||
"version": "1.10.7",
|
"version": "1.10.14",
|
||||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.10.7.tgz",
|
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.10.14.tgz",
|
||||||
"integrity": "sha512-QP8vz7yELWfop5mM5foN6KkLylVO7ZUgWSF2cA0owwIaziactB2hCPZY5QU690coJouk9KmdFsPWDnaCFUP8tg==",
|
"integrity": "sha512-20yRXZjMJVz1wp1TcscKiGTVXistG+saIaxOmxSNQia1Qun3hSWLL+u6+5kXbfYGr7R2N6kqSwtZbIfJI25r9Q==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
@@ -5360,9 +5351,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@swc/core-linux-arm64-gnu": {
|
"node_modules/@swc/core-linux-arm64-gnu": {
|
||||||
"version": "1.10.7",
|
"version": "1.10.14",
|
||||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.10.7.tgz",
|
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.10.14.tgz",
|
||||||
"integrity": "sha512-NgUDBGQcOeLNR+EOpmUvSDIP/F7i/OVOKxst4wOvT5FTxhnkWrW+StJGKj+DcUVSK5eWOYboSXr1y+Hlywwokw==",
|
"integrity": "sha512-Gy7cGrNkiMfPxQyLGxdgXPwyWzNzbHuWycJFcoKBihxZKZIW8hkPBttkGivuLC+0qOgsV2/U+S7tlvAju7FtmQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -5377,9 +5368,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@swc/core-linux-arm64-musl": {
|
"node_modules/@swc/core-linux-arm64-musl": {
|
||||||
"version": "1.10.7",
|
"version": "1.10.14",
|
||||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.10.7.tgz",
|
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.10.14.tgz",
|
||||||
"integrity": "sha512-gp5Un3EbeSThBIh6oac5ZArV/CsSmTKj5jNuuUAuEsML3VF9vqPO+25VuxCvsRf/z3py+xOWRaN2HY/rjMeZog==",
|
"integrity": "sha512-+oYVqJvFw62InZ8PIy1rBACJPC2WTe4vbVb9kM1jJj2D7dKLm9acnnYIVIDsM5Wo7Uab8RvPHXVbs19IBurzuw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -5394,9 +5385,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@swc/core-linux-x64-gnu": {
|
"node_modules/@swc/core-linux-x64-gnu": {
|
||||||
"version": "1.10.7",
|
"version": "1.10.14",
|
||||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.10.7.tgz",
|
"resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.10.14.tgz",
|
||||||
"integrity": "sha512-k/OxLLMl/edYqbZyUNg6/bqEHTXJT15l9WGqsl/2QaIGwWGvles8YjruQYQ9d4h/thSXLT9gd8bExU2D0N+bUA==",
|
"integrity": "sha512-OmEbVEKQFLQVHwo4EJl9osmlulURy46k232Opfpn/1ji0t2KcNCci3POsnfMuoZjLkGJv8vGNJdPQxX+CP+wSA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -5411,9 +5402,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@swc/core-linux-x64-musl": {
|
"node_modules/@swc/core-linux-x64-musl": {
|
||||||
"version": "1.10.7",
|
"version": "1.10.14",
|
||||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.10.7.tgz",
|
"resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.10.14.tgz",
|
||||||
"integrity": "sha512-XeDoURdWt/ybYmXLCEE8aSiTOzEn0o3Dx5l9hgt0IZEmTts7HgHHVeRgzGXbR4yDo0MfRuX5nE1dYpTmCz0uyA==",
|
"integrity": "sha512-OZW+Icm8DMPqHbhdxplkuG8qrNnPk5i7xJOZWYi1y5bTjgGFI4nEzrsmmeHKMdQTaWwsFrm3uK1rlyQ48MmXmg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -5428,9 +5419,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@swc/core-win32-arm64-msvc": {
|
"node_modules/@swc/core-win32-arm64-msvc": {
|
||||||
"version": "1.10.7",
|
"version": "1.10.14",
|
||||||
"resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.10.7.tgz",
|
"resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.10.14.tgz",
|
||||||
"integrity": "sha512-nYAbi/uLS+CU0wFtBx8TquJw2uIMKBnl04LBmiVoFrsIhqSl+0MklaA9FVMGA35NcxSJfcm92Prl2W2LfSnTqQ==",
|
"integrity": "sha512-sTvc+xrDQXy3HXZFtTEClY35Efvuc3D+busYm0+rb1+Thau4HLRY9WP+sOKeGwH9/16rzfzYEqD7Ds8A9ykrHw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -5445,9 +5436,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@swc/core-win32-ia32-msvc": {
|
"node_modules/@swc/core-win32-ia32-msvc": {
|
||||||
"version": "1.10.7",
|
"version": "1.10.14",
|
||||||
"resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.10.7.tgz",
|
"resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.10.14.tgz",
|
||||||
"integrity": "sha512-+aGAbsDsIxeLxw0IzyQLtvtAcI1ctlXVvVcXZMNXIXtTURM876yNrufRo4ngoXB3jnb1MLjIIjgXfFs/eZTUSw==",
|
"integrity": "sha512-j2iQ4y9GWTKtES5eMU0sDsFdYni7IxME7ejFej25Tv3Fq4B+U9tgtYWlJwh1858nIWDXelHiKcSh/UICAyVMdQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ia32"
|
"ia32"
|
||||||
],
|
],
|
||||||
@@ -5462,9 +5453,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@swc/core-win32-x64-msvc": {
|
"node_modules/@swc/core-win32-x64-msvc": {
|
||||||
"version": "1.10.7",
|
"version": "1.10.14",
|
||||||
"resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.10.7.tgz",
|
"resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.10.14.tgz",
|
||||||
"integrity": "sha512-TBf4clpDBjF/UUnkKrT0/th76/zwvudk5wwobiTFqDywMApHip5O0VpBgZ+4raY2TM8k5+ujoy7bfHb22zu17Q==",
|
"integrity": "sha512-TYtWkUSMkjs0jGPeWdtWbex4B+DlQZmN/ySVLiPI+EltYCLEXsFMkVFq6aWn48dqFHggFK0UYfvDrJUR2c3Qxg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -5504,13 +5495,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@testcontainers/postgresql": {
|
"node_modules/@testcontainers/postgresql": {
|
||||||
"version": "10.16.0",
|
"version": "10.18.0",
|
||||||
"resolved": "https://registry.npmjs.org/@testcontainers/postgresql/-/postgresql-10.16.0.tgz",
|
"resolved": "https://registry.npmjs.org/@testcontainers/postgresql/-/postgresql-10.18.0.tgz",
|
||||||
"integrity": "sha512-zWFQI+3QxlEELRvVv27i6zlVEPNUz9zKaSh7iWmFlCdfhcyr78daS0FG8FIfdQ79VK7YXA4jv+dTYXa2SwXu/w==",
|
"integrity": "sha512-WxkE/tBlBpoKvqDEqL3i/mL6BOBWnXb8FXKtLhEeZ3lSt0zlldkTozMmewNsKJtFTBZdv7uFwMzWyXP12t0sxQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"testcontainers": "^10.16.0"
|
"testcontainers": "^10.18.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@turf/boolean-point-in-polygon": {
|
"node_modules/@turf/boolean-point-in-polygon": {
|
||||||
@@ -5777,9 +5768,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@types/lodash": {
|
"node_modules/@types/lodash": {
|
||||||
"version": "4.17.14",
|
"version": "4.17.15",
|
||||||
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.14.tgz",
|
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.15.tgz",
|
||||||
"integrity": "sha512-jsxagdikDiDBeIRaPYtArcT8my4tN1og7MtMRquFT3XNA6axxyHDRUemqDz/taRDdOUn0GnGHRCuff4q48sW9A==",
|
"integrity": "sha512-w/P33JFeySuhN6JLkysYUK2gEmy9kHHFN7E8ro0tkfmlDOgxBDzWEZ/J8cWA+fHqFevpswDTFZnDx+R9lbL6xw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
@@ -5842,9 +5833,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/node": {
|
"node_modules/@types/node": {
|
||||||
"version": "22.10.9",
|
"version": "22.13.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.9.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.1.tgz",
|
||||||
"integrity": "sha512-Ir6hwgsKyNESl/gLOcEz3krR4CBGgliDqBQ2ma4wIhEx0w+xnoeTq3tdrNw15kU3SxogDjOgv9sqdtLW8mIHaw==",
|
"integrity": "sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"undici-types": "~6.20.0"
|
"undici-types": "~6.20.0"
|
||||||
@@ -5919,9 +5910,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@types/react": {
|
"node_modules/@types/react": {
|
||||||
"version": "19.0.7",
|
"version": "19.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.0.8.tgz",
|
||||||
"integrity": "sha512-MoFsEJKkAtZCrC1r6CM8U22GzhG7u2Wir8ons/aCKH6MBdD1ibV24zOSSkdZVUKqN5i396zG5VKLYZ3yaUZdLA==",
|
"integrity": "sha512-9P/o1IGdfmQxrujGbIMDyYaaCykhLKc0NGCtYcECNUr9UAaDe4gwvV9bR6tvd5Br1SG0j+PBpbKr2UYY8CwqSw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -6068,21 +6059,21 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||||
"version": "8.20.0",
|
"version": "8.23.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.20.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.23.0.tgz",
|
||||||
"integrity": "sha512-naduuphVw5StFfqp4Gq4WhIBE2gN1GEmMUExpJYknZJdRnc+2gDzB8Z3+5+/Kv33hPQRDGzQO/0opHE72lZZ6A==",
|
"integrity": "sha512-vBz65tJgRrA1Q5gWlRfvoH+w943dq9K1p1yDBY2pc+a1nbBLZp7fB9+Hk8DaALUbzjqlMfgaqlVPT1REJdkt/w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/regexpp": "^4.10.0",
|
"@eslint-community/regexpp": "^4.10.0",
|
||||||
"@typescript-eslint/scope-manager": "8.20.0",
|
"@typescript-eslint/scope-manager": "8.23.0",
|
||||||
"@typescript-eslint/type-utils": "8.20.0",
|
"@typescript-eslint/type-utils": "8.23.0",
|
||||||
"@typescript-eslint/utils": "8.20.0",
|
"@typescript-eslint/utils": "8.23.0",
|
||||||
"@typescript-eslint/visitor-keys": "8.20.0",
|
"@typescript-eslint/visitor-keys": "8.23.0",
|
||||||
"graphemer": "^1.4.0",
|
"graphemer": "^1.4.0",
|
||||||
"ignore": "^5.3.1",
|
"ignore": "^5.3.1",
|
||||||
"natural-compare": "^1.4.0",
|
"natural-compare": "^1.4.0",
|
||||||
"ts-api-utils": "^2.0.0"
|
"ts-api-utils": "^2.0.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
@@ -6098,16 +6089,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/parser": {
|
"node_modules/@typescript-eslint/parser": {
|
||||||
"version": "8.20.0",
|
"version": "8.23.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.20.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.23.0.tgz",
|
||||||
"integrity": "sha512-gKXG7A5HMyjDIedBi6bUrDcun8GIjnI8qOwVLiY3rx6T/sHP/19XLJOnIq/FgQvWLHja5JN/LSE7eklNBr612g==",
|
"integrity": "sha512-h2lUByouOXFAlMec2mILeELUbME5SZRN/7R9Cw2RD2lRQQY08MWMM+PmVVKKJNK1aIwqTo9t/0CvOxwPbRIE2Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/scope-manager": "8.20.0",
|
"@typescript-eslint/scope-manager": "8.23.0",
|
||||||
"@typescript-eslint/types": "8.20.0",
|
"@typescript-eslint/types": "8.23.0",
|
||||||
"@typescript-eslint/typescript-estree": "8.20.0",
|
"@typescript-eslint/typescript-estree": "8.23.0",
|
||||||
"@typescript-eslint/visitor-keys": "8.20.0",
|
"@typescript-eslint/visitor-keys": "8.23.0",
|
||||||
"debug": "^4.3.4"
|
"debug": "^4.3.4"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -6123,14 +6114,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/scope-manager": {
|
"node_modules/@typescript-eslint/scope-manager": {
|
||||||
"version": "8.20.0",
|
"version": "8.23.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.20.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.23.0.tgz",
|
||||||
"integrity": "sha512-J7+VkpeGzhOt3FeG1+SzhiMj9NzGD/M6KoGn9f4dbz3YzK9hvbhVTmLj/HiTp9DazIzJ8B4XcM80LrR9Dm1rJw==",
|
"integrity": "sha512-OGqo7+dXHqI7Hfm+WqkZjKjsiRtFUQHPdGMXzk5mYXhJUedO7e/Y7i8AK3MyLMgZR93TX4bIzYrfyVjLC+0VSw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/types": "8.20.0",
|
"@typescript-eslint/types": "8.23.0",
|
||||||
"@typescript-eslint/visitor-keys": "8.20.0"
|
"@typescript-eslint/visitor-keys": "8.23.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
@@ -6141,16 +6132,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/type-utils": {
|
"node_modules/@typescript-eslint/type-utils": {
|
||||||
"version": "8.20.0",
|
"version": "8.23.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.20.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.23.0.tgz",
|
||||||
"integrity": "sha512-bPC+j71GGvA7rVNAHAtOjbVXbLN5PkwqMvy1cwGeaxUoRQXVuKCebRoLzm+IPW/NtFFpstn1ummSIasD5t60GA==",
|
"integrity": "sha512-iIuLdYpQWZKbiH+RkCGc6iu+VwscP5rCtQ1lyQ7TYuKLrcZoeJVpcLiG8DliXVkUxirW/PWlmS+d6yD51L9jvA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/typescript-estree": "8.20.0",
|
"@typescript-eslint/typescript-estree": "8.23.0",
|
||||||
"@typescript-eslint/utils": "8.20.0",
|
"@typescript-eslint/utils": "8.23.0",
|
||||||
"debug": "^4.3.4",
|
"debug": "^4.3.4",
|
||||||
"ts-api-utils": "^2.0.0"
|
"ts-api-utils": "^2.0.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
@@ -6165,9 +6156,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/types": {
|
"node_modules/@typescript-eslint/types": {
|
||||||
"version": "8.20.0",
|
"version": "8.23.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.20.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.23.0.tgz",
|
||||||
"integrity": "sha512-cqaMiY72CkP+2xZRrFt3ExRBu0WmVitN/rYPZErA80mHjHx/Svgp8yfbzkJmDoQ/whcytOPO9/IZXnOc+wigRA==",
|
"integrity": "sha512-1sK4ILJbCmZOTt9k4vkoulT6/y5CHJ1qUYxqpF1K/DBAd8+ZUL4LlSCxOssuH5m4rUaaN0uS0HlVPvd45zjduQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -6179,20 +6170,20 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/typescript-estree": {
|
"node_modules/@typescript-eslint/typescript-estree": {
|
||||||
"version": "8.20.0",
|
"version": "8.23.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.20.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.23.0.tgz",
|
||||||
"integrity": "sha512-Y7ncuy78bJqHI35NwzWol8E0X7XkRVS4K4P4TCyzWkOJih5NDvtoRDW4Ba9YJJoB2igm9yXDdYI/+fkiiAxPzA==",
|
"integrity": "sha512-LcqzfipsB8RTvH8FX24W4UUFk1bl+0yTOf9ZA08XngFwMg4Kj8A+9hwz8Cr/ZS4KwHrmo9PJiLZkOt49vPnuvQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/types": "8.20.0",
|
"@typescript-eslint/types": "8.23.0",
|
||||||
"@typescript-eslint/visitor-keys": "8.20.0",
|
"@typescript-eslint/visitor-keys": "8.23.0",
|
||||||
"debug": "^4.3.4",
|
"debug": "^4.3.4",
|
||||||
"fast-glob": "^3.3.2",
|
"fast-glob": "^3.3.2",
|
||||||
"is-glob": "^4.0.3",
|
"is-glob": "^4.0.3",
|
||||||
"minimatch": "^9.0.4",
|
"minimatch": "^9.0.4",
|
||||||
"semver": "^7.6.0",
|
"semver": "^7.6.0",
|
||||||
"ts-api-utils": "^2.0.0"
|
"ts-api-utils": "^2.0.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
@@ -6232,16 +6223,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/utils": {
|
"node_modules/@typescript-eslint/utils": {
|
||||||
"version": "8.20.0",
|
"version": "8.23.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.20.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.23.0.tgz",
|
||||||
"integrity": "sha512-dq70RUw6UK9ei7vxc4KQtBRk7qkHZv447OUZ6RPQMQl71I3NZxQJX/f32Smr+iqWrB02pHKn2yAdHBb0KNrRMA==",
|
"integrity": "sha512-uB/+PSo6Exu02b5ZEiVtmY6RVYO7YU5xqgzTIVZwTHvvK3HsL8tZZHFaTLFtRG3CsV4A5mhOv+NZx5BlhXPyIA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/eslint-utils": "^4.4.0",
|
"@eslint-community/eslint-utils": "^4.4.0",
|
||||||
"@typescript-eslint/scope-manager": "8.20.0",
|
"@typescript-eslint/scope-manager": "8.23.0",
|
||||||
"@typescript-eslint/types": "8.20.0",
|
"@typescript-eslint/types": "8.23.0",
|
||||||
"@typescript-eslint/typescript-estree": "8.20.0"
|
"@typescript-eslint/typescript-estree": "8.23.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
@@ -6256,13 +6247,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/visitor-keys": {
|
"node_modules/@typescript-eslint/visitor-keys": {
|
||||||
"version": "8.20.0",
|
"version": "8.23.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.20.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.23.0.tgz",
|
||||||
"integrity": "sha512-v/BpkeeYAsPkKCkR8BDwcno0llhzWVqPOamQrAEMdpZav2Y9OVjd9dwJyBLJWwf335B5DmlifECIkZRJCaGaHA==",
|
"integrity": "sha512-oWWhcWDLwDfu++BGTZcmXWqpwtkwb5o7fxUIGksMQQDSdPW9prsSnfIOZMlsj4vBOSrcnjIUZMiIjODgGosFhQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/types": "8.20.0",
|
"@typescript-eslint/types": "8.23.0",
|
||||||
"eslint-visitor-keys": "^4.2.0"
|
"eslint-visitor-keys": "^4.2.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -6287,9 +6278,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vitest/coverage-v8": {
|
"node_modules/@vitest/coverage-v8": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.0.5.tgz",
|
||||||
"integrity": "sha512-uVbJ/xhImdNtzPnLyxCZJMTeTIYdgcC2nWtBBBpR1H6z0w8m7D+9/zrDIx2nNxgMg9r+X8+RY2qVpUDeW2b3nw==",
|
"integrity": "sha512-zOOWIsj5fHh3jjGwQg+P+J1FW3s4jBu1Zqga0qW60yutsBtqEqNEJKWYh7cYn1yGD+1bdPsPdC/eL4eVK56xMg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -6310,8 +6301,8 @@
|
|||||||
"url": "https://opencollective.com/vitest"
|
"url": "https://opencollective.com/vitest"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@vitest/browser": "3.0.3",
|
"@vitest/browser": "3.0.5",
|
||||||
"vitest": "3.0.3"
|
"vitest": "3.0.5"
|
||||||
},
|
},
|
||||||
"peerDependenciesMeta": {
|
"peerDependenciesMeta": {
|
||||||
"@vitest/browser": {
|
"@vitest/browser": {
|
||||||
@@ -6320,14 +6311,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vitest/expect": {
|
"node_modules/@vitest/expect": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.5.tgz",
|
||||||
"integrity": "sha512-SbRCHU4qr91xguu+dH3RUdI5dC86zm8aZWydbp961aIR7G8OYNN6ZiayFuf9WAngRbFOfdrLHCGgXTj3GtoMRQ==",
|
"integrity": "sha512-nNIOqupgZ4v5jWuQx2DSlHLEs7Q4Oh/7AYwNyE+k0UQzG7tSmjPXShUikn1mpNGzYEN2jJbTvLejwShMitovBA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vitest/spy": "3.0.3",
|
"@vitest/spy": "3.0.5",
|
||||||
"@vitest/utils": "3.0.3",
|
"@vitest/utils": "3.0.5",
|
||||||
"chai": "^5.1.2",
|
"chai": "^5.1.2",
|
||||||
"tinyrainbow": "^2.0.0"
|
"tinyrainbow": "^2.0.0"
|
||||||
},
|
},
|
||||||
@@ -6336,13 +6327,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vitest/mocker": {
|
"node_modules/@vitest/mocker": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.5.tgz",
|
||||||
"integrity": "sha512-XT2XBc4AN9UdaxJAeIlcSZ0ILi/GzmG5G8XSly4gaiqIvPV3HMTSIDZWJVX6QRJ0PX1m+W8Cy0K9ByXNb/bPIA==",
|
"integrity": "sha512-CLPNBFBIE7x6aEGbIjaQAX03ZZlBMaWwAjBdMkIf/cAn6xzLTiM3zYqO/WAbieEjsAZir6tO71mzeHZoodThvw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vitest/spy": "3.0.3",
|
"@vitest/spy": "3.0.5",
|
||||||
"estree-walker": "^3.0.3",
|
"estree-walker": "^3.0.3",
|
||||||
"magic-string": "^0.30.17"
|
"magic-string": "^0.30.17"
|
||||||
},
|
},
|
||||||
@@ -6373,9 +6364,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vitest/pretty-format": {
|
"node_modules/@vitest/pretty-format": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.5.tgz",
|
||||||
"integrity": "sha512-gCrM9F7STYdsDoNjGgYXKPq4SkSxwwIU5nkaQvdUxiQ0EcNlez+PdKOVIsUJvh9P9IeIFmjn4IIREWblOBpP2Q==",
|
"integrity": "sha512-CjUtdmpOcm4RVtB+up8r2vVDLR16Mgm/bYdkGFe3Yj/scRfCpbSi2W/BDSDcFK7ohw8UXvjMbOp9H4fByd/cOA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -6386,38 +6377,38 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vitest/runner": {
|
"node_modules/@vitest/runner": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.5.tgz",
|
||||||
"integrity": "sha512-Rgi2kOAk5ZxWZlwPguRJFOBmWs6uvvyAAR9k3MvjRvYrG7xYvKChZcmnnpJCS98311CBDMqsW9MzzRFsj2gX3g==",
|
"integrity": "sha512-BAiZFityFexZQi2yN4OX3OkJC6scwRo8EhRB0Z5HIGGgd2q+Nq29LgHU/+ovCtd0fOfXj5ZI6pwdlUmC5bpi8A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vitest/utils": "3.0.3",
|
"@vitest/utils": "3.0.5",
|
||||||
"pathe": "^2.0.1"
|
"pathe": "^2.0.2"
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://opencollective.com/vitest"
|
"url": "https://opencollective.com/vitest"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vitest/snapshot": {
|
"node_modules/@vitest/snapshot": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.5.tgz",
|
||||||
"integrity": "sha512-kNRcHlI4txBGztuJfPEJ68VezlPAXLRT1u5UCx219TU3kOG2DplNxhWLwDf2h6emwmTPogzLnGVwP6epDaJN6Q==",
|
"integrity": "sha512-GJPZYcd7v8QNUJ7vRvLDmRwl+a1fGg4T/54lZXe+UOGy47F9yUfE18hRCtXL5aHN/AONu29NGzIXSVFh9K0feA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vitest/pretty-format": "3.0.3",
|
"@vitest/pretty-format": "3.0.5",
|
||||||
"magic-string": "^0.30.17",
|
"magic-string": "^0.30.17",
|
||||||
"pathe": "^2.0.1"
|
"pathe": "^2.0.2"
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://opencollective.com/vitest"
|
"url": "https://opencollective.com/vitest"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vitest/spy": {
|
"node_modules/@vitest/spy": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.5.tgz",
|
||||||
"integrity": "sha512-7/dgux8ZBbF7lEIKNnEqQlyRaER9nkAL9eTmdKJkDO3hS8p59ATGwKOCUDHcBLKr7h/oi/6hP+7djQk8049T2A==",
|
"integrity": "sha512-5fOzHj0WbUNqPK6blI/8VzZdkBlQLnT25knX0r4dbZI9qoZDf3qAdjoMmDcLG5A83W6oUUFJgUd0EYBc2P5xqg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -6428,13 +6419,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vitest/utils": {
|
"node_modules/@vitest/utils": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.5.tgz",
|
||||||
"integrity": "sha512-f+s8CvyzPtMFY1eZKkIHGhPsQgYo5qCm6O8KZoim9qm1/jT64qBgGpO5tHscNH6BzRHM+edLNOP+3vO8+8pE/A==",
|
"integrity": "sha512-N9AX0NUoUtVwKwy21JtwzaqR5L5R5A99GAbrHfCCXK1lp593i/3AZAXhSP43wRQuxYsflrdzEfXZFo1reR1Nkg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vitest/pretty-format": "3.0.3",
|
"@vitest/pretty-format": "3.0.5",
|
||||||
"loupe": "^3.1.2",
|
"loupe": "^3.1.2",
|
||||||
"tinyrainbow": "^2.0.0"
|
"tinyrainbow": "^2.0.0"
|
||||||
},
|
},
|
||||||
@@ -8836,9 +8827,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint": {
|
"node_modules/eslint": {
|
||||||
"version": "9.18.0",
|
"version": "9.19.0",
|
||||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.18.0.tgz",
|
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.19.0.tgz",
|
||||||
"integrity": "sha512-+waTfRWQlSbpt3KWE+CjrPPYnbq9kfZIYUqapc0uBXyjTp8aYXZDsUH16m39Ryq3NjAVP4tjuF7KaukeqoCoaA==",
|
"integrity": "sha512-ug92j0LepKlbbEv6hD911THhoRHmbdXt2gX+VDABAW/Ir7D3nqKdv5Pf5vtlyY6HQMTEP2skXY43ueqTCWssEA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -8847,7 +8838,7 @@
|
|||||||
"@eslint/config-array": "^0.19.0",
|
"@eslint/config-array": "^0.19.0",
|
||||||
"@eslint/core": "^0.10.0",
|
"@eslint/core": "^0.10.0",
|
||||||
"@eslint/eslintrc": "^3.2.0",
|
"@eslint/eslintrc": "^3.2.0",
|
||||||
"@eslint/js": "9.18.0",
|
"@eslint/js": "9.19.0",
|
||||||
"@eslint/plugin-kit": "^0.2.5",
|
"@eslint/plugin-kit": "^0.2.5",
|
||||||
"@humanfs/node": "^0.16.6",
|
"@humanfs/node": "^0.16.6",
|
||||||
"@humanwhocodes/module-importer": "^1.0.1",
|
"@humanwhocodes/module-importer": "^1.0.1",
|
||||||
@@ -8909,9 +8900,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint-plugin-prettier": {
|
"node_modules/eslint-plugin-prettier": {
|
||||||
"version": "5.2.2",
|
"version": "5.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.3.tgz",
|
||||||
"integrity": "sha512-1yI3/hf35wmlq66C8yOyrujQnel+v5l1Vop5Cl2I6ylyNTT1JbuUUnV3/41PzwTzcyDp/oF0jWE3HXvcH5AQOQ==",
|
"integrity": "sha512-qJ+y0FfCp/mQYQ/vWQ3s7eUlFEL4PyKfAJxsnYTJ4YT73nsJBWqmEpFryxV9OeUiqmsTsYJ5Y+KDNaeP31wrRw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -9861,9 +9852,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/geo-tz": {
|
"node_modules/geo-tz": {
|
||||||
"version": "8.1.2",
|
"version": "8.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/geo-tz/-/geo-tz-8.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/geo-tz/-/geo-tz-8.1.3.tgz",
|
||||||
"integrity": "sha512-S1udoP7MZ+CVu+7Iy/VayVNmEHTWgfJ52TjpfC2/4f+j0SB/ZXMjGrwZTqPMo6/O2m5lrGLCFCY0bkxUqiLN+g==",
|
"integrity": "sha512-zzF0hjqLl+1n5tXDCxwdS/BmF+N1TdQc6rbubh6PO6/9DtntX/yBox1Ti0q24MrjajWG0fSv0gv2w6Zff/kmeA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@turf/boolean-point-in-polygon": "^7.1.0",
|
"@turf/boolean-point-in-polygon": "^7.1.0",
|
||||||
@@ -11210,9 +11201,9 @@
|
|||||||
"license": "Apache-2.0"
|
"license": "Apache-2.0"
|
||||||
},
|
},
|
||||||
"node_modules/loupe": {
|
"node_modules/loupe": {
|
||||||
"version": "3.1.2",
|
"version": "3.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.3.tgz",
|
||||||
"integrity": "sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==",
|
"integrity": "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
@@ -11515,9 +11506,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/mock-fs": {
|
"node_modules/mock-fs": {
|
||||||
"version": "5.4.1",
|
"version": "5.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-5.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-5.5.0.tgz",
|
||||||
"integrity": "sha512-sz/Q8K1gXXXHR+qr0GZg2ysxCRr323kuN10O7CtQjraJsFDJ4SJ+0I5MzALz7aRp9lHk8Cc/YdsT95h9Ka1aFw==",
|
"integrity": "sha512-d/P1M/RacgM3dB0sJ8rjeRNXxtapkPCUnMGmIN0ixJ16F/E4GUZCvWcSGfWGz8eaXYvn1s9baUwNjI4LOPEjiA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -11803,9 +11794,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/nestjs-cls": {
|
"node_modules/nestjs-cls": {
|
||||||
"version": "5.0.0",
|
"version": "5.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/nestjs-cls/-/nestjs-cls-5.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/nestjs-cls/-/nestjs-cls-5.0.1.tgz",
|
||||||
"integrity": "sha512-0rpkCngRISkd2x9z7q0bR8R4AeZe43WkLBaDuTE6Uaw9r1OEWfEGfGS6M4OlXG20CIxDtaAIbWW8wFM5YCNRkA==",
|
"integrity": "sha512-TA1qkFkkWct1LXXjcNk4jxQgvZrL34bojK3D4oOo59ru7xrQ1erN3/737T+XezOZ2ZPngGVeJZ9WipaD9N+G0Q==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16"
|
"node": ">=16"
|
||||||
@@ -11966,9 +11957,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/nodemailer": {
|
"node_modules/nodemailer": {
|
||||||
"version": "6.9.16",
|
"version": "6.10.0",
|
||||||
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.16.tgz",
|
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.10.0.tgz",
|
||||||
"integrity": "sha512-psAuZdTIRN08HKVd/E8ObdV6NO7NTBY3KsC30F7M4H1OnmLCUNaS56FpYxyb26zWLSyYF9Ozch9KYHhHegsiOQ==",
|
"integrity": "sha512-SQ3wZCExjeSatLE/HBaXS5vqUOQk6GtBdIIKxiFdmm01mOQZX/POJkO3SUX1wDiYcwUOJwT23scFSC9fY2H8IA==",
|
||||||
"license": "MIT-0",
|
"license": "MIT-0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.0.0"
|
"node": ">=6.0.0"
|
||||||
@@ -14028,9 +14019,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/semver": {
|
"node_modules/semver": {
|
||||||
"version": "7.6.3",
|
"version": "7.7.1",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
|
||||||
"integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
|
"integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"bin": {
|
"bin": {
|
||||||
"semver": "bin/semver.js"
|
"semver": "bin/semver.js"
|
||||||
@@ -14569,9 +14560,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/sql-formatter": {
|
"node_modules/sql-formatter": {
|
||||||
"version": "15.4.9",
|
"version": "15.4.10",
|
||||||
"resolved": "https://registry.npmjs.org/sql-formatter/-/sql-formatter-15.4.9.tgz",
|
"resolved": "https://registry.npmjs.org/sql-formatter/-/sql-formatter-15.4.10.tgz",
|
||||||
"integrity": "sha512-5vmt2HlCAVozxsBZuXWkAki/KGawaK+b5GG5x+BtXOFVpN/8cqppblFUxHl4jxdA0cvo14lABhM+KBnrUapOlw==",
|
"integrity": "sha512-zQfiuxU1F/C7TNu+880BdL+fuvJTd1Kj8R0wv48dfZ27NR3z1PWvQFkH8ai/HrIy+NyvXCaZBkJHp/EeZFXSOA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -15262,9 +15253,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/testcontainers": {
|
"node_modules/testcontainers": {
|
||||||
"version": "10.16.0",
|
"version": "10.18.0",
|
||||||
"resolved": "https://registry.npmjs.org/testcontainers/-/testcontainers-10.16.0.tgz",
|
"resolved": "https://registry.npmjs.org/testcontainers/-/testcontainers-10.18.0.tgz",
|
||||||
"integrity": "sha512-oxPLuOtrRWS11A+Yn0+zXB7GkmNarflWqmy6CQJk8KJ75LZs2/zlUXDpizTbPpCGtk4kE2EQYwFZjrE967F8Wg==",
|
"integrity": "sha512-MnwWsPjsN5QVe+lSU1LwLZVOyjgwSwv1INzkw8FekdwgvOtvJ7FThQEkbmzRcguQootgwmA9FG54NoTChZDRvA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -15282,7 +15273,7 @@
|
|||||||
"ssh-remote-port-forward": "^1.0.4",
|
"ssh-remote-port-forward": "^1.0.4",
|
||||||
"tar-fs": "^3.0.6",
|
"tar-fs": "^3.0.6",
|
||||||
"tmp": "^0.2.3",
|
"tmp": "^0.2.3",
|
||||||
"undici": "^5.28.4"
|
"undici": "^5.28.5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/testcontainers/node_modules/tmp": {
|
"node_modules/testcontainers/node_modules/tmp": {
|
||||||
@@ -15456,9 +15447,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/ts-api-utils": {
|
"node_modules/ts-api-utils": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.1.tgz",
|
||||||
"integrity": "sha512-xCt/TOAc+EOHS1XPnijD3/yzpH6qg2xppZO1YDqGoVsNXfQfzHpOdNuXwrwOU8u4ITXJyDCTyt8w5g1sZv9ynQ==",
|
"integrity": "sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -15839,9 +15830,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/undici": {
|
"node_modules/undici": {
|
||||||
"version": "5.28.4",
|
"version": "5.28.5",
|
||||||
"resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz",
|
"resolved": "https://registry.npmjs.org/undici/-/undici-5.28.5.tgz",
|
||||||
"integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==",
|
"integrity": "sha512-zICwjrDrcrUE0pyyJc1I2QzBkLM8FINsgOrt6WjA+BgajVq9Nxu2PbFFXUrAggLfDXlZGZBVZYw7WNV5KiBiBA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -16078,16 +16069,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vite-node": {
|
"node_modules/vite-node": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.5.tgz",
|
||||||
"integrity": "sha512-0sQcwhwAEw/UJGojbhOrnq3HtiZ3tC7BzpAa0lx3QaTX0S3YX70iGcik25UBdB96pmdwjyY2uyKNYruxCDmiEg==",
|
"integrity": "sha512-02JEJl7SbtwSDJdYS537nU6l+ktdvcREfLksk/NDAqtdKWGqHl+joXzEubHROmS3E6pip+Xgu2tFezMu75jH7A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cac": "^6.7.14",
|
"cac": "^6.7.14",
|
||||||
"debug": "^4.4.0",
|
"debug": "^4.4.0",
|
||||||
"es-module-lexer": "^1.6.0",
|
"es-module-lexer": "^1.6.0",
|
||||||
"pathe": "^2.0.1",
|
"pathe": "^2.0.2",
|
||||||
"vite": "^5.0.0 || ^6.0.0"
|
"vite": "^5.0.0 || ^6.0.0"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
@@ -16580,31 +16571,31 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vitest": {
|
"node_modules/vitest": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.5.tgz",
|
||||||
"integrity": "sha512-dWdwTFUW9rcnL0LyF2F+IfvNQWB0w9DERySCk8VMG75F8k25C7LsZoh6XfCjPvcR8Nb+Lqi9JKr6vnzH7HSrpQ==",
|
"integrity": "sha512-4dof+HvqONw9bvsYxtkfUp2uHsTN9bV2CZIi1pWgoFpL1Lld8LA1ka9q/ONSsoScAKG7NVGf2stJTI7XRkXb2Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vitest/expect": "3.0.3",
|
"@vitest/expect": "3.0.5",
|
||||||
"@vitest/mocker": "3.0.3",
|
"@vitest/mocker": "3.0.5",
|
||||||
"@vitest/pretty-format": "^3.0.3",
|
"@vitest/pretty-format": "^3.0.5",
|
||||||
"@vitest/runner": "3.0.3",
|
"@vitest/runner": "3.0.5",
|
||||||
"@vitest/snapshot": "3.0.3",
|
"@vitest/snapshot": "3.0.5",
|
||||||
"@vitest/spy": "3.0.3",
|
"@vitest/spy": "3.0.5",
|
||||||
"@vitest/utils": "3.0.3",
|
"@vitest/utils": "3.0.5",
|
||||||
"chai": "^5.1.2",
|
"chai": "^5.1.2",
|
||||||
"debug": "^4.4.0",
|
"debug": "^4.4.0",
|
||||||
"expect-type": "^1.1.0",
|
"expect-type": "^1.1.0",
|
||||||
"magic-string": "^0.30.17",
|
"magic-string": "^0.30.17",
|
||||||
"pathe": "^2.0.1",
|
"pathe": "^2.0.2",
|
||||||
"std-env": "^3.8.0",
|
"std-env": "^3.8.0",
|
||||||
"tinybench": "^2.9.0",
|
"tinybench": "^2.9.0",
|
||||||
"tinyexec": "^0.3.2",
|
"tinyexec": "^0.3.2",
|
||||||
"tinypool": "^1.0.2",
|
"tinypool": "^1.0.2",
|
||||||
"tinyrainbow": "^2.0.0",
|
"tinyrainbow": "^2.0.0",
|
||||||
"vite": "^5.0.0 || ^6.0.0",
|
"vite": "^5.0.0 || ^6.0.0",
|
||||||
"vite-node": "3.0.3",
|
"vite-node": "3.0.5",
|
||||||
"why-is-node-running": "^2.3.0"
|
"why-is-node-running": "^2.3.0"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
@@ -16618,9 +16609,10 @@
|
|||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@edge-runtime/vm": "*",
|
"@edge-runtime/vm": "*",
|
||||||
|
"@types/debug": "^4.1.12",
|
||||||
"@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
|
"@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
|
||||||
"@vitest/browser": "3.0.3",
|
"@vitest/browser": "3.0.5",
|
||||||
"@vitest/ui": "3.0.3",
|
"@vitest/ui": "3.0.5",
|
||||||
"happy-dom": "*",
|
"happy-dom": "*",
|
||||||
"jsdom": "*"
|
"jsdom": "*"
|
||||||
},
|
},
|
||||||
@@ -16628,6 +16620,9 @@
|
|||||||
"@edge-runtime/vm": {
|
"@edge-runtime/vm": {
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
|
"@types/debug": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
"@types/node": {
|
"@types/node": {
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
|
|||||||
+2
-2
@@ -45,7 +45,7 @@
|
|||||||
"@nestjs/swagger": "^11.0.2",
|
"@nestjs/swagger": "^11.0.2",
|
||||||
"@nestjs/typeorm": "^11.0.0",
|
"@nestjs/typeorm": "^11.0.0",
|
||||||
"@nestjs/websockets": "^11.0.4",
|
"@nestjs/websockets": "^11.0.4",
|
||||||
"@opentelemetry/auto-instrumentations-node": "^0.55.0",
|
"@opentelemetry/auto-instrumentations-node": "^0.56.0",
|
||||||
"@opentelemetry/context-async-hooks": "^1.24.0",
|
"@opentelemetry/context-async-hooks": "^1.24.0",
|
||||||
"@opentelemetry/exporter-prometheus": "^0.57.0",
|
"@opentelemetry/exporter-prometheus": "^0.57.0",
|
||||||
"@opentelemetry/sdk-node": "^0.57.0",
|
"@opentelemetry/sdk-node": "^0.57.0",
|
||||||
@@ -112,7 +112,7 @@
|
|||||||
"@types/lodash": "^4.14.197",
|
"@types/lodash": "^4.14.197",
|
||||||
"@types/mock-fs": "^4.13.1",
|
"@types/mock-fs": "^4.13.1",
|
||||||
"@types/multer": "^1.4.7",
|
"@types/multer": "^1.4.7",
|
||||||
"@types/node": "^22.10.9",
|
"@types/node": "^22.13.1",
|
||||||
"@types/nodemailer": "^6.4.14",
|
"@types/nodemailer": "^6.4.14",
|
||||||
"@types/picomatch": "^3.0.0",
|
"@types/picomatch": "^3.0.0",
|
||||||
"@types/pngjs": "^6.0.5",
|
"@types/pngjs": "^6.0.5",
|
||||||
|
|||||||
@@ -13,22 +13,23 @@ import { IWorker } from 'src/constants';
|
|||||||
import { controllers } from 'src/controllers';
|
import { controllers } from 'src/controllers';
|
||||||
import { entities } from 'src/entities';
|
import { entities } from 'src/entities';
|
||||||
import { ImmichWorker } from 'src/enum';
|
import { ImmichWorker } from 'src/enum';
|
||||||
import { IEventRepository } from 'src/interfaces/event.interface';
|
|
||||||
import { IJobRepository } from 'src/interfaces/job.interface';
|
|
||||||
import { AuthGuard } from 'src/middleware/auth.guard';
|
import { AuthGuard } from 'src/middleware/auth.guard';
|
||||||
import { ErrorInterceptor } from 'src/middleware/error.interceptor';
|
import { ErrorInterceptor } from 'src/middleware/error.interceptor';
|
||||||
import { FileUploadInterceptor } from 'src/middleware/file-upload.interceptor';
|
import { FileUploadInterceptor } from 'src/middleware/file-upload.interceptor';
|
||||||
import { GlobalExceptionFilter } from 'src/middleware/global-exception.filter';
|
import { GlobalExceptionFilter } from 'src/middleware/global-exception.filter';
|
||||||
import { LoggingInterceptor } from 'src/middleware/logging.interceptor';
|
import { LoggingInterceptor } from 'src/middleware/logging.interceptor';
|
||||||
import { providers, repositories } from 'src/repositories';
|
import { repositories } from 'src/repositories';
|
||||||
import { ConfigRepository } from 'src/repositories/config.repository';
|
import { ConfigRepository } from 'src/repositories/config.repository';
|
||||||
|
import { EventRepository } from 'src/repositories/event.repository';
|
||||||
|
import { JobRepository } from 'src/repositories/job.repository';
|
||||||
import { LoggingRepository } from 'src/repositories/logging.repository';
|
import { LoggingRepository } from 'src/repositories/logging.repository';
|
||||||
import { teardownTelemetry, TelemetryRepository } from 'src/repositories/telemetry.repository';
|
import { teardownTelemetry, TelemetryRepository } from 'src/repositories/telemetry.repository';
|
||||||
import { services } from 'src/services';
|
import { services } from 'src/services';
|
||||||
|
import { AuthService } from 'src/services/auth.service';
|
||||||
import { CliService } from 'src/services/cli.service';
|
import { CliService } from 'src/services/cli.service';
|
||||||
import { DatabaseService } from 'src/services/database.service';
|
import { DatabaseService } from 'src/services/database.service';
|
||||||
|
|
||||||
const common = [...services, ...providers, ...repositories];
|
const common = [...repositories, ...services];
|
||||||
|
|
||||||
const middleware = [
|
const middleware = [
|
||||||
FileUploadInterceptor,
|
FileUploadInterceptor,
|
||||||
@@ -78,21 +79,30 @@ class BaseModule implements OnModuleInit, OnModuleDestroy {
|
|||||||
constructor(
|
constructor(
|
||||||
@Inject(IWorker) private worker: ImmichWorker,
|
@Inject(IWorker) private worker: ImmichWorker,
|
||||||
logger: LoggingRepository,
|
logger: LoggingRepository,
|
||||||
@Inject(IEventRepository) private eventRepository: IEventRepository,
|
private eventRepository: EventRepository,
|
||||||
@Inject(IJobRepository) private jobRepository: IJobRepository,
|
private jobRepository: JobRepository,
|
||||||
private telemetryRepository: TelemetryRepository,
|
private telemetryRepository: TelemetryRepository,
|
||||||
|
private authService: AuthService,
|
||||||
) {
|
) {
|
||||||
logger.setAppName(this.worker);
|
logger.setAppName(this.worker);
|
||||||
}
|
}
|
||||||
|
|
||||||
async onModuleInit() {
|
async onModuleInit() {
|
||||||
this.telemetryRepository.setup({ repositories: [...providers.map(({ useClass }) => useClass), ...repositories] });
|
this.telemetryRepository.setup({ repositories });
|
||||||
|
|
||||||
this.jobRepository.setup({ services });
|
this.jobRepository.setup({ services });
|
||||||
if (this.worker === ImmichWorker.MICROSERVICES) {
|
if (this.worker === ImmichWorker.MICROSERVICES) {
|
||||||
this.jobRepository.startWorkers();
|
this.jobRepository.startWorkers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.eventRepository.setAuthFn(async (client) =>
|
||||||
|
this.authService.authenticate({
|
||||||
|
headers: client.request.headers,
|
||||||
|
queryParams: {},
|
||||||
|
metadata: { adminRoute: false, sharedLinkRoute: false, uri: '/api/socket.io' },
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
this.eventRepository.setup({ services });
|
this.eventRepository.setup({ services });
|
||||||
await this.eventRepository.emit('app.bootstrap');
|
await this.eventRepository.emit('app.bootstrap');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { Reflector } from '@nestjs/core';
|
|||||||
import { SchedulerRegistry } from '@nestjs/schedule';
|
import { SchedulerRegistry } from '@nestjs/schedule';
|
||||||
import { Test } from '@nestjs/testing';
|
import { Test } from '@nestjs/testing';
|
||||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
import { ClassConstructor } from 'class-transformer';
|
||||||
import { PostgresJSDialect } from 'kysely-postgres-js';
|
import { PostgresJSDialect } from 'kysely-postgres-js';
|
||||||
import { KyselyModule } from 'nestjs-kysely';
|
import { KyselyModule } from 'nestjs-kysely';
|
||||||
import { OpenTelemetryModule } from 'nestjs-otel';
|
import { OpenTelemetryModule } from 'nestjs-otel';
|
||||||
@@ -13,7 +14,7 @@ import postgres from 'postgres';
|
|||||||
import { format } from 'sql-formatter';
|
import { format } from 'sql-formatter';
|
||||||
import { GENERATE_SQL_KEY, GenerateSqlQueries } from 'src/decorators';
|
import { GENERATE_SQL_KEY, GenerateSqlQueries } from 'src/decorators';
|
||||||
import { entities } from 'src/entities';
|
import { entities } from 'src/entities';
|
||||||
import { providers, repositories } from 'src/repositories';
|
import { repositories } from 'src/repositories';
|
||||||
import { AccessRepository } from 'src/repositories/access.repository';
|
import { AccessRepository } from 'src/repositories/access.repository';
|
||||||
import { ConfigRepository } from 'src/repositories/config.repository';
|
import { ConfigRepository } from 'src/repositories/config.repository';
|
||||||
import { LoggingRepository } from 'src/repositories/logging.repository';
|
import { LoggingRepository } from 'src/repositories/logging.repository';
|
||||||
@@ -45,8 +46,7 @@ export class SqlLogger implements Logger {
|
|||||||
|
|
||||||
const reflector = new Reflector();
|
const reflector = new Reflector();
|
||||||
|
|
||||||
type Repository = (typeof providers)[0]['useClass'];
|
type Repository = ClassConstructor<any>;
|
||||||
type Provider = { provide: any; useClass: Repository };
|
|
||||||
type SqlGeneratorOptions = { targetDir: string };
|
type SqlGeneratorOptions = { targetDir: string };
|
||||||
|
|
||||||
class SqlGenerator {
|
class SqlGenerator {
|
||||||
@@ -59,15 +59,11 @@ class SqlGenerator {
|
|||||||
async run() {
|
async run() {
|
||||||
try {
|
try {
|
||||||
await this.setup();
|
await this.setup();
|
||||||
const targets = [
|
for (const Repository of repositories) {
|
||||||
...providers,
|
if (Repository === LoggingRepository) {
|
||||||
...repositories.map((repository) => ({ provide: repository, useClass: repository as any })),
|
|
||||||
];
|
|
||||||
for (const repository of targets) {
|
|
||||||
if (repository.provide === LoggingRepository) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
await this.process(repository);
|
await this.process(Repository);
|
||||||
}
|
}
|
||||||
await this.write();
|
await this.write();
|
||||||
this.stats();
|
this.stats();
|
||||||
@@ -105,19 +101,19 @@ class SqlGenerator {
|
|||||||
TypeOrmModule.forFeature(entities),
|
TypeOrmModule.forFeature(entities),
|
||||||
OpenTelemetryModule.forRoot(otel),
|
OpenTelemetryModule.forRoot(otel),
|
||||||
],
|
],
|
||||||
providers: [...providers, ...repositories, AuthService, SchedulerRegistry],
|
providers: [...repositories, AuthService, SchedulerRegistry],
|
||||||
}).compile();
|
}).compile();
|
||||||
|
|
||||||
this.app = await moduleFixture.createNestApplication().init();
|
this.app = await moduleFixture.createNestApplication().init();
|
||||||
}
|
}
|
||||||
|
|
||||||
async process({ provide: token, useClass: Repository }: Provider) {
|
async process(Repository: Repository) {
|
||||||
if (!this.app) {
|
if (!this.app) {
|
||||||
throw new Error('Not initialized');
|
throw new Error('Not initialized');
|
||||||
}
|
}
|
||||||
|
|
||||||
const data: string[] = [`-- NOTE: This file is auto generated by ./sql-generator`];
|
const data: string[] = [`-- NOTE: This file is auto generated by ./sql-generator`];
|
||||||
const instance = this.app.get<Repository>(token);
|
const instance = this.app.get<Repository>(Repository);
|
||||||
|
|
||||||
// normal repositories
|
// normal repositories
|
||||||
data.push(...(await this.runTargets(instance, `${Repository.name}`)));
|
data.push(...(await this.runTargets(instance, `${Repository.name}`)));
|
||||||
|
|||||||
@@ -5,14 +5,14 @@ import {
|
|||||||
CQMode,
|
CQMode,
|
||||||
ImageFormat,
|
ImageFormat,
|
||||||
LogLevel,
|
LogLevel,
|
||||||
|
QueueName,
|
||||||
ToneMapping,
|
ToneMapping,
|
||||||
TranscodeHWAccel,
|
TranscodeHWAccel,
|
||||||
TranscodePolicy,
|
TranscodePolicy,
|
||||||
VideoCodec,
|
VideoCodec,
|
||||||
VideoContainer,
|
VideoContainer,
|
||||||
} from 'src/enum';
|
} from 'src/enum';
|
||||||
import { ConcurrentQueueName, QueueName } from 'src/interfaces/job.interface';
|
import { ConcurrentQueueName, ImageOptions } from 'src/types';
|
||||||
import { ImageOptions } from 'src/types';
|
|
||||||
|
|
||||||
export interface SystemConfig {
|
export interface SystemConfig {
|
||||||
backup: {
|
backup: {
|
||||||
|
|||||||
+11
-1
@@ -1,7 +1,7 @@
|
|||||||
import { Duration } from 'luxon';
|
import { Duration } from 'luxon';
|
||||||
import { readFileSync } from 'node:fs';
|
import { readFileSync } from 'node:fs';
|
||||||
import { SemVer } from 'semver';
|
import { SemVer } from 'semver';
|
||||||
import { ExifOrientation } from 'src/enum';
|
import { DatabaseExtension, ExifOrientation } from 'src/enum';
|
||||||
|
|
||||||
export const POSTGRES_VERSION_RANGE = '>=14.0.0';
|
export const POSTGRES_VERSION_RANGE = '>=14.0.0';
|
||||||
export const VECTORS_VERSION_RANGE = '>=0.2 <0.4';
|
export const VECTORS_VERSION_RANGE = '>=0.2 <0.4';
|
||||||
@@ -16,6 +16,16 @@ export const LIFECYCLE_EXTENSION = 'x-immich-lifecycle';
|
|||||||
export const DEPRECATED_IN_PREFIX = 'This property was deprecated in ';
|
export const DEPRECATED_IN_PREFIX = 'This property was deprecated in ';
|
||||||
export const ADDED_IN_PREFIX = 'This property was added in ';
|
export const ADDED_IN_PREFIX = 'This property was added in ';
|
||||||
|
|
||||||
|
export const JOBS_ASSET_PAGINATION_SIZE = 1000;
|
||||||
|
export const JOBS_LIBRARY_PAGINATION_SIZE = 10_000;
|
||||||
|
|
||||||
|
export const EXTENSION_NAMES: Record<DatabaseExtension, string> = {
|
||||||
|
cube: 'cube',
|
||||||
|
earthdistance: 'earthdistance',
|
||||||
|
vector: 'pgvector',
|
||||||
|
vectors: 'pgvecto.rs',
|
||||||
|
} as const;
|
||||||
|
|
||||||
export const SALT_ROUNDS = 10;
|
export const SALT_ROUNDS = 10;
|
||||||
|
|
||||||
export const IWorker = 'IWorker';
|
export const IWorker = 'IWorker';
|
||||||
|
|||||||
@@ -35,9 +35,10 @@ import { AuthDto } from 'src/dtos/auth.dto';
|
|||||||
import { ImmichHeader, RouteKey } from 'src/enum';
|
import { ImmichHeader, RouteKey } from 'src/enum';
|
||||||
import { AssetUploadInterceptor } from 'src/middleware/asset-upload.interceptor';
|
import { AssetUploadInterceptor } from 'src/middleware/asset-upload.interceptor';
|
||||||
import { Auth, Authenticated, FileResponse } from 'src/middleware/auth.guard';
|
import { Auth, Authenticated, FileResponse } from 'src/middleware/auth.guard';
|
||||||
import { FileUploadInterceptor, UploadFiles, getFiles } from 'src/middleware/file-upload.interceptor';
|
import { FileUploadInterceptor, getFiles } from 'src/middleware/file-upload.interceptor';
|
||||||
import { LoggingRepository } from 'src/repositories/logging.repository';
|
import { LoggingRepository } from 'src/repositories/logging.repository';
|
||||||
import { AssetMediaService } from 'src/services/asset-media.service';
|
import { AssetMediaService } from 'src/services/asset-media.service';
|
||||||
|
import { UploadFiles } from 'src/types';
|
||||||
import { sendFile } from 'src/utils/file';
|
import { sendFile } from 'src/utils/file';
|
||||||
import { FileNotEmptyValidator, UUIDParamDto } from 'src/validation';
|
import { FileNotEmptyValidator, UUIDParamDto } from 'src/validation';
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ export class UserController {
|
|||||||
|
|
||||||
@Get('me')
|
@Get('me')
|
||||||
@Authenticated()
|
@Authenticated()
|
||||||
getMyUser(@Auth() auth: AuthDto): UserAdminResponseDto {
|
getMyUser(@Auth() auth: AuthDto): Promise<UserAdminResponseDto> {
|
||||||
return this.service.getMe(auth);
|
return this.service.getMe(auth);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,7 +56,7 @@ export class UserController {
|
|||||||
|
|
||||||
@Get('me/preferences')
|
@Get('me/preferences')
|
||||||
@Authenticated()
|
@Authenticated()
|
||||||
getMyPreferences(@Auth() auth: AuthDto): UserPreferencesResponseDto {
|
getMyPreferences(@Auth() auth: AuthDto): Promise<UserPreferencesResponseDto> {
|
||||||
return this.service.getMyPreferences(auth);
|
return this.service.getMyPreferences(auth);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,7 +71,7 @@ export class UserController {
|
|||||||
|
|
||||||
@Get('me/license')
|
@Get('me/license')
|
||||||
@Authenticated()
|
@Authenticated()
|
||||||
getUserLicense(@Auth() auth: AuthDto): LicenseResponseDto {
|
getUserLicense(@Auth() auth: AuthDto): Promise<LicenseResponseDto> {
|
||||||
return this.service.getLicense(auth);
|
return this.service.getLicense(auth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ vitest.mock('src/constants', () => ({
|
|||||||
APP_MEDIA_LOCATION: '/photos',
|
APP_MEDIA_LOCATION: '/photos',
|
||||||
ADDED_IN_PREFIX: 'This property was added in ',
|
ADDED_IN_PREFIX: 'This property was added in ',
|
||||||
DEPRECATED_IN_PREFIX: 'This property was deprecated in ',
|
DEPRECATED_IN_PREFIX: 'This property was deprecated in ',
|
||||||
|
IWorker: 'IWorker',
|
||||||
}));
|
}));
|
||||||
|
|
||||||
describe('StorageCore', () => {
|
describe('StorageCore', () => {
|
||||||
|
|||||||
@@ -4,12 +4,14 @@ import { APP_MEDIA_LOCATION } from 'src/constants';
|
|||||||
import { AssetEntity } from 'src/entities/asset.entity';
|
import { AssetEntity } from 'src/entities/asset.entity';
|
||||||
import { PersonEntity } from 'src/entities/person.entity';
|
import { PersonEntity } from 'src/entities/person.entity';
|
||||||
import { AssetFileType, AssetPathType, ImageFormat, PathType, PersonPathType, StorageFolder } from 'src/enum';
|
import { AssetFileType, AssetPathType, ImageFormat, PathType, PersonPathType, StorageFolder } from 'src/enum';
|
||||||
import { IAssetRepository } from 'src/interfaces/asset.interface';
|
import { AssetRepository } from 'src/repositories/asset.repository';
|
||||||
import { ICryptoRepository } from 'src/interfaces/crypto.interface';
|
import { ConfigRepository } from 'src/repositories/config.repository';
|
||||||
import { IMoveRepository } from 'src/interfaces/move.interface';
|
import { CryptoRepository } from 'src/repositories/crypto.repository';
|
||||||
import { IPersonRepository } from 'src/interfaces/person.interface';
|
import { LoggingRepository } from 'src/repositories/logging.repository';
|
||||||
import { IStorageRepository } from 'src/interfaces/storage.interface';
|
import { MoveRepository } from 'src/repositories/move.repository';
|
||||||
import { IConfigRepository, ILoggingRepository, ISystemMetadataRepository } from 'src/types';
|
import { PersonRepository } from 'src/repositories/person.repository';
|
||||||
|
import { StorageRepository } from 'src/repositories/storage.repository';
|
||||||
|
import { SystemMetadataRepository } from 'src/repositories/system-metadata.repository';
|
||||||
import { getAssetFiles } from 'src/utils/asset.util';
|
import { getAssetFiles } from 'src/utils/asset.util';
|
||||||
import { getConfig } from 'src/utils/config';
|
import { getConfig } from 'src/utils/config';
|
||||||
|
|
||||||
@@ -31,25 +33,25 @@ let instance: StorageCore | null;
|
|||||||
|
|
||||||
export class StorageCore {
|
export class StorageCore {
|
||||||
private constructor(
|
private constructor(
|
||||||
private assetRepository: IAssetRepository,
|
private assetRepository: AssetRepository,
|
||||||
private configRepository: IConfigRepository,
|
private configRepository: ConfigRepository,
|
||||||
private cryptoRepository: ICryptoRepository,
|
private cryptoRepository: CryptoRepository,
|
||||||
private moveRepository: IMoveRepository,
|
private moveRepository: MoveRepository,
|
||||||
private personRepository: IPersonRepository,
|
private personRepository: PersonRepository,
|
||||||
private storageRepository: IStorageRepository,
|
private storageRepository: StorageRepository,
|
||||||
private systemMetadataRepository: ISystemMetadataRepository,
|
private systemMetadataRepository: SystemMetadataRepository,
|
||||||
private logger: ILoggingRepository,
|
private logger: LoggingRepository,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
static create(
|
static create(
|
||||||
assetRepository: IAssetRepository,
|
assetRepository: AssetRepository,
|
||||||
configRepository: IConfigRepository,
|
configRepository: ConfigRepository,
|
||||||
cryptoRepository: ICryptoRepository,
|
cryptoRepository: CryptoRepository,
|
||||||
moveRepository: IMoveRepository,
|
moveRepository: MoveRepository,
|
||||||
personRepository: IPersonRepository,
|
personRepository: PersonRepository,
|
||||||
storageRepository: IStorageRepository,
|
storageRepository: StorageRepository,
|
||||||
systemMetadataRepository: ISystemMetadataRepository,
|
systemMetadataRepository: SystemMetadataRepository,
|
||||||
logger: ILoggingRepository,
|
logger: LoggingRepository,
|
||||||
) {
|
) {
|
||||||
if (!instance) {
|
if (!instance) {
|
||||||
instance = new StorageCore(
|
instance = new StorageCore(
|
||||||
|
|||||||
@@ -1,3 +1,53 @@
|
|||||||
|
import { Permission } from 'src/enum';
|
||||||
|
|
||||||
|
export type AuthUser = {
|
||||||
|
id: string;
|
||||||
|
isAdmin: boolean;
|
||||||
|
name: string;
|
||||||
|
email: string;
|
||||||
|
quotaUsageInBytes: number;
|
||||||
|
quotaSizeInBytes: number | null;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type AuthApiKey = {
|
||||||
|
id: string;
|
||||||
|
permissions: Permission[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type AuthSharedLink = {
|
||||||
|
id: string;
|
||||||
|
expiresAt: Date | null;
|
||||||
|
userId: string;
|
||||||
|
showExif: boolean;
|
||||||
|
allowUpload: boolean;
|
||||||
|
allowDownload: boolean;
|
||||||
|
password: string | null;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type AuthSession = {
|
||||||
|
id: string;
|
||||||
|
};
|
||||||
|
|
||||||
export const columns = {
|
export const columns = {
|
||||||
|
authUser: [
|
||||||
|
'users.id',
|
||||||
|
'users.name',
|
||||||
|
'users.email',
|
||||||
|
'users.isAdmin',
|
||||||
|
'users.quotaUsageInBytes',
|
||||||
|
'users.quotaSizeInBytes',
|
||||||
|
],
|
||||||
|
authApiKey: ['api_keys.id', 'api_keys.permissions'],
|
||||||
|
authSession: ['sessions.id', 'sessions.updatedAt'],
|
||||||
|
authSharedLink: [
|
||||||
|
'shared_links.id',
|
||||||
|
'shared_links.userId',
|
||||||
|
'shared_links.expiresAt',
|
||||||
|
'shared_links.showExif',
|
||||||
|
'shared_links.allowUpload',
|
||||||
|
'shared_links.allowDownload',
|
||||||
|
'shared_links.password',
|
||||||
|
],
|
||||||
userDto: ['id', 'name', 'email', 'profileImagePath', 'profileChangedAt'],
|
userDto: ['id', 'name', 'email', 'profileImagePath', 'profileChangedAt'],
|
||||||
|
apiKey: ['id', 'name', 'userId', 'createdAt', 'updatedAt', 'permissions'],
|
||||||
} as const;
|
} as const;
|
||||||
|
|||||||
Vendored
+14
-18
@@ -3,23 +3,19 @@
|
|||||||
* Please do not edit it manually.
|
* Please do not edit it manually.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { ColumnType } from "kysely";
|
import type { ColumnType } from 'kysely';
|
||||||
|
import { Permission } from 'src/enum';
|
||||||
|
|
||||||
export type ArrayType<T> = ArrayTypeImpl<T> extends (infer U)[]
|
export type ArrayType<T> = ArrayTypeImpl<T> extends (infer U)[] ? U[] : ArrayTypeImpl<T>;
|
||||||
? U[]
|
|
||||||
: ArrayTypeImpl<T>;
|
|
||||||
|
|
||||||
export type ArrayTypeImpl<T> = T extends ColumnType<infer S, infer I, infer U>
|
export type ArrayTypeImpl<T> = T extends ColumnType<infer S, infer I, infer U> ? ColumnType<S[], I[], U[]> : T[];
|
||||||
? ColumnType<S[], I[], U[]>
|
|
||||||
: T[];
|
|
||||||
|
|
||||||
export type AssetsStatusEnum = "active" | "deleted" | "trashed";
|
export type AssetsStatusEnum = 'active' | 'deleted' | 'trashed';
|
||||||
|
|
||||||
export type Generated<T> = T extends ColumnType<infer S, infer I, infer U>
|
export type Generated<T> =
|
||||||
? ColumnType<S, I | undefined, U>
|
T extends ColumnType<infer S, infer I, infer U> ? ColumnType<S, I | undefined, U> : ColumnType<T, T | undefined, T>;
|
||||||
: ColumnType<T, T | undefined, T>;
|
|
||||||
|
|
||||||
export type Int8 = ColumnType<string, bigint | number | string, bigint | number | string>;
|
export type Int8 = ColumnType<number>;
|
||||||
|
|
||||||
export type Json = JsonValue;
|
export type Json = JsonValue;
|
||||||
|
|
||||||
@@ -33,7 +29,7 @@ export type JsonPrimitive = boolean | number | string | null;
|
|||||||
|
|
||||||
export type JsonValue = JsonArray | JsonObject | JsonPrimitive;
|
export type JsonValue = JsonArray | JsonObject | JsonPrimitive;
|
||||||
|
|
||||||
export type Sourcetype = "exif" | "machine-learning";
|
export type Sourcetype = 'exif' | 'machine-learning';
|
||||||
|
|
||||||
export type Timestamp = ColumnType<Date, Date | string, Date | string>;
|
export type Timestamp = ColumnType<Date, Date | string, Date | string>;
|
||||||
|
|
||||||
@@ -81,7 +77,7 @@ export interface ApiKeys {
|
|||||||
id: Generated<string>;
|
id: Generated<string>;
|
||||||
key: string;
|
key: string;
|
||||||
name: string;
|
name: string;
|
||||||
permissions: string[];
|
permissions: Permission[];
|
||||||
updatedAt: Generated<Timestamp>;
|
updatedAt: Generated<Timestamp>;
|
||||||
userId: string;
|
userId: string;
|
||||||
}
|
}
|
||||||
@@ -126,8 +122,8 @@ export interface Assets {
|
|||||||
duplicateId: string | null;
|
duplicateId: string | null;
|
||||||
duration: string | null;
|
duration: string | null;
|
||||||
encodedVideoPath: Generated<string | null>;
|
encodedVideoPath: Generated<string | null>;
|
||||||
fileCreatedAt: Timestamp;
|
fileCreatedAt: Timestamp | null;
|
||||||
fileModifiedAt: Timestamp;
|
fileModifiedAt: Timestamp | null;
|
||||||
id: Generated<string>;
|
id: Generated<string>;
|
||||||
isArchived: Generated<boolean>;
|
isArchived: Generated<boolean>;
|
||||||
isExternal: Generated<boolean>;
|
isExternal: Generated<boolean>;
|
||||||
@@ -136,7 +132,7 @@ export interface Assets {
|
|||||||
isVisible: Generated<boolean>;
|
isVisible: Generated<boolean>;
|
||||||
libraryId: string | null;
|
libraryId: string | null;
|
||||||
livePhotoVideoId: string | null;
|
livePhotoVideoId: string | null;
|
||||||
localDateTime: Timestamp;
|
localDateTime: Timestamp | null;
|
||||||
originalFileName: string;
|
originalFileName: string;
|
||||||
originalPath: string;
|
originalPath: string;
|
||||||
ownerId: string;
|
ownerId: string;
|
||||||
@@ -444,6 +440,6 @@ export interface DB {
|
|||||||
typeorm_metadata: TypeormMetadata;
|
typeorm_metadata: TypeormMetadata;
|
||||||
user_metadata: UserMetadata;
|
user_metadata: UserMetadata;
|
||||||
users: Users;
|
users: Users;
|
||||||
"vectors.pg_vector_index_stat": VectorsPgVectorIndexStat;
|
'vectors.pg_vector_index_stat': VectorsPgVectorIndexStat;
|
||||||
version_history: VersionHistory;
|
version_history: VersionHistory;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,8 @@ import { SetMetadata, applyDecorators } from '@nestjs/common';
|
|||||||
import { ApiExtension, ApiOperation, ApiProperty, ApiTags } from '@nestjs/swagger';
|
import { ApiExtension, ApiOperation, ApiProperty, ApiTags } from '@nestjs/swagger';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import { ADDED_IN_PREFIX, DEPRECATED_IN_PREFIX, LIFECYCLE_EXTENSION } from 'src/constants';
|
import { ADDED_IN_PREFIX, DEPRECATED_IN_PREFIX, LIFECYCLE_EXTENSION } from 'src/constants';
|
||||||
import { ImmichWorker, MetadataKey } from 'src/enum';
|
import { ImmichWorker, JobName, MetadataKey, QueueName } from 'src/enum';
|
||||||
import { EmitEvent } from 'src/interfaces/event.interface';
|
import { EmitEvent } from 'src/repositories/event.repository';
|
||||||
import { JobName, QueueName } from 'src/interfaces/job.interface';
|
|
||||||
import { setUnion } from 'src/utils/set';
|
import { setUnion } from 'src/utils/set';
|
||||||
|
|
||||||
// PostgreSQL uses a 16-bit integer to indicate the number of bound parameters. This means that the
|
// PostgreSQL uses a 16-bit integer to indicate the number of bound parameters. This means that the
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ import {
|
|||||||
ValidateIf,
|
ValidateIf,
|
||||||
} from 'class-validator';
|
} from 'class-validator';
|
||||||
import { BulkIdsDto } from 'src/dtos/asset-ids.response.dto';
|
import { BulkIdsDto } from 'src/dtos/asset-ids.response.dto';
|
||||||
import { AssetType } from 'src/enum';
|
import { AssetType, ExifOrientation } from 'src/enum';
|
||||||
import { AssetStats } from 'src/interfaces/asset.interface';
|
import { AssetStats } from 'src/repositories/asset.repository';
|
||||||
import { Optional, ValidateBoolean, ValidateUUID } from 'src/validation';
|
import { Optional, ValidateBoolean, ValidateUUID } from 'src/validation';
|
||||||
|
|
||||||
export class DeviceIdDto {
|
export class DeviceIdDto {
|
||||||
@@ -54,6 +54,12 @@ export class UpdateAssetBase {
|
|||||||
@Max(5)
|
@Max(5)
|
||||||
@Min(-1)
|
@Min(-1)
|
||||||
rating?: number;
|
rating?: number;
|
||||||
|
|
||||||
|
@Optional()
|
||||||
|
@Min(1)
|
||||||
|
@Max(8)
|
||||||
|
@ApiProperty({ type: 'integer' })
|
||||||
|
orientation?: ExifOrientation;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class AssetBulkUpdateDto extends UpdateAssetBase {
|
export class AssetBulkUpdateDto extends UpdateAssetBase {
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
import { Transform } from 'class-transformer';
|
import { Transform } from 'class-transformer';
|
||||||
import { IsEmail, IsNotEmpty, IsString, MinLength } from 'class-validator';
|
import { IsEmail, IsNotEmpty, IsString, MinLength } from 'class-validator';
|
||||||
import { SessionEntity } from 'src/entities/session.entity';
|
import { AuthApiKey, AuthSession, AuthSharedLink, AuthUser } from 'src/database';
|
||||||
import { SharedLinkEntity } from 'src/entities/shared-link.entity';
|
|
||||||
import { UserEntity } from 'src/entities/user.entity';
|
import { UserEntity } from 'src/entities/user.entity';
|
||||||
import { ImmichCookie } from 'src/enum';
|
import { ImmichCookie } from 'src/enum';
|
||||||
import { AuthApiKey } from 'src/types';
|
|
||||||
import { toEmail } from 'src/validation';
|
import { toEmail } from 'src/validation';
|
||||||
|
|
||||||
export type CookieResponse = {
|
export type CookieResponse = {
|
||||||
@@ -14,11 +12,11 @@ export type CookieResponse = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export class AuthDto {
|
export class AuthDto {
|
||||||
user!: UserEntity;
|
user!: AuthUser;
|
||||||
|
|
||||||
apiKey?: AuthApiKey;
|
apiKey?: AuthApiKey;
|
||||||
sharedLink?: SharedLinkEntity;
|
sharedLink?: AuthSharedLink;
|
||||||
session?: SessionEntity;
|
session?: AuthSession;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class LoginCredentialDto {
|
export class LoginCredentialDto {
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
import { IsEnum, IsNotEmpty } from 'class-validator';
|
import { IsEnum, IsNotEmpty } from 'class-validator';
|
||||||
import { ManualJobName } from 'src/enum';
|
import { JobCommand, ManualJobName, QueueName } from 'src/enum';
|
||||||
import { JobCommand, QueueName } from 'src/interfaces/job.interface';
|
|
||||||
import { ValidateBoolean } from 'src/validation';
|
import { ValidateBoolean } from 'src/validation';
|
||||||
|
|
||||||
export class JobIdParamDto {
|
export class JobIdParamDto {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
import { IsEnum, IsNotEmpty } from 'class-validator';
|
import { IsEnum, IsNotEmpty } from 'class-validator';
|
||||||
import { UserResponseDto } from 'src/dtos/user.dto';
|
import { UserResponseDto } from 'src/dtos/user.dto';
|
||||||
import { PartnerDirection } from 'src/interfaces/partner.interface';
|
import { PartnerDirection } from 'src/repositories/partner.repository';
|
||||||
|
|
||||||
export class UpdatePartnerDto {
|
export class UpdatePartnerDto {
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
|
|||||||
@@ -25,13 +25,14 @@ import {
|
|||||||
Colorspace,
|
Colorspace,
|
||||||
ImageFormat,
|
ImageFormat,
|
||||||
LogLevel,
|
LogLevel,
|
||||||
|
QueueName,
|
||||||
ToneMapping,
|
ToneMapping,
|
||||||
TranscodeHWAccel,
|
TranscodeHWAccel,
|
||||||
TranscodePolicy,
|
TranscodePolicy,
|
||||||
VideoCodec,
|
VideoCodec,
|
||||||
VideoContainer,
|
VideoContainer,
|
||||||
} from 'src/enum';
|
} from 'src/enum';
|
||||||
import { ConcurrentQueueName, QueueName } from 'src/interfaces/job.interface';
|
import { ConcurrentQueueName } from 'src/types';
|
||||||
import { IsCronExpression, ValidateBoolean } from 'src/validation';
|
import { IsCronExpression, ValidateBoolean } from 'src/validation';
|
||||||
|
|
||||||
const isLibraryScanEnabled = (config: SystemConfigLibraryScanDto) => config.enabled;
|
const isLibraryScanEnabled = (config: SystemConfigLibraryScanDto) => config.enabled;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
import { IsEnum, IsNotEmpty, IsString } from 'class-validator';
|
import { IsEnum, IsNotEmpty, IsString } from 'class-validator';
|
||||||
import { AssetOrder } from 'src/enum';
|
import { AssetOrder } from 'src/enum';
|
||||||
import { TimeBucketSize } from 'src/interfaces/asset.interface';
|
import { TimeBucketSize } from 'src/repositories/asset.repository';
|
||||||
import { Optional, ValidateBoolean, ValidateUUID } from 'src/validation';
|
import { Optional, ValidateBoolean, ValidateUUID } from 'src/validation';
|
||||||
|
|
||||||
export class TimeBucketDto {
|
export class TimeBucketDto {
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ export const mapUser = (entity: UserEntity): UserResponseDto => {
|
|||||||
email: entity.email,
|
email: entity.email,
|
||||||
name: entity.name,
|
name: entity.name,
|
||||||
profileImagePath: entity.profileImagePath,
|
profileImagePath: entity.profileImagePath,
|
||||||
avatarColor: getPreferences(entity).avatar.color,
|
avatarColor: getPreferences(entity.email, entity.metadata || []).avatar.color,
|
||||||
profileChangedAt: entity.profileChangedAt,
|
profileChangedAt: entity.profileChangedAt,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ import { StackEntity } from 'src/entities/stack.entity';
|
|||||||
import { TagEntity } from 'src/entities/tag.entity';
|
import { TagEntity } from 'src/entities/tag.entity';
|
||||||
import { UserEntity } from 'src/entities/user.entity';
|
import { UserEntity } from 'src/entities/user.entity';
|
||||||
import { AssetFileType, AssetStatus, AssetType } from 'src/enum';
|
import { AssetFileType, AssetStatus, AssetType } from 'src/enum';
|
||||||
import { TimeBucketSize } from 'src/interfaces/asset.interface';
|
import { TimeBucketSize } from 'src/repositories/asset.repository';
|
||||||
import { AssetSearchBuilderOptions } from 'src/interfaces/search.interface';
|
import { AssetSearchBuilderOptions } from 'src/repositories/search.repository';
|
||||||
import { anyUuid, asUuid } from 'src/utils/database';
|
import { anyUuid, asUuid } from 'src/utils/database';
|
||||||
import {
|
import {
|
||||||
Column,
|
Column,
|
||||||
@@ -100,13 +100,13 @@ export class AssetEntity {
|
|||||||
deletedAt!: Date | null;
|
deletedAt!: Date | null;
|
||||||
|
|
||||||
@Index('idx_asset_file_created_at')
|
@Index('idx_asset_file_created_at')
|
||||||
@Column({ type: 'timestamptz' })
|
@Column({ type: 'timestamptz', nullable: true, default: null })
|
||||||
fileCreatedAt!: Date;
|
fileCreatedAt!: Date;
|
||||||
|
|
||||||
@Column({ type: 'timestamptz' })
|
@Column({ type: 'timestamptz', nullable: true, default: null })
|
||||||
localDateTime!: Date;
|
localDateTime!: Date;
|
||||||
|
|
||||||
@Column({ type: 'timestamptz' })
|
@Column({ type: 'timestamptz', nullable: true, default: null })
|
||||||
fileModifiedAt!: Date;
|
fileModifiedAt!: Date;
|
||||||
|
|
||||||
@Column({ type: 'boolean', default: false })
|
@Column({ type: 'boolean', default: false })
|
||||||
@@ -180,6 +180,12 @@ export class AssetEntity {
|
|||||||
duplicateId!: string | null;
|
duplicateId!: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type AssetEntityPlaceholder = AssetEntity & {
|
||||||
|
fileCreatedAt: Date | null;
|
||||||
|
fileModifiedAt: Date | null;
|
||||||
|
localDateTime: Date | null;
|
||||||
|
};
|
||||||
|
|
||||||
export function withExif<O>(qb: SelectQueryBuilder<DB, 'assets', O>) {
|
export function withExif<O>(qb: SelectQueryBuilder<DB, 'assets', O>) {
|
||||||
return qb.leftJoin('exif', 'assets.id', 'exif.assetId').select((eb) => eb.fn.toJson(eb.table('exif')).as('exifInfo'));
|
return qb.leftJoin('exif', 'assets.id', 'exif.assetId').select((eb) => eb.fn.toJson(eb.table('exif')).as('exifInfo'));
|
||||||
}
|
}
|
||||||
@@ -419,5 +425,8 @@ export function searchAssetBuilder(kysely: Kysely<DB>, options: AssetSearchBuild
|
|||||||
)
|
)
|
||||||
.$if(!!options.withExif, withExifInner)
|
.$if(!!options.withExif, withExifInner)
|
||||||
.$if(!!(options.withFaces || options.withPeople || options.personIds), (qb) => qb.select(withFacesAndPeople))
|
.$if(!!(options.withFaces || options.withPeople || options.personIds), (qb) => qb.select(withFacesAndPeople))
|
||||||
.$if(!options.withDeleted, (qb) => qb.where('assets.deletedAt', 'is', null));
|
.$if(!options.withDeleted, (qb) => qb.where('assets.deletedAt', 'is', null))
|
||||||
|
.where('assets.fileCreatedAt', 'is not', null)
|
||||||
|
.where('assets.fileModifiedAt', 'is not', null)
|
||||||
|
.where('assets.localDateTime', 'is not', null);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,13 +4,18 @@ import { DeepPartial } from 'src/types';
|
|||||||
import { HumanReadableSize } from 'src/utils/bytes';
|
import { HumanReadableSize } from 'src/utils/bytes';
|
||||||
import { Column, Entity, ManyToOne, PrimaryColumn } from 'typeorm';
|
import { Column, Entity, ManyToOne, PrimaryColumn } from 'typeorm';
|
||||||
|
|
||||||
|
export type UserMetadataItem<T extends keyof UserMetadata = UserMetadataKey> = {
|
||||||
|
key: T;
|
||||||
|
value: UserMetadata[T];
|
||||||
|
};
|
||||||
|
|
||||||
@Entity('user_metadata')
|
@Entity('user_metadata')
|
||||||
export class UserMetadataEntity<T extends keyof UserMetadata = UserMetadataKey> {
|
export class UserMetadataEntity<T extends keyof UserMetadata = UserMetadataKey> implements UserMetadataItem<T> {
|
||||||
@PrimaryColumn({ type: 'uuid' })
|
@PrimaryColumn({ type: 'uuid' })
|
||||||
userId!: string;
|
userId!: string;
|
||||||
|
|
||||||
@ManyToOne(() => UserEntity, (user) => user.metadata, { onUpdate: 'CASCADE', onDelete: 'CASCADE' })
|
@ManyToOne(() => UserEntity, (user) => user.metadata, { onUpdate: 'CASCADE', onDelete: 'CASCADE' })
|
||||||
user!: UserEntity;
|
user?: UserEntity;
|
||||||
|
|
||||||
@PrimaryColumn({ type: 'varchar' })
|
@PrimaryColumn({ type: 'varchar' })
|
||||||
key!: T;
|
key!: T;
|
||||||
|
|||||||
@@ -384,3 +384,156 @@ export enum ExifOrientation {
|
|||||||
MirrorHorizontalRotate90CW = 7,
|
MirrorHorizontalRotate90CW = 7,
|
||||||
Rotate270CW = 8,
|
Rotate270CW = 8,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum DatabaseExtension {
|
||||||
|
CUBE = 'cube',
|
||||||
|
EARTH_DISTANCE = 'earthdistance',
|
||||||
|
VECTOR = 'vector',
|
||||||
|
VECTORS = 'vectors',
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum BootstrapEventPriority {
|
||||||
|
// Database service should be initialized before anything else, most other services need database access
|
||||||
|
DatabaseService = -200,
|
||||||
|
// Initialise config after other bootstrap services, stop other services from using config on bootstrap
|
||||||
|
SystemConfig = 100,
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum QueueName {
|
||||||
|
THUMBNAIL_GENERATION = 'thumbnailGeneration',
|
||||||
|
METADATA_EXTRACTION = 'metadataExtraction',
|
||||||
|
VIDEO_CONVERSION = 'videoConversion',
|
||||||
|
FACE_DETECTION = 'faceDetection',
|
||||||
|
FACIAL_RECOGNITION = 'facialRecognition',
|
||||||
|
SMART_SEARCH = 'smartSearch',
|
||||||
|
DUPLICATE_DETECTION = 'duplicateDetection',
|
||||||
|
BACKGROUND_TASK = 'backgroundTask',
|
||||||
|
STORAGE_TEMPLATE_MIGRATION = 'storageTemplateMigration',
|
||||||
|
MIGRATION = 'migration',
|
||||||
|
SEARCH = 'search',
|
||||||
|
SIDECAR = 'sidecar',
|
||||||
|
LIBRARY = 'library',
|
||||||
|
NOTIFICATION = 'notifications',
|
||||||
|
BACKUP_DATABASE = 'backupDatabase',
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum JobName {
|
||||||
|
//backups
|
||||||
|
BACKUP_DATABASE = 'database-backup',
|
||||||
|
|
||||||
|
// conversion
|
||||||
|
QUEUE_VIDEO_CONVERSION = 'queue-video-conversion',
|
||||||
|
VIDEO_CONVERSION = 'video-conversion',
|
||||||
|
|
||||||
|
// thumbnails
|
||||||
|
QUEUE_GENERATE_THUMBNAILS = 'queue-generate-thumbnails',
|
||||||
|
GENERATE_THUMBNAILS = 'generate-thumbnails',
|
||||||
|
GENERATE_PERSON_THUMBNAIL = 'generate-person-thumbnail',
|
||||||
|
|
||||||
|
// metadata
|
||||||
|
QUEUE_METADATA_EXTRACTION = 'queue-metadata-extraction',
|
||||||
|
METADATA_EXTRACTION = 'metadata-extraction',
|
||||||
|
LINK_LIVE_PHOTOS = 'link-live-photos',
|
||||||
|
|
||||||
|
// user
|
||||||
|
USER_DELETION = 'user-deletion',
|
||||||
|
USER_DELETE_CHECK = 'user-delete-check',
|
||||||
|
USER_SYNC_USAGE = 'user-sync-usage',
|
||||||
|
|
||||||
|
// asset
|
||||||
|
ASSET_DELETION = 'asset-deletion',
|
||||||
|
ASSET_DELETION_CHECK = 'asset-deletion-check',
|
||||||
|
|
||||||
|
// storage template
|
||||||
|
STORAGE_TEMPLATE_MIGRATION = 'storage-template-migration',
|
||||||
|
STORAGE_TEMPLATE_MIGRATION_SINGLE = 'storage-template-migration-single',
|
||||||
|
|
||||||
|
// tags
|
||||||
|
TAG_CLEANUP = 'tag-cleanup',
|
||||||
|
|
||||||
|
// migration
|
||||||
|
QUEUE_MIGRATION = 'queue-migration',
|
||||||
|
MIGRATE_ASSET = 'migrate-asset',
|
||||||
|
MIGRATE_PERSON = 'migrate-person',
|
||||||
|
|
||||||
|
// facial recognition
|
||||||
|
PERSON_CLEANUP = 'person-cleanup',
|
||||||
|
QUEUE_FACE_DETECTION = 'queue-face-detection',
|
||||||
|
FACE_DETECTION = 'face-detection',
|
||||||
|
QUEUE_FACIAL_RECOGNITION = 'queue-facial-recognition',
|
||||||
|
FACIAL_RECOGNITION = 'facial-recognition',
|
||||||
|
|
||||||
|
// library management
|
||||||
|
LIBRARY_QUEUE_SYNC_FILES = 'library-queue-sync-files',
|
||||||
|
LIBRARY_QUEUE_SYNC_ASSETS = 'library-queue-sync-assets',
|
||||||
|
LIBRARY_SYNC_FILE = 'library-sync-file',
|
||||||
|
LIBRARY_SYNC_ASSET = 'library-sync-asset',
|
||||||
|
LIBRARY_DELETE = 'library-delete',
|
||||||
|
LIBRARY_QUEUE_SYNC_ALL = 'library-queue-sync-all',
|
||||||
|
LIBRARY_QUEUE_CLEANUP = 'library-queue-cleanup',
|
||||||
|
|
||||||
|
// cleanup
|
||||||
|
DELETE_FILES = 'delete-files',
|
||||||
|
CLEAN_OLD_AUDIT_LOGS = 'clean-old-audit-logs',
|
||||||
|
CLEAN_OLD_SESSION_TOKENS = 'clean-old-session-tokens',
|
||||||
|
|
||||||
|
// smart search
|
||||||
|
QUEUE_SMART_SEARCH = 'queue-smart-search',
|
||||||
|
SMART_SEARCH = 'smart-search',
|
||||||
|
|
||||||
|
QUEUE_TRASH_EMPTY = 'queue-trash-empty',
|
||||||
|
|
||||||
|
// duplicate detection
|
||||||
|
QUEUE_DUPLICATE_DETECTION = 'queue-duplicate-detection',
|
||||||
|
DUPLICATE_DETECTION = 'duplicate-detection',
|
||||||
|
|
||||||
|
// XMP sidecars
|
||||||
|
QUEUE_SIDECAR = 'queue-sidecar',
|
||||||
|
SIDECAR_DISCOVERY = 'sidecar-discovery',
|
||||||
|
SIDECAR_SYNC = 'sidecar-sync',
|
||||||
|
SIDECAR_WRITE = 'sidecar-write',
|
||||||
|
|
||||||
|
// Notification
|
||||||
|
NOTIFY_SIGNUP = 'notify-signup',
|
||||||
|
NOTIFY_ALBUM_INVITE = 'notify-album-invite',
|
||||||
|
NOTIFY_ALBUM_UPDATE = 'notify-album-update',
|
||||||
|
SEND_EMAIL = 'notification-send-email',
|
||||||
|
|
||||||
|
// Version check
|
||||||
|
VERSION_CHECK = 'version-check',
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum JobCommand {
|
||||||
|
START = 'start',
|
||||||
|
PAUSE = 'pause',
|
||||||
|
RESUME = 'resume',
|
||||||
|
EMPTY = 'empty',
|
||||||
|
CLEAR_FAILED = 'clear-failed',
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum JobStatus {
|
||||||
|
SUCCESS = 'success',
|
||||||
|
FAILED = 'failed',
|
||||||
|
SKIPPED = 'skipped',
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum QueueCleanType {
|
||||||
|
FAILED = 'failed',
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum VectorIndex {
|
||||||
|
CLIP = 'clip_index',
|
||||||
|
FACE = 'face_index',
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum DatabaseLock {
|
||||||
|
GeodataImport = 100,
|
||||||
|
Migrations = 200,
|
||||||
|
SystemFileMounts = 300,
|
||||||
|
StorageTemplateMigration = 420,
|
||||||
|
VersionHistory = 500,
|
||||||
|
CLIPDimSize = 512,
|
||||||
|
Library = 1337,
|
||||||
|
GetSystemConfig = 69,
|
||||||
|
BackupDatabase = 42,
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,35 +0,0 @@
|
|||||||
import { Insertable, Updateable } from 'kysely';
|
|
||||||
import { Albums } from 'src/db';
|
|
||||||
import { AlbumUserCreateDto } from 'src/dtos/album.dto';
|
|
||||||
import { AlbumEntity } from 'src/entities/album.entity';
|
|
||||||
import { IBulkAsset } from 'src/utils/asset.util';
|
|
||||||
|
|
||||||
export const IAlbumRepository = 'IAlbumRepository';
|
|
||||||
|
|
||||||
export interface AlbumAssetCount {
|
|
||||||
albumId: string;
|
|
||||||
assetCount: number;
|
|
||||||
startDate: Date | null;
|
|
||||||
endDate: Date | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface AlbumInfoOptions {
|
|
||||||
withAssets: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IAlbumRepository extends IBulkAsset {
|
|
||||||
getById(id: string, options: AlbumInfoOptions): Promise<AlbumEntity | undefined>;
|
|
||||||
getByAssetId(ownerId: string, assetId: string): Promise<AlbumEntity[]>;
|
|
||||||
removeAsset(assetId: string): Promise<void>;
|
|
||||||
getMetadataForIds(ids: string[]): Promise<AlbumAssetCount[]>;
|
|
||||||
getOwned(ownerId: string): Promise<AlbumEntity[]>;
|
|
||||||
getShared(ownerId: string): Promise<AlbumEntity[]>;
|
|
||||||
getNotShared(ownerId: string): Promise<AlbumEntity[]>;
|
|
||||||
restoreAll(userId: string): Promise<void>;
|
|
||||||
softDeleteAll(userId: string): Promise<void>;
|
|
||||||
deleteAll(userId: string): Promise<void>;
|
|
||||||
create(album: Insertable<Albums>, assetIds: string[], albumUsers: AlbumUserCreateDto[]): Promise<AlbumEntity>;
|
|
||||||
update(id: string, album: Updateable<Albums>): Promise<AlbumEntity>;
|
|
||||||
delete(id: string): Promise<void>;
|
|
||||||
updateThumbnails(): Promise<number | undefined>;
|
|
||||||
}
|
|
||||||
@@ -1,170 +0,0 @@
|
|||||||
import { Insertable, Updateable } from 'kysely';
|
|
||||||
import { AssetFiles, AssetJobStatus, Assets, Exif } from 'src/db';
|
|
||||||
import { AssetEntity } from 'src/entities/asset.entity';
|
|
||||||
import { AssetFileType, AssetOrder, AssetStatus, AssetType } from 'src/enum';
|
|
||||||
import { AssetSearchOptions, SearchExploreItem } from 'src/interfaces/search.interface';
|
|
||||||
import { Paginated, PaginationOptions } from 'src/utils/pagination';
|
|
||||||
|
|
||||||
export type AssetStats = Record<AssetType, number>;
|
|
||||||
|
|
||||||
export interface AssetStatsOptions {
|
|
||||||
isFavorite?: boolean;
|
|
||||||
isArchived?: boolean;
|
|
||||||
isTrashed?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface LivePhotoSearchOptions {
|
|
||||||
ownerId: string;
|
|
||||||
libraryId?: string | null;
|
|
||||||
livePhotoCID: string;
|
|
||||||
otherAssetId: string;
|
|
||||||
type: AssetType;
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum WithoutProperty {
|
|
||||||
THUMBNAIL = 'thumbnail',
|
|
||||||
ENCODED_VIDEO = 'encoded-video',
|
|
||||||
EXIF = 'exif',
|
|
||||||
SMART_SEARCH = 'smart-search',
|
|
||||||
DUPLICATE = 'duplicate',
|
|
||||||
FACES = 'faces',
|
|
||||||
SIDECAR = 'sidecar',
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum WithProperty {
|
|
||||||
SIDECAR = 'sidecar',
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum TimeBucketSize {
|
|
||||||
DAY = 'DAY',
|
|
||||||
MONTH = 'MONTH',
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface AssetBuilderOptions {
|
|
||||||
isArchived?: boolean;
|
|
||||||
isFavorite?: boolean;
|
|
||||||
isTrashed?: boolean;
|
|
||||||
isDuplicate?: boolean;
|
|
||||||
albumId?: string;
|
|
||||||
tagId?: string;
|
|
||||||
personId?: string;
|
|
||||||
userIds?: string[];
|
|
||||||
withStacked?: boolean;
|
|
||||||
exifInfo?: boolean;
|
|
||||||
status?: AssetStatus;
|
|
||||||
assetType?: AssetType;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TimeBucketOptions extends AssetBuilderOptions {
|
|
||||||
size: TimeBucketSize;
|
|
||||||
order?: AssetOrder;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TimeBucketItem {
|
|
||||||
timeBucket: string;
|
|
||||||
count: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface MonthDay {
|
|
||||||
day: number;
|
|
||||||
month: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface AssetExploreFieldOptions {
|
|
||||||
maxFields: number;
|
|
||||||
minAssetsPerField: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface AssetFullSyncOptions {
|
|
||||||
ownerId: string;
|
|
||||||
lastId?: string;
|
|
||||||
updatedUntil: Date;
|
|
||||||
limit: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface AssetDeltaSyncOptions {
|
|
||||||
userIds: string[];
|
|
||||||
updatedAfter: Date;
|
|
||||||
limit: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface AssetUpdateDuplicateOptions {
|
|
||||||
targetDuplicateId: string | null;
|
|
||||||
assetIds: string[];
|
|
||||||
duplicateIds: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface UpsertFileOptions {
|
|
||||||
assetId: string;
|
|
||||||
type: AssetFileType;
|
|
||||||
path: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface AssetGetByChecksumOptions {
|
|
||||||
ownerId: string;
|
|
||||||
checksum: Buffer;
|
|
||||||
libraryId?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type AssetPathEntity = Pick<AssetEntity, 'id' | 'originalPath' | 'isOffline'>;
|
|
||||||
|
|
||||||
export interface GetByIdsRelations {
|
|
||||||
exifInfo?: boolean;
|
|
||||||
faces?: { person?: boolean };
|
|
||||||
files?: boolean;
|
|
||||||
library?: boolean;
|
|
||||||
owner?: boolean;
|
|
||||||
smartSearch?: boolean;
|
|
||||||
stack?: { assets?: boolean };
|
|
||||||
tags?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface DuplicateGroup {
|
|
||||||
duplicateId: string;
|
|
||||||
assets: AssetEntity[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface DayOfYearAssets {
|
|
||||||
yearsAgo: number;
|
|
||||||
assets: AssetEntity[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export const IAssetRepository = 'IAssetRepository';
|
|
||||||
|
|
||||||
export interface IAssetRepository {
|
|
||||||
create(asset: Insertable<Assets>): Promise<AssetEntity>;
|
|
||||||
getByIds(ids: string[], relations?: GetByIdsRelations): Promise<AssetEntity[]>;
|
|
||||||
getByIdsWithAllRelations(ids: string[]): Promise<AssetEntity[]>;
|
|
||||||
getByDayOfYear(ownerIds: string[], monthDay: MonthDay): Promise<DayOfYearAssets[]>;
|
|
||||||
getByChecksum(options: AssetGetByChecksumOptions): Promise<AssetEntity | undefined>;
|
|
||||||
getByChecksums(userId: string, checksums: Buffer[]): Promise<AssetEntity[]>;
|
|
||||||
getUploadAssetIdByChecksum(ownerId: string, checksum: Buffer): Promise<string | undefined>;
|
|
||||||
getByAlbumId(pagination: PaginationOptions, albumId: string): Paginated<AssetEntity>;
|
|
||||||
getByDeviceIds(ownerId: string, deviceId: string, deviceAssetIds: string[]): Promise<string[]>;
|
|
||||||
getByUserId(pagination: PaginationOptions, userId: string, options?: AssetSearchOptions): Paginated<AssetEntity>;
|
|
||||||
getById(id: string, relations?: GetByIdsRelations): Promise<AssetEntity | undefined>;
|
|
||||||
getWithout(pagination: PaginationOptions, property: WithoutProperty): Paginated<AssetEntity>;
|
|
||||||
getRandom(userIds: string[], count: number): Promise<AssetEntity[]>;
|
|
||||||
getLastUpdatedAssetForAlbumId(albumId: string): Promise<AssetEntity | undefined>;
|
|
||||||
getByLibraryIdAndOriginalPath(libraryId: string, originalPath: string): Promise<AssetEntity | undefined>;
|
|
||||||
deleteAll(ownerId: string): Promise<void>;
|
|
||||||
getAll(pagination: PaginationOptions, options?: AssetSearchOptions): Paginated<AssetEntity>;
|
|
||||||
getAllByDeviceId(userId: string, deviceId: string): Promise<string[]>;
|
|
||||||
getLivePhotoCount(motionId: string): Promise<number>;
|
|
||||||
updateAll(ids: string[], options: Updateable<Assets>): Promise<void>;
|
|
||||||
updateDuplicates(options: AssetUpdateDuplicateOptions): Promise<void>;
|
|
||||||
update(asset: Updateable<Assets> & { id: string }): Promise<AssetEntity>;
|
|
||||||
remove(asset: AssetEntity): Promise<void>;
|
|
||||||
findLivePhotoMatch(options: LivePhotoSearchOptions): Promise<AssetEntity | undefined>;
|
|
||||||
getStatistics(ownerId: string, options: AssetStatsOptions): Promise<AssetStats>;
|
|
||||||
getTimeBuckets(options: TimeBucketOptions): Promise<TimeBucketItem[]>;
|
|
||||||
getTimeBucket(timeBucket: string, options: TimeBucketOptions): Promise<AssetEntity[]>;
|
|
||||||
upsertExif(exif: Insertable<Exif>): Promise<void>;
|
|
||||||
upsertJobStatus(...jobStatus: Insertable<AssetJobStatus>[]): Promise<void>;
|
|
||||||
getAssetIdByCity(userId: string, options: AssetExploreFieldOptions): Promise<SearchExploreItem<string>>;
|
|
||||||
getDuplicates(userId: string): Promise<DuplicateGroup[]>;
|
|
||||||
getAllForUserFullSync(options: AssetFullSyncOptions): Promise<AssetEntity[]>;
|
|
||||||
getChangedDeltaSync(options: AssetDeltaSyncOptions): Promise<AssetEntity[]>;
|
|
||||||
upsertFile(options: Insertable<AssetFiles>): Promise<void>;
|
|
||||||
upsertFiles(options: Insertable<AssetFiles>[]): Promise<void>;
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
export const ICryptoRepository = 'ICryptoRepository';
|
|
||||||
|
|
||||||
export interface ICryptoRepository {
|
|
||||||
randomBytes(size: number): Buffer;
|
|
||||||
randomUUID(): string;
|
|
||||||
hashFile(filePath: string | Buffer): Promise<Buffer>;
|
|
||||||
hashSha256(data: string): string;
|
|
||||||
verifySha256(data: string, encrypted: string, publicKey: string): boolean;
|
|
||||||
hashSha1(data: string | Buffer): Buffer;
|
|
||||||
hashBcrypt(data: string | Buffer, saltOrRounds: string | number): Promise<string>;
|
|
||||||
compareBcrypt(data: string | Buffer, encrypted: string): boolean;
|
|
||||||
newPassword(bytes: number): string;
|
|
||||||
}
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
export enum DatabaseExtension {
|
|
||||||
CUBE = 'cube',
|
|
||||||
EARTH_DISTANCE = 'earthdistance',
|
|
||||||
VECTOR = 'vector',
|
|
||||||
VECTORS = 'vectors',
|
|
||||||
}
|
|
||||||
|
|
||||||
export type VectorExtension = DatabaseExtension.VECTOR | DatabaseExtension.VECTORS;
|
|
||||||
|
|
||||||
export type DatabaseConnectionURL = {
|
|
||||||
connectionType: 'url';
|
|
||||||
url: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type DatabaseConnectionParts = {
|
|
||||||
connectionType: 'parts';
|
|
||||||
host: string;
|
|
||||||
port: number;
|
|
||||||
username: string;
|
|
||||||
password: string;
|
|
||||||
database: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type DatabaseConnectionParams = DatabaseConnectionURL | DatabaseConnectionParts;
|
|
||||||
|
|
||||||
export enum VectorIndex {
|
|
||||||
CLIP = 'clip_index',
|
|
||||||
FACE = 'face_index',
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum DatabaseLock {
|
|
||||||
GeodataImport = 100,
|
|
||||||
Migrations = 200,
|
|
||||||
SystemFileMounts = 300,
|
|
||||||
StorageTemplateMigration = 420,
|
|
||||||
VersionHistory = 500,
|
|
||||||
CLIPDimSize = 512,
|
|
||||||
Library = 1337,
|
|
||||||
GetSystemConfig = 69,
|
|
||||||
BackupDatabase = 42,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const EXTENSION_NAMES: Record<DatabaseExtension, string> = {
|
|
||||||
cube: 'cube',
|
|
||||||
earthdistance: 'earthdistance',
|
|
||||||
vector: 'pgvector',
|
|
||||||
vectors: 'pgvecto.rs',
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export interface ExtensionVersion {
|
|
||||||
availableVersion: string | null;
|
|
||||||
installedVersion: string | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface VectorUpdateResult {
|
|
||||||
restartRequired: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const IDatabaseRepository = 'IDatabaseRepository';
|
|
||||||
|
|
||||||
export interface IDatabaseRepository {
|
|
||||||
init(): void;
|
|
||||||
reconnect(): Promise<boolean>;
|
|
||||||
shutdown(): Promise<void>;
|
|
||||||
getExtensionVersion(extension: DatabaseExtension): Promise<ExtensionVersion>;
|
|
||||||
getExtensionVersionRange(extension: VectorExtension): string;
|
|
||||||
getPostgresVersion(): Promise<string>;
|
|
||||||
getPostgresVersionRange(): string;
|
|
||||||
createExtension(extension: DatabaseExtension): Promise<void>;
|
|
||||||
updateVectorExtension(extension: VectorExtension, version?: string): Promise<VectorUpdateResult>;
|
|
||||||
reindex(index: VectorIndex): Promise<void>;
|
|
||||||
shouldReindex(name: VectorIndex): Promise<boolean>;
|
|
||||||
runMigrations(options?: { transaction?: 'all' | 'none' | 'each' }): Promise<void>;
|
|
||||||
withLock<R>(lock: DatabaseLock, callback: () => Promise<R>): Promise<R>;
|
|
||||||
tryLock(lock: DatabaseLock): Promise<boolean>;
|
|
||||||
isBusy(lock: DatabaseLock): boolean;
|
|
||||||
wait(lock: DatabaseLock): Promise<void>;
|
|
||||||
}
|
|
||||||
@@ -1,114 +0,0 @@
|
|||||||
import { ClassConstructor } from 'class-transformer';
|
|
||||||
import { SystemConfig } from 'src/config';
|
|
||||||
import { AssetResponseDto } from 'src/dtos/asset-response.dto';
|
|
||||||
import { ReleaseNotification, ServerVersionResponseDto } from 'src/dtos/server.dto';
|
|
||||||
import { JobItem, QueueName } from 'src/interfaces/job.interface';
|
|
||||||
|
|
||||||
export const IEventRepository = 'IEventRepository';
|
|
||||||
|
|
||||||
type EventMap = {
|
|
||||||
// app events
|
|
||||||
'app.bootstrap': [];
|
|
||||||
'app.shutdown': [];
|
|
||||||
|
|
||||||
'config.init': [{ newConfig: SystemConfig }];
|
|
||||||
// config events
|
|
||||||
'config.update': [
|
|
||||||
{
|
|
||||||
newConfig: SystemConfig;
|
|
||||||
oldConfig: SystemConfig;
|
|
||||||
},
|
|
||||||
];
|
|
||||||
'config.validate': [{ newConfig: SystemConfig; oldConfig: SystemConfig }];
|
|
||||||
|
|
||||||
// album events
|
|
||||||
'album.update': [{ id: string; recipientIds: string[] }];
|
|
||||||
'album.invite': [{ id: string; userId: string }];
|
|
||||||
|
|
||||||
// asset events
|
|
||||||
'asset.tag': [{ assetId: string }];
|
|
||||||
'asset.untag': [{ assetId: string }];
|
|
||||||
'asset.hide': [{ assetId: string; userId: string }];
|
|
||||||
'asset.show': [{ assetId: string; userId: string }];
|
|
||||||
'asset.trash': [{ assetId: string; userId: string }];
|
|
||||||
'asset.delete': [{ assetId: string; userId: string }];
|
|
||||||
|
|
||||||
// asset bulk events
|
|
||||||
'assets.trash': [{ assetIds: string[]; userId: string }];
|
|
||||||
'assets.delete': [{ assetIds: string[]; userId: string }];
|
|
||||||
'assets.restore': [{ assetIds: string[]; userId: string }];
|
|
||||||
|
|
||||||
'job.start': [QueueName, JobItem];
|
|
||||||
|
|
||||||
// session events
|
|
||||||
'session.delete': [{ sessionId: string }];
|
|
||||||
|
|
||||||
// stack events
|
|
||||||
'stack.create': [{ stackId: string; userId: string }];
|
|
||||||
'stack.update': [{ stackId: string; userId: string }];
|
|
||||||
'stack.delete': [{ stackId: string; userId: string }];
|
|
||||||
|
|
||||||
// stack bulk events
|
|
||||||
'stacks.delete': [{ stackIds: string[]; userId: string }];
|
|
||||||
|
|
||||||
// user events
|
|
||||||
'user.signup': [{ notify: boolean; id: string; tempPassword?: string }];
|
|
||||||
|
|
||||||
// websocket events
|
|
||||||
'websocket.connect': [{ userId: string }];
|
|
||||||
};
|
|
||||||
|
|
||||||
export const serverEvents = ['config.update'] as const;
|
|
||||||
export type ServerEvents = (typeof serverEvents)[number];
|
|
||||||
|
|
||||||
export type EmitEvent = keyof EventMap;
|
|
||||||
export type EmitHandler<T extends EmitEvent> = (...args: ArgsOf<T>) => Promise<void> | void;
|
|
||||||
export type ArgOf<T extends EmitEvent> = EventMap[T][0];
|
|
||||||
export type ArgsOf<T extends EmitEvent> = EventMap[T];
|
|
||||||
|
|
||||||
export interface ClientEventMap {
|
|
||||||
on_upload_success: [AssetResponseDto];
|
|
||||||
on_user_delete: [string];
|
|
||||||
on_asset_delete: [string];
|
|
||||||
on_asset_trash: [string[]];
|
|
||||||
on_asset_update: [AssetResponseDto];
|
|
||||||
on_asset_hidden: [string];
|
|
||||||
on_asset_restore: [string[]];
|
|
||||||
on_asset_stack_update: string[];
|
|
||||||
on_person_thumbnail: [string];
|
|
||||||
on_server_version: [ServerVersionResponseDto];
|
|
||||||
on_config_update: [];
|
|
||||||
on_new_release: [ReleaseNotification];
|
|
||||||
on_session_delete: [string];
|
|
||||||
}
|
|
||||||
|
|
||||||
export type EventItem<T extends EmitEvent> = {
|
|
||||||
event: T;
|
|
||||||
handler: EmitHandler<T>;
|
|
||||||
server: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
export enum BootstrapEventPriority {
|
|
||||||
// Database service should be initialized before anything else, most other services need database access
|
|
||||||
DatabaseService = -200,
|
|
||||||
// Initialise config after other bootstrap services, stop other services from using config on bootstrap
|
|
||||||
SystemConfig = 100,
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IEventRepository {
|
|
||||||
setup(options: { services: ClassConstructor<unknown>[] }): void;
|
|
||||||
emit<T extends keyof EventMap>(event: T, ...args: ArgsOf<T>): Promise<void>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send to connected clients for a specific user
|
|
||||||
*/
|
|
||||||
clientSend<E extends keyof ClientEventMap>(event: E, room: string, ...data: ClientEventMap[E]): void;
|
|
||||||
/**
|
|
||||||
* Send to all connected clients
|
|
||||||
*/
|
|
||||||
clientBroadcast<E extends keyof ClientEventMap>(event: E, ...data: ClientEventMap[E]): void;
|
|
||||||
/**
|
|
||||||
* Send to all connected servers
|
|
||||||
*/
|
|
||||||
serverSend<T extends ServerEvents>(event: T, ...args: ArgsOf<T>): void;
|
|
||||||
}
|
|
||||||
@@ -1,329 +0,0 @@
|
|||||||
import { ClassConstructor } from 'class-transformer';
|
|
||||||
import { EmailImageAttachment } from 'src/repositories/notification.repository';
|
|
||||||
|
|
||||||
export enum QueueName {
|
|
||||||
THUMBNAIL_GENERATION = 'thumbnailGeneration',
|
|
||||||
METADATA_EXTRACTION = 'metadataExtraction',
|
|
||||||
VIDEO_CONVERSION = 'videoConversion',
|
|
||||||
FACE_DETECTION = 'faceDetection',
|
|
||||||
FACIAL_RECOGNITION = 'facialRecognition',
|
|
||||||
SMART_SEARCH = 'smartSearch',
|
|
||||||
DUPLICATE_DETECTION = 'duplicateDetection',
|
|
||||||
BACKGROUND_TASK = 'backgroundTask',
|
|
||||||
STORAGE_TEMPLATE_MIGRATION = 'storageTemplateMigration',
|
|
||||||
MIGRATION = 'migration',
|
|
||||||
SEARCH = 'search',
|
|
||||||
SIDECAR = 'sidecar',
|
|
||||||
LIBRARY = 'library',
|
|
||||||
NOTIFICATION = 'notifications',
|
|
||||||
BACKUP_DATABASE = 'backupDatabase',
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ConcurrentQueueName = Exclude<
|
|
||||||
QueueName,
|
|
||||||
| QueueName.STORAGE_TEMPLATE_MIGRATION
|
|
||||||
| QueueName.FACIAL_RECOGNITION
|
|
||||||
| QueueName.DUPLICATE_DETECTION
|
|
||||||
| QueueName.BACKUP_DATABASE
|
|
||||||
>;
|
|
||||||
|
|
||||||
export enum JobCommand {
|
|
||||||
START = 'start',
|
|
||||||
PAUSE = 'pause',
|
|
||||||
RESUME = 'resume',
|
|
||||||
EMPTY = 'empty',
|
|
||||||
CLEAR_FAILED = 'clear-failed',
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum JobName {
|
|
||||||
//backups
|
|
||||||
BACKUP_DATABASE = 'database-backup',
|
|
||||||
|
|
||||||
// conversion
|
|
||||||
QUEUE_VIDEO_CONVERSION = 'queue-video-conversion',
|
|
||||||
VIDEO_CONVERSION = 'video-conversion',
|
|
||||||
|
|
||||||
// thumbnails
|
|
||||||
QUEUE_GENERATE_THUMBNAILS = 'queue-generate-thumbnails',
|
|
||||||
GENERATE_THUMBNAILS = 'generate-thumbnails',
|
|
||||||
GENERATE_PERSON_THUMBNAIL = 'generate-person-thumbnail',
|
|
||||||
|
|
||||||
// metadata
|
|
||||||
QUEUE_METADATA_EXTRACTION = 'queue-metadata-extraction',
|
|
||||||
METADATA_EXTRACTION = 'metadata-extraction',
|
|
||||||
LINK_LIVE_PHOTOS = 'link-live-photos',
|
|
||||||
|
|
||||||
// user
|
|
||||||
USER_DELETION = 'user-deletion',
|
|
||||||
USER_DELETE_CHECK = 'user-delete-check',
|
|
||||||
USER_SYNC_USAGE = 'user-sync-usage',
|
|
||||||
|
|
||||||
// asset
|
|
||||||
ASSET_DELETION = 'asset-deletion',
|
|
||||||
ASSET_DELETION_CHECK = 'asset-deletion-check',
|
|
||||||
|
|
||||||
// storage template
|
|
||||||
STORAGE_TEMPLATE_MIGRATION = 'storage-template-migration',
|
|
||||||
STORAGE_TEMPLATE_MIGRATION_SINGLE = 'storage-template-migration-single',
|
|
||||||
|
|
||||||
// tags
|
|
||||||
TAG_CLEANUP = 'tag-cleanup',
|
|
||||||
|
|
||||||
// migration
|
|
||||||
QUEUE_MIGRATION = 'queue-migration',
|
|
||||||
MIGRATE_ASSET = 'migrate-asset',
|
|
||||||
MIGRATE_PERSON = 'migrate-person',
|
|
||||||
|
|
||||||
// facial recognition
|
|
||||||
PERSON_CLEANUP = 'person-cleanup',
|
|
||||||
QUEUE_FACE_DETECTION = 'queue-face-detection',
|
|
||||||
FACE_DETECTION = 'face-detection',
|
|
||||||
QUEUE_FACIAL_RECOGNITION = 'queue-facial-recognition',
|
|
||||||
FACIAL_RECOGNITION = 'facial-recognition',
|
|
||||||
|
|
||||||
// library management
|
|
||||||
LIBRARY_QUEUE_SYNC_FILES = 'library-queue-sync-files',
|
|
||||||
LIBRARY_QUEUE_SYNC_ASSETS = 'library-queue-sync-assets',
|
|
||||||
LIBRARY_SYNC_FILE = 'library-sync-file',
|
|
||||||
LIBRARY_SYNC_ASSET = 'library-sync-asset',
|
|
||||||
LIBRARY_DELETE = 'library-delete',
|
|
||||||
LIBRARY_QUEUE_SYNC_ALL = 'library-queue-sync-all',
|
|
||||||
LIBRARY_QUEUE_CLEANUP = 'library-queue-cleanup',
|
|
||||||
|
|
||||||
// cleanup
|
|
||||||
DELETE_FILES = 'delete-files',
|
|
||||||
CLEAN_OLD_AUDIT_LOGS = 'clean-old-audit-logs',
|
|
||||||
CLEAN_OLD_SESSION_TOKENS = 'clean-old-session-tokens',
|
|
||||||
|
|
||||||
// smart search
|
|
||||||
QUEUE_SMART_SEARCH = 'queue-smart-search',
|
|
||||||
SMART_SEARCH = 'smart-search',
|
|
||||||
|
|
||||||
QUEUE_TRASH_EMPTY = 'queue-trash-empty',
|
|
||||||
|
|
||||||
// duplicate detection
|
|
||||||
QUEUE_DUPLICATE_DETECTION = 'queue-duplicate-detection',
|
|
||||||
DUPLICATE_DETECTION = 'duplicate-detection',
|
|
||||||
|
|
||||||
// XMP sidecars
|
|
||||||
QUEUE_SIDECAR = 'queue-sidecar',
|
|
||||||
SIDECAR_DISCOVERY = 'sidecar-discovery',
|
|
||||||
SIDECAR_SYNC = 'sidecar-sync',
|
|
||||||
SIDECAR_WRITE = 'sidecar-write',
|
|
||||||
|
|
||||||
// Notification
|
|
||||||
NOTIFY_SIGNUP = 'notify-signup',
|
|
||||||
NOTIFY_ALBUM_INVITE = 'notify-album-invite',
|
|
||||||
NOTIFY_ALBUM_UPDATE = 'notify-album-update',
|
|
||||||
SEND_EMAIL = 'notification-send-email',
|
|
||||||
|
|
||||||
// Version check
|
|
||||||
VERSION_CHECK = 'version-check',
|
|
||||||
}
|
|
||||||
|
|
||||||
export const JOBS_ASSET_PAGINATION_SIZE = 1000;
|
|
||||||
export const JOBS_LIBRARY_PAGINATION_SIZE = 10_000;
|
|
||||||
|
|
||||||
export interface IBaseJob {
|
|
||||||
force?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IDelayedJob extends IBaseJob {
|
|
||||||
/** The minimum time to wait to execute this job, in milliseconds. */
|
|
||||||
delay?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IEntityJob extends IBaseJob {
|
|
||||||
id: string;
|
|
||||||
source?: 'upload' | 'sidecar-write' | 'copy';
|
|
||||||
notify?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IAssetDeleteJob extends IEntityJob {
|
|
||||||
deleteOnDisk: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ILibraryFileJob extends IEntityJob {
|
|
||||||
ownerId: string;
|
|
||||||
assetPath: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ILibraryAssetJob extends IEntityJob {
|
|
||||||
importPaths: string[];
|
|
||||||
exclusionPatterns: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IBulkEntityJob extends IBaseJob {
|
|
||||||
ids: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IDeleteFilesJob extends IBaseJob {
|
|
||||||
files: Array<string | null | undefined>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ISidecarWriteJob extends IEntityJob {
|
|
||||||
description?: string;
|
|
||||||
dateTimeOriginal?: string;
|
|
||||||
latitude?: number;
|
|
||||||
longitude?: number;
|
|
||||||
rating?: number;
|
|
||||||
tags?: true;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IDeferrableJob extends IEntityJob {
|
|
||||||
deferred?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface INightlyJob extends IBaseJob {
|
|
||||||
nightly?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IEmailJob {
|
|
||||||
to: string;
|
|
||||||
subject: string;
|
|
||||||
html: string;
|
|
||||||
text: string;
|
|
||||||
imageAttachments?: EmailImageAttachment[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface INotifySignupJob extends IEntityJob {
|
|
||||||
tempPassword?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface INotifyAlbumInviteJob extends IEntityJob {
|
|
||||||
recipientId: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface INotifyAlbumUpdateJob extends IEntityJob, IDelayedJob {
|
|
||||||
recipientIds: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface JobCounts {
|
|
||||||
active: number;
|
|
||||||
completed: number;
|
|
||||||
failed: number;
|
|
||||||
delayed: number;
|
|
||||||
waiting: number;
|
|
||||||
paused: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface QueueStatus {
|
|
||||||
isActive: boolean;
|
|
||||||
isPaused: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum QueueCleanType {
|
|
||||||
FAILED = 'failed',
|
|
||||||
}
|
|
||||||
|
|
||||||
export type JobItem =
|
|
||||||
// Backups
|
|
||||||
| { name: JobName.BACKUP_DATABASE; data?: IBaseJob }
|
|
||||||
|
|
||||||
// Transcoding
|
|
||||||
| { name: JobName.QUEUE_VIDEO_CONVERSION; data: IBaseJob }
|
|
||||||
| { name: JobName.VIDEO_CONVERSION; data: IEntityJob }
|
|
||||||
|
|
||||||
// Thumbnails
|
|
||||||
| { name: JobName.QUEUE_GENERATE_THUMBNAILS; data: IBaseJob }
|
|
||||||
| { name: JobName.GENERATE_THUMBNAILS; data: IEntityJob }
|
|
||||||
|
|
||||||
// User
|
|
||||||
| { name: JobName.USER_DELETE_CHECK; data?: IBaseJob }
|
|
||||||
| { name: JobName.USER_DELETION; data: IEntityJob }
|
|
||||||
| { name: JobName.USER_SYNC_USAGE; data?: IBaseJob }
|
|
||||||
|
|
||||||
// Storage Template
|
|
||||||
| { name: JobName.STORAGE_TEMPLATE_MIGRATION; data?: IBaseJob }
|
|
||||||
| { name: JobName.STORAGE_TEMPLATE_MIGRATION_SINGLE; data: IEntityJob }
|
|
||||||
|
|
||||||
// Migration
|
|
||||||
| { name: JobName.QUEUE_MIGRATION; data?: IBaseJob }
|
|
||||||
| { name: JobName.MIGRATE_ASSET; data: IEntityJob }
|
|
||||||
| { name: JobName.MIGRATE_PERSON; data: IEntityJob }
|
|
||||||
|
|
||||||
// Metadata Extraction
|
|
||||||
| { name: JobName.QUEUE_METADATA_EXTRACTION; data: IBaseJob }
|
|
||||||
| { name: JobName.METADATA_EXTRACTION; data: IEntityJob }
|
|
||||||
| { name: JobName.LINK_LIVE_PHOTOS; data: IEntityJob }
|
|
||||||
// Sidecar Scanning
|
|
||||||
| { name: JobName.QUEUE_SIDECAR; data: IBaseJob }
|
|
||||||
| { name: JobName.SIDECAR_DISCOVERY; data: IEntityJob }
|
|
||||||
| { name: JobName.SIDECAR_SYNC; data: IEntityJob }
|
|
||||||
| { name: JobName.SIDECAR_WRITE; data: ISidecarWriteJob }
|
|
||||||
|
|
||||||
// Facial Recognition
|
|
||||||
| { name: JobName.QUEUE_FACE_DETECTION; data: IBaseJob }
|
|
||||||
| { name: JobName.FACE_DETECTION; data: IEntityJob }
|
|
||||||
| { name: JobName.QUEUE_FACIAL_RECOGNITION; data: INightlyJob }
|
|
||||||
| { name: JobName.FACIAL_RECOGNITION; data: IDeferrableJob }
|
|
||||||
| { name: JobName.GENERATE_PERSON_THUMBNAIL; data: IEntityJob }
|
|
||||||
|
|
||||||
// Smart Search
|
|
||||||
| { name: JobName.QUEUE_SMART_SEARCH; data: IBaseJob }
|
|
||||||
| { name: JobName.SMART_SEARCH; data: IEntityJob }
|
|
||||||
| { name: JobName.QUEUE_TRASH_EMPTY; data?: IBaseJob }
|
|
||||||
|
|
||||||
// Duplicate Detection
|
|
||||||
| { name: JobName.QUEUE_DUPLICATE_DETECTION; data: IBaseJob }
|
|
||||||
| { name: JobName.DUPLICATE_DETECTION; data: IEntityJob }
|
|
||||||
|
|
||||||
// Filesystem
|
|
||||||
| { name: JobName.DELETE_FILES; data: IDeleteFilesJob }
|
|
||||||
|
|
||||||
// Cleanup
|
|
||||||
| { name: JobName.CLEAN_OLD_AUDIT_LOGS; data?: IBaseJob }
|
|
||||||
| { name: JobName.CLEAN_OLD_SESSION_TOKENS; data?: IBaseJob }
|
|
||||||
|
|
||||||
// Tags
|
|
||||||
| { name: JobName.TAG_CLEANUP; data?: IBaseJob }
|
|
||||||
|
|
||||||
// Asset Deletion
|
|
||||||
| { name: JobName.PERSON_CLEANUP; data?: IBaseJob }
|
|
||||||
| { name: JobName.ASSET_DELETION; data: IAssetDeleteJob }
|
|
||||||
| { name: JobName.ASSET_DELETION_CHECK; data?: IBaseJob }
|
|
||||||
|
|
||||||
// Library Management
|
|
||||||
| { name: JobName.LIBRARY_SYNC_FILE; data: ILibraryFileJob }
|
|
||||||
| { name: JobName.LIBRARY_QUEUE_SYNC_FILES; data: IEntityJob }
|
|
||||||
| { name: JobName.LIBRARY_QUEUE_SYNC_ASSETS; data: IEntityJob }
|
|
||||||
| { name: JobName.LIBRARY_SYNC_ASSET; data: ILibraryAssetJob }
|
|
||||||
| { name: JobName.LIBRARY_DELETE; data: IEntityJob }
|
|
||||||
| { name: JobName.LIBRARY_QUEUE_SYNC_ALL; data?: IBaseJob }
|
|
||||||
| { name: JobName.LIBRARY_QUEUE_CLEANUP; data: IBaseJob }
|
|
||||||
|
|
||||||
// Notification
|
|
||||||
| { name: JobName.SEND_EMAIL; data: IEmailJob }
|
|
||||||
| { name: JobName.NOTIFY_ALBUM_INVITE; data: INotifyAlbumInviteJob }
|
|
||||||
| { name: JobName.NOTIFY_ALBUM_UPDATE; data: INotifyAlbumUpdateJob }
|
|
||||||
| { name: JobName.NOTIFY_SIGNUP; data: INotifySignupJob }
|
|
||||||
|
|
||||||
// Version check
|
|
||||||
| { name: JobName.VERSION_CHECK; data: IBaseJob };
|
|
||||||
|
|
||||||
export enum JobStatus {
|
|
||||||
SUCCESS = 'success',
|
|
||||||
FAILED = 'failed',
|
|
||||||
SKIPPED = 'skipped',
|
|
||||||
}
|
|
||||||
export type Jobs = { [K in JobItem['name']]: (JobItem & { name: K })['data'] };
|
|
||||||
export type JobOf<T extends JobName> = Jobs[T];
|
|
||||||
|
|
||||||
export const IJobRepository = 'IJobRepository';
|
|
||||||
|
|
||||||
export interface IJobRepository {
|
|
||||||
setup(options: { services: ClassConstructor<unknown>[] }): void;
|
|
||||||
startWorkers(): void;
|
|
||||||
run(job: JobItem): Promise<JobStatus>;
|
|
||||||
setConcurrency(queueName: QueueName, concurrency: number): void;
|
|
||||||
queue(item: JobItem): Promise<void>;
|
|
||||||
queueAll(items: JobItem[]): Promise<void>;
|
|
||||||
pause(name: QueueName): Promise<void>;
|
|
||||||
resume(name: QueueName): Promise<void>;
|
|
||||||
empty(name: QueueName): Promise<void>;
|
|
||||||
clear(name: QueueName, type: QueueCleanType): Promise<string[]>;
|
|
||||||
getQueueStatus(name: QueueName): Promise<QueueStatus>;
|
|
||||||
getJobCounts(name: QueueName): Promise<JobCounts>;
|
|
||||||
waitForQueueCompletion(...queues: QueueName[]): Promise<void>;
|
|
||||||
removeJob(jobId: string, name: JobName): Promise<IEntityJob | undefined>;
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
import { Insertable, Updateable } from 'kysely';
|
|
||||||
import { Libraries } from 'src/db';
|
|
||||||
import { LibraryStatsResponseDto } from 'src/dtos/library.dto';
|
|
||||||
import { LibraryEntity } from 'src/entities/library.entity';
|
|
||||||
|
|
||||||
export const ILibraryRepository = 'ILibraryRepository';
|
|
||||||
|
|
||||||
export interface ILibraryRepository {
|
|
||||||
getAll(withDeleted?: boolean): Promise<LibraryEntity[]>;
|
|
||||||
getAllDeleted(): Promise<LibraryEntity[]>;
|
|
||||||
get(id: string, withDeleted?: boolean): Promise<LibraryEntity | undefined>;
|
|
||||||
create(library: Insertable<Libraries>): Promise<LibraryEntity>;
|
|
||||||
delete(id: string): Promise<void>;
|
|
||||||
softDelete(id: string): Promise<void>;
|
|
||||||
update(id: string, library: Updateable<Libraries>): Promise<LibraryEntity>;
|
|
||||||
getStatistics(id: string): Promise<LibraryStatsResponseDto | undefined>;
|
|
||||||
}
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
export const IMachineLearningRepository = 'IMachineLearningRepository';
|
|
||||||
|
|
||||||
export interface BoundingBox {
|
|
||||||
x1: number;
|
|
||||||
y1: number;
|
|
||||||
x2: number;
|
|
||||||
y2: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum ModelTask {
|
|
||||||
FACIAL_RECOGNITION = 'facial-recognition',
|
|
||||||
SEARCH = 'clip',
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum ModelType {
|
|
||||||
DETECTION = 'detection',
|
|
||||||
PIPELINE = 'pipeline',
|
|
||||||
RECOGNITION = 'recognition',
|
|
||||||
TEXTUAL = 'textual',
|
|
||||||
VISUAL = 'visual',
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ModelPayload = { imagePath: string } | { text: string };
|
|
||||||
|
|
||||||
type ModelOptions = { modelName: string };
|
|
||||||
|
|
||||||
export type FaceDetectionOptions = ModelOptions & { minScore: number };
|
|
||||||
|
|
||||||
type VisualResponse = { imageHeight: number; imageWidth: number };
|
|
||||||
export type ClipVisualRequest = { [ModelTask.SEARCH]: { [ModelType.VISUAL]: ModelOptions } };
|
|
||||||
export type ClipVisualResponse = { [ModelTask.SEARCH]: string } & VisualResponse;
|
|
||||||
|
|
||||||
export type ClipTextualRequest = { [ModelTask.SEARCH]: { [ModelType.TEXTUAL]: ModelOptions } };
|
|
||||||
export type ClipTextualResponse = { [ModelTask.SEARCH]: string };
|
|
||||||
|
|
||||||
export type FacialRecognitionRequest = {
|
|
||||||
[ModelTask.FACIAL_RECOGNITION]: {
|
|
||||||
[ModelType.DETECTION]: ModelOptions & { options: { minScore: number } };
|
|
||||||
[ModelType.RECOGNITION]: ModelOptions;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export interface Face {
|
|
||||||
boundingBox: BoundingBox;
|
|
||||||
embedding: string;
|
|
||||||
score: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type FacialRecognitionResponse = { [ModelTask.FACIAL_RECOGNITION]: Face[] } & VisualResponse;
|
|
||||||
export type DetectedFaces = { faces: Face[] } & VisualResponse;
|
|
||||||
export type MachineLearningRequest = ClipVisualRequest | ClipTextualRequest | FacialRecognitionRequest;
|
|
||||||
|
|
||||||
export interface IMachineLearningRepository {
|
|
||||||
encodeImage(urls: string[], imagePath: string, config: ModelOptions): Promise<string>;
|
|
||||||
encodeText(urls: string[], text: string, config: ModelOptions): Promise<string>;
|
|
||||||
detectFaces(urls: string[], imagePath: string, config: FaceDetectionOptions): Promise<DetectedFaces>;
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
import { Insertable, Updateable } from 'kysely';
|
|
||||||
import { MoveHistory } from 'src/db';
|
|
||||||
import { MoveEntity } from 'src/entities/move.entity';
|
|
||||||
import { PathType } from 'src/enum';
|
|
||||||
|
|
||||||
export const IMoveRepository = 'IMoveRepository';
|
|
||||||
|
|
||||||
export type MoveCreate = Pick<MoveEntity, 'oldPath' | 'newPath' | 'entityId' | 'pathType'> & Partial<MoveEntity>;
|
|
||||||
|
|
||||||
export interface IMoveRepository {
|
|
||||||
create(entity: Insertable<MoveHistory>): Promise<MoveEntity>;
|
|
||||||
getByEntity(entityId: string, pathType: PathType): Promise<MoveEntity | undefined>;
|
|
||||||
update(id: string, entity: Updateable<MoveHistory>): Promise<MoveEntity>;
|
|
||||||
delete(id: string): Promise<MoveEntity>;
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
import { Updateable } from 'kysely';
|
|
||||||
import { Partners } from 'src/db';
|
|
||||||
import { PartnerEntity } from 'src/entities/partner.entity';
|
|
||||||
|
|
||||||
export interface PartnerIds {
|
|
||||||
sharedById: string;
|
|
||||||
sharedWithId: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum PartnerDirection {
|
|
||||||
SharedBy = 'shared-by',
|
|
||||||
SharedWith = 'shared-with',
|
|
||||||
}
|
|
||||||
|
|
||||||
export const IPartnerRepository = 'IPartnerRepository';
|
|
||||||
|
|
||||||
export interface IPartnerRepository {
|
|
||||||
getAll(userId: string): Promise<PartnerEntity[]>;
|
|
||||||
get(partner: PartnerIds): Promise<PartnerEntity | undefined>;
|
|
||||||
create(partner: PartnerIds): Promise<PartnerEntity>;
|
|
||||||
remove(partner: PartnerIds): Promise<void>;
|
|
||||||
update(partner: PartnerIds, entity: Updateable<Partners>): Promise<PartnerEntity>;
|
|
||||||
}
|
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
import { Insertable, Selectable, Updateable } from 'kysely';
|
|
||||||
import { AssetFaces, FaceSearch, Person } from 'src/db';
|
|
||||||
import { AssetFaceEntity } from 'src/entities/asset-face.entity';
|
|
||||||
import { PersonEntity } from 'src/entities/person.entity';
|
|
||||||
import { SourceType } from 'src/enum';
|
|
||||||
import { Paginated, PaginationOptions } from 'src/utils/pagination';
|
|
||||||
import { FindOptionsRelations } from 'typeorm';
|
|
||||||
|
|
||||||
export const IPersonRepository = 'IPersonRepository';
|
|
||||||
|
|
||||||
export interface PersonSearchOptions {
|
|
||||||
minimumFaceCount: number;
|
|
||||||
withHidden: boolean;
|
|
||||||
closestFaceAssetId?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface PersonNameSearchOptions {
|
|
||||||
withHidden?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface PersonNameResponse {
|
|
||||||
id: string;
|
|
||||||
name: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface AssetFaceId {
|
|
||||||
assetId: string;
|
|
||||||
personId: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface UpdateFacesData {
|
|
||||||
oldPersonId?: string;
|
|
||||||
faceIds?: string[];
|
|
||||||
newPersonId: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface PersonStatistics {
|
|
||||||
assets: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface PeopleStatistics {
|
|
||||||
total: number;
|
|
||||||
hidden: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface DeleteFacesOptions {
|
|
||||||
sourceType: SourceType;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type UnassignFacesOptions = DeleteFacesOptions;
|
|
||||||
|
|
||||||
export type SelectFaceOptions = (keyof Selectable<AssetFaces>)[];
|
|
||||||
|
|
||||||
export interface IPersonRepository {
|
|
||||||
getAll(options?: Partial<PersonEntity>): AsyncIterableIterator<PersonEntity>;
|
|
||||||
getAllForUser(pagination: PaginationOptions, userId: string, options: PersonSearchOptions): Paginated<PersonEntity>;
|
|
||||||
getAllWithoutFaces(): Promise<PersonEntity[]>;
|
|
||||||
getById(personId: string): Promise<PersonEntity | null>;
|
|
||||||
getByName(userId: string, personName: string, options: PersonNameSearchOptions): Promise<PersonEntity[]>;
|
|
||||||
getDistinctNames(userId: string, options: PersonNameSearchOptions): Promise<PersonNameResponse[]>;
|
|
||||||
|
|
||||||
create(person: Insertable<Person>): Promise<PersonEntity>;
|
|
||||||
createAll(people: Insertable<Person>[]): Promise<string[]>;
|
|
||||||
delete(entities: PersonEntity[]): Promise<void>;
|
|
||||||
deleteFaces(options: DeleteFacesOptions): Promise<void>;
|
|
||||||
refreshFaces(
|
|
||||||
facesToAdd: Insertable<AssetFaces>[],
|
|
||||||
faceIdsToRemove: string[],
|
|
||||||
embeddingsToAdd?: Insertable<FaceSearch>[],
|
|
||||||
): Promise<void>;
|
|
||||||
getAllFaces(options?: Partial<AssetFaceEntity>): AsyncIterableIterator<AssetFaceEntity>;
|
|
||||||
getFaceById(id: string): Promise<AssetFaceEntity>;
|
|
||||||
getFaceByIdWithAssets(
|
|
||||||
id: string,
|
|
||||||
relations?: FindOptionsRelations<AssetFaceEntity>,
|
|
||||||
select?: SelectFaceOptions,
|
|
||||||
): Promise<AssetFaceEntity | undefined>;
|
|
||||||
getFaces(assetId: string): Promise<AssetFaceEntity[]>;
|
|
||||||
getFacesByIds(ids: AssetFaceId[]): Promise<AssetFaceEntity[]>;
|
|
||||||
getRandomFace(personId: string): Promise<AssetFaceEntity | undefined>;
|
|
||||||
getStatistics(personId: string): Promise<PersonStatistics>;
|
|
||||||
reassignFace(assetFaceId: string, newPersonId: string): Promise<number>;
|
|
||||||
getNumberOfPeople(userId: string): Promise<PeopleStatistics>;
|
|
||||||
reassignFaces(data: UpdateFacesData): Promise<number>;
|
|
||||||
unassignFaces(options: UnassignFacesOptions): Promise<void>;
|
|
||||||
update(person: Updateable<Person> & { id: string }): Promise<PersonEntity>;
|
|
||||||
updateAll(people: Insertable<Person>[]): Promise<void>;
|
|
||||||
getLatestFaceDate(): Promise<string | undefined>;
|
|
||||||
}
|
|
||||||
@@ -1,213 +0,0 @@
|
|||||||
import { AssetEntity } from 'src/entities/asset.entity';
|
|
||||||
import { GeodataPlacesEntity } from 'src/entities/geodata-places.entity';
|
|
||||||
import { AssetStatus, AssetType } from 'src/enum';
|
|
||||||
import { Paginated } from 'src/utils/pagination';
|
|
||||||
|
|
||||||
export const ISearchRepository = 'ISearchRepository';
|
|
||||||
|
|
||||||
export interface SearchResult<T> {
|
|
||||||
/** total matches */
|
|
||||||
total: number;
|
|
||||||
/** collection size */
|
|
||||||
count: number;
|
|
||||||
/** current page */
|
|
||||||
page: number;
|
|
||||||
/** items for page */
|
|
||||||
items: T[];
|
|
||||||
/** score */
|
|
||||||
distances: number[];
|
|
||||||
facets: SearchFacet[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface SearchFacet {
|
|
||||||
fieldName: string;
|
|
||||||
counts: Array<{
|
|
||||||
count: number;
|
|
||||||
value: string;
|
|
||||||
}>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type SearchExploreItemSet<T> = Array<{
|
|
||||||
value: string;
|
|
||||||
data: T;
|
|
||||||
}>;
|
|
||||||
|
|
||||||
export interface SearchExploreItem<T> {
|
|
||||||
fieldName: string;
|
|
||||||
items: SearchExploreItemSet<T>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface SearchAssetIDOptions {
|
|
||||||
checksum?: Buffer;
|
|
||||||
deviceAssetId?: string;
|
|
||||||
id?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface SearchUserIdOptions {
|
|
||||||
deviceId?: string;
|
|
||||||
libraryId?: string | null;
|
|
||||||
userIds?: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export type SearchIdOptions = SearchAssetIDOptions & SearchUserIdOptions;
|
|
||||||
|
|
||||||
export interface SearchStatusOptions {
|
|
||||||
isArchived?: boolean;
|
|
||||||
isEncoded?: boolean;
|
|
||||||
isFavorite?: boolean;
|
|
||||||
isMotion?: boolean;
|
|
||||||
isOffline?: boolean;
|
|
||||||
isVisible?: boolean;
|
|
||||||
isNotInAlbum?: boolean;
|
|
||||||
type?: AssetType;
|
|
||||||
status?: AssetStatus;
|
|
||||||
withArchived?: boolean;
|
|
||||||
withDeleted?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface SearchOneToOneRelationOptions {
|
|
||||||
withExif?: boolean;
|
|
||||||
withStacked?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface SearchRelationOptions extends SearchOneToOneRelationOptions {
|
|
||||||
withFaces?: boolean;
|
|
||||||
withPeople?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface SearchDateOptions {
|
|
||||||
createdBefore?: Date;
|
|
||||||
createdAfter?: Date;
|
|
||||||
takenBefore?: Date;
|
|
||||||
takenAfter?: Date;
|
|
||||||
trashedBefore?: Date;
|
|
||||||
trashedAfter?: Date;
|
|
||||||
updatedBefore?: Date;
|
|
||||||
updatedAfter?: Date;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface SearchPathOptions {
|
|
||||||
encodedVideoPath?: string;
|
|
||||||
originalFileName?: string;
|
|
||||||
originalPath?: string;
|
|
||||||
previewPath?: string;
|
|
||||||
thumbnailPath?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface SearchExifOptions {
|
|
||||||
city?: string | null;
|
|
||||||
country?: string | null;
|
|
||||||
lensModel?: string | null;
|
|
||||||
make?: string | null;
|
|
||||||
model?: string | null;
|
|
||||||
state?: string | null;
|
|
||||||
description?: string | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface SearchEmbeddingOptions {
|
|
||||||
embedding: string;
|
|
||||||
userIds: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface SearchPeopleOptions {
|
|
||||||
personIds?: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface SearchTagOptions {
|
|
||||||
tagIds?: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface SearchOrderOptions {
|
|
||||||
orderDirection?: 'asc' | 'desc';
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface SearchPaginationOptions {
|
|
||||||
page: number;
|
|
||||||
size: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
type BaseAssetSearchOptions = SearchDateOptions &
|
|
||||||
SearchIdOptions &
|
|
||||||
SearchExifOptions &
|
|
||||||
SearchOrderOptions &
|
|
||||||
SearchPathOptions &
|
|
||||||
SearchStatusOptions &
|
|
||||||
SearchUserIdOptions &
|
|
||||||
SearchPeopleOptions &
|
|
||||||
SearchTagOptions;
|
|
||||||
|
|
||||||
export type AssetSearchOptions = BaseAssetSearchOptions & SearchRelationOptions;
|
|
||||||
|
|
||||||
export type AssetSearchOneToOneRelationOptions = BaseAssetSearchOptions & SearchOneToOneRelationOptions;
|
|
||||||
|
|
||||||
export type AssetSearchBuilderOptions = Omit<AssetSearchOptions, 'orderDirection'>;
|
|
||||||
|
|
||||||
export type SmartSearchOptions = SearchDateOptions &
|
|
||||||
SearchEmbeddingOptions &
|
|
||||||
SearchExifOptions &
|
|
||||||
SearchOneToOneRelationOptions &
|
|
||||||
SearchStatusOptions &
|
|
||||||
SearchUserIdOptions &
|
|
||||||
SearchPeopleOptions &
|
|
||||||
SearchTagOptions;
|
|
||||||
|
|
||||||
export interface FaceEmbeddingSearch extends SearchEmbeddingOptions {
|
|
||||||
hasPerson?: boolean;
|
|
||||||
numResults: number;
|
|
||||||
maxDistance: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface AssetDuplicateSearch {
|
|
||||||
assetId: string;
|
|
||||||
embedding: string;
|
|
||||||
maxDistance: number;
|
|
||||||
type: AssetType;
|
|
||||||
userIds: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface FaceSearchResult {
|
|
||||||
distance: number;
|
|
||||||
id: string;
|
|
||||||
personId: string | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface AssetDuplicateResult {
|
|
||||||
assetId: string;
|
|
||||||
duplicateId: string | null;
|
|
||||||
distance: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface GetStatesOptions {
|
|
||||||
country?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface GetCitiesOptions extends GetStatesOptions {
|
|
||||||
state?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface GetCameraModelsOptions {
|
|
||||||
make?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface GetCameraMakesOptions {
|
|
||||||
model?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ISearchRepository {
|
|
||||||
searchMetadata(pagination: SearchPaginationOptions, options: AssetSearchOptions): Paginated<AssetEntity>;
|
|
||||||
searchSmart(pagination: SearchPaginationOptions, options: SmartSearchOptions): Paginated<AssetEntity>;
|
|
||||||
searchDuplicates(options: AssetDuplicateSearch): Promise<AssetDuplicateResult[]>;
|
|
||||||
searchFaces(search: FaceEmbeddingSearch): Promise<FaceSearchResult[]>;
|
|
||||||
searchRandom(size: number, options: AssetSearchOptions): Promise<AssetEntity[]>;
|
|
||||||
upsert(assetId: string, embedding: string): Promise<void>;
|
|
||||||
searchPlaces(placeName: string): Promise<GeodataPlacesEntity[]>;
|
|
||||||
getAssetsByCity(userIds: string[]): Promise<AssetEntity[]>;
|
|
||||||
deleteAllSearchEmbeddings(): Promise<void>;
|
|
||||||
getDimensionSize(): Promise<number>;
|
|
||||||
setDimensionSize(dimSize: number): Promise<void>;
|
|
||||||
getCountries(userIds: string[]): Promise<Array<string | null>>;
|
|
||||||
getStates(userIds: string[], options: GetStatesOptions): Promise<Array<string | null>>;
|
|
||||||
getCities(userIds: string[], options: GetCitiesOptions): Promise<Array<string | null>>;
|
|
||||||
getCameraMakes(userIds: string[], options: GetCameraMakesOptions): Promise<Array<string | null>>;
|
|
||||||
getCameraModels(userIds: string[], options: GetCameraModelsOptions): Promise<Array<string | null>>;
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
import { Insertable, Updateable } from 'kysely';
|
|
||||||
import { SharedLinks } from 'src/db';
|
|
||||||
import { SharedLinkEntity } from 'src/entities/shared-link.entity';
|
|
||||||
|
|
||||||
export const ISharedLinkRepository = 'ISharedLinkRepository';
|
|
||||||
|
|
||||||
export type SharedLinkSearchOptions = {
|
|
||||||
userId: string;
|
|
||||||
albumId?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export interface ISharedLinkRepository {
|
|
||||||
getAll(options: SharedLinkSearchOptions): Promise<SharedLinkEntity[]>;
|
|
||||||
get(userId: string, id: string): Promise<SharedLinkEntity | undefined>;
|
|
||||||
getByKey(key: Buffer): Promise<SharedLinkEntity | undefined>;
|
|
||||||
create(entity: Insertable<SharedLinks> & { assetIds?: string[] }): Promise<SharedLinkEntity>;
|
|
||||||
update(entity: Updateable<SharedLinks> & { id: string; assetIds?: string[] }): Promise<SharedLinkEntity>;
|
|
||||||
remove(entity: SharedLinkEntity): Promise<void>;
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
import { Updateable } from 'kysely';
|
|
||||||
import { StackEntity } from 'src/entities/stack.entity';
|
|
||||||
|
|
||||||
export const IStackRepository = 'IStackRepository';
|
|
||||||
|
|
||||||
export interface StackSearch {
|
|
||||||
ownerId: string;
|
|
||||||
primaryAssetId?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IStackRepository {
|
|
||||||
search(query: StackSearch): Promise<StackEntity[]>;
|
|
||||||
create(stack: { ownerId: string; assetIds: string[] }): Promise<StackEntity>;
|
|
||||||
update(id: string, entity: Updateable<StackEntity>): Promise<StackEntity>;
|
|
||||||
delete(id: string): Promise<void>;
|
|
||||||
deleteAll(ids: string[]): Promise<void>;
|
|
||||||
getById(id: string): Promise<StackEntity | undefined>;
|
|
||||||
}
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
import { WatchOptions } from 'chokidar';
|
|
||||||
import { Stats } from 'node:fs';
|
|
||||||
import { FileReadOptions } from 'node:fs/promises';
|
|
||||||
import { Readable, Writable } from 'node:stream';
|
|
||||||
import { CrawlOptionsDto, WalkOptionsDto } from 'src/dtos/library.dto';
|
|
||||||
|
|
||||||
export interface ImmichReadStream {
|
|
||||||
stream: Readable;
|
|
||||||
type?: string;
|
|
||||||
length?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ImmichZipStream extends ImmichReadStream {
|
|
||||||
addFile: (inputPath: string, filename: string) => void;
|
|
||||||
finalize: () => Promise<void>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface DiskUsage {
|
|
||||||
available: number;
|
|
||||||
free: number;
|
|
||||||
total: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const IStorageRepository = 'IStorageRepository';
|
|
||||||
|
|
||||||
export interface WatchEvents {
|
|
||||||
onReady(): void;
|
|
||||||
onAdd(path: string): void;
|
|
||||||
onChange(path: string): void;
|
|
||||||
onUnlink(path: string): void;
|
|
||||||
onError(error: Error): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IStorageRepository {
|
|
||||||
createZipStream(): ImmichZipStream;
|
|
||||||
createReadStream(filepath: string, mimeType?: string | null): Promise<ImmichReadStream>;
|
|
||||||
readFile(filepath: string, options?: FileReadOptions<Buffer>): Promise<Buffer>;
|
|
||||||
createFile(filepath: string, buffer: Buffer): Promise<void>;
|
|
||||||
createWriteStream(filepath: string): Writable;
|
|
||||||
createOrOverwriteFile(filepath: string, buffer: Buffer): Promise<void>;
|
|
||||||
overwriteFile(filepath: string, buffer: Buffer): Promise<void>;
|
|
||||||
realpath(filepath: string): Promise<string>;
|
|
||||||
unlink(filepath: string): Promise<void>;
|
|
||||||
unlinkDir(folder: string, options?: { recursive?: boolean; force?: boolean }): Promise<void>;
|
|
||||||
removeEmptyDirs(folder: string, self?: boolean): Promise<void>;
|
|
||||||
checkFileExists(filepath: string, mode?: number): Promise<boolean>;
|
|
||||||
mkdirSync(filepath: string): void;
|
|
||||||
checkDiskUsage(folder: string): Promise<DiskUsage>;
|
|
||||||
readdir(folder: string): Promise<string[]>;
|
|
||||||
stat(filepath: string): Promise<Stats>;
|
|
||||||
crawl(options: CrawlOptionsDto): Promise<string[]>;
|
|
||||||
walk(options: WalkOptionsDto): AsyncGenerator<string[]>;
|
|
||||||
copyFile(source: string, target: string): Promise<void>;
|
|
||||||
rename(source: string, target: string): Promise<void>;
|
|
||||||
watch(paths: string[], options: WatchOptions, events: Partial<WatchEvents>): () => Promise<void>;
|
|
||||||
utimes(filepath: string, atime: Date, mtime: Date): Promise<void>;
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
import { TagEntity } from 'src/entities/tag.entity';
|
|
||||||
import { IBulkAsset } from 'src/utils/asset.util';
|
|
||||||
|
|
||||||
export const ITagRepository = 'ITagRepository';
|
|
||||||
|
|
||||||
export type AssetTagItem = { assetId: string; tagId: string };
|
|
||||||
|
|
||||||
export interface ITagRepository extends IBulkAsset {
|
|
||||||
getAll(userId: string): Promise<TagEntity[]>;
|
|
||||||
getByValue(userId: string, value: string): Promise<TagEntity | null>;
|
|
||||||
upsertValue(request: { userId: string; value: string; parent?: TagEntity }): Promise<TagEntity>;
|
|
||||||
|
|
||||||
create(tag: Partial<TagEntity>): Promise<TagEntity>;
|
|
||||||
get(id: string): Promise<TagEntity | null>;
|
|
||||||
update(tag: { id: string } & Partial<TagEntity>): Promise<TagEntity>;
|
|
||||||
delete(id: string): Promise<void>;
|
|
||||||
|
|
||||||
upsertAssetTags({ assetId, tagIds }: { assetId: string; tagIds: string[] }): Promise<void>;
|
|
||||||
upsertAssetIds(items: AssetTagItem[]): Promise<AssetTagItem[]>;
|
|
||||||
deleteEmptyTags(): Promise<void>;
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
import { Insertable, Updateable } from 'kysely';
|
|
||||||
import { Users } from 'src/db';
|
|
||||||
import { UserMetadata } from 'src/entities/user-metadata.entity';
|
|
||||||
import { UserEntity } from 'src/entities/user.entity';
|
|
||||||
|
|
||||||
export interface UserListFilter {
|
|
||||||
withDeleted?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface UserStatsQueryResponse {
|
|
||||||
userId: string;
|
|
||||||
userName: string;
|
|
||||||
photos: number;
|
|
||||||
videos: number;
|
|
||||||
usage: number;
|
|
||||||
usagePhotos: number;
|
|
||||||
usageVideos: number;
|
|
||||||
quotaSizeInBytes: number | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface UserFindOptions {
|
|
||||||
withDeleted?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const IUserRepository = 'IUserRepository';
|
|
||||||
|
|
||||||
export interface IUserRepository {
|
|
||||||
get(id: string, options: UserFindOptions): Promise<UserEntity | undefined>;
|
|
||||||
getAdmin(): Promise<UserEntity | undefined>;
|
|
||||||
hasAdmin(): Promise<boolean>;
|
|
||||||
getByEmail(email: string, withPassword?: boolean): Promise<UserEntity | undefined>;
|
|
||||||
getByStorageLabel(storageLabel: string): Promise<UserEntity | undefined>;
|
|
||||||
getByOAuthId(oauthId: string): Promise<UserEntity | undefined>;
|
|
||||||
getDeletedUsers(): Promise<UserEntity[]>;
|
|
||||||
getList(filter?: UserListFilter): Promise<UserEntity[]>;
|
|
||||||
getUserStats(): Promise<UserStatsQueryResponse[]>;
|
|
||||||
create(user: Insertable<Users>): Promise<UserEntity>;
|
|
||||||
update(id: string, user: Updateable<Users>): Promise<UserEntity>;
|
|
||||||
restore(id: string): Promise<UserEntity>;
|
|
||||||
upsertMetadata<T extends keyof UserMetadata>(id: string, item: { key: T; value: UserMetadata[T] }): Promise<void>;
|
|
||||||
deleteMetadata<T extends keyof UserMetadata>(id: string, key: T): Promise<void>;
|
|
||||||
delete(user: UserEntity, hard?: boolean): Promise<UserEntity>;
|
|
||||||
updateUsage(id: string, delta: number): Promise<void>;
|
|
||||||
syncUsage(id?: string): Promise<void>;
|
|
||||||
}
|
|
||||||
@@ -10,14 +10,10 @@ import { UploadFieldName } from 'src/dtos/asset-media.dto';
|
|||||||
import { RouteKey } from 'src/enum';
|
import { RouteKey } from 'src/enum';
|
||||||
import { AuthRequest } from 'src/middleware/auth.guard';
|
import { AuthRequest } from 'src/middleware/auth.guard';
|
||||||
import { LoggingRepository } from 'src/repositories/logging.repository';
|
import { LoggingRepository } from 'src/repositories/logging.repository';
|
||||||
import { AssetMediaService, UploadFile } from 'src/services/asset-media.service';
|
import { AssetMediaService } from 'src/services/asset-media.service';
|
||||||
|
import { ImmichFile, UploadFile, UploadFiles } from 'src/types';
|
||||||
import { asRequest, mapToUploadFile } from 'src/utils/asset.util';
|
import { asRequest, mapToUploadFile } from 'src/utils/asset.util';
|
||||||
|
|
||||||
export interface UploadFiles {
|
|
||||||
assetData: ImmichFile[];
|
|
||||||
sidecarData: ImmichFile[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getFile(files: UploadFiles, property: 'assetData' | 'sidecarData') {
|
export function getFile(files: UploadFiles, property: 'assetData' | 'sidecarData') {
|
||||||
const file = files[property]?.[0];
|
const file = files[property]?.[0];
|
||||||
return file ? mapToUploadFile(file) : file;
|
return file ? mapToUploadFile(file) : file;
|
||||||
@@ -30,12 +26,6 @@ export function getFiles(files: UploadFiles) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ImmichFile extends Express.Multer.File {
|
|
||||||
/** sha1 hash of file */
|
|
||||||
uuid: string;
|
|
||||||
checksum: Buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
type DiskStorageCallback = (error: Error | null, result: string) => void;
|
type DiskStorageCallback = (error: Error | null, result: string) => void;
|
||||||
|
|
||||||
type ImmichMulterFile = Express.Multer.File & { uuid: string };
|
type ImmichMulterFile = Express.Multer.File & { uuid: string };
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { DatabaseExtension } from 'src/interfaces/database.interface';
|
import { DatabaseExtension } from 'src/enum';
|
||||||
import { ConfigRepository } from 'src/repositories/config.repository';
|
import { ConfigRepository } from 'src/repositories/config.repository';
|
||||||
import { MigrationInterface, QueryRunner } from 'typeorm';
|
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { DatabaseExtension } from 'src/interfaces/database.interface';
|
import { DatabaseExtension } from 'src/enum';
|
||||||
import { ConfigRepository } from 'src/repositories/config.repository';
|
import { ConfigRepository } from 'src/repositories/config.repository';
|
||||||
import { MigrationInterface, QueryRunner } from 'typeorm';
|
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { DatabaseExtension } from 'src/interfaces/database.interface';
|
import { DatabaseExtension } from 'src/enum';
|
||||||
import { ConfigRepository } from 'src/repositories/config.repository';
|
import { ConfigRepository } from 'src/repositories/config.repository';
|
||||||
import { MigrationInterface, QueryRunner } from 'typeorm';
|
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||||
|
|
||||||
|
export class NullableDates1737845696644 implements MigrationInterface {
|
||||||
|
name = 'NullableDates1737845696644'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "assets" ALTER COLUMN "fileCreatedAt" DROP NOT NULL`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "assets" ALTER COLUMN "localDateTime" DROP NOT NULL`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "assets" ALTER COLUMN "fileModifiedAt" DROP NOT NULL`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "assets" ALTER COLUMN "fileModifiedAt" SET NOT NULL`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "assets" ALTER COLUMN "localDateTime" SET NOT NULL`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "assets" ALTER COLUMN "fileCreatedAt" SET NOT NULL`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -43,3 +43,6 @@ where
|
|||||||
and "activity"."albumId" = $2
|
and "activity"."albumId" = $2
|
||||||
and "activity"."isLiked" = $3
|
and "activity"."isLiked" = $3
|
||||||
and "assets"."deletedAt" is null
|
and "assets"."deletedAt" is null
|
||||||
|
and "assets"."fileCreatedAt" is not null
|
||||||
|
and "assets"."fileModifiedAt" is not null
|
||||||
|
and "assets"."localDateTime" is not null
|
||||||
|
|||||||
@@ -3,29 +3,28 @@
|
|||||||
-- ApiKeyRepository.getKey
|
-- ApiKeyRepository.getKey
|
||||||
select
|
select
|
||||||
"api_keys"."id",
|
"api_keys"."id",
|
||||||
"api_keys"."key",
|
|
||||||
"api_keys"."userId",
|
|
||||||
"api_keys"."permissions",
|
"api_keys"."permissions",
|
||||||
to_json("user") as "user"
|
(
|
||||||
from
|
|
||||||
"api_keys"
|
|
||||||
inner join lateral (
|
|
||||||
select
|
select
|
||||||
"users".*,
|
to_json(obj)
|
||||||
|
from
|
||||||
(
|
(
|
||||||
select
|
select
|
||||||
array_agg("user_metadata") as "metadata"
|
"users"."id",
|
||||||
|
"users"."name",
|
||||||
|
"users"."email",
|
||||||
|
"users"."isAdmin",
|
||||||
|
"users"."quotaUsageInBytes",
|
||||||
|
"users"."quotaSizeInBytes"
|
||||||
from
|
from
|
||||||
"user_metadata"
|
"users"
|
||||||
where
|
where
|
||||||
"users"."id" = "user_metadata"."userId"
|
"users"."id" = "api_keys"."userId"
|
||||||
) as "metadata"
|
and "users"."deletedAt" is null
|
||||||
from
|
) as obj
|
||||||
"users"
|
) as "user"
|
||||||
where
|
from
|
||||||
"users"."id" = "api_keys"."userId"
|
"api_keys"
|
||||||
and "users"."deletedAt" is null
|
|
||||||
) as "user" on true
|
|
||||||
where
|
where
|
||||||
"api_keys"."key" = $1
|
"api_keys"."key" = $1
|
||||||
|
|
||||||
|
|||||||
@@ -159,6 +159,9 @@ where
|
|||||||
"ownerId" = $1::uuid
|
"ownerId" = $1::uuid
|
||||||
and "deviceId" = $2
|
and "deviceId" = $2
|
||||||
and "isVisible" = $3
|
and "isVisible" = $3
|
||||||
|
and "assets"."fileCreatedAt" is not null
|
||||||
|
and "assets"."fileModifiedAt" is not null
|
||||||
|
and "assets"."localDateTime" is not null
|
||||||
and "deletedAt" is null
|
and "deletedAt" is null
|
||||||
|
|
||||||
-- AssetRepository.getLivePhotoCount
|
-- AssetRepository.getLivePhotoCount
|
||||||
@@ -260,6 +263,9 @@ with
|
|||||||
where
|
where
|
||||||
"assets"."deletedAt" is null
|
"assets"."deletedAt" is null
|
||||||
and "assets"."isVisible" = $2
|
and "assets"."isVisible" = $2
|
||||||
|
and "assets"."fileCreatedAt" is not null
|
||||||
|
and "assets"."fileModifiedAt" is not null
|
||||||
|
and "assets"."localDateTime" is not null
|
||||||
)
|
)
|
||||||
select
|
select
|
||||||
"timeBucket",
|
"timeBucket",
|
||||||
|
|||||||
@@ -13,6 +13,9 @@ where
|
|||||||
and "assets"."isFavorite" = $4
|
and "assets"."isFavorite" = $4
|
||||||
and "assets"."isArchived" = $5
|
and "assets"."isArchived" = $5
|
||||||
and "assets"."deletedAt" is null
|
and "assets"."deletedAt" is null
|
||||||
|
and "assets"."fileCreatedAt" is not null
|
||||||
|
and "assets"."fileModifiedAt" is not null
|
||||||
|
and "assets"."localDateTime" is not null
|
||||||
order by
|
order by
|
||||||
"assets"."fileCreatedAt" desc
|
"assets"."fileCreatedAt" desc
|
||||||
limit
|
limit
|
||||||
@@ -34,6 +37,9 @@ offset
|
|||||||
and "assets"."isFavorite" = $4
|
and "assets"."isFavorite" = $4
|
||||||
and "assets"."isArchived" = $5
|
and "assets"."isArchived" = $5
|
||||||
and "assets"."deletedAt" is null
|
and "assets"."deletedAt" is null
|
||||||
|
and "assets"."fileCreatedAt" is not null
|
||||||
|
and "assets"."fileModifiedAt" is not null
|
||||||
|
and "assets"."localDateTime" is not null
|
||||||
and "assets"."id" < $6
|
and "assets"."id" < $6
|
||||||
order by
|
order by
|
||||||
random()
|
random()
|
||||||
@@ -54,6 +60,9 @@ union all
|
|||||||
and "assets"."isFavorite" = $11
|
and "assets"."isFavorite" = $11
|
||||||
and "assets"."isArchived" = $12
|
and "assets"."isArchived" = $12
|
||||||
and "assets"."deletedAt" is null
|
and "assets"."deletedAt" is null
|
||||||
|
and "assets"."fileCreatedAt" is not null
|
||||||
|
and "assets"."fileModifiedAt" is not null
|
||||||
|
and "assets"."localDateTime" is not null
|
||||||
and "assets"."id" > $13
|
and "assets"."id" > $13
|
||||||
order by
|
order by
|
||||||
random()
|
random()
|
||||||
@@ -77,6 +86,9 @@ where
|
|||||||
and "assets"."isFavorite" = $4
|
and "assets"."isFavorite" = $4
|
||||||
and "assets"."isArchived" = $5
|
and "assets"."isArchived" = $5
|
||||||
and "assets"."deletedAt" is null
|
and "assets"."deletedAt" is null
|
||||||
|
and "assets"."fileCreatedAt" is not null
|
||||||
|
and "assets"."fileModifiedAt" is not null
|
||||||
|
and "assets"."localDateTime" is not null
|
||||||
order by
|
order by
|
||||||
smart_search.embedding <=> $6
|
smart_search.embedding <=> $6
|
||||||
limit
|
limit
|
||||||
|
|||||||
@@ -10,41 +10,29 @@ where
|
|||||||
|
|
||||||
-- SessionRepository.getByToken
|
-- SessionRepository.getByToken
|
||||||
select
|
select
|
||||||
"sessions".*,
|
"sessions"."id",
|
||||||
to_json("user") as "user"
|
"sessions"."updatedAt",
|
||||||
from
|
(
|
||||||
"sessions"
|
|
||||||
inner join lateral (
|
|
||||||
select
|
select
|
||||||
"id",
|
to_json(obj)
|
||||||
"email",
|
from
|
||||||
"createdAt",
|
|
||||||
"profileImagePath",
|
|
||||||
"isAdmin",
|
|
||||||
"shouldChangePassword",
|
|
||||||
"deletedAt",
|
|
||||||
"oauthId",
|
|
||||||
"updatedAt",
|
|
||||||
"storageLabel",
|
|
||||||
"name",
|
|
||||||
"quotaSizeInBytes",
|
|
||||||
"quotaUsageInBytes",
|
|
||||||
"status",
|
|
||||||
"profileChangedAt",
|
|
||||||
(
|
(
|
||||||
select
|
select
|
||||||
array_agg("user_metadata") as "metadata"
|
"users"."id",
|
||||||
|
"users"."name",
|
||||||
|
"users"."email",
|
||||||
|
"users"."isAdmin",
|
||||||
|
"users"."quotaUsageInBytes",
|
||||||
|
"users"."quotaSizeInBytes"
|
||||||
from
|
from
|
||||||
"user_metadata"
|
"users"
|
||||||
where
|
where
|
||||||
"users"."id" = "user_metadata"."userId"
|
"users"."id" = "sessions"."userId"
|
||||||
) as "metadata"
|
and "users"."deletedAt" is null
|
||||||
from
|
) as obj
|
||||||
"users"
|
) as "user"
|
||||||
where
|
from
|
||||||
"users"."id" = "sessions"."userId"
|
"sessions"
|
||||||
and "users"."deletedAt" is null
|
|
||||||
) as "user" on true
|
|
||||||
where
|
where
|
||||||
"sessions"."token" = $1
|
"sessions"."token" = $1
|
||||||
|
|
||||||
|
|||||||
@@ -153,12 +153,19 @@ where
|
|||||||
"shared_links"."type" = $2
|
"shared_links"."type" = $2
|
||||||
or "album"."id" is not null
|
or "album"."id" is not null
|
||||||
)
|
)
|
||||||
|
and "shared_links"."albumId" = $3
|
||||||
order by
|
order by
|
||||||
"shared_links"."createdAt" desc
|
"shared_links"."createdAt" desc
|
||||||
|
|
||||||
-- SharedLinkRepository.getByKey
|
-- SharedLinkRepository.getByKey
|
||||||
select
|
select
|
||||||
"shared_links".*,
|
"shared_links"."id",
|
||||||
|
"shared_links"."userId",
|
||||||
|
"shared_links"."expiresAt",
|
||||||
|
"shared_links"."showExif",
|
||||||
|
"shared_links"."allowUpload",
|
||||||
|
"shared_links"."allowDownload",
|
||||||
|
"shared_links"."password",
|
||||||
(
|
(
|
||||||
select
|
select
|
||||||
to_json(obj)
|
to_json(obj)
|
||||||
@@ -166,20 +173,11 @@ select
|
|||||||
(
|
(
|
||||||
select
|
select
|
||||||
"users"."id",
|
"users"."id",
|
||||||
"users"."email",
|
|
||||||
"users"."createdAt",
|
|
||||||
"users"."profileImagePath",
|
|
||||||
"users"."isAdmin",
|
|
||||||
"users"."shouldChangePassword",
|
|
||||||
"users"."deletedAt",
|
|
||||||
"users"."oauthId",
|
|
||||||
"users"."updatedAt",
|
|
||||||
"users"."storageLabel",
|
|
||||||
"users"."name",
|
"users"."name",
|
||||||
"users"."quotaSizeInBytes",
|
"users"."email",
|
||||||
|
"users"."isAdmin",
|
||||||
"users"."quotaUsageInBytes",
|
"users"."quotaUsageInBytes",
|
||||||
"users"."status",
|
"users"."quotaSizeInBytes"
|
||||||
"users"."profileChangedAt"
|
|
||||||
from
|
from
|
||||||
"users"
|
"users"
|
||||||
where
|
where
|
||||||
|
|||||||
@@ -10,6 +10,9 @@ where
|
|||||||
and "isVisible" = $3
|
and "isVisible" = $3
|
||||||
and "isArchived" = $4
|
and "isArchived" = $4
|
||||||
and "deletedAt" is null
|
and "deletedAt" is null
|
||||||
|
and "fileModifiedAt" is not null
|
||||||
|
and "fileModifiedAt" is not null
|
||||||
|
and "localDateTime" is not null
|
||||||
|
|
||||||
-- ViewRepository.getAssetsByOriginalPath
|
-- ViewRepository.getAssetsByOriginalPath
|
||||||
select
|
select
|
||||||
@@ -23,6 +26,9 @@ where
|
|||||||
and "isVisible" = $2
|
and "isVisible" = $2
|
||||||
and "isArchived" = $3
|
and "isArchived" = $3
|
||||||
and "deletedAt" is null
|
and "deletedAt" is null
|
||||||
|
and "fileModifiedAt" is not null
|
||||||
|
and "fileModifiedAt" is not null
|
||||||
|
and "localDateTime" is not null
|
||||||
and "originalPath" like $4
|
and "originalPath" like $4
|
||||||
and "originalPath" not like $5
|
and "originalPath" not like $5
|
||||||
order by
|
order by
|
||||||
|
|||||||
@@ -65,6 +65,9 @@ export class ActivityRepository {
|
|||||||
.where('activity.albumId', '=', albumId)
|
.where('activity.albumId', '=', albumId)
|
||||||
.where('activity.isLiked', '=', false)
|
.where('activity.isLiked', '=', false)
|
||||||
.where('assets.deletedAt', 'is', null)
|
.where('assets.deletedAt', 'is', null)
|
||||||
|
.where('assets.fileCreatedAt', 'is not', null)
|
||||||
|
.where('assets.fileModifiedAt', 'is not', null)
|
||||||
|
.where('assets.localDateTime', 'is not', null)
|
||||||
.executeTakeFirstOrThrow();
|
.executeTakeFirstOrThrow();
|
||||||
|
|
||||||
return count as number;
|
return count as number;
|
||||||
|
|||||||
@@ -6,7 +6,17 @@ import { Albums, DB } from 'src/db';
|
|||||||
import { Chunked, ChunkedArray, ChunkedSet, DummyValue, GenerateSql } from 'src/decorators';
|
import { Chunked, ChunkedArray, ChunkedSet, DummyValue, GenerateSql } from 'src/decorators';
|
||||||
import { AlbumUserCreateDto } from 'src/dtos/album.dto';
|
import { AlbumUserCreateDto } from 'src/dtos/album.dto';
|
||||||
import { AlbumEntity } from 'src/entities/album.entity';
|
import { AlbumEntity } from 'src/entities/album.entity';
|
||||||
import { AlbumAssetCount, AlbumInfoOptions, IAlbumRepository } from 'src/interfaces/album.interface';
|
|
||||||
|
export interface AlbumAssetCount {
|
||||||
|
albumId: string;
|
||||||
|
assetCount: number;
|
||||||
|
startDate: Date | null;
|
||||||
|
endDate: Date | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AlbumInfoOptions {
|
||||||
|
withAssets: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
const userColumns = [
|
const userColumns = [
|
||||||
'id',
|
'id',
|
||||||
@@ -71,7 +81,7 @@ const withAssets = (eb: ExpressionBuilder<DB, 'albums'>) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AlbumRepository implements IAlbumRepository {
|
export class AlbumRepository {
|
||||||
constructor(@InjectKysely() private db: Kysely<DB>) {}
|
constructor(@InjectKysely() private db: Kysely<DB>) {}
|
||||||
|
|
||||||
@GenerateSql({ params: [DummyValue.UUID, { withAssets: true }] })
|
@GenerateSql({ params: [DummyValue.UUID, { withAssets: true }] })
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { Insertable, Kysely, Updateable } from 'kysely';
|
import { Insertable, Kysely, Updateable } from 'kysely';
|
||||||
|
import { jsonObjectFrom } from 'kysely/helpers/postgres';
|
||||||
import { InjectKysely } from 'nestjs-kysely';
|
import { InjectKysely } from 'nestjs-kysely';
|
||||||
|
import { columns } from 'src/database';
|
||||||
import { ApiKeys, DB } from 'src/db';
|
import { ApiKeys, DB } from 'src/db';
|
||||||
import { DummyValue, GenerateSql } from 'src/decorators';
|
import { DummyValue, GenerateSql } from 'src/decorators';
|
||||||
import { asUuid } from 'src/utils/database';
|
import { asUuid } from 'src/utils/database';
|
||||||
|
|
||||||
const columns = ['id', 'name', 'userId', 'createdAt', 'updatedAt', 'permissions'] as const;
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ApiKeyRepository {
|
export class ApiKeyRepository {
|
||||||
constructor(@InjectKysely() private db: Kysely<DB>) {}
|
constructor(@InjectKysely() private db: Kysely<DB>) {}
|
||||||
@@ -33,29 +33,15 @@ export class ApiKeyRepository {
|
|||||||
getKey(hashedToken: string) {
|
getKey(hashedToken: string) {
|
||||||
return this.db
|
return this.db
|
||||||
.selectFrom('api_keys')
|
.selectFrom('api_keys')
|
||||||
.innerJoinLateral(
|
.select((eb) => [
|
||||||
(eb) =>
|
...columns.authApiKey,
|
||||||
|
jsonObjectFrom(
|
||||||
eb
|
eb
|
||||||
.selectFrom('users')
|
.selectFrom('users')
|
||||||
.selectAll('users')
|
.select(columns.authUser)
|
||||||
.select((eb) =>
|
|
||||||
eb
|
|
||||||
.selectFrom('user_metadata')
|
|
||||||
.whereRef('users.id', '=', 'user_metadata.userId')
|
|
||||||
.select((eb) => eb.fn('array_agg', [eb.table('user_metadata')]).as('metadata'))
|
|
||||||
.as('metadata'),
|
|
||||||
)
|
|
||||||
.whereRef('users.id', '=', 'api_keys.userId')
|
.whereRef('users.id', '=', 'api_keys.userId')
|
||||||
.where('users.deletedAt', 'is', null)
|
.where('users.deletedAt', 'is', null),
|
||||||
.as('user'),
|
).as('user'),
|
||||||
(join) => join.onTrue(),
|
|
||||||
)
|
|
||||||
.select((eb) => [
|
|
||||||
'api_keys.id',
|
|
||||||
'api_keys.key',
|
|
||||||
'api_keys.userId',
|
|
||||||
'api_keys.permissions',
|
|
||||||
eb.fn.toJson('user').as('user'),
|
|
||||||
])
|
])
|
||||||
.where('api_keys.key', '=', hashedToken)
|
.where('api_keys.key', '=', hashedToken)
|
||||||
.executeTakeFirst();
|
.executeTakeFirst();
|
||||||
@@ -65,7 +51,7 @@ export class ApiKeyRepository {
|
|||||||
getById(userId: string, id: string) {
|
getById(userId: string, id: string) {
|
||||||
return this.db
|
return this.db
|
||||||
.selectFrom('api_keys')
|
.selectFrom('api_keys')
|
||||||
.select(columns)
|
.select(columns.apiKey)
|
||||||
.where('id', '=', asUuid(id))
|
.where('id', '=', asUuid(id))
|
||||||
.where('userId', '=', userId)
|
.where('userId', '=', userId)
|
||||||
.executeTakeFirst();
|
.executeTakeFirst();
|
||||||
@@ -75,7 +61,7 @@ export class ApiKeyRepository {
|
|||||||
getByUserId(userId: string) {
|
getByUserId(userId: string) {
|
||||||
return this.db
|
return this.db
|
||||||
.selectFrom('api_keys')
|
.selectFrom('api_keys')
|
||||||
.select(columns)
|
.select(columns.apiKey)
|
||||||
.where('userId', '=', userId)
|
.where('userId', '=', userId)
|
||||||
.orderBy('createdAt', 'desc')
|
.orderBy('createdAt', 'desc')
|
||||||
.execute();
|
.execute();
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { AssetFiles, AssetJobStatus, Assets, DB, Exif } from 'src/db';
|
|||||||
import { Chunked, ChunkedArray, DummyValue, GenerateSql } from 'src/decorators';
|
import { Chunked, ChunkedArray, DummyValue, GenerateSql } from 'src/decorators';
|
||||||
import {
|
import {
|
||||||
AssetEntity,
|
AssetEntity,
|
||||||
|
AssetEntityPlaceholder,
|
||||||
hasPeople,
|
hasPeople,
|
||||||
searchAssetBuilder,
|
searchAssetBuilder,
|
||||||
truncatedDate,
|
truncatedDate,
|
||||||
@@ -21,34 +22,138 @@ import {
|
|||||||
withTagId,
|
withTagId,
|
||||||
withTags,
|
withTags,
|
||||||
} from 'src/entities/asset.entity';
|
} from 'src/entities/asset.entity';
|
||||||
import { AssetFileType, AssetStatus, AssetType } from 'src/enum';
|
import { AssetFileType, AssetOrder, AssetStatus, AssetType } from 'src/enum';
|
||||||
import {
|
|
||||||
AssetDeltaSyncOptions,
|
|
||||||
AssetExploreFieldOptions,
|
|
||||||
AssetFullSyncOptions,
|
|
||||||
AssetGetByChecksumOptions,
|
|
||||||
AssetStats,
|
|
||||||
AssetStatsOptions,
|
|
||||||
AssetUpdateDuplicateOptions,
|
|
||||||
DayOfYearAssets,
|
|
||||||
DuplicateGroup,
|
|
||||||
GetByIdsRelations,
|
|
||||||
IAssetRepository,
|
|
||||||
LivePhotoSearchOptions,
|
|
||||||
MonthDay,
|
|
||||||
TimeBucketItem,
|
|
||||||
TimeBucketOptions,
|
|
||||||
TimeBucketSize,
|
|
||||||
WithProperty,
|
|
||||||
WithoutProperty,
|
|
||||||
} from 'src/interfaces/asset.interface';
|
|
||||||
import { AssetSearchOptions, SearchExploreItem, SearchExploreItemSet } from 'src/interfaces/search.interface';
|
|
||||||
import { MapMarker, MapMarkerSearchOptions } from 'src/repositories/map.repository';
|
import { MapMarker, MapMarkerSearchOptions } from 'src/repositories/map.repository';
|
||||||
|
import { AssetSearchOptions, SearchExploreItem, SearchExploreItemSet } from 'src/repositories/search.repository';
|
||||||
import { anyUuid, asUuid, mapUpsertColumns } from 'src/utils/database';
|
import { anyUuid, asUuid, mapUpsertColumns } from 'src/utils/database';
|
||||||
import { Paginated, PaginationOptions, paginationHelper } from 'src/utils/pagination';
|
import { Paginated, PaginationOptions, paginationHelper } from 'src/utils/pagination';
|
||||||
|
|
||||||
|
export type AssetStats = Record<AssetType, number>;
|
||||||
|
|
||||||
|
export interface AssetStatsOptions {
|
||||||
|
isFavorite?: boolean;
|
||||||
|
isArchived?: boolean;
|
||||||
|
isTrashed?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface LivePhotoSearchOptions {
|
||||||
|
ownerId: string;
|
||||||
|
libraryId?: string | null;
|
||||||
|
livePhotoCID: string;
|
||||||
|
otherAssetId: string;
|
||||||
|
type: AssetType;
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum WithoutProperty {
|
||||||
|
THUMBNAIL = 'thumbnail',
|
||||||
|
ENCODED_VIDEO = 'encoded-video',
|
||||||
|
EXIF = 'exif',
|
||||||
|
SMART_SEARCH = 'smart-search',
|
||||||
|
DUPLICATE = 'duplicate',
|
||||||
|
FACES = 'faces',
|
||||||
|
SIDECAR = 'sidecar',
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum WithProperty {
|
||||||
|
SIDECAR = 'sidecar',
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum TimeBucketSize {
|
||||||
|
DAY = 'DAY',
|
||||||
|
MONTH = 'MONTH',
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AssetBuilderOptions {
|
||||||
|
isArchived?: boolean;
|
||||||
|
isFavorite?: boolean;
|
||||||
|
isTrashed?: boolean;
|
||||||
|
isDuplicate?: boolean;
|
||||||
|
albumId?: string;
|
||||||
|
tagId?: string;
|
||||||
|
personId?: string;
|
||||||
|
userIds?: string[];
|
||||||
|
withStacked?: boolean;
|
||||||
|
exifInfo?: boolean;
|
||||||
|
status?: AssetStatus;
|
||||||
|
assetType?: AssetType;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TimeBucketOptions extends AssetBuilderOptions {
|
||||||
|
size: TimeBucketSize;
|
||||||
|
order?: AssetOrder;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TimeBucketItem {
|
||||||
|
timeBucket: string;
|
||||||
|
count: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MonthDay {
|
||||||
|
day: number;
|
||||||
|
month: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AssetExploreFieldOptions {
|
||||||
|
maxFields: number;
|
||||||
|
minAssetsPerField: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AssetFullSyncOptions {
|
||||||
|
ownerId: string;
|
||||||
|
lastId?: string;
|
||||||
|
updatedUntil: Date;
|
||||||
|
limit: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AssetDeltaSyncOptions {
|
||||||
|
userIds: string[];
|
||||||
|
updatedAfter: Date;
|
||||||
|
limit: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AssetUpdateDuplicateOptions {
|
||||||
|
targetDuplicateId: string | null;
|
||||||
|
assetIds: string[];
|
||||||
|
duplicateIds: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UpsertFileOptions {
|
||||||
|
assetId: string;
|
||||||
|
type: AssetFileType;
|
||||||
|
path: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AssetGetByChecksumOptions {
|
||||||
|
ownerId: string;
|
||||||
|
checksum: Buffer;
|
||||||
|
libraryId?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type AssetPathEntity = Pick<AssetEntity, 'id' | 'originalPath' | 'isOffline'>;
|
||||||
|
|
||||||
|
export interface GetByIdsRelations {
|
||||||
|
exifInfo?: boolean;
|
||||||
|
faces?: { person?: boolean };
|
||||||
|
files?: boolean;
|
||||||
|
library?: boolean;
|
||||||
|
owner?: boolean;
|
||||||
|
smartSearch?: boolean;
|
||||||
|
stack?: { assets?: boolean };
|
||||||
|
tags?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DuplicateGroup {
|
||||||
|
duplicateId: string;
|
||||||
|
assets: AssetEntity[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DayOfYearAssets {
|
||||||
|
yearsAgo: number;
|
||||||
|
assets: AssetEntity[];
|
||||||
|
}
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AssetRepository implements IAssetRepository {
|
export class AssetRepository {
|
||||||
constructor(@InjectKysely() private db: Kysely<DB>) {}
|
constructor(@InjectKysely() private db: Kysely<DB>) {}
|
||||||
|
|
||||||
async upsertExif(exif: Insertable<Exif>): Promise<void> {
|
async upsertExif(exif: Insertable<Exif>): Promise<void> {
|
||||||
@@ -79,8 +184,12 @@ export class AssetRepository implements IAssetRepository {
|
|||||||
.execute();
|
.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
create(asset: Insertable<Assets>): Promise<AssetEntity> {
|
create(asset: Insertable<Assets>): Promise<AssetEntityPlaceholder> {
|
||||||
return this.db.insertInto('assets').values(asset).returningAll().executeTakeFirst() as any as Promise<AssetEntity>;
|
return this.db
|
||||||
|
.insertInto('assets')
|
||||||
|
.values(asset)
|
||||||
|
.returningAll()
|
||||||
|
.executeTakeFirst() as any as Promise<AssetEntityPlaceholder>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@GenerateSql({ params: [DummyValue.UUID, { day: 1, month: 1 }] })
|
@GenerateSql({ params: [DummyValue.UUID, { day: 1, month: 1 }] })
|
||||||
@@ -291,6 +400,9 @@ export class AssetRepository implements IAssetRepository {
|
|||||||
.where('ownerId', '=', asUuid(ownerId))
|
.where('ownerId', '=', asUuid(ownerId))
|
||||||
.where('deviceId', '=', deviceId)
|
.where('deviceId', '=', deviceId)
|
||||||
.where('isVisible', '=', true)
|
.where('isVisible', '=', true)
|
||||||
|
.where('assets.fileCreatedAt', 'is not', null)
|
||||||
|
.where('assets.fileModifiedAt', 'is not', null)
|
||||||
|
.where('assets.localDateTime', 'is not', null)
|
||||||
.where('deletedAt', 'is', null)
|
.where('deletedAt', 'is', null)
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
@@ -458,7 +570,10 @@ export class AssetRepository implements IAssetRepository {
|
|||||||
.where('job_status.duplicatesDetectedAt', 'is', null)
|
.where('job_status.duplicatesDetectedAt', 'is', null)
|
||||||
.where('job_status.previewAt', 'is not', null)
|
.where('job_status.previewAt', 'is not', null)
|
||||||
.where((eb) => eb.exists(eb.selectFrom('smart_search').where('assetId', '=', eb.ref('assets.id'))))
|
.where((eb) => eb.exists(eb.selectFrom('smart_search').where('assetId', '=', eb.ref('assets.id'))))
|
||||||
.where('assets.isVisible', '=', true),
|
.where('assets.isVisible', '=', true)
|
||||||
|
.where('assets.fileCreatedAt', 'is not', null)
|
||||||
|
.where('assets.fileModifiedAt', 'is not', null)
|
||||||
|
.where('assets.localDateTime', 'is not', null),
|
||||||
)
|
)
|
||||||
.$if(property === WithoutProperty.ENCODED_VIDEO, (qb) =>
|
.$if(property === WithoutProperty.ENCODED_VIDEO, (qb) =>
|
||||||
qb
|
qb
|
||||||
@@ -524,7 +639,7 @@ export class AssetRepository implements IAssetRepository {
|
|||||||
.executeTakeFirst() as Promise<AssetEntity | undefined>;
|
.executeTakeFirst() as Promise<AssetEntity | undefined>;
|
||||||
}
|
}
|
||||||
|
|
||||||
getMapMarkers(ownerIds: string[], options: MapMarkerSearchOptions = {}): Promise<MapMarker[]> {
|
private getMapMarkers(ownerIds: string[], options: MapMarkerSearchOptions = {}): Promise<MapMarker[]> {
|
||||||
const { isArchived, isFavorite, fileCreatedAfter, fileCreatedBefore } = options;
|
const { isArchived, isFavorite, fileCreatedAfter, fileCreatedBefore } = options;
|
||||||
|
|
||||||
return this.db
|
return this.db
|
||||||
@@ -552,6 +667,9 @@ export class AssetRepository implements IAssetRepository {
|
|||||||
.select((eb) => eb.fn.countAll().filterWhere('type', '=', AssetType.VIDEO).as(AssetType.VIDEO))
|
.select((eb) => eb.fn.countAll().filterWhere('type', '=', AssetType.VIDEO).as(AssetType.VIDEO))
|
||||||
.select((eb) => eb.fn.countAll().filterWhere('type', '=', AssetType.OTHER).as(AssetType.OTHER))
|
.select((eb) => eb.fn.countAll().filterWhere('type', '=', AssetType.OTHER).as(AssetType.OTHER))
|
||||||
.where('ownerId', '=', asUuid(ownerId))
|
.where('ownerId', '=', asUuid(ownerId))
|
||||||
|
.where('assets.fileCreatedAt', 'is not', null)
|
||||||
|
.where('assets.fileModifiedAt', 'is not', null)
|
||||||
|
.where('assets.localDateTime', 'is not', null)
|
||||||
.where('isVisible', '=', true)
|
.where('isVisible', '=', true)
|
||||||
.$if(isArchived !== undefined, (qb) => qb.where('isArchived', '=', isArchived!))
|
.$if(isArchived !== undefined, (qb) => qb.where('isArchived', '=', isArchived!))
|
||||||
.$if(isFavorite !== undefined, (qb) => qb.where('isFavorite', '=', isFavorite!))
|
.$if(isFavorite !== undefined, (qb) => qb.where('isFavorite', '=', isFavorite!))
|
||||||
@@ -584,6 +702,9 @@ export class AssetRepository implements IAssetRepository {
|
|||||||
.$if(!!options.isTrashed, (qb) => qb.where('assets.status', '!=', AssetStatus.DELETED))
|
.$if(!!options.isTrashed, (qb) => qb.where('assets.status', '!=', AssetStatus.DELETED))
|
||||||
.where('assets.deletedAt', options.isTrashed ? 'is not' : 'is', null)
|
.where('assets.deletedAt', options.isTrashed ? 'is not' : 'is', null)
|
||||||
.where('assets.isVisible', '=', true)
|
.where('assets.isVisible', '=', true)
|
||||||
|
.where('assets.fileCreatedAt', 'is not', null)
|
||||||
|
.where('assets.fileModifiedAt', 'is not', null)
|
||||||
|
.where('assets.localDateTime', 'is not', null)
|
||||||
.$if(!!options.albumId, (qb) =>
|
.$if(!!options.albumId, (qb) =>
|
||||||
qb
|
qb
|
||||||
.innerJoin('albums_assets_assets', 'assets.id', 'albums_assets_assets.assetsId')
|
.innerJoin('albums_assets_assets', 'assets.id', 'albums_assets_assets.assetsId')
|
||||||
|
|||||||
@@ -13,9 +13,16 @@ import { Notice } from 'postgres';
|
|||||||
import { citiesFile, excludePaths, IWorker } from 'src/constants';
|
import { citiesFile, excludePaths, IWorker } from 'src/constants';
|
||||||
import { Telemetry } from 'src/decorators';
|
import { Telemetry } from 'src/decorators';
|
||||||
import { EnvDto } from 'src/dtos/env.dto';
|
import { EnvDto } from 'src/dtos/env.dto';
|
||||||
import { ImmichEnvironment, ImmichHeader, ImmichTelemetry, ImmichWorker, LogLevel } from 'src/enum';
|
import {
|
||||||
import { DatabaseConnectionParams, DatabaseExtension, VectorExtension } from 'src/interfaces/database.interface';
|
DatabaseExtension,
|
||||||
import { QueueName } from 'src/interfaces/job.interface';
|
ImmichEnvironment,
|
||||||
|
ImmichHeader,
|
||||||
|
ImmichTelemetry,
|
||||||
|
ImmichWorker,
|
||||||
|
LogLevel,
|
||||||
|
QueueName,
|
||||||
|
} from 'src/enum';
|
||||||
|
import { DatabaseConnectionParams, VectorExtension } from 'src/types';
|
||||||
import { setDifference } from 'src/utils/set';
|
import { setDifference } from 'src/utils/set';
|
||||||
import { PostgresConnectionOptions } from 'typeorm/driver/postgres/PostgresConnectionOptions.js';
|
import { PostgresConnectionOptions } from 'typeorm/driver/postgres/PostgresConnectionOptions.js';
|
||||||
|
|
||||||
|
|||||||
@@ -2,11 +2,10 @@ import { Injectable } from '@nestjs/common';
|
|||||||
import { compareSync, hash } from 'bcrypt';
|
import { compareSync, hash } from 'bcrypt';
|
||||||
import { createHash, createPublicKey, createVerify, randomBytes, randomUUID } from 'node:crypto';
|
import { createHash, createPublicKey, createVerify, randomBytes, randomUUID } from 'node:crypto';
|
||||||
import { createReadStream } from 'node:fs';
|
import { createReadStream } from 'node:fs';
|
||||||
import { ICryptoRepository } from 'src/interfaces/crypto.interface';
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CryptoRepository implements ICryptoRepository {
|
export class CryptoRepository {
|
||||||
randomUUID() {
|
randomUUID(): string {
|
||||||
return randomUUID();
|
return randomUUID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,26 +4,18 @@ import AsyncLock from 'async-lock';
|
|||||||
import { Kysely, sql } from 'kysely';
|
import { Kysely, sql } from 'kysely';
|
||||||
import { InjectKysely } from 'nestjs-kysely';
|
import { InjectKysely } from 'nestjs-kysely';
|
||||||
import semver from 'semver';
|
import semver from 'semver';
|
||||||
import { POSTGRES_VERSION_RANGE, VECTOR_VERSION_RANGE, VECTORS_VERSION_RANGE } from 'src/constants';
|
import { EXTENSION_NAMES, POSTGRES_VERSION_RANGE, VECTOR_VERSION_RANGE, VECTORS_VERSION_RANGE } from 'src/constants';
|
||||||
import { DB } from 'src/db';
|
import { DB } from 'src/db';
|
||||||
import {
|
import { DatabaseExtension, DatabaseLock, VectorIndex } from 'src/enum';
|
||||||
DatabaseExtension,
|
|
||||||
DatabaseLock,
|
|
||||||
EXTENSION_NAMES,
|
|
||||||
ExtensionVersion,
|
|
||||||
IDatabaseRepository,
|
|
||||||
VectorExtension,
|
|
||||||
VectorIndex,
|
|
||||||
VectorUpdateResult,
|
|
||||||
} from 'src/interfaces/database.interface';
|
|
||||||
import { ConfigRepository } from 'src/repositories/config.repository';
|
import { ConfigRepository } from 'src/repositories/config.repository';
|
||||||
import { LoggingRepository } from 'src/repositories/logging.repository';
|
import { LoggingRepository } from 'src/repositories/logging.repository';
|
||||||
|
import { ExtensionVersion, VectorExtension, VectorUpdateResult } from 'src/types';
|
||||||
import { UPSERT_COLUMNS } from 'src/utils/database';
|
import { UPSERT_COLUMNS } from 'src/utils/database';
|
||||||
import { isValidInteger } from 'src/validation';
|
import { isValidInteger } from 'src/validation';
|
||||||
import { DataSource, EntityManager, EntityMetadata, QueryRunner } from 'typeorm';
|
import { DataSource, EntityManager, EntityMetadata, QueryRunner } from 'typeorm';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class DatabaseRepository implements IDatabaseRepository {
|
export class DatabaseRepository {
|
||||||
private vectorExtension: VectorExtension;
|
private vectorExtension: VectorExtension;
|
||||||
private readonly asyncLock = new AsyncLock();
|
private readonly asyncLock = new AsyncLock();
|
||||||
|
|
||||||
|
|||||||
@@ -10,21 +10,15 @@ import {
|
|||||||
import { ClassConstructor } from 'class-transformer';
|
import { ClassConstructor } from 'class-transformer';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import { Server, Socket } from 'socket.io';
|
import { Server, Socket } from 'socket.io';
|
||||||
|
import { SystemConfig } from 'src/config';
|
||||||
import { EventConfig } from 'src/decorators';
|
import { EventConfig } from 'src/decorators';
|
||||||
import { ImmichWorker, MetadataKey } from 'src/enum';
|
import { AssetResponseDto } from 'src/dtos/asset-response.dto';
|
||||||
import {
|
import { AuthDto } from 'src/dtos/auth.dto';
|
||||||
ArgsOf,
|
import { ReleaseNotification, ServerVersionResponseDto } from 'src/dtos/server.dto';
|
||||||
ClientEventMap,
|
import { ImmichWorker, MetadataKey, QueueName } from 'src/enum';
|
||||||
EmitEvent,
|
|
||||||
EmitHandler,
|
|
||||||
EventItem,
|
|
||||||
IEventRepository,
|
|
||||||
serverEvents,
|
|
||||||
ServerEvents,
|
|
||||||
} from 'src/interfaces/event.interface';
|
|
||||||
import { ConfigRepository } from 'src/repositories/config.repository';
|
import { ConfigRepository } from 'src/repositories/config.repository';
|
||||||
import { LoggingRepository } from 'src/repositories/logging.repository';
|
import { LoggingRepository } from 'src/repositories/logging.repository';
|
||||||
import { AuthService } from 'src/services/auth.service';
|
import { JobItem } from 'src/types';
|
||||||
import { handlePromiseError } from 'src/utils/misc';
|
import { handlePromiseError } from 'src/utils/misc';
|
||||||
|
|
||||||
type EmitHandlers = Partial<{ [T in EmitEvent]: Array<EventItem<T>> }>;
|
type EmitHandlers = Partial<{ [T in EmitEvent]: Array<EventItem<T>> }>;
|
||||||
@@ -37,14 +31,99 @@ type Item<T extends EmitEvent> = {
|
|||||||
label: string;
|
label: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type EventMap = {
|
||||||
|
// app events
|
||||||
|
'app.bootstrap': [];
|
||||||
|
'app.shutdown': [];
|
||||||
|
|
||||||
|
'config.init': [{ newConfig: SystemConfig }];
|
||||||
|
// config events
|
||||||
|
'config.update': [
|
||||||
|
{
|
||||||
|
newConfig: SystemConfig;
|
||||||
|
oldConfig: SystemConfig;
|
||||||
|
},
|
||||||
|
];
|
||||||
|
'config.validate': [{ newConfig: SystemConfig; oldConfig: SystemConfig }];
|
||||||
|
|
||||||
|
// album events
|
||||||
|
'album.update': [{ id: string; recipientIds: string[] }];
|
||||||
|
'album.invite': [{ id: string; userId: string }];
|
||||||
|
|
||||||
|
// asset events
|
||||||
|
'asset.tag': [{ assetId: string }];
|
||||||
|
'asset.untag': [{ assetId: string }];
|
||||||
|
'asset.hide': [{ assetId: string; userId: string }];
|
||||||
|
'asset.show': [{ assetId: string; userId: string }];
|
||||||
|
'asset.trash': [{ assetId: string; userId: string }];
|
||||||
|
'asset.delete': [{ assetId: string; userId: string }];
|
||||||
|
|
||||||
|
// asset bulk events
|
||||||
|
'assets.trash': [{ assetIds: string[]; userId: string }];
|
||||||
|
'assets.delete': [{ assetIds: string[]; userId: string }];
|
||||||
|
'assets.restore': [{ assetIds: string[]; userId: string }];
|
||||||
|
|
||||||
|
'job.start': [QueueName, JobItem];
|
||||||
|
|
||||||
|
// session events
|
||||||
|
'session.delete': [{ sessionId: string }];
|
||||||
|
|
||||||
|
// stack events
|
||||||
|
'stack.create': [{ stackId: string; userId: string }];
|
||||||
|
'stack.update': [{ stackId: string; userId: string }];
|
||||||
|
'stack.delete': [{ stackId: string; userId: string }];
|
||||||
|
|
||||||
|
// stack bulk events
|
||||||
|
'stacks.delete': [{ stackIds: string[]; userId: string }];
|
||||||
|
|
||||||
|
// user events
|
||||||
|
'user.signup': [{ notify: boolean; id: string; tempPassword?: string }];
|
||||||
|
|
||||||
|
// websocket events
|
||||||
|
'websocket.connect': [{ userId: string }];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const serverEvents = ['config.update'] as const;
|
||||||
|
export type ServerEvents = (typeof serverEvents)[number];
|
||||||
|
|
||||||
|
export type EmitEvent = keyof EventMap;
|
||||||
|
export type EmitHandler<T extends EmitEvent> = (...args: ArgsOf<T>) => Promise<void> | void;
|
||||||
|
export type ArgOf<T extends EmitEvent> = EventMap[T][0];
|
||||||
|
export type ArgsOf<T extends EmitEvent> = EventMap[T];
|
||||||
|
|
||||||
|
export interface ClientEventMap {
|
||||||
|
on_upload_success: [AssetResponseDto];
|
||||||
|
on_user_delete: [string];
|
||||||
|
on_asset_delete: [string];
|
||||||
|
on_asset_trash: [string[]];
|
||||||
|
on_asset_update: [AssetResponseDto];
|
||||||
|
on_asset_hidden: [string];
|
||||||
|
on_asset_restore: [string[]];
|
||||||
|
on_asset_stack_update: string[];
|
||||||
|
on_person_thumbnail: [string];
|
||||||
|
on_server_version: [ServerVersionResponseDto];
|
||||||
|
on_config_update: [];
|
||||||
|
on_new_release: [ReleaseNotification];
|
||||||
|
on_session_delete: [string];
|
||||||
|
}
|
||||||
|
|
||||||
|
export type EventItem<T extends EmitEvent> = {
|
||||||
|
event: T;
|
||||||
|
handler: EmitHandler<T>;
|
||||||
|
server: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type AuthFn = (client: Socket) => Promise<AuthDto>;
|
||||||
|
|
||||||
@WebSocketGateway({
|
@WebSocketGateway({
|
||||||
cors: true,
|
cors: true,
|
||||||
path: '/api/socket.io',
|
path: '/api/socket.io',
|
||||||
transports: ['websocket'],
|
transports: ['websocket'],
|
||||||
})
|
})
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class EventRepository implements OnGatewayConnection, OnGatewayDisconnect, OnGatewayInit, IEventRepository {
|
export class EventRepository implements OnGatewayConnection, OnGatewayDisconnect, OnGatewayInit {
|
||||||
private emitHandlers: EmitHandlers = {};
|
private emitHandlers: EmitHandlers = {};
|
||||||
|
private authFn?: AuthFn;
|
||||||
|
|
||||||
@WebSocketServer()
|
@WebSocketServer()
|
||||||
private server?: Server;
|
private server?: Server;
|
||||||
@@ -122,11 +201,7 @@ export class EventRepository implements OnGatewayConnection, OnGatewayDisconnect
|
|||||||
async handleConnection(client: Socket) {
|
async handleConnection(client: Socket) {
|
||||||
try {
|
try {
|
||||||
this.logger.log(`Websocket Connect: ${client.id}`);
|
this.logger.log(`Websocket Connect: ${client.id}`);
|
||||||
const auth = await this.moduleRef.get(AuthService).authenticate({
|
const auth = await this.authenticate(client);
|
||||||
headers: client.request.headers,
|
|
||||||
queryParams: {},
|
|
||||||
metadata: { adminRoute: false, sharedLinkRoute: false, uri: '/api/socket.io' },
|
|
||||||
});
|
|
||||||
await client.join(auth.user.id);
|
await client.join(auth.user.id);
|
||||||
if (auth.session) {
|
if (auth.session) {
|
||||||
await client.join(auth.session.id);
|
await client.join(auth.session.id);
|
||||||
@@ -182,4 +257,16 @@ export class EventRepository implements OnGatewayConnection, OnGatewayDisconnect
|
|||||||
this.logger.debug(`Server event: ${event} (send)`);
|
this.logger.debug(`Server event: ${event} (send)`);
|
||||||
this.server?.serverSideEmit(event, ...args);
|
this.server?.serverSideEmit(event, ...args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setAuthFn(fn: (client: Socket) => Promise<AuthDto>) {
|
||||||
|
this.authFn = fn;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async authenticate(client: Socket) {
|
||||||
|
if (!this.authFn) {
|
||||||
|
throw new Error('Auth function not set');
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.authFn(client);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,3 @@
|
|||||||
import { IAlbumRepository } from 'src/interfaces/album.interface';
|
|
||||||
import { IAssetRepository } from 'src/interfaces/asset.interface';
|
|
||||||
import { ICryptoRepository } from 'src/interfaces/crypto.interface';
|
|
||||||
import { IDatabaseRepository } from 'src/interfaces/database.interface';
|
|
||||||
import { IEventRepository } from 'src/interfaces/event.interface';
|
|
||||||
import { IJobRepository } from 'src/interfaces/job.interface';
|
|
||||||
import { ILibraryRepository } from 'src/interfaces/library.interface';
|
|
||||||
import { IMachineLearningRepository } from 'src/interfaces/machine-learning.interface';
|
|
||||||
import { IMoveRepository } from 'src/interfaces/move.interface';
|
|
||||||
import { IPartnerRepository } from 'src/interfaces/partner.interface';
|
|
||||||
import { IPersonRepository } from 'src/interfaces/person.interface';
|
|
||||||
import { ISearchRepository } from 'src/interfaces/search.interface';
|
|
||||||
import { ISharedLinkRepository } from 'src/interfaces/shared-link.interface';
|
|
||||||
import { IStackRepository } from 'src/interfaces/stack.interface';
|
|
||||||
import { IStorageRepository } from 'src/interfaces/storage.interface';
|
|
||||||
import { ITagRepository } from 'src/interfaces/tag.interface';
|
|
||||||
import { IUserRepository } from 'src/interfaces/user.interface';
|
|
||||||
import { AccessRepository } from 'src/repositories/access.repository';
|
import { AccessRepository } from 'src/repositories/access.repository';
|
||||||
import { ActivityRepository } from 'src/repositories/activity.repository';
|
import { ActivityRepository } from 'src/repositories/activity.repository';
|
||||||
import { AlbumUserRepository } from 'src/repositories/album-user.repository';
|
import { AlbumUserRepository } from 'src/repositories/album-user.repository';
|
||||||
@@ -58,44 +41,41 @@ import { ViewRepository } from 'src/repositories/view-repository';
|
|||||||
export const repositories = [
|
export const repositories = [
|
||||||
AccessRepository,
|
AccessRepository,
|
||||||
ActivityRepository,
|
ActivityRepository,
|
||||||
|
AlbumRepository,
|
||||||
AlbumUserRepository,
|
AlbumUserRepository,
|
||||||
AuditRepository,
|
AuditRepository,
|
||||||
ApiKeyRepository,
|
ApiKeyRepository,
|
||||||
|
AssetRepository,
|
||||||
ConfigRepository,
|
ConfigRepository,
|
||||||
CronRepository,
|
CronRepository,
|
||||||
|
CryptoRepository,
|
||||||
|
DatabaseRepository,
|
||||||
|
EventRepository,
|
||||||
|
JobRepository,
|
||||||
|
LibraryRepository,
|
||||||
LoggingRepository,
|
LoggingRepository,
|
||||||
|
MachineLearningRepository,
|
||||||
MapRepository,
|
MapRepository,
|
||||||
MediaRepository,
|
MediaRepository,
|
||||||
MemoryRepository,
|
MemoryRepository,
|
||||||
MetadataRepository,
|
MetadataRepository,
|
||||||
|
MoveRepository,
|
||||||
NotificationRepository,
|
NotificationRepository,
|
||||||
OAuthRepository,
|
OAuthRepository,
|
||||||
|
PartnerRepository,
|
||||||
|
PersonRepository,
|
||||||
ProcessRepository,
|
ProcessRepository,
|
||||||
|
SearchRepository,
|
||||||
SessionRepository,
|
SessionRepository,
|
||||||
ServerInfoRepository,
|
ServerInfoRepository,
|
||||||
|
SharedLinkRepository,
|
||||||
|
StackRepository,
|
||||||
|
StorageRepository,
|
||||||
SystemMetadataRepository,
|
SystemMetadataRepository,
|
||||||
|
TagRepository,
|
||||||
TelemetryRepository,
|
TelemetryRepository,
|
||||||
TrashRepository,
|
TrashRepository,
|
||||||
|
UserRepository,
|
||||||
ViewRepository,
|
ViewRepository,
|
||||||
VersionHistoryRepository,
|
VersionHistoryRepository,
|
||||||
];
|
];
|
||||||
|
|
||||||
export const providers = [
|
|
||||||
{ provide: IAlbumRepository, useClass: AlbumRepository },
|
|
||||||
{ provide: IAssetRepository, useClass: AssetRepository },
|
|
||||||
{ provide: ICryptoRepository, useClass: CryptoRepository },
|
|
||||||
{ provide: IDatabaseRepository, useClass: DatabaseRepository },
|
|
||||||
{ provide: IEventRepository, useClass: EventRepository },
|
|
||||||
{ provide: IJobRepository, useClass: JobRepository },
|
|
||||||
{ provide: ILibraryRepository, useClass: LibraryRepository },
|
|
||||||
{ provide: IMachineLearningRepository, useClass: MachineLearningRepository },
|
|
||||||
{ provide: IMoveRepository, useClass: MoveRepository },
|
|
||||||
{ provide: IPartnerRepository, useClass: PartnerRepository },
|
|
||||||
{ provide: IPersonRepository, useClass: PersonRepository },
|
|
||||||
{ provide: ISearchRepository, useClass: SearchRepository },
|
|
||||||
{ provide: ISharedLinkRepository, useClass: SharedLinkRepository },
|
|
||||||
{ provide: IStackRepository, useClass: StackRepository },
|
|
||||||
{ provide: IStorageRepository, useClass: StorageRepository },
|
|
||||||
{ provide: ITagRepository, useClass: TagRepository },
|
|
||||||
{ provide: IUserRepository, useClass: UserRepository },
|
|
||||||
];
|
|
||||||
|
|||||||
@@ -1,26 +1,15 @@
|
|||||||
import { getQueueToken } from '@nestjs/bullmq';
|
import { getQueueToken } from '@nestjs/bullmq';
|
||||||
import { Inject, Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { ModuleRef, Reflector } from '@nestjs/core';
|
import { ModuleRef, Reflector } from '@nestjs/core';
|
||||||
import { JobsOptions, Queue, Worker } from 'bullmq';
|
import { JobsOptions, Queue, Worker } from 'bullmq';
|
||||||
import { ClassConstructor } from 'class-transformer';
|
import { ClassConstructor } from 'class-transformer';
|
||||||
import { setTimeout } from 'node:timers/promises';
|
import { setTimeout } from 'node:timers/promises';
|
||||||
import { JobConfig } from 'src/decorators';
|
import { JobConfig } from 'src/decorators';
|
||||||
import { MetadataKey } from 'src/enum';
|
import { JobName, JobStatus, MetadataKey, QueueCleanType, QueueName } from 'src/enum';
|
||||||
import { IEventRepository } from 'src/interfaces/event.interface';
|
|
||||||
import {
|
|
||||||
IEntityJob,
|
|
||||||
IJobRepository,
|
|
||||||
JobCounts,
|
|
||||||
JobItem,
|
|
||||||
JobName,
|
|
||||||
JobOf,
|
|
||||||
JobStatus,
|
|
||||||
QueueCleanType,
|
|
||||||
QueueName,
|
|
||||||
QueueStatus,
|
|
||||||
} from 'src/interfaces/job.interface';
|
|
||||||
import { ConfigRepository } from 'src/repositories/config.repository';
|
import { ConfigRepository } from 'src/repositories/config.repository';
|
||||||
|
import { EventRepository } from 'src/repositories/event.repository';
|
||||||
import { LoggingRepository } from 'src/repositories/logging.repository';
|
import { LoggingRepository } from 'src/repositories/logging.repository';
|
||||||
|
import { IEntityJob, JobCounts, JobItem, JobOf, QueueStatus } from 'src/types';
|
||||||
import { getKeyByValue, getMethodNames, ImmichStartupError } from 'src/utils/misc';
|
import { getKeyByValue, getMethodNames, ImmichStartupError } from 'src/utils/misc';
|
||||||
|
|
||||||
type JobMapItem = {
|
type JobMapItem = {
|
||||||
@@ -31,14 +20,14 @@ type JobMapItem = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class JobRepository implements IJobRepository {
|
export class JobRepository {
|
||||||
private workers: Partial<Record<QueueName, Worker>> = {};
|
private workers: Partial<Record<QueueName, Worker>> = {};
|
||||||
private handlers: Partial<Record<JobName, JobMapItem>> = {};
|
private handlers: Partial<Record<JobName, JobMapItem>> = {};
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private moduleRef: ModuleRef,
|
private moduleRef: ModuleRef,
|
||||||
private configRepository: ConfigRepository,
|
private configRepository: ConfigRepository,
|
||||||
@Inject(IEventRepository) private eventRepository: IEventRepository,
|
private eventRepository: EventRepository,
|
||||||
private logger: LoggingRepository,
|
private logger: LoggingRepository,
|
||||||
) {
|
) {
|
||||||
this.logger.setContext(JobRepository.name);
|
this.logger.setContext(JobRepository.name);
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import { DummyValue, GenerateSql } from 'src/decorators';
|
|||||||
import { LibraryStatsResponseDto } from 'src/dtos/library.dto';
|
import { LibraryStatsResponseDto } from 'src/dtos/library.dto';
|
||||||
import { LibraryEntity } from 'src/entities/library.entity';
|
import { LibraryEntity } from 'src/entities/library.entity';
|
||||||
import { AssetType } from 'src/enum';
|
import { AssetType } from 'src/enum';
|
||||||
import { ILibraryRepository } from 'src/interfaces/library.interface';
|
|
||||||
|
|
||||||
const userColumns = [
|
const userColumns = [
|
||||||
'users.id',
|
'users.id',
|
||||||
@@ -34,7 +33,7 @@ const withOwner = (eb: ExpressionBuilder<DB, 'libraries'>) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class LibraryRepository implements ILibraryRepository {
|
export class LibraryRepository {
|
||||||
constructor(@InjectKysely() private db: Kysely<DB>) {}
|
constructor(@InjectKysely() private db: Kysely<DB>) {}
|
||||||
|
|
||||||
@GenerateSql({ params: [DummyValue.UUID] })
|
@GenerateSql({ params: [DummyValue.UUID] })
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
import { ClsService } from 'nestjs-cls';
|
import { ClsService } from 'nestjs-cls';
|
||||||
import { ImmichWorker } from 'src/enum';
|
import { ImmichWorker } from 'src/enum';
|
||||||
|
import { ConfigRepository } from 'src/repositories/config.repository';
|
||||||
import { LoggingRepository } from 'src/repositories/logging.repository';
|
import { LoggingRepository } from 'src/repositories/logging.repository';
|
||||||
import { IConfigRepository } from 'src/types';
|
|
||||||
import { mockEnvData, newConfigRepositoryMock } from 'test/repositories/config.repository.mock';
|
import { mockEnvData, newConfigRepositoryMock } from 'test/repositories/config.repository.mock';
|
||||||
import { Mocked } from 'vitest';
|
import { Mocked } from 'vitest';
|
||||||
|
|
||||||
describe(LoggingRepository.name, () => {
|
describe(LoggingRepository.name, () => {
|
||||||
let sut: LoggingRepository;
|
let sut: LoggingRepository;
|
||||||
|
|
||||||
let configMock: Mocked<IConfigRepository>;
|
let configMock: Mocked<ConfigRepository>;
|
||||||
let clsMock: Mocked<ClsService>;
|
let clsMock: Mocked<ClsService>;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
|||||||
@@ -1,21 +1,60 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { readFile } from 'node:fs/promises';
|
import { readFile } from 'node:fs/promises';
|
||||||
import { CLIPConfig } from 'src/dtos/model-config.dto';
|
import { CLIPConfig } from 'src/dtos/model-config.dto';
|
||||||
import {
|
|
||||||
ClipTextualResponse,
|
|
||||||
ClipVisualResponse,
|
|
||||||
FaceDetectionOptions,
|
|
||||||
FacialRecognitionResponse,
|
|
||||||
IMachineLearningRepository,
|
|
||||||
MachineLearningRequest,
|
|
||||||
ModelPayload,
|
|
||||||
ModelTask,
|
|
||||||
ModelType,
|
|
||||||
} from 'src/interfaces/machine-learning.interface';
|
|
||||||
import { LoggingRepository } from 'src/repositories/logging.repository';
|
import { LoggingRepository } from 'src/repositories/logging.repository';
|
||||||
|
|
||||||
|
export interface BoundingBox {
|
||||||
|
x1: number;
|
||||||
|
y1: number;
|
||||||
|
x2: number;
|
||||||
|
y2: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum ModelTask {
|
||||||
|
FACIAL_RECOGNITION = 'facial-recognition',
|
||||||
|
SEARCH = 'clip',
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum ModelType {
|
||||||
|
DETECTION = 'detection',
|
||||||
|
PIPELINE = 'pipeline',
|
||||||
|
RECOGNITION = 'recognition',
|
||||||
|
TEXTUAL = 'textual',
|
||||||
|
VISUAL = 'visual',
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ModelPayload = { imagePath: string } | { text: string };
|
||||||
|
|
||||||
|
type ModelOptions = { modelName: string };
|
||||||
|
|
||||||
|
export type FaceDetectionOptions = ModelOptions & { minScore: number };
|
||||||
|
|
||||||
|
type VisualResponse = { imageHeight: number; imageWidth: number };
|
||||||
|
export type ClipVisualRequest = { [ModelTask.SEARCH]: { [ModelType.VISUAL]: ModelOptions } };
|
||||||
|
export type ClipVisualResponse = { [ModelTask.SEARCH]: string } & VisualResponse;
|
||||||
|
|
||||||
|
export type ClipTextualRequest = { [ModelTask.SEARCH]: { [ModelType.TEXTUAL]: ModelOptions } };
|
||||||
|
export type ClipTextualResponse = { [ModelTask.SEARCH]: string };
|
||||||
|
|
||||||
|
export type FacialRecognitionRequest = {
|
||||||
|
[ModelTask.FACIAL_RECOGNITION]: {
|
||||||
|
[ModelType.DETECTION]: ModelOptions & { options: { minScore: number } };
|
||||||
|
[ModelType.RECOGNITION]: ModelOptions;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface Face {
|
||||||
|
boundingBox: BoundingBox;
|
||||||
|
embedding: string;
|
||||||
|
score: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type FacialRecognitionResponse = { [ModelTask.FACIAL_RECOGNITION]: Face[] } & VisualResponse;
|
||||||
|
export type DetectedFaces = { faces: Face[] } & VisualResponse;
|
||||||
|
export type MachineLearningRequest = ClipVisualRequest | ClipTextualRequest | FacialRecognitionRequest;
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class MachineLearningRepository implements IMachineLearningRepository {
|
export class MachineLearningRepository {
|
||||||
constructor(private logger: LoggingRepository) {
|
constructor(private logger: LoggingRepository) {
|
||||||
this.logger.setContext(MachineLearningRepository.name);
|
this.logger.setContext(MachineLearningRepository.name);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { jsonArrayFrom } from 'kysely/helpers/postgres';
|
|||||||
import { InjectKysely } from 'nestjs-kysely';
|
import { InjectKysely } from 'nestjs-kysely';
|
||||||
import { DB, Memories } from 'src/db';
|
import { DB, Memories } from 'src/db';
|
||||||
import { Chunked, ChunkedSet, DummyValue, GenerateSql } from 'src/decorators';
|
import { Chunked, ChunkedSet, DummyValue, GenerateSql } from 'src/decorators';
|
||||||
import { IBulkAsset } from 'src/utils/asset.util';
|
import { IBulkAsset } from 'src/types';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class MemoryRepository implements IBulkAsset {
|
export class MemoryRepository implements IBulkAsset {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { BinaryField, DefaultReadTaskOptions, ExifTool, Tags } from 'exiftool-vendored';
|
import { BinaryField, DefaultReadTaskOptions, ExifTool, Tags } from 'exiftool-vendored';
|
||||||
import geotz from 'geo-tz';
|
import geotz from 'geo-tz';
|
||||||
|
import { LogLevel } from 'src/enum';
|
||||||
import { LoggingRepository } from 'src/repositories/logging.repository';
|
import { LoggingRepository } from 'src/repositories/logging.repository';
|
||||||
|
|
||||||
interface ExifDuration {
|
interface ExifDuration {
|
||||||
@@ -101,6 +102,9 @@ export class MetadataRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async writeTags(path: string, tags: Partial<Tags>): Promise<void> {
|
async writeTags(path: string, tags: Partial<Tags>): Promise<void> {
|
||||||
|
if (this.logger.isLevelEnabled(LogLevel.VERBOSE)) {
|
||||||
|
this.logger.verbose(`Writing tags ${JSON.stringify(tags)} to ${path}`);
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
await this.exiftool.write(path, tags);
|
await this.exiftool.write(path, tags);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -5,10 +5,11 @@ import { DB, MoveHistory } from 'src/db';
|
|||||||
import { DummyValue, GenerateSql } from 'src/decorators';
|
import { DummyValue, GenerateSql } from 'src/decorators';
|
||||||
import { MoveEntity } from 'src/entities/move.entity';
|
import { MoveEntity } from 'src/entities/move.entity';
|
||||||
import { PathType } from 'src/enum';
|
import { PathType } from 'src/enum';
|
||||||
import { IMoveRepository } from 'src/interfaces/move.interface';
|
|
||||||
|
export type MoveCreate = Pick<MoveEntity, 'oldPath' | 'newPath' | 'entityId' | 'pathType'> & Partial<MoveEntity>;
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class MoveRepository implements IMoveRepository {
|
export class MoveRepository {
|
||||||
constructor(@InjectKysely() private db: Kysely<DB>) {}
|
constructor(@InjectKysely() private db: Kysely<DB>) {}
|
||||||
|
|
||||||
create(entity: Insertable<MoveHistory>): Promise<MoveEntity> {
|
create(entity: Insertable<MoveHistory>): Promise<MoveEntity> {
|
||||||
|
|||||||
@@ -1,17 +1,16 @@
|
|||||||
import { LoggingRepository } from 'src/repositories/logging.repository';
|
import { LoggingRepository } from 'src/repositories/logging.repository';
|
||||||
import { EmailRenderRequest, EmailTemplate, NotificationRepository } from 'src/repositories/notification.repository';
|
import { EmailRenderRequest, EmailTemplate, NotificationRepository } from 'src/repositories/notification.repository';
|
||||||
import { ILoggingRepository } from 'src/types';
|
import { ILoggingRepository, newLoggingRepositoryMock } from 'test/repositories/logger.repository.mock';
|
||||||
import { newLoggingRepositoryMock } from 'test/repositories/logger.repository.mock';
|
|
||||||
import { Mocked } from 'vitest';
|
import { Mocked } from 'vitest';
|
||||||
|
|
||||||
describe(NotificationRepository.name, () => {
|
describe(NotificationRepository.name, () => {
|
||||||
let sut: NotificationRepository;
|
let sut: NotificationRepository;
|
||||||
let loggerMock: Mocked<ILoggingRepository>;
|
let loggerMock: Mocked<LoggingRepository>;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
loggerMock = newLoggingRepositoryMock();
|
loggerMock = newLoggingRepositoryMock() as ILoggingRepository as Mocked<LoggingRepository>;
|
||||||
|
|
||||||
sut = new NotificationRepository(loggerMock as ILoggingRepository as LoggingRepository);
|
sut = new NotificationRepository(loggerMock as LoggingRepository);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('renderEmail', () => {
|
describe('renderEmail', () => {
|
||||||
|
|||||||
@@ -7,12 +7,7 @@ import { AlbumUpdateEmail } from 'src/emails/album-update.email';
|
|||||||
import { TestEmail } from 'src/emails/test.email';
|
import { TestEmail } from 'src/emails/test.email';
|
||||||
import { WelcomeEmail } from 'src/emails/welcome.email';
|
import { WelcomeEmail } from 'src/emails/welcome.email';
|
||||||
import { LoggingRepository } from 'src/repositories/logging.repository';
|
import { LoggingRepository } from 'src/repositories/logging.repository';
|
||||||
|
import { EmailImageAttachment } from 'src/types';
|
||||||
export type EmailImageAttachment = {
|
|
||||||
filename: string;
|
|
||||||
path: string;
|
|
||||||
cid: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type SendEmailOptions = {
|
export type SendEmailOptions = {
|
||||||
from: string;
|
from: string;
|
||||||
|
|||||||
@@ -5,7 +5,16 @@ import { InjectKysely } from 'nestjs-kysely';
|
|||||||
import { DB, Partners, Users } from 'src/db';
|
import { DB, Partners, Users } from 'src/db';
|
||||||
import { DummyValue, GenerateSql } from 'src/decorators';
|
import { DummyValue, GenerateSql } from 'src/decorators';
|
||||||
import { PartnerEntity } from 'src/entities/partner.entity';
|
import { PartnerEntity } from 'src/entities/partner.entity';
|
||||||
import { IPartnerRepository, PartnerIds } from 'src/interfaces/partner.interface';
|
|
||||||
|
export interface PartnerIds {
|
||||||
|
sharedById: string;
|
||||||
|
sharedWithId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum PartnerDirection {
|
||||||
|
SharedBy = 'shared-by',
|
||||||
|
SharedWith = 'shared-with',
|
||||||
|
}
|
||||||
|
|
||||||
const columns = ['id', 'name', 'email', 'profileImagePath', 'profileChangedAt'] as const;
|
const columns = ['id', 'name', 'email', 'profileImagePath', 'profileChangedAt'] as const;
|
||||||
|
|
||||||
@@ -28,7 +37,7 @@ const withSharedWith = (eb: ExpressionBuilder<DB, 'partners'>) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class PartnerRepository implements IPartnerRepository {
|
export class PartnerRepository {
|
||||||
constructor(@InjectKysely() private db: Kysely<DB>) {}
|
constructor(@InjectKysely() private db: Kysely<DB>) {}
|
||||||
|
|
||||||
@GenerateSql({ params: [DummyValue.UUID] })
|
@GenerateSql({ params: [DummyValue.UUID] })
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { ExpressionBuilder, Insertable, Kysely, sql } from 'kysely';
|
import { ExpressionBuilder, Insertable, Kysely, Selectable, sql } from 'kysely';
|
||||||
import { jsonObjectFrom } from 'kysely/helpers/postgres';
|
import { jsonObjectFrom } from 'kysely/helpers/postgres';
|
||||||
import { InjectKysely } from 'nestjs-kysely';
|
import { InjectKysely } from 'nestjs-kysely';
|
||||||
import { AssetFaces, DB, FaceSearch, Person } from 'src/db';
|
import { AssetFaces, DB, FaceSearch, Person } from 'src/db';
|
||||||
@@ -7,23 +7,53 @@ import { ChunkedArray, DummyValue, GenerateSql } from 'src/decorators';
|
|||||||
import { AssetFaceEntity } from 'src/entities/asset-face.entity';
|
import { AssetFaceEntity } from 'src/entities/asset-face.entity';
|
||||||
import { PersonEntity } from 'src/entities/person.entity';
|
import { PersonEntity } from 'src/entities/person.entity';
|
||||||
import { SourceType } from 'src/enum';
|
import { SourceType } from 'src/enum';
|
||||||
import {
|
|
||||||
AssetFaceId,
|
|
||||||
DeleteFacesOptions,
|
|
||||||
IPersonRepository,
|
|
||||||
PeopleStatistics,
|
|
||||||
PersonNameResponse,
|
|
||||||
PersonNameSearchOptions,
|
|
||||||
PersonSearchOptions,
|
|
||||||
PersonStatistics,
|
|
||||||
SelectFaceOptions,
|
|
||||||
UnassignFacesOptions,
|
|
||||||
UpdateFacesData,
|
|
||||||
} from 'src/interfaces/person.interface';
|
|
||||||
import { mapUpsertColumns } from 'src/utils/database';
|
import { mapUpsertColumns } from 'src/utils/database';
|
||||||
import { Paginated, PaginationOptions } from 'src/utils/pagination';
|
import { Paginated, PaginationOptions } from 'src/utils/pagination';
|
||||||
import { FindOptionsRelations } from 'typeorm';
|
import { FindOptionsRelations } from 'typeorm';
|
||||||
|
|
||||||
|
export interface PersonSearchOptions {
|
||||||
|
minimumFaceCount: number;
|
||||||
|
withHidden: boolean;
|
||||||
|
closestFaceAssetId?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PersonNameSearchOptions {
|
||||||
|
withHidden?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PersonNameResponse {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AssetFaceId {
|
||||||
|
assetId: string;
|
||||||
|
personId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UpdateFacesData {
|
||||||
|
oldPersonId?: string;
|
||||||
|
faceIds?: string[];
|
||||||
|
newPersonId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PersonStatistics {
|
||||||
|
assets: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PeopleStatistics {
|
||||||
|
total: number;
|
||||||
|
hidden: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DeleteFacesOptions {
|
||||||
|
sourceType: SourceType;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type UnassignFacesOptions = DeleteFacesOptions;
|
||||||
|
|
||||||
|
export type SelectFaceOptions = (keyof Selectable<AssetFaces>)[];
|
||||||
|
|
||||||
const withPerson = (eb: ExpressionBuilder<DB, 'asset_faces'>) => {
|
const withPerson = (eb: ExpressionBuilder<DB, 'asset_faces'>) => {
|
||||||
return jsonObjectFrom(
|
return jsonObjectFrom(
|
||||||
eb.selectFrom('person').selectAll('person').whereRef('person.id', '=', 'asset_faces.personId'),
|
eb.selectFrom('person').selectAll('person').whereRef('person.id', '=', 'asset_faces.personId'),
|
||||||
@@ -43,7 +73,7 @@ const withFaceSearch = (eb: ExpressionBuilder<DB, 'asset_faces'>) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class PersonRepository implements IPersonRepository {
|
export class PersonRepository {
|
||||||
constructor(@InjectKysely() private db: Kysely<DB>) {}
|
constructor(@InjectKysely() private db: Kysely<DB>) {}
|
||||||
|
|
||||||
@GenerateSql({ params: [{ oldPersonId: DummyValue.UUID, newPersonId: DummyValue.UUID }] })
|
@GenerateSql({ params: [{ oldPersonId: DummyValue.UUID, newPersonId: DummyValue.UUID }] })
|
||||||
|
|||||||
@@ -6,26 +6,202 @@ import { DB } from 'src/db';
|
|||||||
import { DummyValue, GenerateSql } from 'src/decorators';
|
import { DummyValue, GenerateSql } from 'src/decorators';
|
||||||
import { AssetEntity, searchAssetBuilder } from 'src/entities/asset.entity';
|
import { AssetEntity, searchAssetBuilder } from 'src/entities/asset.entity';
|
||||||
import { GeodataPlacesEntity } from 'src/entities/geodata-places.entity';
|
import { GeodataPlacesEntity } from 'src/entities/geodata-places.entity';
|
||||||
import { AssetType } from 'src/enum';
|
import { AssetStatus, AssetType } from 'src/enum';
|
||||||
import {
|
|
||||||
AssetDuplicateSearch,
|
|
||||||
AssetSearchOptions,
|
|
||||||
FaceEmbeddingSearch,
|
|
||||||
GetCameraMakesOptions,
|
|
||||||
GetCameraModelsOptions,
|
|
||||||
GetCitiesOptions,
|
|
||||||
GetStatesOptions,
|
|
||||||
ISearchRepository,
|
|
||||||
SearchPaginationOptions,
|
|
||||||
SmartSearchOptions,
|
|
||||||
} from 'src/interfaces/search.interface';
|
|
||||||
import { LoggingRepository } from 'src/repositories/logging.repository';
|
import { LoggingRepository } from 'src/repositories/logging.repository';
|
||||||
import { anyUuid, asUuid } from 'src/utils/database';
|
import { anyUuid, asUuid } from 'src/utils/database';
|
||||||
import { Paginated } from 'src/utils/pagination';
|
import { Paginated } from 'src/utils/pagination';
|
||||||
import { isValidInteger } from 'src/validation';
|
import { isValidInteger } from 'src/validation';
|
||||||
|
|
||||||
|
export interface SearchResult<T> {
|
||||||
|
/** total matches */
|
||||||
|
total: number;
|
||||||
|
/** collection size */
|
||||||
|
count: number;
|
||||||
|
/** current page */
|
||||||
|
page: number;
|
||||||
|
/** items for page */
|
||||||
|
items: T[];
|
||||||
|
/** score */
|
||||||
|
distances: number[];
|
||||||
|
facets: SearchFacet[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SearchFacet {
|
||||||
|
fieldName: string;
|
||||||
|
counts: Array<{
|
||||||
|
count: number;
|
||||||
|
value: string;
|
||||||
|
}>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type SearchExploreItemSet<T> = Array<{
|
||||||
|
value: string;
|
||||||
|
data: T;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
export interface SearchExploreItem<T> {
|
||||||
|
fieldName: string;
|
||||||
|
items: SearchExploreItemSet<T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SearchAssetIDOptions {
|
||||||
|
checksum?: Buffer;
|
||||||
|
deviceAssetId?: string;
|
||||||
|
id?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SearchUserIdOptions {
|
||||||
|
deviceId?: string;
|
||||||
|
libraryId?: string | null;
|
||||||
|
userIds?: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export type SearchIdOptions = SearchAssetIDOptions & SearchUserIdOptions;
|
||||||
|
|
||||||
|
export interface SearchStatusOptions {
|
||||||
|
isArchived?: boolean;
|
||||||
|
isEncoded?: boolean;
|
||||||
|
isFavorite?: boolean;
|
||||||
|
isMotion?: boolean;
|
||||||
|
isOffline?: boolean;
|
||||||
|
isVisible?: boolean;
|
||||||
|
isNotInAlbum?: boolean;
|
||||||
|
type?: AssetType;
|
||||||
|
status?: AssetStatus;
|
||||||
|
withArchived?: boolean;
|
||||||
|
withDeleted?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SearchOneToOneRelationOptions {
|
||||||
|
withExif?: boolean;
|
||||||
|
withStacked?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SearchRelationOptions extends SearchOneToOneRelationOptions {
|
||||||
|
withFaces?: boolean;
|
||||||
|
withPeople?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SearchDateOptions {
|
||||||
|
createdBefore?: Date;
|
||||||
|
createdAfter?: Date;
|
||||||
|
takenBefore?: Date;
|
||||||
|
takenAfter?: Date;
|
||||||
|
trashedBefore?: Date;
|
||||||
|
trashedAfter?: Date;
|
||||||
|
updatedBefore?: Date;
|
||||||
|
updatedAfter?: Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SearchPathOptions {
|
||||||
|
encodedVideoPath?: string;
|
||||||
|
originalFileName?: string;
|
||||||
|
originalPath?: string;
|
||||||
|
previewPath?: string;
|
||||||
|
thumbnailPath?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SearchExifOptions {
|
||||||
|
city?: string | null;
|
||||||
|
country?: string | null;
|
||||||
|
lensModel?: string | null;
|
||||||
|
make?: string | null;
|
||||||
|
model?: string | null;
|
||||||
|
state?: string | null;
|
||||||
|
description?: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SearchEmbeddingOptions {
|
||||||
|
embedding: string;
|
||||||
|
userIds: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SearchPeopleOptions {
|
||||||
|
personIds?: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SearchTagOptions {
|
||||||
|
tagIds?: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SearchOrderOptions {
|
||||||
|
orderDirection?: 'asc' | 'desc';
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SearchPaginationOptions {
|
||||||
|
page: number;
|
||||||
|
size: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
type BaseAssetSearchOptions = SearchDateOptions &
|
||||||
|
SearchIdOptions &
|
||||||
|
SearchExifOptions &
|
||||||
|
SearchOrderOptions &
|
||||||
|
SearchPathOptions &
|
||||||
|
SearchStatusOptions &
|
||||||
|
SearchUserIdOptions &
|
||||||
|
SearchPeopleOptions &
|
||||||
|
SearchTagOptions;
|
||||||
|
|
||||||
|
export type AssetSearchOptions = BaseAssetSearchOptions & SearchRelationOptions;
|
||||||
|
|
||||||
|
export type AssetSearchOneToOneRelationOptions = BaseAssetSearchOptions & SearchOneToOneRelationOptions;
|
||||||
|
|
||||||
|
export type AssetSearchBuilderOptions = Omit<AssetSearchOptions, 'orderDirection'>;
|
||||||
|
|
||||||
|
export type SmartSearchOptions = SearchDateOptions &
|
||||||
|
SearchEmbeddingOptions &
|
||||||
|
SearchExifOptions &
|
||||||
|
SearchOneToOneRelationOptions &
|
||||||
|
SearchStatusOptions &
|
||||||
|
SearchUserIdOptions &
|
||||||
|
SearchPeopleOptions &
|
||||||
|
SearchTagOptions;
|
||||||
|
|
||||||
|
export interface FaceEmbeddingSearch extends SearchEmbeddingOptions {
|
||||||
|
hasPerson?: boolean;
|
||||||
|
numResults: number;
|
||||||
|
maxDistance: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AssetDuplicateSearch {
|
||||||
|
assetId: string;
|
||||||
|
embedding: string;
|
||||||
|
maxDistance: number;
|
||||||
|
type: AssetType;
|
||||||
|
userIds: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FaceSearchResult {
|
||||||
|
distance: number;
|
||||||
|
id: string;
|
||||||
|
personId: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AssetDuplicateResult {
|
||||||
|
assetId: string;
|
||||||
|
duplicateId: string | null;
|
||||||
|
distance: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GetStatesOptions {
|
||||||
|
country?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GetCitiesOptions extends GetStatesOptions {
|
||||||
|
state?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GetCameraModelsOptions {
|
||||||
|
make?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GetCameraMakesOptions {
|
||||||
|
model?: string;
|
||||||
|
}
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class SearchRepository implements ISearchRepository {
|
export class SearchRepository {
|
||||||
constructor(
|
constructor(
|
||||||
private logger: LoggingRepository,
|
private logger: LoggingRepository,
|
||||||
@InjectKysely() private db: Kysely<DB>,
|
@InjectKysely() private db: Kysely<DB>,
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { Insertable, Kysely, Updateable } from 'kysely';
|
import { Insertable, Kysely, Updateable } from 'kysely';
|
||||||
|
import { jsonObjectFrom } from 'kysely/helpers/postgres';
|
||||||
import { InjectKysely } from 'nestjs-kysely';
|
import { InjectKysely } from 'nestjs-kysely';
|
||||||
|
import { columns } from 'src/database';
|
||||||
import { DB, Sessions } from 'src/db';
|
import { DB, Sessions } from 'src/db';
|
||||||
import { DummyValue, GenerateSql } from 'src/decorators';
|
import { DummyValue, GenerateSql } from 'src/decorators';
|
||||||
import { withUser } from 'src/entities/session.entity';
|
import { withUser } from 'src/entities/session.entity';
|
||||||
@@ -25,9 +27,16 @@ export class SessionRepository {
|
|||||||
getByToken(token: string) {
|
getByToken(token: string) {
|
||||||
return this.db
|
return this.db
|
||||||
.selectFrom('sessions')
|
.selectFrom('sessions')
|
||||||
.innerJoinLateral(withUser, (join) => join.onTrue())
|
.select((eb) => [
|
||||||
.selectAll('sessions')
|
...columns.authSession,
|
||||||
.select((eb) => eb.fn.toJson('user').as('user'))
|
jsonObjectFrom(
|
||||||
|
eb
|
||||||
|
.selectFrom('users')
|
||||||
|
.select(columns.authUser)
|
||||||
|
.whereRef('users.id', '=', 'sessions.userId')
|
||||||
|
.where('users.deletedAt', 'is', null),
|
||||||
|
).as('user'),
|
||||||
|
])
|
||||||
.where('sessions.token', '=', token)
|
.where('sessions.token', '=', token)
|
||||||
.executeTakeFirst();
|
.executeTakeFirst();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,14 +3,19 @@ import { Insertable, Kysely, sql, Updateable } from 'kysely';
|
|||||||
import { jsonObjectFrom } from 'kysely/helpers/postgres';
|
import { jsonObjectFrom } from 'kysely/helpers/postgres';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import { InjectKysely } from 'nestjs-kysely';
|
import { InjectKysely } from 'nestjs-kysely';
|
||||||
|
import { columns } from 'src/database';
|
||||||
import { DB, SharedLinks } from 'src/db';
|
import { DB, SharedLinks } from 'src/db';
|
||||||
import { DummyValue, GenerateSql } from 'src/decorators';
|
import { DummyValue, GenerateSql } from 'src/decorators';
|
||||||
import { SharedLinkEntity } from 'src/entities/shared-link.entity';
|
import { SharedLinkEntity } from 'src/entities/shared-link.entity';
|
||||||
import { SharedLinkType } from 'src/enum';
|
import { SharedLinkType } from 'src/enum';
|
||||||
import { ISharedLinkRepository, SharedLinkSearchOptions } from 'src/interfaces/shared-link.interface';
|
|
||||||
|
export type SharedLinkSearchOptions = {
|
||||||
|
userId: string;
|
||||||
|
albumId?: string;
|
||||||
|
};
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class SharedLinkRepository implements ISharedLinkRepository {
|
export class SharedLinkRepository {
|
||||||
constructor(@InjectKysely() private db: Kysely<DB>) {}
|
constructor(@InjectKysely() private db: Kysely<DB>) {}
|
||||||
|
|
||||||
@GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID] })
|
@GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID] })
|
||||||
@@ -92,7 +97,7 @@ export class SharedLinkRepository implements ISharedLinkRepository {
|
|||||||
.executeTakeFirst() as Promise<SharedLinkEntity | undefined>;
|
.executeTakeFirst() as Promise<SharedLinkEntity | undefined>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@GenerateSql({ params: [DummyValue.UUID] })
|
@GenerateSql({ params: [{ userId: DummyValue.UUID, albumId: DummyValue.UUID }] })
|
||||||
getAll({ userId, albumId }: SharedLinkSearchOptions): Promise<SharedLinkEntity[]> {
|
getAll({ userId, albumId }: SharedLinkSearchOptions): Promise<SharedLinkEntity[]> {
|
||||||
return this.db
|
return this.db
|
||||||
.selectFrom('shared_links')
|
.selectFrom('shared_links')
|
||||||
@@ -156,39 +161,20 @@ export class SharedLinkRepository implements ISharedLinkRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@GenerateSql({ params: [DummyValue.BUFFER] })
|
@GenerateSql({ params: [DummyValue.BUFFER] })
|
||||||
async getByKey(key: Buffer): Promise<SharedLinkEntity | undefined> {
|
async getByKey(key: Buffer) {
|
||||||
return this.db
|
return this.db
|
||||||
.selectFrom('shared_links')
|
.selectFrom('shared_links')
|
||||||
.selectAll('shared_links')
|
|
||||||
.where('shared_links.key', '=', key)
|
.where('shared_links.key', '=', key)
|
||||||
.leftJoin('albums', 'albums.id', 'shared_links.albumId')
|
.leftJoin('albums', 'albums.id', 'shared_links.albumId')
|
||||||
.where('albums.deletedAt', 'is', null)
|
.where('albums.deletedAt', 'is', null)
|
||||||
.select((eb) =>
|
.select((eb) => [
|
||||||
|
...columns.authSharedLink,
|
||||||
jsonObjectFrom(
|
jsonObjectFrom(
|
||||||
eb
|
eb.selectFrom('users').select(columns.authUser).whereRef('users.id', '=', 'shared_links.userId'),
|
||||||
.selectFrom('users')
|
|
||||||
.select([
|
|
||||||
'users.id',
|
|
||||||
'users.email',
|
|
||||||
'users.createdAt',
|
|
||||||
'users.profileImagePath',
|
|
||||||
'users.isAdmin',
|
|
||||||
'users.shouldChangePassword',
|
|
||||||
'users.deletedAt',
|
|
||||||
'users.oauthId',
|
|
||||||
'users.updatedAt',
|
|
||||||
'users.storageLabel',
|
|
||||||
'users.name',
|
|
||||||
'users.quotaSizeInBytes',
|
|
||||||
'users.quotaUsageInBytes',
|
|
||||||
'users.status',
|
|
||||||
'users.profileChangedAt',
|
|
||||||
])
|
|
||||||
.whereRef('users.id', '=', 'shared_links.userId'),
|
|
||||||
).as('user'),
|
).as('user'),
|
||||||
)
|
])
|
||||||
.where((eb) => eb.or([eb('shared_links.type', '=', SharedLinkType.INDIVIDUAL), eb('albums.id', 'is not', null)]))
|
.where((eb) => eb.or([eb('shared_links.type', '=', SharedLinkType.INDIVIDUAL), eb('albums.id', 'is not', null)]))
|
||||||
.executeTakeFirst() as Promise<SharedLinkEntity | undefined>;
|
.executeTakeFirst();
|
||||||
}
|
}
|
||||||
|
|
||||||
async create(entity: Insertable<SharedLinks> & { assetIds?: string[] }): Promise<SharedLinkEntity> {
|
async create(entity: Insertable<SharedLinks> & { assetIds?: string[] }): Promise<SharedLinkEntity> {
|
||||||
|
|||||||
@@ -5,9 +5,13 @@ import { InjectKysely } from 'nestjs-kysely';
|
|||||||
import { DB } from 'src/db';
|
import { DB } from 'src/db';
|
||||||
import { DummyValue, GenerateSql } from 'src/decorators';
|
import { DummyValue, GenerateSql } from 'src/decorators';
|
||||||
import { StackEntity } from 'src/entities/stack.entity';
|
import { StackEntity } from 'src/entities/stack.entity';
|
||||||
import { IStackRepository, StackSearch } from 'src/interfaces/stack.interface';
|
|
||||||
import { asUuid } from 'src/utils/database';
|
import { asUuid } from 'src/utils/database';
|
||||||
|
|
||||||
|
export interface StackSearch {
|
||||||
|
ownerId: string;
|
||||||
|
primaryAssetId?: string;
|
||||||
|
}
|
||||||
|
|
||||||
const withAssets = (eb: ExpressionBuilder<DB, 'asset_stack'>, withTags = false) => {
|
const withAssets = (eb: ExpressionBuilder<DB, 'asset_stack'>, withTags = false) => {
|
||||||
return jsonArrayFrom(
|
return jsonArrayFrom(
|
||||||
eb
|
eb
|
||||||
@@ -35,7 +39,7 @@ const withAssets = (eb: ExpressionBuilder<DB, 'asset_stack'>, withTags = false)
|
|||||||
};
|
};
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class StackRepository implements IStackRepository {
|
export class StackRepository {
|
||||||
constructor(@InjectKysely() private db: Kysely<DB>) {}
|
constructor(@InjectKysely() private db: Kysely<DB>) {}
|
||||||
|
|
||||||
@GenerateSql({ params: [{ ownerId: DummyValue.UUID }] })
|
@GenerateSql({ params: [{ ownerId: DummyValue.UUID }] })
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ import mockfs from 'mock-fs';
|
|||||||
import { CrawlOptionsDto } from 'src/dtos/library.dto';
|
import { CrawlOptionsDto } from 'src/dtos/library.dto';
|
||||||
import { LoggingRepository } from 'src/repositories/logging.repository';
|
import { LoggingRepository } from 'src/repositories/logging.repository';
|
||||||
import { StorageRepository } from 'src/repositories/storage.repository';
|
import { StorageRepository } from 'src/repositories/storage.repository';
|
||||||
import { ILoggingRepository } from 'src/types';
|
import { ILoggingRepository, newLoggingRepositoryMock } from 'test/repositories/logger.repository.mock';
|
||||||
import { newLoggingRepositoryMock } from 'test/repositories/logger.repository.mock';
|
import { Mocked } from 'vitest';
|
||||||
|
|
||||||
interface Test {
|
interface Test {
|
||||||
test: string;
|
test: string;
|
||||||
@@ -182,11 +182,11 @@ const tests: Test[] = [
|
|||||||
|
|
||||||
describe(StorageRepository.name, () => {
|
describe(StorageRepository.name, () => {
|
||||||
let sut: StorageRepository;
|
let sut: StorageRepository;
|
||||||
let logger: ILoggingRepository;
|
let logger: Mocked<ILoggingRepository>;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
logger = newLoggingRepositoryMock();
|
logger = newLoggingRepositoryMock();
|
||||||
sut = new StorageRepository(logger as LoggingRepository);
|
sut = new StorageRepository(logger as ILoggingRepository as LoggingRepository);
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
|||||||
@@ -5,20 +5,38 @@ import { escapePath, glob, globStream } from 'fast-glob';
|
|||||||
import { constants, createReadStream, createWriteStream, existsSync, mkdirSync } from 'node:fs';
|
import { constants, createReadStream, createWriteStream, existsSync, mkdirSync } from 'node:fs';
|
||||||
import fs from 'node:fs/promises';
|
import fs from 'node:fs/promises';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import { Writable } from 'node:stream';
|
import { Readable, Writable } from 'node:stream';
|
||||||
import { CrawlOptionsDto, WalkOptionsDto } from 'src/dtos/library.dto';
|
import { CrawlOptionsDto, WalkOptionsDto } from 'src/dtos/library.dto';
|
||||||
import {
|
|
||||||
DiskUsage,
|
|
||||||
IStorageRepository,
|
|
||||||
ImmichReadStream,
|
|
||||||
ImmichZipStream,
|
|
||||||
WatchEvents,
|
|
||||||
} from 'src/interfaces/storage.interface';
|
|
||||||
import { LoggingRepository } from 'src/repositories/logging.repository';
|
import { LoggingRepository } from 'src/repositories/logging.repository';
|
||||||
import { mimeTypes } from 'src/utils/mime-types';
|
import { mimeTypes } from 'src/utils/mime-types';
|
||||||
|
|
||||||
|
export interface WatchEvents {
|
||||||
|
onReady(): void;
|
||||||
|
onAdd(path: string): void;
|
||||||
|
onChange(path: string): void;
|
||||||
|
onUnlink(path: string): void;
|
||||||
|
onError(error: Error): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ImmichReadStream {
|
||||||
|
stream: Readable;
|
||||||
|
type?: string;
|
||||||
|
length?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ImmichZipStream extends ImmichReadStream {
|
||||||
|
addFile: (inputPath: string, filename: string) => void;
|
||||||
|
finalize: () => Promise<void>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DiskUsage {
|
||||||
|
available: number;
|
||||||
|
free: number;
|
||||||
|
total: number;
|
||||||
|
}
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class StorageRepository implements IStorageRepository {
|
export class StorageRepository {
|
||||||
constructor(private logger: LoggingRepository) {
|
constructor(private logger: LoggingRepository) {
|
||||||
this.logger.setContext(StorageRepository.name);
|
this.logger.setContext(StorageRepository.name);
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user