chore!: remove deviceId and deviceAssetId (#27818)

chore: remove deviceId and deviceAssetId
This commit is contained in:
Daniel Dietzler 2026-04-15 21:00:33 +02:00 committed by GitHub
parent d410131312
commit 8ee5d3039a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
55 changed files with 31 additions and 1102 deletions

View File

@ -404,8 +404,6 @@ const uploadFile = async (input: string, stats: Stats): Promise<AssetMediaRespon
const { baseUrl, headers } = defaults;
const formData = new FormData();
formData.append('deviceAssetId', `${basename(input)}-${stats.size}`.replaceAll(/\s+/g, ''));
formData.append('deviceId', 'CLI');
formData.append('fileCreatedAt', stats.mtime.toISOString());
formData.append('fileModifiedAt', stats.mtime.toISOString());
formData.append('fileSize', String(stats.size));

View File

@ -20,8 +20,6 @@ def upload(file):
}
data = {
'deviceAssetId': f'{file}-{stats.st_mtime}',
'deviceId': 'python',
'fileCreatedAt': datetime.fromtimestamp(stats.st_mtime),
'fileModifiedAt': datetime.fromtimestamp(stats.st_mtime),
'isFavorite': 'false',

View File

@ -1091,8 +1091,6 @@ describe('/asset', () => {
const { body, status } = await request(app)
.post('/assets')
.set('Authorization', `Bearer ${quotaUser.accessToken}`)
.field('deviceAssetId', 'example-image')
.field('deviceId', 'e2e')
.field('fileCreatedAt', new Date().toISOString())
.field('fileModifiedAt', new Date().toISOString())
.attach('assetData', makeRandomImage(), 'example.jpg');
@ -1109,8 +1107,6 @@ describe('/asset', () => {
const { body, status } = await request(app)
.post('/assets')
.set('Authorization', `Bearer ${quotaUser.accessToken}`)
.field('deviceAssetId', 'example-image')
.field('deviceId', 'e2e')
.field('fileCreatedAt', new Date().toISOString())
.field('fileModifiedAt', new Date().toISOString())
.attach('assetData', randomBytes(2014), 'example.jpg');
@ -1164,29 +1160,4 @@ describe('/asset', () => {
expect(video.checksum).toStrictEqual(checksum);
});
});
describe('POST /assets/exist', () => {
it('ignores invalid deviceAssetIds', async () => {
const response = await utils.checkExistingAssets(user1.accessToken, {
deviceId: 'test-assets-exist',
deviceAssetIds: ['invalid', 'INVALID'],
});
expect(response.existingIds).toHaveLength(0);
});
it('returns the IDs of existing assets', async () => {
await utils.createAsset(user1.accessToken, {
deviceId: 'test-assets-exist',
deviceAssetId: 'test-asset-0',
});
const response = await utils.checkExistingAssets(user1.accessToken, {
deviceId: 'test-assets-exist',
deviceAssetIds: ['test-asset-0'],
});
expect(response.existingIds).toEqual(['test-asset-0']);
});
});
});

View File

@ -74,7 +74,6 @@ describe('/search', () => {
const bytes = await readFile(join(testAssetDir, filename));
assets.push(
await utils.createAsset(admin.accessToken, {
deviceAssetId: `test-${filename}`,
assetData: { bytes, filename },
...dto,
}),

View File

@ -16,8 +16,8 @@ test.describe('Duplicates Utility', () => {
test.beforeEach(async ({ context }) => {
[firstAsset, secondAsset] = await Promise.all([
utils.createAsset(admin.accessToken, { deviceAssetId: 'duplicate-a' }),
utils.createAsset(admin.accessToken, { deviceAssetId: 'duplicate-b' }),
utils.createAsset(admin.accessToken, {}),
utils.createAsset(admin.accessToken, {}),
]);
await updateAssets(

View File

@ -315,11 +315,9 @@ export function toAssetResponseDto(asset: MockTimelineAsset, owner?: UserRespons
return {
id: asset.id,
deviceAssetId: `device-${asset.id}`,
ownerId: asset.ownerId,
owner: owner || defaultOwner,
libraryId: `library-${asset.ownerId}`,
deviceId: `device-${asset.ownerId}`,
type: asset.isVideo ? AssetTypeEnum.Video : AssetTypeEnum.Image,
originalPath: `/original/${asset.id}.${asset.isVideo ? 'mp4' : 'jpg'}`,
originalFileName: `${asset.id}.${asset.isVideo ? 'mp4' : 'jpg'}`,

View File

@ -16,7 +16,6 @@ export const createMockStackAsset = (ownerId: string): AssetResponseDto => {
const now = new Date().toISOString();
return {
id: assetId,
deviceAssetId: `device-${assetId}`,
ownerId,
owner: {
id: ownerId,
@ -27,7 +26,6 @@ export const createMockStackAsset = (ownerId: string): AssetResponseDto => {
avatarColor: 'blue' as never,
},
libraryId: `library-${ownerId}`,
deviceId: `device-${ownerId}`,
type: AssetTypeEnum.Image,
originalPath: `/original/${assetId}.jpg`,
originalFileName: `${assetId}.jpg`,

View File

@ -3,7 +3,6 @@ import {
AssetMediaResponseDto,
AssetResponseDto,
AssetVisibility,
CheckExistingAssetsDto,
CreateAlbumDto,
CreateLibraryDto,
JobCreateDto,
@ -20,7 +19,6 @@ import {
UserAdminCreateDto,
UserPreferencesUpdateDto,
ValidateLibraryDto,
checkExistingAssets,
createAlbum,
createApiKey,
createJob,
@ -343,8 +341,6 @@ export const utils = {
},
) => {
const _dto = {
deviceAssetId: 'test-1',
deviceId: 'test',
fileCreatedAt: new Date().toISOString(),
fileModifiedAt: new Date().toISOString(),
...dto,
@ -416,9 +412,6 @@ export const utils = {
getAssetInfo: (accessToken: string, id: string) => getAssetInfo({ id }, { headers: asBearerAuth(accessToken) }),
checkExistingAssets: (accessToken: string, checkExistingAssetsDto: CheckExistingAssetsDto) =>
checkExistingAssets({ checkExistingAssetsDto }, { headers: asBearerAuth(accessToken) }),
searchAssets: async (accessToken: string, dto: MetadataSearchDto) => {
return searchAssets({ metadataSearchDto: dto }, { headers: asBearerAuth(accessToken) });
},

View File

@ -96,14 +96,12 @@ Class | Method | HTTP request | Description
*AlbumsApi* | [**updateAlbumInfo**](doc//AlbumsApi.md#updatealbuminfo) | **PATCH** /albums/{id} | Update an album
*AlbumsApi* | [**updateAlbumUser**](doc//AlbumsApi.md#updatealbumuser) | **PUT** /albums/{id}/user/{userId} | Update user role
*AssetsApi* | [**checkBulkUpload**](doc//AssetsApi.md#checkbulkupload) | **POST** /assets/bulk-upload-check | Check bulk upload
*AssetsApi* | [**checkExistingAssets**](doc//AssetsApi.md#checkexistingassets) | **POST** /assets/exist | Check existing assets
*AssetsApi* | [**copyAsset**](doc//AssetsApi.md#copyasset) | **PUT** /assets/copy | Copy asset
*AssetsApi* | [**deleteAssetMetadata**](doc//AssetsApi.md#deleteassetmetadata) | **DELETE** /assets/{id}/metadata/{key} | Delete asset metadata by key
*AssetsApi* | [**deleteAssets**](doc//AssetsApi.md#deleteassets) | **DELETE** /assets | Delete assets
*AssetsApi* | [**deleteBulkAssetMetadata**](doc//AssetsApi.md#deletebulkassetmetadata) | **DELETE** /assets/metadata | Delete asset metadata
*AssetsApi* | [**downloadAsset**](doc//AssetsApi.md#downloadasset) | **GET** /assets/{id}/original | Download original asset
*AssetsApi* | [**editAsset**](doc//AssetsApi.md#editasset) | **PUT** /assets/{id}/edits | Apply edits to an existing asset
*AssetsApi* | [**getAllUserAssetsByDeviceId**](doc//AssetsApi.md#getalluserassetsbydeviceid) | **GET** /assets/device/{deviceId} | Retrieve assets by device ID
*AssetsApi* | [**getAssetEdits**](doc//AssetsApi.md#getassetedits) | **GET** /assets/{id}/edits | Retrieve edits for an existing asset
*AssetsApi* | [**getAssetInfo**](doc//AssetsApi.md#getassetinfo) | **GET** /assets/{id} | Retrieve an asset
*AssetsApi* | [**getAssetMetadata**](doc//AssetsApi.md#getassetmetadata) | **GET** /assets/{id}/metadata | Get asset metadata
@ -142,7 +140,6 @@ Class | Method | HTTP request | Description
*DatabaseBackupsAdminApi* | [**startDatabaseRestoreFlow**](doc//DatabaseBackupsAdminApi.md#startdatabaserestoreflow) | **POST** /admin/database-backups/start-restore | Start database backup restore flow
*DatabaseBackupsAdminApi* | [**uploadDatabaseBackup**](doc//DatabaseBackupsAdminApi.md#uploaddatabasebackup) | **POST** /admin/database-backups/upload | Upload database backup
*DeprecatedApi* | [**createPartnerDeprecated**](doc//DeprecatedApi.md#createpartnerdeprecated) | **POST** /partners/{id} | Create a partner
*DeprecatedApi* | [**getAllUserAssetsByDeviceId**](doc//DeprecatedApi.md#getalluserassetsbydeviceid) | **GET** /assets/device/{deviceId} | Retrieve assets by device ID
*DeprecatedApi* | [**getQueuesLegacy**](doc//DeprecatedApi.md#getqueueslegacy) | **GET** /jobs | Retrieve queue counts and status
*DeprecatedApi* | [**runQueueCommandLegacy**](doc//DeprecatedApi.md#runqueuecommandlegacy) | **PUT** /jobs/{name} | Run jobs
*DownloadApi* | [**downloadArchive**](doc//DownloadApi.md#downloadarchive) | **POST** /download/archive | Download asset archive
@ -396,8 +393,6 @@ Class | Method | HTTP request | Description
- [CastResponse](doc//CastResponse.md)
- [CastUpdate](doc//CastUpdate.md)
- [ChangePasswordDto](doc//ChangePasswordDto.md)
- [CheckExistingAssetsDto](doc//CheckExistingAssetsDto.md)
- [CheckExistingAssetsResponseDto](doc//CheckExistingAssetsResponseDto.md)
- [Colorspace](doc//Colorspace.md)
- [ContributorCountResponseDto](doc//ContributorCountResponseDto.md)
- [CreateAlbumDto](doc//CreateAlbumDto.md)

View File

@ -142,8 +142,6 @@ part 'model/cq_mode.dart';
part 'model/cast_response.dart';
part 'model/cast_update.dart';
part 'model/change_password_dto.dart';
part 'model/check_existing_assets_dto.dart';
part 'model/check_existing_assets_response_dto.dart';
part 'model/colorspace.dart';
part 'model/contributor_count_response_dto.dart';
part 'model/create_album_dto.dart';

View File

@ -72,62 +72,6 @@ class AssetsApi {
return null;
}
/// Check existing assets
///
/// Checks if multiple assets exist on the server and returns all existing - used by background backup
///
/// Note: This method returns the HTTP [Response].
///
/// Parameters:
///
/// * [CheckExistingAssetsDto] checkExistingAssetsDto (required):
Future<Response> checkExistingAssetsWithHttpInfo(CheckExistingAssetsDto checkExistingAssetsDto,) async {
// ignore: prefer_const_declarations
final apiPath = r'/assets/exist';
// ignore: prefer_final_locals
Object? postBody = checkExistingAssetsDto;
final queryParams = <QueryParam>[];
final headerParams = <String, String>{};
final formParams = <String, String>{};
const contentTypes = <String>['application/json'];
return apiClient.invokeAPI(
apiPath,
'POST',
queryParams,
postBody,
headerParams,
formParams,
contentTypes.isEmpty ? null : contentTypes.first,
);
}
/// Check existing assets
///
/// Checks if multiple assets exist on the server and returns all existing - used by background backup
///
/// Parameters:
///
/// * [CheckExistingAssetsDto] checkExistingAssetsDto (required):
Future<CheckExistingAssetsResponseDto?> checkExistingAssets(CheckExistingAssetsDto checkExistingAssetsDto,) async {
final response = await checkExistingAssetsWithHttpInfo(checkExistingAssetsDto,);
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), 'CheckExistingAssetsResponseDto',) as CheckExistingAssetsResponseDto;
}
return null;
}
/// Copy asset
///
/// Copy asset information like albums, tags, etc. from one asset to another.
@ -472,68 +416,6 @@ class AssetsApi {
return null;
}
/// Retrieve assets by device ID
///
/// Get all asset of a device that are in the database, ID only.
///
/// Note: This method returns the HTTP [Response].
///
/// Parameters:
///
/// * [String] deviceId (required):
/// Device ID
Future<Response> getAllUserAssetsByDeviceIdWithHttpInfo(String deviceId,) async {
// ignore: prefer_const_declarations
final apiPath = r'/assets/device/{deviceId}'
.replaceAll('{deviceId}', deviceId);
// ignore: prefer_final_locals
Object? postBody;
final queryParams = <QueryParam>[];
final headerParams = <String, String>{};
final formParams = <String, String>{};
const contentTypes = <String>[];
return apiClient.invokeAPI(
apiPath,
'GET',
queryParams,
postBody,
headerParams,
formParams,
contentTypes.isEmpty ? null : contentTypes.first,
);
}
/// Retrieve assets by device ID
///
/// Get all asset of a device that are in the database, ID only.
///
/// Parameters:
///
/// * [String] deviceId (required):
/// Device ID
Future<List<String>?> getAllUserAssetsByDeviceId(String deviceId,) async {
final response = await getAllUserAssetsByDeviceIdWithHttpInfo(deviceId,);
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<String>') as List)
.cast<String>()
.toList(growable: false);
}
return null;
}
/// Retrieve edits for an existing asset
///
/// Retrieve a series of edit actions (crop, rotate, mirror) associated with the specified asset.
@ -1339,12 +1221,6 @@ class AssetsApi {
/// * [MultipartFile] assetData (required):
/// Asset file data
///
/// * [String] deviceAssetId (required):
/// Device asset ID
///
/// * [String] deviceId (required):
/// Device ID
///
/// * [DateTime] fileCreatedAt (required):
/// File creation date
///
@ -1377,7 +1253,7 @@ class AssetsApi {
/// Sidecar file data
///
/// * [AssetVisibility] visibility:
Future<Response> uploadAssetWithHttpInfo(MultipartFile assetData, String deviceAssetId, String deviceId, DateTime fileCreatedAt, DateTime fileModifiedAt, { String? key, String? slug, String? xImmichChecksum, String? duration, String? filename, bool? isFavorite, String? livePhotoVideoId, List<AssetMetadataUpsertItemDto>? metadata, MultipartFile? sidecarData, AssetVisibility? visibility, }) async {
Future<Response> uploadAssetWithHttpInfo(MultipartFile assetData, DateTime fileCreatedAt, DateTime fileModifiedAt, { String? key, String? slug, String? xImmichChecksum, String? duration, String? filename, bool? isFavorite, String? livePhotoVideoId, List<AssetMetadataUpsertItemDto>? metadata, MultipartFile? sidecarData, AssetVisibility? visibility, }) async {
// ignore: prefer_const_declarations
final apiPath = r'/assets';
@ -1408,14 +1284,6 @@ class AssetsApi {
mp.fields[r'assetData'] = assetData.field;
mp.files.add(assetData);
}
if (deviceAssetId != null) {
hasFields = true;
mp.fields[r'deviceAssetId'] = parameterToString(deviceAssetId);
}
if (deviceId != null) {
hasFields = true;
mp.fields[r'deviceId'] = parameterToString(deviceId);
}
if (duration != null) {
hasFields = true;
mp.fields[r'duration'] = parameterToString(duration);
@ -1477,12 +1345,6 @@ class AssetsApi {
/// * [MultipartFile] assetData (required):
/// Asset file data
///
/// * [String] deviceAssetId (required):
/// Device asset ID
///
/// * [String] deviceId (required):
/// Device ID
///
/// * [DateTime] fileCreatedAt (required):
/// File creation date
///
@ -1515,8 +1377,8 @@ class AssetsApi {
/// Sidecar file data
///
/// * [AssetVisibility] visibility:
Future<AssetMediaResponseDto?> uploadAsset(MultipartFile assetData, String deviceAssetId, String deviceId, DateTime fileCreatedAt, DateTime fileModifiedAt, { String? key, String? slug, String? xImmichChecksum, String? duration, String? filename, bool? isFavorite, String? livePhotoVideoId, List<AssetMetadataUpsertItemDto>? metadata, MultipartFile? sidecarData, AssetVisibility? visibility, }) async {
final response = await uploadAssetWithHttpInfo(assetData, deviceAssetId, deviceId, fileCreatedAt, fileModifiedAt, key: key, slug: slug, xImmichChecksum: xImmichChecksum, duration: duration, filename: filename, isFavorite: isFavorite, livePhotoVideoId: livePhotoVideoId, metadata: metadata, sidecarData: sidecarData, visibility: visibility, );
Future<AssetMediaResponseDto?> uploadAsset(MultipartFile assetData, DateTime fileCreatedAt, DateTime fileModifiedAt, { String? key, String? slug, String? xImmichChecksum, String? duration, String? filename, bool? isFavorite, String? livePhotoVideoId, List<AssetMetadataUpsertItemDto>? metadata, MultipartFile? sidecarData, AssetVisibility? visibility, }) async {
final response = await uploadAssetWithHttpInfo(assetData, fileCreatedAt, fileModifiedAt, key: key, slug: slug, xImmichChecksum: xImmichChecksum, duration: duration, filename: filename, isFavorite: isFavorite, livePhotoVideoId: livePhotoVideoId, metadata: metadata, sidecarData: sidecarData, visibility: visibility, );
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}

View File

@ -73,68 +73,6 @@ class DeprecatedApi {
return null;
}
/// Retrieve assets by device ID
///
/// Get all asset of a device that are in the database, ID only.
///
/// Note: This method returns the HTTP [Response].
///
/// Parameters:
///
/// * [String] deviceId (required):
/// Device ID
Future<Response> getAllUserAssetsByDeviceIdWithHttpInfo(String deviceId,) async {
// ignore: prefer_const_declarations
final apiPath = r'/assets/device/{deviceId}'
.replaceAll('{deviceId}', deviceId);
// ignore: prefer_final_locals
Object? postBody;
final queryParams = <QueryParam>[];
final headerParams = <String, String>{};
final formParams = <String, String>{};
const contentTypes = <String>[];
return apiClient.invokeAPI(
apiPath,
'GET',
queryParams,
postBody,
headerParams,
formParams,
contentTypes.isEmpty ? null : contentTypes.first,
);
}
/// Retrieve assets by device ID
///
/// Get all asset of a device that are in the database, ID only.
///
/// Parameters:
///
/// * [String] deviceId (required):
/// Device ID
Future<List<String>?> getAllUserAssetsByDeviceId(String deviceId,) async {
final response = await getAllUserAssetsByDeviceIdWithHttpInfo(deviceId,);
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<String>') as List)
.cast<String>()
.toList(growable: false);
}
return null;
}
/// Retrieve queue counts and status
///
/// Retrieve the counts of the current queue, as well as the current status.

View File

@ -368,9 +368,6 @@ class SearchApi {
/// * [DateTime] createdBefore:
/// Filter by creation date (before)
///
/// * [String] deviceId:
/// Device ID to filter by
///
/// * [bool] isEncoded:
/// Filter by encoded status
///
@ -446,7 +443,7 @@ class SearchApi {
///
/// * [bool] withExif:
/// Include EXIF data in response
Future<Response> searchLargeAssetsWithHttpInfo({ List<String>? albumIds, String? city, String? country, DateTime? createdAfter, DateTime? createdBefore, String? deviceId, bool? isEncoded, bool? isFavorite, bool? isMotion, bool? isNotInAlbum, bool? isOffline, String? lensModel, String? libraryId, String? make, int? minFileSize, String? model, String? ocr, List<String>? personIds, num? rating, num? size, String? state, List<String>? tagIds, DateTime? takenAfter, DateTime? takenBefore, DateTime? trashedAfter, DateTime? trashedBefore, AssetTypeEnum? type, DateTime? updatedAfter, DateTime? updatedBefore, AssetVisibility? visibility, bool? withDeleted, bool? withExif, }) async {
Future<Response> searchLargeAssetsWithHttpInfo({ List<String>? albumIds, String? city, String? country, DateTime? createdAfter, DateTime? createdBefore, bool? isEncoded, bool? isFavorite, bool? isMotion, bool? isNotInAlbum, bool? isOffline, String? lensModel, String? libraryId, String? make, int? minFileSize, String? model, String? ocr, List<String>? personIds, num? rating, num? size, String? state, List<String>? tagIds, DateTime? takenAfter, DateTime? takenBefore, DateTime? trashedAfter, DateTime? trashedBefore, AssetTypeEnum? type, DateTime? updatedAfter, DateTime? updatedBefore, AssetVisibility? visibility, bool? withDeleted, bool? withExif, }) async {
// ignore: prefer_const_declarations
final apiPath = r'/search/large-assets';
@ -472,9 +469,6 @@ class SearchApi {
if (createdBefore != null) {
queryParams.addAll(_queryParams('', 'createdBefore', createdBefore));
}
if (deviceId != null) {
queryParams.addAll(_queryParams('', 'deviceId', deviceId));
}
if (isEncoded != null) {
queryParams.addAll(_queryParams('', 'isEncoded', isEncoded));
}
@ -589,9 +583,6 @@ class SearchApi {
/// * [DateTime] createdBefore:
/// Filter by creation date (before)
///
/// * [String] deviceId:
/// Device ID to filter by
///
/// * [bool] isEncoded:
/// Filter by encoded status
///
@ -667,8 +658,8 @@ class SearchApi {
///
/// * [bool] withExif:
/// Include EXIF data in response
Future<List<AssetResponseDto>?> searchLargeAssets({ List<String>? albumIds, String? city, String? country, DateTime? createdAfter, DateTime? createdBefore, String? deviceId, bool? isEncoded, bool? isFavorite, bool? isMotion, bool? isNotInAlbum, bool? isOffline, String? lensModel, String? libraryId, String? make, int? minFileSize, String? model, String? ocr, List<String>? personIds, num? rating, num? size, String? state, List<String>? tagIds, DateTime? takenAfter, DateTime? takenBefore, DateTime? trashedAfter, DateTime? trashedBefore, AssetTypeEnum? type, DateTime? updatedAfter, DateTime? updatedBefore, AssetVisibility? visibility, bool? withDeleted, bool? withExif, }) async {
final response = await searchLargeAssetsWithHttpInfo( albumIds: albumIds, city: city, country: country, createdAfter: createdAfter, createdBefore: createdBefore, deviceId: deviceId, isEncoded: isEncoded, isFavorite: isFavorite, isMotion: isMotion, isNotInAlbum: isNotInAlbum, isOffline: isOffline, lensModel: lensModel, libraryId: libraryId, make: make, minFileSize: minFileSize, model: model, ocr: ocr, personIds: personIds, rating: rating, size: size, state: state, tagIds: tagIds, takenAfter: takenAfter, takenBefore: takenBefore, trashedAfter: trashedAfter, trashedBefore: trashedBefore, type: type, updatedAfter: updatedAfter, updatedBefore: updatedBefore, visibility: visibility, withDeleted: withDeleted, withExif: withExif, );
Future<List<AssetResponseDto>?> searchLargeAssets({ List<String>? albumIds, String? city, String? country, DateTime? createdAfter, DateTime? createdBefore, bool? isEncoded, bool? isFavorite, bool? isMotion, bool? isNotInAlbum, bool? isOffline, String? lensModel, String? libraryId, String? make, int? minFileSize, String? model, String? ocr, List<String>? personIds, num? rating, num? size, String? state, List<String>? tagIds, DateTime? takenAfter, DateTime? takenBefore, DateTime? trashedAfter, DateTime? trashedBefore, AssetTypeEnum? type, DateTime? updatedAfter, DateTime? updatedBefore, AssetVisibility? visibility, bool? withDeleted, bool? withExif, }) async {
final response = await searchLargeAssetsWithHttpInfo( albumIds: albumIds, city: city, country: country, createdAfter: createdAfter, createdBefore: createdBefore, isEncoded: isEncoded, isFavorite: isFavorite, isMotion: isMotion, isNotInAlbum: isNotInAlbum, isOffline: isOffline, lensModel: lensModel, libraryId: libraryId, make: make, minFileSize: minFileSize, model: model, ocr: ocr, personIds: personIds, rating: rating, size: size, state: state, tagIds: tagIds, takenAfter: takenAfter, takenBefore: takenBefore, trashedAfter: trashedAfter, trashedBefore: trashedBefore, type: type, updatedAfter: updatedAfter, updatedBefore: updatedBefore, visibility: visibility, withDeleted: withDeleted, withExif: withExif, );
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}

View File

@ -330,10 +330,6 @@ class ApiClient {
return CastUpdate.fromJson(value);
case 'ChangePasswordDto':
return ChangePasswordDto.fromJson(value);
case 'CheckExistingAssetsDto':
return CheckExistingAssetsDto.fromJson(value);
case 'CheckExistingAssetsResponseDto':
return CheckExistingAssetsResponseDto.fromJson(value);
case 'Colorspace':
return ColorspaceTypeTransformer().decode(value);
case 'ContributorCountResponseDto':

View File

@ -15,8 +15,6 @@ class AssetResponseDto {
AssetResponseDto({
required this.checksum,
required this.createdAt,
required this.deviceAssetId,
required this.deviceId,
this.duplicateId,
required this.duration,
this.exifInfo,
@ -56,12 +54,6 @@ class AssetResponseDto {
/// The UTC timestamp when the asset was originally uploaded to Immich.
DateTime createdAt;
/// Device asset ID
String deviceAssetId;
/// Device ID
String deviceId;
/// Duplicate group ID
String? duplicateId;
@ -179,8 +171,6 @@ class AssetResponseDto {
bool operator ==(Object other) => identical(this, other) || other is AssetResponseDto &&
other.checksum == checksum &&
other.createdAt == createdAt &&
other.deviceAssetId == deviceAssetId &&
other.deviceId == deviceId &&
other.duplicateId == duplicateId &&
other.duration == duration &&
other.exifInfo == exifInfo &&
@ -218,8 +208,6 @@ class AssetResponseDto {
// ignore: unnecessary_parenthesis
(checksum.hashCode) +
(createdAt.hashCode) +
(deviceAssetId.hashCode) +
(deviceId.hashCode) +
(duplicateId == null ? 0 : duplicateId!.hashCode) +
(duration.hashCode) +
(exifInfo == null ? 0 : exifInfo!.hashCode) +
@ -253,14 +241,12 @@ class AssetResponseDto {
(width == null ? 0 : width!.hashCode);
@override
String toString() => 'AssetResponseDto[checksum=$checksum, createdAt=$createdAt, deviceAssetId=$deviceAssetId, deviceId=$deviceId, duplicateId=$duplicateId, duration=$duration, exifInfo=$exifInfo, fileCreatedAt=$fileCreatedAt, fileModifiedAt=$fileModifiedAt, hasMetadata=$hasMetadata, height=$height, id=$id, isArchived=$isArchived, isEdited=$isEdited, isFavorite=$isFavorite, isOffline=$isOffline, isTrashed=$isTrashed, libraryId=$libraryId, livePhotoVideoId=$livePhotoVideoId, localDateTime=$localDateTime, originalFileName=$originalFileName, originalMimeType=$originalMimeType, originalPath=$originalPath, owner=$owner, ownerId=$ownerId, people=$people, resized=$resized, stack=$stack, tags=$tags, thumbhash=$thumbhash, type=$type, unassignedFaces=$unassignedFaces, updatedAt=$updatedAt, visibility=$visibility, width=$width]';
String toString() => 'AssetResponseDto[checksum=$checksum, createdAt=$createdAt, duplicateId=$duplicateId, duration=$duration, exifInfo=$exifInfo, fileCreatedAt=$fileCreatedAt, fileModifiedAt=$fileModifiedAt, hasMetadata=$hasMetadata, height=$height, id=$id, isArchived=$isArchived, isEdited=$isEdited, isFavorite=$isFavorite, isOffline=$isOffline, isTrashed=$isTrashed, libraryId=$libraryId, livePhotoVideoId=$livePhotoVideoId, localDateTime=$localDateTime, originalFileName=$originalFileName, originalMimeType=$originalMimeType, originalPath=$originalPath, owner=$owner, ownerId=$ownerId, people=$people, resized=$resized, stack=$stack, tags=$tags, thumbhash=$thumbhash, type=$type, unassignedFaces=$unassignedFaces, updatedAt=$updatedAt, visibility=$visibility, width=$width]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
json[r'checksum'] = this.checksum;
json[r'createdAt'] = this.createdAt.toUtc().toIso8601String();
json[r'deviceAssetId'] = this.deviceAssetId;
json[r'deviceId'] = this.deviceId;
if (this.duplicateId != null) {
json[r'duplicateId'] = this.duplicateId;
} else {
@ -350,8 +336,6 @@ class AssetResponseDto {
return AssetResponseDto(
checksum: mapValueOfType<String>(json, r'checksum')!,
createdAt: mapDateTime(json, r'createdAt', r'')!,
deviceAssetId: mapValueOfType<String>(json, r'deviceAssetId')!,
deviceId: mapValueOfType<String>(json, r'deviceId')!,
duplicateId: mapValueOfType<String>(json, r'duplicateId'),
duration: mapValueOfType<String>(json, r'duration')!,
exifInfo: ExifResponseDto.fromJson(json[r'exifInfo']),
@ -436,8 +420,6 @@ class AssetResponseDto {
static const requiredKeys = <String>{
'checksum',
'createdAt',
'deviceAssetId',
'deviceId',
'duration',
'fileCreatedAt',
'fileModifiedAt',

View File

@ -1,111 +0,0 @@
//
// AUTO-GENERATED FILE, DO NOT MODIFY!
//
// @dart=2.18
// 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 CheckExistingAssetsDto {
/// Returns a new [CheckExistingAssetsDto] instance.
CheckExistingAssetsDto({
this.deviceAssetIds = const [],
required this.deviceId,
});
/// Device asset IDs to check
List<String> deviceAssetIds;
/// Device ID
String deviceId;
@override
bool operator ==(Object other) => identical(this, other) || other is CheckExistingAssetsDto &&
_deepEquality.equals(other.deviceAssetIds, deviceAssetIds) &&
other.deviceId == deviceId;
@override
int get hashCode =>
// ignore: unnecessary_parenthesis
(deviceAssetIds.hashCode) +
(deviceId.hashCode);
@override
String toString() => 'CheckExistingAssetsDto[deviceAssetIds=$deviceAssetIds, deviceId=$deviceId]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
json[r'deviceAssetIds'] = this.deviceAssetIds;
json[r'deviceId'] = this.deviceId;
return json;
}
/// Returns a new [CheckExistingAssetsDto] instance and imports its values from
/// [value] if it's a [Map], null otherwise.
// ignore: prefer_constructors_over_static_methods
static CheckExistingAssetsDto? fromJson(dynamic value) {
upgradeDto(value, "CheckExistingAssetsDto");
if (value is Map) {
final json = value.cast<String, dynamic>();
return CheckExistingAssetsDto(
deviceAssetIds: json[r'deviceAssetIds'] is Iterable
? (json[r'deviceAssetIds'] as Iterable).cast<String>().toList(growable: false)
: const [],
deviceId: mapValueOfType<String>(json, r'deviceId')!,
);
}
return null;
}
static List<CheckExistingAssetsDto> listFromJson(dynamic json, {bool growable = false,}) {
final result = <CheckExistingAssetsDto>[];
if (json is List && json.isNotEmpty) {
for (final row in json) {
final value = CheckExistingAssetsDto.fromJson(row);
if (value != null) {
result.add(value);
}
}
}
return result.toList(growable: growable);
}
static Map<String, CheckExistingAssetsDto> mapFromJson(dynamic json) {
final map = <String, CheckExistingAssetsDto>{};
if (json is Map && json.isNotEmpty) {
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
for (final entry in json.entries) {
final value = CheckExistingAssetsDto.fromJson(entry.value);
if (value != null) {
map[entry.key] = value;
}
}
}
return map;
}
// maps a json object with a list of CheckExistingAssetsDto-objects as value to a dart map
static Map<String, List<CheckExistingAssetsDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
final map = <String, List<CheckExistingAssetsDto>>{};
if (json is Map && json.isNotEmpty) {
// ignore: parameter_assignments
json = json.cast<String, dynamic>();
for (final entry in json.entries) {
map[entry.key] = CheckExistingAssetsDto.listFromJson(entry.value, growable: growable,);
}
}
return map;
}
/// The list of required keys that must be present in a JSON.
static const requiredKeys = <String>{
'deviceAssetIds',
'deviceId',
};
}

View File

@ -1,102 +0,0 @@
//
// AUTO-GENERATED FILE, DO NOT MODIFY!
//
// @dart=2.18
// 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 CheckExistingAssetsResponseDto {
/// Returns a new [CheckExistingAssetsResponseDto] instance.
CheckExistingAssetsResponseDto({
this.existingIds = const [],
});
/// Existing asset IDs
List<String> existingIds;
@override
bool operator ==(Object other) => identical(this, other) || other is CheckExistingAssetsResponseDto &&
_deepEquality.equals(other.existingIds, existingIds);
@override
int get hashCode =>
// ignore: unnecessary_parenthesis
(existingIds.hashCode);
@override
String toString() => 'CheckExistingAssetsResponseDto[existingIds=$existingIds]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
json[r'existingIds'] = this.existingIds;
return json;
}
/// Returns a new [CheckExistingAssetsResponseDto] instance and imports its values from
/// [value] if it's a [Map], null otherwise.
// ignore: prefer_constructors_over_static_methods
static CheckExistingAssetsResponseDto? fromJson(dynamic value) {
upgradeDto(value, "CheckExistingAssetsResponseDto");
if (value is Map) {
final json = value.cast<String, dynamic>();
return CheckExistingAssetsResponseDto(
existingIds: json[r'existingIds'] is Iterable
? (json[r'existingIds'] as Iterable).cast<String>().toList(growable: false)
: const [],
);
}
return null;
}
static List<CheckExistingAssetsResponseDto> listFromJson(dynamic json, {bool growable = false,}) {
final result = <CheckExistingAssetsResponseDto>[];
if (json is List && json.isNotEmpty) {
for (final row in json) {
final value = CheckExistingAssetsResponseDto.fromJson(row);
if (value != null) {
result.add(value);
}
}
}
return result.toList(growable: growable);
}
static Map<String, CheckExistingAssetsResponseDto> mapFromJson(dynamic json) {
final map = <String, CheckExistingAssetsResponseDto>{};
if (json is Map && json.isNotEmpty) {
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
for (final entry in json.entries) {
final value = CheckExistingAssetsResponseDto.fromJson(entry.value);
if (value != null) {
map[entry.key] = value;
}
}
}
return map;
}
// maps a json object with a list of CheckExistingAssetsResponseDto-objects as value to a dart map
static Map<String, List<CheckExistingAssetsResponseDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
final map = <String, List<CheckExistingAssetsResponseDto>>{};
if (json is Map && json.isNotEmpty) {
// ignore: parameter_assignments
json = json.cast<String, dynamic>();
for (final entry in json.entries) {
map[entry.key] = CheckExistingAssetsResponseDto.listFromJson(entry.value, growable: growable,);
}
}
return map;
}
/// The list of required keys that must be present in a JSON.
static const requiredKeys = <String>{
'existingIds',
};
}

View File

@ -20,8 +20,6 @@ class MetadataSearchDto {
this.createdAfter,
this.createdBefore,
this.description,
this.deviceAssetId,
this.deviceId,
this.encodedVideoPath,
this.id,
this.isEncoded,
@ -104,24 +102,6 @@ class MetadataSearchDto {
///
String? description;
/// Filter by device asset ID
///
/// 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? deviceAssetId;
/// Device ID to filter by
///
/// 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? deviceId;
/// Filter by encoded video file path
///
/// Please note: This property should have been non-nullable! Since the specification file
@ -403,8 +383,6 @@ class MetadataSearchDto {
other.createdAfter == createdAfter &&
other.createdBefore == createdBefore &&
other.description == description &&
other.deviceAssetId == deviceAssetId &&
other.deviceId == deviceId &&
other.encodedVideoPath == encodedVideoPath &&
other.id == id &&
other.isEncoded == isEncoded &&
@ -451,8 +429,6 @@ class MetadataSearchDto {
(createdAfter == null ? 0 : createdAfter!.hashCode) +
(createdBefore == null ? 0 : createdBefore!.hashCode) +
(description == null ? 0 : description!.hashCode) +
(deviceAssetId == null ? 0 : deviceAssetId!.hashCode) +
(deviceId == null ? 0 : deviceId!.hashCode) +
(encodedVideoPath == null ? 0 : encodedVideoPath!.hashCode) +
(id == null ? 0 : id!.hashCode) +
(isEncoded == null ? 0 : isEncoded!.hashCode) +
@ -490,7 +466,7 @@ class MetadataSearchDto {
(withStacked == null ? 0 : withStacked!.hashCode);
@override
String toString() => 'MetadataSearchDto[albumIds=$albumIds, checksum=$checksum, city=$city, country=$country, createdAfter=$createdAfter, createdBefore=$createdBefore, description=$description, deviceAssetId=$deviceAssetId, deviceId=$deviceId, encodedVideoPath=$encodedVideoPath, id=$id, isEncoded=$isEncoded, isFavorite=$isFavorite, isMotion=$isMotion, isNotInAlbum=$isNotInAlbum, isOffline=$isOffline, lensModel=$lensModel, libraryId=$libraryId, make=$make, model=$model, ocr=$ocr, order=$order, originalFileName=$originalFileName, originalPath=$originalPath, page=$page, personIds=$personIds, previewPath=$previewPath, rating=$rating, size=$size, state=$state, tagIds=$tagIds, takenAfter=$takenAfter, takenBefore=$takenBefore, thumbnailPath=$thumbnailPath, trashedAfter=$trashedAfter, trashedBefore=$trashedBefore, type=$type, updatedAfter=$updatedAfter, updatedBefore=$updatedBefore, visibility=$visibility, withDeleted=$withDeleted, withExif=$withExif, withPeople=$withPeople, withStacked=$withStacked]';
String toString() => 'MetadataSearchDto[albumIds=$albumIds, checksum=$checksum, city=$city, country=$country, createdAfter=$createdAfter, createdBefore=$createdBefore, description=$description, encodedVideoPath=$encodedVideoPath, id=$id, isEncoded=$isEncoded, isFavorite=$isFavorite, isMotion=$isMotion, isNotInAlbum=$isNotInAlbum, isOffline=$isOffline, lensModel=$lensModel, libraryId=$libraryId, make=$make, model=$model, ocr=$ocr, order=$order, originalFileName=$originalFileName, originalPath=$originalPath, page=$page, personIds=$personIds, previewPath=$previewPath, rating=$rating, size=$size, state=$state, tagIds=$tagIds, takenAfter=$takenAfter, takenBefore=$takenBefore, thumbnailPath=$thumbnailPath, trashedAfter=$trashedAfter, trashedBefore=$trashedBefore, type=$type, updatedAfter=$updatedAfter, updatedBefore=$updatedBefore, visibility=$visibility, withDeleted=$withDeleted, withExif=$withExif, withPeople=$withPeople, withStacked=$withStacked]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
@ -529,16 +505,6 @@ class MetadataSearchDto {
} else {
// json[r'description'] = null;
}
if (this.deviceAssetId != null) {
json[r'deviceAssetId'] = this.deviceAssetId;
} else {
// json[r'deviceAssetId'] = null;
}
if (this.deviceId != null) {
json[r'deviceId'] = this.deviceId;
} else {
// json[r'deviceId'] = null;
}
if (this.encodedVideoPath != null) {
json[r'encodedVideoPath'] = this.encodedVideoPath;
} else {
@ -743,8 +709,6 @@ class MetadataSearchDto {
createdAfter: mapDateTime(json, r'createdAfter', r'/^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$/'),
createdBefore: mapDateTime(json, r'createdBefore', r'/^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$/'),
description: mapValueOfType<String>(json, r'description'),
deviceAssetId: mapValueOfType<String>(json, r'deviceAssetId'),
deviceId: mapValueOfType<String>(json, r'deviceId'),
encodedVideoPath: mapValueOfType<String>(json, r'encodedVideoPath'),
id: mapValueOfType<String>(json, r'id'),
isEncoded: mapValueOfType<bool>(json, r'isEncoded'),

View File

@ -18,7 +18,6 @@ class RandomSearchDto {
this.country,
this.createdAfter,
this.createdBefore,
this.deviceId,
this.isEncoded,
this.isFavorite,
this.isMotion,
@ -75,15 +74,6 @@ class RandomSearchDto {
///
DateTime? createdBefore;
/// Device ID to filter by
///
/// 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? deviceId;
/// Filter by encoded status
///
/// Please note: This property should have been non-nullable! Since the specification file
@ -290,7 +280,6 @@ class RandomSearchDto {
other.country == country &&
other.createdAfter == createdAfter &&
other.createdBefore == createdBefore &&
other.deviceId == deviceId &&
other.isEncoded == isEncoded &&
other.isFavorite == isFavorite &&
other.isMotion == isMotion &&
@ -327,7 +316,6 @@ class RandomSearchDto {
(country == null ? 0 : country!.hashCode) +
(createdAfter == null ? 0 : createdAfter!.hashCode) +
(createdBefore == null ? 0 : createdBefore!.hashCode) +
(deviceId == null ? 0 : deviceId!.hashCode) +
(isEncoded == null ? 0 : isEncoded!.hashCode) +
(isFavorite == null ? 0 : isFavorite!.hashCode) +
(isMotion == null ? 0 : isMotion!.hashCode) +
@ -357,7 +345,7 @@ class RandomSearchDto {
(withStacked == null ? 0 : withStacked!.hashCode);
@override
String toString() => 'RandomSearchDto[albumIds=$albumIds, city=$city, country=$country, createdAfter=$createdAfter, createdBefore=$createdBefore, deviceId=$deviceId, isEncoded=$isEncoded, isFavorite=$isFavorite, isMotion=$isMotion, isNotInAlbum=$isNotInAlbum, isOffline=$isOffline, lensModel=$lensModel, libraryId=$libraryId, make=$make, model=$model, ocr=$ocr, personIds=$personIds, rating=$rating, size=$size, state=$state, tagIds=$tagIds, takenAfter=$takenAfter, takenBefore=$takenBefore, trashedAfter=$trashedAfter, trashedBefore=$trashedBefore, type=$type, updatedAfter=$updatedAfter, updatedBefore=$updatedBefore, visibility=$visibility, withDeleted=$withDeleted, withExif=$withExif, withPeople=$withPeople, withStacked=$withStacked]';
String toString() => 'RandomSearchDto[albumIds=$albumIds, city=$city, country=$country, createdAfter=$createdAfter, createdBefore=$createdBefore, isEncoded=$isEncoded, isFavorite=$isFavorite, isMotion=$isMotion, isNotInAlbum=$isNotInAlbum, isOffline=$isOffline, lensModel=$lensModel, libraryId=$libraryId, make=$make, model=$model, ocr=$ocr, personIds=$personIds, rating=$rating, size=$size, state=$state, tagIds=$tagIds, takenAfter=$takenAfter, takenBefore=$takenBefore, trashedAfter=$trashedAfter, trashedBefore=$trashedBefore, type=$type, updatedAfter=$updatedAfter, updatedBefore=$updatedBefore, visibility=$visibility, withDeleted=$withDeleted, withExif=$withExif, withPeople=$withPeople, withStacked=$withStacked]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
@ -386,11 +374,6 @@ class RandomSearchDto {
} else {
// json[r'createdBefore'] = null;
}
if (this.deviceId != null) {
json[r'deviceId'] = this.deviceId;
} else {
// json[r'deviceId'] = null;
}
if (this.isEncoded != null) {
json[r'isEncoded'] = this.isEncoded;
} else {
@ -553,7 +536,6 @@ class RandomSearchDto {
country: mapValueOfType<String>(json, r'country'),
createdAfter: mapDateTime(json, r'createdAfter', r'/^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$/'),
createdBefore: mapDateTime(json, r'createdBefore', r'/^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$/'),
deviceId: mapValueOfType<String>(json, r'deviceId'),
isEncoded: mapValueOfType<bool>(json, r'isEncoded'),
isFavorite: mapValueOfType<bool>(json, r'isFavorite'),
isMotion: mapValueOfType<bool>(json, r'isMotion'),

View File

@ -18,7 +18,6 @@ class SmartSearchDto {
this.country,
this.createdAfter,
this.createdBefore,
this.deviceId,
this.isEncoded,
this.isFavorite,
this.isMotion,
@ -77,15 +76,6 @@ class SmartSearchDto {
///
DateTime? createdBefore;
/// Device ID to filter by
///
/// 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? deviceId;
/// Filter by encoded status
///
/// Please note: This property should have been non-nullable! Since the specification file
@ -312,7 +302,6 @@ class SmartSearchDto {
other.country == country &&
other.createdAfter == createdAfter &&
other.createdBefore == createdBefore &&
other.deviceId == deviceId &&
other.isEncoded == isEncoded &&
other.isFavorite == isFavorite &&
other.isMotion == isMotion &&
@ -351,7 +340,6 @@ class SmartSearchDto {
(country == null ? 0 : country!.hashCode) +
(createdAfter == null ? 0 : createdAfter!.hashCode) +
(createdBefore == null ? 0 : createdBefore!.hashCode) +
(deviceId == null ? 0 : deviceId!.hashCode) +
(isEncoded == null ? 0 : isEncoded!.hashCode) +
(isFavorite == null ? 0 : isFavorite!.hashCode) +
(isMotion == null ? 0 : isMotion!.hashCode) +
@ -383,7 +371,7 @@ class SmartSearchDto {
(withExif == null ? 0 : withExif!.hashCode);
@override
String toString() => 'SmartSearchDto[albumIds=$albumIds, city=$city, country=$country, createdAfter=$createdAfter, createdBefore=$createdBefore, deviceId=$deviceId, isEncoded=$isEncoded, isFavorite=$isFavorite, isMotion=$isMotion, isNotInAlbum=$isNotInAlbum, isOffline=$isOffline, language=$language, lensModel=$lensModel, libraryId=$libraryId, make=$make, model=$model, ocr=$ocr, page=$page, personIds=$personIds, query=$query, queryAssetId=$queryAssetId, rating=$rating, size=$size, state=$state, tagIds=$tagIds, takenAfter=$takenAfter, takenBefore=$takenBefore, trashedAfter=$trashedAfter, trashedBefore=$trashedBefore, type=$type, updatedAfter=$updatedAfter, updatedBefore=$updatedBefore, visibility=$visibility, withDeleted=$withDeleted, withExif=$withExif]';
String toString() => 'SmartSearchDto[albumIds=$albumIds, city=$city, country=$country, createdAfter=$createdAfter, createdBefore=$createdBefore, isEncoded=$isEncoded, isFavorite=$isFavorite, isMotion=$isMotion, isNotInAlbum=$isNotInAlbum, isOffline=$isOffline, language=$language, lensModel=$lensModel, libraryId=$libraryId, make=$make, model=$model, ocr=$ocr, page=$page, personIds=$personIds, query=$query, queryAssetId=$queryAssetId, rating=$rating, size=$size, state=$state, tagIds=$tagIds, takenAfter=$takenAfter, takenBefore=$takenBefore, trashedAfter=$trashedAfter, trashedBefore=$trashedBefore, type=$type, updatedAfter=$updatedAfter, updatedBefore=$updatedBefore, visibility=$visibility, withDeleted=$withDeleted, withExif=$withExif]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
@ -412,11 +400,6 @@ class SmartSearchDto {
} else {
// json[r'createdBefore'] = null;
}
if (this.deviceId != null) {
json[r'deviceId'] = this.deviceId;
} else {
// json[r'deviceId'] = null;
}
if (this.isEncoded != null) {
json[r'isEncoded'] = this.isEncoded;
} else {
@ -589,7 +572,6 @@ class SmartSearchDto {
country: mapValueOfType<String>(json, r'country'),
createdAfter: mapDateTime(json, r'createdAfter', r'/^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$/'),
createdBefore: mapDateTime(json, r'createdBefore', r'/^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$/'),
deviceId: mapValueOfType<String>(json, r'deviceId'),
isEncoded: mapValueOfType<bool>(json, r'isEncoded'),
isFavorite: mapValueOfType<bool>(json, r'isFavorite'),
isMotion: mapValueOfType<bool>(json, r'isMotion'),

View File

@ -19,7 +19,6 @@ class StatisticsSearchDto {
this.createdAfter,
this.createdBefore,
this.description,
this.deviceId,
this.isEncoded,
this.isFavorite,
this.isMotion,
@ -80,15 +79,6 @@ class StatisticsSearchDto {
///
String? description;
/// Device ID to filter by
///
/// 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? deviceId;
/// Filter by encoded status
///
/// Please note: This property should have been non-nullable! Since the specification file
@ -248,7 +238,6 @@ class StatisticsSearchDto {
other.createdAfter == createdAfter &&
other.createdBefore == createdBefore &&
other.description == description &&
other.deviceId == deviceId &&
other.isEncoded == isEncoded &&
other.isFavorite == isFavorite &&
other.isMotion == isMotion &&
@ -281,7 +270,6 @@ class StatisticsSearchDto {
(createdAfter == null ? 0 : createdAfter!.hashCode) +
(createdBefore == null ? 0 : createdBefore!.hashCode) +
(description == null ? 0 : description!.hashCode) +
(deviceId == null ? 0 : deviceId!.hashCode) +
(isEncoded == null ? 0 : isEncoded!.hashCode) +
(isFavorite == null ? 0 : isFavorite!.hashCode) +
(isMotion == null ? 0 : isMotion!.hashCode) +
@ -306,7 +294,7 @@ class StatisticsSearchDto {
(visibility == null ? 0 : visibility!.hashCode);
@override
String toString() => 'StatisticsSearchDto[albumIds=$albumIds, city=$city, country=$country, createdAfter=$createdAfter, createdBefore=$createdBefore, description=$description, deviceId=$deviceId, isEncoded=$isEncoded, isFavorite=$isFavorite, isMotion=$isMotion, isNotInAlbum=$isNotInAlbum, isOffline=$isOffline, lensModel=$lensModel, libraryId=$libraryId, make=$make, model=$model, ocr=$ocr, personIds=$personIds, rating=$rating, state=$state, tagIds=$tagIds, takenAfter=$takenAfter, takenBefore=$takenBefore, trashedAfter=$trashedAfter, trashedBefore=$trashedBefore, type=$type, updatedAfter=$updatedAfter, updatedBefore=$updatedBefore, visibility=$visibility]';
String toString() => 'StatisticsSearchDto[albumIds=$albumIds, city=$city, country=$country, createdAfter=$createdAfter, createdBefore=$createdBefore, description=$description, isEncoded=$isEncoded, isFavorite=$isFavorite, isMotion=$isMotion, isNotInAlbum=$isNotInAlbum, isOffline=$isOffline, lensModel=$lensModel, libraryId=$libraryId, make=$make, model=$model, ocr=$ocr, personIds=$personIds, rating=$rating, state=$state, tagIds=$tagIds, takenAfter=$takenAfter, takenBefore=$takenBefore, trashedAfter=$trashedAfter, trashedBefore=$trashedBefore, type=$type, updatedAfter=$updatedAfter, updatedBefore=$updatedBefore, visibility=$visibility]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
@ -340,11 +328,6 @@ class StatisticsSearchDto {
} else {
// json[r'description'] = null;
}
if (this.deviceId != null) {
json[r'deviceId'] = this.deviceId;
} else {
// json[r'deviceId'] = null;
}
if (this.isEncoded != null) {
json[r'isEncoded'] = this.isEncoded;
} else {
@ -483,7 +466,6 @@ class StatisticsSearchDto {
createdAfter: mapDateTime(json, r'createdAfter', r'/^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$/'),
createdBefore: mapDateTime(json, r'createdBefore', r'/^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$/'),
description: mapValueOfType<String>(json, r'description'),
deviceId: mapValueOfType<String>(json, r'deviceId'),
isEncoded: mapValueOfType<bool>(json, r'isEncoded'),
isFavorite: mapValueOfType<bool>(json, r'isFavorite'),
isMotion: mapValueOfType<bool>(json, r'isMotion'),

View File

@ -3084,126 +3084,6 @@
"x-immich-state": "Stable"
}
},
"/assets/device/{deviceId}": {
"get": {
"deprecated": true,
"description": "Get all asset of a device that are in the database, ID only.",
"operationId": "getAllUserAssetsByDeviceId",
"parameters": [
{
"name": "deviceId",
"required": true,
"in": "path",
"description": "Device ID",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"items": {
"type": "string"
},
"type": "array"
}
}
},
"description": ""
}
},
"security": [
{
"bearer": []
},
{
"cookie": []
},
{
"api_key": []
}
],
"summary": "Retrieve assets by device ID",
"tags": [
"Assets",
"Deprecated"
],
"x-immich-history": [
{
"version": "v1",
"state": "Added"
},
{
"version": "v2",
"state": "Deprecated"
}
],
"x-immich-state": "Deprecated"
}
},
"/assets/exist": {
"post": {
"description": "Checks if multiple assets exist on the server and returns all existing - used by background backup",
"operationId": "checkExistingAssets",
"parameters": [],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CheckExistingAssetsDto"
}
}
},
"required": true
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CheckExistingAssetsResponseDto"
}
}
},
"description": ""
}
},
"security": [
{
"bearer": []
},
{
"cookie": []
},
{
"api_key": []
}
],
"summary": "Check existing assets",
"tags": [
"Assets"
],
"x-immich-history": [
{
"version": "v1",
"state": "Added"
},
{
"version": "v1",
"state": "Beta"
},
{
"version": "v2",
"state": "Stable"
}
],
"x-immich-permission": "asset.upload",
"x-immich-state": "Stable"
}
},
"/assets/jobs": {
"post": {
"description": "Run a specific job on a set of assets.",
@ -9255,15 +9135,6 @@
"type": "string"
}
},
{
"name": "deviceId",
"required": false,
"in": "query",
"description": "Device ID to filter by",
"schema": {
"type": "string"
}
},
{
"name": "isEncoded",
"required": false,
@ -16343,14 +16214,6 @@
"format": "binary",
"type": "string"
},
"deviceAssetId": {
"description": "Device asset ID",
"type": "string"
},
"deviceId": {
"description": "Device ID",
"type": "string"
},
"duration": {
"description": "Duration (for videos)",
"type": "string"
@ -16401,8 +16264,6 @@
},
"required": [
"assetData",
"deviceAssetId",
"deviceId",
"fileCreatedAt",
"fileModifiedAt"
],
@ -16718,14 +16579,6 @@
"format": "date-time",
"type": "string"
},
"deviceAssetId": {
"description": "Device asset ID",
"type": "string"
},
"deviceId": {
"description": "Device ID",
"type": "string"
},
"duplicateId": {
"description": "Duplicate group ID",
"nullable": true,
@ -16907,8 +16760,6 @@
"required": [
"checksum",
"createdAt",
"deviceAssetId",
"deviceId",
"duration",
"fileCreatedAt",
"fileModifiedAt",
@ -17184,42 +17035,6 @@
],
"type": "object"
},
"CheckExistingAssetsDto": {
"properties": {
"deviceAssetIds": {
"description": "Device asset IDs to check",
"items": {
"type": "string"
},
"minItems": 1,
"type": "array"
},
"deviceId": {
"description": "Device ID",
"type": "string"
}
},
"required": [
"deviceAssetIds",
"deviceId"
],
"type": "object"
},
"CheckExistingAssetsResponseDto": {
"properties": {
"existingIds": {
"description": "Existing asset IDs",
"items": {
"type": "string"
},
"type": "array"
}
},
"required": [
"existingIds"
],
"type": "object"
},
"Colorspace": {
"description": "Colorspace",
"enum": [
@ -18794,14 +18609,6 @@
"description": "Filter by description text",
"type": "string"
},
"deviceAssetId": {
"description": "Filter by device asset ID",
"type": "string"
},
"deviceId": {
"description": "Device ID to filter by",
"type": "string"
},
"encodedVideoPath": {
"description": "Filter by encoded video file path",
"type": "string"
@ -20675,10 +20482,6 @@
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
"type": "string"
},
"deviceId": {
"description": "Device ID to filter by",
"type": "string"
},
"isEncoded": {
"description": "Filter by encoded status",
"type": "boolean"
@ -22054,10 +21857,6 @@
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
"type": "string"
},
"deviceId": {
"description": "Device ID to filter by",
"type": "string"
},
"isEncoded": {
"description": "Filter by encoded status",
"type": "boolean"
@ -22337,10 +22136,6 @@
"description": "Filter by description text",
"type": "string"
},
"deviceId": {
"description": "Device ID to filter by",
"type": "string"
},
"isEncoded": {
"description": "Filter by encoded status",
"type": "boolean"

View File

@ -557,10 +557,6 @@ export type AssetResponseDto = {
checksum: string;
/** The UTC timestamp when the asset was originally uploaded to Immich. */
createdAt: string;
/** Device asset ID */
deviceAssetId: string;
/** Device ID */
deviceId: string;
/** Duplicate group ID */
duplicateId?: string | null;
/** Video duration (for videos) */
@ -773,10 +769,6 @@ export type AssetMetadataUpsertItemDto = {
export type AssetMediaCreateDto = {
/** Asset file data */
assetData: Blob;
/** Device asset ID */
deviceAssetId: string;
/** Device ID */
deviceId: string;
/** Duration (for videos) */
duration?: string;
/** File creation date */
@ -863,16 +855,6 @@ export type AssetCopyDto = {
/** Target asset ID */
targetId: string;
};
export type CheckExistingAssetsDto = {
/** Device asset IDs to check */
deviceAssetIds: string[];
/** Device ID */
deviceId: string;
};
export type CheckExistingAssetsResponseDto = {
/** Existing asset IDs */
existingIds: string[];
};
export type AssetJobsDto = {
/** Asset IDs */
assetIds: string[];
@ -1661,10 +1643,6 @@ export type MetadataSearchDto = {
createdBefore?: string;
/** Filter by description text */
description?: string;
/** Filter by device asset ID */
deviceAssetId?: string;
/** Device ID to filter by */
deviceId?: string;
/** Filter by encoded video file path */
encodedVideoPath?: string;
/** Filter by asset ID */
@ -1790,8 +1768,6 @@ export type RandomSearchDto = {
createdAfter?: string;
/** Filter by creation date (before) */
createdBefore?: string;
/** Device ID to filter by */
deviceId?: string;
/** Filter by encoded status */
isEncoded?: boolean;
/** Filter by favorite status */
@ -1856,8 +1832,6 @@ export type SmartSearchDto = {
createdAfter?: string;
/** Filter by creation date (before) */
createdBefore?: string;
/** Device ID to filter by */
deviceId?: string;
/** Filter by encoded status */
isEncoded?: boolean;
/** Filter by favorite status */
@ -1928,8 +1902,6 @@ export type StatisticsSearchDto = {
createdBefore?: string;
/** Filter by description text */
description?: string;
/** Device ID to filter by */
deviceId?: string;
/** Filter by encoded status */
isEncoded?: boolean;
/** Filter by favorite status */
@ -3958,34 +3930,6 @@ export function copyAsset({ assetCopyDto }: {
body: assetCopyDto
})));
}
/**
* Retrieve assets by device ID
*/
export function getAllUserAssetsByDeviceId({ deviceId }: {
deviceId: string;
}, opts?: Oazapfts.RequestOpts) {
return oazapfts.ok(oazapfts.fetchJson<{
status: 200;
data: string[];
}>(`/assets/device/${encodeURIComponent(deviceId)}`, {
...opts
}));
}
/**
* Check existing assets
*/
export function checkExistingAssets({ checkExistingAssetsDto }: {
checkExistingAssetsDto: CheckExistingAssetsDto;
}, opts?: Oazapfts.RequestOpts) {
return oazapfts.ok(oazapfts.fetchJson<{
status: 200;
data: CheckExistingAssetsResponseDto;
}>("/assets/exist", oazapfts.json({
...opts,
method: "POST",
body: checkExistingAssetsDto
})));
}
/**
* Run an asset job
*/
@ -5365,13 +5309,12 @@ export function getExploreData(opts?: Oazapfts.RequestOpts) {
/**
* Search large assets
*/
export function searchLargeAssets({ albumIds, city, country, createdAfter, createdBefore, deviceId, isEncoded, isFavorite, isMotion, isNotInAlbum, isOffline, lensModel, libraryId, make, minFileSize, model, ocr, personIds, rating, size, state, tagIds, takenAfter, takenBefore, trashedAfter, trashedBefore, $type, updatedAfter, updatedBefore, visibility, withDeleted, withExif }: {
export function searchLargeAssets({ albumIds, city, country, createdAfter, createdBefore, isEncoded, isFavorite, isMotion, isNotInAlbum, isOffline, lensModel, libraryId, make, minFileSize, model, ocr, personIds, rating, size, state, tagIds, takenAfter, takenBefore, trashedAfter, trashedBefore, $type, updatedAfter, updatedBefore, visibility, withDeleted, withExif }: {
albumIds?: string[];
city?: string | null;
country?: string | null;
createdAfter?: string;
createdBefore?: string;
deviceId?: string;
isEncoded?: boolean;
isFavorite?: boolean;
isMotion?: boolean;
@ -5408,7 +5351,6 @@ export function searchLargeAssets({ albumIds, city, country, createdAfter, creat
country,
createdAfter,
createdBefore,
deviceId,
isEncoded,
isFavorite,
isMotion,

View File

@ -9,8 +9,6 @@ import { automock, ControllerContext, controllerSetup, mockBaseService } from 't
const makeUploadDto = (options?: { omit: string }): Record<string, any> => {
const dto: Record<string, any> = {
deviceAssetId: 'example-image',
deviceId: 'TEST',
fileCreatedAt: new Date().toISOString(),
fileModifiedAt: new Date().toISOString(),
isFavorite: 'false',
@ -87,28 +85,6 @@ describe(AssetMediaController.name, () => {
);
});
it('should require `deviceAssetId`', async () => {
const { status, body } = await request(ctx.getHttpServer())
.post('/assets')
.attach('assetData', assetData, filename)
.field({ ...makeUploadDto({ omit: 'deviceAssetId' }) });
expect(status).toBe(400);
expect(body).toEqual(
factory.responses.badRequest(['[deviceAssetId] Invalid input: expected string, received undefined']),
);
});
it('should require `deviceId`', async () => {
const { status, body } = await request(ctx.getHttpServer())
.post('/assets')
.attach('assetData', assetData, filename)
.field({ ...makeUploadDto({ omit: 'deviceId' }) });
expect(status).toBe(400);
expect(body).toEqual(
factory.responses.badRequest(['[deviceId] Invalid input: expected string, received undefined']),
);
});
it('should require `fileCreatedAt`', async () => {
const { status, body } = await request(ctx.getHttpServer())
.post('/assets')

View File

@ -21,14 +21,12 @@ import {
AssetBulkUploadCheckResponseDto,
AssetMediaResponseDto,
AssetMediaStatus,
CheckExistingAssetsResponseDto,
} from 'src/dtos/asset-media-response.dto';
import {
AssetBulkUploadCheckDto,
AssetMediaCreateDto,
AssetMediaOptionsDto,
AssetMediaSize,
CheckExistingAssetsDto,
} from 'src/dtos/asset-media.dto';
import { AssetDownloadOriginalDto } from 'src/dtos/asset.dto';
import { AuthDto } from 'src/dtos/auth.dto';
@ -179,21 +177,6 @@ export class AssetMediaController {
await sendFile(res, next, () => this.service.playbackVideo(auth, id), this.logger);
}
@Post('exist')
@Authenticated({ permission: Permission.AssetUpload })
@Endpoint({
summary: 'Check existing assets',
description: 'Checks if multiple assets exist on the server and returns all existing - used by background backup',
history: new HistoryBuilder().added('v1').beta('v1').stable('v2'),
})
@HttpCode(HttpStatus.OK)
checkExistingAssets(
@Auth() auth: AuthDto,
@Body() dto: CheckExistingAssetsDto,
): Promise<CheckExistingAssetsResponseDto> {
return this.service.checkExistingAssets(auth, dto);
}
@Post('bulk-upload-check')
@Authenticated({ permission: Permission.AssetUpload })
@Endpoint({

View File

@ -15,7 +15,6 @@ import {
AssetMetadataUpsertDto,
AssetStatsDto,
AssetStatsResponseDto,
DeviceIdDto,
UpdateAssetDto,
} from 'src/dtos/asset.dto';
import { AuthDto } from 'src/dtos/auth.dto';
@ -31,17 +30,6 @@ import { UUIDParamDto } from 'src/validation';
export class AssetController {
constructor(private service: AssetService) {}
@Get('/device/:deviceId')
@Endpoint({
summary: 'Retrieve assets by device ID',
description: 'Get all asset of a device that are in the database, ID only.',
history: new HistoryBuilder().added('v1').deprecated('v2'),
})
@Authenticated()
getAllUserAssetsByDeviceId(@Auth() auth: AuthDto, @Param() { deviceId }: DeviceIdDto) {
return this.service.getUserAssetsByDeviceId(auth, deviceId);
}
@Get('statistics')
@Authenticated({ permission: Permission.AssetStatistics })
@Endpoint({

View File

@ -114,8 +114,6 @@ export type Asset = {
id: string;
checksum: Buffer<ArrayBufferLike>;
checksumAlgorithm: ChecksumAlgorithm;
deviceAssetId: string;
deviceId: string;
fileCreatedAt: Date;
fileModifiedAt: Date;
isExternal: boolean;
@ -333,8 +331,6 @@ export const columns = {
'asset.id',
'asset.checksum',
'asset.checksumAlgorithm',
'asset.deviceAssetId',
'asset.deviceId',
'asset.fileCreatedAt',
'asset.fileModifiedAt',
'asset.isExternal',

View File

@ -49,12 +49,5 @@ const AssetBulkUploadCheckResponseSchema = z
})
.meta({ id: 'AssetBulkUploadCheckResponseDto' });
const CheckExistingAssetsResponseSchema = z
.object({
existingIds: z.array(z.string()).describe('Existing asset IDs'),
})
.meta({ id: 'CheckExistingAssetsResponseDto' });
export class AssetMediaResponseDto extends createZodDto(AssetMediaResponseSchema) {}
export class AssetBulkUploadCheckResponseDto extends createZodDto(AssetBulkUploadCheckResponseSchema) {}
export class CheckExistingAssetsResponseDto extends createZodDto(CheckExistingAssetsResponseSchema) {}

View File

@ -36,8 +36,6 @@ export enum UploadFieldName {
}
const AssetMediaBaseSchema = z.object({
deviceAssetId: z.string().describe('Device asset ID'),
deviceId: z.string().describe('Device ID'),
fileCreatedAt: isoDatetimeToDate.describe('File creation date'),
fileModifiedAt: isoDatetimeToDate.describe('File modification date'),
duration: z.string().optional().describe('Duration (for videos)'),
@ -71,14 +69,6 @@ const AssetBulkUploadCheckSchema = z
})
.meta({ id: 'AssetBulkUploadCheckDto' });
const CheckExistingAssetsSchema = z
.object({
deviceAssetIds: z.array(z.string()).min(1).describe('Device asset IDs to check'),
deviceId: z.string().describe('Device ID'),
})
.meta({ id: 'CheckExistingAssetsDto' });
export class AssetMediaOptionsDto extends createZodDto(AssetMediaOptionsSchema) {}
export class AssetMediaCreateDto extends createZodDto(AssetMediaCreateSchema) {}
export class AssetBulkUploadCheckDto extends createZodDto(AssetBulkUploadCheckSchema) {}
export class CheckExistingAssetsDto extends createZodDto(CheckExistingAssetsSchema) {}

View File

@ -72,8 +72,6 @@ export const AssetResponseSchema = SanitizedAssetResponseSchema.extend(
.string()
.meta({ format: 'date-time' })
.describe('The UTC timestamp when the asset was originally uploaded to Immich.'),
deviceAssetId: z.string().describe('Device asset ID'),
deviceId: z.string().describe('Device ID'),
ownerId: z.string().describe('Owner user ID'),
owner: UserResponseSchema.optional(),
libraryId: z
@ -137,8 +135,6 @@ export type MapAsset = {
status: AssetStatus;
checksum: Buffer<ArrayBufferLike>;
checksumAlgorithm: ChecksumAlgorithm;
deviceAssetId: string;
deviceId: string;
duplicateId: string | null;
duration: string | null;
edits?: ShallowDehydrateObject<AssetEditActionItem>[];
@ -239,10 +235,8 @@ export function mapAsset(entity: MaybeDehydrated<MapAsset>, options: AssetMapOpt
return {
id: entity.id,
createdAt: asDateString(entity.createdAt),
deviceAssetId: entity.deviceAssetId,
ownerId: entity.ownerId,
owner: entity.owner ? mapUser(entity.owner) : undefined,
deviceId: entity.deviceId,
libraryId: entity.libraryId,
type: entity.type,
originalPath: entity.originalPath,

View File

@ -6,12 +6,6 @@ import { AssetStats } from 'src/repositories/asset.repository';
import { IsNotSiblingOf, isoDatetimeToDate, latitudeSchema, longitudeSchema, stringToBool } from 'src/validation';
import z from 'zod';
const DeviceIdSchema = z
.object({
deviceId: z.string().describe('Device ID'),
})
.meta({ id: 'DeviceIdDto' });
const UpdateAssetBaseSchema = z
.object({
isFavorite: z.boolean().optional().describe('Mark as favorite'),
@ -182,7 +176,6 @@ export const mapStats = (stats: AssetStats): AssetStatsResponseDto => {
};
};
export class DeviceIdDto extends createZodDto(DeviceIdSchema) {}
export class AssetBulkUpdateDto extends createZodDto(AssetBulkUpdateSchema) {}
export class UpdateAssetDto extends createZodDto(UpdateAssetSchema) {}
export class AssetBulkDeleteDto extends createZodDto(AssetBulkDeleteSchema) {}

View File

@ -9,7 +9,6 @@ import z from 'zod';
const BaseSearchSchema = z.object({
libraryId: z.uuidv4().nullish().describe('Library ID to filter by'),
deviceId: z.string().optional().describe('Device ID to filter by'),
type: AssetTypeSchema.optional(),
isEncoded: z.boolean().optional().describe('Filter by encoded status'),
isFavorite: z.boolean().optional().describe('Filter by favorite status'),
@ -68,7 +67,6 @@ const LargeAssetSearchSchema = BaseSearchWithResultsSchema.extend({
const MetadataSearchSchema = RandomSearchSchema.extend({
id: z.uuidv4().optional().describe('Filter by asset ID'),
deviceAssetId: z.string().optional().describe('Filter by device asset ID'),
description: z.string().trim().optional().describe('Filter by description text'),
checksum: z.string().optional().describe('Filter by file checksum'),
originalFileName: z.string().trim().optional().describe('Filter by original file name'),

View File

@ -250,8 +250,6 @@ select
"asset"."id",
"asset"."checksum",
"asset"."checksumAlgorithm",
"asset"."deviceAssetId",
"asset"."deviceId",
"asset"."fileCreatedAt",
"asset"."fileModifiedAt",
"asset"."isExternal",

View File

@ -242,17 +242,6 @@ where
limit
$3
-- AssetRepository.getAllByDeviceId
select
"deviceAssetId"
from
"asset"
where
"ownerId" = $1::uuid
and "deviceId" = $2
and "visibility" != $3
and "deletedAt" is null
-- AssetRepository.getLivePhotoCount
select
count(*) as "count"
@ -312,9 +301,8 @@ limit
-- AssetRepository.updateAll
update "asset"
set
"deviceId" = $1
where
"id" = any ($2::uuid[])
"id" = any ($1::uuid[])
-- AssetRepository.getByChecksum
select

View File

@ -448,18 +448,6 @@ export class AssetRepository {
await this.db.deleteFrom('asset').where('ownerId', '=', ownerId).execute();
}
async getByDeviceIds(ownerId: string, deviceId: string, deviceAssetIds: string[]): Promise<string[]> {
const assets = await this.db
.selectFrom('asset')
.select(['deviceAssetId'])
.where('deviceAssetId', 'in', deviceAssetIds)
.where('deviceId', '=', deviceId)
.where('ownerId', '=', asUuid(ownerId))
.execute();
return assets.map((asset) => asset.deviceAssetId);
}
@GenerateSql({ params: [DummyValue.UUID, DummyValue.STRING] })
getByLibraryIdAndOriginalPath(libraryId: string, originalPath: string) {
return this.db
@ -471,27 +459,6 @@ export class AssetRepository {
.executeTakeFirst();
}
/**
* Get assets by device's Id on the database
* @param ownerId
* @param deviceId
*
* @returns Promise<string[]> - Array of assetIds belong to the device
*/
@GenerateSql({ params: [DummyValue.UUID, DummyValue.STRING] })
async getAllByDeviceId(ownerId: string, deviceId: string): Promise<string[]> {
const items = await this.db
.selectFrom('asset')
.select(['deviceAssetId'])
.where('ownerId', '=', asUuid(ownerId))
.where('deviceId', '=', deviceId)
.where('visibility', '!=', AssetVisibility.Hidden)
.where('deletedAt', 'is', null)
.execute();
return items.map((asset) => asset.deviceAssetId);
}
@GenerateSql({ params: [DummyValue.UUID] })
async getLivePhotoCount(motionId: string): Promise<number> {
const [{ count }] = await this.db
@ -568,7 +535,7 @@ export class AssetRepository {
.executeTakeFirst();
}
@GenerateSql({ params: [[DummyValue.UUID], { deviceId: DummyValue.STRING }] })
@GenerateSql({ params: [[DummyValue.UUID], {}] })
@Chunked()
async updateAll(ids: string[], options: Updateable<AssetTable>): Promise<void> {
if (ids.length === 0) {

View File

@ -14,12 +14,10 @@ import { isValidInteger } from 'src/validation';
export interface SearchAssetIdOptions {
checksum?: Buffer;
deviceAssetId?: string;
id?: string;
}
export interface SearchUserIdOptions {
deviceId?: string;
libraryId?: string | null;
userIds?: string[];
}

View File

@ -0,0 +1,11 @@
import { Kysely, sql } from 'kysely';
export async function up(db: Kysely<any>): Promise<void> {
await sql`ALTER TABLE "asset" DROP COLUMN "deviceAssetId";`.execute(db);
await sql`ALTER TABLE "asset" DROP COLUMN "deviceId";`.execute(db);
}
export async function down(db: Kysely<any>): Promise<void> {
await sql`ALTER TABLE "asset" ADD "deviceAssetId" character varying NOT NULL;`.execute(db);
await sql`ALTER TABLE "asset" ADD "deviceId" character varying NOT NULL;`.execute(db);
}

View File

@ -65,15 +65,9 @@ export class AssetTable {
@PrimaryGeneratedColumn()
id!: Generated<string>;
@Column()
deviceAssetId!: string;
@ForeignKeyColumn(() => UserTable, { onDelete: 'CASCADE', onUpdate: 'CASCADE', nullable: false })
ownerId!: string;
@Column()
deviceId!: string;
@Column()
type!: AssetType;

View File

@ -145,8 +145,6 @@ const uploadTests = [
];
const createDto = Object.freeze({
deviceAssetId: 'deviceAssetId',
deviceId: 'deviceId',
fileCreatedAt: new Date('2022-06-19T23:41:36.910Z'),
fileModifiedAt: new Date('2022-06-19T23:41:36.910Z'),
isFavorite: false,
@ -156,8 +154,6 @@ const createDto = Object.freeze({
const assetEntity = Object.freeze({
id: 'id_1',
ownerId: 'user_id_1',
deviceAssetId: 'device_asset_id_1',
deviceId: 'device_id_1',
type: AssetType.Video,
originalPath: 'fake_path/asset_1.jpeg',
fileModifiedAt: new Date('2022-06-19T23:41:36.910Z'),
@ -765,17 +761,6 @@ describe(AssetMediaService.name, () => {
});
});
describe('checkExistingAssets', () => {
it('should get existing asset ids', async () => {
mocks.asset.getByDeviceIds.mockResolvedValue(['42']);
await expect(
sut.checkExistingAssets(authStub.admin, { deviceId: '420', deviceAssetIds: ['69'] }),
).resolves.toEqual({ existingIds: ['42'] });
expect(mocks.asset.getByDeviceIds).toHaveBeenCalledWith(userStub.admin.id, '420', ['69']);
});
});
describe('bulkUploadCheck', () => {
it('should accept hex and base64 checksums', async () => {
const file1 = Buffer.from('d2947b871a706081be194569951b7db246907957', 'hex');

View File

@ -9,14 +9,12 @@ import {
AssetMediaStatus,
AssetRejectReason,
AssetUploadAction,
CheckExistingAssetsResponseDto,
} from 'src/dtos/asset-media-response.dto';
import {
AssetBulkUploadCheckDto,
AssetMediaCreateDto,
AssetMediaOptionsDto,
AssetMediaSize,
CheckExistingAssetsDto,
UploadFieldName,
} from 'src/dtos/asset-media.dto';
import { AssetDownloadOriginalDto } from 'src/dtos/asset.dto';
@ -251,18 +249,6 @@ export class AssetMediaService extends BaseService {
});
}
async checkExistingAssets(
auth: AuthDto,
checkExistingAssetsDto: CheckExistingAssetsDto,
): Promise<CheckExistingAssetsResponseDto> {
const existingIds = await this.assetRepository.getByDeviceIds(
auth.user.id,
checkExistingAssetsDto.deviceId,
checkExistingAssetsDto.deviceAssetIds,
);
return { existingIds };
}
async bulkUploadCheck(auth: AuthDto, dto: AssetBulkUploadCheckDto): Promise<AssetBulkUploadCheckResponseDto> {
const checksums: Buffer[] = dto.assets.map((asset) => fromChecksum(asset.checksum));
const results = await this.assetRepository.getByChecksums(auth.user.id, checksums);
@ -340,9 +326,6 @@ export class AssetMediaService extends BaseService {
checksumAlgorithm: ChecksumAlgorithm.sha1File,
originalPath: file.originalPath,
deviceAssetId: dto.deviceAssetId,
deviceId: dto.deviceId,
fileCreatedAt: dto.fileCreatedAt,
fileModifiedAt: dto.fileModifiedAt,
localDateTime: dto.fileCreatedAt,

View File

@ -685,20 +685,6 @@ describe(AssetService.name, () => {
});
});
describe('getUserAssetsByDeviceId', () => {
it('get assets by device id', async () => {
const assets = [AssetFactory.create(), AssetFactory.create()];
mocks.asset.getAllByDeviceId.mockResolvedValue(assets.map((asset) => asset.deviceAssetId));
const deviceId = 'device-id';
const result = await sut.getUserAssetsByDeviceId(authStub.user1, deviceId);
expect(result.length).toEqual(2);
expect(result).toEqual(assets.map((asset) => asset.deviceAssetId));
});
});
describe('upsertMetadata', () => {
it('should throw a bad request exception if duplicate keys are sent', async () => {
const asset = AssetFactory.create();

View File

@ -59,10 +59,6 @@ export class AssetService extends BaseService {
return mapStats(stats);
}
async getUserAssetsByDeviceId(auth: AuthDto, deviceId: string) {
return this.assetRepository.getAllByDeviceId(auth.user.id, deviceId);
}
async get(auth: AuthDto, id: string): Promise<AssetResponseDto | SanitizedAssetResponseDto> {
await this.requireAccess({ auth, permission: Permission.AssetRead, ids: [id] });

View File

@ -570,7 +570,6 @@ describe(LibraryService.name, () => {
ownerId: library.ownerId,
libraryId: library.id,
originalPath: '/data/user1/photo.jpg',
deviceId: 'Library Import',
type: AssetType.Image,
originalFileName: 'photo.jpg',
isExternal: true,

View File

@ -2,7 +2,7 @@ import { BadRequestException, Injectable } from '@nestjs/common';
import { Insertable } from 'kysely';
import { R_OK } from 'node:constants';
import { Stats } from 'node:fs';
import path, { basename, isAbsolute, parse } from 'node:path';
import path, { isAbsolute, parse } from 'node:path';
import picomatch from 'picomatch';
import { JOBS_LIBRARY_PAGINATION_SIZE } from 'src/constants';
import { StorageCore } from 'src/cores/storage.core';
@ -411,9 +411,6 @@ export class LibraryService extends BaseService {
fileCreatedAt: stat.mtime,
fileModifiedAt: stat.mtime,
localDateTime: stat.mtime,
// TODO: device asset id is deprecated, remove it
deviceAssetId: `${basename(assetPath)}`.replaceAll(/\s+/g, ''),
deviceId: 'Library Import',
type: mimeTypes.isVideo(assetPath) ? AssetType.Video : AssetType.Image,
originalFileName: parse(assetPath).base,
isExternal: true,

View File

@ -654,8 +654,6 @@ describe(MetadataService.name, () => {
expect(mocks.asset.create).toHaveBeenCalledWith({
checksum: expect.any(Buffer),
checksumAlgorithm: ChecksumAlgorithm.sha1File,
deviceAssetId: 'NONE',
deviceId: 'NONE',
fileCreatedAt: asset.fileCreatedAt,
fileModifiedAt: asset.fileModifiedAt,
id: motionAsset.id,
@ -708,8 +706,6 @@ describe(MetadataService.name, () => {
expect(mocks.asset.create).toHaveBeenCalledWith({
checksum: expect.any(Buffer),
checksumAlgorithm: ChecksumAlgorithm.sha1File,
deviceAssetId: 'NONE',
deviceId: 'NONE',
fileCreatedAt: asset.fileCreatedAt,
fileModifiedAt: asset.fileModifiedAt,
id: motionAsset.id,
@ -762,8 +758,6 @@ describe(MetadataService.name, () => {
expect(mocks.asset.create).toHaveBeenCalledWith({
checksum: expect.any(Buffer),
checksumAlgorithm: ChecksumAlgorithm.sha1File,
deviceAssetId: 'NONE',
deviceId: 'NONE',
fileCreatedAt: asset.fileCreatedAt,
fileModifiedAt: asset.fileModifiedAt,
id: motionAsset.id,

View File

@ -681,8 +681,6 @@ export class MetadataService extends BaseService {
originalPath: StorageCore.getAndroidMotionPath(asset, motionAssetId),
originalFileName: `${parse(asset.originalFileName).name}.mp4`,
visibility: AssetVisibility.Hidden,
deviceAssetId: 'NONE',
deviceId: 'NONE',
});
isNewMotionAsset = true;

View File

@ -351,8 +351,6 @@ export function searchAssetBuilder(kysely: Kysely<DB>, options: AssetSearchBuild
.where('asset_exif.rating', options.rating === null ? 'is' : '=', options.rating!),
)
.$if(!!options.checksum, (qb) => qb.where('asset.checksum', '=', options.checksum!))
.$if(!!options.deviceAssetId, (qb) => qb.where('asset.deviceAssetId', '=', options.deviceAssetId!))
.$if(!!options.deviceId, (qb) => qb.where('asset.deviceId', '=', options.deviceId!))
.$if(!!options.id, (qb) => qb.where('asset.id', '=', asUuid(options.id!)))
.$if(!!options.libraryId, (qb) => qb.where('asset.libraryId', '=', asUuid(options.libraryId!)))
.$if(!!options.userIds, (qb) => qb.where('asset.ownerId', '=', anyUuid(options.userIds!)))

View File

@ -21,8 +21,6 @@ const createAsset = (
width: 1920,
height: 1080,
createdAt: new Date().toISOString(),
deviceAssetId: 'device-asset-1',
deviceId: 'device-1',
ownerId: 'owner-1',
originalPath: '/path/to/asset',
originalFileName: 'asset.jpg',

View File

@ -54,8 +54,6 @@ export class AssetFactory {
status: AssetStatus.Active,
checksum: newSha1(),
checksumAlgorithm: ChecksumAlgorithm.sha1File,
deviceAssetId: '',
deviceId: '',
duplicateId: null,
duration: null,
fileCreatedAt: new Date(now++),

View File

@ -127,8 +127,6 @@ export const getForMetadataExtraction = (asset: ReturnType<AssetFactory['build']
id: asset.id,
checksum: asset.checksum,
checksumAlgorithm: asset.checksumAlgorithm,
deviceAssetId: asset.deviceAssetId,
deviceId: asset.deviceId,
fileCreatedAt: asset.fileCreatedAt,
fileModifiedAt: asset.fileModifiedAt,
isExternal: asset.isExternal,

View File

@ -549,8 +549,6 @@ const assetInsert = (asset: Partial<Insertable<AssetTable>> = {}) => {
const id = asset.id || newUuid();
const now = newDate();
const defaults: Insertable<AssetTable> = {
deviceAssetId: '',
deviceId: '',
originalFileName: '',
checksum: randomBytes(32),
checksumAlgorithm: ChecksumAlgorithm.sha1File,

View File

@ -52,8 +52,6 @@ describe(AssetService.name, () => {
sut.uploadAsset(
auth,
{
deviceId: 'some-id',
deviceAssetId: 'some-id',
fileModifiedAt: new Date(),
fileCreatedAt: new Date(),
assetData: Buffer.from('some data'),
@ -66,7 +64,7 @@ describe(AssetService.name, () => {
});
expect(ctx.getMock(EventRepository).emit).toHaveBeenCalledWith('AssetCreate', {
asset: expect.objectContaining({ deviceAssetId: 'some-id' }),
asset: expect.objectContaining({}),
});
});
@ -87,8 +85,6 @@ describe(AssetService.name, () => {
sut.uploadAsset(
auth,
{
deviceId: 'some-id',
deviceAssetId: 'some-id',
fileModifiedAt: new Date(),
fileCreatedAt: new Date(),
assetData: Buffer.from('some data'),
@ -125,8 +121,6 @@ describe(AssetService.name, () => {
const auth = factory.auth({ user: { id: user.id }, sharedLink });
const file = mediumFactory.uploadFile();
const uploadDto = {
deviceId: 'some-id',
deviceAssetId: 'some-id',
fileModifiedAt: new Date(),
fileCreatedAt: new Date(),
assetData: Buffer.from('some data'),
@ -166,8 +160,6 @@ describe(AssetService.name, () => {
const auth = factory.auth({ user: { id: user.id }, sharedLink });
const uploadDto = {
deviceId: 'some-id',
deviceAssetId: 'some-id',
fileModifiedAt: new Date(),
fileCreatedAt: new Date(),
assetData: Buffer.from('some data'),
@ -206,8 +198,6 @@ describe(AssetService.name, () => {
const auth = factory.auth({ user: { id: user.id }, sharedLink });
const uploadDto = {
deviceId: 'some-id',
deviceAssetId: 'some-id',
fileModifiedAt: new Date(),
fileCreatedAt: new Date(),
assetData: Buffer.from('some data'),
@ -248,8 +238,6 @@ describe(AssetService.name, () => {
const auth = factory.auth({ user: { id: user.id }, sharedLink });
const uploadDto = {
deviceId: 'some-id',
deviceAssetId: 'some-id',
fileModifiedAt: new Date(),
fileCreatedAt: new Date(),
assetData: Buffer.from('some data'),

View File

@ -15,12 +15,10 @@ export const newAssetRepositoryMock = (): Mocked<RepositoryInterface<AssetReposi
getByDayOfYear: vitest.fn(),
getByIds: vitest.fn().mockResolvedValue([]),
getByIdsWithAllRelationsButStacks: vitest.fn().mockResolvedValue([]),
getByDeviceIds: vitest.fn(),
getById: vitest.fn(),
getByChecksum: vitest.fn(),
getByChecksums: vitest.fn(),
getUploadAssetIdByChecksum: vitest.fn(),
getAllByDeviceId: vitest.fn(),
getLivePhotoCount: vitest.fn(),
getLibraryAssetCount: vitest.fn(),
updateAll: vitest.fn(),

View File

@ -110,7 +110,7 @@ export const fileUploadHandler = async ({
const deviceAssetId = getDeviceAssetId(file);
uploadAssetsStore.addItem({ id: deviceAssetId, file, albumId });
promises.push(
uploadExecutionQueue.addTask(() => fileUploader({ assetFile: file, deviceAssetId, albumId, isLockedAssets })),
uploadExecutionQueue.addTask(() => fileUploader({ deviceAssetId, assetFile: file, albumId, isLockedAssets })),
);
} else {
toastManager.warning(get(t)('unsupported_file_type', { values: { file: file.name, type: file.type } }), {
@ -132,6 +132,7 @@ type FileUploaderParams = {
albumId?: string;
replaceAssetId?: string;
isLockedAssets?: boolean;
// TODO rework the asset uploader and remove this
deviceAssetId: string;
};
@ -151,8 +152,6 @@ async function fileUploader({
try {
const formData = new FormData();
for (const [key, value] of Object.entries({
deviceAssetId,
deviceId: 'WEB',
fileCreatedAt,
fileModifiedAt: new Date(assetFile.lastModified).toISOString(),
isFavorite: 'false',

View File

@ -7,9 +7,7 @@ import { Sync } from 'factory.ts';
export const assetFactory = Sync.makeFactory<AssetResponseDto>({
id: Sync.each(() => faker.string.uuid()),
createdAt: Sync.each(() => faker.date.past().toISOString()),
deviceAssetId: Sync.each(() => faker.string.uuid()),
ownerId: Sync.each(() => faker.string.uuid()),
deviceId: '',
libraryId: Sync.each(() => faker.string.uuid()),
type: Sync.each(() => faker.helpers.enumValue(AssetTypeEnum)),
originalPath: Sync.each(() => faker.system.filePath()),