feat: asset metadata (#20446)

This commit is contained in:
Jason Rasmussen
2025-08-27 14:31:23 -04:00
committed by GitHub
parent 25a94bd117
commit 88072910da
37 changed files with 1999 additions and 21 deletions
+7
View File
@@ -1,6 +1,7 @@
import { ApiProperty } from '@nestjs/swagger';
import { Type } from 'class-transformer';
import { ArrayNotEmpty, IsArray, IsNotEmpty, IsString, ValidateNested } from 'class-validator';
import { AssetMetadataUpsertItemDto } from 'src/dtos/asset.dto';
import { AssetVisibility } from 'src/enum';
import { Optional, ValidateBoolean, ValidateDate, ValidateEnum, ValidateUUID } from 'src/validation';
@@ -64,6 +65,12 @@ export class AssetMediaCreateDto extends AssetMediaBase {
@ValidateUUID({ optional: true })
livePhotoVideoId?: string;
@Optional()
@IsArray()
@ValidateNested({ each: true })
@Type(() => AssetMetadataUpsertItemDto)
metadata!: AssetMetadataUpsertItemDto[];
@ApiProperty({ type: 'string', format: 'binary', required: false })
[UploadFieldName.SIDECAR_DATA]?: any;
}
+52 -1
View File
@@ -1,21 +1,25 @@
import { ApiProperty } from '@nestjs/swagger';
import { Type } from 'class-transformer';
import {
IsArray,
IsDateString,
IsInt,
IsLatitude,
IsLongitude,
IsNotEmpty,
IsObject,
IsPositive,
IsString,
IsTimeZone,
Max,
Min,
ValidateIf,
ValidateNested,
} from 'class-validator';
import { BulkIdsDto } from 'src/dtos/asset-ids.response.dto';
import { AssetType, AssetVisibility } from 'src/enum';
import { AssetMetadataKey, AssetType, AssetVisibility } from 'src/enum';
import { AssetStats } from 'src/repositories/asset.repository';
import { AssetMetadata, AssetMetadataItem } from 'src/types';
import { IsNotSiblingOf, Optional, ValidateBoolean, ValidateEnum, ValidateUUID } from 'src/validation';
export class DeviceIdDto {
@@ -135,6 +139,53 @@ export class AssetStatsResponseDto {
total!: number;
}
export class AssetMetadataRouteParams {
@ValidateUUID()
id!: string;
@ValidateEnum({ enum: AssetMetadataKey, name: 'AssetMetadataKey' })
key!: AssetMetadataKey;
}
export class AssetMetadataUpsertDto {
@IsArray()
@ValidateNested({ each: true })
@Type(() => AssetMetadataUpsertItemDto)
items!: AssetMetadataUpsertItemDto[];
}
export class AssetMetadataUpsertItemDto implements AssetMetadataItem {
@ValidateEnum({ enum: AssetMetadataKey, name: 'AssetMetadataKey' })
key!: AssetMetadataKey;
@IsObject()
@ValidateNested()
@Type((options) => {
switch (options?.object.key) {
case AssetMetadataKey.MobileApp: {
return AssetMetadataMobileAppDto;
}
default: {
return Object;
}
}
})
value!: AssetMetadata[AssetMetadataKey];
}
export class AssetMetadataMobileAppDto {
@IsString()
@Optional()
iCloudId?: string;
}
export class AssetMetadataResponseDto {
@ValidateEnum({ enum: AssetMetadataKey, name: 'AssetMetadataKey' })
key!: AssetMetadataKey;
value!: object;
updatedAt!: Date;
}
export const mapStats = (stats: AssetStats): AssetStatsResponseDto => {
return {
images: stats[AssetType.Image],
+18
View File
@@ -4,6 +4,7 @@ import { ArrayMaxSize, IsInt, IsPositive, IsString } from 'class-validator';
import { AssetResponseDto } from 'src/dtos/asset-response.dto';
import {
AlbumUserRole,
AssetMetadataKey,
AssetOrder,
AssetType,
AssetVisibility,
@@ -162,6 +163,21 @@ export class SyncAssetExifV1 {
fps!: number | null;
}
@ExtraModel()
export class SyncAssetMetadataV1 {
assetId!: string;
@ValidateEnum({ enum: AssetMetadataKey, name: 'AssetMetadataKey' })
key!: AssetMetadataKey;
value!: object;
}
@ExtraModel()
export class SyncAssetMetadataDeleteV1 {
assetId!: string;
@ValidateEnum({ enum: AssetMetadataKey, name: 'AssetMetadataKey' })
key!: AssetMetadataKey;
}
@ExtraModel()
export class SyncAlbumDeleteV1 {
albumId!: string;
@@ -328,6 +344,8 @@ export type SyncItem = {
[SyncEntityType.PartnerDeleteV1]: SyncPartnerDeleteV1;
[SyncEntityType.AssetV1]: SyncAssetV1;
[SyncEntityType.AssetDeleteV1]: SyncAssetDeleteV1;
[SyncEntityType.AssetMetadataV1]: SyncAssetMetadataV1;
[SyncEntityType.AssetMetadataDeleteV1]: SyncAssetMetadataDeleteV1;
[SyncEntityType.AssetExifV1]: SyncAssetExifV1;
[SyncEntityType.PartnerAssetV1]: SyncAssetV1;
[SyncEntityType.PartnerAssetBackfillV1]: SyncAssetV1;