From c254a04aec87784df2d76bc6ec54aaa5f2291328 Mon Sep 17 00:00:00 2001 From: Alex Date: Sat, 15 Jul 2023 20:24:46 -0500 Subject: [PATCH] feat(server): add endpoint to get supported media types on the server (#3284) * feat(server): add endpoint to get supported media types on the server * api generation * remove xmp format * change dto * openapi * dev --- cli/src/api/open-api/api.ts | 81 ++++++++++++++++++ mobile/openapi/.openapi-generator/FILES | 3 + mobile/openapi/README.md | Bin 17931 -> 18132 bytes mobile/openapi/doc/ServerInfoApi.md | Bin 5677 -> 6615 bytes .../doc/ServerMediaTypesResponseDto.md | Bin 0 -> 563 bytes mobile/openapi/lib/api.dart | Bin 5813 -> 5864 bytes mobile/openapi/lib/api/server_info_api.dart | Bin 5980 -> 7431 bytes mobile/openapi/lib/api_client.dart | Bin 18329 -> 18435 bytes .../server_media_types_response_dto.dart | Bin 0 -> 3726 bytes mobile/openapi/test/server_info_api_test.dart | Bin 949 -> 1096 bytes .../server_media_types_response_dto_test.dart | Bin 0 -> 889 bytes server/immich-openapi-specs.json | 49 +++++++++++ .../response-dto/server-stats-response.dto.ts | 6 ++ .../domain/server-info/server-info.service.ts | 18 +++- .../controllers/server-info.controller.ts | 7 ++ web/src/api/open-api/api.ts | 81 ++++++++++++++++++ 16 files changed, 243 insertions(+), 2 deletions(-) create mode 100644 mobile/openapi/doc/ServerMediaTypesResponseDto.md create mode 100644 mobile/openapi/lib/model/server_media_types_response_dto.dart create mode 100644 mobile/openapi/test/server_media_types_response_dto_test.dart diff --git a/cli/src/api/open-api/api.ts b/cli/src/api/open-api/api.ts index b0bf9a8f2f..f6a1127a58 100644 --- a/cli/src/api/open-api/api.ts +++ b/cli/src/api/open-api/api.ts @@ -2085,6 +2085,31 @@ export interface ServerInfoResponseDto { */ 'diskAvailable': string; } +/** + * + * @export + * @interface ServerMediaTypesResponseDto + */ +export interface ServerMediaTypesResponseDto { + /** + * + * @type {Array} + * @memberof ServerMediaTypesResponseDto + */ + 'video': Array; + /** + * + * @type {Array} + * @memberof ServerMediaTypesResponseDto + */ + 'image': Array; + /** + * + * @type {Array} + * @memberof ServerMediaTypesResponseDto + */ + 'sidecar': Array; +} /** * * @export @@ -9711,6 +9736,35 @@ export const ServerInfoApiAxiosParamCreator = function (configuration?: Configur + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getSupportedMediaTypes: async (options: AxiosRequestConfig = {}): Promise => { + const localVarPath = `/server-info/media-types`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + + setSearchParams(localVarUrlObj, localVarQueryParameter); let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; @@ -9786,6 +9840,15 @@ export const ServerInfoApiFp = function(configuration?: Configuration) { const localVarAxiosArgs = await localVarAxiosParamCreator.getStats(options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, + /** + * + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async getSupportedMediaTypes(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.getSupportedMediaTypes(options); + return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + }, /** * * @param {*} [options] Override http request option. @@ -9829,6 +9892,14 @@ export const ServerInfoApiFactory = function (configuration?: Configuration, bas getStats(options?: AxiosRequestConfig): AxiosPromise { return localVarFp.getStats(options).then((request) => request(axios, basePath)); }, + /** + * + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getSupportedMediaTypes(options?: AxiosRequestConfig): AxiosPromise { + return localVarFp.getSupportedMediaTypes(options).then((request) => request(axios, basePath)); + }, /** * * @param {*} [options] Override http request option. @@ -9877,6 +9948,16 @@ export class ServerInfoApi extends BaseAPI { return ServerInfoApiFp(this.configuration).getStats(options).then((request) => request(this.axios, this.basePath)); } + /** + * + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ServerInfoApi + */ + public getSupportedMediaTypes(options?: AxiosRequestConfig) { + return ServerInfoApiFp(this.configuration).getSupportedMediaTypes(options).then((request) => request(this.axios, this.basePath)); + } + /** * * @param {*} [options] Override http request option. diff --git a/mobile/openapi/.openapi-generator/FILES b/mobile/openapi/.openapi-generator/FILES index f098bf4ffe..5c610108b5 100644 --- a/mobile/openapi/.openapi-generator/FILES +++ b/mobile/openapi/.openapi-generator/FILES @@ -88,6 +88,7 @@ doc/SearchFacetResponseDto.md doc/SearchResponseDto.md doc/ServerInfoApi.md doc/ServerInfoResponseDto.md +doc/ServerMediaTypesResponseDto.md doc/ServerPingResponse.md doc/ServerStatsResponseDto.md doc/ServerVersionReponseDto.md @@ -221,6 +222,7 @@ lib/model/search_facet_count_response_dto.dart lib/model/search_facet_response_dto.dart lib/model/search_response_dto.dart lib/model/server_info_response_dto.dart +lib/model/server_media_types_response_dto.dart lib/model/server_ping_response.dart lib/model/server_stats_response_dto.dart lib/model/server_version_reponse_dto.dart @@ -337,6 +339,7 @@ test/search_facet_response_dto_test.dart test/search_response_dto_test.dart test/server_info_api_test.dart test/server_info_response_dto_test.dart +test/server_media_types_response_dto_test.dart test/server_ping_response_test.dart test/server_stats_response_dto_test.dart test/server_version_reponse_dto_test.dart diff --git a/mobile/openapi/README.md b/mobile/openapi/README.md index 3d9dc921109c8d62ae1deaa0f7e259bcbee5a09c..b8fa7a4d2484185e9e330fecb61af8f96cc9500e 100644 GIT binary patch delta 136 zcmeC~VZ74IxIso)EIqX(xU`@kzo;ZN#Wyu2GclyHAhme%2SqtEm~bvgxCA7usZgV! zrRDA#qNSyvUz}Q0mRh8nnU|KY4_2ZJRx?>&NpiD{@_K1bxN(yi4TJ@P!OG!c#hW+U HMX>__e%CQ_ delta 19 bcmcc8%h=t+xIspF^L*v?(wnE)JFo))P^brX diff --git a/mobile/openapi/doc/ServerInfoApi.md b/mobile/openapi/doc/ServerInfoApi.md index 3b39ef93eee19e4e861bf2152d2d9fecd2d3f804..0666c7d414b8d744e0adf61e3eb5235630239875 100644 GIT binary patch delta 264 zcmZ3hbKQ8uc}CIn)RN%Rf`a^_lGGI6)RfG`kjjG8$vuoxLNL)>kZ1`|w0LqHqa+uY zs|(_9KF(M!=!4aOVl6E$JB8rXqO#N?xT(cKsl^5PdBv$NCHV?iwN1|Fv75YH*bj%R u4hlpI!dwM6b+Wu*x+a{5Y=@RstOmLhCQoEn*(9pVIN5=RWwV{|dnN$431jg9 delta 17 Zcmca^yjEw!dB)AwO!YD0suyn2X+7e diff --git a/mobile/openapi/doc/ServerMediaTypesResponseDto.md b/mobile/openapi/doc/ServerMediaTypesResponseDto.md new file mode 100644 index 0000000000000000000000000000000000000000..78253e27f7e01a91fd14b74bd4c476094a26fd55 GIT binary patch literal 563 zcmbVJO>4t2488kT2y*BeNP6GKpd&pDno`=`LZBvAJF~vq{zUyPpK z)6+)=I16XZfA60 zWd~1zVRFWA&&6lSAQ2{ai8@wV2T2CD7}ZJ-2=9;#<*P7u!FsmjBw7&*qqukiUPMLl zTdeZ@WDQcD3p3A`HuC+JgLQ|85fZd9xYx&?feAVpm!WA}(b++UyFwSmuhZe*O4T%v zveDE=oz4NhG~2c}WjWg{=2g8Y2a_4#(k)Z)pELQ0#r2r#k%0I5_8R{#J2 delta 12 UcmaE%yH$6?E`iN&1%9&v04df6A^-pY diff --git a/mobile/openapi/lib/api/server_info_api.dart b/mobile/openapi/lib/api/server_info_api.dart index 8cc3460c9b6111a0274eddb843385241a4c81812..fb34e09ce866e5939102add22182e894f575b904 100644 GIT binary patch delta 172 zcmcbk*KV~zO^7=;H6=4qx1_QlwRp0Yko6>97NOFDg8ZVA)D&NkR0vomUnqeKp>lH$ z?;b`ygmh49aY24wajHv6zP+77dTL2979*C6sEJ~g+FZbI%ftycZSqDzNd#~6Il(?w E0C)^P`Tzg` delta 12 TcmZp-x}O=$B)aWhr`A%g^p diff --git a/mobile/openapi/lib/api_client.dart b/mobile/openapi/lib/api_client.dart index 824d4c9eb45553ba79e27c7d71bd237e443cc1a9..b2208df562e0c4d41d62ef850f0d753384da4730 100644 GIT binary patch delta 53 zcmbQ)&)7VHaYL>Nr*CRXW@1QXLF(j#3JLB=1&jay diff --git a/mobile/openapi/lib/model/server_media_types_response_dto.dart b/mobile/openapi/lib/model/server_media_types_response_dto.dart new file mode 100644 index 0000000000000000000000000000000000000000..2cba41363df82375a02e19abea667dfa74ae92f3 GIT binary patch literal 3726 zcmcInZExE)5dQ98aRq`}##DLhr@@`v7E3a;YhobDJ`9E-FfwhklO>I$V;E`v`|ggS zB*%`D6`KLuB6)AT=eZ*_9QKAo`1r@oIk|z0$?2!_ zKVP93Nq(3MZR5AmPj7oPRLi{3GFcQlS*T2oV3Ti*oF_7qYnj{7kJY*?v^}aJvaQ&e zq})#WBDaZ}qeHb&QnR`_>MT>aG)Y$EOBAy! zktaX@n4~MAO|OUUEEEeUN|}pNMfiQ!>!q162Ck*Pllnr=mAKiJ(p*VXqGNe#3%KtA z3^5m1(r$EaKtL|HFzry8f#RT38KG{6U_iD3>`IyF4mVgp47_2O&cbF%t;JFvUoxnb z3jJvDVSqaW_@a#c<=SeMFUP?452xAo;dEt}7d{l28;y?8N%Q+rXl zg{8Ex5@z*lF~}x*qI)h=X^hZ2qAN0RC5auI9MAgf@IsUoB|@0*un<)`Mwg#Wk)uP$ z$A!v8248Usd37Lt|M1R1#1d28XZQUX$~HuPB*HN@B0PK~Qia(F)v!^CXf8hXNO})M z@9!;25cwRFMIFn4!tb5PHqyXC7wgLGl&7$c7bwuDnxA6gW+CL84EaxF-zvl9-C|3r z{i8`*yAR;TElw|hheE;a$$OmFtUJyq=LfO{5-%O zdMpy9qHY8Y>Vaz#t?YJCEx@4NhtVEA#vX(Cgq>X6X4EB`&wB`nM=h3!Msm;&Y#a(yXBPpRB!abi89!Km93}pD=S?V~drP*YbdrXI) z>C8n;j3?_vcnS_r17=~Q%w=KE)}`Hf^H>CUIt7)NVvFZ7i#F@NOk4@YU6mM7U*J6= zEvxJ?>FNr66?0!`Tc?gin~TJJ?&`Fq>2mKe*h8YyIw%C6O18q?uY#%F&pYaO3~Nyy z1ypE3nyS#40W5nznlsbWGpWDgGsQbRx38<1fY0fjp|#C5RcoAssuM zu)^K3w#u$>ipq}eu^rgFaT;i#I^6JtM@_ohlVL3VBkXy$;F&`tb(BXhEqe6dX4vyy zzlUcpq|i&~SRFpChVm@iaEtpa=zuCBIO~MANEd>y`BD88)=YFn+G`!?wMC#I+^l5H z760Z1NK1p)G=V(WAdPM%;HAZ&TdE!bpRXsE^v+Vz!@Y}m<=;uSz7US@IWyJm&%Lem R-GN#S{3%95yfb3g`UkovvxWcw literal 0 HcmV?d00001 diff --git a/mobile/openapi/test/server_info_api_test.dart b/mobile/openapi/test/server_info_api_test.dart index b662587eef233d76fa5c2111d3eba13297441e24..4fee682a2552353d272a2b126ba67cdbd30acc6f 100644 GIT binary patch delta 84 zcmdnWeu86zAG5A+YD#8eNM%84aZqY;L4ICws!K_}okDtQNpNXFL4Hw5Y6?Qh63?) z`jAZ)zHff>eaZ7I&*AKQRero!-K=iUs#O8!mshJL6eZl06bU^WdGty$qv1w@+%ieBhrO_#Ed|p%+o>$B(VC-Are33jEZgk}GmrHHc697K zS@fLib1vNNRgD{(g(yfffubu;uh|c|9(fnu(frHGr2TURTgEM@U+|aHJ%6U c`W^V>|9^bY^fk&m7I>cUZ!2gQsfnlTFX6f$O#lD@ literal 0 HcmV?d00001 diff --git a/server/immich-openapi-specs.json b/server/immich-openapi-specs.json index c2c006744c..877ea38673 100644 --- a/server/immich-openapi-specs.json +++ b/server/immich-openapi-specs.json @@ -3040,6 +3040,27 @@ ] } }, + "/server-info/media-types": { + "get": { + "operationId": "getSupportedMediaTypes", + "parameters": [], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ServerMediaTypesResponseDto" + } + } + } + } + }, + "tags": [ + "Server Info" + ] + } + }, "/server-info/ping": { "get": { "operationId": "pingServer", @@ -6118,6 +6139,34 @@ "diskAvailable" ] }, + "ServerMediaTypesResponseDto": { + "type": "object", + "properties": { + "video": { + "type": "array", + "items": { + "type": "string" + } + }, + "image": { + "type": "array", + "items": { + "type": "string" + } + }, + "sidecar": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "video", + "image", + "sidecar" + ] + }, "ServerPingResponse": { "type": "object", "properties": { diff --git a/server/src/domain/server-info/response-dto/server-stats-response.dto.ts b/server/src/domain/server-info/response-dto/server-stats-response.dto.ts index ed7a071769..1459ba452a 100644 --- a/server/src/domain/server-info/response-dto/server-stats-response.dto.ts +++ b/server/src/domain/server-info/response-dto/server-stats-response.dto.ts @@ -25,3 +25,9 @@ export class ServerStatsResponseDto { }) usageByUser: UsageByUserDto[] = []; } + +export class ServerMediaTypesResponseDto { + video!: string[]; + image!: string[]; + sidecar!: string[]; +} diff --git a/server/src/domain/server-info/server-info.service.ts b/server/src/domain/server-info/server-info.service.ts index 9d36f1b66d..ceeb85e295 100644 --- a/server/src/domain/server-info/server-info.service.ts +++ b/server/src/domain/server-info/server-info.service.ts @@ -1,9 +1,15 @@ import { Inject, Injectable } from '@nestjs/common'; -import { serverVersion } from '../domain.constant'; +import { mimeTypes, serverVersion } from '../domain.constant'; import { asHumanReadable } from '../domain.util'; import { IStorageRepository, StorageCore, StorageFolder } from '../storage'; import { IUserRepository, UserStatsQueryResponse } from '../user'; -import { ServerInfoResponseDto, ServerPingResponse, ServerStatsResponseDto, UsageByUserDto } from './response-dto'; +import { + ServerInfoResponseDto, + ServerMediaTypesResponseDto, + ServerPingResponse, + ServerStatsResponseDto, + UsageByUserDto, +} from './response-dto'; @Injectable() export class ServerInfoService { @@ -60,4 +66,12 @@ export class ServerInfoService { return serverStats; } + + getSupportedMediaTypes(): ServerMediaTypesResponseDto { + return { + video: [...Object.keys(mimeTypes.video)], + image: [...Object.keys(mimeTypes.image)], + sidecar: [...Object.keys(mimeTypes.sidecar)], + }; + } } diff --git a/server/src/immich/controllers/server-info.controller.ts b/server/src/immich/controllers/server-info.controller.ts index e98485cbe8..59b6351787 100644 --- a/server/src/immich/controllers/server-info.controller.ts +++ b/server/src/immich/controllers/server-info.controller.ts @@ -1,6 +1,7 @@ import { ServerInfoResponseDto, ServerInfoService, + ServerMediaTypesResponseDto, ServerPingResponse, ServerStatsResponseDto, ServerVersionReponseDto, @@ -39,4 +40,10 @@ export class ServerInfoController { getStats(): Promise { return this.service.getStats(); } + + @PublicRoute() + @Get('/media-types') + getSupportedMediaTypes(): ServerMediaTypesResponseDto { + return this.service.getSupportedMediaTypes(); + } } diff --git a/web/src/api/open-api/api.ts b/web/src/api/open-api/api.ts index 66c717c814..414f7b147d 100644 --- a/web/src/api/open-api/api.ts +++ b/web/src/api/open-api/api.ts @@ -2085,6 +2085,31 @@ export interface ServerInfoResponseDto { */ 'diskAvailable': string; } +/** + * + * @export + * @interface ServerMediaTypesResponseDto + */ +export interface ServerMediaTypesResponseDto { + /** + * + * @type {Array} + * @memberof ServerMediaTypesResponseDto + */ + 'video': Array; + /** + * + * @type {Array} + * @memberof ServerMediaTypesResponseDto + */ + 'image': Array; + /** + * + * @type {Array} + * @memberof ServerMediaTypesResponseDto + */ + 'sidecar': Array; +} /** * * @export @@ -9771,6 +9796,35 @@ export const ServerInfoApiAxiosParamCreator = function (configuration?: Configur + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getSupportedMediaTypes: async (options: AxiosRequestConfig = {}): Promise => { + const localVarPath = `/server-info/media-types`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + + setSearchParams(localVarUrlObj, localVarQueryParameter); let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; @@ -9846,6 +9900,15 @@ export const ServerInfoApiFp = function(configuration?: Configuration) { const localVarAxiosArgs = await localVarAxiosParamCreator.getStats(options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, + /** + * + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async getSupportedMediaTypes(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.getSupportedMediaTypes(options); + return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + }, /** * * @param {*} [options] Override http request option. @@ -9889,6 +9952,14 @@ export const ServerInfoApiFactory = function (configuration?: Configuration, bas getStats(options?: any): AxiosPromise { return localVarFp.getStats(options).then((request) => request(axios, basePath)); }, + /** + * + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getSupportedMediaTypes(options?: any): AxiosPromise { + return localVarFp.getSupportedMediaTypes(options).then((request) => request(axios, basePath)); + }, /** * * @param {*} [options] Override http request option. @@ -9937,6 +10008,16 @@ export class ServerInfoApi extends BaseAPI { return ServerInfoApiFp(this.configuration).getStats(options).then((request) => request(this.axios, this.basePath)); } + /** + * + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ServerInfoApi + */ + public getSupportedMediaTypes(options?: AxiosRequestConfig) { + return ServerInfoApiFp(this.configuration).getSupportedMediaTypes(options).then((request) => request(this.axios, this.basePath)); + } + /** * * @param {*} [options] Override http request option.