Merge branch 'main' of https://github.com/immich-app/immich into feat/cli-e2e
This commit is contained in:
commit
969b0b7367
26 changed files with 63 additions and 1694 deletions
280
cli/src/api/open-api/api.ts
generated
280
cli/src/api/open-api/api.ts
generated
|
@ -1773,97 +1773,6 @@ export interface FileReportItemDto {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface ImportAssetDto
|
||||
*/
|
||||
export interface ImportAssetDto {
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof ImportAssetDto
|
||||
*/
|
||||
'assetPath': string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof ImportAssetDto
|
||||
*/
|
||||
'deviceAssetId': string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof ImportAssetDto
|
||||
*/
|
||||
'deviceId': string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof ImportAssetDto
|
||||
*/
|
||||
'duration'?: string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof ImportAssetDto
|
||||
*/
|
||||
'fileCreatedAt': string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof ImportAssetDto
|
||||
*/
|
||||
'fileModifiedAt': string;
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
* @memberof ImportAssetDto
|
||||
*/
|
||||
'isArchived'?: boolean;
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
* @memberof ImportAssetDto
|
||||
*/
|
||||
'isExternal'?: boolean;
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
* @memberof ImportAssetDto
|
||||
*/
|
||||
'isFavorite'?: boolean;
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
* @memberof ImportAssetDto
|
||||
*/
|
||||
'isOffline'?: boolean;
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
* @memberof ImportAssetDto
|
||||
*/
|
||||
'isReadOnly'?: boolean;
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
* @memberof ImportAssetDto
|
||||
*/
|
||||
'isVisible'?: boolean;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof ImportAssetDto
|
||||
*/
|
||||
'libraryId'?: string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof ImportAssetDto
|
||||
*/
|
||||
'sidecarPath'?: string;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
|
@ -2794,19 +2703,6 @@ export interface SearchAlbumResponseDto {
|
|||
*/
|
||||
'total': number;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface SearchAssetDto
|
||||
*/
|
||||
export interface SearchAssetDto {
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof SearchAssetDto
|
||||
*/
|
||||
'searchTerm': string;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
|
@ -7622,50 +7518,6 @@ export const AssetApiAxiosParamCreator = function (configuration?: Configuration
|
|||
options: localVarRequestOptions,
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {ImportAssetDto} importAssetDto
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
importFile: async (importAssetDto: ImportAssetDto, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
|
||||
// verify required parameter 'importAssetDto' is not null or undefined
|
||||
assertParamExists('importFile', 'importAssetDto', importAssetDto)
|
||||
const localVarPath = `/asset/import`;
|
||||
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
||||
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
|
||||
let baseOptions;
|
||||
if (configuration) {
|
||||
baseOptions = configuration.baseOptions;
|
||||
}
|
||||
|
||||
const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options};
|
||||
const localVarHeaderParameter = {} as any;
|
||||
const localVarQueryParameter = {} as any;
|
||||
|
||||
// authentication cookie required
|
||||
|
||||
// authentication api_key required
|
||||
await setApiKeyToObject(localVarHeaderParameter, "x-api-key", configuration)
|
||||
|
||||
// authentication bearer required
|
||||
// http bearer authentication required
|
||||
await setBearerAuthToObject(localVarHeaderParameter, configuration)
|
||||
|
||||
|
||||
|
||||
localVarHeaderParameter['Content-Type'] = 'application/json';
|
||||
|
||||
setSearchParams(localVarUrlObj, localVarQueryParameter);
|
||||
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
||||
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
|
||||
localVarRequestOptions.data = serializeDataIfNeeded(importAssetDto, localVarRequestOptions, configuration)
|
||||
|
||||
return {
|
||||
url: toPathString(localVarUrlObj),
|
||||
options: localVarRequestOptions,
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {BulkIdsDto} bulkIdsDto
|
||||
|
@ -7792,50 +7644,6 @@ export const AssetApiAxiosParamCreator = function (configuration?: Configuration
|
|||
options: localVarRequestOptions,
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {SearchAssetDto} searchAssetDto
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
searchAsset: async (searchAssetDto: SearchAssetDto, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
|
||||
// verify required parameter 'searchAssetDto' is not null or undefined
|
||||
assertParamExists('searchAsset', 'searchAssetDto', searchAssetDto)
|
||||
const localVarPath = `/asset/search`;
|
||||
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
||||
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
|
||||
let baseOptions;
|
||||
if (configuration) {
|
||||
baseOptions = configuration.baseOptions;
|
||||
}
|
||||
|
||||
const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options};
|
||||
const localVarHeaderParameter = {} as any;
|
||||
const localVarQueryParameter = {} as any;
|
||||
|
||||
// authentication cookie required
|
||||
|
||||
// authentication api_key required
|
||||
await setApiKeyToObject(localVarHeaderParameter, "x-api-key", configuration)
|
||||
|
||||
// authentication bearer required
|
||||
// http bearer authentication required
|
||||
await setBearerAuthToObject(localVarHeaderParameter, configuration)
|
||||
|
||||
|
||||
|
||||
localVarHeaderParameter['Content-Type'] = 'application/json';
|
||||
|
||||
setSearchParams(localVarUrlObj, localVarQueryParameter);
|
||||
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
||||
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
|
||||
localVarRequestOptions.data = serializeDataIfNeeded(searchAssetDto, localVarRequestOptions, configuration)
|
||||
|
||||
return {
|
||||
url: toPathString(localVarUrlObj),
|
||||
options: localVarRequestOptions,
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {string} [id]
|
||||
|
@ -8659,16 +8467,6 @@ export const AssetApiFp = function(configuration?: Configuration) {
|
|||
const localVarAxiosArgs = await localVarAxiosParamCreator.getUserAssetsByDeviceId(deviceId, options);
|
||||
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {ImportAssetDto} importAssetDto
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async importFile(importAssetDto: ImportAssetDto, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<AssetFileUploadResponseDto>> {
|
||||
const localVarAxiosArgs = await localVarAxiosParamCreator.importFile(importAssetDto, options);
|
||||
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {BulkIdsDto} bulkIdsDto
|
||||
|
@ -8698,16 +8496,6 @@ export const AssetApiFp = function(configuration?: Configuration) {
|
|||
const localVarAxiosArgs = await localVarAxiosParamCreator.runAssetJobs(assetJobsDto, options);
|
||||
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {SearchAssetDto} searchAssetDto
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async searchAsset(searchAssetDto: SearchAssetDto, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Array<AssetResponseDto>>> {
|
||||
const localVarAxiosArgs = await localVarAxiosParamCreator.searchAsset(searchAssetDto, options);
|
||||
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {string} [id]
|
||||
|
@ -9012,15 +8800,6 @@ export const AssetApiFactory = function (configuration?: Configuration, basePath
|
|||
getUserAssetsByDeviceId(requestParameters: AssetApiGetUserAssetsByDeviceIdRequest, options?: AxiosRequestConfig): AxiosPromise<Array<string>> {
|
||||
return localVarFp.getUserAssetsByDeviceId(requestParameters.deviceId, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {AssetApiImportFileRequest} requestParameters Request parameters.
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
importFile(requestParameters: AssetApiImportFileRequest, options?: AxiosRequestConfig): AxiosPromise<AssetFileUploadResponseDto> {
|
||||
return localVarFp.importFile(requestParameters.importAssetDto, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {AssetApiRestoreAssetsRequest} requestParameters Request parameters.
|
||||
|
@ -9047,15 +8826,6 @@ export const AssetApiFactory = function (configuration?: Configuration, basePath
|
|||
runAssetJobs(requestParameters: AssetApiRunAssetJobsRequest, options?: AxiosRequestConfig): AxiosPromise<void> {
|
||||
return localVarFp.runAssetJobs(requestParameters.assetJobsDto, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {AssetApiSearchAssetRequest} requestParameters Request parameters.
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
searchAsset(requestParameters: AssetApiSearchAssetRequest, options?: AxiosRequestConfig): AxiosPromise<Array<AssetResponseDto>> {
|
||||
return localVarFp.searchAsset(requestParameters.searchAssetDto, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {AssetApiSearchAssetsRequest} requestParameters Request parameters.
|
||||
|
@ -9603,20 +9373,6 @@ export interface AssetApiGetUserAssetsByDeviceIdRequest {
|
|||
readonly deviceId: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Request parameters for importFile operation in AssetApi.
|
||||
* @export
|
||||
* @interface AssetApiImportFileRequest
|
||||
*/
|
||||
export interface AssetApiImportFileRequest {
|
||||
/**
|
||||
*
|
||||
* @type {ImportAssetDto}
|
||||
* @memberof AssetApiImportFile
|
||||
*/
|
||||
readonly importAssetDto: ImportAssetDto
|
||||
}
|
||||
|
||||
/**
|
||||
* Request parameters for restoreAssets operation in AssetApi.
|
||||
* @export
|
||||
|
@ -9645,20 +9401,6 @@ export interface AssetApiRunAssetJobsRequest {
|
|||
readonly assetJobsDto: AssetJobsDto
|
||||
}
|
||||
|
||||
/**
|
||||
* Request parameters for searchAsset operation in AssetApi.
|
||||
* @export
|
||||
* @interface AssetApiSearchAssetRequest
|
||||
*/
|
||||
export interface AssetApiSearchAssetRequest {
|
||||
/**
|
||||
*
|
||||
* @type {SearchAssetDto}
|
||||
* @memberof AssetApiSearchAsset
|
||||
*/
|
||||
readonly searchAssetDto: SearchAssetDto
|
||||
}
|
||||
|
||||
/**
|
||||
* Request parameters for searchAssets operation in AssetApi.
|
||||
* @export
|
||||
|
@ -10372,17 +10114,6 @@ export class AssetApi extends BaseAPI {
|
|||
return AssetApiFp(this.configuration).getUserAssetsByDeviceId(requestParameters.deviceId, options).then((request) => request(this.axios, this.basePath));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {AssetApiImportFileRequest} requestParameters Request parameters.
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
* @memberof AssetApi
|
||||
*/
|
||||
public importFile(requestParameters: AssetApiImportFileRequest, options?: AxiosRequestConfig) {
|
||||
return AssetApiFp(this.configuration).importFile(requestParameters.importAssetDto, options).then((request) => request(this.axios, this.basePath));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {AssetApiRestoreAssetsRequest} requestParameters Request parameters.
|
||||
|
@ -10415,17 +10146,6 @@ export class AssetApi extends BaseAPI {
|
|||
return AssetApiFp(this.configuration).runAssetJobs(requestParameters.assetJobsDto, options).then((request) => request(this.axios, this.basePath));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {AssetApiSearchAssetRequest} requestParameters Request parameters.
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
* @memberof AssetApi
|
||||
*/
|
||||
public searchAsset(requestParameters: AssetApiSearchAssetRequest, options?: AxiosRequestConfig) {
|
||||
return AssetApiFp(this.configuration).searchAsset(requestParameters.searchAssetDto, options).then((request) => request(this.axios, this.basePath));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {AssetApiSearchAssetsRequest} requestParameters Request parameters.
|
||||
|
|
|
@ -188,19 +188,18 @@ Typesense URL example JSON before encoding:
|
|||
|
||||
| Variable | Description | Default | Services |
|
||||
| :----------------------------------------------- | :---------------------------------------------------------------- | :-----------------: | :--------------- |
|
||||
| `MACHINE_LEARNING_MODEL_TTL`<sup>\*1</sup> | Inactivity time (s) before a model is unloaded (disabled if <= 0) | `0` | machine learning |
|
||||
| `MACHINE_LEARNING_MODEL_TTL` | Inactivity time (s) before a model is unloaded (disabled if <= 0) | `300` | machine learning |
|
||||
| `MACHINE_LEARNING_MODEL_TTL_POLL_S` | Interval (s) between checks for the model TTL (disabled if <= 0) | `10` | machine learning |
|
||||
| `MACHINE_LEARNING_CACHE_FOLDER` | Directory where models are downloaded | `/cache` | machine learning |
|
||||
| `MACHINE_LEARNING_REQUEST_THREADS`<sup>\*2</sup> | Thread count of the request thread pool (disabled if <= 0) | number of CPU cores | machine learning |
|
||||
| `MACHINE_LEARNING_REQUEST_THREADS`<sup>\*1</sup> | Thread count of the request thread pool (disabled if <= 0) | number of CPU cores | machine learning |
|
||||
| `MACHINE_LEARNING_MODEL_INTER_OP_THREADS` | Number of parallel model operations | `1` | machine learning |
|
||||
| `MACHINE_LEARNING_MODEL_INTRA_OP_THREADS` | Number of threads for each model operation | `2` | machine learning |
|
||||
| `MACHINE_LEARNING_WORKERS`<sup>\*3</sup> | Number of worker processes to spawn | `1` | machine learning |
|
||||
| `MACHINE_LEARNING_WORKERS`<sup>\*2</sup> | Number of worker processes to spawn | `1` | machine learning |
|
||||
| `MACHINE_LEARNING_WORKER_TIMEOUT` | Maximum time (s) of unresponsiveness before a worker is killed | `120` | machine learning |
|
||||
|
||||
\*1: This is an experimental feature. It may result in increased memory use over time when loading models repeatedly.
|
||||
\*1: It is recommended to begin with this parameter when changing the concurrency levels of the machine learning service and then tune the other ones.
|
||||
|
||||
\*2: It is recommended to begin with this parameter when changing the concurrency levels of the machine learning service and then tune the other ones.
|
||||
|
||||
\*3: Since each process duplicates models in memory, changing this is not recommended unless you have abundant memory to go around.
|
||||
\*2: Since each process duplicates models in memory, changing this is not recommended unless you have abundant memory to go around.
|
||||
|
||||
:::info
|
||||
|
||||
|
|
|
@ -13,7 +13,8 @@ from .schemas import ModelType
|
|||
|
||||
class Settings(BaseSettings):
|
||||
cache_folder: str = "/cache"
|
||||
model_ttl: int = 0
|
||||
model_ttl: int = 300
|
||||
model_ttl_poll_s: int = 10
|
||||
host: str = "0.0.0.0"
|
||||
port: int = 3003
|
||||
workers: int = 1
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
import asyncio
|
||||
import gc
|
||||
import os
|
||||
import sys
|
||||
import threading
|
||||
import time
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from typing import Any
|
||||
from zipfile import BadZipFile
|
||||
|
@ -34,7 +38,10 @@ def init_state() -> None:
|
|||
)
|
||||
# asyncio is a huge bottleneck for performance, so we use a thread pool to run blocking code
|
||||
app.state.thread_pool = ThreadPoolExecutor(settings.request_threads) if settings.request_threads > 0 else None
|
||||
app.state.locks = {model_type: threading.Lock() for model_type in ModelType}
|
||||
app.state.lock = threading.Lock()
|
||||
app.state.last_called = None
|
||||
if settings.model_ttl > 0 and settings.model_ttl_poll_s > 0:
|
||||
asyncio.ensure_future(idle_shutdown_task())
|
||||
log.info(f"Initialized request thread pool with {settings.request_threads} threads.")
|
||||
|
||||
|
||||
|
@ -79,9 +86,9 @@ async def predict(
|
|||
|
||||
|
||||
async def run(model: InferenceModel, inputs: Any) -> Any:
|
||||
app.state.last_called = time.time()
|
||||
if app.state.thread_pool is None:
|
||||
return model.predict(inputs)
|
||||
|
||||
return await asyncio.get_running_loop().run_in_executor(app.state.thread_pool, model.predict, inputs)
|
||||
|
||||
|
||||
|
@ -90,7 +97,7 @@ async def load(model: InferenceModel) -> InferenceModel:
|
|||
return model
|
||||
|
||||
def _load() -> None:
|
||||
with app.state.locks[model.model_type]:
|
||||
with app.state.lock:
|
||||
model.load()
|
||||
|
||||
loop = asyncio.get_running_loop()
|
||||
|
@ -113,3 +120,27 @@ async def load(model: InferenceModel) -> InferenceModel:
|
|||
else:
|
||||
await loop.run_in_executor(app.state.thread_pool, _load)
|
||||
return model
|
||||
|
||||
|
||||
async def idle_shutdown_task() -> None:
|
||||
while True:
|
||||
log.debug("Checking for inactivity...")
|
||||
if app.state.last_called is not None and time.time() - app.state.last_called > settings.model_ttl:
|
||||
log.info("Shutting down due to inactivity.")
|
||||
loop = asyncio.get_running_loop()
|
||||
for task in asyncio.all_tasks(loop):
|
||||
if task is not asyncio.current_task():
|
||||
try:
|
||||
task.cancel()
|
||||
except asyncio.CancelledError:
|
||||
pass
|
||||
sys.stderr.close()
|
||||
sys.stdout.close()
|
||||
sys.stdout = sys.stderr = open(os.devnull, "w")
|
||||
try:
|
||||
await app.state.model_cache.cache.clear()
|
||||
gc.collect()
|
||||
loop.stop()
|
||||
except asyncio.CancelledError:
|
||||
pass
|
||||
await asyncio.sleep(settings.model_ttl_poll_s)
|
||||
|
|
6
mobile/openapi/.openapi-generator/FILES
generated
6
mobile/openapi/.openapi-generator/FILES
generated
|
@ -66,7 +66,6 @@ doc/FileChecksumResponseDto.md
|
|||
doc/FileReportDto.md
|
||||
doc/FileReportFixDto.md
|
||||
doc/FileReportItemDto.md
|
||||
doc/ImportAssetDto.md
|
||||
doc/JobApi.md
|
||||
doc/JobCommand.md
|
||||
doc/JobCommandDto.md
|
||||
|
@ -109,7 +108,6 @@ doc/RecognitionConfig.md
|
|||
doc/ScanLibraryDto.md
|
||||
doc/SearchAlbumResponseDto.md
|
||||
doc/SearchApi.md
|
||||
doc/SearchAssetDto.md
|
||||
doc/SearchAssetResponseDto.md
|
||||
doc/SearchExploreItem.md
|
||||
doc/SearchExploreResponseDto.md
|
||||
|
@ -256,7 +254,6 @@ 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/import_asset_dto.dart
|
||||
lib/model/job_command.dart
|
||||
lib/model/job_command_dto.dart
|
||||
lib/model/job_counts_dto.dart
|
||||
|
@ -293,7 +290,6 @@ lib/model/reaction_type.dart
|
|||
lib/model/recognition_config.dart
|
||||
lib/model/scan_library_dto.dart
|
||||
lib/model/search_album_response_dto.dart
|
||||
lib/model/search_asset_dto.dart
|
||||
lib/model/search_asset_response_dto.dart
|
||||
lib/model/search_explore_item.dart
|
||||
lib/model/search_explore_response_dto.dart
|
||||
|
@ -415,7 +411,6 @@ 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/import_asset_dto_test.dart
|
||||
test/job_api_test.dart
|
||||
test/job_command_dto_test.dart
|
||||
test/job_command_test.dart
|
||||
|
@ -458,7 +453,6 @@ test/recognition_config_test.dart
|
|||
test/scan_library_dto_test.dart
|
||||
test/search_album_response_dto_test.dart
|
||||
test/search_api_test.dart
|
||||
test/search_asset_dto_test.dart
|
||||
test/search_asset_response_dto_test.dart
|
||||
test/search_explore_item_test.dart
|
||||
test/search_explore_response_dto_test.dart
|
||||
|
|
4
mobile/openapi/README.md
generated
4
mobile/openapi/README.md
generated
|
@ -111,11 +111,9 @@ Class | Method | HTTP request | Description
|
|||
*AssetApi* | [**getTimeBucket**](doc//AssetApi.md#gettimebucket) | **GET** /asset/time-bucket |
|
||||
*AssetApi* | [**getTimeBuckets**](doc//AssetApi.md#gettimebuckets) | **GET** /asset/time-buckets |
|
||||
*AssetApi* | [**getUserAssetsByDeviceId**](doc//AssetApi.md#getuserassetsbydeviceid) | **GET** /asset/{deviceId} |
|
||||
*AssetApi* | [**importFile**](doc//AssetApi.md#importfile) | **POST** /asset/import |
|
||||
*AssetApi* | [**restoreAssets**](doc//AssetApi.md#restoreassets) | **POST** /asset/restore |
|
||||
*AssetApi* | [**restoreTrash**](doc//AssetApi.md#restoretrash) | **POST** /asset/trash/restore |
|
||||
*AssetApi* | [**runAssetJobs**](doc//AssetApi.md#runassetjobs) | **POST** /asset/jobs |
|
||||
*AssetApi* | [**searchAsset**](doc//AssetApi.md#searchasset) | **POST** /asset/search |
|
||||
*AssetApi* | [**searchAssets**](doc//AssetApi.md#searchassets) | **GET** /assets |
|
||||
*AssetApi* | [**serveFile**](doc//AssetApi.md#servefile) | **GET** /asset/file/{id} |
|
||||
*AssetApi* | [**updateAsset**](doc//AssetApi.md#updateasset) | **PUT** /asset/{id} |
|
||||
|
@ -265,7 +263,6 @@ Class | Method | HTTP request | Description
|
|||
- [FileReportDto](doc//FileReportDto.md)
|
||||
- [FileReportFixDto](doc//FileReportFixDto.md)
|
||||
- [FileReportItemDto](doc//FileReportItemDto.md)
|
||||
- [ImportAssetDto](doc//ImportAssetDto.md)
|
||||
- [JobCommand](doc//JobCommand.md)
|
||||
- [JobCommandDto](doc//JobCommandDto.md)
|
||||
- [JobCountsDto](doc//JobCountsDto.md)
|
||||
|
@ -302,7 +299,6 @@ Class | Method | HTTP request | Description
|
|||
- [RecognitionConfig](doc//RecognitionConfig.md)
|
||||
- [ScanLibraryDto](doc//ScanLibraryDto.md)
|
||||
- [SearchAlbumResponseDto](doc//SearchAlbumResponseDto.md)
|
||||
- [SearchAssetDto](doc//SearchAssetDto.md)
|
||||
- [SearchAssetResponseDto](doc//SearchAssetResponseDto.md)
|
||||
- [SearchExploreItem](doc//SearchExploreItem.md)
|
||||
- [SearchExploreResponseDto](doc//SearchExploreResponseDto.md)
|
||||
|
|
112
mobile/openapi/doc/AssetApi.md
generated
112
mobile/openapi/doc/AssetApi.md
generated
|
@ -29,11 +29,9 @@ Method | HTTP request | Description
|
|||
[**getTimeBucket**](AssetApi.md#gettimebucket) | **GET** /asset/time-bucket |
|
||||
[**getTimeBuckets**](AssetApi.md#gettimebuckets) | **GET** /asset/time-buckets |
|
||||
[**getUserAssetsByDeviceId**](AssetApi.md#getuserassetsbydeviceid) | **GET** /asset/{deviceId} |
|
||||
[**importFile**](AssetApi.md#importfile) | **POST** /asset/import |
|
||||
[**restoreAssets**](AssetApi.md#restoreassets) | **POST** /asset/restore |
|
||||
[**restoreTrash**](AssetApi.md#restoretrash) | **POST** /asset/trash/restore |
|
||||
[**runAssetJobs**](AssetApi.md#runassetjobs) | **POST** /asset/jobs |
|
||||
[**searchAsset**](AssetApi.md#searchasset) | **POST** /asset/search |
|
||||
[**searchAssets**](AssetApi.md#searchassets) | **GET** /assets |
|
||||
[**serveFile**](AssetApi.md#servefile) | **GET** /asset/file/{id} |
|
||||
[**updateAsset**](AssetApi.md#updateasset) | **PUT** /asset/{id} |
|
||||
|
@ -1210,61 +1208,6 @@ Name | Type | Description | Notes
|
|||
|
||||
[[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)
|
||||
|
||||
# **importFile**
|
||||
> AssetFileUploadResponseDto importFile(importAssetDto)
|
||||
|
||||
|
||||
|
||||
### 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 = AssetApi();
|
||||
final importAssetDto = ImportAssetDto(); // ImportAssetDto |
|
||||
|
||||
try {
|
||||
final result = api_instance.importFile(importAssetDto);
|
||||
print(result);
|
||||
} catch (e) {
|
||||
print('Exception when calling AssetApi->importFile: $e\n');
|
||||
}
|
||||
```
|
||||
|
||||
### Parameters
|
||||
|
||||
Name | Type | Description | Notes
|
||||
------------- | ------------- | ------------- | -------------
|
||||
**importAssetDto** | [**ImportAssetDto**](ImportAssetDto.md)| |
|
||||
|
||||
### Return type
|
||||
|
||||
[**AssetFileUploadResponseDto**](AssetFileUploadResponseDto.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)
|
||||
|
||||
# **restoreAssets**
|
||||
> restoreAssets(bulkIdsDto)
|
||||
|
||||
|
@ -1423,61 +1366,6 @@ 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)
|
||||
|
||||
# **searchAsset**
|
||||
> List<AssetResponseDto> searchAsset(searchAssetDto)
|
||||
|
||||
|
||||
|
||||
### 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 = AssetApi();
|
||||
final searchAssetDto = SearchAssetDto(); // SearchAssetDto |
|
||||
|
||||
try {
|
||||
final result = api_instance.searchAsset(searchAssetDto);
|
||||
print(result);
|
||||
} catch (e) {
|
||||
print('Exception when calling AssetApi->searchAsset: $e\n');
|
||||
}
|
||||
```
|
||||
|
||||
### Parameters
|
||||
|
||||
Name | Type | Description | Notes
|
||||
------------- | ------------- | ------------- | -------------
|
||||
**searchAssetDto** | [**SearchAssetDto**](SearchAssetDto.md)| |
|
||||
|
||||
### Return type
|
||||
|
||||
[**List<AssetResponseDto>**](AssetResponseDto.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)
|
||||
|
||||
# **searchAssets**
|
||||
> List<AssetResponseDto> searchAssets(id, libraryId, type, order, deviceAssetId, deviceId, checksum, isArchived, isEncoded, isExternal, isFavorite, isMotion, isOffline, isReadOnly, isVisible, withDeleted, withStacked, withExif, withPeople, createdBefore, createdAfter, updatedBefore, updatedAfter, trashedBefore, trashedAfter, takenBefore, takenAfter, originalFileName, originalPath, resizePath, webpPath, encodedVideoPath, city, state, country, make, model, lensModel, page, size)
|
||||
|
||||
|
|
28
mobile/openapi/doc/ImportAssetDto.md
generated
28
mobile/openapi/doc/ImportAssetDto.md
generated
|
@ -1,28 +0,0 @@
|
|||
# openapi.model.ImportAssetDto
|
||||
|
||||
## Load the model package
|
||||
```dart
|
||||
import 'package:openapi/api.dart';
|
||||
```
|
||||
|
||||
## Properties
|
||||
Name | Type | Description | Notes
|
||||
------------ | ------------- | ------------- | -------------
|
||||
**assetPath** | **String** | |
|
||||
**deviceAssetId** | **String** | |
|
||||
**deviceId** | **String** | |
|
||||
**duration** | **String** | | [optional]
|
||||
**fileCreatedAt** | [**DateTime**](DateTime.md) | |
|
||||
**fileModifiedAt** | [**DateTime**](DateTime.md) | |
|
||||
**isArchived** | **bool** | | [optional]
|
||||
**isExternal** | **bool** | | [optional]
|
||||
**isFavorite** | **bool** | | [optional]
|
||||
**isOffline** | **bool** | | [optional]
|
||||
**isReadOnly** | **bool** | | [optional] [default to true]
|
||||
**isVisible** | **bool** | | [optional]
|
||||
**libraryId** | **String** | | [optional]
|
||||
**sidecarPath** | **String** | | [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)
|
||||
|
||||
|
15
mobile/openapi/doc/SearchAssetDto.md
generated
15
mobile/openapi/doc/SearchAssetDto.md
generated
|
@ -1,15 +0,0 @@
|
|||
# openapi.model.SearchAssetDto
|
||||
|
||||
## Load the model package
|
||||
```dart
|
||||
import 'package:openapi/api.dart';
|
||||
```
|
||||
|
||||
## Properties
|
||||
Name | Type | Description | Notes
|
||||
------------ | ------------- | ------------- | -------------
|
||||
**searchTerm** | **String** | |
|
||||
|
||||
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||
|
||||
|
2
mobile/openapi/lib/api.dart
generated
2
mobile/openapi/lib/api.dart
generated
|
@ -103,7 +103,6 @@ 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/import_asset_dto.dart';
|
||||
part 'model/job_command.dart';
|
||||
part 'model/job_command_dto.dart';
|
||||
part 'model/job_counts_dto.dart';
|
||||
|
@ -140,7 +139,6 @@ part 'model/reaction_type.dart';
|
|||
part 'model/recognition_config.dart';
|
||||
part 'model/scan_library_dto.dart';
|
||||
part 'model/search_album_response_dto.dart';
|
||||
part 'model/search_asset_dto.dart';
|
||||
part 'model/search_asset_response_dto.dart';
|
||||
part 'model/search_explore_item.dart';
|
||||
part 'model/search_explore_response_dto.dart';
|
||||
|
|
97
mobile/openapi/lib/api/asset_api.dart
generated
97
mobile/openapi/lib/api/asset_api.dart
generated
|
@ -1267,53 +1267,6 @@ class AssetApi {
|
|||
return null;
|
||||
}
|
||||
|
||||
/// Performs an HTTP 'POST /asset/import' operation and returns the [Response].
|
||||
/// Parameters:
|
||||
///
|
||||
/// * [ImportAssetDto] importAssetDto (required):
|
||||
Future<Response> importFileWithHttpInfo(ImportAssetDto importAssetDto,) async {
|
||||
// ignore: prefer_const_declarations
|
||||
final path = r'/asset/import';
|
||||
|
||||
// ignore: prefer_final_locals
|
||||
Object? postBody = importAssetDto;
|
||||
|
||||
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:
|
||||
///
|
||||
/// * [ImportAssetDto] importAssetDto (required):
|
||||
Future<AssetFileUploadResponseDto?> importFile(ImportAssetDto importAssetDto,) async {
|
||||
final response = await importFileWithHttpInfo(importAssetDto,);
|
||||
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), 'AssetFileUploadResponseDto',) as AssetFileUploadResponseDto;
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Performs an HTTP 'POST /asset/restore' operation and returns the [Response].
|
||||
/// Parameters:
|
||||
///
|
||||
|
@ -1425,56 +1378,6 @@ class AssetApi {
|
|||
}
|
||||
}
|
||||
|
||||
/// Performs an HTTP 'POST /asset/search' operation and returns the [Response].
|
||||
/// Parameters:
|
||||
///
|
||||
/// * [SearchAssetDto] searchAssetDto (required):
|
||||
Future<Response> searchAssetWithHttpInfo(SearchAssetDto searchAssetDto,) async {
|
||||
// ignore: prefer_const_declarations
|
||||
final path = r'/asset/search';
|
||||
|
||||
// ignore: prefer_final_locals
|
||||
Object? postBody = searchAssetDto;
|
||||
|
||||
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:
|
||||
///
|
||||
/// * [SearchAssetDto] searchAssetDto (required):
|
||||
Future<List<AssetResponseDto>?> searchAsset(SearchAssetDto searchAssetDto,) async {
|
||||
final response = await searchAssetWithHttpInfo(searchAssetDto,);
|
||||
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<AssetResponseDto>') as List)
|
||||
.cast<AssetResponseDto>()
|
||||
.toList();
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Performs an HTTP 'GET /assets' operation and returns the [Response].
|
||||
/// Parameters:
|
||||
///
|
||||
|
|
4
mobile/openapi/lib/api_client.dart
generated
4
mobile/openapi/lib/api_client.dart
generated
|
@ -295,8 +295,6 @@ class ApiClient {
|
|||
return FileReportFixDto.fromJson(value);
|
||||
case 'FileReportItemDto':
|
||||
return FileReportItemDto.fromJson(value);
|
||||
case 'ImportAssetDto':
|
||||
return ImportAssetDto.fromJson(value);
|
||||
case 'JobCommand':
|
||||
return JobCommandTypeTransformer().decode(value);
|
||||
case 'JobCommandDto':
|
||||
|
@ -369,8 +367,6 @@ class ApiClient {
|
|||
return ScanLibraryDto.fromJson(value);
|
||||
case 'SearchAlbumResponseDto':
|
||||
return SearchAlbumResponseDto.fromJson(value);
|
||||
case 'SearchAssetDto':
|
||||
return SearchAssetDto.fromJson(value);
|
||||
case 'SearchAssetResponseDto':
|
||||
return SearchAssetResponseDto.fromJson(value);
|
||||
case 'SearchExploreItem':
|
||||
|
|
273
mobile/openapi/lib/model/import_asset_dto.dart
generated
273
mobile/openapi/lib/model/import_asset_dto.dart
generated
|
@ -1,273 +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 ImportAssetDto {
|
||||
/// Returns a new [ImportAssetDto] instance.
|
||||
ImportAssetDto({
|
||||
required this.assetPath,
|
||||
required this.deviceAssetId,
|
||||
required this.deviceId,
|
||||
this.duration,
|
||||
required this.fileCreatedAt,
|
||||
required this.fileModifiedAt,
|
||||
this.isArchived,
|
||||
this.isExternal,
|
||||
this.isFavorite,
|
||||
this.isOffline,
|
||||
this.isReadOnly = true,
|
||||
this.isVisible,
|
||||
this.libraryId,
|
||||
this.sidecarPath,
|
||||
});
|
||||
|
||||
String assetPath;
|
||||
|
||||
String deviceAssetId;
|
||||
|
||||
String deviceId;
|
||||
|
||||
///
|
||||
/// 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? duration;
|
||||
|
||||
DateTime fileCreatedAt;
|
||||
|
||||
DateTime fileModifiedAt;
|
||||
|
||||
///
|
||||
/// 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? isArchived;
|
||||
|
||||
///
|
||||
/// 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? isExternal;
|
||||
|
||||
///
|
||||
/// 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? isFavorite;
|
||||
|
||||
///
|
||||
/// 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? isOffline;
|
||||
|
||||
bool isReadOnly;
|
||||
|
||||
///
|
||||
/// 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? isVisible;
|
||||
|
||||
///
|
||||
/// 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? libraryId;
|
||||
|
||||
///
|
||||
/// 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? sidecarPath;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is ImportAssetDto &&
|
||||
other.assetPath == assetPath &&
|
||||
other.deviceAssetId == deviceAssetId &&
|
||||
other.deviceId == deviceId &&
|
||||
other.duration == duration &&
|
||||
other.fileCreatedAt == fileCreatedAt &&
|
||||
other.fileModifiedAt == fileModifiedAt &&
|
||||
other.isArchived == isArchived &&
|
||||
other.isExternal == isExternal &&
|
||||
other.isFavorite == isFavorite &&
|
||||
other.isOffline == isOffline &&
|
||||
other.isReadOnly == isReadOnly &&
|
||||
other.isVisible == isVisible &&
|
||||
other.libraryId == libraryId &&
|
||||
other.sidecarPath == sidecarPath;
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
// ignore: unnecessary_parenthesis
|
||||
(assetPath.hashCode) +
|
||||
(deviceAssetId.hashCode) +
|
||||
(deviceId.hashCode) +
|
||||
(duration == null ? 0 : duration!.hashCode) +
|
||||
(fileCreatedAt.hashCode) +
|
||||
(fileModifiedAt.hashCode) +
|
||||
(isArchived == null ? 0 : isArchived!.hashCode) +
|
||||
(isExternal == null ? 0 : isExternal!.hashCode) +
|
||||
(isFavorite == null ? 0 : isFavorite!.hashCode) +
|
||||
(isOffline == null ? 0 : isOffline!.hashCode) +
|
||||
(isReadOnly.hashCode) +
|
||||
(isVisible == null ? 0 : isVisible!.hashCode) +
|
||||
(libraryId == null ? 0 : libraryId!.hashCode) +
|
||||
(sidecarPath == null ? 0 : sidecarPath!.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'ImportAssetDto[assetPath=$assetPath, deviceAssetId=$deviceAssetId, deviceId=$deviceId, duration=$duration, fileCreatedAt=$fileCreatedAt, fileModifiedAt=$fileModifiedAt, isArchived=$isArchived, isExternal=$isExternal, isFavorite=$isFavorite, isOffline=$isOffline, isReadOnly=$isReadOnly, isVisible=$isVisible, libraryId=$libraryId, sidecarPath=$sidecarPath]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
json[r'assetPath'] = this.assetPath;
|
||||
json[r'deviceAssetId'] = this.deviceAssetId;
|
||||
json[r'deviceId'] = this.deviceId;
|
||||
if (this.duration != null) {
|
||||
json[r'duration'] = this.duration;
|
||||
} else {
|
||||
// json[r'duration'] = null;
|
||||
}
|
||||
json[r'fileCreatedAt'] = this.fileCreatedAt.toUtc().toIso8601String();
|
||||
json[r'fileModifiedAt'] = this.fileModifiedAt.toUtc().toIso8601String();
|
||||
if (this.isArchived != null) {
|
||||
json[r'isArchived'] = this.isArchived;
|
||||
} else {
|
||||
// json[r'isArchived'] = null;
|
||||
}
|
||||
if (this.isExternal != null) {
|
||||
json[r'isExternal'] = this.isExternal;
|
||||
} else {
|
||||
// json[r'isExternal'] = null;
|
||||
}
|
||||
if (this.isFavorite != null) {
|
||||
json[r'isFavorite'] = this.isFavorite;
|
||||
} else {
|
||||
// json[r'isFavorite'] = null;
|
||||
}
|
||||
if (this.isOffline != null) {
|
||||
json[r'isOffline'] = this.isOffline;
|
||||
} else {
|
||||
// json[r'isOffline'] = null;
|
||||
}
|
||||
json[r'isReadOnly'] = this.isReadOnly;
|
||||
if (this.isVisible != null) {
|
||||
json[r'isVisible'] = this.isVisible;
|
||||
} else {
|
||||
// json[r'isVisible'] = null;
|
||||
}
|
||||
if (this.libraryId != null) {
|
||||
json[r'libraryId'] = this.libraryId;
|
||||
} else {
|
||||
// json[r'libraryId'] = null;
|
||||
}
|
||||
if (this.sidecarPath != null) {
|
||||
json[r'sidecarPath'] = this.sidecarPath;
|
||||
} else {
|
||||
// json[r'sidecarPath'] = null;
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
/// Returns a new [ImportAssetDto] instance and imports its values from
|
||||
/// [value] if it's a [Map], null otherwise.
|
||||
// ignore: prefer_constructors_over_static_methods
|
||||
static ImportAssetDto? fromJson(dynamic value) {
|
||||
if (value is Map) {
|
||||
final json = value.cast<String, dynamic>();
|
||||
|
||||
return ImportAssetDto(
|
||||
assetPath: mapValueOfType<String>(json, r'assetPath')!,
|
||||
deviceAssetId: mapValueOfType<String>(json, r'deviceAssetId')!,
|
||||
deviceId: mapValueOfType<String>(json, r'deviceId')!,
|
||||
duration: mapValueOfType<String>(json, r'duration'),
|
||||
fileCreatedAt: mapDateTime(json, r'fileCreatedAt', '')!,
|
||||
fileModifiedAt: mapDateTime(json, r'fileModifiedAt', '')!,
|
||||
isArchived: mapValueOfType<bool>(json, r'isArchived'),
|
||||
isExternal: mapValueOfType<bool>(json, r'isExternal'),
|
||||
isFavorite: mapValueOfType<bool>(json, r'isFavorite'),
|
||||
isOffline: mapValueOfType<bool>(json, r'isOffline'),
|
||||
isReadOnly: mapValueOfType<bool>(json, r'isReadOnly') ?? true,
|
||||
isVisible: mapValueOfType<bool>(json, r'isVisible'),
|
||||
libraryId: mapValueOfType<String>(json, r'libraryId'),
|
||||
sidecarPath: mapValueOfType<String>(json, r'sidecarPath'),
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static List<ImportAssetDto> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <ImportAssetDto>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
for (final row in json) {
|
||||
final value = ImportAssetDto.fromJson(row);
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toList(growable: growable);
|
||||
}
|
||||
|
||||
static Map<String, ImportAssetDto> mapFromJson(dynamic json) {
|
||||
final map = <String, ImportAssetDto>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||
for (final entry in json.entries) {
|
||||
final value = ImportAssetDto.fromJson(entry.value);
|
||||
if (value != null) {
|
||||
map[entry.key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
// maps a json object with a list of ImportAssetDto-objects as value to a dart map
|
||||
static Map<String, List<ImportAssetDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||
final map = <String, List<ImportAssetDto>>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
// ignore: parameter_assignments
|
||||
json = json.cast<String, dynamic>();
|
||||
for (final entry in json.entries) {
|
||||
map[entry.key] = ImportAssetDto.listFromJson(entry.value, growable: growable,);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/// The list of required keys that must be present in a JSON.
|
||||
static const requiredKeys = <String>{
|
||||
'assetPath',
|
||||
'deviceAssetId',
|
||||
'deviceId',
|
||||
'fileCreatedAt',
|
||||
'fileModifiedAt',
|
||||
};
|
||||
}
|
||||
|
98
mobile/openapi/lib/model/search_asset_dto.dart
generated
98
mobile/openapi/lib/model/search_asset_dto.dart
generated
|
@ -1,98 +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 SearchAssetDto {
|
||||
/// Returns a new [SearchAssetDto] instance.
|
||||
SearchAssetDto({
|
||||
required this.searchTerm,
|
||||
});
|
||||
|
||||
String searchTerm;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is SearchAssetDto &&
|
||||
other.searchTerm == searchTerm;
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
// ignore: unnecessary_parenthesis
|
||||
(searchTerm.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'SearchAssetDto[searchTerm=$searchTerm]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
json[r'searchTerm'] = this.searchTerm;
|
||||
return json;
|
||||
}
|
||||
|
||||
/// Returns a new [SearchAssetDto] instance and imports its values from
|
||||
/// [value] if it's a [Map], null otherwise.
|
||||
// ignore: prefer_constructors_over_static_methods
|
||||
static SearchAssetDto? fromJson(dynamic value) {
|
||||
if (value is Map) {
|
||||
final json = value.cast<String, dynamic>();
|
||||
|
||||
return SearchAssetDto(
|
||||
searchTerm: mapValueOfType<String>(json, r'searchTerm')!,
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static List<SearchAssetDto> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <SearchAssetDto>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
for (final row in json) {
|
||||
final value = SearchAssetDto.fromJson(row);
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toList(growable: growable);
|
||||
}
|
||||
|
||||
static Map<String, SearchAssetDto> mapFromJson(dynamic json) {
|
||||
final map = <String, SearchAssetDto>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||
for (final entry in json.entries) {
|
||||
final value = SearchAssetDto.fromJson(entry.value);
|
||||
if (value != null) {
|
||||
map[entry.key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
// maps a json object with a list of SearchAssetDto-objects as value to a dart map
|
||||
static Map<String, List<SearchAssetDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||
final map = <String, List<SearchAssetDto>>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
// ignore: parameter_assignments
|
||||
json = json.cast<String, dynamic>();
|
||||
for (final entry in json.entries) {
|
||||
map[entry.key] = SearchAssetDto.listFromJson(entry.value, growable: growable,);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/// The list of required keys that must be present in a JSON.
|
||||
static const requiredKeys = <String>{
|
||||
'searchTerm',
|
||||
};
|
||||
}
|
||||
|
10
mobile/openapi/test/asset_api_test.dart
generated
10
mobile/openapi/test/asset_api_test.dart
generated
|
@ -127,11 +127,6 @@ void main() {
|
|||
// TODO
|
||||
});
|
||||
|
||||
//Future<AssetFileUploadResponseDto> importFile(ImportAssetDto importAssetDto) async
|
||||
test('test importFile', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
//Future restoreAssets(BulkIdsDto bulkIdsDto) async
|
||||
test('test restoreAssets', () async {
|
||||
// TODO
|
||||
|
@ -147,11 +142,6 @@ void main() {
|
|||
// TODO
|
||||
});
|
||||
|
||||
//Future<List<AssetResponseDto>> searchAsset(SearchAssetDto searchAssetDto) async
|
||||
test('test searchAsset', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
//Future<List<AssetResponseDto>> searchAssets({ String id, String libraryId, AssetTypeEnum type, AssetOrder order, String deviceAssetId, String deviceId, String checksum, bool isArchived, bool isEncoded, bool isExternal, bool isFavorite, bool isMotion, bool isOffline, bool isReadOnly, bool isVisible, bool withDeleted, bool withStacked, bool withExif, bool withPeople, DateTime createdBefore, DateTime createdAfter, DateTime updatedBefore, DateTime updatedAfter, DateTime trashedBefore, DateTime trashedAfter, DateTime takenBefore, DateTime takenAfter, String originalFileName, String originalPath, String resizePath, String webpPath, String encodedVideoPath, String city, String state, String country, String make, String model, String lensModel, num page, num size }) async
|
||||
test('test searchAssets', () async {
|
||||
// TODO
|
||||
|
|
92
mobile/openapi/test/import_asset_dto_test.dart
generated
92
mobile/openapi/test/import_asset_dto_test.dart
generated
|
@ -1,92 +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
|
||||
|
||||
import 'package:openapi/api.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
// tests for ImportAssetDto
|
||||
void main() {
|
||||
// final instance = ImportAssetDto();
|
||||
|
||||
group('test ImportAssetDto', () {
|
||||
// String assetPath
|
||||
test('to test the property `assetPath`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// String deviceAssetId
|
||||
test('to test the property `deviceAssetId`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// String deviceId
|
||||
test('to test the property `deviceId`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// String duration
|
||||
test('to test the property `duration`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// DateTime fileCreatedAt
|
||||
test('to test the property `fileCreatedAt`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// DateTime fileModifiedAt
|
||||
test('to test the property `fileModifiedAt`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// bool isArchived
|
||||
test('to test the property `isArchived`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// bool isExternal
|
||||
test('to test the property `isExternal`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// bool isFavorite
|
||||
test('to test the property `isFavorite`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// bool isOffline
|
||||
test('to test the property `isOffline`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// bool isReadOnly (default value: true)
|
||||
test('to test the property `isReadOnly`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// bool isVisible
|
||||
test('to test the property `isVisible`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// String libraryId
|
||||
test('to test the property `libraryId`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// String sidecarPath
|
||||
test('to test the property `sidecarPath`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
}
|
27
mobile/openapi/test/search_asset_dto_test.dart
generated
27
mobile/openapi/test/search_asset_dto_test.dart
generated
|
@ -1,27 +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
|
||||
|
||||
import 'package:openapi/api.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
// tests for SearchAssetDto
|
||||
void main() {
|
||||
// final instance = SearchAssetDto();
|
||||
|
||||
group('test SearchAssetDto', () {
|
||||
// String searchTerm
|
||||
test('to test the property `searchTerm`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
}
|
|
@ -1485,48 +1485,6 @@
|
|||
]
|
||||
}
|
||||
},
|
||||
"/asset/import": {
|
||||
"post": {
|
||||
"operationId": "importFile",
|
||||
"parameters": [],
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ImportAssetDto"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": true
|
||||
},
|
||||
"responses": {
|
||||
"201": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/AssetFileUploadResponseDto"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"bearer": []
|
||||
},
|
||||
{
|
||||
"cookie": []
|
||||
},
|
||||
{
|
||||
"api_key": []
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Asset"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/asset/jobs": {
|
||||
"post": {
|
||||
"operationId": "runAssetJobs",
|
||||
|
@ -1763,51 +1721,6 @@
|
|||
]
|
||||
}
|
||||
},
|
||||
"/asset/search": {
|
||||
"post": {
|
||||
"operationId": "searchAsset",
|
||||
"parameters": [],
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/SearchAssetDto"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": true
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/AssetResponseDto"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"bearer": []
|
||||
},
|
||||
{
|
||||
"cookie": []
|
||||
},
|
||||
{
|
||||
"api_key": []
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Asset"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/asset/search-terms": {
|
||||
"get": {
|
||||
"operationId": "getAssetSearchTerms",
|
||||
|
@ -7585,64 +7498,6 @@
|
|||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ImportAssetDto": {
|
||||
"properties": {
|
||||
"assetPath": {
|
||||
"type": "string"
|
||||
},
|
||||
"deviceAssetId": {
|
||||
"type": "string"
|
||||
},
|
||||
"deviceId": {
|
||||
"type": "string"
|
||||
},
|
||||
"duration": {
|
||||
"type": "string"
|
||||
},
|
||||
"fileCreatedAt": {
|
||||
"format": "date-time",
|
||||
"type": "string"
|
||||
},
|
||||
"fileModifiedAt": {
|
||||
"format": "date-time",
|
||||
"type": "string"
|
||||
},
|
||||
"isArchived": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"isExternal": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"isFavorite": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"isOffline": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"isReadOnly": {
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"isVisible": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"libraryId": {
|
||||
"format": "uuid",
|
||||
"type": "string"
|
||||
},
|
||||
"sidecarPath": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"assetPath",
|
||||
"deviceAssetId",
|
||||
"deviceId",
|
||||
"fileCreatedAt",
|
||||
"fileModifiedAt"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"JobCommand": {
|
||||
"enum": [
|
||||
"start",
|
||||
|
@ -8346,17 +8201,6 @@
|
|||
],
|
||||
"type": "object"
|
||||
},
|
||||
"SearchAssetDto": {
|
||||
"properties": {
|
||||
"searchTerm": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"searchTerm"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"SearchAssetResponseDto": {
|
||||
"properties": {
|
||||
"count": {
|
||||
|
|
|
@ -24,10 +24,9 @@ import { AssetService } from './asset.service';
|
|||
import { AssetBulkUploadCheckDto } from './dto/asset-check.dto';
|
||||
import { AssetSearchDto } from './dto/asset-search.dto';
|
||||
import { CheckExistingAssetsDto } from './dto/check-existing-assets.dto';
|
||||
import { CreateAssetDto, ImportAssetDto } from './dto/create-asset.dto';
|
||||
import { CreateAssetDto } from './dto/create-asset.dto';
|
||||
import { DeviceIdDto } from './dto/device-id.dto';
|
||||
import { GetAssetThumbnailDto } from './dto/get-asset-thumbnail.dto';
|
||||
import { SearchAssetDto } from './dto/search-asset.dto';
|
||||
import { ServeFileDto } from './dto/serve-file.dto';
|
||||
import { AssetBulkUploadCheckResponseDto } from './response-dto/asset-check-response.dto';
|
||||
import { AssetFileUploadResponseDto } from './response-dto/asset-file-upload-response.dto';
|
||||
|
@ -82,20 +81,6 @@ export class AssetController {
|
|||
return responseDto;
|
||||
}
|
||||
|
||||
@Post('import')
|
||||
async importFile(
|
||||
@AuthUser() authUser: AuthUserDto,
|
||||
@Body(new ValidationPipe({ transform: true })) dto: ImportAssetDto,
|
||||
@Response({ passthrough: true }) res: Res,
|
||||
): Promise<AssetFileUploadResponseDto> {
|
||||
const responseDto = await this.assetService.importFile(authUser, dto);
|
||||
if (responseDto.duplicate) {
|
||||
res.status(200);
|
||||
}
|
||||
|
||||
return responseDto;
|
||||
}
|
||||
|
||||
@SharedLinkRoute()
|
||||
@Get('/file/:id')
|
||||
@ApiOkResponse({
|
||||
|
@ -144,15 +129,6 @@ export class AssetController {
|
|||
return this.assetService.getAssetSearchTerm(authUser);
|
||||
}
|
||||
|
||||
@Post('/search')
|
||||
@HttpCode(HttpStatus.OK)
|
||||
searchAsset(
|
||||
@AuthUser() authUser: AuthUserDto,
|
||||
@Body(ValidationPipe) dto: SearchAssetDto,
|
||||
): Promise<AssetResponseDto[]> {
|
||||
return this.assetService.searchAsset(authUser, dto);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all AssetEntity belong to the user
|
||||
*/
|
||||
|
|
|
@ -2,7 +2,7 @@ import { AuthUserDto, IJobRepository, JobName, mimeTypes, UploadFile } from '@ap
|
|||
import { AssetEntity } from '@app/infra/entities';
|
||||
import { parse } from 'node:path';
|
||||
import { IAssetRepository } from './asset-repository';
|
||||
import { CreateAssetDto, ImportAssetDto } from './dto/create-asset.dto';
|
||||
import { CreateAssetDto } from './dto/create-asset.dto';
|
||||
|
||||
export class AssetCore {
|
||||
constructor(
|
||||
|
@ -12,7 +12,7 @@ export class AssetCore {
|
|||
|
||||
async create(
|
||||
authUser: AuthUserDto,
|
||||
dto: (CreateAssetDto | ImportAssetDto) & { libraryId: string },
|
||||
dto: CreateAssetDto & { libraryId: string },
|
||||
file: UploadFile,
|
||||
livePhotoAssetId?: string,
|
||||
sidecarPath?: string,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { ICryptoRepository, IJobRepository, ILibraryRepository, IStorageRepository, JobName } from '@app/domain';
|
||||
import { IJobRepository, ILibraryRepository, JobName } from '@app/domain';
|
||||
import { ASSET_CHECKSUM_CONSTRAINT, AssetEntity, AssetType, ExifEntity } from '@app/infra/entities';
|
||||
import { BadRequestException } from '@nestjs/common';
|
||||
import {
|
||||
|
@ -7,13 +7,11 @@ import {
|
|||
authStub,
|
||||
fileStub,
|
||||
newAccessRepositoryMock,
|
||||
newCryptoRepositoryMock,
|
||||
newJobRepositoryMock,
|
||||
newLibraryRepositoryMock,
|
||||
newStorageRepositoryMock,
|
||||
} from '@test';
|
||||
import { when } from 'jest-when';
|
||||
import { QueryFailedError, Repository } from 'typeorm';
|
||||
import { QueryFailedError } from 'typeorm';
|
||||
import { IAssetRepository } from './asset-repository';
|
||||
import { AssetService } from './asset.service';
|
||||
import { CreateAssetDto } from './dto/create-asset.dto';
|
||||
|
@ -85,12 +83,9 @@ const _getAssets = () => {
|
|||
|
||||
describe('AssetService', () => {
|
||||
let sut: AssetService;
|
||||
let a: Repository<AssetEntity>; // TO BE DELETED AFTER FINISHED REFACTORING
|
||||
let accessMock: IAccessRepositoryMock;
|
||||
let assetRepositoryMock: jest.Mocked<IAssetRepository>;
|
||||
let cryptoMock: jest.Mocked<ICryptoRepository>;
|
||||
let jobMock: jest.Mocked<IJobRepository>;
|
||||
let storageMock: jest.Mocked<IStorageRepository>;
|
||||
let libraryMock: jest.Mocked<ILibraryRepository>;
|
||||
|
||||
beforeEach(() => {
|
||||
|
@ -110,12 +105,10 @@ describe('AssetService', () => {
|
|||
};
|
||||
|
||||
accessMock = newAccessRepositoryMock();
|
||||
cryptoMock = newCryptoRepositoryMock();
|
||||
jobMock = newJobRepositoryMock();
|
||||
storageMock = newStorageRepositoryMock();
|
||||
libraryMock = newLibraryRepositoryMock();
|
||||
|
||||
sut = new AssetService(accessMock, assetRepositoryMock, a, cryptoMock, jobMock, libraryMock, storageMock);
|
||||
sut = new AssetService(accessMock, assetRepositoryMock, jobMock, libraryMock);
|
||||
|
||||
when(assetRepositoryMock.get)
|
||||
.calledWith(assetStub.livePhotoStillAsset.id)
|
||||
|
@ -165,7 +158,6 @@ describe('AssetService', () => {
|
|||
name: JobName.DELETE_FILES,
|
||||
data: { files: ['fake_path/asset_1.jpeg', undefined, undefined] },
|
||||
});
|
||||
expect(storageMock.moveFile).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should handle a live photo', async () => {
|
||||
|
@ -238,47 +230,6 @@ describe('AssetService', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('importFile', () => {
|
||||
it('should handle a file import', async () => {
|
||||
assetRepositoryMock.create.mockResolvedValue(assetStub.image);
|
||||
storageMock.checkFileExists.mockResolvedValue(true);
|
||||
accessMock.library.hasOwnerAccess.mockResolvedValue(true);
|
||||
|
||||
await expect(
|
||||
sut.importFile(authStub.external1, {
|
||||
..._getCreateAssetDto(),
|
||||
assetPath: '/data/user1/fake_path/asset_1.jpeg',
|
||||
isReadOnly: true,
|
||||
libraryId: 'library-id',
|
||||
}),
|
||||
).resolves.toEqual({ duplicate: false, id: 'asset-id' });
|
||||
|
||||
expect(assetRepositoryMock.create).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should handle a duplicate if originalPath already exists', async () => {
|
||||
const error = new QueryFailedError('', [], '');
|
||||
(error as any).constraint = ASSET_CHECKSUM_CONSTRAINT;
|
||||
|
||||
assetRepositoryMock.create.mockRejectedValue(error);
|
||||
assetRepositoryMock.getAssetsByChecksums.mockResolvedValue([assetStub.image]);
|
||||
storageMock.checkFileExists.mockResolvedValue(true);
|
||||
accessMock.library.hasOwnerAccess.mockResolvedValue(true);
|
||||
cryptoMock.hashFile.mockResolvedValue(Buffer.from('file hash', 'utf8'));
|
||||
|
||||
await expect(
|
||||
sut.importFile(authStub.external1, {
|
||||
..._getCreateAssetDto(),
|
||||
assetPath: '/data/user1/fake_path/asset_1.jpeg',
|
||||
isReadOnly: true,
|
||||
libraryId: 'library-id',
|
||||
}),
|
||||
).resolves.toEqual({ duplicate: true, id: 'asset-id' });
|
||||
|
||||
expect(assetRepositoryMock.create).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('getAssetById', () => {
|
||||
it('should allow owner access', async () => {
|
||||
accessMock.asset.hasOwnerAccess.mockResolvedValue(true);
|
||||
|
|
|
@ -4,10 +4,8 @@ import {
|
|||
AuthUserDto,
|
||||
getLivePhotoMotionFilename,
|
||||
IAccessRepository,
|
||||
ICryptoRepository,
|
||||
IJobRepository,
|
||||
ILibraryRepository,
|
||||
IStorageRepository,
|
||||
JobName,
|
||||
mapAsset,
|
||||
mimeTypes,
|
||||
|
@ -16,28 +14,19 @@ import {
|
|||
UploadFile,
|
||||
} from '@app/domain';
|
||||
import { ASSET_CHECKSUM_CONSTRAINT, AssetEntity, AssetType, LibraryType } from '@app/infra/entities';
|
||||
import {
|
||||
BadRequestException,
|
||||
Inject,
|
||||
Injectable,
|
||||
InternalServerErrorException,
|
||||
Logger,
|
||||
NotFoundException,
|
||||
} from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { Inject, Injectable, InternalServerErrorException, Logger, NotFoundException } from '@nestjs/common';
|
||||
import { Response as Res, Response } from 'express';
|
||||
import { constants } from 'fs';
|
||||
import fs from 'fs/promises';
|
||||
import path from 'path';
|
||||
import { QueryFailedError, Repository } from 'typeorm';
|
||||
import { QueryFailedError } from 'typeorm';
|
||||
import { IAssetRepository } from './asset-repository';
|
||||
import { AssetCore } from './asset.core';
|
||||
import { AssetBulkUploadCheckDto } from './dto/asset-check.dto';
|
||||
import { AssetSearchDto } from './dto/asset-search.dto';
|
||||
import { CheckExistingAssetsDto } from './dto/check-existing-assets.dto';
|
||||
import { CreateAssetDto, ImportAssetDto } from './dto/create-asset.dto';
|
||||
import { CreateAssetDto } from './dto/create-asset.dto';
|
||||
import { GetAssetThumbnailDto, GetAssetThumbnailFormatEnum } from './dto/get-asset-thumbnail.dto';
|
||||
import { SearchAssetDto } from './dto/search-asset.dto';
|
||||
import { SearchPropertiesDto } from './dto/search-properties.dto';
|
||||
import { ServeFileDto } from './dto/serve-file.dto';
|
||||
import {
|
||||
|
@ -62,11 +51,8 @@ export class AssetService {
|
|||
constructor(
|
||||
@Inject(IAccessRepository) accessRepository: IAccessRepository,
|
||||
@Inject(IAssetRepository) private _assetRepository: IAssetRepository,
|
||||
@InjectRepository(AssetEntity) private assetRepository: Repository<AssetEntity>,
|
||||
@Inject(ICryptoRepository) private cryptoRepository: ICryptoRepository,
|
||||
@Inject(IJobRepository) private jobRepository: IJobRepository,
|
||||
@Inject(ILibraryRepository) private libraryRepository: ILibraryRepository,
|
||||
@Inject(IStorageRepository) private storageRepository: IStorageRepository,
|
||||
) {
|
||||
this.assetCore = new AssetCore(_assetRepository, jobRepository);
|
||||
this.access = AccessCore.create(accessRepository);
|
||||
|
@ -124,59 +110,6 @@ export class AssetService {
|
|||
}
|
||||
}
|
||||
|
||||
public async importFile(authUser: AuthUserDto, dto: ImportAssetDto): Promise<AssetFileUploadResponseDto> {
|
||||
dto = {
|
||||
...dto,
|
||||
assetPath: path.resolve(dto.assetPath),
|
||||
sidecarPath: dto.sidecarPath ? path.resolve(dto.sidecarPath) : undefined,
|
||||
};
|
||||
|
||||
if (!mimeTypes.isAsset(dto.assetPath)) {
|
||||
throw new BadRequestException(`Unsupported file type ${dto.assetPath}`);
|
||||
}
|
||||
|
||||
if (dto.sidecarPath && !mimeTypes.isSidecar(dto.sidecarPath)) {
|
||||
throw new BadRequestException(`Unsupported sidecar file type`);
|
||||
}
|
||||
|
||||
for (const filepath of [dto.assetPath, dto.sidecarPath]) {
|
||||
if (!filepath) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const exists = await this.storageRepository.checkFileExists(filepath, constants.R_OK);
|
||||
if (!exists) {
|
||||
throw new BadRequestException('File does not exist');
|
||||
}
|
||||
}
|
||||
|
||||
if (!authUser.externalPath || !dto.assetPath.match(new RegExp(`^${authUser.externalPath}`))) {
|
||||
throw new BadRequestException("File does not exist within user's external path");
|
||||
}
|
||||
|
||||
const assetFile: UploadFile = {
|
||||
checksum: await this.cryptoRepository.hashFile(dto.assetPath),
|
||||
originalPath: dto.assetPath,
|
||||
originalName: path.parse(dto.assetPath).name,
|
||||
};
|
||||
|
||||
try {
|
||||
const libraryId = await this.getLibraryId(authUser, dto.libraryId);
|
||||
await this.access.requirePermission(authUser, Permission.ASSET_UPLOAD, libraryId);
|
||||
const asset = await this.assetCore.create(authUser, { ...dto, libraryId }, assetFile, undefined, dto.sidecarPath);
|
||||
return { id: asset.id, duplicate: false };
|
||||
} catch (error: QueryFailedError | Error | any) {
|
||||
// handle duplicates with a success response
|
||||
if (error instanceof QueryFailedError && (error as any).constraint === ASSET_CHECKSUM_CONSTRAINT) {
|
||||
const [duplicate] = await this._assetRepository.getAssetsByChecksums(authUser.id, [assetFile.checksum]);
|
||||
return { id: duplicate.id, duplicate: true };
|
||||
}
|
||||
|
||||
this.logger.error(`Error importing file ${error}`, error?.stack);
|
||||
throw new BadRequestException(`Error importing file`, `${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
public async getUserAssetsByDeviceId(authUser: AuthUserDto, deviceId: string) {
|
||||
return this._assetRepository.getAllByDeviceId(authUser.id, deviceId);
|
||||
}
|
||||
|
@ -285,30 +218,6 @@ export class AssetService {
|
|||
return Array.from(possibleSearchTerm).filter((x) => x != null && x != '');
|
||||
}
|
||||
|
||||
async searchAsset(authUser: AuthUserDto, searchAssetDto: SearchAssetDto): Promise<AssetResponseDto[]> {
|
||||
const query = `
|
||||
SELECT a.*
|
||||
FROM assets a
|
||||
LEFT JOIN smart_info si ON a.id = si."assetId"
|
||||
LEFT JOIN exif e ON a.id = e."assetId"
|
||||
|
||||
WHERE a."ownerId" = $1
|
||||
AND
|
||||
(
|
||||
TO_TSVECTOR('english', ARRAY_TO_STRING(si.tags, ',')) @@ PLAINTO_TSQUERY('english', $2) OR
|
||||
TO_TSVECTOR('english', ARRAY_TO_STRING(si.objects, ',')) @@ PLAINTO_TSQUERY('english', $2) OR
|
||||
e."exifTextSearchableColumn" @@ PLAINTO_TSQUERY('english', $2)
|
||||
);
|
||||
`;
|
||||
|
||||
const searchResults: AssetEntity[] = await this.assetRepository.query(query, [
|
||||
authUser.id,
|
||||
searchAssetDto.searchTerm,
|
||||
]);
|
||||
|
||||
return searchResults.map((asset) => mapAsset(asset));
|
||||
}
|
||||
|
||||
async getCuratedLocation(authUser: AuthUserDto): Promise<CuratedLocationsResponseDto[]> {
|
||||
return this._assetRepository.getLocationsByUserId(authUser.id);
|
||||
}
|
||||
|
|
|
@ -70,23 +70,3 @@ export class CreateAssetDto extends CreateAssetBase {
|
|||
@ApiProperty({ type: 'string', format: 'binary', required: false })
|
||||
[UploadFieldName.SIDECAR_DATA]?: any;
|
||||
}
|
||||
|
||||
export class ImportAssetDto extends CreateAssetBase {
|
||||
@Optional()
|
||||
@IsBoolean()
|
||||
@Transform(toBoolean)
|
||||
isReadOnly?: boolean = true;
|
||||
|
||||
@ValidateUUID()
|
||||
@Optional()
|
||||
libraryId?: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
assetPath!: string;
|
||||
|
||||
@IsString()
|
||||
@Optional()
|
||||
@IsNotEmpty()
|
||||
sidecarPath?: string;
|
||||
}
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
import { IsNotEmpty } from 'class-validator';
|
||||
|
||||
export class SearchAssetDto {
|
||||
@IsNotEmpty()
|
||||
searchTerm!: string;
|
||||
}
|
280
web/src/api/open-api/api.ts
generated
280
web/src/api/open-api/api.ts
generated
|
@ -1773,97 +1773,6 @@ export interface FileReportItemDto {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface ImportAssetDto
|
||||
*/
|
||||
export interface ImportAssetDto {
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof ImportAssetDto
|
||||
*/
|
||||
'assetPath': string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof ImportAssetDto
|
||||
*/
|
||||
'deviceAssetId': string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof ImportAssetDto
|
||||
*/
|
||||
'deviceId': string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof ImportAssetDto
|
||||
*/
|
||||
'duration'?: string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof ImportAssetDto
|
||||
*/
|
||||
'fileCreatedAt': string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof ImportAssetDto
|
||||
*/
|
||||
'fileModifiedAt': string;
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
* @memberof ImportAssetDto
|
||||
*/
|
||||
'isArchived'?: boolean;
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
* @memberof ImportAssetDto
|
||||
*/
|
||||
'isExternal'?: boolean;
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
* @memberof ImportAssetDto
|
||||
*/
|
||||
'isFavorite'?: boolean;
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
* @memberof ImportAssetDto
|
||||
*/
|
||||
'isOffline'?: boolean;
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
* @memberof ImportAssetDto
|
||||
*/
|
||||
'isReadOnly'?: boolean;
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
* @memberof ImportAssetDto
|
||||
*/
|
||||
'isVisible'?: boolean;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof ImportAssetDto
|
||||
*/
|
||||
'libraryId'?: string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof ImportAssetDto
|
||||
*/
|
||||
'sidecarPath'?: string;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
|
@ -2794,19 +2703,6 @@ export interface SearchAlbumResponseDto {
|
|||
*/
|
||||
'total': number;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface SearchAssetDto
|
||||
*/
|
||||
export interface SearchAssetDto {
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof SearchAssetDto
|
||||
*/
|
||||
'searchTerm': string;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
|
@ -7622,50 +7518,6 @@ export const AssetApiAxiosParamCreator = function (configuration?: Configuration
|
|||
options: localVarRequestOptions,
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {ImportAssetDto} importAssetDto
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
importFile: async (importAssetDto: ImportAssetDto, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
|
||||
// verify required parameter 'importAssetDto' is not null or undefined
|
||||
assertParamExists('importFile', 'importAssetDto', importAssetDto)
|
||||
const localVarPath = `/asset/import`;
|
||||
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
||||
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
|
||||
let baseOptions;
|
||||
if (configuration) {
|
||||
baseOptions = configuration.baseOptions;
|
||||
}
|
||||
|
||||
const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options};
|
||||
const localVarHeaderParameter = {} as any;
|
||||
const localVarQueryParameter = {} as any;
|
||||
|
||||
// authentication cookie required
|
||||
|
||||
// authentication api_key required
|
||||
await setApiKeyToObject(localVarHeaderParameter, "x-api-key", configuration)
|
||||
|
||||
// authentication bearer required
|
||||
// http bearer authentication required
|
||||
await setBearerAuthToObject(localVarHeaderParameter, configuration)
|
||||
|
||||
|
||||
|
||||
localVarHeaderParameter['Content-Type'] = 'application/json';
|
||||
|
||||
setSearchParams(localVarUrlObj, localVarQueryParameter);
|
||||
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
||||
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
|
||||
localVarRequestOptions.data = serializeDataIfNeeded(importAssetDto, localVarRequestOptions, configuration)
|
||||
|
||||
return {
|
||||
url: toPathString(localVarUrlObj),
|
||||
options: localVarRequestOptions,
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {BulkIdsDto} bulkIdsDto
|
||||
|
@ -7792,50 +7644,6 @@ export const AssetApiAxiosParamCreator = function (configuration?: Configuration
|
|||
options: localVarRequestOptions,
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {SearchAssetDto} searchAssetDto
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
searchAsset: async (searchAssetDto: SearchAssetDto, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
|
||||
// verify required parameter 'searchAssetDto' is not null or undefined
|
||||
assertParamExists('searchAsset', 'searchAssetDto', searchAssetDto)
|
||||
const localVarPath = `/asset/search`;
|
||||
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
||||
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
|
||||
let baseOptions;
|
||||
if (configuration) {
|
||||
baseOptions = configuration.baseOptions;
|
||||
}
|
||||
|
||||
const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options};
|
||||
const localVarHeaderParameter = {} as any;
|
||||
const localVarQueryParameter = {} as any;
|
||||
|
||||
// authentication cookie required
|
||||
|
||||
// authentication api_key required
|
||||
await setApiKeyToObject(localVarHeaderParameter, "x-api-key", configuration)
|
||||
|
||||
// authentication bearer required
|
||||
// http bearer authentication required
|
||||
await setBearerAuthToObject(localVarHeaderParameter, configuration)
|
||||
|
||||
|
||||
|
||||
localVarHeaderParameter['Content-Type'] = 'application/json';
|
||||
|
||||
setSearchParams(localVarUrlObj, localVarQueryParameter);
|
||||
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
||||
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
|
||||
localVarRequestOptions.data = serializeDataIfNeeded(searchAssetDto, localVarRequestOptions, configuration)
|
||||
|
||||
return {
|
||||
url: toPathString(localVarUrlObj),
|
||||
options: localVarRequestOptions,
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {string} [id]
|
||||
|
@ -8659,16 +8467,6 @@ export const AssetApiFp = function(configuration?: Configuration) {
|
|||
const localVarAxiosArgs = await localVarAxiosParamCreator.getUserAssetsByDeviceId(deviceId, options);
|
||||
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {ImportAssetDto} importAssetDto
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async importFile(importAssetDto: ImportAssetDto, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<AssetFileUploadResponseDto>> {
|
||||
const localVarAxiosArgs = await localVarAxiosParamCreator.importFile(importAssetDto, options);
|
||||
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {BulkIdsDto} bulkIdsDto
|
||||
|
@ -8698,16 +8496,6 @@ export const AssetApiFp = function(configuration?: Configuration) {
|
|||
const localVarAxiosArgs = await localVarAxiosParamCreator.runAssetJobs(assetJobsDto, options);
|
||||
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {SearchAssetDto} searchAssetDto
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async searchAsset(searchAssetDto: SearchAssetDto, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Array<AssetResponseDto>>> {
|
||||
const localVarAxiosArgs = await localVarAxiosParamCreator.searchAsset(searchAssetDto, options);
|
||||
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {string} [id]
|
||||
|
@ -9012,15 +8800,6 @@ export const AssetApiFactory = function (configuration?: Configuration, basePath
|
|||
getUserAssetsByDeviceId(requestParameters: AssetApiGetUserAssetsByDeviceIdRequest, options?: AxiosRequestConfig): AxiosPromise<Array<string>> {
|
||||
return localVarFp.getUserAssetsByDeviceId(requestParameters.deviceId, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {AssetApiImportFileRequest} requestParameters Request parameters.
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
importFile(requestParameters: AssetApiImportFileRequest, options?: AxiosRequestConfig): AxiosPromise<AssetFileUploadResponseDto> {
|
||||
return localVarFp.importFile(requestParameters.importAssetDto, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {AssetApiRestoreAssetsRequest} requestParameters Request parameters.
|
||||
|
@ -9047,15 +8826,6 @@ export const AssetApiFactory = function (configuration?: Configuration, basePath
|
|||
runAssetJobs(requestParameters: AssetApiRunAssetJobsRequest, options?: AxiosRequestConfig): AxiosPromise<void> {
|
||||
return localVarFp.runAssetJobs(requestParameters.assetJobsDto, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {AssetApiSearchAssetRequest} requestParameters Request parameters.
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
searchAsset(requestParameters: AssetApiSearchAssetRequest, options?: AxiosRequestConfig): AxiosPromise<Array<AssetResponseDto>> {
|
||||
return localVarFp.searchAsset(requestParameters.searchAssetDto, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {AssetApiSearchAssetsRequest} requestParameters Request parameters.
|
||||
|
@ -9603,20 +9373,6 @@ export interface AssetApiGetUserAssetsByDeviceIdRequest {
|
|||
readonly deviceId: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Request parameters for importFile operation in AssetApi.
|
||||
* @export
|
||||
* @interface AssetApiImportFileRequest
|
||||
*/
|
||||
export interface AssetApiImportFileRequest {
|
||||
/**
|
||||
*
|
||||
* @type {ImportAssetDto}
|
||||
* @memberof AssetApiImportFile
|
||||
*/
|
||||
readonly importAssetDto: ImportAssetDto
|
||||
}
|
||||
|
||||
/**
|
||||
* Request parameters for restoreAssets operation in AssetApi.
|
||||
* @export
|
||||
|
@ -9645,20 +9401,6 @@ export interface AssetApiRunAssetJobsRequest {
|
|||
readonly assetJobsDto: AssetJobsDto
|
||||
}
|
||||
|
||||
/**
|
||||
* Request parameters for searchAsset operation in AssetApi.
|
||||
* @export
|
||||
* @interface AssetApiSearchAssetRequest
|
||||
*/
|
||||
export interface AssetApiSearchAssetRequest {
|
||||
/**
|
||||
*
|
||||
* @type {SearchAssetDto}
|
||||
* @memberof AssetApiSearchAsset
|
||||
*/
|
||||
readonly searchAssetDto: SearchAssetDto
|
||||
}
|
||||
|
||||
/**
|
||||
* Request parameters for searchAssets operation in AssetApi.
|
||||
* @export
|
||||
|
@ -10372,17 +10114,6 @@ export class AssetApi extends BaseAPI {
|
|||
return AssetApiFp(this.configuration).getUserAssetsByDeviceId(requestParameters.deviceId, options).then((request) => request(this.axios, this.basePath));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {AssetApiImportFileRequest} requestParameters Request parameters.
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
* @memberof AssetApi
|
||||
*/
|
||||
public importFile(requestParameters: AssetApiImportFileRequest, options?: AxiosRequestConfig) {
|
||||
return AssetApiFp(this.configuration).importFile(requestParameters.importAssetDto, options).then((request) => request(this.axios, this.basePath));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {AssetApiRestoreAssetsRequest} requestParameters Request parameters.
|
||||
|
@ -10415,17 +10146,6 @@ export class AssetApi extends BaseAPI {
|
|||
return AssetApiFp(this.configuration).runAssetJobs(requestParameters.assetJobsDto, options).then((request) => request(this.axios, this.basePath));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {AssetApiSearchAssetRequest} requestParameters Request parameters.
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
* @memberof AssetApi
|
||||
*/
|
||||
public searchAsset(requestParameters: AssetApiSearchAssetRequest, options?: AxiosRequestConfig) {
|
||||
return AssetApiFp(this.configuration).searchAsset(requestParameters.searchAssetDto, options).then((request) => request(this.axios, this.basePath));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {AssetApiSearchAssetsRequest} requestParameters Request parameters.
|
||||
|
|
|
@ -173,4 +173,16 @@
|
|||
<div class="mb-6 mt-auto">
|
||||
<StatusBox />
|
||||
</div>
|
||||
|
||||
{#if $page.data.user.isAdmin}
|
||||
<!-- TODO REMOVE IN 1.88 -->
|
||||
<div class="bg-red-100 dark:bg-gray-900 ml-4 mb-4 p-5 text-sm dark:text-red-300 rounded-2xl">
|
||||
<p>
|
||||
The upcoming release <span class="font-mono">v1.88.0</span> will include breaking change in the way Immich
|
||||
deploy its application. Please read the following
|
||||
<a href="https://github.com/immich-app/immich/discussions/5086" class="underline">annoucement</a> to make sure you
|
||||
are ready for the update.
|
||||
</p>
|
||||
</div>
|
||||
{/if}
|
||||
</SideBarSection>
|
||||
|
|
Loading…
Reference in a new issue