feat: expose createdAt in getAssetInfo (#21184)

* Expose createdAt in getAssetInfo

* Add missing createdAt fields
This commit is contained in:
Wingy 2025-08-25 11:27:21 -04:00 committed by GitHub
parent c2313f7a99
commit 5fb8d651ec
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 29 additions and 1 deletions

View file

@ -14,6 +14,7 @@ class AssetResponseDto {
/// Returns a new [AssetResponseDto] instance. /// Returns a new [AssetResponseDto] instance.
AssetResponseDto({ AssetResponseDto({
required this.checksum, required this.checksum,
required this.createdAt,
required this.deviceAssetId, required this.deviceAssetId,
required this.deviceId, required this.deviceId,
this.duplicateId, this.duplicateId,
@ -49,6 +50,9 @@ class AssetResponseDto {
/// base64 encoded sha1 hash /// base64 encoded sha1 hash
String checksum; String checksum;
/// The UTC timestamp when the asset was originally uploaded to Immich.
DateTime createdAt;
String deviceAssetId; String deviceAssetId;
String deviceId; String deviceId;
@ -142,6 +146,7 @@ class AssetResponseDto {
@override @override
bool operator ==(Object other) => identical(this, other) || other is AssetResponseDto && bool operator ==(Object other) => identical(this, other) || other is AssetResponseDto &&
other.checksum == checksum && other.checksum == checksum &&
other.createdAt == createdAt &&
other.deviceAssetId == deviceAssetId && other.deviceAssetId == deviceAssetId &&
other.deviceId == deviceId && other.deviceId == deviceId &&
other.duplicateId == duplicateId && other.duplicateId == duplicateId &&
@ -177,6 +182,7 @@ class AssetResponseDto {
int get hashCode => int get hashCode =>
// ignore: unnecessary_parenthesis // ignore: unnecessary_parenthesis
(checksum.hashCode) + (checksum.hashCode) +
(createdAt.hashCode) +
(deviceAssetId.hashCode) + (deviceAssetId.hashCode) +
(deviceId.hashCode) + (deviceId.hashCode) +
(duplicateId == null ? 0 : duplicateId!.hashCode) + (duplicateId == null ? 0 : duplicateId!.hashCode) +
@ -209,11 +215,12 @@ class AssetResponseDto {
(visibility.hashCode); (visibility.hashCode);
@override @override
String toString() => 'AssetResponseDto[checksum=$checksum, deviceAssetId=$deviceAssetId, deviceId=$deviceId, duplicateId=$duplicateId, duration=$duration, exifInfo=$exifInfo, fileCreatedAt=$fileCreatedAt, fileModifiedAt=$fileModifiedAt, hasMetadata=$hasMetadata, id=$id, isArchived=$isArchived, 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]'; String toString() => 'AssetResponseDto[checksum=$checksum, createdAt=$createdAt, deviceAssetId=$deviceAssetId, deviceId=$deviceId, duplicateId=$duplicateId, duration=$duration, exifInfo=$exifInfo, fileCreatedAt=$fileCreatedAt, fileModifiedAt=$fileModifiedAt, hasMetadata=$hasMetadata, id=$id, isArchived=$isArchived, 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]';
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final json = <String, dynamic>{}; final json = <String, dynamic>{};
json[r'checksum'] = this.checksum; json[r'checksum'] = this.checksum;
json[r'createdAt'] = this.createdAt.toUtc().toIso8601String();
json[r'deviceAssetId'] = this.deviceAssetId; json[r'deviceAssetId'] = this.deviceAssetId;
json[r'deviceId'] = this.deviceId; json[r'deviceId'] = this.deviceId;
if (this.duplicateId != null) { if (this.duplicateId != null) {
@ -293,6 +300,7 @@ class AssetResponseDto {
return AssetResponseDto( return AssetResponseDto(
checksum: mapValueOfType<String>(json, r'checksum')!, checksum: mapValueOfType<String>(json, r'checksum')!,
createdAt: mapDateTime(json, r'createdAt', r'')!,
deviceAssetId: mapValueOfType<String>(json, r'deviceAssetId')!, deviceAssetId: mapValueOfType<String>(json, r'deviceAssetId')!,
deviceId: mapValueOfType<String>(json, r'deviceId')!, deviceId: mapValueOfType<String>(json, r'deviceId')!,
duplicateId: mapValueOfType<String>(json, r'duplicateId'), duplicateId: mapValueOfType<String>(json, r'duplicateId'),
@ -371,6 +379,7 @@ class AssetResponseDto {
/// The list of required keys that must be present in a JSON. /// The list of required keys that must be present in a JSON.
static const requiredKeys = <String>{ static const requiredKeys = <String>{
'checksum', 'checksum',
'createdAt',
'deviceAssetId', 'deviceAssetId',
'deviceId', 'deviceId',
'duration', 'duration',

View file

@ -10720,6 +10720,12 @@
"description": "base64 encoded sha1 hash", "description": "base64 encoded sha1 hash",
"type": "string" "type": "string"
}, },
"createdAt": {
"description": "The UTC timestamp when the asset was originally uploaded to Immich.",
"example": "2024-01-15T20:30:00.000Z",
"format": "date-time",
"type": "string"
},
"deviceAssetId": { "deviceAssetId": {
"type": "string" "type": "string"
}, },
@ -10855,6 +10861,7 @@
}, },
"required": [ "required": [
"checksum", "checksum",
"createdAt",
"deviceAssetId", "deviceAssetId",
"deviceId", "deviceId",
"duration", "duration",

View file

@ -317,6 +317,8 @@ export type TagResponseDto = {
export type AssetResponseDto = { export type AssetResponseDto = {
/** base64 encoded sha1 hash */ /** base64 encoded sha1 hash */
checksum: string; checksum: string;
/** The UTC timestamp when the asset was originally uploaded to Immich. */
createdAt: string;
deviceAssetId: string; deviceAssetId: string;
deviceId: string; deviceId: string;
duplicateId?: string | null; duplicateId?: string | null;

View file

@ -37,6 +37,13 @@ export class SanitizedAssetResponseDto {
} }
export class AssetResponseDto extends SanitizedAssetResponseDto { export class AssetResponseDto extends SanitizedAssetResponseDto {
@ApiProperty({
type: 'string',
format: 'date-time',
description: 'The UTC timestamp when the asset was originally uploaded to Immich.',
example: '2024-01-15T20:30:00.000Z',
})
createdAt!: Date;
deviceAssetId!: string; deviceAssetId!: string;
deviceId!: string; deviceId!: string;
ownerId!: string; ownerId!: string;
@ -190,6 +197,7 @@ export function mapAsset(entity: MapAsset, options: AssetMapOptions = {}): Asset
return { return {
id: entity.id, id: entity.id,
createdAt: entity.createdAt,
deviceAssetId: entity.deviceAssetId, deviceAssetId: entity.deviceAssetId,
ownerId: entity.ownerId, ownerId: entity.ownerId,
owner: entity.owner ? mapUser(entity.owner) : undefined, owner: entity.owner ? mapUser(entity.owner) : undefined,

View file

@ -46,6 +46,7 @@ const assetInfo: ExifResponseDto = {
const assetResponse: AssetResponseDto = { const assetResponse: AssetResponseDto = {
id: 'id_1', id: 'id_1',
createdAt: today,
deviceAssetId: 'device_asset_id_1', deviceAssetId: 'device_asset_id_1',
ownerId: 'user_id_1', ownerId: 'user_id_1',
deviceId: 'device_id_1', deviceId: 'device_id_1',

View file

@ -6,6 +6,7 @@ import { Sync } from 'factory.ts';
export const assetFactory = Sync.makeFactory<AssetResponseDto>({ export const assetFactory = Sync.makeFactory<AssetResponseDto>({
id: Sync.each(() => faker.string.uuid()), id: Sync.each(() => faker.string.uuid()),
createdAt: Sync.each(() => faker.date.past().toISOString()),
deviceAssetId: Sync.each(() => faker.string.uuid()), deviceAssetId: Sync.each(() => faker.string.uuid()),
ownerId: Sync.each(() => faker.string.uuid()), ownerId: Sync.each(() => faker.string.uuid()),
deviceId: '', deviceId: '',