diff --git a/mobile/lib/models/server_info/server_disk_info.model.dart b/mobile/lib/models/server_info/server_disk_info.model.dart index 95e94e369c..01ce49beec 100644 --- a/mobile/lib/models/server_info/server_disk_info.model.dart +++ b/mobile/lib/models/server_info/server_disk_info.model.dart @@ -32,7 +32,7 @@ class ServerDiskInfo { return 'ServerDiskInfo(diskAvailable: $diskAvailable, diskSize: $diskSize, diskUse: $diskUse, diskUsagePercentage: $diskUsagePercentage)'; } - ServerDiskInfo.fromDto(ServerInfoResponseDto dto) + ServerDiskInfo.fromDto(ServerStorageResponseDto dto) : diskAvailable = dto.diskAvailable, diskSize = dto.diskSize, diskUse = dto.diskUse, diff --git a/mobile/lib/providers/backup/backup.provider.dart b/mobile/lib/providers/backup/backup.provider.dart index ab869c2328..58027e3b94 100644 --- a/mobile/lib/providers/backup/backup.provider.dart +++ b/mobile/lib/providers/backup/backup.provider.dart @@ -374,7 +374,7 @@ class BackupNotifier extends StateNotifier { if (state.backupProgress != BackUpProgressEnum.inBackground) { await _getBackupAlbumsInfo(); - await updateServerInfo(); + await updateDiskInfo(); await _updateBackupAssetCount(); } else { log.warning("cannot get backup info - background backup is in progress!"); @@ -542,7 +542,7 @@ class BackupNotifier extends StateNotifier { _updatePersistentAlbumsSelection(); } - updateServerInfo(); + updateDiskInfo(); } void _onUploadProgress(int sent, int total) { @@ -579,13 +579,13 @@ class BackupNotifier extends StateNotifier { ); } - Future updateServerInfo() async { - final serverInfo = await _serverInfoService.getServerInfo(); + Future updateDiskInfo() async { + final diskInfo = await _serverInfoService.getDiskInfo(); // Update server info - if (serverInfo != null) { + if (diskInfo != null) { state = state.copyWith( - serverInfo: serverInfo, + serverInfo: diskInfo, ); } } diff --git a/mobile/lib/providers/backup/manual_upload.provider.dart b/mobile/lib/providers/backup/manual_upload.provider.dart index 1de7f7a788..b446711226 100644 --- a/mobile/lib/providers/backup/manual_upload.provider.dart +++ b/mobile/lib/providers/backup/manual_upload.provider.dart @@ -121,7 +121,7 @@ class ManualUploadNotifier extends StateNotifier { bool isDuplicated, ) { state = state.copyWith(successfulUploads: state.successfulUploads + 1); - _backupProvider.updateServerInfo(); + _backupProvider.updateDiskInfo(); } void _onAssetUploadError(ErrorUploadAsset errorAssetInfo) { diff --git a/mobile/lib/services/server_info.service.dart b/mobile/lib/services/server_info.service.dart index a2ce77c820..e2b7db2fce 100644 --- a/mobile/lib/services/server_info.service.dart +++ b/mobile/lib/services/server_info.service.dart @@ -18,14 +18,14 @@ class ServerInfoService { ServerInfoService(this._apiService); - Future getServerInfo() async { + Future getDiskInfo() async { try { - final dto = await _apiService.serverInfoApi.getServerInfo(); + final dto = await _apiService.serverInfoApi.getStorage(); if (dto != null) { return ServerDiskInfo.fromDto(dto); } } catch (e) { - debugPrint("Error [getServerInfo] ${e.toString()}"); + debugPrint("Error [getDiskInfo] ${e.toString()}"); } return null; } diff --git a/mobile/lib/widgets/common/app_bar_dialog/app_bar_dialog.dart b/mobile/lib/widgets/common/app_bar_dialog/app_bar_dialog.dart index 75d3966b97..fbcfd64713 100644 --- a/mobile/lib/widgets/common/app_bar_dialog/app_bar_dialog.dart +++ b/mobile/lib/widgets/common/app_bar_dialog/app_bar_dialog.dart @@ -31,7 +31,7 @@ class ImmichAppBarDialog extends HookConsumerWidget { useEffect( () { - ref.read(backupProvider.notifier).updateServerInfo(); + ref.read(backupProvider.notifier).updateDiskInfo(); ref.read(currentUserProvider.notifier).refresh(); return null; }, diff --git a/mobile/openapi/README.md b/mobile/openapi/README.md index 090182fc39..6055742602 100644 Binary files a/mobile/openapi/README.md and b/mobile/openapi/README.md differ diff --git a/mobile/openapi/lib/api.dart b/mobile/openapi/lib/api.dart index 8cd0f4365c..be7c4a936e 100644 Binary files a/mobile/openapi/lib/api.dart and b/mobile/openapi/lib/api.dart differ diff --git a/mobile/openapi/lib/api/deprecated_api.dart b/mobile/openapi/lib/api/deprecated_api.dart new file mode 100644 index 0000000000..117735015d Binary files /dev/null and b/mobile/openapi/lib/api/deprecated_api.dart differ diff --git a/mobile/openapi/lib/api/server_info_api.dart b/mobile/openapi/lib/api/server_info_api.dart index db72dd370d..6e55c62759 100644 Binary files a/mobile/openapi/lib/api/server_info_api.dart and b/mobile/openapi/lib/api/server_info_api.dart differ diff --git a/mobile/openapi/lib/api_client.dart b/mobile/openapi/lib/api_client.dart index 2bebf46b1c..3e2f2c15c6 100644 Binary files a/mobile/openapi/lib/api_client.dart and b/mobile/openapi/lib/api_client.dart differ diff --git a/mobile/openapi/lib/model/server_info_response_dto.dart b/mobile/openapi/lib/model/server_storage_response_dto.dart similarity index 71% rename from mobile/openapi/lib/model/server_info_response_dto.dart rename to mobile/openapi/lib/model/server_storage_response_dto.dart index 295e0f7e6a..ab0f169e4b 100644 Binary files a/mobile/openapi/lib/model/server_info_response_dto.dart and b/mobile/openapi/lib/model/server_storage_response_dto.dart differ diff --git a/open-api/immich-openapi-specs.json b/open-api/immich-openapi-specs.json index f2d30f1537..c6eff20a47 100644 --- a/open-api/immich-openapi-specs.json +++ b/open-api/immich-openapi-specs.json @@ -4337,6 +4337,8 @@ }, "/server-info": { "get": { + "deprecated": true, + "description": "This property was deprecated in v1.106.0", "operationId": "getServerInfo", "parameters": [], "responses": { @@ -4344,7 +4346,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ServerInfoResponseDto" + "$ref": "#/components/schemas/ServerStorageResponseDto" } } }, @@ -4363,8 +4365,12 @@ } ], "tags": [ - "Server Info" - ] + "Server Info", + "Deprecated" + ], + "x-immich-lifecycle": { + "deprecatedAt": "v1.106.0" + } } }, "/server-info/config": { @@ -4483,6 +4489,38 @@ ] } }, + "/server-info/storage": { + "get": { + "operationId": "getStorage", + "parameters": [], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ServerStorageResponseDto" + } + } + }, + "description": "" + } + }, + "security": [ + { + "bearer": [] + }, + { + "cookie": [] + }, + { + "api_key": [] + } + ], + "tags": [ + "Server Info" + ] + } + }, "/server-info/theme": { "get": { "operationId": "getTheme", @@ -9487,45 +9525,6 @@ ], "type": "object" }, - "ServerInfoResponseDto": { - "properties": { - "diskAvailable": { - "type": "string" - }, - "diskAvailableRaw": { - "format": "int64", - "type": "integer" - }, - "diskSize": { - "type": "string" - }, - "diskSizeRaw": { - "format": "int64", - "type": "integer" - }, - "diskUsagePercentage": { - "format": "float", - "type": "number" - }, - "diskUse": { - "type": "string" - }, - "diskUseRaw": { - "format": "int64", - "type": "integer" - } - }, - "required": [ - "diskAvailable", - "diskAvailableRaw", - "diskSize", - "diskSizeRaw", - "diskUsagePercentage", - "diskUse", - "diskUseRaw" - ], - "type": "object" - }, "ServerMediaTypesResponseDto": { "properties": { "image": { @@ -9606,6 +9605,45 @@ ], "type": "object" }, + "ServerStorageResponseDto": { + "properties": { + "diskAvailable": { + "type": "string" + }, + "diskAvailableRaw": { + "format": "int64", + "type": "integer" + }, + "diskSize": { + "type": "string" + }, + "diskSizeRaw": { + "format": "int64", + "type": "integer" + }, + "diskUsagePercentage": { + "format": "float", + "type": "number" + }, + "diskUse": { + "type": "string" + }, + "diskUseRaw": { + "format": "int64", + "type": "integer" + } + }, + "required": [ + "diskAvailable", + "diskAvailableRaw", + "diskSize", + "diskSizeRaw", + "diskUsagePercentage", + "diskUse", + "diskUseRaw" + ], + "type": "object" + }, "ServerThemeDto": { "properties": { "customCss": { diff --git a/open-api/typescript-sdk/src/fetch-client.ts b/open-api/typescript-sdk/src/fetch-client.ts index d3ab222d77..050dbfeb9a 100644 --- a/open-api/typescript-sdk/src/fetch-client.ts +++ b/open-api/typescript-sdk/src/fetch-client.ts @@ -732,7 +732,7 @@ export type SmartSearchDto = { withDeleted?: boolean; withExif?: boolean; }; -export type ServerInfoResponseDto = { +export type ServerStorageResponseDto = { diskAvailable: string; diskAvailableRaw: number; diskSize: string; @@ -2245,10 +2245,13 @@ export function getSearchSuggestions({ country, make, model, state, $type }: { ...opts })); } +/** + * This property was deprecated in v1.106.0 + */ export function getServerInfo(opts?: Oazapfts.RequestOpts) { return oazapfts.ok(oazapfts.fetchJson<{ status: 200; - data: ServerInfoResponseDto; + data: ServerStorageResponseDto; }>("/server-info", { ...opts })); @@ -2293,6 +2296,14 @@ export function getServerStatistics(opts?: Oazapfts.RequestOpts) { ...opts })); } +export function getStorage(opts?: Oazapfts.RequestOpts) { + return oazapfts.ok(oazapfts.fetchJson<{ + status: 200; + data: ServerStorageResponseDto; + }>("/server-info/storage", { + ...opts + })); +} export function getTheme(opts?: Oazapfts.RequestOpts) { return oazapfts.ok(oazapfts.fetchJson<{ status: 200; diff --git a/server/src/controllers/server-info.controller.ts b/server/src/controllers/server-info.controller.ts index 960acfe3fd..308778dbb5 100644 --- a/server/src/controllers/server-info.controller.ts +++ b/server/src/controllers/server-info.controller.ts @@ -1,12 +1,13 @@ import { Controller, Get } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; +import { EndpointLifecycle } from 'src/decorators'; import { ServerConfigDto, ServerFeaturesDto, - ServerInfoResponseDto, ServerMediaTypesResponseDto, ServerPingResponse, ServerStatsResponseDto, + ServerStorageResponseDto, ServerThemeDto, ServerVersionResponseDto, } from 'src/dtos/server-info.dto'; @@ -23,9 +24,16 @@ export class ServerInfoController { ) {} @Get() + @EndpointLifecycle({ deprecatedAt: 'v1.106.0' }) @Authenticated() - getServerInfo(): Promise { - return this.service.getInfo(); + getServerInfo(): Promise { + return this.service.getStorage(); + } + + @Get('storage') + @Authenticated() + getStorage(): Promise { + return this.service.getStorage(); } @Get('ping') diff --git a/server/src/dtos/server-info.dto.ts b/server/src/dtos/server-info.dto.ts index 1e91332c0d..6afe8534c7 100644 --- a/server/src/dtos/server-info.dto.ts +++ b/server/src/dtos/server-info.dto.ts @@ -7,7 +7,7 @@ export class ServerPingResponse { res!: string; } -export class ServerInfoResponseDto { +export class ServerStorageResponseDto { diskSize!: string; diskUse!: string; diskAvailable!: string; diff --git a/server/src/services/server-info.service.spec.ts b/server/src/services/server-info.service.spec.ts index 41f2e95e22..57beb165db 100644 --- a/server/src/services/server-info.service.spec.ts +++ b/server/src/services/server-info.service.spec.ts @@ -29,11 +29,11 @@ describe(ServerInfoService.name, () => { expect(sut).toBeDefined(); }); - describe('getInfo', () => { + describe('getStorage', () => { it('should return the disk space as B', async () => { storageMock.checkDiskUsage.mockResolvedValue({ free: 200, available: 300, total: 500 }); - await expect(sut.getInfo()).resolves.toEqual({ + await expect(sut.getStorage()).resolves.toEqual({ diskAvailable: '300 B', diskAvailableRaw: 300, diskSize: '500 B', @@ -49,7 +49,7 @@ describe(ServerInfoService.name, () => { it('should return the disk space as KiB', async () => { storageMock.checkDiskUsage.mockResolvedValue({ free: 200_000, available: 300_000, total: 500_000 }); - await expect(sut.getInfo()).resolves.toEqual({ + await expect(sut.getStorage()).resolves.toEqual({ diskAvailable: '293.0 KiB', diskAvailableRaw: 300_000, diskSize: '488.3 KiB', @@ -65,7 +65,7 @@ describe(ServerInfoService.name, () => { it('should return the disk space as MiB', async () => { storageMock.checkDiskUsage.mockResolvedValue({ free: 200_000_000, available: 300_000_000, total: 500_000_000 }); - await expect(sut.getInfo()).resolves.toEqual({ + await expect(sut.getStorage()).resolves.toEqual({ diskAvailable: '286.1 MiB', diskAvailableRaw: 300_000_000, diskSize: '476.8 MiB', @@ -85,7 +85,7 @@ describe(ServerInfoService.name, () => { total: 500_000_000_000, }); - await expect(sut.getInfo()).resolves.toEqual({ + await expect(sut.getStorage()).resolves.toEqual({ diskAvailable: '279.4 GiB', diskAvailableRaw: 300_000_000_000, diskSize: '465.7 GiB', @@ -105,7 +105,7 @@ describe(ServerInfoService.name, () => { total: 500_000_000_000_000, }); - await expect(sut.getInfo()).resolves.toEqual({ + await expect(sut.getStorage()).resolves.toEqual({ diskAvailable: '272.8 TiB', diskAvailableRaw: 300_000_000_000_000, diskSize: '454.7 TiB', @@ -125,7 +125,7 @@ describe(ServerInfoService.name, () => { total: 500_000_000_000_000_000, }); - await expect(sut.getInfo()).resolves.toEqual({ + await expect(sut.getStorage()).resolves.toEqual({ diskAvailable: '266.5 PiB', diskAvailableRaw: 300_000_000_000_000_000, diskSize: '444.1 PiB', diff --git a/server/src/services/server-info.service.ts b/server/src/services/server-info.service.ts index 9e27e9d7ac..89e095ba5d 100644 --- a/server/src/services/server-info.service.ts +++ b/server/src/services/server-info.service.ts @@ -4,10 +4,10 @@ import { SystemConfigCore } from 'src/cores/system-config.core'; import { ServerConfigDto, ServerFeaturesDto, - ServerInfoResponseDto, ServerMediaTypesResponseDto, ServerPingResponse, ServerStatsResponseDto, + ServerStorageResponseDto, UsageByUserDto, } from 'src/dtos/server-info.dto'; import { SystemMetadataKey } from 'src/entities/system-metadata.entity'; @@ -42,13 +42,13 @@ export class ServerInfoService { } } - async getInfo(): Promise { + async getStorage(): Promise { const libraryBase = StorageCore.getBaseFolder(StorageFolder.LIBRARY); const diskInfo = await this.storageRepository.checkDiskUsage(libraryBase); const usagePercentage = (((diskInfo.total - diskInfo.free) / diskInfo.total) * 100).toFixed(2); - const serverInfo = new ServerInfoResponseDto(); + const serverInfo = new ServerStorageResponseDto(); serverInfo.diskAvailable = asHumanReadable(diskInfo.available); serverInfo.diskSize = asHumanReadable(diskInfo.total); serverInfo.diskUse = asHumanReadable(diskInfo.total - diskInfo.free); diff --git a/web/src/lib/stores/server-info.store.ts b/web/src/lib/stores/server-info.store.ts index 817bbeca4a..360b2c5630 100644 --- a/web/src/lib/stores/server-info.store.ts +++ b/web/src/lib/stores/server-info.store.ts @@ -1,4 +1,4 @@ -import type { ServerInfoResponseDto } from '@immich/sdk'; +import type { ServerStorageResponseDto } from '@immich/sdk'; import { writable } from 'svelte/store'; -export const serverInfo = writable(); +export const serverInfo = writable(); diff --git a/web/src/lib/utils/auth.ts b/web/src/lib/utils/auth.ts index dc7bb53db1..1fbc158f74 100644 --- a/web/src/lib/utils/auth.ts +++ b/web/src/lib/utils/auth.ts @@ -1,7 +1,7 @@ import { browser } from '$app/environment'; import { serverInfo } from '$lib/stores/server-info.store'; import { user } from '$lib/stores/user.store'; -import { getMyUserInfo, getServerInfo } from '@immich/sdk'; +import { getMyUserInfo, getStorage } from '@immich/sdk'; import { redirect } from '@sveltejs/kit'; import { get } from 'svelte/store'; import { AppRoute } from '../constants'; @@ -58,7 +58,7 @@ export const authenticate = async (options?: AuthOptions) => { export const requestServerInfo = async () => { if (get(user)) { - const data = await getServerInfo(); + const data = await getStorage(); serverInfo.set(data); } };