1
0
forked from Cutlery/immich

Merge branch 'main' of https://github.com/immich-app/immich into feat/offline-files-job

This commit is contained in:
Jonathan Jogenfors 2024-04-04 23:09:52 +02:00
commit a352f7e1d7
152 changed files with 5617 additions and 1473 deletions

View File

@ -1,4 +1,4 @@
FROM node:20-alpine3.19@sha256:bf77dc26e48ea95fca9d1aceb5acfa69d2e546b765ec2abfb502975f1a2d4def as core
FROM node:20-alpine3.19@sha256:ef3f47741e161900ddd07addcaca7e76534a9205e4cd73b2ed091ba339004a75 as core
WORKDIR /usr/src/open-api/typescript-sdk
COPY open-api/typescript-sdk/package*.json open-api/typescript-sdk/tsconfig*.json ./

112
cli/package-lock.json generated
View File

@ -1251,16 +1251,16 @@
"dev": true
},
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.3.1.tgz",
"integrity": "sha512-STEDMVQGww5lhCuNXVSQfbfuNII5E08QWkvAw5Qwf+bj2WT+JkG1uc+5/vXA3AOYMDHVOSpL+9rcbEUiHIm2dw==",
"version": "7.4.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.4.0.tgz",
"integrity": "sha512-yHMQ/oFaM7HZdVrVm/M2WHaNPgyuJH4WelkSVEWSSsir34kxW2kDJCxlXRhhGWEsMN0WAW/vLpKfKVcm8k+MPw==",
"dev": true,
"dependencies": {
"@eslint-community/regexpp": "^4.5.1",
"@typescript-eslint/scope-manager": "7.3.1",
"@typescript-eslint/type-utils": "7.3.1",
"@typescript-eslint/utils": "7.3.1",
"@typescript-eslint/visitor-keys": "7.3.1",
"@typescript-eslint/scope-manager": "7.4.0",
"@typescript-eslint/type-utils": "7.4.0",
"@typescript-eslint/utils": "7.4.0",
"@typescript-eslint/visitor-keys": "7.4.0",
"debug": "^4.3.4",
"graphemer": "^1.4.0",
"ignore": "^5.2.4",
@ -1286,15 +1286,15 @@
}
},
"node_modules/@typescript-eslint/parser": {
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.3.1.tgz",
"integrity": "sha512-Rq49+pq7viTRCH48XAbTA+wdLRrB/3sRq4Lpk0oGDm0VmnjBrAOVXH/Laalmwsv2VpekiEfVFwJYVk6/e8uvQw==",
"version": "7.4.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.4.0.tgz",
"integrity": "sha512-ZvKHxHLusweEUVwrGRXXUVzFgnWhigo4JurEj0dGF1tbcGh6buL+ejDdjxOQxv6ytcY1uhun1p2sm8iWStlgLQ==",
"dev": true,
"dependencies": {
"@typescript-eslint/scope-manager": "7.3.1",
"@typescript-eslint/types": "7.3.1",
"@typescript-eslint/typescript-estree": "7.3.1",
"@typescript-eslint/visitor-keys": "7.3.1",
"@typescript-eslint/scope-manager": "7.4.0",
"@typescript-eslint/types": "7.4.0",
"@typescript-eslint/typescript-estree": "7.4.0",
"@typescript-eslint/visitor-keys": "7.4.0",
"debug": "^4.3.4"
},
"engines": {
@ -1314,13 +1314,13 @@
}
},
"node_modules/@typescript-eslint/scope-manager": {
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.3.1.tgz",
"integrity": "sha512-fVS6fPxldsKY2nFvyT7IP78UO1/I2huG+AYu5AMjCT9wtl6JFiDnsv4uad4jQ0GTFzcUV5HShVeN96/17bTBag==",
"version": "7.4.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.4.0.tgz",
"integrity": "sha512-68VqENG5HK27ypafqLVs8qO+RkNc7TezCduYrx8YJpXq2QGZ30vmNZGJJJC48+MVn4G2dCV8m5ZTVnzRexTVtw==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "7.3.1",
"@typescript-eslint/visitor-keys": "7.3.1"
"@typescript-eslint/types": "7.4.0",
"@typescript-eslint/visitor-keys": "7.4.0"
},
"engines": {
"node": "^18.18.0 || >=20.0.0"
@ -1331,13 +1331,13 @@
}
},
"node_modules/@typescript-eslint/type-utils": {
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.3.1.tgz",
"integrity": "sha512-iFhaysxFsMDQlzJn+vr3OrxN8NmdQkHks4WaqD4QBnt5hsq234wcYdyQ9uquzJJIDAj5W4wQne3yEsYA6OmXGw==",
"version": "7.4.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.4.0.tgz",
"integrity": "sha512-247ETeHgr9WTRMqHbbQdzwzhuyaJ8dPTuyuUEMANqzMRB1rj/9qFIuIXK7l0FX9i9FXbHeBQl/4uz6mYuCE7Aw==",
"dev": true,
"dependencies": {
"@typescript-eslint/typescript-estree": "7.3.1",
"@typescript-eslint/utils": "7.3.1",
"@typescript-eslint/typescript-estree": "7.4.0",
"@typescript-eslint/utils": "7.4.0",
"debug": "^4.3.4",
"ts-api-utils": "^1.0.1"
},
@ -1358,9 +1358,9 @@
}
},
"node_modules/@typescript-eslint/types": {
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.3.1.tgz",
"integrity": "sha512-2tUf3uWggBDl4S4183nivWQ2HqceOZh1U4hhu4p1tPiIJoRRXrab7Y+Y0p+dozYwZVvLPRI6r5wKe9kToF9FIw==",
"version": "7.4.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.4.0.tgz",
"integrity": "sha512-mjQopsbffzJskos5B4HmbsadSJQWaRK0UxqQ7GuNA9Ga4bEKeiO6b2DnB6cM6bpc8lemaPseh0H9B/wyg+J7rw==",
"dev": true,
"engines": {
"node": "^18.18.0 || >=20.0.0"
@ -1371,13 +1371,13 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.3.1.tgz",
"integrity": "sha512-tLpuqM46LVkduWP7JO7yVoWshpJuJzxDOPYIVWUUZbW+4dBpgGeUdl/fQkhuV0A8eGnphYw3pp8d2EnvPOfxmQ==",
"version": "7.4.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.4.0.tgz",
"integrity": "sha512-A99j5AYoME/UBQ1ucEbbMEmGkN7SE0BvZFreSnTd1luq7yulcHdyGamZKizU7canpGDWGJ+Q6ZA9SyQobipePg==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "7.3.1",
"@typescript-eslint/visitor-keys": "7.3.1",
"@typescript-eslint/types": "7.4.0",
"@typescript-eslint/visitor-keys": "7.4.0",
"debug": "^4.3.4",
"globby": "^11.1.0",
"is-glob": "^4.0.3",
@ -1399,17 +1399,17 @@
}
},
"node_modules/@typescript-eslint/utils": {
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.3.1.tgz",
"integrity": "sha512-jIERm/6bYQ9HkynYlNZvXpzmXWZGhMbrOvq3jJzOSOlKXsVjrrolzWBjDW6/TvT5Q3WqaN4EkmcfdQwi9tDjBQ==",
"version": "7.4.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.4.0.tgz",
"integrity": "sha512-NQt9QLM4Tt8qrlBVY9lkMYzfYtNz8/6qwZg8pI3cMGlPnj6mOpRxxAm7BMJN9K0AiY+1BwJ5lVC650YJqYOuNg==",
"dev": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.4.0",
"@types/json-schema": "^7.0.12",
"@types/semver": "^7.5.0",
"@typescript-eslint/scope-manager": "7.3.1",
"@typescript-eslint/types": "7.3.1",
"@typescript-eslint/typescript-estree": "7.3.1",
"@typescript-eslint/scope-manager": "7.4.0",
"@typescript-eslint/types": "7.4.0",
"@typescript-eslint/typescript-estree": "7.4.0",
"semver": "^7.5.4"
},
"engines": {
@ -1424,12 +1424,12 @@
}
},
"node_modules/@typescript-eslint/visitor-keys": {
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.3.1.tgz",
"integrity": "sha512-9RMXwQF8knsZvfv9tdi+4D/j7dMG28X/wMJ8Jj6eOHyHWwDW4ngQJcqEczSsqIKKjFiLFr40Mnr7a5ulDD3vmw==",
"version": "7.4.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.4.0.tgz",
"integrity": "sha512-0zkC7YM0iX5Y41homUUeW1CHtZR01K3ybjM1l6QczoMuay0XKtrb93kv95AxUGwdjGr64nNqnOCwmEl616N8CA==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "7.3.1",
"@typescript-eslint/types": "7.4.0",
"eslint-visitor-keys": "^3.4.1"
},
"engines": {
@ -2555,16 +2555,16 @@
}
},
"node_modules/glob": {
"version": "10.3.10",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz",
"integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==",
"version": "10.3.12",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz",
"integrity": "sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==",
"dev": true,
"dependencies": {
"foreground-child": "^3.1.0",
"jackspeak": "^2.3.5",
"jackspeak": "^2.3.6",
"minimatch": "^9.0.1",
"minipass": "^5.0.0 || ^6.0.2 || ^7.0.0",
"path-scurry": "^1.10.1"
"minipass": "^7.0.4",
"path-scurry": "^1.10.2"
},
"bin": {
"glob": "dist/esm/bin.mjs"
@ -3411,12 +3411,12 @@
"dev": true
},
"node_modules/path-scurry": {
"version": "1.10.1",
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz",
"integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==",
"version": "1.10.2",
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.2.tgz",
"integrity": "sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==",
"dev": true,
"dependencies": {
"lru-cache": "^9.1.1 || ^10.0.0",
"lru-cache": "^10.2.0",
"minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
},
"engines": {
@ -4456,13 +4456,13 @@
}
},
"node_modules/vite": {
"version": "5.2.3",
"resolved": "https://registry.npmjs.org/vite/-/vite-5.2.3.tgz",
"integrity": "sha512-+i1oagbvkVIhEy9TnEV+fgXsng13nZM90JQbrcPrf6DvW2mXARlz+DK7DLiDP+qeKoD1FCVx/1SpFL1CLq9Mhw==",
"version": "5.2.7",
"resolved": "https://registry.npmjs.org/vite/-/vite-5.2.7.tgz",
"integrity": "sha512-k14PWOKLI6pMaSzAuGtT+Cf0YmIx12z9YGon39onaJNy8DLBfBJrzg9FQEmkAM5lpHBZs9wksWAsyF/HkpEwJA==",
"dev": true,
"dependencies": {
"esbuild": "^0.20.1",
"postcss": "^8.4.36",
"postcss": "^8.4.38",
"rollup": "^4.13.0"
},
"bin": {

View File

@ -76,7 +76,7 @@ services:
container_name: immich_prometheus
ports:
- 9090:9090
image: prom/prometheus@sha256:5ccad477d0057e62a7cd1981ffcc43785ac10c5a35522dc207466ff7e7ec845f
image: prom/prometheus@sha256:dec2018ae55885fed717f25c289b8c9cff0bf5fbb9e619fb49b6161ac493c016
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus-data:/prometheus

View File

@ -253,8 +253,19 @@ The initial backup is the most intensive due to the number of jobs running. The
### Can I limit the amount of CPU and RAM usage?
By default, a container has no resource constraints and can use as much of a given resource as the host's kernel scheduler allows.
You can look at the [original docker docs](https://docs.docker.com/config/containers/resource_constraints/) or use this [guide](https://www.baeldung.com/ops/docker-memory-limit) to learn how to limit this.
By default, a container has no resource constraints and can use as much of a given resource as the host's kernel scheduler allows. To limit this, you can add the following to the `docker-compose.yml` block of any containers that you want to have limited resources.
```yaml
deploy:
resources:
limits:
# Number of CPU threads
cpus: '1.00'
# Gigabytes of memory
memory: '1G'
```
For more details, you can look at the [original docker docs](https://docs.docker.com/config/containers/resource_constraints/) or use this [guide](https://www.baeldung.com/ops/docker-memory-limit).
### How can I boost machine learning speed?
@ -296,6 +307,17 @@ You may need to add mount points or docker volumes for the following internal co
The non-root user/group needs read/write access to the volume mounts, including `UPLOAD_LOCATION`.
For a further hardened system, you can add the following block to every container except for `immich_postgres`.
```yaml
security_opt:
# Prevent escalation of privileges after container is started
- no-new-privileges:true
cap_drop:
# Prevent access to raw network traffic
- NET_RAW
```
### How can I **purge** data from Immich?
Data for Immich comes in two forms:

View File

@ -18,12 +18,11 @@ Thanks for being interested in contributing 😊
### Server and web app
This environment includes the following services:
This environment includes the services below. Additional details are available in each service's README.
- Core server - `/server/src/immich`
- Machine learning - `/machine-learning`
- Microservices - `/server/src/microservicess`
- Web app - `/web`
- Server - [`/server`](https://github.com/immich-app/immich/tree/main/server)
- Web app - [`/web`](https://github.com/immich-app/immich/tree/main/web)
- Machine learning - [`/machine-learning`](https://github.com/immich-app/immich/tree/main/machine-learning)
- Redis
- PostgreSQL development database with exposed port `5432` so you can use any database client to acess it

View File

@ -0,0 +1,42 @@
# Supported formats
Immich supports a number of image and video formats, the most common of which are outlined here.
:::note
For the full list, you can refer to the [Immich source code](https://github.com/immich-app/immich/blob/main/server/src/utils/mime-types.ts).
:::
## Image formats
| Format | Extension(s) | Supported? | Notes |
| :-------- | :---------------------------- | :----------------: | :-------------- |
| `AVIF` | `.avif` | :white_check_mark: | |
| `BMP` | `.bmp` | :white_check_mark: | |
| `GIF` | `.gif` | :white_check_mark: | |
| `HEIC` | `.heic` | :white_check_mark: | |
| `HEIF` | `.heif` | :white_check_mark: | |
| `JPEG` | `.jpeg` `.jpg` `.jpe` `.insp` | :white_check_mark: | |
| `JPEG XL` | `.jxl` | :white_check_mark: | |
| `PNG` | `.png` | :white_check_mark: | |
| `PSD` | `.psd` | :white_check_mark: | Adobe Photoshop |
| `RAW` | `.raw` | :white_check_mark: | |
| `RW2` | `.rw2` | :white_check_mark: | |
| `SVG` | `.svg` | :white_check_mark: | |
| `TIFF` | `.tif` `.tiff` | :white_check_mark: | |
| `WEBP` | `.webp` | :white_check_mark: | |
## Video formats
| Format | Extension(s) | Supported? | Notes |
| :---------- | :-------------------- | :----------------: | :---- |
| `3GPP` | `.3gp` `.3gpp` | :white_check_mark: | |
| `AVI` | `.avi` | :white_check_mark: | |
| `FLV` | `.flv` | :white_check_mark: | |
| `M4V` | `.m4v` | :white_check_mark: | |
| `MATROSKA` | `.mkv` | :white_check_mark: | |
| `MP2T` | `.mts` `.m2ts` | :white_check_mark: | |
| `MP4` | `.mp4` `.insv` | :white_check_mark: | |
| `MPEG` | `.mpg` `.mpe` `.mpeg` | :white_check_mark: | |
| `QUICKTIME` | `.mov` | :white_check_mark: | |
| `WEBM` | `.webm` | :white_check_mark: | |
| `WMV` | `.wmv` | :white_check_mark: | |

View File

@ -45,7 +45,7 @@ SELECT * FROM "assets" JOIN "exif" ON "assets"."id" = "exif"."assetId" WHERE "ex
```
```sql title="Without thumbnails"
SELECT * FROM "assets" WHERE "assets"."resizePath" IS NULL OR "assets"."webpPath" IS NULL;
SELECT * FROM "assets" WHERE "assets"."previewPath" IS NULL OR "assets"."thumbnailPath" IS NULL;
```
```sql title="By type"

View File

@ -114,9 +114,11 @@ The default configuration looks like this:
"hashVerificationEnabled": true,
"template": "{{y}}/{{y}}-{{MM}}-{{dd}}/{{filename}}"
},
"thumbnail": {
"webpSize": 250,
"jpegSize": 1440,
"image": {
"thumbnailFormat": "webp",
"thumbnailSize": 250,
"previewFormat": "jpeg",
"previewSize": 1440,
"quality": 80,
"colorspace": "p3"
},

View File

@ -17,10 +17,10 @@ If this should not work, try running `docker compose up -d --force-recreate`.
## Docker Compose
| Variable | Description | Default | Services |
| :---------------- | :-------------------- | :-------: | :-------------------------------------------------- |
| `IMMICH_VERSION` | Image tags | `release` | server, microservices, machine learning, web, proxy |
| `UPLOAD_LOCATION` | Host Path for uploads | | server, microservices |
| Variable | Description | Default | Services |
| :---------------- | :-------------------- | :-------: | :-------------------------------------- |
| `IMMICH_VERSION` | Image tags | `release` | server, microservices, machine learning |
| `UPLOAD_LOCATION` | Host Path for uploads | | server, microservices |
:::tip
@ -30,15 +30,15 @@ These environment variables are used by the `docker-compose.yml` file and do **N
## General
| Variable | Description | Default | Services |
| :------------------------------ | :------------------------------------------- | :------------------: | :------------------------------------------- |
| `TZ` | Timezone | | microservices |
| `NODE_ENV` | Environment (production, development) | `production` | server, microservices, machine learning, web |
| `LOG_LEVEL` | Log Level (verbose, debug, log, warn, error) | `log` | server, microservices |
| `IMMICH_MEDIA_LOCATION` | Media Location | `./upload` | server, microservices |
| `IMMICH_CONFIG_FILE` | Path to config file | | server, microservices |
| `IMMICH_WEB_ROOT` | Path of root index.html | `/usr/src/app/www` | server |
| `IMMICH_REVERSE_GEOCODING_ROOT` | Path of reverse geocoding dump directory | `/usr/src/resources` | microservices |
| Variable | Description | Default | Services |
| :------------------------------ | :------------------------------------------- | :------------------: | :-------------------------------------- |
| `TZ` | Timezone | | microservices |
| `NODE_ENV` | Environment (production, development) | `production` | server, microservices, machine learning |
| `LOG_LEVEL` | Log Level (verbose, debug, log, warn, error) | `log` | server, microservices, machine learning |
| `IMMICH_MEDIA_LOCATION` | Media Location | `./upload` | server, microservices |
| `IMMICH_CONFIG_FILE` | Path to config file | | server, microservices |
| `IMMICH_WEB_ROOT` | Path of root index.html | `/usr/src/app/www` | server |
| `IMMICH_REVERSE_GEOCODING_ROOT` | Path of reverse geocoding dump directory | `/usr/src/resources` | microservices |
:::tip
`TZ` should be set to a `TZ identifier` from [this list](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List). For example, `TZ="Etc/UTC"`.
@ -50,7 +50,6 @@ These environment variables are used by the `docker-compose.yml` file and do **N
| Variable | Description | Default | Services |
| :---------------------- | :-------------------- | :-------: | :--------------- |
| `PORT` | Web Port | `3000` | web |
| `SERVER_PORT` | Server Port | `3001` | server |
| `MICROSERVICES_PORT` | Microservices Port | `3002` | microservices |
| `MACHINE_LEARNING_HOST` | Machine Learning Host | `0.0.0.0` | machine learning |
@ -164,13 +163,14 @@ The following variables support the use of [Docker secrets](https://docs.docker.
To use any of these, replace the regular environment variable with the equivalent `_FILE` environment variable. The value of
the `_FILE` variable should be set to the path of a file containing the variable value.
| Regular Variable | Equivalent Docker Secrets '\_FILE' Variable |
| :----------------: | :-----------------------------------------: |
| `DB_HOSTNAME` | `DB_HOSTNAME_FILE`<sup>\*1</sup> |
| `DB_DATABASE_NAME` | `DB_DATABASE_NAME_FILE`<sup>\*1</sup> |
| `DB_USERNAME` | `DB_USERNAME_FILE`<sup>\*1</sup> |
| `DB_PASSWORD` | `DB_PASSWORD_FILE`<sup>\*1</sup> |
| `REDIS_PASSWORD` | `REDIS_PASSWORD_FILE`<sup>\*2</sup> |
| Regular Variable | Equivalent Docker Secrets '\_FILE' Variable |
| :----------------- | :------------------------------------------ |
| `DB_HOSTNAME` | `DB_HOSTNAME_FILE`<sup>\*1</sup> |
| `DB_DATABASE_NAME` | `DB_DATABASE_NAME_FILE`<sup>\*1</sup> |
| `DB_USERNAME` | `DB_USERNAME_FILE`<sup>\*1</sup> |
| `DB_PASSWORD` | `DB_PASSWORD_FILE`<sup>\*1</sup> |
| `DB_URL` | `DB_URL_FILE`<sup>\*1</sup> |
| `REDIS_PASSWORD` | `REDIS_PASSWORD_FILE`<sup>\*2</sup> |
\*1: See the [official documentation](https://github.com/docker-library/docs/tree/master/postgres#docker-secrets) for
details on how to use Docker Secrets in the Postgres image.

14
docs/package-lock.json generated
View File

@ -3429,9 +3429,9 @@
}
},
"node_modules/@tsconfig/docusaurus": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/@tsconfig/docusaurus/-/docusaurus-2.0.2.tgz",
"integrity": "sha512-12HWfYmgUl4M2o76/TFufGtI68wl2k/b8qPrIrG7ci9YJLrpAtadpy897Bz5v29Mlkr7a1Hq4KHdQTKtU+2rhQ==",
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@tsconfig/docusaurus/-/docusaurus-2.0.3.tgz",
"integrity": "sha512-3l1L5PzWVa7l0691TjnsZ0yOIEwG9DziSqu5IPZPlI5Dowi7z42cEym8Y35GHbgHvPcBfNxfrbxm7Cncn4nByQ==",
"dev": true
},
"node_modules/@types/acorn": {
@ -15781,9 +15781,9 @@
}
},
"node_modules/tailwindcss": {
"version": "3.4.1",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.1.tgz",
"integrity": "sha512-qAYmXRfk3ENzuPBakNK0SRrUDipP8NQnEY6772uDhflcQz5EhRdD7JNZxyrFHVQNCwULPBn6FNPp9brpO7ctcA==",
"version": "3.4.3",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.3.tgz",
"integrity": "sha512-U7sxQk/n397Bmx4JHbJx/iSOOv5G+II3f1kpLpY2QeUv5DcPdcTsYLlusZfq1NthHS1c1cZoyFmmkex1rzke0A==",
"dependencies": {
"@alloc/quick-lru": "^5.2.0",
"arg": "^5.0.2",
@ -15793,7 +15793,7 @@
"fast-glob": "^3.3.0",
"glob-parent": "^6.0.2",
"is-glob": "^4.0.3",
"jiti": "^1.19.1",
"jiti": "^1.21.0",
"lilconfig": "^2.1.0",
"micromatch": "^4.0.5",
"normalize-path": "^3.0.0",

84
e2e/package-lock.json generated
View File

@ -1277,16 +1277,16 @@
}
},
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.3.1.tgz",
"integrity": "sha512-STEDMVQGww5lhCuNXVSQfbfuNII5E08QWkvAw5Qwf+bj2WT+JkG1uc+5/vXA3AOYMDHVOSpL+9rcbEUiHIm2dw==",
"version": "7.4.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.4.0.tgz",
"integrity": "sha512-yHMQ/oFaM7HZdVrVm/M2WHaNPgyuJH4WelkSVEWSSsir34kxW2kDJCxlXRhhGWEsMN0WAW/vLpKfKVcm8k+MPw==",
"dev": true,
"dependencies": {
"@eslint-community/regexpp": "^4.5.1",
"@typescript-eslint/scope-manager": "7.3.1",
"@typescript-eslint/type-utils": "7.3.1",
"@typescript-eslint/utils": "7.3.1",
"@typescript-eslint/visitor-keys": "7.3.1",
"@typescript-eslint/scope-manager": "7.4.0",
"@typescript-eslint/type-utils": "7.4.0",
"@typescript-eslint/utils": "7.4.0",
"@typescript-eslint/visitor-keys": "7.4.0",
"debug": "^4.3.4",
"graphemer": "^1.4.0",
"ignore": "^5.2.4",
@ -1312,15 +1312,15 @@
}
},
"node_modules/@typescript-eslint/parser": {
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.3.1.tgz",
"integrity": "sha512-Rq49+pq7viTRCH48XAbTA+wdLRrB/3sRq4Lpk0oGDm0VmnjBrAOVXH/Laalmwsv2VpekiEfVFwJYVk6/e8uvQw==",
"version": "7.4.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.4.0.tgz",
"integrity": "sha512-ZvKHxHLusweEUVwrGRXXUVzFgnWhigo4JurEj0dGF1tbcGh6buL+ejDdjxOQxv6ytcY1uhun1p2sm8iWStlgLQ==",
"dev": true,
"dependencies": {
"@typescript-eslint/scope-manager": "7.3.1",
"@typescript-eslint/types": "7.3.1",
"@typescript-eslint/typescript-estree": "7.3.1",
"@typescript-eslint/visitor-keys": "7.3.1",
"@typescript-eslint/scope-manager": "7.4.0",
"@typescript-eslint/types": "7.4.0",
"@typescript-eslint/typescript-estree": "7.4.0",
"@typescript-eslint/visitor-keys": "7.4.0",
"debug": "^4.3.4"
},
"engines": {
@ -1340,13 +1340,13 @@
}
},
"node_modules/@typescript-eslint/scope-manager": {
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.3.1.tgz",
"integrity": "sha512-fVS6fPxldsKY2nFvyT7IP78UO1/I2huG+AYu5AMjCT9wtl6JFiDnsv4uad4jQ0GTFzcUV5HShVeN96/17bTBag==",
"version": "7.4.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.4.0.tgz",
"integrity": "sha512-68VqENG5HK27ypafqLVs8qO+RkNc7TezCduYrx8YJpXq2QGZ30vmNZGJJJC48+MVn4G2dCV8m5ZTVnzRexTVtw==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "7.3.1",
"@typescript-eslint/visitor-keys": "7.3.1"
"@typescript-eslint/types": "7.4.0",
"@typescript-eslint/visitor-keys": "7.4.0"
},
"engines": {
"node": "^18.18.0 || >=20.0.0"
@ -1357,13 +1357,13 @@
}
},
"node_modules/@typescript-eslint/type-utils": {
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.3.1.tgz",
"integrity": "sha512-iFhaysxFsMDQlzJn+vr3OrxN8NmdQkHks4WaqD4QBnt5hsq234wcYdyQ9uquzJJIDAj5W4wQne3yEsYA6OmXGw==",
"version": "7.4.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.4.0.tgz",
"integrity": "sha512-247ETeHgr9WTRMqHbbQdzwzhuyaJ8dPTuyuUEMANqzMRB1rj/9qFIuIXK7l0FX9i9FXbHeBQl/4uz6mYuCE7Aw==",
"dev": true,
"dependencies": {
"@typescript-eslint/typescript-estree": "7.3.1",
"@typescript-eslint/utils": "7.3.1",
"@typescript-eslint/typescript-estree": "7.4.0",
"@typescript-eslint/utils": "7.4.0",
"debug": "^4.3.4",
"ts-api-utils": "^1.0.1"
},
@ -1384,9 +1384,9 @@
}
},
"node_modules/@typescript-eslint/types": {
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.3.1.tgz",
"integrity": "sha512-2tUf3uWggBDl4S4183nivWQ2HqceOZh1U4hhu4p1tPiIJoRRXrab7Y+Y0p+dozYwZVvLPRI6r5wKe9kToF9FIw==",
"version": "7.4.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.4.0.tgz",
"integrity": "sha512-mjQopsbffzJskos5B4HmbsadSJQWaRK0UxqQ7GuNA9Ga4bEKeiO6b2DnB6cM6bpc8lemaPseh0H9B/wyg+J7rw==",
"dev": true,
"engines": {
"node": "^18.18.0 || >=20.0.0"
@ -1397,13 +1397,13 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.3.1.tgz",
"integrity": "sha512-tLpuqM46LVkduWP7JO7yVoWshpJuJzxDOPYIVWUUZbW+4dBpgGeUdl/fQkhuV0A8eGnphYw3pp8d2EnvPOfxmQ==",
"version": "7.4.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.4.0.tgz",
"integrity": "sha512-A99j5AYoME/UBQ1ucEbbMEmGkN7SE0BvZFreSnTd1luq7yulcHdyGamZKizU7canpGDWGJ+Q6ZA9SyQobipePg==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "7.3.1",
"@typescript-eslint/visitor-keys": "7.3.1",
"@typescript-eslint/types": "7.4.0",
"@typescript-eslint/visitor-keys": "7.4.0",
"debug": "^4.3.4",
"globby": "^11.1.0",
"is-glob": "^4.0.3",
@ -1449,17 +1449,17 @@
}
},
"node_modules/@typescript-eslint/utils": {
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.3.1.tgz",
"integrity": "sha512-jIERm/6bYQ9HkynYlNZvXpzmXWZGhMbrOvq3jJzOSOlKXsVjrrolzWBjDW6/TvT5Q3WqaN4EkmcfdQwi9tDjBQ==",
"version": "7.4.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.4.0.tgz",
"integrity": "sha512-NQt9QLM4Tt8qrlBVY9lkMYzfYtNz8/6qwZg8pI3cMGlPnj6mOpRxxAm7BMJN9K0AiY+1BwJ5lVC650YJqYOuNg==",
"dev": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.4.0",
"@types/json-schema": "^7.0.12",
"@types/semver": "^7.5.0",
"@typescript-eslint/scope-manager": "7.3.1",
"@typescript-eslint/types": "7.3.1",
"@typescript-eslint/typescript-estree": "7.3.1",
"@typescript-eslint/scope-manager": "7.4.0",
"@typescript-eslint/types": "7.4.0",
"@typescript-eslint/typescript-estree": "7.4.0",
"semver": "^7.5.4"
},
"engines": {
@ -1474,12 +1474,12 @@
}
},
"node_modules/@typescript-eslint/visitor-keys": {
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.3.1.tgz",
"integrity": "sha512-9RMXwQF8knsZvfv9tdi+4D/j7dMG28X/wMJ8Jj6eOHyHWwDW4ngQJcqEczSsqIKKjFiLFr40Mnr7a5ulDD3vmw==",
"version": "7.4.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.4.0.tgz",
"integrity": "sha512-0zkC7YM0iX5Y41homUUeW1CHtZR01K3ybjM1l6QczoMuay0XKtrb93kv95AxUGwdjGr64nNqnOCwmEl616N8CA==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "7.3.1",
"@typescript-eslint/types": "7.4.0",
"eslint-visitor-keys": "^3.4.1"
},
"engines": {

View File

@ -0,0 +1,376 @@
import {
AssetFileUploadResponseDto,
LoginResponseDto,
MemoryResponseDto,
MemoryType,
createMemory,
getMemory,
} from '@immich/sdk';
import { createUserDto, uuidDto } from 'src/fixtures';
import { errorDto } from 'src/responses';
import { app, asBearerAuth, utils } from 'src/utils';
import request from 'supertest';
import { beforeAll, describe, expect, it } from 'vitest';
describe('/memories', () => {
let admin: LoginResponseDto;
let user: LoginResponseDto;
let adminAsset: AssetFileUploadResponseDto;
let userAsset1: AssetFileUploadResponseDto;
let userAsset2: AssetFileUploadResponseDto;
let userMemory: MemoryResponseDto;
beforeAll(async () => {
await utils.resetDatabase();
admin = await utils.adminSetup();
user = await utils.userSetup(admin.accessToken, createUserDto.user1);
[adminAsset, userAsset1, userAsset2] = await Promise.all([
utils.createAsset(admin.accessToken),
utils.createAsset(user.accessToken),
utils.createAsset(user.accessToken),
]);
userMemory = await createMemory(
{
memoryCreateDto: {
type: MemoryType.OnThisDay,
memoryAt: new Date(2021).toISOString(),
data: { year: 2021 },
assetIds: [],
},
},
{ headers: asBearerAuth(user.accessToken) },
);
});
describe('GET /memories', () => {
it('should require authentication', async () => {
const { status, body } = await request(app).get('/memories');
expect(status).toBe(401);
expect(body).toEqual(errorDto.unauthorized);
});
});
describe('POST /memories', () => {
it('should require authentication', async () => {
const { status, body } = await request(app).post('/memories');
expect(status).toBe(401);
expect(body).toEqual(errorDto.unauthorized);
});
it('should validate data when type is on this day', async () => {
const { status, body } = await request(app)
.post('/memories')
.set('Authorization', `Bearer ${user.accessToken}`)
.send({
type: 'on_this_day',
data: {},
memoryAt: new Date(2021).toISOString(),
});
expect(status).toBe(400);
expect(body).toEqual(
errorDto.badRequest(['data.year must be a positive number', 'data.year must be an integer number']),
);
});
it('should create a new memory', async () => {
const { status, body } = await request(app)
.post('/memories')
.set('Authorization', `Bearer ${user.accessToken}`)
.send({
type: 'on_this_day',
data: { year: 2021 },
memoryAt: new Date(2021).toISOString(),
});
expect(status).toBe(201);
expect(body).toEqual({
id: expect.any(String),
type: 'on_this_day',
data: { year: 2021 },
createdAt: expect.any(String),
updatedAt: expect.any(String),
deletedAt: null,
seenAt: null,
isSaved: false,
memoryAt: expect.any(String),
ownerId: user.userId,
assets: [],
});
});
it('should create a new memory (with assets)', async () => {
const { status, body } = await request(app)
.post('/memories')
.set('Authorization', `Bearer ${user.accessToken}`)
.send({
type: 'on_this_day',
data: { year: 2021 },
memoryAt: new Date(2021).toISOString(),
assetIds: [userAsset1.id, userAsset2.id],
});
expect(status).toBe(201);
expect(body).toMatchObject({
id: expect.any(String),
assets: expect.arrayContaining([
expect.objectContaining({ id: userAsset1.id }),
expect.objectContaining({ id: userAsset2.id }),
]),
});
expect(body.assets).toHaveLength(2);
});
it('should create a new memory and ignore assets the user does not have access to', async () => {
const { status, body } = await request(app)
.post('/memories')
.set('Authorization', `Bearer ${user.accessToken}`)
.send({
type: 'on_this_day',
data: { year: 2021 },
memoryAt: new Date(2021).toISOString(),
assetIds: [userAsset1.id, adminAsset.id],
});
expect(status).toBe(201);
expect(body).toMatchObject({
id: expect.any(String),
assets: [expect.objectContaining({ id: userAsset1.id })],
});
expect(body.assets).toHaveLength(1);
});
});
describe('GET /memories/:id', () => {
it('should require authentication', async () => {
const { status, body } = await request(app).get(`/memories/${uuidDto.invalid}`);
expect(status).toBe(401);
expect(body).toEqual(errorDto.unauthorized);
});
it('should require a valid id', async () => {
const { status, body } = await request(app)
.get(`/memories/${uuidDto.invalid}`)
.set('Authorization', `Bearer ${user.accessToken}`);
expect(status).toBe(400);
expect(body).toEqual(errorDto.badRequest(['id must be a UUID']));
});
it('should require access', async () => {
const { status, body } = await request(app)
.get(`/memories/${userMemory.id}`)
.set('Authorization', `Bearer ${admin.accessToken}`);
expect(status).toBe(400);
expect(body).toEqual(errorDto.noPermission);
});
it('should get the memory', async () => {
const { status, body } = await request(app)
.get(`/memories/${userMemory.id}`)
.set('Authorization', `Bearer ${user.accessToken}`);
expect(status).toBe(200);
expect(body).toMatchObject({ id: userMemory.id });
});
});
describe('PUT /memories/:id', () => {
it('should require authentication', async () => {
const { status, body } = await request(app).put(`/memories/${uuidDto.invalid}`).send({ isSaved: true });
expect(status).toBe(401);
expect(body).toEqual(errorDto.unauthorized);
});
it('should require a valid id', async () => {
const { status, body } = await request(app)
.put(`/memories/${uuidDto.invalid}`)
.send({ isSaved: true })
.set('Authorization', `Bearer ${user.accessToken}`);
expect(status).toBe(400);
expect(body).toEqual(errorDto.badRequest(['id must be a UUID']));
});
it('should require access', async () => {
const { status, body } = await request(app)
.put(`/memories/${userMemory.id}`)
.send({ isSaved: true })
.set('Authorization', `Bearer ${admin.accessToken}`);
expect(status).toBe(400);
expect(body).toEqual(errorDto.noPermission);
});
it('should update the memory', async () => {
const before = await getMemory({ id: userMemory.id }, { headers: asBearerAuth(user.accessToken) });
expect(before.isSaved).toBe(false);
const { status, body } = await request(app)
.put(`/memories/${userMemory.id}`)
.send({ isSaved: true })
.set('Authorization', `Bearer ${user.accessToken}`);
expect(status).toBe(200);
expect(body).toMatchObject({
id: userMemory.id,
isSaved: true,
});
});
});
describe('PUT /memories/:id/assets', () => {
it('should require authentication', async () => {
const { status, body } = await request(app)
.put(`/memories/${userMemory.id}/assets`)
.send({ ids: [userAsset1.id] });
expect(status).toBe(401);
expect(body).toEqual(errorDto.unauthorized);
});
it('should require a valid id', async () => {
const { status, body } = await request(app)
.put(`/memories/${uuidDto.invalid}/assets`)
.send({ ids: [userAsset1.id] })
.set('Authorization', `Bearer ${user.accessToken}`);
expect(status).toBe(400);
expect(body).toEqual(errorDto.badRequest(['id must be a UUID']));
});
it('should require access', async () => {
const { status, body } = await request(app)
.put(`/memories/${userMemory.id}/assets`)
.send({ ids: [userAsset1.id] })
.set('Authorization', `Bearer ${admin.accessToken}`);
expect(status).toBe(400);
expect(body).toEqual(errorDto.noPermission);
});
it('should require a valid asset id', async () => {
const { status, body } = await request(app)
.put(`/memories/${userMemory.id}/assets`)
.send({ ids: [uuidDto.invalid] })
.set('Authorization', `Bearer ${user.accessToken}`);
expect(status).toBe(400);
expect(body).toEqual(errorDto.badRequest(['each value in ids must be a UUID']));
});
it('should require asset access', async () => {
const { status, body } = await request(app)
.put(`/memories/${userMemory.id}/assets`)
.send({ ids: [adminAsset.id] })
.set('Authorization', `Bearer ${user.accessToken}`);
expect(status).toBe(200);
expect(body).toHaveLength(1);
expect(body[0]).toEqual({
id: adminAsset.id,
success: false,
error: 'no_permission',
});
});
it('should add assets to the memory', async () => {
const { status, body } = await request(app)
.put(`/memories/${userMemory.id}/assets`)
.send({ ids: [userAsset1.id] })
.set('Authorization', `Bearer ${user.accessToken}`);
expect(status).toBe(200);
expect(body).toHaveLength(1);
expect(body[0]).toEqual({ id: userAsset1.id, success: true });
});
});
describe('DELETE /memories/:id/assets', () => {
it('should require authentication', async () => {
const { status, body } = await request(app)
.delete(`/memories/${userMemory.id}/assets`)
.send({ ids: [userAsset1.id] });
expect(status).toBe(401);
expect(body).toEqual(errorDto.unauthorized);
});
it('should require a valid id', async () => {
const { status, body } = await request(app)
.delete(`/memories/${uuidDto.invalid}/assets`)
.send({ ids: [userAsset1.id] })
.set('Authorization', `Bearer ${user.accessToken}`);
expect(status).toBe(400);
expect(body).toEqual(errorDto.badRequest(['id must be a UUID']));
});
it('should require access', async () => {
const { status, body } = await request(app)
.delete(`/memories/${userMemory.id}/assets`)
.send({ ids: [userAsset1.id] })
.set('Authorization', `Bearer ${admin.accessToken}`);
expect(status).toBe(400);
expect(body).toEqual(errorDto.noPermission);
});
it('should require a valid asset id', async () => {
const { status, body } = await request(app)
.delete(`/memories/${userMemory.id}/assets`)
.send({ ids: [uuidDto.invalid] })
.set('Authorization', `Bearer ${user.accessToken}`);
expect(status).toBe(400);
expect(body).toEqual(errorDto.badRequest(['each value in ids must be a UUID']));
});
it('should only remove assets in the memory', async () => {
const { status, body } = await request(app)
.delete(`/memories/${userMemory.id}/assets`)
.send({ ids: [adminAsset.id] })
.set('Authorization', `Bearer ${user.accessToken}`);
expect(status).toBe(200);
expect(body).toHaveLength(1);
expect(body[0]).toEqual({
id: adminAsset.id,
success: false,
error: 'not_found',
});
});
it('should remove assets from the memory', async () => {
const { status, body } = await request(app)
.delete(`/memories/${userMemory.id}/assets`)
.send({ ids: [userAsset1.id] })
.set('Authorization', `Bearer ${user.accessToken}`);
expect(status).toBe(200);
expect(body).toHaveLength(1);
expect(body[0]).toEqual({ id: userAsset1.id, success: true });
});
});
describe('DELETE /memories/:id', () => {
it('should require authentication', async () => {
const { status, body } = await request(app).delete(`/memories/${uuidDto.invalid}`);
expect(status).toBe(401);
expect(body).toEqual(errorDto.unauthorized);
});
it('should require a valid id', async () => {
const { status, body } = await request(app)
.delete(`/memories/${uuidDto.invalid}`)
.set('Authorization', `Bearer ${user.accessToken}`);
expect(status).toBe(400);
expect(body).toEqual(errorDto.badRequest(['id must be a UUID']));
});
it('should require access', async () => {
const { status, body } = await request(app)
.delete(`/memories/${userMemory.id}`)
.set('Authorization', `Bearer ${admin.accessToken}`);
expect(status).toBe(400);
expect(body).toEqual(errorDto.noPermission);
});
it('should delete the memory', async () => {
const { status } = await request(app)
.delete(`/memories/${userMemory.id}`)
.send({ isSaved: true })
.set('Authorization', `Bearer ${user.accessToken}`);
expect(status).toBe(204);
});
});
});

View File

@ -133,7 +133,7 @@ describe('/search', () => {
assetLast = assets.at(-1) as AssetFileUploadResponseDto;
await deleteAssets({ assetBulkDeleteDto: { ids: [assetSilver.id] } }, { headers: asBearerAuth(admin.accessToken) });
});
}, 30_000);
afterAll(async () => {
utils.disconnectWebsocket(websocket);

View File

@ -64,33 +64,33 @@ trio = ["trio (>=0.23)"]
[[package]]
name = "black"
version = "24.2.0"
version = "24.3.0"
description = "The uncompromising code formatter."
optional = false
python-versions = ">=3.8"
files = [
{file = "black-24.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6981eae48b3b33399c8757036c7f5d48a535b962a7c2310d19361edeef64ce29"},
{file = "black-24.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d533d5e3259720fdbc1b37444491b024003e012c5173f7d06825a77508085430"},
{file = "black-24.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:61a0391772490ddfb8a693c067df1ef5227257e72b0e4108482b8d41b5aee13f"},
{file = "black-24.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:992e451b04667116680cb88f63449267c13e1ad134f30087dec8527242e9862a"},
{file = "black-24.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:163baf4ef40e6897a2a9b83890e59141cc8c2a98f2dda5080dc15c00ee1e62cd"},
{file = "black-24.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e37c99f89929af50ffaf912454b3e3b47fd64109659026b678c091a4cd450fb2"},
{file = "black-24.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f9de21bafcba9683853f6c96c2d515e364aee631b178eaa5145fc1c61a3cc92"},
{file = "black-24.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:9db528bccb9e8e20c08e716b3b09c6bdd64da0dd129b11e160bf082d4642ac23"},
{file = "black-24.2.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d84f29eb3ee44859052073b7636533ec995bd0f64e2fb43aeceefc70090e752b"},
{file = "black-24.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1e08fb9a15c914b81dd734ddd7fb10513016e5ce7e6704bdd5e1251ceee51ac9"},
{file = "black-24.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:810d445ae6069ce64030c78ff6127cd9cd178a9ac3361435708b907d8a04c693"},
{file = "black-24.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:ba15742a13de85e9b8f3239c8f807723991fbfae24bad92d34a2b12e81904982"},
{file = "black-24.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7e53a8c630f71db01b28cd9602a1ada68c937cbf2c333e6ed041390d6968faf4"},
{file = "black-24.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:93601c2deb321b4bad8f95df408e3fb3943d85012dddb6121336b8e24a0d1218"},
{file = "black-24.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0057f800de6acc4407fe75bb147b0c2b5cbb7c3ed110d3e5999cd01184d53b0"},
{file = "black-24.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:faf2ee02e6612577ba0181f4347bcbcf591eb122f7841ae5ba233d12c39dcb4d"},
{file = "black-24.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:057c3dc602eaa6fdc451069bd027a1b2635028b575a6c3acfd63193ced20d9c8"},
{file = "black-24.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:08654d0797e65f2423f850fc8e16a0ce50925f9337fb4a4a176a7aa4026e63f8"},
{file = "black-24.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ca610d29415ee1a30a3f30fab7a8f4144e9d34c89a235d81292a1edb2b55f540"},
{file = "black-24.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:4dd76e9468d5536abd40ffbc7a247f83b2324f0c050556d9c371c2b9a9a95e31"},
{file = "black-24.2.0-py3-none-any.whl", hash = "sha256:e8a6ae970537e67830776488bca52000eaa37fa63b9988e8c487458d9cd5ace6"},
{file = "black-24.2.0.tar.gz", hash = "sha256:bce4f25c27c3435e4dace4815bcb2008b87e167e3bf4ee47ccdc5ce906eb4894"},
{file = "black-24.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7d5e026f8da0322b5662fa7a8e752b3fa2dac1c1cbc213c3d7ff9bdd0ab12395"},
{file = "black-24.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9f50ea1132e2189d8dff0115ab75b65590a3e97de1e143795adb4ce317934995"},
{file = "black-24.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e2af80566f43c85f5797365077fb64a393861a3730bd110971ab7a0c94e873e7"},
{file = "black-24.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:4be5bb28e090456adfc1255e03967fb67ca846a03be7aadf6249096100ee32d0"},
{file = "black-24.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4f1373a7808a8f135b774039f61d59e4be7eb56b2513d3d2f02a8b9365b8a8a9"},
{file = "black-24.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:aadf7a02d947936ee418777e0247ea114f78aff0d0959461057cae8a04f20597"},
{file = "black-24.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65c02e4ea2ae09d16314d30912a58ada9a5c4fdfedf9512d23326128ac08ac3d"},
{file = "black-24.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:bf21b7b230718a5f08bd32d5e4f1db7fc8788345c8aea1d155fc17852b3410f5"},
{file = "black-24.3.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:2818cf72dfd5d289e48f37ccfa08b460bf469e67fb7c4abb07edc2e9f16fb63f"},
{file = "black-24.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4acf672def7eb1725f41f38bf6bf425c8237248bb0804faa3965c036f7672d11"},
{file = "black-24.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c7ed6668cbbfcd231fa0dc1b137d3e40c04c7f786e626b405c62bcd5db5857e4"},
{file = "black-24.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:56f52cfbd3dabe2798d76dbdd299faa046a901041faf2cf33288bc4e6dae57b5"},
{file = "black-24.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:79dcf34b33e38ed1b17434693763301d7ccbd1c5860674a8f871bd15139e7837"},
{file = "black-24.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e19cb1c6365fd6dc38a6eae2dcb691d7d83935c10215aef8e6c38edee3f77abd"},
{file = "black-24.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65b76c275e4c1c5ce6e9870911384bff5ca31ab63d19c76811cb1fb162678213"},
{file = "black-24.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:b5991d523eee14756f3c8d5df5231550ae8993e2286b8014e2fdea7156ed0959"},
{file = "black-24.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c45f8dff244b3c431b36e3224b6be4a127c6aca780853574c00faf99258041eb"},
{file = "black-24.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6905238a754ceb7788a73f02b45637d820b2f5478b20fec82ea865e4f5d4d9f7"},
{file = "black-24.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7de8d330763c66663661a1ffd432274a2f92f07feeddd89ffd085b5744f85e7"},
{file = "black-24.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:7bb041dca0d784697af4646d3b62ba4a6b028276ae878e53f6b4f74ddd6db99f"},
{file = "black-24.3.0-py3-none-any.whl", hash = "sha256:41622020d7120e01d377f74249e677039d20e6344ff5851de8a10f11f513bf93"},
{file = "black-24.3.0.tar.gz", hash = "sha256:a0c9c4a0771afc6919578cec71ce82a3e31e054904e7197deacbc9382671c41f"},
]
[package.dependencies]
@ -2110,61 +2110,62 @@ numpy = [
[[package]]
name = "orjson"
version = "3.9.15"
version = "3.10.0"
description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy"
optional = false
python-versions = ">=3.8"
files = [
{file = "orjson-3.9.15-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:d61f7ce4727a9fa7680cd6f3986b0e2c732639f46a5e0156e550e35258aa313a"},
{file = "orjson-3.9.15-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4feeb41882e8aa17634b589533baafdceb387e01e117b1ec65534ec724023d04"},
{file = "orjson-3.9.15-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fbbeb3c9b2edb5fd044b2a070f127a0ac456ffd079cb82746fc84af01ef021a4"},
{file = "orjson-3.9.15-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b66bcc5670e8a6b78f0313bcb74774c8291f6f8aeef10fe70e910b8040f3ab75"},
{file = "orjson-3.9.15-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2973474811db7b35c30248d1129c64fd2bdf40d57d84beed2a9a379a6f57d0ab"},
{file = "orjson-3.9.15-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fe41b6f72f52d3da4db524c8653e46243c8c92df826ab5ffaece2dba9cccd58"},
{file = "orjson-3.9.15-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4228aace81781cc9d05a3ec3a6d2673a1ad0d8725b4e915f1089803e9efd2b99"},
{file = "orjson-3.9.15-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:6f7b65bfaf69493c73423ce9db66cfe9138b2f9ef62897486417a8fcb0a92bfe"},
{file = "orjson-3.9.15-cp310-none-win32.whl", hash = "sha256:2d99e3c4c13a7b0fb3792cc04c2829c9db07838fb6973e578b85c1745e7d0ce7"},
{file = "orjson-3.9.15-cp310-none-win_amd64.whl", hash = "sha256:b725da33e6e58e4a5d27958568484aa766e825e93aa20c26c91168be58e08cbb"},
{file = "orjson-3.9.15-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:c8e8fe01e435005d4421f183038fc70ca85d2c1e490f51fb972db92af6e047c2"},
{file = "orjson-3.9.15-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:87f1097acb569dde17f246faa268759a71a2cb8c96dd392cd25c668b104cad2f"},
{file = "orjson-3.9.15-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ff0f9913d82e1d1fadbd976424c316fbc4d9c525c81d047bbdd16bd27dd98cfc"},
{file = "orjson-3.9.15-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8055ec598605b0077e29652ccfe9372247474375e0e3f5775c91d9434e12d6b1"},
{file = "orjson-3.9.15-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d6768a327ea1ba44c9114dba5fdda4a214bdb70129065cd0807eb5f010bfcbb5"},
{file = "orjson-3.9.15-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:12365576039b1a5a47df01aadb353b68223da413e2e7f98c02403061aad34bde"},
{file = "orjson-3.9.15-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:71c6b009d431b3839d7c14c3af86788b3cfac41e969e3e1c22f8a6ea13139404"},
{file = "orjson-3.9.15-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e18668f1bd39e69b7fed19fa7cd1cd110a121ec25439328b5c89934e6d30d357"},
{file = "orjson-3.9.15-cp311-none-win32.whl", hash = "sha256:62482873e0289cf7313461009bf62ac8b2e54bc6f00c6fabcde785709231a5d7"},
{file = "orjson-3.9.15-cp311-none-win_amd64.whl", hash = "sha256:b3d336ed75d17c7b1af233a6561cf421dee41d9204aa3cfcc6c9c65cd5bb69a8"},
{file = "orjson-3.9.15-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:82425dd5c7bd3adfe4e94c78e27e2fa02971750c2b7ffba648b0f5d5cc016a73"},
{file = "orjson-3.9.15-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c51378d4a8255b2e7c1e5cc430644f0939539deddfa77f6fac7b56a9784160a"},
{file = "orjson-3.9.15-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6ae4e06be04dc00618247c4ae3f7c3e561d5bc19ab6941427f6d3722a0875ef7"},
{file = "orjson-3.9.15-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bcef128f970bb63ecf9a65f7beafd9b55e3aaf0efc271a4154050fc15cdb386e"},
{file = "orjson-3.9.15-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b72758f3ffc36ca566ba98a8e7f4f373b6c17c646ff8ad9b21ad10c29186f00d"},
{file = "orjson-3.9.15-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10c57bc7b946cf2efa67ac55766e41764b66d40cbd9489041e637c1304400494"},
{file = "orjson-3.9.15-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:946c3a1ef25338e78107fba746f299f926db408d34553b4754e90a7de1d44068"},
{file = "orjson-3.9.15-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2f256d03957075fcb5923410058982aea85455d035607486ccb847f095442bda"},
{file = "orjson-3.9.15-cp312-none-win_amd64.whl", hash = "sha256:5bb399e1b49db120653a31463b4a7b27cf2fbfe60469546baf681d1b39f4edf2"},
{file = "orjson-3.9.15-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:b17f0f14a9c0ba55ff6279a922d1932e24b13fc218a3e968ecdbf791b3682b25"},
{file = "orjson-3.9.15-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7f6cbd8e6e446fb7e4ed5bac4661a29e43f38aeecbf60c4b900b825a353276a1"},
{file = "orjson-3.9.15-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:76bc6356d07c1d9f4b782813094d0caf1703b729d876ab6a676f3aaa9a47e37c"},
{file = "orjson-3.9.15-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fdfa97090e2d6f73dced247a2f2d8004ac6449df6568f30e7fa1a045767c69a6"},
{file = "orjson-3.9.15-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7413070a3e927e4207d00bd65f42d1b780fb0d32d7b1d951f6dc6ade318e1b5a"},
{file = "orjson-3.9.15-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9cf1596680ac1f01839dba32d496136bdd5d8ffb858c280fa82bbfeb173bdd40"},
{file = "orjson-3.9.15-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:809d653c155e2cc4fd39ad69c08fdff7f4016c355ae4b88905219d3579e31eb7"},
{file = "orjson-3.9.15-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:920fa5a0c5175ab14b9c78f6f820b75804fb4984423ee4c4f1e6d748f8b22bc1"},
{file = "orjson-3.9.15-cp38-none-win32.whl", hash = "sha256:2b5c0f532905e60cf22a511120e3719b85d9c25d0e1c2a8abb20c4dede3b05a5"},
{file = "orjson-3.9.15-cp38-none-win_amd64.whl", hash = "sha256:67384f588f7f8daf040114337d34a5188346e3fae6c38b6a19a2fe8c663a2f9b"},
{file = "orjson-3.9.15-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:6fc2fe4647927070df3d93f561d7e588a38865ea0040027662e3e541d592811e"},
{file = "orjson-3.9.15-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34cbcd216e7af5270f2ffa63a963346845eb71e174ea530867b7443892d77180"},
{file = "orjson-3.9.15-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f541587f5c558abd93cb0de491ce99a9ef8d1ae29dd6ab4dbb5a13281ae04cbd"},
{file = "orjson-3.9.15-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:92255879280ef9c3c0bcb327c5a1b8ed694c290d61a6a532458264f887f052cb"},
{file = "orjson-3.9.15-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:05a1f57fb601c426635fcae9ddbe90dfc1ed42245eb4c75e4960440cac667262"},
{file = "orjson-3.9.15-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ede0bde16cc6e9b96633df1631fbcd66491d1063667f260a4f2386a098393790"},
{file = "orjson-3.9.15-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:e88b97ef13910e5f87bcbc4dd7979a7de9ba8702b54d3204ac587e83639c0c2b"},
{file = "orjson-3.9.15-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:57d5d8cf9c27f7ef6bc56a5925c7fbc76b61288ab674eb352c26ac780caa5b10"},
{file = "orjson-3.9.15-cp39-none-win32.whl", hash = "sha256:001f4eb0ecd8e9ebd295722d0cbedf0748680fb9998d3993abaed2f40587257a"},
{file = "orjson-3.9.15-cp39-none-win_amd64.whl", hash = "sha256:ea0b183a5fe6b2b45f3b854b0d19c4e932d6f5934ae1f723b07cf9560edd4ec7"},
{file = "orjson-3.9.15.tar.gz", hash = "sha256:95cae920959d772f30ab36d3b25f83bb0f3be671e986c72ce22f8fa700dae061"},
{file = "orjson-3.10.0-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:47af5d4b850a2d1328660661f0881b67fdbe712aea905dadd413bdea6f792c33"},
{file = "orjson-3.10.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c90681333619d78360d13840c7235fdaf01b2b129cb3a4f1647783b1971542b6"},
{file = "orjson-3.10.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:400c5b7c4222cb27b5059adf1fb12302eebcabf1978f33d0824aa5277ca899bd"},
{file = "orjson-3.10.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5dcb32e949eae80fb335e63b90e5808b4b0f64e31476b3777707416b41682db5"},
{file = "orjson-3.10.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aa7d507c7493252c0a0264b5cc7e20fa2f8622b8a83b04d819b5ce32c97cf57b"},
{file = "orjson-3.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e286a51def6626f1e0cc134ba2067dcf14f7f4b9550f6dd4535fd9d79000040b"},
{file = "orjson-3.10.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:8acd4b82a5f3a3ec8b1dc83452941d22b4711964c34727eb1e65449eead353ca"},
{file = "orjson-3.10.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:30707e646080dd3c791f22ce7e4a2fc2438765408547c10510f1f690bd336217"},
{file = "orjson-3.10.0-cp310-none-win32.whl", hash = "sha256:115498c4ad34188dcb73464e8dc80e490a3e5e88a925907b6fedcf20e545001a"},
{file = "orjson-3.10.0-cp310-none-win_amd64.whl", hash = "sha256:6735dd4a5a7b6df00a87d1d7a02b84b54d215fb7adac50dd24da5997ffb4798d"},
{file = "orjson-3.10.0-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9587053e0cefc284e4d1cd113c34468b7d3f17666d22b185ea654f0775316a26"},
{file = "orjson-3.10.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bef1050b1bdc9ea6c0d08468e3e61c9386723633b397e50b82fda37b3563d72"},
{file = "orjson-3.10.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d16c6963ddf3b28c0d461641517cd312ad6b3cf303d8b87d5ef3fa59d6844337"},
{file = "orjson-3.10.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4251964db47ef090c462a2d909f16c7c7d5fe68e341dabce6702879ec26d1134"},
{file = "orjson-3.10.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:73bbbdc43d520204d9ef0817ac03fa49c103c7f9ea94f410d2950755be2c349c"},
{file = "orjson-3.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:414e5293b82373606acf0d66313aecb52d9c8c2404b1900683eb32c3d042dbd7"},
{file = "orjson-3.10.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:feaed5bb09877dc27ed0d37f037ddef6cb76d19aa34b108db270d27d3d2ef747"},
{file = "orjson-3.10.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5127478260db640323cea131ee88541cb1a9fbce051f0b22fa2f0892f44da302"},
{file = "orjson-3.10.0-cp311-none-win32.whl", hash = "sha256:b98345529bafe3c06c09996b303fc0a21961820d634409b8639bc16bd4f21b63"},
{file = "orjson-3.10.0-cp311-none-win_amd64.whl", hash = "sha256:658ca5cee3379dd3d37dbacd43d42c1b4feee99a29d847ef27a1cb18abdfb23f"},
{file = "orjson-3.10.0-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:4329c1d24fd130ee377e32a72dc54a3c251e6706fccd9a2ecb91b3606fddd998"},
{file = "orjson-3.10.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ef0f19fdfb6553342b1882f438afd53c7cb7aea57894c4490c43e4431739c700"},
{file = "orjson-3.10.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c4f60db24161534764277f798ef53b9d3063092f6d23f8f962b4a97edfa997a0"},
{file = "orjson-3.10.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1de3fd5c7b208d836f8ecb4526995f0d5877153a4f6f12f3e9bf11e49357de98"},
{file = "orjson-3.10.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f93e33f67729d460a177ba285002035d3f11425ed3cebac5f6ded4ef36b28344"},
{file = "orjson-3.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:237ba922aef472761acd697eef77fef4831ab769a42e83c04ac91e9f9e08fa0e"},
{file = "orjson-3.10.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:98c1bfc6a9bec52bc8f0ab9b86cc0874b0299fccef3562b793c1576cf3abb570"},
{file = "orjson-3.10.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:30d795a24be16c03dca0c35ca8f9c8eaaa51e3342f2c162d327bd0225118794a"},
{file = "orjson-3.10.0-cp312-none-win32.whl", hash = "sha256:6a3f53dc650bc860eb26ec293dfb489b2f6ae1cbfc409a127b01229980e372f7"},
{file = "orjson-3.10.0-cp312-none-win_amd64.whl", hash = "sha256:983db1f87c371dc6ffc52931eb75f9fe17dc621273e43ce67bee407d3e5476e9"},
{file = "orjson-3.10.0-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9a667769a96a72ca67237224a36faf57db0c82ab07d09c3aafc6f956196cfa1b"},
{file = "orjson-3.10.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ade1e21dfde1d37feee8cf6464c20a2f41fa46c8bcd5251e761903e46102dc6b"},
{file = "orjson-3.10.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:23c12bb4ced1c3308eff7ba5c63ef8f0edb3e4c43c026440247dd6c1c61cea4b"},
{file = "orjson-3.10.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b2d014cf8d4dc9f03fc9f870de191a49a03b1bcda51f2a957943fb9fafe55aac"},
{file = "orjson-3.10.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eadecaa16d9783affca33597781328e4981b048615c2ddc31c47a51b833d6319"},
{file = "orjson-3.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cd583341218826f48bd7c6ebf3310b4126216920853cbc471e8dbeaf07b0b80e"},
{file = "orjson-3.10.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:90bfc137c75c31d32308fd61951d424424426ddc39a40e367704661a9ee97095"},
{file = "orjson-3.10.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:13b5d3c795b09a466ec9fcf0bd3ad7b85467d91a60113885df7b8d639a9d374b"},
{file = "orjson-3.10.0-cp38-none-win32.whl", hash = "sha256:5d42768db6f2ce0162544845facb7c081e9364a5eb6d2ef06cd17f6050b048d8"},
{file = "orjson-3.10.0-cp38-none-win_amd64.whl", hash = "sha256:33e6655a2542195d6fd9f850b428926559dee382f7a862dae92ca97fea03a5ad"},
{file = "orjson-3.10.0-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:4050920e831a49d8782a1720d3ca2f1c49b150953667eed6e5d63a62e80f46a2"},
{file = "orjson-3.10.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1897aa25a944cec774ce4a0e1c8e98fb50523e97366c637b7d0cddabc42e6643"},
{file = "orjson-3.10.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9bf565a69e0082ea348c5657401acec3cbbb31564d89afebaee884614fba36b4"},
{file = "orjson-3.10.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b6ebc17cfbbf741f5c1a888d1854354536f63d84bee537c9a7c0335791bb9009"},
{file = "orjson-3.10.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d2817877d0b69f78f146ab305c5975d0618df41acf8811249ee64231f5953fee"},
{file = "orjson-3.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:57d017863ec8aa4589be30a328dacd13c2dc49de1c170bc8d8c8a98ece0f2925"},
{file = "orjson-3.10.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:22c2f7e377ac757bd3476ecb7480c8ed79d98ef89648f0176deb1da5cd014eb7"},
{file = "orjson-3.10.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:e62ba42bfe64c60c1bc84799944f80704e996592c6b9e14789c8e2a303279912"},
{file = "orjson-3.10.0-cp39-none-win32.whl", hash = "sha256:60c0b1bdbccd959ebd1575bd0147bd5e10fc76f26216188be4a36b691c937077"},
{file = "orjson-3.10.0-cp39-none-win_amd64.whl", hash = "sha256:175a41500ebb2fdf320bf78e8b9a75a1279525b62ba400b2b2444e274c2c8bee"},
{file = "orjson-3.10.0.tar.gz", hash = "sha256:ba4d8cac5f2e2cff36bea6b6481cdb92b38c202bcec603d6f5ff91960595a1ed"},
]
[[package]]

View File

@ -2,6 +2,7 @@ import 'package:flutter/foundation.dart';
import 'package:immich_mobile/shared/models/asset.dart';
import 'package:immich_mobile/shared/models/store.dart';
import 'package:immich_mobile/shared/models/user.dart';
import 'package:immich_mobile/utils/datetime_comparison.dart';
import 'package:isar/isar.dart';
import 'package:openapi/api.dart';
import 'package:photo_manager/photo_manager.dart';
@ -72,21 +73,18 @@ class Album {
@override
bool operator ==(other) {
if (other is! Album) return false;
final lastModifiedAssetTimestampIsSetAndEqual =
lastModifiedAssetTimestamp != null &&
other.lastModifiedAssetTimestamp != null
? lastModifiedAssetTimestamp!
.isAtSameMomentAs(other.lastModifiedAssetTimestamp!)
: true;
return id == other.id &&
remoteId == other.remoteId &&
localId == other.localId &&
name == other.name &&
createdAt.isAtSameMomentAs(other.createdAt) &&
modifiedAt.isAtSameMomentAs(other.modifiedAt) &&
lastModifiedAssetTimestampIsSetAndEqual &&
isAtSameMomentAs(startDate, other.startDate) &&
isAtSameMomentAs(endDate, other.endDate) &&
isAtSameMomentAs(
lastModifiedAssetTimestamp,
other.lastModifiedAssetTimestamp,
) &&
shared == other.shared &&
activityEnabled == other.activityEnabled &&
owner.value == other.owner.value &&
@ -104,6 +102,8 @@ class Album {
name.hashCode ^
createdAt.hashCode ^
modifiedAt.hashCode ^
startDate.hashCode ^
endDate.hashCode ^
lastModifiedAssetTimestamp.hashCode ^
shared.hashCode ^
activityEnabled.hashCode ^

View File

@ -12,6 +12,7 @@ import 'package:immich_mobile/shared/providers/db.provider.dart';
import 'package:immich_mobile/shared/services/hash.service.dart';
import 'package:immich_mobile/utils/async_mutex.dart';
import 'package:immich_mobile/extensions/collection_extensions.dart';
import 'package:immich_mobile/utils/datetime_comparison.dart';
import 'package:immich_mobile/utils/diff.dart';
import 'package:isar/isar.dart';
import 'package:logging/logging.dart';
@ -343,8 +344,13 @@ class SyncService {
album.name = dto.albumName;
album.shared = dto.shared;
album.createdAt = dto.createdAt;
album.modifiedAt = dto.updatedAt;
album.startDate = dto.startDate;
album.endDate = dto.endDate;
album.lastModifiedAssetTimestamp = originalDto.lastModifiedAssetTimestamp;
album.shared = dto.shared;
album.activityEnabled = dto.isActivityEnabled;
if (album.thumbnail.value?.remoteId != dto.albumThumbnailAssetId) {
album.thumbnail.value = await _db.assets
.where()
@ -863,12 +869,10 @@ bool _hasAlbumResponseDtoChanged(AlbumResponseDto dto, Album a) {
dto.shared != a.shared ||
dto.sharedUsers.length != a.sharedUsers.length ||
!dto.updatedAt.isAtSameMomentAs(a.modifiedAt) ||
(dto.lastModifiedAssetTimestamp == null &&
a.lastModifiedAssetTimestamp != null) ||
(dto.lastModifiedAssetTimestamp != null &&
a.lastModifiedAssetTimestamp == null) ||
(dto.lastModifiedAssetTimestamp != null &&
a.lastModifiedAssetTimestamp != null &&
!dto.lastModifiedAssetTimestamp!
.isAtSameMomentAs(a.lastModifiedAssetTimestamp!));
!isAtSameMomentAs(dto.startDate, a.startDate) ||
!isAtSameMomentAs(dto.endDate, a.endDate) ||
!isAtSameMomentAs(
dto.lastModifiedAssetTimestamp,
a.lastModifiedAssetTimestamp,
);
}

View File

@ -0,0 +1,3 @@
bool isAtSameMomentAs(DateTime? a, DateTime? b) =>
(a == null && b == null) ||
((a != null && b != null) && a.isAtSameMomentAs(b));

View File

@ -72,6 +72,7 @@ doc/FileChecksumResponseDto.md
doc/FileReportDto.md
doc/FileReportFixDto.md
doc/FileReportItemDto.md
doc/ImageFormat.md
doc/JobApi.md
doc/JobCommand.md
doc/JobCommandDto.md
@ -89,7 +90,12 @@ doc/LoginResponseDto.md
doc/LogoutResponseDto.md
doc/MapMarkerResponseDto.md
doc/MapTheme.md
doc/MemoryApi.md
doc/MemoryCreateDto.md
doc/MemoryLaneResponseDto.md
doc/MemoryResponseDto.md
doc/MemoryType.md
doc/MemoryUpdateDto.md
doc/MergePersonDto.md
doc/MetadataSearchDto.md
doc/ModelType.md
@ -97,6 +103,7 @@ doc/OAuthApi.md
doc/OAuthAuthorizeResponseDto.md
doc/OAuthCallbackDto.md
doc/OAuthConfigDto.md
doc/OnThisDayDto.md
doc/PartnerApi.md
doc/PartnerResponseDto.md
doc/PathEntityType.md
@ -145,6 +152,7 @@ doc/SmartSearchDto.md
doc/SystemConfigApi.md
doc/SystemConfigDto.md
doc/SystemConfigFFmpegDto.md
doc/SystemConfigImageDto.md
doc/SystemConfigJobDto.md
doc/SystemConfigLibraryDto.md
doc/SystemConfigLibraryScanDto.md
@ -160,7 +168,6 @@ doc/SystemConfigServerDto.md
doc/SystemConfigStorageTemplateDto.md
doc/SystemConfigTemplateStorageOptionDto.md
doc/SystemConfigThemeDto.md
doc/SystemConfigThumbnailDto.md
doc/SystemConfigTrashDto.md
doc/SystemConfigUserDto.md
doc/TagApi.md
@ -204,6 +211,7 @@ lib/api/download_api.dart
lib/api/face_api.dart
lib/api/job_api.dart
lib/api/library_api.dart
lib/api/memory_api.dart
lib/api/o_auth_api.dart
lib/api/partner_api.dart
lib/api/person_api.dart
@ -284,6 +292,7 @@ lib/model/file_checksum_response_dto.dart
lib/model/file_report_dto.dart
lib/model/file_report_fix_dto.dart
lib/model/file_report_item_dto.dart
lib/model/image_format.dart
lib/model/job_command.dart
lib/model/job_command_dto.dart
lib/model/job_counts_dto.dart
@ -299,13 +308,18 @@ lib/model/login_response_dto.dart
lib/model/logout_response_dto.dart
lib/model/map_marker_response_dto.dart
lib/model/map_theme.dart
lib/model/memory_create_dto.dart
lib/model/memory_lane_response_dto.dart
lib/model/memory_response_dto.dart
lib/model/memory_type.dart
lib/model/memory_update_dto.dart
lib/model/merge_person_dto.dart
lib/model/metadata_search_dto.dart
lib/model/model_type.dart
lib/model/o_auth_authorize_response_dto.dart
lib/model/o_auth_callback_dto.dart
lib/model/o_auth_config_dto.dart
lib/model/on_this_day_dto.dart
lib/model/partner_response_dto.dart
lib/model/path_entity_type.dart
lib/model/path_type.dart
@ -348,6 +362,7 @@ lib/model/smart_info_response_dto.dart
lib/model/smart_search_dto.dart
lib/model/system_config_dto.dart
lib/model/system_config_f_fmpeg_dto.dart
lib/model/system_config_image_dto.dart
lib/model/system_config_job_dto.dart
lib/model/system_config_library_dto.dart
lib/model/system_config_library_scan_dto.dart
@ -363,7 +378,6 @@ lib/model/system_config_server_dto.dart
lib/model/system_config_storage_template_dto.dart
lib/model/system_config_template_storage_option_dto.dart
lib/model/system_config_theme_dto.dart
lib/model/system_config_thumbnail_dto.dart
lib/model/system_config_trash_dto.dart
lib/model/system_config_user_dto.dart
lib/model/tag_response_dto.dart
@ -461,6 +475,7 @@ test/file_checksum_response_dto_test.dart
test/file_report_dto_test.dart
test/file_report_fix_dto_test.dart
test/file_report_item_dto_test.dart
test/image_format_test.dart
test/job_api_test.dart
test/job_command_dto_test.dart
test/job_command_test.dart
@ -478,7 +493,12 @@ test/login_response_dto_test.dart
test/logout_response_dto_test.dart
test/map_marker_response_dto_test.dart
test/map_theme_test.dart
test/memory_api_test.dart
test/memory_create_dto_test.dart
test/memory_lane_response_dto_test.dart
test/memory_response_dto_test.dart
test/memory_type_test.dart
test/memory_update_dto_test.dart
test/merge_person_dto_test.dart
test/metadata_search_dto_test.dart
test/model_type_test.dart
@ -486,6 +506,7 @@ test/o_auth_api_test.dart
test/o_auth_authorize_response_dto_test.dart
test/o_auth_callback_dto_test.dart
test/o_auth_config_dto_test.dart
test/on_this_day_dto_test.dart
test/partner_api_test.dart
test/partner_response_dto_test.dart
test/path_entity_type_test.dart
@ -534,6 +555,7 @@ test/smart_search_dto_test.dart
test/system_config_api_test.dart
test/system_config_dto_test.dart
test/system_config_f_fmpeg_dto_test.dart
test/system_config_image_dto_test.dart
test/system_config_job_dto_test.dart
test/system_config_library_dto_test.dart
test/system_config_library_scan_dto_test.dart
@ -549,7 +571,6 @@ test/system_config_server_dto_test.dart
test/system_config_storage_template_dto_test.dart
test/system_config_template_storage_option_dto_test.dart
test/system_config_theme_dto_test.dart
test/system_config_thumbnail_dto_test.dart
test/system_config_trash_dto_test.dart
test/system_config_user_dto_test.dart
test/tag_api_test.dart

View File

@ -140,6 +140,13 @@ Class | Method | HTTP request | Description
*LibraryApi* | [**scanLibrary**](doc//LibraryApi.md#scanlibrary) | **POST** /library/{id}/scan |
*LibraryApi* | [**updateLibrary**](doc//LibraryApi.md#updatelibrary) | **PUT** /library/{id} |
*LibraryApi* | [**validate**](doc//LibraryApi.md#validate) | **POST** /library/{id}/validate |
*MemoryApi* | [**addMemoryAssets**](doc//MemoryApi.md#addmemoryassets) | **PUT** /memories/{id}/assets |
*MemoryApi* | [**createMemory**](doc//MemoryApi.md#creatememory) | **POST** /memories |
*MemoryApi* | [**deleteMemory**](doc//MemoryApi.md#deletememory) | **DELETE** /memories/{id} |
*MemoryApi* | [**getMemory**](doc//MemoryApi.md#getmemory) | **GET** /memories/{id} |
*MemoryApi* | [**removeMemoryAssets**](doc//MemoryApi.md#removememoryassets) | **DELETE** /memories/{id}/assets |
*MemoryApi* | [**searchMemories**](doc//MemoryApi.md#searchmemories) | **GET** /memories |
*MemoryApi* | [**updateMemory**](doc//MemoryApi.md#updatememory) | **PUT** /memories/{id} |
*OAuthApi* | [**finishOAuth**](doc//OAuthApi.md#finishoauth) | **POST** /oauth/callback |
*OAuthApi* | [**linkOAuthAccount**](doc//OAuthApi.md#linkoauthaccount) | **POST** /oauth/link |
*OAuthApi* | [**redirectOAuthToMobile**](doc//OAuthApi.md#redirectoauthtomobile) | **GET** /oauth/mobile-redirect |
@ -277,6 +284,7 @@ Class | Method | HTTP request | Description
- [FileReportDto](doc//FileReportDto.md)
- [FileReportFixDto](doc//FileReportFixDto.md)
- [FileReportItemDto](doc//FileReportItemDto.md)
- [ImageFormat](doc//ImageFormat.md)
- [JobCommand](doc//JobCommand.md)
- [JobCommandDto](doc//JobCommandDto.md)
- [JobCountsDto](doc//JobCountsDto.md)
@ -292,13 +300,18 @@ Class | Method | HTTP request | Description
- [LogoutResponseDto](doc//LogoutResponseDto.md)
- [MapMarkerResponseDto](doc//MapMarkerResponseDto.md)
- [MapTheme](doc//MapTheme.md)
- [MemoryCreateDto](doc//MemoryCreateDto.md)
- [MemoryLaneResponseDto](doc//MemoryLaneResponseDto.md)
- [MemoryResponseDto](doc//MemoryResponseDto.md)
- [MemoryType](doc//MemoryType.md)
- [MemoryUpdateDto](doc//MemoryUpdateDto.md)
- [MergePersonDto](doc//MergePersonDto.md)
- [MetadataSearchDto](doc//MetadataSearchDto.md)
- [ModelType](doc//ModelType.md)
- [OAuthAuthorizeResponseDto](doc//OAuthAuthorizeResponseDto.md)
- [OAuthCallbackDto](doc//OAuthCallbackDto.md)
- [OAuthConfigDto](doc//OAuthConfigDto.md)
- [OnThisDayDto](doc//OnThisDayDto.md)
- [PartnerResponseDto](doc//PartnerResponseDto.md)
- [PathEntityType](doc//PathEntityType.md)
- [PathType](doc//PathType.md)
@ -341,6 +354,7 @@ Class | Method | HTTP request | Description
- [SmartSearchDto](doc//SmartSearchDto.md)
- [SystemConfigDto](doc//SystemConfigDto.md)
- [SystemConfigFFmpegDto](doc//SystemConfigFFmpegDto.md)
- [SystemConfigImageDto](doc//SystemConfigImageDto.md)
- [SystemConfigJobDto](doc//SystemConfigJobDto.md)
- [SystemConfigLibraryDto](doc//SystemConfigLibraryDto.md)
- [SystemConfigLibraryScanDto](doc//SystemConfigLibraryScanDto.md)
@ -356,7 +370,6 @@ Class | Method | HTTP request | Description
- [SystemConfigStorageTemplateDto](doc//SystemConfigStorageTemplateDto.md)
- [SystemConfigTemplateStorageOptionDto](doc//SystemConfigTemplateStorageOptionDto.md)
- [SystemConfigThemeDto](doc//SystemConfigThemeDto.md)
- [SystemConfigThumbnailDto](doc//SystemConfigThumbnailDto.md)
- [SystemConfigTrashDto](doc//SystemConfigTrashDto.md)
- [SystemConfigUserDto](doc//SystemConfigUserDto.md)
- [TagResponseDto](doc//TagResponseDto.md)

View File

@ -886,7 +886,7 @@ void (empty response body)
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **searchAssets**
> List<AssetResponseDto> searchAssets(checksum, city, country, createdAfter, createdBefore, deviceAssetId, deviceId, encodedVideoPath, id, isArchived, isEncoded, isExternal, isFavorite, isMotion, isNotInAlbum, isOffline, isReadOnly, isVisible, lensModel, libraryId, make, model, order, originalFileName, originalPath, page, personIds, resizePath, size, state, takenAfter, takenBefore, trashedAfter, trashedBefore, type, updatedAfter, updatedBefore, webpPath, withArchived, withDeleted, withExif, withPeople, withStacked)
> List<AssetResponseDto> searchAssets(checksum, city, country, createdAfter, createdBefore, deviceAssetId, deviceId, encodedVideoPath, id, isArchived, isEncoded, isExternal, isFavorite, isMotion, isNotInAlbum, isOffline, isReadOnly, isVisible, lensModel, libraryId, make, model, order, originalFileName, originalPath, page, personIds, previewPath, resizePath, size, state, takenAfter, takenBefore, thumbnailPath, trashedAfter, trashedBefore, type, updatedAfter, updatedBefore, webpPath, withArchived, withDeleted, withExif, withPeople, withStacked)
@ -936,11 +936,13 @@ final originalFileName = originalFileName_example; // String |
final originalPath = originalPath_example; // String |
final page = 8.14; // num |
final personIds = []; // List<String> |
final previewPath = previewPath_example; // String |
final resizePath = resizePath_example; // String |
final size = 8.14; // num |
final state = state_example; // String |
final takenAfter = 2013-10-20T19:20:30+01:00; // DateTime |
final takenBefore = 2013-10-20T19:20:30+01:00; // DateTime |
final thumbnailPath = thumbnailPath_example; // String |
final trashedAfter = 2013-10-20T19:20:30+01:00; // DateTime |
final trashedBefore = 2013-10-20T19:20:30+01:00; // DateTime |
final type = ; // AssetTypeEnum |
@ -954,7 +956,7 @@ final withPeople = true; // bool |
final withStacked = true; // bool |
try {
final result = api_instance.searchAssets(checksum, city, country, createdAfter, createdBefore, deviceAssetId, deviceId, encodedVideoPath, id, isArchived, isEncoded, isExternal, isFavorite, isMotion, isNotInAlbum, isOffline, isReadOnly, isVisible, lensModel, libraryId, make, model, order, originalFileName, originalPath, page, personIds, resizePath, size, state, takenAfter, takenBefore, trashedAfter, trashedBefore, type, updatedAfter, updatedBefore, webpPath, withArchived, withDeleted, withExif, withPeople, withStacked);
final result = api_instance.searchAssets(checksum, city, country, createdAfter, createdBefore, deviceAssetId, deviceId, encodedVideoPath, id, isArchived, isEncoded, isExternal, isFavorite, isMotion, isNotInAlbum, isOffline, isReadOnly, isVisible, lensModel, libraryId, make, model, order, originalFileName, originalPath, page, personIds, previewPath, resizePath, size, state, takenAfter, takenBefore, thumbnailPath, trashedAfter, trashedBefore, type, updatedAfter, updatedBefore, webpPath, withArchived, withDeleted, withExif, withPeople, withStacked);
print(result);
} catch (e) {
print('Exception when calling AssetApi->searchAssets: $e\n');
@ -992,11 +994,13 @@ Name | Type | Description | Notes
**originalPath** | **String**| | [optional]
**page** | **num**| | [optional]
**personIds** | [**List<String>**](String.md)| | [optional] [default to const []]
**previewPath** | **String**| | [optional]
**resizePath** | **String**| | [optional]
**size** | **num**| | [optional]
**state** | **String**| | [optional]
**takenAfter** | **DateTime**| | [optional]
**takenBefore** | **DateTime**| | [optional]
**thumbnailPath** | **String**| | [optional]
**trashedAfter** | **DateTime**| | [optional]
**trashedBefore** | **DateTime**| | [optional]
**type** | [**AssetTypeEnum**](.md)| | [optional]

14
mobile/openapi/doc/ImageFormat.md generated Normal file
View File

@ -0,0 +1,14 @@
# openapi.model.ImageFormat
## Load the model package
```dart
import 'package:openapi/api.dart';
```
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

406
mobile/openapi/doc/MemoryApi.md generated Normal file
View File

@ -0,0 +1,406 @@
# openapi.api.MemoryApi
## Load the API package
```dart
import 'package:openapi/api.dart';
```
All URIs are relative to */api*
Method | HTTP request | Description
------------- | ------------- | -------------
[**addMemoryAssets**](MemoryApi.md#addmemoryassets) | **PUT** /memories/{id}/assets |
[**createMemory**](MemoryApi.md#creatememory) | **POST** /memories |
[**deleteMemory**](MemoryApi.md#deletememory) | **DELETE** /memories/{id} |
[**getMemory**](MemoryApi.md#getmemory) | **GET** /memories/{id} |
[**removeMemoryAssets**](MemoryApi.md#removememoryassets) | **DELETE** /memories/{id}/assets |
[**searchMemories**](MemoryApi.md#searchmemories) | **GET** /memories |
[**updateMemory**](MemoryApi.md#updatememory) | **PUT** /memories/{id} |
# **addMemoryAssets**
> List<BulkIdResponseDto> addMemoryAssets(id, bulkIdsDto)
### Example
```dart
import 'package:openapi/api.dart';
// TODO Configure API key authorization: cookie
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
// TODO Configure API key authorization: api_key
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
// TODO Configure HTTP Bearer authorization: bearer
// Case 1. Use String Token
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
// Case 2. Use Function which generate token.
// String yourTokenGeneratorFunction() { ... }
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
final api_instance = MemoryApi();
final id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
final bulkIdsDto = BulkIdsDto(); // BulkIdsDto |
try {
final result = api_instance.addMemoryAssets(id, bulkIdsDto);
print(result);
} catch (e) {
print('Exception when calling MemoryApi->addMemoryAssets: $e\n');
}
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**id** | **String**| |
**bulkIdsDto** | [**BulkIdsDto**](BulkIdsDto.md)| |
### Return type
[**List<BulkIdResponseDto>**](BulkIdResponseDto.md)
### Authorization
[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
### HTTP request headers
- **Content-Type**: application/json
- **Accept**: application/json
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **createMemory**
> MemoryResponseDto createMemory(memoryCreateDto)
### Example
```dart
import 'package:openapi/api.dart';
// TODO Configure API key authorization: cookie
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
// TODO Configure API key authorization: api_key
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
// TODO Configure HTTP Bearer authorization: bearer
// Case 1. Use String Token
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
// Case 2. Use Function which generate token.
// String yourTokenGeneratorFunction() { ... }
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
final api_instance = MemoryApi();
final memoryCreateDto = MemoryCreateDto(); // MemoryCreateDto |
try {
final result = api_instance.createMemory(memoryCreateDto);
print(result);
} catch (e) {
print('Exception when calling MemoryApi->createMemory: $e\n');
}
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**memoryCreateDto** | [**MemoryCreateDto**](MemoryCreateDto.md)| |
### Return type
[**MemoryResponseDto**](MemoryResponseDto.md)
### Authorization
[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
### HTTP request headers
- **Content-Type**: application/json
- **Accept**: application/json
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **deleteMemory**
> deleteMemory(id)
### Example
```dart
import 'package:openapi/api.dart';
// TODO Configure API key authorization: cookie
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
// TODO Configure API key authorization: api_key
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
// TODO Configure HTTP Bearer authorization: bearer
// Case 1. Use String Token
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
// Case 2. Use Function which generate token.
// String yourTokenGeneratorFunction() { ... }
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
final api_instance = MemoryApi();
final id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
try {
api_instance.deleteMemory(id);
} catch (e) {
print('Exception when calling MemoryApi->deleteMemory: $e\n');
}
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**id** | **String**| |
### Return type
void (empty response body)
### Authorization
[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: Not defined
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **getMemory**
> MemoryResponseDto getMemory(id)
### Example
```dart
import 'package:openapi/api.dart';
// TODO Configure API key authorization: cookie
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
// TODO Configure API key authorization: api_key
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
// TODO Configure HTTP Bearer authorization: bearer
// Case 1. Use String Token
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
// Case 2. Use Function which generate token.
// String yourTokenGeneratorFunction() { ... }
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
final api_instance = MemoryApi();
final id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
try {
final result = api_instance.getMemory(id);
print(result);
} catch (e) {
print('Exception when calling MemoryApi->getMemory: $e\n');
}
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**id** | **String**| |
### Return type
[**MemoryResponseDto**](MemoryResponseDto.md)
### Authorization
[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: application/json
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **removeMemoryAssets**
> List<BulkIdResponseDto> removeMemoryAssets(id, bulkIdsDto)
### Example
```dart
import 'package:openapi/api.dart';
// TODO Configure API key authorization: cookie
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
// TODO Configure API key authorization: api_key
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
// TODO Configure HTTP Bearer authorization: bearer
// Case 1. Use String Token
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
// Case 2. Use Function which generate token.
// String yourTokenGeneratorFunction() { ... }
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
final api_instance = MemoryApi();
final id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
final bulkIdsDto = BulkIdsDto(); // BulkIdsDto |
try {
final result = api_instance.removeMemoryAssets(id, bulkIdsDto);
print(result);
} catch (e) {
print('Exception when calling MemoryApi->removeMemoryAssets: $e\n');
}
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**id** | **String**| |
**bulkIdsDto** | [**BulkIdsDto**](BulkIdsDto.md)| |
### Return type
[**List<BulkIdResponseDto>**](BulkIdResponseDto.md)
### Authorization
[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
### HTTP request headers
- **Content-Type**: application/json
- **Accept**: application/json
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **searchMemories**
> List<MemoryResponseDto> searchMemories()
### Example
```dart
import 'package:openapi/api.dart';
// TODO Configure API key authorization: cookie
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
// TODO Configure API key authorization: api_key
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
// TODO Configure HTTP Bearer authorization: bearer
// Case 1. Use String Token
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
// Case 2. Use Function which generate token.
// String yourTokenGeneratorFunction() { ... }
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
final api_instance = MemoryApi();
try {
final result = api_instance.searchMemories();
print(result);
} catch (e) {
print('Exception when calling MemoryApi->searchMemories: $e\n');
}
```
### Parameters
This endpoint does not need any parameter.
### Return type
[**List<MemoryResponseDto>**](MemoryResponseDto.md)
### Authorization
[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: application/json
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **updateMemory**
> MemoryResponseDto updateMemory(id, memoryUpdateDto)
### Example
```dart
import 'package:openapi/api.dart';
// TODO Configure API key authorization: cookie
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
// TODO Configure API key authorization: api_key
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
// TODO Configure HTTP Bearer authorization: bearer
// Case 1. Use String Token
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
// Case 2. Use Function which generate token.
// String yourTokenGeneratorFunction() { ... }
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
final api_instance = MemoryApi();
final id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
final memoryUpdateDto = MemoryUpdateDto(); // MemoryUpdateDto |
try {
final result = api_instance.updateMemory(id, memoryUpdateDto);
print(result);
} catch (e) {
print('Exception when calling MemoryApi->updateMemory: $e\n');
}
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**id** | **String**| |
**memoryUpdateDto** | [**MemoryUpdateDto**](MemoryUpdateDto.md)| |
### Return type
[**MemoryResponseDto**](MemoryResponseDto.md)
### Authorization
[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
### HTTP request headers
- **Content-Type**: application/json
- **Accept**: application/json
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)

20
mobile/openapi/doc/MemoryCreateDto.md generated Normal file
View File

@ -0,0 +1,20 @@
# openapi.model.MemoryCreateDto
## Load the model package
```dart
import 'package:openapi/api.dart';
```
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**assetIds** | **List<String>** | | [optional] [default to const []]
**data** | [**OnThisDayDto**](OnThisDayDto.md) | |
**isSaved** | **bool** | | [optional]
**memoryAt** | [**DateTime**](DateTime.md) | |
**seenAt** | [**DateTime**](DateTime.md) | | [optional]
**type** | [**MemoryType**](MemoryType.md) | |
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

25
mobile/openapi/doc/MemoryResponseDto.md generated Normal file
View File

@ -0,0 +1,25 @@
# openapi.model.MemoryResponseDto
## Load the model package
```dart
import 'package:openapi/api.dart';
```
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**assets** | [**List<AssetResponseDto>**](AssetResponseDto.md) | | [default to const []]
**createdAt** | [**DateTime**](DateTime.md) | |
**data** | [**OnThisDayDto**](OnThisDayDto.md) | |
**deletedAt** | [**DateTime**](DateTime.md) | | [optional]
**id** | **String** | |
**isSaved** | **bool** | |
**memoryAt** | [**DateTime**](DateTime.md) | |
**ownerId** | **String** | |
**seenAt** | [**DateTime**](DateTime.md) | | [optional]
**type** | **String** | |
**updatedAt** | [**DateTime**](DateTime.md) | |
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

14
mobile/openapi/doc/MemoryType.md generated Normal file
View File

@ -0,0 +1,14 @@
# openapi.model.MemoryType
## Load the model package
```dart
import 'package:openapi/api.dart';
```
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

17
mobile/openapi/doc/MemoryUpdateDto.md generated Normal file
View File

@ -0,0 +1,17 @@
# openapi.model.MemoryUpdateDto
## Load the model package
```dart
import 'package:openapi/api.dart';
```
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**isSaved** | **bool** | | [optional]
**memoryAt** | [**DateTime**](DateTime.md) | | [optional]
**seenAt** | [**DateTime**](DateTime.md) | | [optional]
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@ -35,11 +35,13 @@ Name | Type | Description | Notes
**originalPath** | **String** | | [optional]
**page** | **num** | | [optional]
**personIds** | **List<String>** | | [optional] [default to const []]
**previewPath** | **String** | | [optional]
**resizePath** | **String** | | [optional]
**size** | **num** | | [optional]
**state** | **String** | | [optional]
**takenAfter** | [**DateTime**](DateTime.md) | | [optional]
**takenBefore** | [**DateTime**](DateTime.md) | | [optional]
**thumbnailPath** | **String** | | [optional]
**trashedAfter** | [**DateTime**](DateTime.md) | | [optional]
**trashedBefore** | [**DateTime**](DateTime.md) | | [optional]
**type** | [**AssetTypeEnum**](AssetTypeEnum.md) | | [optional]

15
mobile/openapi/doc/OnThisDayDto.md generated Normal file
View File

@ -0,0 +1,15 @@
# openapi.model.OnThisDayDto
## Load the model package
```dart
import 'package:openapi/api.dart';
```
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**year** | **num** | |
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@ -9,6 +9,7 @@ import 'package:openapi/api.dart';
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**ffmpeg** | [**SystemConfigFFmpegDto**](SystemConfigFFmpegDto.md) | |
**image** | [**SystemConfigImageDto**](SystemConfigImageDto.md) | |
**job** | [**SystemConfigJobDto**](SystemConfigJobDto.md) | |
**library_** | [**SystemConfigLibraryDto**](SystemConfigLibraryDto.md) | |
**logging** | [**SystemConfigLoggingDto**](SystemConfigLoggingDto.md) | |
@ -21,7 +22,6 @@ Name | Type | Description | Notes
**server** | [**SystemConfigServerDto**](SystemConfigServerDto.md) | |
**storageTemplate** | [**SystemConfigStorageTemplateDto**](SystemConfigStorageTemplateDto.md) | |
**theme** | [**SystemConfigThemeDto**](SystemConfigThemeDto.md) | |
**thumbnail** | [**SystemConfigThumbnailDto**](SystemConfigThumbnailDto.md) | |
**trash** | [**SystemConfigTrashDto**](SystemConfigTrashDto.md) | |
**user** | [**SystemConfigUserDto**](SystemConfigUserDto.md) | |

View File

@ -1,4 +1,4 @@
# openapi.model.SystemConfigThumbnailDto
# openapi.model.SystemConfigImageDto
## Load the model package
```dart
@ -9,9 +9,11 @@ import 'package:openapi/api.dart';
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**colorspace** | [**Colorspace**](Colorspace.md) | |
**jpegSize** | **int** | |
**previewFormat** | [**ImageFormat**](ImageFormat.md) | |
**previewSize** | **int** | |
**quality** | **int** | |
**webpSize** | **int** | |
**thumbnailFormat** | [**ImageFormat**](ImageFormat.md) | |
**thumbnailSize** | **int** | |
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@ -39,6 +39,7 @@ part 'api/download_api.dart';
part 'api/face_api.dart';
part 'api/job_api.dart';
part 'api/library_api.dart';
part 'api/memory_api.dart';
part 'api/o_auth_api.dart';
part 'api/partner_api.dart';
part 'api/person_api.dart';
@ -112,6 +113,7 @@ part 'model/file_checksum_response_dto.dart';
part 'model/file_report_dto.dart';
part 'model/file_report_fix_dto.dart';
part 'model/file_report_item_dto.dart';
part 'model/image_format.dart';
part 'model/job_command.dart';
part 'model/job_command_dto.dart';
part 'model/job_counts_dto.dart';
@ -127,13 +129,18 @@ part 'model/login_response_dto.dart';
part 'model/logout_response_dto.dart';
part 'model/map_marker_response_dto.dart';
part 'model/map_theme.dart';
part 'model/memory_create_dto.dart';
part 'model/memory_lane_response_dto.dart';
part 'model/memory_response_dto.dart';
part 'model/memory_type.dart';
part 'model/memory_update_dto.dart';
part 'model/merge_person_dto.dart';
part 'model/metadata_search_dto.dart';
part 'model/model_type.dart';
part 'model/o_auth_authorize_response_dto.dart';
part 'model/o_auth_callback_dto.dart';
part 'model/o_auth_config_dto.dart';
part 'model/on_this_day_dto.dart';
part 'model/partner_response_dto.dart';
part 'model/path_entity_type.dart';
part 'model/path_type.dart';
@ -176,6 +183,7 @@ part 'model/smart_info_response_dto.dart';
part 'model/smart_search_dto.dart';
part 'model/system_config_dto.dart';
part 'model/system_config_f_fmpeg_dto.dart';
part 'model/system_config_image_dto.dart';
part 'model/system_config_job_dto.dart';
part 'model/system_config_library_dto.dart';
part 'model/system_config_library_scan_dto.dart';
@ -191,7 +199,6 @@ part 'model/system_config_server_dto.dart';
part 'model/system_config_storage_template_dto.dart';
part 'model/system_config_template_storage_option_dto.dart';
part 'model/system_config_theme_dto.dart';
part 'model/system_config_thumbnail_dto.dart';
part 'model/system_config_trash_dto.dart';
part 'model/system_config_user_dto.dart';
part 'model/tag_response_dto.dart';

View File

@ -931,6 +931,8 @@ class AssetApi {
///
/// * [List<String>] personIds:
///
/// * [String] previewPath:
///
/// * [String] resizePath:
///
/// * [num] size:
@ -941,6 +943,8 @@ class AssetApi {
///
/// * [DateTime] takenBefore:
///
/// * [String] thumbnailPath:
///
/// * [DateTime] trashedAfter:
///
/// * [DateTime] trashedBefore:
@ -962,7 +966,7 @@ class AssetApi {
/// * [bool] withPeople:
///
/// * [bool] withStacked:
Future<Response> searchAssetsWithHttpInfo({ String? checksum, String? city, String? country, DateTime? createdAfter, DateTime? createdBefore, String? deviceAssetId, String? deviceId, String? encodedVideoPath, String? id, bool? isArchived, bool? isEncoded, bool? isExternal, bool? isFavorite, bool? isMotion, bool? isNotInAlbum, bool? isOffline, bool? isReadOnly, bool? isVisible, String? lensModel, String? libraryId, String? make, String? model, AssetOrder? order, String? originalFileName, String? originalPath, num? page, List<String>? personIds, String? resizePath, num? size, String? state, DateTime? takenAfter, DateTime? takenBefore, DateTime? trashedAfter, DateTime? trashedBefore, AssetTypeEnum? type, DateTime? updatedAfter, DateTime? updatedBefore, String? webpPath, bool? withArchived, bool? withDeleted, bool? withExif, bool? withPeople, bool? withStacked, }) async {
Future<Response> searchAssetsWithHttpInfo({ String? checksum, String? city, String? country, DateTime? createdAfter, DateTime? createdBefore, String? deviceAssetId, String? deviceId, String? encodedVideoPath, String? id, bool? isArchived, bool? isEncoded, bool? isExternal, bool? isFavorite, bool? isMotion, bool? isNotInAlbum, bool? isOffline, bool? isReadOnly, bool? isVisible, String? lensModel, String? libraryId, String? make, String? model, AssetOrder? order, String? originalFileName, String? originalPath, num? page, List<String>? personIds, String? previewPath, String? resizePath, num? size, String? state, DateTime? takenAfter, DateTime? takenBefore, String? thumbnailPath, DateTime? trashedAfter, DateTime? trashedBefore, AssetTypeEnum? type, DateTime? updatedAfter, DateTime? updatedBefore, String? webpPath, bool? withArchived, bool? withDeleted, bool? withExif, bool? withPeople, bool? withStacked, }) async {
// ignore: prefer_const_declarations
final path = r'/assets';
@ -1054,6 +1058,9 @@ class AssetApi {
if (personIds != null) {
queryParams.addAll(_queryParams('multi', 'personIds', personIds));
}
if (previewPath != null) {
queryParams.addAll(_queryParams('', 'previewPath', previewPath));
}
if (resizePath != null) {
queryParams.addAll(_queryParams('', 'resizePath', resizePath));
}
@ -1069,6 +1076,9 @@ class AssetApi {
if (takenBefore != null) {
queryParams.addAll(_queryParams('', 'takenBefore', takenBefore));
}
if (thumbnailPath != null) {
queryParams.addAll(_queryParams('', 'thumbnailPath', thumbnailPath));
}
if (trashedAfter != null) {
queryParams.addAll(_queryParams('', 'trashedAfter', trashedAfter));
}
@ -1173,6 +1183,8 @@ class AssetApi {
///
/// * [List<String>] personIds:
///
/// * [String] previewPath:
///
/// * [String] resizePath:
///
/// * [num] size:
@ -1183,6 +1195,8 @@ class AssetApi {
///
/// * [DateTime] takenBefore:
///
/// * [String] thumbnailPath:
///
/// * [DateTime] trashedAfter:
///
/// * [DateTime] trashedBefore:
@ -1204,8 +1218,8 @@ class AssetApi {
/// * [bool] withPeople:
///
/// * [bool] withStacked:
Future<List<AssetResponseDto>?> searchAssets({ String? checksum, String? city, String? country, DateTime? createdAfter, DateTime? createdBefore, String? deviceAssetId, String? deviceId, String? encodedVideoPath, String? id, bool? isArchived, bool? isEncoded, bool? isExternal, bool? isFavorite, bool? isMotion, bool? isNotInAlbum, bool? isOffline, bool? isReadOnly, bool? isVisible, String? lensModel, String? libraryId, String? make, String? model, AssetOrder? order, String? originalFileName, String? originalPath, num? page, List<String>? personIds, String? resizePath, num? size, String? state, DateTime? takenAfter, DateTime? takenBefore, DateTime? trashedAfter, DateTime? trashedBefore, AssetTypeEnum? type, DateTime? updatedAfter, DateTime? updatedBefore, String? webpPath, bool? withArchived, bool? withDeleted, bool? withExif, bool? withPeople, bool? withStacked, }) async {
final response = await searchAssetsWithHttpInfo( checksum: checksum, city: city, country: country, createdAfter: createdAfter, createdBefore: createdBefore, deviceAssetId: deviceAssetId, deviceId: deviceId, encodedVideoPath: encodedVideoPath, id: id, isArchived: isArchived, isEncoded: isEncoded, isExternal: isExternal, isFavorite: isFavorite, isMotion: isMotion, isNotInAlbum: isNotInAlbum, isOffline: isOffline, isReadOnly: isReadOnly, isVisible: isVisible, lensModel: lensModel, libraryId: libraryId, make: make, model: model, order: order, originalFileName: originalFileName, originalPath: originalPath, page: page, personIds: personIds, resizePath: resizePath, size: size, state: state, takenAfter: takenAfter, takenBefore: takenBefore, trashedAfter: trashedAfter, trashedBefore: trashedBefore, type: type, updatedAfter: updatedAfter, updatedBefore: updatedBefore, webpPath: webpPath, withArchived: withArchived, withDeleted: withDeleted, withExif: withExif, withPeople: withPeople, withStacked: withStacked, );
Future<List<AssetResponseDto>?> searchAssets({ String? checksum, String? city, String? country, DateTime? createdAfter, DateTime? createdBefore, String? deviceAssetId, String? deviceId, String? encodedVideoPath, String? id, bool? isArchived, bool? isEncoded, bool? isExternal, bool? isFavorite, bool? isMotion, bool? isNotInAlbum, bool? isOffline, bool? isReadOnly, bool? isVisible, String? lensModel, String? libraryId, String? make, String? model, AssetOrder? order, String? originalFileName, String? originalPath, num? page, List<String>? personIds, String? previewPath, String? resizePath, num? size, String? state, DateTime? takenAfter, DateTime? takenBefore, String? thumbnailPath, DateTime? trashedAfter, DateTime? trashedBefore, AssetTypeEnum? type, DateTime? updatedAfter, DateTime? updatedBefore, String? webpPath, bool? withArchived, bool? withDeleted, bool? withExif, bool? withPeople, bool? withStacked, }) async {
final response = await searchAssetsWithHttpInfo( checksum: checksum, city: city, country: country, createdAfter: createdAfter, createdBefore: createdBefore, deviceAssetId: deviceAssetId, deviceId: deviceId, encodedVideoPath: encodedVideoPath, id: id, isArchived: isArchived, isEncoded: isEncoded, isExternal: isExternal, isFavorite: isFavorite, isMotion: isMotion, isNotInAlbum: isNotInAlbum, isOffline: isOffline, isReadOnly: isReadOnly, isVisible: isVisible, lensModel: lensModel, libraryId: libraryId, make: make, model: model, order: order, originalFileName: originalFileName, originalPath: originalPath, page: page, personIds: personIds, previewPath: previewPath, resizePath: resizePath, size: size, state: state, takenAfter: takenAfter, takenBefore: takenBefore, thumbnailPath: thumbnailPath, trashedAfter: trashedAfter, trashedBefore: trashedBefore, type: type, updatedAfter: updatedAfter, updatedBefore: updatedBefore, webpPath: webpPath, withArchived: withArchived, withDeleted: withDeleted, withExif: withExif, withPeople: withPeople, withStacked: withStacked, );
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}

359
mobile/openapi/lib/api/memory_api.dart generated Normal file
View File

@ -0,0 +1,359 @@
//
// AUTO-GENERATED FILE, DO NOT MODIFY!
//
// @dart=2.12
// ignore_for_file: unused_element, unused_import
// ignore_for_file: always_put_required_named_parameters_first
// ignore_for_file: constant_identifier_names
// ignore_for_file: lines_longer_than_80_chars
part of openapi.api;
class MemoryApi {
MemoryApi([ApiClient? apiClient]) : apiClient = apiClient ?? defaultApiClient;
final ApiClient apiClient;
/// Performs an HTTP 'PUT /memories/{id}/assets' operation and returns the [Response].
/// Parameters:
///
/// * [String] id (required):
///
/// * [BulkIdsDto] bulkIdsDto (required):
Future<Response> addMemoryAssetsWithHttpInfo(String id, BulkIdsDto bulkIdsDto,) async {
// ignore: prefer_const_declarations
final path = r'/memories/{id}/assets'
.replaceAll('{id}', id);
// ignore: prefer_final_locals
Object? postBody = bulkIdsDto;
final queryParams = <QueryParam>[];
final headerParams = <String, String>{};
final formParams = <String, String>{};
const contentTypes = <String>['application/json'];
return apiClient.invokeAPI(
path,
'PUT',
queryParams,
postBody,
headerParams,
formParams,
contentTypes.isEmpty ? null : contentTypes.first,
);
}
/// Parameters:
///
/// * [String] id (required):
///
/// * [BulkIdsDto] bulkIdsDto (required):
Future<List<BulkIdResponseDto>?> addMemoryAssets(String id, BulkIdsDto bulkIdsDto,) async {
final response = await addMemoryAssetsWithHttpInfo(id, bulkIdsDto,);
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}
// When a remote server returns no body with a status of 204, we shall not decode it.
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
// FormatException when trying to decode an empty string.
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
final responseBody = await _decodeBodyBytes(response);
return (await apiClient.deserializeAsync(responseBody, 'List<BulkIdResponseDto>') as List)
.cast<BulkIdResponseDto>()
.toList(growable: false);
}
return null;
}
/// Performs an HTTP 'POST /memories' operation and returns the [Response].
/// Parameters:
///
/// * [MemoryCreateDto] memoryCreateDto (required):
Future<Response> createMemoryWithHttpInfo(MemoryCreateDto memoryCreateDto,) async {
// ignore: prefer_const_declarations
final path = r'/memories';
// ignore: prefer_final_locals
Object? postBody = memoryCreateDto;
final queryParams = <QueryParam>[];
final headerParams = <String, String>{};
final formParams = <String, String>{};
const contentTypes = <String>['application/json'];
return apiClient.invokeAPI(
path,
'POST',
queryParams,
postBody,
headerParams,
formParams,
contentTypes.isEmpty ? null : contentTypes.first,
);
}
/// Parameters:
///
/// * [MemoryCreateDto] memoryCreateDto (required):
Future<MemoryResponseDto?> createMemory(MemoryCreateDto memoryCreateDto,) async {
final response = await createMemoryWithHttpInfo(memoryCreateDto,);
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}
// When a remote server returns no body with a status of 204, we shall not decode it.
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
// FormatException when trying to decode an empty string.
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'MemoryResponseDto',) as MemoryResponseDto;
}
return null;
}
/// Performs an HTTP 'DELETE /memories/{id}' operation and returns the [Response].
/// Parameters:
///
/// * [String] id (required):
Future<Response> deleteMemoryWithHttpInfo(String id,) async {
// ignore: prefer_const_declarations
final path = r'/memories/{id}'
.replaceAll('{id}', id);
// ignore: prefer_final_locals
Object? postBody;
final queryParams = <QueryParam>[];
final headerParams = <String, String>{};
final formParams = <String, String>{};
const contentTypes = <String>[];
return apiClient.invokeAPI(
path,
'DELETE',
queryParams,
postBody,
headerParams,
formParams,
contentTypes.isEmpty ? null : contentTypes.first,
);
}
/// Parameters:
///
/// * [String] id (required):
Future<void> deleteMemory(String id,) async {
final response = await deleteMemoryWithHttpInfo(id,);
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}
}
/// Performs an HTTP 'GET /memories/{id}' operation and returns the [Response].
/// Parameters:
///
/// * [String] id (required):
Future<Response> getMemoryWithHttpInfo(String id,) async {
// ignore: prefer_const_declarations
final path = r'/memories/{id}'
.replaceAll('{id}', id);
// ignore: prefer_final_locals
Object? postBody;
final queryParams = <QueryParam>[];
final headerParams = <String, String>{};
final formParams = <String, String>{};
const contentTypes = <String>[];
return apiClient.invokeAPI(
path,
'GET',
queryParams,
postBody,
headerParams,
formParams,
contentTypes.isEmpty ? null : contentTypes.first,
);
}
/// Parameters:
///
/// * [String] id (required):
Future<MemoryResponseDto?> getMemory(String id,) async {
final response = await getMemoryWithHttpInfo(id,);
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}
// When a remote server returns no body with a status of 204, we shall not decode it.
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
// FormatException when trying to decode an empty string.
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'MemoryResponseDto',) as MemoryResponseDto;
}
return null;
}
/// Performs an HTTP 'DELETE /memories/{id}/assets' operation and returns the [Response].
/// Parameters:
///
/// * [String] id (required):
///
/// * [BulkIdsDto] bulkIdsDto (required):
Future<Response> removeMemoryAssetsWithHttpInfo(String id, BulkIdsDto bulkIdsDto,) async {
// ignore: prefer_const_declarations
final path = r'/memories/{id}/assets'
.replaceAll('{id}', id);
// ignore: prefer_final_locals
Object? postBody = bulkIdsDto;
final queryParams = <QueryParam>[];
final headerParams = <String, String>{};
final formParams = <String, String>{};
const contentTypes = <String>['application/json'];
return apiClient.invokeAPI(
path,
'DELETE',
queryParams,
postBody,
headerParams,
formParams,
contentTypes.isEmpty ? null : contentTypes.first,
);
}
/// Parameters:
///
/// * [String] id (required):
///
/// * [BulkIdsDto] bulkIdsDto (required):
Future<List<BulkIdResponseDto>?> removeMemoryAssets(String id, BulkIdsDto bulkIdsDto,) async {
final response = await removeMemoryAssetsWithHttpInfo(id, bulkIdsDto,);
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}
// When a remote server returns no body with a status of 204, we shall not decode it.
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
// FormatException when trying to decode an empty string.
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
final responseBody = await _decodeBodyBytes(response);
return (await apiClient.deserializeAsync(responseBody, 'List<BulkIdResponseDto>') as List)
.cast<BulkIdResponseDto>()
.toList(growable: false);
}
return null;
}
/// Performs an HTTP 'GET /memories' operation and returns the [Response].
Future<Response> searchMemoriesWithHttpInfo() async {
// ignore: prefer_const_declarations
final path = r'/memories';
// ignore: prefer_final_locals
Object? postBody;
final queryParams = <QueryParam>[];
final headerParams = <String, String>{};
final formParams = <String, String>{};
const contentTypes = <String>[];
return apiClient.invokeAPI(
path,
'GET',
queryParams,
postBody,
headerParams,
formParams,
contentTypes.isEmpty ? null : contentTypes.first,
);
}
Future<List<MemoryResponseDto>?> searchMemories() async {
final response = await searchMemoriesWithHttpInfo();
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}
// When a remote server returns no body with a status of 204, we shall not decode it.
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
// FormatException when trying to decode an empty string.
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
final responseBody = await _decodeBodyBytes(response);
return (await apiClient.deserializeAsync(responseBody, 'List<MemoryResponseDto>') as List)
.cast<MemoryResponseDto>()
.toList(growable: false);
}
return null;
}
/// Performs an HTTP 'PUT /memories/{id}' operation and returns the [Response].
/// Parameters:
///
/// * [String] id (required):
///
/// * [MemoryUpdateDto] memoryUpdateDto (required):
Future<Response> updateMemoryWithHttpInfo(String id, MemoryUpdateDto memoryUpdateDto,) async {
// ignore: prefer_const_declarations
final path = r'/memories/{id}'
.replaceAll('{id}', id);
// ignore: prefer_final_locals
Object? postBody = memoryUpdateDto;
final queryParams = <QueryParam>[];
final headerParams = <String, String>{};
final formParams = <String, String>{};
const contentTypes = <String>['application/json'];
return apiClient.invokeAPI(
path,
'PUT',
queryParams,
postBody,
headerParams,
formParams,
contentTypes.isEmpty ? null : contentTypes.first,
);
}
/// Parameters:
///
/// * [String] id (required):
///
/// * [MemoryUpdateDto] memoryUpdateDto (required):
Future<MemoryResponseDto?> updateMemory(String id, MemoryUpdateDto memoryUpdateDto,) async {
final response = await updateMemoryWithHttpInfo(id, memoryUpdateDto,);
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}
// When a remote server returns no body with a status of 204, we shall not decode it.
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
// FormatException when trying to decode an empty string.
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'MemoryResponseDto',) as MemoryResponseDto;
}
return null;
}
}

View File

@ -304,6 +304,8 @@ class ApiClient {
return FileReportFixDto.fromJson(value);
case 'FileReportItemDto':
return FileReportItemDto.fromJson(value);
case 'ImageFormat':
return ImageFormatTypeTransformer().decode(value);
case 'JobCommand':
return JobCommandTypeTransformer().decode(value);
case 'JobCommandDto':
@ -334,8 +336,16 @@ class ApiClient {
return MapMarkerResponseDto.fromJson(value);
case 'MapTheme':
return MapThemeTypeTransformer().decode(value);
case 'MemoryCreateDto':
return MemoryCreateDto.fromJson(value);
case 'MemoryLaneResponseDto':
return MemoryLaneResponseDto.fromJson(value);
case 'MemoryResponseDto':
return MemoryResponseDto.fromJson(value);
case 'MemoryType':
return MemoryTypeTypeTransformer().decode(value);
case 'MemoryUpdateDto':
return MemoryUpdateDto.fromJson(value);
case 'MergePersonDto':
return MergePersonDto.fromJson(value);
case 'MetadataSearchDto':
@ -348,6 +358,8 @@ class ApiClient {
return OAuthCallbackDto.fromJson(value);
case 'OAuthConfigDto':
return OAuthConfigDto.fromJson(value);
case 'OnThisDayDto':
return OnThisDayDto.fromJson(value);
case 'PartnerResponseDto':
return PartnerResponseDto.fromJson(value);
case 'PathEntityType':
@ -432,6 +444,8 @@ class ApiClient {
return SystemConfigDto.fromJson(value);
case 'SystemConfigFFmpegDto':
return SystemConfigFFmpegDto.fromJson(value);
case 'SystemConfigImageDto':
return SystemConfigImageDto.fromJson(value);
case 'SystemConfigJobDto':
return SystemConfigJobDto.fromJson(value);
case 'SystemConfigLibraryDto':
@ -462,8 +476,6 @@ class ApiClient {
return SystemConfigTemplateStorageOptionDto.fromJson(value);
case 'SystemConfigThemeDto':
return SystemConfigThemeDto.fromJson(value);
case 'SystemConfigThumbnailDto':
return SystemConfigThumbnailDto.fromJson(value);
case 'SystemConfigTrashDto':
return SystemConfigTrashDto.fromJson(value);
case 'SystemConfigUserDto':

View File

@ -79,6 +79,9 @@ String parameterToString(dynamic value) {
if (value is EntityType) {
return EntityTypeTypeTransformer().encode(value).toString();
}
if (value is ImageFormat) {
return ImageFormatTypeTransformer().encode(value).toString();
}
if (value is JobCommand) {
return JobCommandTypeTransformer().encode(value).toString();
}
@ -94,6 +97,9 @@ String parameterToString(dynamic value) {
if (value is MapTheme) {
return MapThemeTypeTransformer().encode(value).toString();
}
if (value is MemoryType) {
return MemoryTypeTypeTransformer().encode(value).toString();
}
if (value is ModelType) {
return ModelTypeTypeTransformer().encode(value).toString();
}

View File

@ -0,0 +1,85 @@
//
// AUTO-GENERATED FILE, DO NOT MODIFY!
//
// @dart=2.12
// ignore_for_file: unused_element, unused_import
// ignore_for_file: always_put_required_named_parameters_first
// ignore_for_file: constant_identifier_names
// ignore_for_file: lines_longer_than_80_chars
part of openapi.api;
class ImageFormat {
/// Instantiate a new enum with the provided [value].
const ImageFormat._(this.value);
/// The underlying value of this enum member.
final String value;
@override
String toString() => value;
String toJson() => value;
static const jpeg = ImageFormat._(r'jpeg');
static const webp = ImageFormat._(r'webp');
/// List of all possible values in this [enum][ImageFormat].
static const values = <ImageFormat>[
jpeg,
webp,
];
static ImageFormat? fromJson(dynamic value) => ImageFormatTypeTransformer().decode(value);
static List<ImageFormat> listFromJson(dynamic json, {bool growable = false,}) {
final result = <ImageFormat>[];
if (json is List && json.isNotEmpty) {
for (final row in json) {
final value = ImageFormat.fromJson(row);
if (value != null) {
result.add(value);
}
}
}
return result.toList(growable: growable);
}
}
/// Transformation class that can [encode] an instance of [ImageFormat] to String,
/// and [decode] dynamic data back to [ImageFormat].
class ImageFormatTypeTransformer {
factory ImageFormatTypeTransformer() => _instance ??= const ImageFormatTypeTransformer._();
const ImageFormatTypeTransformer._();
String encode(ImageFormat data) => data.value;
/// Decodes a [dynamic value][data] to a ImageFormat.
///
/// 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.
ImageFormat? decode(dynamic data, {bool allowNull = true}) {
if (data != null) {
switch (data) {
case r'jpeg': return ImageFormat.jpeg;
case r'webp': return ImageFormat.webp;
default:
if (!allowNull) {
throw ArgumentError('Unknown enum value to decode: $data');
}
}
}
return null;
}
/// Singleton [ImageFormatTypeTransformer] instance.
static ImageFormatTypeTransformer? _instance;
}

View File

@ -0,0 +1,157 @@
//
// AUTO-GENERATED FILE, DO NOT MODIFY!
//
// @dart=2.12
// ignore_for_file: unused_element, unused_import
// ignore_for_file: always_put_required_named_parameters_first
// ignore_for_file: constant_identifier_names
// ignore_for_file: lines_longer_than_80_chars
part of openapi.api;
class MemoryCreateDto {
/// Returns a new [MemoryCreateDto] instance.
MemoryCreateDto({
this.assetIds = const [],
required this.data,
this.isSaved,
required this.memoryAt,
this.seenAt,
required this.type,
});
List<String> assetIds;
OnThisDayDto data;
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
bool? isSaved;
DateTime memoryAt;
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
DateTime? seenAt;
MemoryType type;
@override
bool operator ==(Object other) => identical(this, other) || other is MemoryCreateDto &&
_deepEquality.equals(other.assetIds, assetIds) &&
other.data == data &&
other.isSaved == isSaved &&
other.memoryAt == memoryAt &&
other.seenAt == seenAt &&
other.type == type;
@override
int get hashCode =>
// ignore: unnecessary_parenthesis
(assetIds.hashCode) +
(data.hashCode) +
(isSaved == null ? 0 : isSaved!.hashCode) +
(memoryAt.hashCode) +
(seenAt == null ? 0 : seenAt!.hashCode) +
(type.hashCode);
@override
String toString() => 'MemoryCreateDto[assetIds=$assetIds, data=$data, isSaved=$isSaved, memoryAt=$memoryAt, seenAt=$seenAt, type=$type]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
json[r'assetIds'] = this.assetIds;
json[r'data'] = this.data;
if (this.isSaved != null) {
json[r'isSaved'] = this.isSaved;
} else {
// json[r'isSaved'] = null;
}
json[r'memoryAt'] = this.memoryAt.toUtc().toIso8601String();
if (this.seenAt != null) {
json[r'seenAt'] = this.seenAt!.toUtc().toIso8601String();
} else {
// json[r'seenAt'] = null;
}
json[r'type'] = this.type;
return json;
}
/// Returns a new [MemoryCreateDto] instance and imports its values from
/// [value] if it's a [Map], null otherwise.
// ignore: prefer_constructors_over_static_methods
static MemoryCreateDto? fromJson(dynamic value) {
if (value is Map) {
final json = value.cast<String, dynamic>();
return MemoryCreateDto(
assetIds: json[r'assetIds'] is Iterable
? (json[r'assetIds'] as Iterable).cast<String>().toList(growable: false)
: const [],
data: OnThisDayDto.fromJson(json[r'data'])!,
isSaved: mapValueOfType<bool>(json, r'isSaved'),
memoryAt: mapDateTime(json, r'memoryAt', r'')!,
seenAt: mapDateTime(json, r'seenAt', r''),
type: MemoryType.fromJson(json[r'type'])!,
);
}
return null;
}
static List<MemoryCreateDto> listFromJson(dynamic json, {bool growable = false,}) {
final result = <MemoryCreateDto>[];
if (json is List && json.isNotEmpty) {
for (final row in json) {
final value = MemoryCreateDto.fromJson(row);
if (value != null) {
result.add(value);
}
}
}
return result.toList(growable: growable);
}
static Map<String, MemoryCreateDto> mapFromJson(dynamic json) {
final map = <String, MemoryCreateDto>{};
if (json is Map && json.isNotEmpty) {
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
for (final entry in json.entries) {
final value = MemoryCreateDto.fromJson(entry.value);
if (value != null) {
map[entry.key] = value;
}
}
}
return map;
}
// maps a json object with a list of MemoryCreateDto-objects as value to a dart map
static Map<String, List<MemoryCreateDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
final map = <String, List<MemoryCreateDto>>{};
if (json is Map && json.isNotEmpty) {
// ignore: parameter_assignments
json = json.cast<String, dynamic>();
for (final entry in json.entries) {
map[entry.key] = MemoryCreateDto.listFromJson(entry.value, growable: growable,);
}
}
return map;
}
/// The list of required keys that must be present in a JSON.
static const requiredKeys = <String>{
'data',
'memoryAt',
'type',
};
}

View File

@ -0,0 +1,267 @@
//
// AUTO-GENERATED FILE, DO NOT MODIFY!
//
// @dart=2.12
// ignore_for_file: unused_element, unused_import
// ignore_for_file: always_put_required_named_parameters_first
// ignore_for_file: constant_identifier_names
// ignore_for_file: lines_longer_than_80_chars
part of openapi.api;
class MemoryResponseDto {
/// Returns a new [MemoryResponseDto] instance.
MemoryResponseDto({
this.assets = const [],
required this.createdAt,
required this.data,
this.deletedAt,
required this.id,
required this.isSaved,
required this.memoryAt,
required this.ownerId,
this.seenAt,
required this.type,
required this.updatedAt,
});
List<AssetResponseDto> assets;
DateTime createdAt;
OnThisDayDto data;
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
DateTime? deletedAt;
String id;
bool isSaved;
DateTime memoryAt;
String ownerId;
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
DateTime? seenAt;
MemoryResponseDtoTypeEnum type;
DateTime updatedAt;
@override
bool operator ==(Object other) => identical(this, other) || other is MemoryResponseDto &&
_deepEquality.equals(other.assets, assets) &&
other.createdAt == createdAt &&
other.data == data &&
other.deletedAt == deletedAt &&
other.id == id &&
other.isSaved == isSaved &&
other.memoryAt == memoryAt &&
other.ownerId == ownerId &&
other.seenAt == seenAt &&
other.type == type &&
other.updatedAt == updatedAt;
@override
int get hashCode =>
// ignore: unnecessary_parenthesis
(assets.hashCode) +
(createdAt.hashCode) +
(data.hashCode) +
(deletedAt == null ? 0 : deletedAt!.hashCode) +
(id.hashCode) +
(isSaved.hashCode) +
(memoryAt.hashCode) +
(ownerId.hashCode) +
(seenAt == null ? 0 : seenAt!.hashCode) +
(type.hashCode) +
(updatedAt.hashCode);
@override
String toString() => 'MemoryResponseDto[assets=$assets, createdAt=$createdAt, data=$data, deletedAt=$deletedAt, id=$id, isSaved=$isSaved, memoryAt=$memoryAt, ownerId=$ownerId, seenAt=$seenAt, type=$type, updatedAt=$updatedAt]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
json[r'assets'] = this.assets;
json[r'createdAt'] = this.createdAt.toUtc().toIso8601String();
json[r'data'] = this.data;
if (this.deletedAt != null) {
json[r'deletedAt'] = this.deletedAt!.toUtc().toIso8601String();
} else {
// json[r'deletedAt'] = null;
}
json[r'id'] = this.id;
json[r'isSaved'] = this.isSaved;
json[r'memoryAt'] = this.memoryAt.toUtc().toIso8601String();
json[r'ownerId'] = this.ownerId;
if (this.seenAt != null) {
json[r'seenAt'] = this.seenAt!.toUtc().toIso8601String();
} else {
// json[r'seenAt'] = null;
}
json[r'type'] = this.type;
json[r'updatedAt'] = this.updatedAt.toUtc().toIso8601String();
return json;
}
/// Returns a new [MemoryResponseDto] instance and imports its values from
/// [value] if it's a [Map], null otherwise.
// ignore: prefer_constructors_over_static_methods
static MemoryResponseDto? fromJson(dynamic value) {
if (value is Map) {
final json = value.cast<String, dynamic>();
return MemoryResponseDto(
assets: AssetResponseDto.listFromJson(json[r'assets']),
createdAt: mapDateTime(json, r'createdAt', r'')!,
data: OnThisDayDto.fromJson(json[r'data'])!,
deletedAt: mapDateTime(json, r'deletedAt', r''),
id: mapValueOfType<String>(json, r'id')!,
isSaved: mapValueOfType<bool>(json, r'isSaved')!,
memoryAt: mapDateTime(json, r'memoryAt', r'')!,
ownerId: mapValueOfType<String>(json, r'ownerId')!,
seenAt: mapDateTime(json, r'seenAt', r''),
type: MemoryResponseDtoTypeEnum.fromJson(json[r'type'])!,
updatedAt: mapDateTime(json, r'updatedAt', r'')!,
);
}
return null;
}
static List<MemoryResponseDto> listFromJson(dynamic json, {bool growable = false,}) {
final result = <MemoryResponseDto>[];
if (json is List && json.isNotEmpty) {
for (final row in json) {
final value = MemoryResponseDto.fromJson(row);
if (value != null) {
result.add(value);
}
}
}
return result.toList(growable: growable);
}
static Map<String, MemoryResponseDto> mapFromJson(dynamic json) {
final map = <String, MemoryResponseDto>{};
if (json is Map && json.isNotEmpty) {
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
for (final entry in json.entries) {
final value = MemoryResponseDto.fromJson(entry.value);
if (value != null) {
map[entry.key] = value;
}
}
}
return map;
}
// maps a json object with a list of MemoryResponseDto-objects as value to a dart map
static Map<String, List<MemoryResponseDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
final map = <String, List<MemoryResponseDto>>{};
if (json is Map && json.isNotEmpty) {
// ignore: parameter_assignments
json = json.cast<String, dynamic>();
for (final entry in json.entries) {
map[entry.key] = MemoryResponseDto.listFromJson(entry.value, growable: growable,);
}
}
return map;
}
/// The list of required keys that must be present in a JSON.
static const requiredKeys = <String>{
'assets',
'createdAt',
'data',
'id',
'isSaved',
'memoryAt',
'ownerId',
'type',
'updatedAt',
};
}
class MemoryResponseDtoTypeEnum {
/// Instantiate a new enum with the provided [value].
const MemoryResponseDtoTypeEnum._(this.value);
/// The underlying value of this enum member.
final String value;
@override
String toString() => value;
String toJson() => value;
static const onThisDay = MemoryResponseDtoTypeEnum._(r'on_this_day');
/// List of all possible values in this [enum][MemoryResponseDtoTypeEnum].
static const values = <MemoryResponseDtoTypeEnum>[
onThisDay,
];
static MemoryResponseDtoTypeEnum? fromJson(dynamic value) => MemoryResponseDtoTypeEnumTypeTransformer().decode(value);
static List<MemoryResponseDtoTypeEnum> listFromJson(dynamic json, {bool growable = false,}) {
final result = <MemoryResponseDtoTypeEnum>[];
if (json is List && json.isNotEmpty) {
for (final row in json) {
final value = MemoryResponseDtoTypeEnum.fromJson(row);
if (value != null) {
result.add(value);
}
}
}
return result.toList(growable: growable);
}
}
/// Transformation class that can [encode] an instance of [MemoryResponseDtoTypeEnum] to String,
/// and [decode] dynamic data back to [MemoryResponseDtoTypeEnum].
class MemoryResponseDtoTypeEnumTypeTransformer {
factory MemoryResponseDtoTypeEnumTypeTransformer() => _instance ??= const MemoryResponseDtoTypeEnumTypeTransformer._();
const MemoryResponseDtoTypeEnumTypeTransformer._();
String encode(MemoryResponseDtoTypeEnum data) => data.value;
/// Decodes a [dynamic value][data] to a MemoryResponseDtoTypeEnum.
///
/// 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.
MemoryResponseDtoTypeEnum? decode(dynamic data, {bool allowNull = true}) {
if (data != null) {
switch (data) {
case r'on_this_day': return MemoryResponseDtoTypeEnum.onThisDay;
default:
if (!allowNull) {
throw ArgumentError('Unknown enum value to decode: $data');
}
}
}
return null;
}
/// Singleton [MemoryResponseDtoTypeEnumTypeTransformer] instance.
static MemoryResponseDtoTypeEnumTypeTransformer? _instance;
}

View File

@ -0,0 +1,82 @@
//
// AUTO-GENERATED FILE, DO NOT MODIFY!
//
// @dart=2.12
// ignore_for_file: unused_element, unused_import
// ignore_for_file: always_put_required_named_parameters_first
// ignore_for_file: constant_identifier_names
// ignore_for_file: lines_longer_than_80_chars
part of openapi.api;
class MemoryType {
/// Instantiate a new enum with the provided [value].
const MemoryType._(this.value);
/// The underlying value of this enum member.
final String value;
@override
String toString() => value;
String toJson() => value;
static const onThisDay = MemoryType._(r'on_this_day');
/// List of all possible values in this [enum][MemoryType].
static const values = <MemoryType>[
onThisDay,
];
static MemoryType? fromJson(dynamic value) => MemoryTypeTypeTransformer().decode(value);
static List<MemoryType> listFromJson(dynamic json, {bool growable = false,}) {
final result = <MemoryType>[];
if (json is List && json.isNotEmpty) {
for (final row in json) {
final value = MemoryType.fromJson(row);
if (value != null) {
result.add(value);
}
}
}
return result.toList(growable: growable);
}
}
/// Transformation class that can [encode] an instance of [MemoryType] to String,
/// and [decode] dynamic data back to [MemoryType].
class MemoryTypeTypeTransformer {
factory MemoryTypeTypeTransformer() => _instance ??= const MemoryTypeTypeTransformer._();
const MemoryTypeTypeTransformer._();
String encode(MemoryType data) => data.value;
/// Decodes a [dynamic value][data] to a MemoryType.
///
/// 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.
MemoryType? decode(dynamic data, {bool allowNull = true}) {
if (data != null) {
switch (data) {
case r'on_this_day': return MemoryType.onThisDay;
default:
if (!allowNull) {
throw ArgumentError('Unknown enum value to decode: $data');
}
}
}
return null;
}
/// Singleton [MemoryTypeTypeTransformer] instance.
static MemoryTypeTypeTransformer? _instance;
}

View File

@ -0,0 +1,141 @@
//
// AUTO-GENERATED FILE, DO NOT MODIFY!
//
// @dart=2.12
// ignore_for_file: unused_element, unused_import
// ignore_for_file: always_put_required_named_parameters_first
// ignore_for_file: constant_identifier_names
// ignore_for_file: lines_longer_than_80_chars
part of openapi.api;
class MemoryUpdateDto {
/// Returns a new [MemoryUpdateDto] instance.
MemoryUpdateDto({
this.isSaved,
this.memoryAt,
this.seenAt,
});
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
bool? isSaved;
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
DateTime? memoryAt;
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
DateTime? seenAt;
@override
bool operator ==(Object other) => identical(this, other) || other is MemoryUpdateDto &&
other.isSaved == isSaved &&
other.memoryAt == memoryAt &&
other.seenAt == seenAt;
@override
int get hashCode =>
// ignore: unnecessary_parenthesis
(isSaved == null ? 0 : isSaved!.hashCode) +
(memoryAt == null ? 0 : memoryAt!.hashCode) +
(seenAt == null ? 0 : seenAt!.hashCode);
@override
String toString() => 'MemoryUpdateDto[isSaved=$isSaved, memoryAt=$memoryAt, seenAt=$seenAt]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
if (this.isSaved != null) {
json[r'isSaved'] = this.isSaved;
} else {
// json[r'isSaved'] = null;
}
if (this.memoryAt != null) {
json[r'memoryAt'] = this.memoryAt!.toUtc().toIso8601String();
} else {
// json[r'memoryAt'] = null;
}
if (this.seenAt != null) {
json[r'seenAt'] = this.seenAt!.toUtc().toIso8601String();
} else {
// json[r'seenAt'] = null;
}
return json;
}
/// Returns a new [MemoryUpdateDto] instance and imports its values from
/// [value] if it's a [Map], null otherwise.
// ignore: prefer_constructors_over_static_methods
static MemoryUpdateDto? fromJson(dynamic value) {
if (value is Map) {
final json = value.cast<String, dynamic>();
return MemoryUpdateDto(
isSaved: mapValueOfType<bool>(json, r'isSaved'),
memoryAt: mapDateTime(json, r'memoryAt', r''),
seenAt: mapDateTime(json, r'seenAt', r''),
);
}
return null;
}
static List<MemoryUpdateDto> listFromJson(dynamic json, {bool growable = false,}) {
final result = <MemoryUpdateDto>[];
if (json is List && json.isNotEmpty) {
for (final row in json) {
final value = MemoryUpdateDto.fromJson(row);
if (value != null) {
result.add(value);
}
}
}
return result.toList(growable: growable);
}
static Map<String, MemoryUpdateDto> mapFromJson(dynamic json) {
final map = <String, MemoryUpdateDto>{};
if (json is Map && json.isNotEmpty) {
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
for (final entry in json.entries) {
final value = MemoryUpdateDto.fromJson(entry.value);
if (value != null) {
map[entry.key] = value;
}
}
}
return map;
}
// maps a json object with a list of MemoryUpdateDto-objects as value to a dart map
static Map<String, List<MemoryUpdateDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
final map = <String, List<MemoryUpdateDto>>{};
if (json is Map && json.isNotEmpty) {
// ignore: parameter_assignments
json = json.cast<String, dynamic>();
for (final entry in json.entries) {
map[entry.key] = MemoryUpdateDto.listFromJson(entry.value, growable: growable,);
}
}
return map;
}
/// The list of required keys that must be present in a JSON.
static const requiredKeys = <String>{
};
}

View File

@ -40,11 +40,13 @@ class MetadataSearchDto {
this.originalPath,
this.page,
this.personIds = const [],
this.previewPath,
this.resizePath,
this.size,
this.state,
this.takenAfter,
this.takenBefore,
this.thumbnailPath,
this.trashedAfter,
this.trashedBefore,
this.type,
@ -268,6 +270,14 @@ class MetadataSearchDto {
List<String> personIds;
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
String? previewPath;
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
@ -308,6 +318,14 @@ class MetadataSearchDto {
///
DateTime? takenBefore;
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
String? thumbnailPath;
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
@ -419,11 +437,13 @@ class MetadataSearchDto {
other.originalPath == originalPath &&
other.page == page &&
_deepEquality.equals(other.personIds, personIds) &&
other.previewPath == previewPath &&
other.resizePath == resizePath &&
other.size == size &&
other.state == state &&
other.takenAfter == takenAfter &&
other.takenBefore == takenBefore &&
other.thumbnailPath == thumbnailPath &&
other.trashedAfter == trashedAfter &&
other.trashedBefore == trashedBefore &&
other.type == type &&
@ -466,11 +486,13 @@ class MetadataSearchDto {
(originalPath == null ? 0 : originalPath!.hashCode) +
(page == null ? 0 : page!.hashCode) +
(personIds.hashCode) +
(previewPath == null ? 0 : previewPath!.hashCode) +
(resizePath == null ? 0 : resizePath!.hashCode) +
(size == null ? 0 : size!.hashCode) +
(state == null ? 0 : state!.hashCode) +
(takenAfter == null ? 0 : takenAfter!.hashCode) +
(takenBefore == null ? 0 : takenBefore!.hashCode) +
(thumbnailPath == null ? 0 : thumbnailPath!.hashCode) +
(trashedAfter == null ? 0 : trashedAfter!.hashCode) +
(trashedBefore == null ? 0 : trashedBefore!.hashCode) +
(type == null ? 0 : type!.hashCode) +
@ -484,7 +506,7 @@ class MetadataSearchDto {
(withStacked == null ? 0 : withStacked!.hashCode);
@override
String toString() => 'MetadataSearchDto[checksum=$checksum, city=$city, country=$country, createdAfter=$createdAfter, createdBefore=$createdBefore, deviceAssetId=$deviceAssetId, deviceId=$deviceId, encodedVideoPath=$encodedVideoPath, id=$id, isArchived=$isArchived, isEncoded=$isEncoded, isExternal=$isExternal, isFavorite=$isFavorite, isMotion=$isMotion, isNotInAlbum=$isNotInAlbum, isOffline=$isOffline, isReadOnly=$isReadOnly, isVisible=$isVisible, lensModel=$lensModel, libraryId=$libraryId, make=$make, model=$model, order=$order, originalFileName=$originalFileName, originalPath=$originalPath, page=$page, personIds=$personIds, resizePath=$resizePath, size=$size, state=$state, takenAfter=$takenAfter, takenBefore=$takenBefore, trashedAfter=$trashedAfter, trashedBefore=$trashedBefore, type=$type, updatedAfter=$updatedAfter, updatedBefore=$updatedBefore, webpPath=$webpPath, withArchived=$withArchived, withDeleted=$withDeleted, withExif=$withExif, withPeople=$withPeople, withStacked=$withStacked]';
String toString() => 'MetadataSearchDto[checksum=$checksum, city=$city, country=$country, createdAfter=$createdAfter, createdBefore=$createdBefore, deviceAssetId=$deviceAssetId, deviceId=$deviceId, encodedVideoPath=$encodedVideoPath, id=$id, isArchived=$isArchived, isEncoded=$isEncoded, isExternal=$isExternal, isFavorite=$isFavorite, isMotion=$isMotion, isNotInAlbum=$isNotInAlbum, isOffline=$isOffline, isReadOnly=$isReadOnly, isVisible=$isVisible, lensModel=$lensModel, libraryId=$libraryId, make=$make, model=$model, order=$order, originalFileName=$originalFileName, originalPath=$originalPath, page=$page, personIds=$personIds, previewPath=$previewPath, resizePath=$resizePath, size=$size, state=$state, takenAfter=$takenAfter, takenBefore=$takenBefore, thumbnailPath=$thumbnailPath, trashedAfter=$trashedAfter, trashedBefore=$trashedBefore, type=$type, updatedAfter=$updatedAfter, updatedBefore=$updatedBefore, webpPath=$webpPath, withArchived=$withArchived, withDeleted=$withDeleted, withExif=$withExif, withPeople=$withPeople, withStacked=$withStacked]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
@ -619,6 +641,11 @@ class MetadataSearchDto {
// json[r'page'] = null;
}
json[r'personIds'] = this.personIds;
if (this.previewPath != null) {
json[r'previewPath'] = this.previewPath;
} else {
// json[r'previewPath'] = null;
}
if (this.resizePath != null) {
json[r'resizePath'] = this.resizePath;
} else {
@ -644,6 +671,11 @@ class MetadataSearchDto {
} else {
// json[r'takenBefore'] = null;
}
if (this.thumbnailPath != null) {
json[r'thumbnailPath'] = this.thumbnailPath;
} else {
// json[r'thumbnailPath'] = null;
}
if (this.trashedAfter != null) {
json[r'trashedAfter'] = this.trashedAfter!.toUtc().toIso8601String();
} else {
@ -735,11 +767,13 @@ class MetadataSearchDto {
personIds: json[r'personIds'] is Iterable
? (json[r'personIds'] as Iterable).cast<String>().toList(growable: false)
: const [],
previewPath: mapValueOfType<String>(json, r'previewPath'),
resizePath: mapValueOfType<String>(json, r'resizePath'),
size: num.parse('${json[r'size']}'),
state: mapValueOfType<String>(json, r'state'),
takenAfter: mapDateTime(json, r'takenAfter', r''),
takenBefore: mapDateTime(json, r'takenBefore', r''),
thumbnailPath: mapValueOfType<String>(json, r'thumbnailPath'),
trashedAfter: mapDateTime(json, r'trashedAfter', r''),
trashedBefore: mapDateTime(json, r'trashedBefore', r''),
type: AssetTypeEnum.fromJson(json[r'type']),

View File

@ -0,0 +1,98 @@
//
// AUTO-GENERATED FILE, DO NOT MODIFY!
//
// @dart=2.12
// ignore_for_file: unused_element, unused_import
// ignore_for_file: always_put_required_named_parameters_first
// ignore_for_file: constant_identifier_names
// ignore_for_file: lines_longer_than_80_chars
part of openapi.api;
class OnThisDayDto {
/// Returns a new [OnThisDayDto] instance.
OnThisDayDto({
required this.year,
});
num year;
@override
bool operator ==(Object other) => identical(this, other) || other is OnThisDayDto &&
other.year == year;
@override
int get hashCode =>
// ignore: unnecessary_parenthesis
(year.hashCode);
@override
String toString() => 'OnThisDayDto[year=$year]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
json[r'year'] = this.year;
return json;
}
/// Returns a new [OnThisDayDto] instance and imports its values from
/// [value] if it's a [Map], null otherwise.
// ignore: prefer_constructors_over_static_methods
static OnThisDayDto? fromJson(dynamic value) {
if (value is Map) {
final json = value.cast<String, dynamic>();
return OnThisDayDto(
year: num.parse('${json[r'year']}'),
);
}
return null;
}
static List<OnThisDayDto> listFromJson(dynamic json, {bool growable = false,}) {
final result = <OnThisDayDto>[];
if (json is List && json.isNotEmpty) {
for (final row in json) {
final value = OnThisDayDto.fromJson(row);
if (value != null) {
result.add(value);
}
}
}
return result.toList(growable: growable);
}
static Map<String, OnThisDayDto> mapFromJson(dynamic json) {
final map = <String, OnThisDayDto>{};
if (json is Map && json.isNotEmpty) {
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
for (final entry in json.entries) {
final value = OnThisDayDto.fromJson(entry.value);
if (value != null) {
map[entry.key] = value;
}
}
}
return map;
}
// maps a json object with a list of OnThisDayDto-objects as value to a dart map
static Map<String, List<OnThisDayDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
final map = <String, List<OnThisDayDto>>{};
if (json is Map && json.isNotEmpty) {
// ignore: parameter_assignments
json = json.cast<String, dynamic>();
for (final entry in json.entries) {
map[entry.key] = OnThisDayDto.listFromJson(entry.value, growable: growable,);
}
}
return map;
}
/// The list of required keys that must be present in a JSON.
static const requiredKeys = <String>{
'year',
};
}

View File

@ -24,8 +24,8 @@ class PathType {
String toJson() => value;
static const original = PathType._(r'original');
static const jpegThumbnail = PathType._(r'jpeg_thumbnail');
static const webpThumbnail = PathType._(r'webp_thumbnail');
static const preview = PathType._(r'preview');
static const thumbnail = PathType._(r'thumbnail');
static const encodedVideo = PathType._(r'encoded_video');
static const sidecar = PathType._(r'sidecar');
static const face = PathType._(r'face');
@ -34,8 +34,8 @@ class PathType {
/// List of all possible values in this [enum][PathType].
static const values = <PathType>[
original,
jpegThumbnail,
webpThumbnail,
preview,
thumbnail,
encodedVideo,
sidecar,
face,
@ -79,8 +79,8 @@ class PathTypeTypeTransformer {
if (data != null) {
switch (data) {
case r'original': return PathType.original;
case r'jpeg_thumbnail': return PathType.jpegThumbnail;
case r'webp_thumbnail': return PathType.webpThumbnail;
case r'preview': return PathType.preview;
case r'thumbnail': return PathType.thumbnail;
case r'encoded_video': return PathType.encodedVideo;
case r'sidecar': return PathType.sidecar;
case r'face': return PathType.face;

View File

@ -14,6 +14,7 @@ class SystemConfigDto {
/// Returns a new [SystemConfigDto] instance.
SystemConfigDto({
required this.ffmpeg,
required this.image,
required this.job,
required this.library_,
required this.logging,
@ -26,13 +27,14 @@ class SystemConfigDto {
required this.server,
required this.storageTemplate,
required this.theme,
required this.thumbnail,
required this.trash,
required this.user,
});
SystemConfigFFmpegDto ffmpeg;
SystemConfigImageDto image;
SystemConfigJobDto job;
SystemConfigLibraryDto library_;
@ -57,8 +59,6 @@ class SystemConfigDto {
SystemConfigThemeDto theme;
SystemConfigThumbnailDto thumbnail;
SystemConfigTrashDto trash;
SystemConfigUserDto user;
@ -66,6 +66,7 @@ class SystemConfigDto {
@override
bool operator ==(Object other) => identical(this, other) || other is SystemConfigDto &&
other.ffmpeg == ffmpeg &&
other.image == image &&
other.job == job &&
other.library_ == library_ &&
other.logging == logging &&
@ -78,7 +79,6 @@ class SystemConfigDto {
other.server == server &&
other.storageTemplate == storageTemplate &&
other.theme == theme &&
other.thumbnail == thumbnail &&
other.trash == trash &&
other.user == user;
@ -86,6 +86,7 @@ class SystemConfigDto {
int get hashCode =>
// ignore: unnecessary_parenthesis
(ffmpeg.hashCode) +
(image.hashCode) +
(job.hashCode) +
(library_.hashCode) +
(logging.hashCode) +
@ -98,16 +99,16 @@ class SystemConfigDto {
(server.hashCode) +
(storageTemplate.hashCode) +
(theme.hashCode) +
(thumbnail.hashCode) +
(trash.hashCode) +
(user.hashCode);
@override
String toString() => 'SystemConfigDto[ffmpeg=$ffmpeg, job=$job, library_=$library_, logging=$logging, machineLearning=$machineLearning, map=$map, newVersionCheck=$newVersionCheck, oauth=$oauth, passwordLogin=$passwordLogin, reverseGeocoding=$reverseGeocoding, server=$server, storageTemplate=$storageTemplate, theme=$theme, thumbnail=$thumbnail, trash=$trash, user=$user]';
String toString() => 'SystemConfigDto[ffmpeg=$ffmpeg, image=$image, job=$job, library_=$library_, logging=$logging, machineLearning=$machineLearning, map=$map, newVersionCheck=$newVersionCheck, oauth=$oauth, passwordLogin=$passwordLogin, reverseGeocoding=$reverseGeocoding, server=$server, storageTemplate=$storageTemplate, theme=$theme, trash=$trash, user=$user]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
json[r'ffmpeg'] = this.ffmpeg;
json[r'image'] = this.image;
json[r'job'] = this.job;
json[r'library'] = this.library_;
json[r'logging'] = this.logging;
@ -120,7 +121,6 @@ class SystemConfigDto {
json[r'server'] = this.server;
json[r'storageTemplate'] = this.storageTemplate;
json[r'theme'] = this.theme;
json[r'thumbnail'] = this.thumbnail;
json[r'trash'] = this.trash;
json[r'user'] = this.user;
return json;
@ -135,6 +135,7 @@ class SystemConfigDto {
return SystemConfigDto(
ffmpeg: SystemConfigFFmpegDto.fromJson(json[r'ffmpeg'])!,
image: SystemConfigImageDto.fromJson(json[r'image'])!,
job: SystemConfigJobDto.fromJson(json[r'job'])!,
library_: SystemConfigLibraryDto.fromJson(json[r'library'])!,
logging: SystemConfigLoggingDto.fromJson(json[r'logging'])!,
@ -147,7 +148,6 @@ class SystemConfigDto {
server: SystemConfigServerDto.fromJson(json[r'server'])!,
storageTemplate: SystemConfigStorageTemplateDto.fromJson(json[r'storageTemplate'])!,
theme: SystemConfigThemeDto.fromJson(json[r'theme'])!,
thumbnail: SystemConfigThumbnailDto.fromJson(json[r'thumbnail'])!,
trash: SystemConfigTrashDto.fromJson(json[r'trash'])!,
user: SystemConfigUserDto.fromJson(json[r'user'])!,
);
@ -198,6 +198,7 @@ class SystemConfigDto {
/// The list of required keys that must be present in a JSON.
static const requiredKeys = <String>{
'ffmpeg',
'image',
'job',
'library',
'logging',
@ -210,7 +211,6 @@ class SystemConfigDto {
'server',
'storageTemplate',
'theme',
'thumbnail',
'trash',
'user',
};

View File

@ -0,0 +1,138 @@
//
// AUTO-GENERATED FILE, DO NOT MODIFY!
//
// @dart=2.12
// ignore_for_file: unused_element, unused_import
// ignore_for_file: always_put_required_named_parameters_first
// ignore_for_file: constant_identifier_names
// ignore_for_file: lines_longer_than_80_chars
part of openapi.api;
class SystemConfigImageDto {
/// Returns a new [SystemConfigImageDto] instance.
SystemConfigImageDto({
required this.colorspace,
required this.previewFormat,
required this.previewSize,
required this.quality,
required this.thumbnailFormat,
required this.thumbnailSize,
});
Colorspace colorspace;
ImageFormat previewFormat;
int previewSize;
int quality;
ImageFormat thumbnailFormat;
int thumbnailSize;
@override
bool operator ==(Object other) => identical(this, other) || other is SystemConfigImageDto &&
other.colorspace == colorspace &&
other.previewFormat == previewFormat &&
other.previewSize == previewSize &&
other.quality == quality &&
other.thumbnailFormat == thumbnailFormat &&
other.thumbnailSize == thumbnailSize;
@override
int get hashCode =>
// ignore: unnecessary_parenthesis
(colorspace.hashCode) +
(previewFormat.hashCode) +
(previewSize.hashCode) +
(quality.hashCode) +
(thumbnailFormat.hashCode) +
(thumbnailSize.hashCode);
@override
String toString() => 'SystemConfigImageDto[colorspace=$colorspace, previewFormat=$previewFormat, previewSize=$previewSize, quality=$quality, thumbnailFormat=$thumbnailFormat, thumbnailSize=$thumbnailSize]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
json[r'colorspace'] = this.colorspace;
json[r'previewFormat'] = this.previewFormat;
json[r'previewSize'] = this.previewSize;
json[r'quality'] = this.quality;
json[r'thumbnailFormat'] = this.thumbnailFormat;
json[r'thumbnailSize'] = this.thumbnailSize;
return json;
}
/// Returns a new [SystemConfigImageDto] instance and imports its values from
/// [value] if it's a [Map], null otherwise.
// ignore: prefer_constructors_over_static_methods
static SystemConfigImageDto? fromJson(dynamic value) {
if (value is Map) {
final json = value.cast<String, dynamic>();
return SystemConfigImageDto(
colorspace: Colorspace.fromJson(json[r'colorspace'])!,
previewFormat: ImageFormat.fromJson(json[r'previewFormat'])!,
previewSize: mapValueOfType<int>(json, r'previewSize')!,
quality: mapValueOfType<int>(json, r'quality')!,
thumbnailFormat: ImageFormat.fromJson(json[r'thumbnailFormat'])!,
thumbnailSize: mapValueOfType<int>(json, r'thumbnailSize')!,
);
}
return null;
}
static List<SystemConfigImageDto> listFromJson(dynamic json, {bool growable = false,}) {
final result = <SystemConfigImageDto>[];
if (json is List && json.isNotEmpty) {
for (final row in json) {
final value = SystemConfigImageDto.fromJson(row);
if (value != null) {
result.add(value);
}
}
}
return result.toList(growable: growable);
}
static Map<String, SystemConfigImageDto> mapFromJson(dynamic json) {
final map = <String, SystemConfigImageDto>{};
if (json is Map && json.isNotEmpty) {
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
for (final entry in json.entries) {
final value = SystemConfigImageDto.fromJson(entry.value);
if (value != null) {
map[entry.key] = value;
}
}
}
return map;
}
// maps a json object with a list of SystemConfigImageDto-objects as value to a dart map
static Map<String, List<SystemConfigImageDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
final map = <String, List<SystemConfigImageDto>>{};
if (json is Map && json.isNotEmpty) {
// ignore: parameter_assignments
json = json.cast<String, dynamic>();
for (final entry in json.entries) {
map[entry.key] = SystemConfigImageDto.listFromJson(entry.value, growable: growable,);
}
}
return map;
}
/// The list of required keys that must be present in a JSON.
static const requiredKeys = <String>{
'colorspace',
'previewFormat',
'previewSize',
'quality',
'thumbnailFormat',
'thumbnailSize',
};
}

View File

@ -1,122 +0,0 @@
//
// AUTO-GENERATED FILE, DO NOT MODIFY!
//
// @dart=2.12
// ignore_for_file: unused_element, unused_import
// ignore_for_file: always_put_required_named_parameters_first
// ignore_for_file: constant_identifier_names
// ignore_for_file: lines_longer_than_80_chars
part of openapi.api;
class SystemConfigThumbnailDto {
/// Returns a new [SystemConfigThumbnailDto] instance.
SystemConfigThumbnailDto({
required this.colorspace,
required this.jpegSize,
required this.quality,
required this.webpSize,
});
Colorspace colorspace;
int jpegSize;
int quality;
int webpSize;
@override
bool operator ==(Object other) => identical(this, other) || other is SystemConfigThumbnailDto &&
other.colorspace == colorspace &&
other.jpegSize == jpegSize &&
other.quality == quality &&
other.webpSize == webpSize;
@override
int get hashCode =>
// ignore: unnecessary_parenthesis
(colorspace.hashCode) +
(jpegSize.hashCode) +
(quality.hashCode) +
(webpSize.hashCode);
@override
String toString() => 'SystemConfigThumbnailDto[colorspace=$colorspace, jpegSize=$jpegSize, quality=$quality, webpSize=$webpSize]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
json[r'colorspace'] = this.colorspace;
json[r'jpegSize'] = this.jpegSize;
json[r'quality'] = this.quality;
json[r'webpSize'] = this.webpSize;
return json;
}
/// Returns a new [SystemConfigThumbnailDto] instance and imports its values from
/// [value] if it's a [Map], null otherwise.
// ignore: prefer_constructors_over_static_methods
static SystemConfigThumbnailDto? fromJson(dynamic value) {
if (value is Map) {
final json = value.cast<String, dynamic>();
return SystemConfigThumbnailDto(
colorspace: Colorspace.fromJson(json[r'colorspace'])!,
jpegSize: mapValueOfType<int>(json, r'jpegSize')!,
quality: mapValueOfType<int>(json, r'quality')!,
webpSize: mapValueOfType<int>(json, r'webpSize')!,
);
}
return null;
}
static List<SystemConfigThumbnailDto> listFromJson(dynamic json, {bool growable = false,}) {
final result = <SystemConfigThumbnailDto>[];
if (json is List && json.isNotEmpty) {
for (final row in json) {
final value = SystemConfigThumbnailDto.fromJson(row);
if (value != null) {
result.add(value);
}
}
}
return result.toList(growable: growable);
}
static Map<String, SystemConfigThumbnailDto> mapFromJson(dynamic json) {
final map = <String, SystemConfigThumbnailDto>{};
if (json is Map && json.isNotEmpty) {
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
for (final entry in json.entries) {
final value = SystemConfigThumbnailDto.fromJson(entry.value);
if (value != null) {
map[entry.key] = value;
}
}
}
return map;
}
// maps a json object with a list of SystemConfigThumbnailDto-objects as value to a dart map
static Map<String, List<SystemConfigThumbnailDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
final map = <String, List<SystemConfigThumbnailDto>>{};
if (json is Map && json.isNotEmpty) {
// ignore: parameter_assignments
json = json.cast<String, dynamic>();
for (final entry in json.entries) {
map[entry.key] = SystemConfigThumbnailDto.listFromJson(entry.value, growable: growable,);
}
}
return map;
}
/// The list of required keys that must be present in a JSON.
static const requiredKeys = <String>{
'colorspace',
'jpegSize',
'quality',
'webpSize',
};
}

View File

@ -100,7 +100,7 @@ void main() {
// TODO
});
//Future<List<AssetResponseDto>> searchAssets({ String checksum, String city, String country, DateTime createdAfter, DateTime createdBefore, String deviceAssetId, String deviceId, String encodedVideoPath, String id, bool isArchived, bool isEncoded, bool isExternal, bool isFavorite, bool isMotion, bool isNotInAlbum, bool isOffline, bool isReadOnly, bool isVisible, String lensModel, String libraryId, String make, String model, AssetOrder order, String originalFileName, String originalPath, num page, List<String> personIds, String resizePath, num size, String state, DateTime takenAfter, DateTime takenBefore, DateTime trashedAfter, DateTime trashedBefore, AssetTypeEnum type, DateTime updatedAfter, DateTime updatedBefore, String webpPath, bool withArchived, bool withDeleted, bool withExif, bool withPeople, bool withStacked }) async
//Future<List<AssetResponseDto>> searchAssets({ String checksum, String city, String country, DateTime createdAfter, DateTime createdBefore, String deviceAssetId, String deviceId, String encodedVideoPath, String id, bool isArchived, bool isEncoded, bool isExternal, bool isFavorite, bool isMotion, bool isNotInAlbum, bool isOffline, bool isReadOnly, bool isVisible, String lensModel, String libraryId, String make, String model, AssetOrder order, String originalFileName, String originalPath, num page, List<String> personIds, String previewPath, String resizePath, num size, String state, DateTime takenAfter, DateTime takenBefore, String thumbnailPath, DateTime trashedAfter, DateTime trashedBefore, AssetTypeEnum type, DateTime updatedAfter, DateTime updatedBefore, String webpPath, bool withArchived, bool withDeleted, bool withExif, bool withPeople, bool withStacked }) async
test('test searchAssets', () async {
// TODO
});

View File

@ -0,0 +1,21 @@
//
// AUTO-GENERATED FILE, DO NOT MODIFY!
//
// @dart=2.12
// ignore_for_file: unused_element, unused_import
// ignore_for_file: always_put_required_named_parameters_first
// ignore_for_file: constant_identifier_names
// ignore_for_file: lines_longer_than_80_chars
import 'package:openapi/api.dart';
import 'package:test/test.dart';
// tests for ImageFormat
void main() {
group('test ImageFormat', () {
});
}

56
mobile/openapi/test/memory_api_test.dart generated Normal file
View File

@ -0,0 +1,56 @@
//
// AUTO-GENERATED FILE, DO NOT MODIFY!
//
// @dart=2.12
// ignore_for_file: unused_element, unused_import
// ignore_for_file: always_put_required_named_parameters_first
// ignore_for_file: constant_identifier_names
// ignore_for_file: lines_longer_than_80_chars
import 'package:openapi/api.dart';
import 'package:test/test.dart';
/// tests for MemoryApi
void main() {
// final instance = MemoryApi();
group('tests for MemoryApi', () {
//Future<List<BulkIdResponseDto>> addMemoryAssets(String id, BulkIdsDto bulkIdsDto) async
test('test addMemoryAssets', () async {
// TODO
});
//Future<MemoryResponseDto> createMemory(MemoryCreateDto memoryCreateDto) async
test('test createMemory', () async {
// TODO
});
//Future deleteMemory(String id) async
test('test deleteMemory', () async {
// TODO
});
//Future<MemoryResponseDto> getMemory(String id) async
test('test getMemory', () async {
// TODO
});
//Future<List<BulkIdResponseDto>> removeMemoryAssets(String id, BulkIdsDto bulkIdsDto) async
test('test removeMemoryAssets', () async {
// TODO
});
//Future<List<MemoryResponseDto>> searchMemories() async
test('test searchMemories', () async {
// TODO
});
//Future<MemoryResponseDto> updateMemory(String id, MemoryUpdateDto memoryUpdateDto) async
test('test updateMemory', () async {
// TODO
});
});
}

View File

@ -0,0 +1,52 @@
//
// AUTO-GENERATED FILE, DO NOT MODIFY!
//
// @dart=2.12
// ignore_for_file: unused_element, unused_import
// ignore_for_file: always_put_required_named_parameters_first
// ignore_for_file: constant_identifier_names
// ignore_for_file: lines_longer_than_80_chars
import 'package:openapi/api.dart';
import 'package:test/test.dart';
// tests for MemoryCreateDto
void main() {
// final instance = MemoryCreateDto();
group('test MemoryCreateDto', () {
// List<String> assetIds (default value: const [])
test('to test the property `assetIds`', () async {
// TODO
});
// OnThisDayDto data
test('to test the property `data`', () async {
// TODO
});
// bool isSaved
test('to test the property `isSaved`', () async {
// TODO
});
// DateTime memoryAt
test('to test the property `memoryAt`', () async {
// TODO
});
// DateTime seenAt
test('to test the property `seenAt`', () async {
// TODO
});
// MemoryType type
test('to test the property `type`', () async {
// TODO
});
});
}

View File

@ -0,0 +1,77 @@
//
// AUTO-GENERATED FILE, DO NOT MODIFY!
//
// @dart=2.12
// ignore_for_file: unused_element, unused_import
// ignore_for_file: always_put_required_named_parameters_first
// ignore_for_file: constant_identifier_names
// ignore_for_file: lines_longer_than_80_chars
import 'package:openapi/api.dart';
import 'package:test/test.dart';
// tests for MemoryResponseDto
void main() {
// final instance = MemoryResponseDto();
group('test MemoryResponseDto', () {
// List<AssetResponseDto> assets (default value: const [])
test('to test the property `assets`', () async {
// TODO
});
// DateTime createdAt
test('to test the property `createdAt`', () async {
// TODO
});
// OnThisDayDto data
test('to test the property `data`', () async {
// TODO
});
// DateTime deletedAt
test('to test the property `deletedAt`', () async {
// TODO
});
// String id
test('to test the property `id`', () async {
// TODO
});
// bool isSaved
test('to test the property `isSaved`', () async {
// TODO
});
// DateTime memoryAt
test('to test the property `memoryAt`', () async {
// TODO
});
// String ownerId
test('to test the property `ownerId`', () async {
// TODO
});
// DateTime seenAt
test('to test the property `seenAt`', () async {
// TODO
});
// String type
test('to test the property `type`', () async {
// TODO
});
// DateTime updatedAt
test('to test the property `updatedAt`', () async {
// TODO
});
});
}

View File

@ -0,0 +1,21 @@
//
// AUTO-GENERATED FILE, DO NOT MODIFY!
//
// @dart=2.12
// ignore_for_file: unused_element, unused_import
// ignore_for_file: always_put_required_named_parameters_first
// ignore_for_file: constant_identifier_names
// ignore_for_file: lines_longer_than_80_chars
import 'package:openapi/api.dart';
import 'package:test/test.dart';
// tests for MemoryType
void main() {
group('test MemoryType', () {
});
}

View File

@ -0,0 +1,37 @@
//
// AUTO-GENERATED FILE, DO NOT MODIFY!
//
// @dart=2.12
// ignore_for_file: unused_element, unused_import
// ignore_for_file: always_put_required_named_parameters_first
// ignore_for_file: constant_identifier_names
// ignore_for_file: lines_longer_than_80_chars
import 'package:openapi/api.dart';
import 'package:test/test.dart';
// tests for MemoryUpdateDto
void main() {
// final instance = MemoryUpdateDto();
group('test MemoryUpdateDto', () {
// bool isSaved
test('to test the property `isSaved`', () async {
// TODO
});
// DateTime memoryAt
test('to test the property `memoryAt`', () async {
// TODO
});
// DateTime seenAt
test('to test the property `seenAt`', () async {
// TODO
});
});
}

View File

@ -151,6 +151,11 @@ void main() {
// TODO
});
// String previewPath
test('to test the property `previewPath`', () async {
// TODO
});
// String resizePath
test('to test the property `resizePath`', () async {
// TODO
@ -176,6 +181,11 @@ void main() {
// TODO
});
// String thumbnailPath
test('to test the property `thumbnailPath`', () async {
// TODO
});
// DateTime trashedAfter
test('to test the property `trashedAfter`', () async {
// TODO

View File

@ -0,0 +1,27 @@
//
// AUTO-GENERATED FILE, DO NOT MODIFY!
//
// @dart=2.12
// ignore_for_file: unused_element, unused_import
// ignore_for_file: always_put_required_named_parameters_first
// ignore_for_file: constant_identifier_names
// ignore_for_file: lines_longer_than_80_chars
import 'package:openapi/api.dart';
import 'package:test/test.dart';
// tests for OnThisDayDto
void main() {
// final instance = OnThisDayDto();
group('test OnThisDayDto', () {
// num year
test('to test the property `year`', () async {
// TODO
});
});
}

View File

@ -21,6 +21,11 @@ void main() {
// TODO
});
// SystemConfigImageDto image
test('to test the property `image`', () async {
// TODO
});
// SystemConfigJobDto job
test('to test the property `job`', () async {
// TODO
@ -81,11 +86,6 @@ void main() {
// TODO
});
// SystemConfigThumbnailDto thumbnail
test('to test the property `thumbnail`', () async {
// TODO
});
// SystemConfigTrashDto trash
test('to test the property `trash`', () async {
// TODO

View File

@ -11,18 +11,23 @@
import 'package:openapi/api.dart';
import 'package:test/test.dart';
// tests for SystemConfigThumbnailDto
// tests for SystemConfigImageDto
void main() {
// final instance = SystemConfigThumbnailDto();
// final instance = SystemConfigImageDto();
group('test SystemConfigThumbnailDto', () {
group('test SystemConfigImageDto', () {
// Colorspace colorspace
test('to test the property `colorspace`', () async {
// TODO
});
// int jpegSize
test('to test the property `jpegSize`', () async {
// ImageFormat previewFormat
test('to test the property `previewFormat`', () async {
// TODO
});
// int previewSize
test('to test the property `previewSize`', () async {
// TODO
});
@ -31,8 +36,13 @@ void main() {
// TODO
});
// int webpSize
test('to test the property `webpSize`', () async {
// ImageFormat thumbnailFormat
test('to test the property `thumbnailFormat`', () async {
// TODO
});
// int thumbnailSize
test('to test the property `thumbnailSize`', () async {
// TODO
});

View File

@ -2101,10 +2101,19 @@
}
}
},
{
"name": "previewPath",
"required": false,
"in": "query",
"schema": {
"type": "string"
}
},
{
"name": "resizePath",
"required": false,
"in": "query",
"deprecated": true,
"schema": {
"type": "string"
}
@ -2143,6 +2152,14 @@
"type": "string"
}
},
{
"name": "thumbnailPath",
"required": false,
"in": "query",
"schema": {
"type": "string"
}
},
{
"name": "trashedAfter",
"required": false,
@ -2191,6 +2208,7 @@
"name": "webpPath",
"required": false,
"in": "query",
"deprecated": true,
"schema": {
"type": "string"
}
@ -3417,6 +3435,314 @@
]
}
},
"/memories": {
"get": {
"operationId": "searchMemories",
"parameters": [],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"items": {
"$ref": "#/components/schemas/MemoryResponseDto"
},
"type": "array"
}
}
},
"description": ""
}
},
"security": [
{
"bearer": []
},
{
"cookie": []
},
{
"api_key": []
}
],
"tags": [
"Memory"
]
},
"post": {
"operationId": "createMemory",
"parameters": [],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/MemoryCreateDto"
}
}
},
"required": true
},
"responses": {
"201": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/MemoryResponseDto"
}
}
},
"description": ""
}
},
"security": [
{
"bearer": []
},
{
"cookie": []
},
{
"api_key": []
}
],
"tags": [
"Memory"
]
}
},
"/memories/{id}": {
"delete": {
"operationId": "deleteMemory",
"parameters": [
{
"name": "id",
"required": true,
"in": "path",
"schema": {
"format": "uuid",
"type": "string"
}
}
],
"responses": {
"204": {
"description": ""
}
},
"security": [
{
"bearer": []
},
{
"cookie": []
},
{
"api_key": []
}
],
"tags": [
"Memory"
]
},
"get": {
"operationId": "getMemory",
"parameters": [
{
"name": "id",
"required": true,
"in": "path",
"schema": {
"format": "uuid",
"type": "string"
}
}
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/MemoryResponseDto"
}
}
},
"description": ""
}
},
"security": [
{
"bearer": []
},
{
"cookie": []
},
{
"api_key": []
}
],
"tags": [
"Memory"
]
},
"put": {
"operationId": "updateMemory",
"parameters": [
{
"name": "id",
"required": true,
"in": "path",
"schema": {
"format": "uuid",
"type": "string"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/MemoryUpdateDto"
}
}
},
"required": true
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/MemoryResponseDto"
}
}
},
"description": ""
}
},
"security": [
{
"bearer": []
},
{
"cookie": []
},
{
"api_key": []
}
],
"tags": [
"Memory"
]
}
},
"/memories/{id}/assets": {
"delete": {
"operationId": "removeMemoryAssets",
"parameters": [
{
"name": "id",
"required": true,
"in": "path",
"schema": {
"format": "uuid",
"type": "string"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/BulkIdsDto"
}
}
},
"required": true
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"items": {
"$ref": "#/components/schemas/BulkIdResponseDto"
},
"type": "array"
}
}
},
"description": ""
}
},
"security": [
{
"bearer": []
},
{
"cookie": []
},
{
"api_key": []
}
],
"tags": [
"Memory"
]
},
"put": {
"operationId": "addMemoryAssets",
"parameters": [
{
"name": "id",
"required": true,
"in": "path",
"schema": {
"format": "uuid",
"type": "string"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/BulkIdsDto"
}
}
},
"required": true
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"items": {
"$ref": "#/components/schemas/BulkIdResponseDto"
},
"type": "array"
}
}
},
"description": ""
}
},
"security": [
{
"bearer": []
},
{
"cookie": []
},
{
"api_key": []
}
],
"tags": [
"Memory"
]
}
},
"/oauth/authorize": {
"post": {
"operationId": "startOAuth",
@ -8114,6 +8440,13 @@
],
"type": "object"
},
"ImageFormat": {
"enum": [
"jpeg",
"webp"
],
"type": "string"
},
"JobCommand": {
"enum": [
"start",
@ -8426,6 +8759,40 @@
],
"type": "string"
},
"MemoryCreateDto": {
"properties": {
"assetIds": {
"items": {
"format": "uuid",
"type": "string"
},
"type": "array"
},
"data": {
"$ref": "#/components/schemas/OnThisDayDto"
},
"isSaved": {
"type": "boolean"
},
"memoryAt": {
"format": "date-time",
"type": "string"
},
"seenAt": {
"format": "date-time",
"type": "string"
},
"type": {
"$ref": "#/components/schemas/MemoryType"
}
},
"required": [
"data",
"memoryAt",
"type"
],
"type": "object"
},
"MemoryLaneResponseDto": {
"properties": {
"assets": {
@ -8449,6 +8816,88 @@
],
"type": "object"
},
"MemoryResponseDto": {
"properties": {
"assets": {
"items": {
"$ref": "#/components/schemas/AssetResponseDto"
},
"type": "array"
},
"createdAt": {
"format": "date-time",
"type": "string"
},
"data": {
"$ref": "#/components/schemas/OnThisDayDto"
},
"deletedAt": {
"format": "date-time",
"type": "string"
},
"id": {
"type": "string"
},
"isSaved": {
"type": "boolean"
},
"memoryAt": {
"format": "date-time",
"type": "string"
},
"ownerId": {
"type": "string"
},
"seenAt": {
"format": "date-time",
"type": "string"
},
"type": {
"enum": [
"on_this_day"
],
"type": "string"
},
"updatedAt": {
"format": "date-time",
"type": "string"
}
},
"required": [
"assets",
"createdAt",
"data",
"id",
"isSaved",
"memoryAt",
"ownerId",
"type",
"updatedAt"
],
"type": "object"
},
"MemoryType": {
"enum": [
"on_this_day"
],
"type": "string"
},
"MemoryUpdateDto": {
"properties": {
"isSaved": {
"type": "boolean"
},
"memoryAt": {
"format": "date-time",
"type": "string"
},
"seenAt": {
"format": "date-time",
"type": "string"
}
},
"type": "object"
},
"MergePersonDto": {
"properties": {
"ids": {
@ -8555,7 +9004,11 @@
},
"type": "array"
},
"previewPath": {
"type": "string"
},
"resizePath": {
"deprecated": true,
"type": "string"
},
"size": {
@ -8572,6 +9025,9 @@
"format": "date-time",
"type": "string"
},
"thumbnailPath": {
"type": "string"
},
"trashedAfter": {
"format": "date-time",
"type": "string"
@ -8592,6 +9048,7 @@
"type": "string"
},
"webpPath": {
"deprecated": true,
"type": "string"
},
"withArchived": {
@ -8653,6 +9110,17 @@
],
"type": "object"
},
"OnThisDayDto": {
"properties": {
"year": {
"type": "number"
}
},
"required": [
"year"
],
"type": "object"
},
"PartnerResponseDto": {
"properties": {
"avatarColor": {
@ -8746,8 +9214,8 @@
"PathType": {
"enum": [
"original",
"jpeg_thumbnail",
"webp_thumbnail",
"preview",
"thumbnail",
"encoded_video",
"sidecar",
"face",
@ -9743,6 +10211,9 @@
"ffmpeg": {
"$ref": "#/components/schemas/SystemConfigFFmpegDto"
},
"image": {
"$ref": "#/components/schemas/SystemConfigImageDto"
},
"job": {
"$ref": "#/components/schemas/SystemConfigJobDto"
},
@ -9779,9 +10250,6 @@
"theme": {
"$ref": "#/components/schemas/SystemConfigThemeDto"
},
"thumbnail": {
"$ref": "#/components/schemas/SystemConfigThumbnailDto"
},
"trash": {
"$ref": "#/components/schemas/SystemConfigTrashDto"
},
@ -9791,6 +10259,7 @@
},
"required": [
"ffmpeg",
"image",
"job",
"library",
"logging",
@ -9803,7 +10272,6 @@
"server",
"storageTemplate",
"theme",
"thumbnail",
"trash",
"user"
],
@ -9902,6 +10370,37 @@
],
"type": "object"
},
"SystemConfigImageDto": {
"properties": {
"colorspace": {
"$ref": "#/components/schemas/Colorspace"
},
"previewFormat": {
"$ref": "#/components/schemas/ImageFormat"
},
"previewSize": {
"type": "integer"
},
"quality": {
"type": "integer"
},
"thumbnailFormat": {
"$ref": "#/components/schemas/ImageFormat"
},
"thumbnailSize": {
"type": "integer"
}
},
"required": [
"colorspace",
"previewFormat",
"previewSize",
"quality",
"thumbnailFormat",
"thumbnailSize"
],
"type": "object"
},
"SystemConfigJobDto": {
"properties": {
"backgroundTask": {
@ -10251,29 +10750,6 @@
],
"type": "object"
},
"SystemConfigThumbnailDto": {
"properties": {
"colorspace": {
"$ref": "#/components/schemas/Colorspace"
},
"jpegSize": {
"type": "integer"
},
"quality": {
"type": "integer"
},
"webpSize": {
"type": "integer"
}
},
"required": [
"colorspace",
"jpegSize",
"quality",
"webpSize"
],
"type": "object"
},
"SystemConfigTrashDto": {
"properties": {
"days": {

View File

@ -494,6 +494,35 @@ export type ValidateLibraryImportPathResponseDto = {
export type ValidateLibraryResponseDto = {
importPaths?: ValidateLibraryImportPathResponseDto[];
};
export type OnThisDayDto = {
year: number;
};
export type MemoryResponseDto = {
assets: AssetResponseDto[];
createdAt: string;
data: OnThisDayDto;
deletedAt?: string;
id: string;
isSaved: boolean;
memoryAt: string;
ownerId: string;
seenAt?: string;
"type": Type2;
updatedAt: string;
};
export type MemoryCreateDto = {
assetIds?: string[];
data: OnThisDayDto;
isSaved?: boolean;
memoryAt: string;
seenAt?: string;
"type": MemoryType;
};
export type MemoryUpdateDto = {
isSaved?: boolean;
memoryAt?: string;
seenAt?: string;
};
export type OAuthConfigDto = {
redirectUri: string;
};
@ -640,11 +669,13 @@ export type MetadataSearchDto = {
originalPath?: string;
page?: number;
personIds?: string[];
previewPath?: string;
resizePath?: string;
size?: number;
state?: string;
takenAfter?: string;
takenBefore?: string;
thumbnailPath?: string;
trashedAfter?: string;
trashedBefore?: string;
"type"?: AssetTypeEnum;
@ -827,6 +858,14 @@ export type SystemConfigFFmpegDto = {
transcode: TranscodePolicy;
twoPass: boolean;
};
export type SystemConfigImageDto = {
colorspace: Colorspace;
previewFormat: ImageFormat;
previewSize: number;
quality: number;
thumbnailFormat: ImageFormat;
thumbnailSize: number;
};
export type JobSettingsDto = {
concurrency: number;
};
@ -919,12 +958,6 @@ export type SystemConfigStorageTemplateDto = {
export type SystemConfigThemeDto = {
customCss: string;
};
export type SystemConfigThumbnailDto = {
colorspace: Colorspace;
jpegSize: number;
quality: number;
webpSize: number;
};
export type SystemConfigTrashDto = {
days: number;
enabled: boolean;
@ -934,6 +967,7 @@ export type SystemConfigUserDto = {
};
export type SystemConfigDto = {
ffmpeg: SystemConfigFFmpegDto;
image: SystemConfigImageDto;
job: SystemConfigJobDto;
library: SystemConfigLibraryDto;
logging: SystemConfigLoggingDto;
@ -946,7 +980,6 @@ export type SystemConfigDto = {
server: SystemConfigServerDto;
storageTemplate: SystemConfigStorageTemplateDto;
theme: SystemConfigThemeDto;
thumbnail: SystemConfigThumbnailDto;
trash: SystemConfigTrashDto;
user: SystemConfigUserDto;
};
@ -1497,7 +1530,7 @@ export function updateAsset({ id, updateAssetDto }: {
body: updateAssetDto
})));
}
export function searchAssets({ checksum, city, country, createdAfter, createdBefore, deviceAssetId, deviceId, encodedVideoPath, id, isArchived, isEncoded, isExternal, isFavorite, isMotion, isNotInAlbum, isOffline, isReadOnly, isVisible, lensModel, libraryId, make, model, order, originalFileName, originalPath, page, personIds, resizePath, size, state, takenAfter, takenBefore, trashedAfter, trashedBefore, $type, updatedAfter, updatedBefore, webpPath, withArchived, withDeleted, withExif, withPeople, withStacked }: {
export function searchAssets({ checksum, city, country, createdAfter, createdBefore, deviceAssetId, deviceId, encodedVideoPath, id, isArchived, isEncoded, isExternal, isFavorite, isMotion, isNotInAlbum, isOffline, isReadOnly, isVisible, lensModel, libraryId, make, model, order, originalFileName, originalPath, page, personIds, previewPath, resizePath, size, state, takenAfter, takenBefore, thumbnailPath, trashedAfter, trashedBefore, $type, updatedAfter, updatedBefore, webpPath, withArchived, withDeleted, withExif, withPeople, withStacked }: {
checksum?: string;
city?: string;
country?: string;
@ -1525,11 +1558,13 @@ export function searchAssets({ checksum, city, country, createdAfter, createdBef
originalPath?: string;
page?: number;
personIds?: string[];
previewPath?: string;
resizePath?: string;
size?: number;
state?: string;
takenAfter?: string;
takenBefore?: string;
thumbnailPath?: string;
trashedAfter?: string;
trashedBefore?: string;
$type?: AssetTypeEnum;
@ -1573,11 +1608,13 @@ export function searchAssets({ checksum, city, country, createdAfter, createdBef
originalPath,
page,
personIds,
previewPath,
resizePath,
size,
state,
takenAfter,
takenBefore,
thumbnailPath,
trashedAfter,
trashedBefore,
"type": $type,
@ -1900,6 +1937,83 @@ export function validate({ id, validateLibraryDto }: {
body: validateLibraryDto
})));
}
export function searchMemories(opts?: Oazapfts.RequestOpts) {
return oazapfts.ok(oazapfts.fetchJson<{
status: 200;
data: MemoryResponseDto[];
}>("/memories", {
...opts
}));
}
export function createMemory({ memoryCreateDto }: {
memoryCreateDto: MemoryCreateDto;
}, opts?: Oazapfts.RequestOpts) {
return oazapfts.ok(oazapfts.fetchJson<{
status: 201;
data: MemoryResponseDto;
}>("/memories", oazapfts.json({
...opts,
method: "POST",
body: memoryCreateDto
})));
}
export function deleteMemory({ id }: {
id: string;
}, opts?: Oazapfts.RequestOpts) {
return oazapfts.ok(oazapfts.fetchText(`/memories/${encodeURIComponent(id)}`, {
...opts,
method: "DELETE"
}));
}
export function getMemory({ id }: {
id: string;
}, opts?: Oazapfts.RequestOpts) {
return oazapfts.ok(oazapfts.fetchJson<{
status: 200;
data: MemoryResponseDto;
}>(`/memories/${encodeURIComponent(id)}`, {
...opts
}));
}
export function updateMemory({ id, memoryUpdateDto }: {
id: string;
memoryUpdateDto: MemoryUpdateDto;
}, opts?: Oazapfts.RequestOpts) {
return oazapfts.ok(oazapfts.fetchJson<{
status: 200;
data: MemoryResponseDto;
}>(`/memories/${encodeURIComponent(id)}`, oazapfts.json({
...opts,
method: "PUT",
body: memoryUpdateDto
})));
}
export function removeMemoryAssets({ id, bulkIdsDto }: {
id: string;
bulkIdsDto: BulkIdsDto;
}, opts?: Oazapfts.RequestOpts) {
return oazapfts.ok(oazapfts.fetchJson<{
status: 200;
data: BulkIdResponseDto[];
}>(`/memories/${encodeURIComponent(id)}/assets`, oazapfts.json({
...opts,
method: "DELETE",
body: bulkIdsDto
})));
}
export function addMemoryAssets({ id, bulkIdsDto }: {
id: string;
bulkIdsDto: BulkIdsDto;
}, opts?: Oazapfts.RequestOpts) {
return oazapfts.ok(oazapfts.fetchJson<{
status: 200;
data: BulkIdResponseDto[];
}>(`/memories/${encodeURIComponent(id)}/assets`, oazapfts.json({
...opts,
method: "PUT",
body: bulkIdsDto
})));
}
export function startOAuth({ oAuthConfigDto }: {
oAuthConfigDto: OAuthConfigDto;
}, opts?: Oazapfts.RequestOpts) {
@ -2802,8 +2916,8 @@ export enum PathEntityType {
}
export enum PathType {
Original = "original",
JpegThumbnail = "jpeg_thumbnail",
WebpThumbnail = "webp_thumbnail",
Preview = "preview",
Thumbnail = "thumbnail",
EncodedVideo = "encoded_video",
Sidecar = "sidecar",
Face = "face",
@ -2834,6 +2948,12 @@ export enum LibraryType {
Upload = "UPLOAD",
External = "EXTERNAL"
}
export enum Type2 {
OnThisDay = "on_this_day"
}
export enum MemoryType {
OnThisDay = "on_this_day"
}
export enum SearchSuggestionType {
Country = "country",
State = "state",
@ -2885,6 +3005,14 @@ export enum TranscodePolicy {
Required = "required",
Disabled = "disabled"
}
export enum Colorspace {
Srgb = "srgb",
P3 = "p3"
}
export enum ImageFormat {
Jpeg = "jpeg",
Webp = "webp"
}
export enum LogLevel {
Verbose = "verbose",
Debug = "debug",
@ -2901,10 +3029,6 @@ export enum ModelType {
FacialRecognition = "facial-recognition",
Clip = "clip"
}
export enum Colorspace {
Srgb = "srgb",
P3 = "p3"
}
export enum MapTheme {
Light = "light",
Dark = "dark"

View File

@ -24,7 +24,7 @@ RUN npm prune --omit=dev --omit=optional
COPY --from=dev /usr/src/app/node_modules/@img ./node_modules/@img
# web build
FROM node:iron-alpine3.18@sha256:876514790dabd49fae7d9c4dfbba027954bd91d8e7d36da76334466533bc6b0c as web
FROM node:iron-alpine3.18@sha256:fa5d3cf51725bd42d32e67917623038539dbe720dab082f590785c001eb4dfef as web
WORKDIR /usr/src/open-api/typescript-sdk
COPY open-api/typescript-sdk/package*.json open-api/typescript-sdk/tsconfig*.json ./

3
server/README.md Normal file
View File

@ -0,0 +1,3 @@
# Immich server project
This project uses the [NestJS](https://nestjs.com/) web framework. Please refer to [the NestJS docs](https://docs.nestjs.com/) for information on getting started as a contributor to this project.

896
server/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -167,6 +167,6 @@
"globalSetup": "<rootDir>/test/global-setup.js"
},
"volta": {
"node": "20.11.1"
"node": "20.12.0"
}
}

View File

@ -10,6 +10,7 @@ import { DownloadController } from 'src/controllers/download.controller';
import { FaceController } from 'src/controllers/face.controller';
import { JobController } from 'src/controllers/job.controller';
import { LibraryController } from 'src/controllers/library.controller';
import { MemoryController } from 'src/controllers/memory.controller';
import { OAuthController } from 'src/controllers/oauth.controller';
import { PartnerController } from 'src/controllers/partner.controller';
import { PersonController } from 'src/controllers/person.controller';
@ -36,6 +37,7 @@ export const controllers = [
FaceController,
JobController,
LibraryController,
MemoryController,
OAuthController,
PartnerController,
SearchController,

View File

@ -0,0 +1,64 @@
import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Post, Put } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import { BulkIdResponseDto, BulkIdsDto } from 'src/dtos/asset-ids.response.dto';
import { AuthDto } from 'src/dtos/auth.dto';
import { MemoryCreateDto, MemoryResponseDto, MemoryUpdateDto } from 'src/dtos/memory.dto';
import { Auth, Authenticated } from 'src/middleware/auth.guard';
import { MemoryService } from 'src/services/memory.service';
import { UUIDParamDto } from 'src/validation';
@ApiTags('Memory')
@Controller('memories')
@Authenticated()
export class MemoryController {
constructor(private service: MemoryService) {}
@Get()
searchMemories(@Auth() auth: AuthDto): Promise<MemoryResponseDto[]> {
return this.service.search(auth);
}
@Post()
createMemory(@Auth() auth: AuthDto, @Body() dto: MemoryCreateDto): Promise<MemoryResponseDto> {
return this.service.create(auth, dto);
}
@Get(':id')
getMemory(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<MemoryResponseDto> {
return this.service.get(auth, id);
}
@Put(':id')
updateMemory(
@Auth() auth: AuthDto,
@Param() { id }: UUIDParamDto,
@Body() dto: MemoryUpdateDto,
): Promise<MemoryResponseDto> {
return this.service.update(auth, id, dto);
}
@Delete(':id')
@HttpCode(HttpStatus.NO_CONTENT)
deleteMemory(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<void> {
return this.service.remove(auth, id);
}
@Put(':id/assets')
addMemoryAssets(
@Auth() auth: AuthDto,
@Param() { id }: UUIDParamDto,
@Body() dto: BulkIdsDto,
): Promise<BulkIdResponseDto[]> {
return this.service.addAssets(auth, id, dto);
}
@Delete(':id/assets')
@HttpCode(HttpStatus.OK)
removeMemoryAssets(
@Auth() auth: AuthDto,
@Body() dto: BulkIdsDto,
@Param() { id }: UUIDParamDto,
): Promise<BulkIdResponseDto[]> {
return this.service.removeAssets(auth, id, dto);
}
}

View File

@ -33,6 +33,10 @@ export enum Permission {
TIMELINE_READ = 'timeline.read',
TIMELINE_DOWNLOAD = 'timeline.download',
MEMORY_READ = 'memory.read',
MEMORY_WRITE = 'memory.write',
MEMORY_DELETE = 'memory.delete',
PERSON_READ = 'person.read',
PERSON_WRITE = 'person.write',
PERSON_MERGE = 'person.merge',
@ -259,6 +263,18 @@ export class AccessCore {
return ids.has(auth.user.id) ? new Set([auth.user.id]) : new Set();
}
case Permission.MEMORY_READ: {
return this.repository.memory.checkOwnerAccess(auth.user.id, ids);
}
case Permission.MEMORY_WRITE: {
return this.repository.memory.checkOwnerAccess(auth.user.id, ids);
}
case Permission.MEMORY_DELETE: {
return this.repository.memory.checkOwnerAccess(auth.user.id, ids);
}
case Permission.PERSON_READ: {
return await this.repository.person.checkOwnerAccess(auth.user.id, ids);
}

View File

@ -4,6 +4,7 @@ import { SystemConfigCore } from 'src/cores/system-config.core';
import { AssetEntity } from 'src/entities/asset.entity';
import { AssetPathType, PathType, PersonPathType } from 'src/entities/move.entity';
import { PersonEntity } from 'src/entities/person.entity';
import { ImageFormat } from 'src/entities/system-config.entity';
import { IAssetRepository } from 'src/interfaces/asset.interface';
import { ICryptoRepository } from 'src/interfaces/crypto.interface';
import { IMoveRepository } from 'src/interfaces/move.interface';
@ -34,7 +35,8 @@ export interface MoveRequest {
};
}
type GeneratedAssetPath = AssetPathType.JPEG_THUMBNAIL | AssetPathType.WEBP_THUMBNAIL | AssetPathType.ENCODED_VIDEO;
export type GeneratedImageType = AssetPathType.PREVIEW | AssetPathType.THUMBNAIL;
export type GeneratedAssetType = GeneratedImageType | AssetPathType.ENCODED_VIDEO;
let instance: StorageCore | null;
@ -94,12 +96,8 @@ export class StorageCore {
return StorageCore.getNestedPath(StorageFolder.THUMBNAILS, person.ownerId, `${person.id}.jpeg`);
}
static getLargeThumbnailPath(asset: AssetEntity) {
return StorageCore.getNestedPath(StorageFolder.THUMBNAILS, asset.ownerId, `${asset.id}.jpeg`);
}
static getSmallThumbnailPath(asset: AssetEntity) {
return StorageCore.getNestedPath(StorageFolder.THUMBNAILS, asset.ownerId, `${asset.id}.webp`);
static getImagePath(asset: AssetEntity, type: GeneratedImageType, format: ImageFormat) {
return StorageCore.getNestedPath(StorageFolder.THUMBNAILS, asset.ownerId, `${asset.id}-${type}.${format}`);
}
static getEncodedVideoPath(asset: AssetEntity) {
@ -128,34 +126,23 @@ export class StorageCore {
return path.startsWith(THUMBNAIL_DIR) || path.startsWith(ENCODED_VIDEO_DIR);
}
async moveAssetFile(asset: AssetEntity, pathType: GeneratedAssetPath) {
const { id: entityId, resizePath, webpPath, encodedVideoPath } = asset;
switch (pathType) {
case AssetPathType.JPEG_THUMBNAIL: {
return this.moveFile({
entityId,
pathType,
oldPath: resizePath,
newPath: StorageCore.getLargeThumbnailPath(asset),
});
}
case AssetPathType.WEBP_THUMBNAIL: {
return this.moveFile({
entityId,
pathType,
oldPath: webpPath,
newPath: StorageCore.getSmallThumbnailPath(asset),
});
}
case AssetPathType.ENCODED_VIDEO: {
return this.moveFile({
entityId,
pathType,
oldPath: encodedVideoPath,
newPath: StorageCore.getEncodedVideoPath(asset),
});
}
}
async moveAssetImage(asset: AssetEntity, pathType: GeneratedImageType, format: ImageFormat) {
const { id: entityId, previewPath, thumbnailPath } = asset;
return this.moveFile({
entityId,
pathType,
oldPath: pathType === AssetPathType.PREVIEW ? previewPath : thumbnailPath,
newPath: StorageCore.getImagePath(asset, AssetPathType.THUMBNAIL, format),
});
}
async moveAssetVideo(asset: AssetEntity) {
return this.moveFile({
entityId: asset.id,
pathType: AssetPathType.ENCODED_VIDEO,
oldPath: asset.encodedVideoPath,
newPath: StorageCore.getEncodedVideoPath(asset),
});
}
async movePersonFile(person: PersonEntity, pathType: PersonPathType) {
@ -294,11 +281,11 @@ export class StorageCore {
case AssetPathType.ORIGINAL: {
return this.assetRepository.update({ id, originalPath: newPath });
}
case AssetPathType.JPEG_THUMBNAIL: {
return this.assetRepository.update({ id, resizePath: newPath });
case AssetPathType.PREVIEW: {
return this.assetRepository.update({ id, previewPath: newPath });
}
case AssetPathType.WEBP_THUMBNAIL: {
return this.assetRepository.update({ id, webpPath: newPath });
case AssetPathType.THUMBNAIL: {
return this.assetRepository.update({ id, thumbnailPath: newPath });
}
case AssetPathType.ENCODED_VIDEO: {
return this.assetRepository.update({ id, encodedVideoPath: newPath });

View File

@ -10,6 +10,7 @@ import {
AudioCodec,
CQMode,
Colorspace,
ImageFormat,
LogLevel,
SystemConfig,
SystemConfigEntity,
@ -112,9 +113,11 @@ export const defaults = Object.freeze<SystemConfig>({
hashVerificationEnabled: true,
template: '{{y}}/{{y}}-{{MM}}-{{dd}}/{{filename}}',
},
thumbnail: {
webpSize: 250,
jpegSize: 1440,
image: {
thumbnailFormat: ImageFormat.WEBP,
thumbnailSize: 250,
previewFormat: ImageFormat.JPEG,
previewSize: 1440,
quality: 80,
colorspace: Colorspace.P3,
},

View File

@ -82,7 +82,7 @@ export function mapAsset(entity: AssetEntity, options: AssetMapOptions = {}): As
type: entity.type,
thumbhash: entity.thumbhash?.toString('base64') ?? null,
localDateTime: entity.localDateTime,
resized: !!entity.resizePath,
resized: !!entity.previewPath,
duration: entity.duration ?? '0:00:00.00000',
livePhotoVideoId: entity.livePhotoVideoId,
hasMetadata: false,
@ -100,7 +100,7 @@ export function mapAsset(entity: AssetEntity, options: AssetMapOptions = {}): As
type: entity.type,
originalPath: entity.originalPath,
originalFileName: entity.originalFileName,
resized: !!entity.resizePath,
resized: !!entity.previewPath,
thumbhash: entity.thumbhash?.toString('base64') ?? null,
fileCreatedAt: entity.fileCreatedAt,
fileModifiedAt: entity.fileModifiedAt,

View File

@ -0,0 +1,84 @@
import { ApiProperty } from '@nestjs/swagger';
import { Type } from 'class-transformer';
import { IsEnum, IsInt, IsObject, IsPositive, ValidateNested } from 'class-validator';
import { AssetResponseDto, mapAsset } from 'src/dtos/asset-response.dto';
import { MemoryEntity, MemoryType } from 'src/entities/memory.entity';
import { ValidateBoolean, ValidateDate, ValidateUUID } from 'src/validation';
class MemoryBaseDto {
@ValidateBoolean({ optional: true })
isSaved?: boolean;
@ValidateDate({ optional: true })
seenAt?: Date;
}
class OnThisDayDto {
@IsInt()
@IsPositive()
year!: number;
}
type MemoryData = OnThisDayDto;
export class MemoryUpdateDto extends MemoryBaseDto {
@ValidateDate({ optional: true })
memoryAt?: Date;
}
export class MemoryCreateDto extends MemoryBaseDto {
@IsEnum(MemoryType)
@ApiProperty({ enum: MemoryType, enumName: 'MemoryType' })
type!: MemoryType;
@IsObject()
@ValidateNested()
@Type((options) => {
switch (options?.object.type) {
case MemoryType.ON_THIS_DAY: {
return OnThisDayDto;
}
default: {
return Object;
}
}
})
data!: MemoryData;
@ValidateDate()
memoryAt!: Date;
@ValidateUUID({ optional: true, each: true })
assetIds?: string[];
}
export class MemoryResponseDto {
id!: string;
createdAt!: Date;
updatedAt!: Date;
deletedAt?: Date;
memoryAt!: Date;
seenAt?: Date;
ownerId!: string;
type!: MemoryType;
data!: MemoryData;
isSaved!: boolean;
assets!: AssetResponseDto[];
}
export const mapMemory = (entity: MemoryEntity): MemoryResponseDto => {
return {
id: entity.id,
createdAt: entity.createdAt,
updatedAt: entity.updatedAt,
deletedAt: entity.deletedAt,
memoryAt: entity.memoryAt,
seenAt: entity.seenAt,
ownerId: entity.ownerId,
type: entity.type,
data: entity.data,
isSaved: entity.isSaved,
assets: entity.assets.map((asset) => mapAsset(asset)),
};
};

View File

@ -163,13 +163,25 @@ export class MetadataSearchDto extends BaseSearchDto {
@IsString()
@IsNotEmpty()
@Optional()
@ApiProperty({ deprecated: true })
resizePath?: string;
@IsString()
@IsNotEmpty()
@Optional()
@ApiProperty({ deprecated: true })
webpPath?: string;
@IsString()
@IsNotEmpty()
@Optional()
previewPath?: string;
@IsString()
@IsNotEmpty()
@Optional()
thumbnailPath?: string;
@IsString()
@IsNotEmpty()
@Optional()

View File

@ -22,6 +22,7 @@ import {
AudioCodec,
CQMode,
Colorspace,
ImageFormat,
LogLevel,
SystemConfig,
ToneMapping,
@ -385,18 +386,26 @@ export class SystemConfigThemeDto {
customCss!: string;
}
class SystemConfigThumbnailDto {
@IsInt()
@Min(1)
@Type(() => Number)
@ApiProperty({ type: 'integer' })
webpSize!: number;
class SystemConfigImageDto {
@IsEnum(ImageFormat)
@ApiProperty({ enumName: 'ImageFormat', enum: ImageFormat })
thumbnailFormat!: ImageFormat;
@IsInt()
@Min(1)
@Type(() => Number)
@ApiProperty({ type: 'integer' })
jpegSize!: number;
thumbnailSize!: number;
@IsEnum(ImageFormat)
@ApiProperty({ enumName: 'ImageFormat', enum: ImageFormat })
previewFormat!: ImageFormat;
@IsInt()
@Min(1)
@Type(() => Number)
@ApiProperty({ type: 'integer' })
previewSize!: number;
@IsInt()
@Min(1)
@ -480,10 +489,10 @@ export class SystemConfigDto implements SystemConfig {
@IsObject()
job!: SystemConfigJobDto;
@Type(() => SystemConfigThumbnailDto)
@Type(() => SystemConfigImageDto)
@ValidateNested()
@IsObject()
thumbnail!: SystemConfigThumbnailDto;
image!: SystemConfigImageDto;
@Type(() => SystemConfigTrashDto)
@ValidateNested()

View File

@ -67,10 +67,10 @@ export class AssetEntity {
originalPath!: string;
@Column({ type: 'varchar', nullable: true })
resizePath!: string | null;
previewPath!: string | null;
@Column({ type: 'varchar', nullable: true, default: '' })
webpPath!: string | null;
thumbnailPath!: string | null;
@Column({ type: 'bytea', nullable: true })
thumbhash!: Buffer | null;

View File

@ -9,6 +9,7 @@ import { AuditEntity } from 'src/entities/audit.entity';
import { ExifEntity } from 'src/entities/exif.entity';
import { GeodataPlacesEntity } from 'src/entities/geodata-places.entity';
import { LibraryEntity } from 'src/entities/library.entity';
import { MemoryEntity } from 'src/entities/memory.entity';
import { MoveEntity } from 'src/entities/move.entity';
import { PartnerEntity } from 'src/entities/partner.entity';
import { PersonEntity } from 'src/entities/person.entity';
@ -32,6 +33,7 @@ export const entities = [
AuditEntity,
ExifEntity,
GeodataPlacesEntity,
MemoryEntity,
MoveEntity,
PartnerEntity,
PersonEntity,

View File

@ -0,0 +1,67 @@
import { AssetEntity } from 'src/entities/asset.entity';
import { UserEntity } from 'src/entities/user.entity';
import {
Column,
CreateDateColumn,
DeleteDateColumn,
Entity,
JoinTable,
ManyToMany,
ManyToOne,
PrimaryGeneratedColumn,
UpdateDateColumn,
} from 'typeorm';
export enum MemoryType {
/** pictures taken on this day X years ago */
ON_THIS_DAY = 'on_this_day',
}
export type OnThisDayData = { year: number };
export interface MemoryData {
[MemoryType.ON_THIS_DAY]: OnThisDayData;
}
@Entity('memories')
export class MemoryEntity<T extends MemoryType = MemoryType> {
@PrimaryGeneratedColumn('uuid')
id!: string;
@CreateDateColumn({ type: 'timestamptz' })
createdAt!: Date;
@UpdateDateColumn({ type: 'timestamptz' })
updatedAt!: Date;
@DeleteDateColumn({ type: 'timestamptz' })
deletedAt?: Date;
@ManyToOne(() => UserEntity, { onDelete: 'CASCADE', onUpdate: 'CASCADE', nullable: false })
owner!: UserEntity;
@Column()
ownerId!: string;
@Column()
type!: T;
@Column({ type: 'jsonb' })
data!: MemoryData[T];
/** unless set to true, will be automatically deleted in the future */
@Column({ default: false })
isSaved!: boolean;
/** memories are sorted in ascending order by this value */
@Column({ type: 'timestamptz' })
memoryAt!: Date;
/** when the user last viewed the memory */
@Column({ type: 'timestamptz', nullable: true })
seenAt?: Date;
@ManyToMany(() => AssetEntity)
@JoinTable()
assets!: AssetEntity[];
}

View File

@ -24,8 +24,8 @@ export class MoveEntity {
export enum AssetPathType {
ORIGINAL = 'original',
JPEG_THUMBNAIL = 'jpeg_thumbnail',
WEBP_THUMBNAIL = 'webp_thumbnail',
PREVIEW = 'preview',
THUMBNAIL = 'thumbnail',
ENCODED_VIDEO = 'encoded_video',
SIDECAR = 'sidecar',
}

View File

@ -165,6 +165,11 @@ export enum Colorspace {
P3 = 'p3',
}
export enum ImageFormat {
JPEG = 'jpeg',
WEBP = 'webp',
}
export enum LogLevel {
VERBOSE = 'verbose',
DEBUG = 'debug',
@ -249,9 +254,11 @@ export interface SystemConfig {
hashVerificationEnabled: boolean;
template: string;
};
thumbnail: {
webpSize: number;
jpegSize: number;
image: {
thumbnailFormat: ImageFormat;
thumbnailSize: number;
previewFormat: ImageFormat;
previewSize: number;
quality: number;
colorspace: Colorspace;
};

View File

@ -32,6 +32,10 @@ export interface IAccessRepository {
checkPartnerAccess(userId: string, partnerIds: Set<string>): Promise<Set<string>>;
};
memory: {
checkOwnerAccess(userId: string, memoryIds: Set<string>): Promise<Set<string>>;
};
person: {
checkFaceOwnerAccess(userId: string, assetFaceId: Set<string>): Promise<Set<string>>;
checkOwnerAccess(userId: string, personIds: Set<string>): Promise<Set<string>>;

View File

@ -33,9 +33,9 @@ export enum JobName {
// thumbnails
QUEUE_GENERATE_THUMBNAILS = 'queue-generate-thumbnails',
GENERATE_JPEG_THUMBNAIL = 'generate-jpeg-thumbnail',
GENERATE_WEBP_THUMBNAIL = 'generate-webp-thumbnail',
GENERATE_THUMBHASH_THUMBNAIL = 'generate-thumbhash-thumbnail',
GENERATE_PREVIEW = 'generate-preview',
GENERATE_THUMBNAIL = 'generate-thumbnail',
GENERATE_THUMBHASH = 'generate-thumbhash',
GENERATE_PERSON_THUMBNAIL = 'generate-person-thumbnail',
// metadata
@ -165,9 +165,9 @@ export type JobItem =
// Thumbnails
| { name: JobName.QUEUE_GENERATE_THUMBNAILS; data: IBaseJob }
| { name: JobName.GENERATE_JPEG_THUMBNAIL; data: IEntityJob }
| { name: JobName.GENERATE_WEBP_THUMBNAIL; data: IEntityJob }
| { name: JobName.GENERATE_THUMBHASH_THUMBNAIL; data: IEntityJob }
| { name: JobName.GENERATE_PREVIEW; data: IEntityJob }
| { name: JobName.GENERATE_THUMBNAIL; data: IEntityJob }
| { name: JobName.GENERATE_THUMBHASH; data: IEntityJob }
// User
| { name: JobName.USER_DELETE_CHECK; data?: IBaseJob }

View File

@ -1,11 +1,11 @@
import { Writable } from 'node:stream';
import { TranscodeTarget, VideoCodec } from 'src/entities/system-config.entity';
import { ImageFormat, TranscodeTarget, VideoCodec } from 'src/entities/system-config.entity';
export const IMediaRepository = 'IMediaRepository';
export interface ResizeOptions {
size: number;
format: 'webp' | 'jpeg';
format: ImageFormat;
colorspace: string;
quality: number;
}

View File

@ -0,0 +1,14 @@
import { MemoryEntity } from 'src/entities/memory.entity';
export const IMemoryRepository = 'IMemoryRepository';
export interface IMemoryRepository {
search(ownerId: string): Promise<MemoryEntity[]>;
get(id: string): Promise<MemoryEntity | null>;
create(memory: Partial<MemoryEntity>): Promise<MemoryEntity>;
update(memory: Partial<MemoryEntity>): Promise<MemoryEntity>;
delete(id: string): Promise<void>;
getAssetIds(id: string, assetIds: string[]): Promise<Set<string>>;
addAssetIds(id: string, assetIds: string[]): Promise<void>;
removeAssetIds(id: string, assetIds: string[]): Promise<void>;
}

View File

@ -117,8 +117,8 @@ export interface SearchPathOptions {
encodedVideoPath?: string;
originalFileName?: string;
originalPath?: string;
resizePath?: string;
webpPath?: string;
previewPath?: string;
thumbnailPath?: string;
}
export interface SearchExifOptions {

View File

@ -0,0 +1,51 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
export class RenameWebpJpegPaths1711257900274 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.renameColumn('assets', 'webpPath', 'thumbnailPath');
await queryRunner.renameColumn('assets', 'resizePath', 'previewPath');
await queryRunner.query(`
UPDATE system_config
SET key = 'image.previewSize'
WHERE key = 'thumbnail.jpegSize'`);
await queryRunner.query(
`UPDATE system_config
SET key = 'image.thumbnailSize'
WHERE key = 'thumbnail.webpSize'`,
);
await queryRunner.query(
`UPDATE system_config
SET key = 'image.quality'
WHERE key = 'thumbnail.quality'`,
);
await queryRunner.query(
`UPDATE system_config
SET key = 'image.colorspace'
WHERE key = 'thumbnail.colorspace'`,
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.renameColumn('assets', 'thumbnailPath', 'webpPath');
await queryRunner.renameColumn('assets', 'previewPath', 'resizePath');
await queryRunner.query(`
UPDATE system_config
SET key = 'thumbnail.jpegSize'
WHERE key = 'image.previewSize'`);
await queryRunner.query(
`UPDATE system_config
SET key = 'thumbnail.webpSize'
WHERE key = 'image.thumbnailSize'`,
);
await queryRunner.query(
`UPDATE system_config
SET key = 'thumbnail.quality'
WHERE key = 'image.quality'`,
);
await queryRunner.query(
`UPDATE system_config
SET key = 'thumbnail.colorspace'
WHERE key = 'image.colorspace'`,
);
}
}

View File

@ -0,0 +1,26 @@
import { MigrationInterface, QueryRunner } from "typeorm";
export class AddMemoryTable1711637874206 implements MigrationInterface {
name = 'AddMemoryTable1711637874206'
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`CREATE TABLE "memories" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "deletedAt" TIMESTAMP WITH TIME ZONE, "ownerId" uuid NOT NULL, "type" character varying NOT NULL, "data" jsonb NOT NULL, "isSaved" boolean NOT NULL DEFAULT false, "memoryAt" TIMESTAMP WITH TIME ZONE NOT NULL, "seenAt" TIMESTAMP WITH TIME ZONE, CONSTRAINT "PK_aaa0692d9496fe827b0568612f8" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE TABLE "memories_assets_assets" ("memoriesId" uuid NOT NULL, "assetsId" uuid NOT NULL, CONSTRAINT "PK_fcaf7112a013d1703c011c6793d" PRIMARY KEY ("memoriesId", "assetsId"))`);
await queryRunner.query(`CREATE INDEX "IDX_984e5c9ab1f04d34538cd32334" ON "memories_assets_assets" ("memoriesId") `);
await queryRunner.query(`CREATE INDEX "IDX_6942ecf52d75d4273de19d2c16" ON "memories_assets_assets" ("assetsId") `);
await queryRunner.query(`ALTER TABLE "memories" ADD CONSTRAINT "FK_575842846f0c28fa5da46c99b19" FOREIGN KEY ("ownerId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE`);
await queryRunner.query(`ALTER TABLE "memories_assets_assets" ADD CONSTRAINT "FK_984e5c9ab1f04d34538cd32334e" FOREIGN KEY ("memoriesId") REFERENCES "memories"("id") ON DELETE CASCADE ON UPDATE CASCADE`);
await queryRunner.query(`ALTER TABLE "memories_assets_assets" ADD CONSTRAINT "FK_6942ecf52d75d4273de19d2c16f" FOREIGN KEY ("assetsId") REFERENCES "assets"("id") ON DELETE CASCADE ON UPDATE CASCADE`);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "memories_assets_assets" DROP CONSTRAINT "FK_6942ecf52d75d4273de19d2c16f"`);
await queryRunner.query(`ALTER TABLE "memories_assets_assets" DROP CONSTRAINT "FK_984e5c9ab1f04d34538cd32334e"`);
await queryRunner.query(`ALTER TABLE "memories" DROP CONSTRAINT "FK_575842846f0c28fa5da46c99b19"`);
await queryRunner.query(`DROP INDEX "public"."IDX_6942ecf52d75d4273de19d2c16"`);
await queryRunner.query(`DROP INDEX "public"."IDX_984e5c9ab1f04d34538cd32334"`);
await queryRunner.query(`DROP TABLE "memories_assets_assets"`);
await queryRunner.query(`DROP TABLE "memories"`);
}
}

View File

@ -196,6 +196,20 @@ WHERE
)
AND ("LibraryEntity"."deletedAt" IS NULL)
-- AccessRepository.memory.checkOwnerAccess
SELECT
"MemoryEntity"."id" AS "MemoryEntity_id"
FROM
"memories" "MemoryEntity"
WHERE
(
(
("MemoryEntity"."id" IN ($1))
AND ("MemoryEntity"."ownerId" = $2)
)
)
AND ("MemoryEntity"."deletedAt" IS NULL)
-- AccessRepository.person.checkOwnerAccess
SELECT
"PersonEntity"."id" AS "PersonEntity_id"

View File

@ -9,8 +9,8 @@ SELECT
"entity"."deviceId" AS "entity_deviceId",
"entity"."type" AS "entity_type",
"entity"."originalPath" AS "entity_originalPath",
"entity"."resizePath" AS "entity_resizePath",
"entity"."webpPath" AS "entity_webpPath",
"entity"."previewPath" AS "entity_previewPath",
"entity"."thumbnailPath" AS "entity_thumbnailPath",
"entity"."thumbhash" AS "entity_thumbhash",
"entity"."encodedVideoPath" AS "entity_encodedVideoPath",
"entity"."createdAt" AS "entity_createdAt",
@ -67,7 +67,7 @@ WHERE
"entity"."ownerId" IN ($1)
AND "entity"."isVisible" = true
AND "entity"."isArchived" = false
AND "entity"."resizePath" IS NOT NULL
AND "entity"."previewPath" IS NOT NULL
AND EXTRACT(
DAY
FROM
@ -92,8 +92,8 @@ SELECT
"AssetEntity"."deviceId" AS "AssetEntity_deviceId",
"AssetEntity"."type" AS "AssetEntity_type",
"AssetEntity"."originalPath" AS "AssetEntity_originalPath",
"AssetEntity"."resizePath" AS "AssetEntity_resizePath",
"AssetEntity"."webpPath" AS "AssetEntity_webpPath",
"AssetEntity"."previewPath" AS "AssetEntity_previewPath",
"AssetEntity"."thumbnailPath" AS "AssetEntity_thumbnailPath",
"AssetEntity"."thumbhash" AS "AssetEntity_thumbhash",
"AssetEntity"."encodedVideoPath" AS "AssetEntity_encodedVideoPath",
"AssetEntity"."createdAt" AS "AssetEntity_createdAt",
@ -128,8 +128,8 @@ SELECT
"AssetEntity"."deviceId" AS "AssetEntity_deviceId",
"AssetEntity"."type" AS "AssetEntity_type",
"AssetEntity"."originalPath" AS "AssetEntity_originalPath",
"AssetEntity"."resizePath" AS "AssetEntity_resizePath",
"AssetEntity"."webpPath" AS "AssetEntity_webpPath",
"AssetEntity"."previewPath" AS "AssetEntity_previewPath",
"AssetEntity"."thumbnailPath" AS "AssetEntity_thumbnailPath",
"AssetEntity"."thumbhash" AS "AssetEntity_thumbhash",
"AssetEntity"."encodedVideoPath" AS "AssetEntity_encodedVideoPath",
"AssetEntity"."createdAt" AS "AssetEntity_createdAt",
@ -213,8 +213,8 @@ SELECT
"bd93d5747511a4dad4923546c51365bf1a803774"."deviceId" AS "bd93d5747511a4dad4923546c51365bf1a803774_deviceId",
"bd93d5747511a4dad4923546c51365bf1a803774"."type" AS "bd93d5747511a4dad4923546c51365bf1a803774_type",
"bd93d5747511a4dad4923546c51365bf1a803774"."originalPath" AS "bd93d5747511a4dad4923546c51365bf1a803774_originalPath",
"bd93d5747511a4dad4923546c51365bf1a803774"."resizePath" AS "bd93d5747511a4dad4923546c51365bf1a803774_resizePath",
"bd93d5747511a4dad4923546c51365bf1a803774"."webpPath" AS "bd93d5747511a4dad4923546c51365bf1a803774_webpPath",
"bd93d5747511a4dad4923546c51365bf1a803774"."previewPath" AS "bd93d5747511a4dad4923546c51365bf1a803774_previewPath",
"bd93d5747511a4dad4923546c51365bf1a803774"."thumbnailPath" AS "bd93d5747511a4dad4923546c51365bf1a803774_thumbnailPath",
"bd93d5747511a4dad4923546c51365bf1a803774"."thumbhash" AS "bd93d5747511a4dad4923546c51365bf1a803774_thumbhash",
"bd93d5747511a4dad4923546c51365bf1a803774"."encodedVideoPath" AS "bd93d5747511a4dad4923546c51365bf1a803774_encodedVideoPath",
"bd93d5747511a4dad4923546c51365bf1a803774"."createdAt" AS "bd93d5747511a4dad4923546c51365bf1a803774_createdAt",
@ -294,8 +294,8 @@ FROM
"AssetEntity"."deviceId" AS "AssetEntity_deviceId",
"AssetEntity"."type" AS "AssetEntity_type",
"AssetEntity"."originalPath" AS "AssetEntity_originalPath",
"AssetEntity"."resizePath" AS "AssetEntity_resizePath",
"AssetEntity"."webpPath" AS "AssetEntity_webpPath",
"AssetEntity"."previewPath" AS "AssetEntity_previewPath",
"AssetEntity"."thumbnailPath" AS "AssetEntity_thumbnailPath",
"AssetEntity"."thumbhash" AS "AssetEntity_thumbhash",
"AssetEntity"."encodedVideoPath" AS "AssetEntity_encodedVideoPath",
"AssetEntity"."createdAt" AS "AssetEntity_createdAt",
@ -391,8 +391,8 @@ SELECT
"AssetEntity"."deviceId" AS "AssetEntity_deviceId",
"AssetEntity"."type" AS "AssetEntity_type",
"AssetEntity"."originalPath" AS "AssetEntity_originalPath",
"AssetEntity"."resizePath" AS "AssetEntity_resizePath",
"AssetEntity"."webpPath" AS "AssetEntity_webpPath",
"AssetEntity"."previewPath" AS "AssetEntity_previewPath",
"AssetEntity"."thumbnailPath" AS "AssetEntity_thumbnailPath",
"AssetEntity"."thumbhash" AS "AssetEntity_thumbhash",
"AssetEntity"."encodedVideoPath" AS "AssetEntity_encodedVideoPath",
"AssetEntity"."createdAt" AS "AssetEntity_createdAt",
@ -437,8 +437,8 @@ SELECT
"AssetEntity"."deviceId" AS "AssetEntity_deviceId",
"AssetEntity"."type" AS "AssetEntity_type",
"AssetEntity"."originalPath" AS "AssetEntity_originalPath",
"AssetEntity"."resizePath" AS "AssetEntity_resizePath",
"AssetEntity"."webpPath" AS "AssetEntity_webpPath",
"AssetEntity"."previewPath" AS "AssetEntity_previewPath",
"AssetEntity"."thumbnailPath" AS "AssetEntity_thumbnailPath",
"AssetEntity"."thumbhash" AS "AssetEntity_thumbhash",
"AssetEntity"."encodedVideoPath" AS "AssetEntity_encodedVideoPath",
"AssetEntity"."createdAt" AS "AssetEntity_createdAt",
@ -481,8 +481,8 @@ SELECT
"AssetEntity"."deviceId" AS "AssetEntity_deviceId",
"AssetEntity"."type" AS "AssetEntity_type",
"AssetEntity"."originalPath" AS "AssetEntity_originalPath",
"AssetEntity"."resizePath" AS "AssetEntity_resizePath",
"AssetEntity"."webpPath" AS "AssetEntity_webpPath",
"AssetEntity"."previewPath" AS "AssetEntity_previewPath",
"AssetEntity"."thumbnailPath" AS "AssetEntity_thumbnailPath",
"AssetEntity"."thumbhash" AS "AssetEntity_thumbhash",
"AssetEntity"."encodedVideoPath" AS "AssetEntity_encodedVideoPath",
"AssetEntity"."createdAt" AS "AssetEntity_createdAt",
@ -570,8 +570,8 @@ SELECT
"asset"."deviceId" AS "asset_deviceId",
"asset"."type" AS "asset_type",
"asset"."originalPath" AS "asset_originalPath",
"asset"."resizePath" AS "asset_resizePath",
"asset"."webpPath" AS "asset_webpPath",
"asset"."previewPath" AS "asset_previewPath",
"asset"."thumbnailPath" AS "asset_thumbnailPath",
"asset"."thumbhash" AS "asset_thumbhash",
"asset"."encodedVideoPath" AS "asset_encodedVideoPath",
"asset"."createdAt" AS "asset_createdAt",
@ -629,8 +629,8 @@ SELECT
"stackedAssets"."deviceId" AS "stackedAssets_deviceId",
"stackedAssets"."type" AS "stackedAssets_type",
"stackedAssets"."originalPath" AS "stackedAssets_originalPath",
"stackedAssets"."resizePath" AS "stackedAssets_resizePath",
"stackedAssets"."webpPath" AS "stackedAssets_webpPath",
"stackedAssets"."previewPath" AS "stackedAssets_previewPath",
"stackedAssets"."thumbnailPath" AS "stackedAssets_thumbnailPath",
"stackedAssets"."thumbhash" AS "stackedAssets_thumbhash",
"stackedAssets"."encodedVideoPath" AS "stackedAssets_encodedVideoPath",
"stackedAssets"."createdAt" AS "stackedAssets_createdAt",

View File

@ -0,0 +1,18 @@
-- NOTE: This file is auto generated by ./sql-generator
-- MemoryRepository.getAssetIds
SELECT
"memories_assets"."assetsId" AS "assetId"
FROM
"memories_assets_assets" "memories_assets"
WHERE
"memories_assets"."memoriesId" = $1
AND "memories_assets"."assetsId" IN ($2)
-- MemoryRepository.removeAssetIds
DELETE FROM "memories_assets_assets"
WHERE
(
"memoriesId" = $1
AND "assetsId" IN ($2)
)

View File

@ -152,8 +152,8 @@ FROM
"AssetFaceEntity__AssetFaceEntity_asset"."deviceId" AS "AssetFaceEntity__AssetFaceEntity_asset_deviceId",
"AssetFaceEntity__AssetFaceEntity_asset"."type" AS "AssetFaceEntity__AssetFaceEntity_asset_type",
"AssetFaceEntity__AssetFaceEntity_asset"."originalPath" AS "AssetFaceEntity__AssetFaceEntity_asset_originalPath",
"AssetFaceEntity__AssetFaceEntity_asset"."resizePath" AS "AssetFaceEntity__AssetFaceEntity_asset_resizePath",
"AssetFaceEntity__AssetFaceEntity_asset"."webpPath" AS "AssetFaceEntity__AssetFaceEntity_asset_webpPath",
"AssetFaceEntity__AssetFaceEntity_asset"."previewPath" AS "AssetFaceEntity__AssetFaceEntity_asset_previewPath",
"AssetFaceEntity__AssetFaceEntity_asset"."thumbnailPath" AS "AssetFaceEntity__AssetFaceEntity_asset_thumbnailPath",
"AssetFaceEntity__AssetFaceEntity_asset"."thumbhash" AS "AssetFaceEntity__AssetFaceEntity_asset_thumbhash",
"AssetFaceEntity__AssetFaceEntity_asset"."encodedVideoPath" AS "AssetFaceEntity__AssetFaceEntity_asset_encodedVideoPath",
"AssetFaceEntity__AssetFaceEntity_asset"."createdAt" AS "AssetFaceEntity__AssetFaceEntity_asset_createdAt",
@ -250,8 +250,8 @@ FROM
"AssetEntity"."deviceId" AS "AssetEntity_deviceId",
"AssetEntity"."type" AS "AssetEntity_type",
"AssetEntity"."originalPath" AS "AssetEntity_originalPath",
"AssetEntity"."resizePath" AS "AssetEntity_resizePath",
"AssetEntity"."webpPath" AS "AssetEntity_webpPath",
"AssetEntity"."previewPath" AS "AssetEntity_previewPath",
"AssetEntity"."thumbnailPath" AS "AssetEntity_thumbnailPath",
"AssetEntity"."thumbhash" AS "AssetEntity_thumbhash",
"AssetEntity"."encodedVideoPath" AS "AssetEntity_encodedVideoPath",
"AssetEntity"."createdAt" AS "AssetEntity_createdAt",
@ -380,8 +380,8 @@ SELECT
"AssetFaceEntity__AssetFaceEntity_asset"."deviceId" AS "AssetFaceEntity__AssetFaceEntity_asset_deviceId",
"AssetFaceEntity__AssetFaceEntity_asset"."type" AS "AssetFaceEntity__AssetFaceEntity_asset_type",
"AssetFaceEntity__AssetFaceEntity_asset"."originalPath" AS "AssetFaceEntity__AssetFaceEntity_asset_originalPath",
"AssetFaceEntity__AssetFaceEntity_asset"."resizePath" AS "AssetFaceEntity__AssetFaceEntity_asset_resizePath",
"AssetFaceEntity__AssetFaceEntity_asset"."webpPath" AS "AssetFaceEntity__AssetFaceEntity_asset_webpPath",
"AssetFaceEntity__AssetFaceEntity_asset"."previewPath" AS "AssetFaceEntity__AssetFaceEntity_asset_previewPath",
"AssetFaceEntity__AssetFaceEntity_asset"."thumbnailPath" AS "AssetFaceEntity__AssetFaceEntity_asset_thumbnailPath",
"AssetFaceEntity__AssetFaceEntity_asset"."thumbhash" AS "AssetFaceEntity__AssetFaceEntity_asset_thumbhash",
"AssetFaceEntity__AssetFaceEntity_asset"."encodedVideoPath" AS "AssetFaceEntity__AssetFaceEntity_asset_encodedVideoPath",
"AssetFaceEntity__AssetFaceEntity_asset"."createdAt" AS "AssetFaceEntity__AssetFaceEntity_asset_createdAt",

View File

@ -14,8 +14,8 @@ FROM
"asset"."deviceId" AS "asset_deviceId",
"asset"."type" AS "asset_type",
"asset"."originalPath" AS "asset_originalPath",
"asset"."resizePath" AS "asset_resizePath",
"asset"."webpPath" AS "asset_webpPath",
"asset"."previewPath" AS "asset_previewPath",
"asset"."thumbnailPath" AS "asset_thumbnailPath",
"asset"."thumbhash" AS "asset_thumbhash",
"asset"."encodedVideoPath" AS "asset_encodedVideoPath",
"asset"."createdAt" AS "asset_createdAt",
@ -45,8 +45,8 @@ FROM
"stackedAssets"."deviceId" AS "stackedAssets_deviceId",
"stackedAssets"."type" AS "stackedAssets_type",
"stackedAssets"."originalPath" AS "stackedAssets_originalPath",
"stackedAssets"."resizePath" AS "stackedAssets_resizePath",
"stackedAssets"."webpPath" AS "stackedAssets_webpPath",
"stackedAssets"."previewPath" AS "stackedAssets_previewPath",
"stackedAssets"."thumbnailPath" AS "stackedAssets_thumbnailPath",
"stackedAssets"."thumbhash" AS "stackedAssets_thumbhash",
"stackedAssets"."encodedVideoPath" AS "stackedAssets_encodedVideoPath",
"stackedAssets"."createdAt" AS "stackedAssets_createdAt",
@ -110,8 +110,8 @@ SELECT
"asset"."deviceId" AS "asset_deviceId",
"asset"."type" AS "asset_type",
"asset"."originalPath" AS "asset_originalPath",
"asset"."resizePath" AS "asset_resizePath",
"asset"."webpPath" AS "asset_webpPath",
"asset"."previewPath" AS "asset_previewPath",
"asset"."thumbnailPath" AS "asset_thumbnailPath",
"asset"."thumbhash" AS "asset_thumbhash",
"asset"."encodedVideoPath" AS "asset_encodedVideoPath",
"asset"."createdAt" AS "asset_createdAt",
@ -141,8 +141,8 @@ SELECT
"stackedAssets"."deviceId" AS "stackedAssets_deviceId",
"stackedAssets"."type" AS "stackedAssets_type",
"stackedAssets"."originalPath" AS "stackedAssets_originalPath",
"stackedAssets"."resizePath" AS "stackedAssets_resizePath",
"stackedAssets"."webpPath" AS "stackedAssets_webpPath",
"stackedAssets"."previewPath" AS "stackedAssets_previewPath",
"stackedAssets"."thumbnailPath" AS "stackedAssets_thumbnailPath",
"stackedAssets"."thumbhash" AS "stackedAssets_thumbhash",
"stackedAssets"."encodedVideoPath" AS "stackedAssets_encodedVideoPath",
"stackedAssets"."createdAt" AS "stackedAssets_createdAt",
@ -320,8 +320,8 @@ SELECT
"asset"."deviceId" AS "asset_deviceId",
"asset"."type" AS "asset_type",
"asset"."originalPath" AS "asset_originalPath",
"asset"."resizePath" AS "asset_resizePath",
"asset"."webpPath" AS "asset_webpPath",
"asset"."previewPath" AS "asset_previewPath",
"asset"."thumbnailPath" AS "asset_thumbnailPath",
"asset"."thumbhash" AS "asset_thumbhash",
"asset"."encodedVideoPath" AS "asset_encodedVideoPath",
"asset"."createdAt" AS "asset_createdAt",

View File

@ -28,8 +28,8 @@ FROM
"SharedLinkEntity__SharedLinkEntity_assets"."deviceId" AS "SharedLinkEntity__SharedLinkEntity_assets_deviceId",
"SharedLinkEntity__SharedLinkEntity_assets"."type" AS "SharedLinkEntity__SharedLinkEntity_assets_type",
"SharedLinkEntity__SharedLinkEntity_assets"."originalPath" AS "SharedLinkEntity__SharedLinkEntity_assets_originalPath",
"SharedLinkEntity__SharedLinkEntity_assets"."resizePath" AS "SharedLinkEntity__SharedLinkEntity_assets_resizePath",
"SharedLinkEntity__SharedLinkEntity_assets"."webpPath" AS "SharedLinkEntity__SharedLinkEntity_assets_webpPath",
"SharedLinkEntity__SharedLinkEntity_assets"."previewPath" AS "SharedLinkEntity__SharedLinkEntity_assets_previewPath",
"SharedLinkEntity__SharedLinkEntity_assets"."thumbnailPath" AS "SharedLinkEntity__SharedLinkEntity_assets_thumbnailPath",
"SharedLinkEntity__SharedLinkEntity_assets"."thumbhash" AS "SharedLinkEntity__SharedLinkEntity_assets_thumbhash",
"SharedLinkEntity__SharedLinkEntity_assets"."encodedVideoPath" AS "SharedLinkEntity__SharedLinkEntity_assets_encodedVideoPath",
"SharedLinkEntity__SharedLinkEntity_assets"."createdAt" AS "SharedLinkEntity__SharedLinkEntity_assets_createdAt",
@ -95,8 +95,8 @@ FROM
"4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."deviceId" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_deviceId",
"4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."type" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_type",
"4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."originalPath" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_originalPath",
"4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."resizePath" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_resizePath",
"4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."webpPath" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_webpPath",
"4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."previewPath" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_previewPath",
"4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."thumbnailPath" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_thumbnailPath",
"4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."thumbhash" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_thumbhash",
"4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."encodedVideoPath" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_encodedVideoPath",
"4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."createdAt" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_createdAt",
@ -218,8 +218,8 @@ SELECT
"SharedLinkEntity__SharedLinkEntity_assets"."deviceId" AS "SharedLinkEntity__SharedLinkEntity_assets_deviceId",
"SharedLinkEntity__SharedLinkEntity_assets"."type" AS "SharedLinkEntity__SharedLinkEntity_assets_type",
"SharedLinkEntity__SharedLinkEntity_assets"."originalPath" AS "SharedLinkEntity__SharedLinkEntity_assets_originalPath",
"SharedLinkEntity__SharedLinkEntity_assets"."resizePath" AS "SharedLinkEntity__SharedLinkEntity_assets_resizePath",
"SharedLinkEntity__SharedLinkEntity_assets"."webpPath" AS "SharedLinkEntity__SharedLinkEntity_assets_webpPath",
"SharedLinkEntity__SharedLinkEntity_assets"."previewPath" AS "SharedLinkEntity__SharedLinkEntity_assets_previewPath",
"SharedLinkEntity__SharedLinkEntity_assets"."thumbnailPath" AS "SharedLinkEntity__SharedLinkEntity_assets_thumbnailPath",
"SharedLinkEntity__SharedLinkEntity_assets"."thumbhash" AS "SharedLinkEntity__SharedLinkEntity_assets_thumbhash",
"SharedLinkEntity__SharedLinkEntity_assets"."encodedVideoPath" AS "SharedLinkEntity__SharedLinkEntity_assets_encodedVideoPath",
"SharedLinkEntity__SharedLinkEntity_assets"."createdAt" AS "SharedLinkEntity__SharedLinkEntity_assets_createdAt",

View File

@ -5,6 +5,7 @@ import { AlbumEntity } from 'src/entities/album.entity';
import { AssetFaceEntity } from 'src/entities/asset-face.entity';
import { AssetEntity } from 'src/entities/asset.entity';
import { LibraryEntity } from 'src/entities/library.entity';
import { MemoryEntity } from 'src/entities/memory.entity';
import { PartnerEntity } from 'src/entities/partner.entity';
import { PersonEntity } from 'src/entities/person.entity';
import { SharedLinkEntity } from 'src/entities/shared-link.entity';
@ -19,6 +20,7 @@ type IAssetAccess = IAccessRepository['asset'];
type IAuthDeviceAccess = IAccessRepository['authDevice'];
type ILibraryAccess = IAccessRepository['library'];
type ITimelineAccess = IAccessRepository['timeline'];
type IMemoryAccess = IAccessRepository['memory'];
type IPersonAccess = IAccessRepository['person'];
type IPartnerAccess = IAccessRepository['partner'];
@ -345,6 +347,28 @@ class TimelineAccess implements ITimelineAccess {
}
}
class MemoryAccess implements IMemoryAccess {
constructor(private memoryRepository: Repository<MemoryEntity>) {}
@GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
@ChunkedSet({ paramIndex: 1 })
async checkOwnerAccess(userId: string, memoryIds: Set<string>): Promise<Set<string>> {
if (memoryIds.size === 0) {
return new Set();
}
return this.memoryRepository
.find({
select: { id: true },
where: {
id: In([...memoryIds]),
ownerId: userId,
},
})
.then((memories) => new Set(memories.map((memory) => memory.id)));
}
}
class PersonAccess implements IPersonAccess {
constructor(
private assetFaceRepository: Repository<AssetFaceEntity>,
@ -416,6 +440,7 @@ export class AccessRepository implements IAccessRepository {
asset: IAssetAccess;
authDevice: IAuthDeviceAccess;
library: ILibraryAccess;
memory: IMemoryAccess;
person: IPersonAccess;
partner: IPartnerAccess;
timeline: ITimelineAccess;
@ -425,6 +450,7 @@ export class AccessRepository implements IAccessRepository {
@InjectRepository(AssetEntity) assetRepository: Repository<AssetEntity>,
@InjectRepository(AlbumEntity) albumRepository: Repository<AlbumEntity>,
@InjectRepository(LibraryEntity) libraryRepository: Repository<LibraryEntity>,
@InjectRepository(MemoryEntity) memoryRepository: Repository<MemoryEntity>,
@InjectRepository(PartnerEntity) partnerRepository: Repository<PartnerEntity>,
@InjectRepository(PersonEntity) personRepository: Repository<PersonEntity>,
@InjectRepository(AssetFaceEntity) assetFaceRepository: Repository<AssetFaceEntity>,
@ -436,6 +462,7 @@ export class AccessRepository implements IAccessRepository {
this.asset = new AssetAccess(albumRepository, assetRepository, partnerRepository, sharedLinkRepository);
this.authDevice = new AuthDeviceAccess(tokenRepository);
this.library = new LibraryAccess(libraryRepository);
this.memory = new MemoryAccess(memoryRepository);
this.person = new PersonAccess(assetFaceRepository, personRepository);
this.partner = new PartnerAccess(partnerRepository);
this.timeline = new TimelineAccess(partnerRepository);

View File

@ -66,7 +66,7 @@ export class AssetRepositoryV1 implements IAssetRepositoryV1 {
getDetectedObjectsByUserId(userId: string): Promise<CuratedObjectsResponseDto[]> {
return this.assetRepository.query(
`
SELECT DISTINCT ON (unnest(si.objects)) a.id, unnest(si.objects) as "object", a."resizePath", a."deviceAssetId", a."deviceId"
SELECT DISTINCT ON (unnest(si.objects)) a.id, unnest(si.objects) as "object", a."previewPath" AS "resizePath", a."deviceAssetId", a."deviceId"
FROM assets a
LEFT JOIN smart_info si ON a.id = si."assetId"
WHERE a."ownerId" = $1
@ -80,7 +80,7 @@ export class AssetRepositoryV1 implements IAssetRepositoryV1 {
getLocationsByUserId(userId: string): Promise<CuratedLocationsResponseDto[]> {
return this.assetRepository.query(
`
SELECT DISTINCT ON (e.city) a.id, e.city, a."resizePath", a."deviceAssetId", a."deviceId"
SELECT DISTINCT ON (e.city) a.id, e.city, a."previewPath" AS "resizePath", a."deviceAssetId", a."deviceId"
FROM assets a
LEFT JOIN exif e ON a.id = e."assetId"
WHERE a."ownerId" = $1

View File

@ -83,7 +83,7 @@ export class AssetRepository implements IAssetRepository {
`entity.ownerId IN (:...ownerIds)
AND entity.isVisible = true
AND entity.isArchived = false
AND entity.resizePath IS NOT NULL
AND entity.previewPath IS NOT NULL
AND EXTRACT(DAY FROM entity.localDateTime AT TIME ZONE 'UTC') = :day
AND EXTRACT(MONTH FROM entity.localDateTime AT TIME ZONE 'UTC') = :month`,
{
@ -302,10 +302,10 @@ export class AssetRepository implements IAssetRepository {
switch (property) {
case WithoutProperty.THUMBNAIL: {
where = [
{ resizePath: IsNull(), isVisible: true },
{ resizePath: '', isVisible: true },
{ webpPath: IsNull(), isVisible: true },
{ webpPath: '', isVisible: true },
{ previewPath: IsNull(), isVisible: true },
{ previewPath: '', isVisible: true },
{ thumbnailPath: IsNull(), isVisible: true },
{ thumbnailPath: '', isVisible: true },
{ thumbhash: IsNull(), isVisible: true },
];
break;
@ -339,7 +339,7 @@ export class AssetRepository implements IAssetRepository {
};
where = {
isVisible: true,
resizePath: Not(IsNull()),
previewPath: Not(IsNull()),
smartSearch: {
embedding: IsNull(),
},
@ -352,7 +352,7 @@ export class AssetRepository implements IAssetRepository {
smartInfo: true,
};
where = {
resizePath: Not(IsNull()),
previewPath: Not(IsNull()),
isVisible: true,
smartInfo: {
tags: IsNull(),
@ -367,7 +367,7 @@ export class AssetRepository implements IAssetRepository {
jobStatus: true,
};
where = {
resizePath: Not(IsNull()),
previewPath: Not(IsNull()),
isVisible: true,
faces: {
assetId: IsNull(),
@ -385,7 +385,7 @@ export class AssetRepository implements IAssetRepository {
faces: true,
};
where = {
resizePath: Not(IsNull()),
previewPath: Not(IsNull()),
isVisible: true,
faces: {
assetId: Not(IsNull()),

View File

@ -13,6 +13,7 @@ import { IJobRepository } from 'src/interfaces/job.interface';
import { ILibraryRepository } from 'src/interfaces/library.interface';
import { IMachineLearningRepository } from 'src/interfaces/machine-learning.interface';
import { IMediaRepository } from 'src/interfaces/media.interface';
import { IMemoryRepository } from 'src/interfaces/memory.interface';
import { IMetadataRepository } from 'src/interfaces/metadata.interface';
import { IMetricRepository } from 'src/interfaces/metric.interface';
import { IMoveRepository } from 'src/interfaces/move.interface';
@ -42,6 +43,7 @@ import { JobRepository } from 'src/repositories/job.repository';
import { LibraryRepository } from 'src/repositories/library.repository';
import { MachineLearningRepository } from 'src/repositories/machine-learning.repository';
import { MediaRepository } from 'src/repositories/media.repository';
import { MemoryRepository } from 'src/repositories/memory.repository';
import { MetadataRepository } from 'src/repositories/metadata.repository';
import { MetricRepository } from 'src/repositories/metric.repository';
import { MoveRepository } from 'src/repositories/move.repository';
@ -72,6 +74,7 @@ export const repositories = [
{ provide: ILibraryRepository, useClass: LibraryRepository },
{ provide: IKeyRepository, useClass: ApiKeyRepository },
{ provide: IMachineLearningRepository, useClass: MachineLearningRepository },
{ provide: IMemoryRepository, useClass: MemoryRepository },
{ provide: IMetadataRepository, useClass: MetadataRepository },
{ provide: IMetricRepository, useClass: MetricRepository },
{ provide: IMoveRepository, useClass: MoveRepository },

View File

@ -35,9 +35,9 @@ export const JOBS_TO_QUEUE: Record<JobName, QueueName> = {
// thumbnails
[JobName.QUEUE_GENERATE_THUMBNAILS]: QueueName.THUMBNAIL_GENERATION,
[JobName.GENERATE_JPEG_THUMBNAIL]: QueueName.THUMBNAIL_GENERATION,
[JobName.GENERATE_WEBP_THUMBNAIL]: QueueName.THUMBNAIL_GENERATION,
[JobName.GENERATE_THUMBHASH_THUMBNAIL]: QueueName.THUMBNAIL_GENERATION,
[JobName.GENERATE_PREVIEW]: QueueName.THUMBNAIL_GENERATION,
[JobName.GENERATE_THUMBNAIL]: QueueName.THUMBNAIL_GENERATION,
[JobName.GENERATE_THUMBHASH]: QueueName.THUMBNAIL_GENERATION,
[JobName.GENERATE_PERSON_THUMBNAIL]: QueueName.THUMBNAIL_GENERATION,
// metadata

View File

@ -0,0 +1,104 @@
import { Injectable } from '@nestjs/common';
import { InjectDataSource, InjectRepository } from '@nestjs/typeorm';
import { Chunked, ChunkedSet, DummyValue, GenerateSql } from 'src/decorators';
import { AssetEntity } from 'src/entities/asset.entity';
import { MemoryEntity } from 'src/entities/memory.entity';
import { IMemoryRepository } from 'src/interfaces/memory.interface';
import { Instrumentation } from 'src/utils/instrumentation';
import { DataSource, In, Repository } from 'typeorm';
@Instrumentation()
@Injectable()
export class MemoryRepository implements IMemoryRepository {
constructor(
@InjectRepository(AssetEntity) private assetRepository: Repository<AssetEntity>,
@InjectRepository(MemoryEntity) private repository: Repository<MemoryEntity>,
@InjectDataSource() private dataSource: DataSource,
) {}
search(ownerId: string): Promise<MemoryEntity[]> {
return this.repository.find({
where: {
ownerId,
},
order: {
memoryAt: 'DESC',
},
});
}
get(id: string): Promise<MemoryEntity | null> {
return this.repository.findOne({
where: {
id,
},
relations: {
assets: true,
},
});
}
create(memory: Partial<MemoryEntity>): Promise<MemoryEntity> {
return this.save(memory);
}
update(memory: Partial<MemoryEntity>): Promise<MemoryEntity> {
return this.save(memory);
}
async delete(id: string): Promise<void> {
await this.repository.delete({ id });
}
@GenerateSql({ params: [DummyValue.UUID, [DummyValue.UUID]] })
@ChunkedSet({ paramIndex: 1 })
async getAssetIds(id: string, assetIds: string[]): Promise<Set<string>> {
if (assetIds.length === 0) {
return new Set();
}
const results = await this.dataSource
.createQueryBuilder()
.select('memories_assets.assetsId', 'assetId')
.from('memories_assets_assets', 'memories_assets')
.where('"memories_assets"."memoriesId" = :memoryId', { memoryId: id })
.andWhere('memories_assets.assetsId IN (:...assetIds)', { assetIds })
.getRawMany();
return new Set(results.map((row) => row['assetId']));
}
@GenerateSql({ params: [{ albumId: DummyValue.UUID, assetIds: [DummyValue.UUID] }] })
async addAssetIds(id: string, assetIds: string[]): Promise<void> {
await this.dataSource
.createQueryBuilder()
.insert()
.into('memories_assets_assets', ['memoriesId', 'assetsId'])
.values(assetIds.map((assetId) => ({ memoriesId: id, assetsId: assetId })))
.execute();
}
@GenerateSql({ params: [DummyValue.UUID, [DummyValue.UUID]] })
@Chunked({ paramIndex: 1 })
async removeAssetIds(id: string, assetIds: string[]): Promise<void> {
await this.dataSource
.createQueryBuilder()
.delete()
.from('memories_assets_assets')
.where({
memoriesId: id,
assetsId: In(assetIds),
})
.execute();
}
private async save(memory: Partial<MemoryEntity>): Promise<MemoryEntity> {
const { id } = await this.repository.save(memory);
return this.repository.findOneOrFail({
where: { id },
relations: {
assets: true,
},
});
}
}

View File

@ -44,13 +44,13 @@ const _getAsset_1 = () => {
asset_1.deviceId = 'device_id_1';
asset_1.type = AssetType.VIDEO;
asset_1.originalPath = 'fake_path/asset_1.jpeg';
asset_1.resizePath = '';
asset_1.previewPath = '';
asset_1.fileModifiedAt = new Date('2022-06-19T23:41:36.910Z');
asset_1.fileCreatedAt = new Date('2022-06-19T23:41:36.910Z');
asset_1.updatedAt = new Date('2022-06-19T23:41:36.910Z');
asset_1.isFavorite = false;
asset_1.isArchived = false;
asset_1.webpPath = '';
asset_1.thumbnailPath = '';
asset_1.encodedVideoPath = '';
asset_1.duration = '0:00:00.000000';
asset_1.exifInfo = new ExifEntity();

View File

@ -247,16 +247,16 @@ export class AssetServiceV1 {
private getThumbnailPath(asset: AssetEntity, format: GetAssetThumbnailFormatEnum) {
switch (format) {
case GetAssetThumbnailFormatEnum.WEBP: {
if (asset.webpPath) {
return asset.webpPath;
if (asset.thumbnailPath) {
return asset.thumbnailPath;
}
this.logger.warn(`WebP thumbnail requested but not found for asset ${asset.id}, falling back to JPEG`);
}
case GetAssetThumbnailFormatEnum.JPEG: {
if (!asset.resizePath) {
if (!asset.previewPath) {
throw new NotFoundException(`No thumbnail found for asset ${asset.id}`);
}
return asset.resizePath;
return asset.previewPath;
}
}
}
@ -268,12 +268,12 @@ export class AssetServiceV1 {
* Serve file viewer on the web
*/
if (dto.isWeb && mimeType != 'image/gif') {
if (!asset.resizePath) {
if (!asset.previewPath) {
this.logger.error('Error serving IMAGE asset for web');
throw new InternalServerErrorException(`Failed to serve image asset for web`, 'ServeFile');
}
return asset.resizePath;
return asset.previewPath;
}
/**
@ -283,15 +283,15 @@ export class AssetServiceV1 {
return asset.originalPath;
}
if (asset.webpPath && asset.webpPath.length > 0) {
return asset.webpPath;
if (asset.thumbnailPath && asset.thumbnailPath.length > 0) {
return asset.thumbnailPath;
}
if (!asset.resizePath) {
throw new Error('resizePath not set');
if (!asset.previewPath) {
throw new Error('previewPath not set');
}
return asset.resizePath;
return asset.previewPath;
}
private async getLibraryId(auth: AuthDto, libraryId?: string) {

View File

@ -661,8 +661,8 @@ describe(AssetService.name, () => {
name: JobName.DELETE_FILES,
data: {
files: [
assetWithFace.webpPath,
assetWithFace.resizePath,
assetWithFace.thumbnailPath,
assetWithFace.previewPath,
assetWithFace.encodedVideoPath,
assetWithFace.sidecarPath,
assetWithFace.originalPath,
@ -745,8 +745,8 @@ describe(AssetService.name, () => {
name: JobName.DELETE_FILES,
data: {
files: [
assetStub.external.webpPath,
assetStub.external.resizePath,
assetStub.external.thumbnailPath,
assetStub.external.previewPath,
assetStub.external.encodedVideoPath,
assetStub.external.sidecarPath,
],
@ -828,9 +828,7 @@ describe(AssetService.name, () => {
it('should run the refresh thumbnails job', async () => {
accessMock.asset.checkOwnerAccess.mockResolvedValue(new Set(['asset-1']));
await sut.run(authStub.admin, { assetIds: ['asset-1'], name: AssetJobName.REGENERATE_THUMBNAIL }),
expect(jobMock.queueAll).toHaveBeenCalledWith([
{ name: JobName.GENERATE_JPEG_THUMBNAIL, data: { id: 'asset-1' } },
]);
expect(jobMock.queueAll).toHaveBeenCalledWith([{ name: JobName.GENERATE_PREVIEW, data: { id: 'asset-1' } }]);
});
it('should run the transcode video', async () => {

View File

@ -399,7 +399,7 @@ export class AssetService {
await this.jobRepository.queue({ name: JobName.ASSET_DELETION, data: { id: asset.livePhotoVideoId } });
}
const files = [asset.webpPath, asset.resizePath, asset.encodedVideoPath, asset.sidecarPath];
const files = [asset.thumbnailPath, asset.previewPath, asset.encodedVideoPath, asset.sidecarPath];
if (!fromExternal) {
files.push(asset.originalPath);
}
@ -472,7 +472,7 @@ export class AssetService {
}
case AssetJobName.REGENERATE_THUMBNAIL: {
jobs.push({ name: JobName.GENERATE_JPEG_THUMBNAIL, data: { id } });
jobs.push({ name: JobName.GENERATE_PREVIEW, data: { id } });
break;
}

Some files were not shown because too many files have changed in this diff Show More