feat: expose createdAt in getAssetInfo (#21184)
Some checks are pending
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
Docker / pre-job (push) Waiting to run
Docker / Re-Tag ML () (push) Blocked by required conditions
Docker / Re-Tag ML (-armnn) (push) Blocked by required conditions
Docker / Re-Tag ML (-cuda) (push) Blocked by required conditions
Docker / Re-Tag ML (-openvino) (push) Blocked by required conditions
Docker / Re-Tag ML (-rknn) (push) Blocked by required conditions
Docker / Re-Tag ML (-rocm) (push) Blocked by required conditions
Docker / Re-Tag Server () (push) Blocked by required conditions
Docker / Build and Push ML (armnn, linux/arm64, -armnn) (push) Blocked by required conditions
Docker / Build and Push ML (cpu, ) (push) Blocked by required conditions
Docker / Build and Push ML (cuda, linux/amd64, -cuda) (push) Blocked by required conditions
Docker / Build and Push ML (openvino, linux/amd64, -openvino) (push) Blocked by required conditions
Docker / Build and Push ML (rknn, linux/arm64, -rknn) (push) Blocked by required conditions
Docker / Build and Push ML (rocm, linux/amd64, {"linux/amd64": "mich"}, -rocm) (push) Blocked by required conditions
Docker / Build and Push Server (push) Blocked by required conditions
Docker / Docker Build & Push Server Success (push) Blocked by required conditions
Docker / Docker Build & Push ML Success (push) Blocked by required conditions
Docs build / pre-job (push) Waiting to run
Docs build / Docs Build (push) Blocked by required conditions
Static Code Analysis / pre-job (push) Waiting to run
Static Code Analysis / Run Dart Code Analysis (push) Blocked by required conditions
Static Code Analysis / zizmor (push) Waiting to run
Test / pre-job (push) Waiting to run
Test / Test & Lint Server (push) Blocked by required conditions
Test / Unit Test CLI (push) Blocked by required conditions
Test / Unit Test CLI (Windows) (push) Blocked by required conditions
Test / Lint Web (push) Blocked by required conditions
Test / Test Web (push) Blocked by required conditions
Test / Test i18n (push) Blocked by required conditions
Test / End-to-End Lint (push) Blocked by required conditions
Test / Medium Tests (Server) (push) Blocked by required conditions
Test / End-to-End Tests (Server & CLI) (ubuntu-24.04-arm) (push) Blocked by required conditions
Test / End-to-End Tests (Server & CLI) (ubuntu-latest) (push) Blocked by required conditions
Test / End-to-End Tests (Web) (ubuntu-24.04-arm) (push) Blocked by required conditions
Test / End-to-End Tests (Web) (ubuntu-latest) (push) Blocked by required conditions
Test / End-to-End Tests Success (push) Blocked by required conditions
Test / Unit Test Mobile (push) Blocked by required conditions
Test / Unit Test ML (push) Blocked by required conditions
Test / .github Files Formatting (push) Blocked by required conditions
Test / ShellCheck (push) Waiting to run
Test / OpenAPI Clients (push) Waiting to run
Test / SQL Schema Checks (push) Waiting to run

* 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
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: '',