Bläddra i källkod

refactor(server): change asset entity to date type (#2599)

* refactor(server): change asset entity to date type

* lower coverage threshold
Michel Heusschen 2 år sedan
förälder
incheckning
94d0705607

+ 3 - 3
mobile/lib/shared/models/asset.dart

@@ -15,9 +15,9 @@ class Asset {
   Asset.remote(AssetResponseDto remote)
       : remoteId = remote.id,
         isLocal = false,
-        fileCreatedAt = DateTime.parse(remote.fileCreatedAt),
-        fileModifiedAt = DateTime.parse(remote.fileModifiedAt),
-        updatedAt = DateTime.parse(remote.updatedAt),
+        fileCreatedAt = remote.fileCreatedAt,
+        fileModifiedAt = remote.fileModifiedAt,
+        updatedAt = remote.updatedAt,
         durationInSeconds = remote.duration.toDuration()?.inSeconds ?? 0,
         type = remote.type.toAssetType(),
         fileName = p.basename(remote.originalPath),

+ 4 - 4
mobile/openapi/doc/AssetApi.md

@@ -1476,8 +1476,8 @@ final assetType = ; // AssetTypeEnum |
 final assetData = BINARY_DATA_HERE; // MultipartFile | 
 final deviceAssetId = deviceAssetId_example; // String | 
 final deviceId = deviceId_example; // String | 
-final fileCreatedAt = fileCreatedAt_example; // String | 
-final fileModifiedAt = fileModifiedAt_example; // String | 
+final fileCreatedAt = 2013-10-20T19:20:30+01:00; // DateTime | 
+final fileModifiedAt = 2013-10-20T19:20:30+01:00; // DateTime | 
 final isFavorite = true; // bool | 
 final fileExtension = fileExtension_example; // String | 
 final key = key_example; // String | 
@@ -1503,8 +1503,8 @@ Name | Type | Description  | Notes
  **assetData** | **MultipartFile**|  | 
  **deviceAssetId** | **String**|  | 
  **deviceId** | **String**|  | 
- **fileCreatedAt** | **String**|  | 
- **fileModifiedAt** | **String**|  | 
+ **fileCreatedAt** | **DateTime**|  | 
+ **fileModifiedAt** | **DateTime**|  | 
  **isFavorite** | **bool**|  | 
  **fileExtension** | **String**|  | 
  **key** | **String**|  | [optional] 

+ 3 - 3
mobile/openapi/doc/AssetResponseDto.md

@@ -16,9 +16,9 @@ Name | Type | Description | Notes
 **originalPath** | **String** |  | 
 **originalFileName** | **String** |  | 
 **resized** | **bool** |  | 
-**fileCreatedAt** | **String** |  | 
-**fileModifiedAt** | **String** |  | 
-**updatedAt** | **String** |  | 
+**fileCreatedAt** | [**DateTime**](DateTime.md) |  | 
+**fileModifiedAt** | [**DateTime**](DateTime.md) |  | 
+**updatedAt** | [**DateTime**](DateTime.md) |  | 
 **isFavorite** | **bool** |  | 
 **isArchived** | **bool** |  | 
 **mimeType** | **String** |  | 

+ 6 - 6
mobile/openapi/lib/api/asset_api.dart

@@ -1405,9 +1405,9 @@ class AssetApi {
   ///
   /// * [String] deviceId (required):
   ///
-  /// * [String] fileCreatedAt (required):
+  /// * [DateTime] fileCreatedAt (required):
   ///
-  /// * [String] fileModifiedAt (required):
+  /// * [DateTime] fileModifiedAt (required):
   ///
   /// * [bool] isFavorite (required):
   ///
@@ -1424,7 +1424,7 @@ class AssetApi {
   /// * [bool] isVisible:
   ///
   /// * [String] duration:
-  Future<Response> uploadFileWithHttpInfo(AssetTypeEnum assetType, MultipartFile assetData, String deviceAssetId, String deviceId, String fileCreatedAt, String fileModifiedAt, bool isFavorite, String fileExtension, { String? key, MultipartFile? livePhotoData, MultipartFile? sidecarData, bool? isArchived, bool? isVisible, String? duration, }) async {
+  Future<Response> uploadFileWithHttpInfo(AssetTypeEnum assetType, MultipartFile assetData, String deviceAssetId, String deviceId, DateTime fileCreatedAt, DateTime fileModifiedAt, bool isFavorite, String fileExtension, { String? key, MultipartFile? livePhotoData, MultipartFile? sidecarData, bool? isArchived, bool? isVisible, String? duration, }) async {
     // ignore: prefer_const_declarations
     final path = r'/asset/upload';
 
@@ -1523,9 +1523,9 @@ class AssetApi {
   ///
   /// * [String] deviceId (required):
   ///
-  /// * [String] fileCreatedAt (required):
+  /// * [DateTime] fileCreatedAt (required):
   ///
-  /// * [String] fileModifiedAt (required):
+  /// * [DateTime] fileModifiedAt (required):
   ///
   /// * [bool] isFavorite (required):
   ///
@@ -1542,7 +1542,7 @@ class AssetApi {
   /// * [bool] isVisible:
   ///
   /// * [String] duration:
-  Future<AssetFileUploadResponseDto?> uploadFile(AssetTypeEnum assetType, MultipartFile assetData, String deviceAssetId, String deviceId, String fileCreatedAt, String fileModifiedAt, bool isFavorite, String fileExtension, { String? key, MultipartFile? livePhotoData, MultipartFile? sidecarData, bool? isArchived, bool? isVisible, String? duration, }) async {
+  Future<AssetFileUploadResponseDto?> uploadFile(AssetTypeEnum assetType, MultipartFile assetData, String deviceAssetId, String deviceId, DateTime fileCreatedAt, DateTime fileModifiedAt, bool isFavorite, String fileExtension, { String? key, MultipartFile? livePhotoData, MultipartFile? sidecarData, bool? isArchived, bool? isVisible, String? duration, }) async {
     final response = await uploadFileWithHttpInfo(assetType, assetData, deviceAssetId, deviceId, fileCreatedAt, fileModifiedAt, isFavorite, fileExtension,  key: key, livePhotoData: livePhotoData, sidecarData: sidecarData, isArchived: isArchived, isVisible: isVisible, duration: duration, );
     if (response.statusCode >= HttpStatus.badRequest) {
       throw ApiException(response.statusCode, await _decodeBodyBytes(response));

+ 9 - 9
mobile/openapi/lib/model/asset_response_dto.dart

@@ -52,11 +52,11 @@ class AssetResponseDto {
 
   bool resized;
 
-  String fileCreatedAt;
+  DateTime fileCreatedAt;
 
-  String fileModifiedAt;
+  DateTime fileModifiedAt;
 
-  String updatedAt;
+  DateTime updatedAt;
 
   bool isFavorite;
 
@@ -153,9 +153,9 @@ class AssetResponseDto {
       json[r'originalPath'] = this.originalPath;
       json[r'originalFileName'] = this.originalFileName;
       json[r'resized'] = this.resized;
-      json[r'fileCreatedAt'] = this.fileCreatedAt;
-      json[r'fileModifiedAt'] = this.fileModifiedAt;
-      json[r'updatedAt'] = this.updatedAt;
+      json[r'fileCreatedAt'] = this.fileCreatedAt.toUtc().toIso8601String();
+      json[r'fileModifiedAt'] = this.fileModifiedAt.toUtc().toIso8601String();
+      json[r'updatedAt'] = this.updatedAt.toUtc().toIso8601String();
       json[r'isFavorite'] = this.isFavorite;
       json[r'isArchived'] = this.isArchived;
     if (this.mimeType != null) {
@@ -212,9 +212,9 @@ class AssetResponseDto {
         originalPath: mapValueOfType<String>(json, r'originalPath')!,
         originalFileName: mapValueOfType<String>(json, r'originalFileName')!,
         resized: mapValueOfType<bool>(json, r'resized')!,
-        fileCreatedAt: mapValueOfType<String>(json, r'fileCreatedAt')!,
-        fileModifiedAt: mapValueOfType<String>(json, r'fileModifiedAt')!,
-        updatedAt: mapValueOfType<String>(json, r'updatedAt')!,
+        fileCreatedAt: mapDateTime(json, r'fileCreatedAt', '')!,
+        fileModifiedAt: mapDateTime(json, r'fileModifiedAt', '')!,
+        updatedAt: mapDateTime(json, r'updatedAt', '')!,
         isFavorite: mapValueOfType<bool>(json, r'isFavorite')!,
         isArchived: mapValueOfType<bool>(json, r'isArchived')!,
         mimeType: mapValueOfType<String>(json, r'mimeType'),

+ 1 - 1
mobile/openapi/test/asset_api_test.dart

@@ -158,7 +158,7 @@ void main() {
       // TODO
     });
 
-    //Future<AssetFileUploadResponseDto> uploadFile(AssetTypeEnum assetType, MultipartFile assetData, String deviceAssetId, String deviceId, String fileCreatedAt, String fileModifiedAt, bool isFavorite, String fileExtension, { String key, MultipartFile livePhotoData, MultipartFile sidecarData, bool isArchived, bool isVisible, String duration }) async
+    //Future<AssetFileUploadResponseDto> uploadFile(AssetTypeEnum assetType, MultipartFile assetData, String deviceAssetId, String deviceId, DateTime fileCreatedAt, DateTime fileModifiedAt, bool isFavorite, String fileExtension, { String key, MultipartFile livePhotoData, MultipartFile sidecarData, bool isArchived, bool isVisible, String duration }) async
     test('test uploadFile', () async {
       // TODO
     });

+ 3 - 3
mobile/openapi/test/asset_response_dto_test.dart

@@ -56,17 +56,17 @@ void main() {
       // TODO
     });
 
-    // String fileCreatedAt
+    // DateTime fileCreatedAt
     test('to test the property `fileCreatedAt`', () async {
       // TODO
     });
 
-    // String fileModifiedAt
+    // DateTime fileModifiedAt
     test('to test the property `fileModifiedAt`', () async {
       // TODO
     });
 
-    // String updatedAt
+    // DateTime updatedAt
     test('to test the property `updatedAt`', () async {
       // TODO
     });

+ 8 - 8
server/apps/immich/src/api-v1/asset/asset.service.spec.ts

@@ -37,8 +37,8 @@ const _getCreateAssetDto = (): CreateAssetDto => {
   createAssetDto.deviceAssetId = 'deviceAssetId';
   createAssetDto.deviceId = 'deviceId';
   createAssetDto.assetType = AssetType.OTHER;
-  createAssetDto.fileCreatedAt = '2022-06-19T23:41:36.910Z';
-  createAssetDto.fileModifiedAt = '2022-06-19T23:41:36.910Z';
+  createAssetDto.fileCreatedAt = new Date('2022-06-19T23:41:36.910Z');
+  createAssetDto.fileModifiedAt = new Date('2022-06-19T23:41:36.910Z');
   createAssetDto.isFavorite = false;
   createAssetDto.isArchived = false;
   createAssetDto.duration = '0:00:00.000000';
@@ -56,9 +56,9 @@ const _getAsset_1 = () => {
   asset_1.type = AssetType.VIDEO;
   asset_1.originalPath = 'fake_path/asset_1.jpeg';
   asset_1.resizePath = '';
-  asset_1.fileModifiedAt = '2022-06-19T23:41:36.910Z';
-  asset_1.fileCreatedAt = '2022-06-19T23:41:36.910Z';
-  asset_1.updatedAt = '2022-06-19T23:41:36.910Z';
+  asset_1.fileModifiedAt = new Date('2022-06-19T23:41:36.910Z');
+  asset_1.fileCreatedAt = new Date('2022-06-19T23:41:36.910Z');
+  asset_1.updatedAt = new Date('2022-06-19T23:41:36.910Z');
   asset_1.isFavorite = false;
   asset_1.isArchived = false;
   asset_1.mimeType = 'image/jpeg';
@@ -81,9 +81,9 @@ const _getAsset_2 = () => {
   asset_2.type = AssetType.VIDEO;
   asset_2.originalPath = 'fake_path/asset_2.jpeg';
   asset_2.resizePath = '';
-  asset_2.fileModifiedAt = '2022-06-19T23:41:36.910Z';
-  asset_2.fileCreatedAt = '2022-06-19T23:41:36.910Z';
-  asset_2.updatedAt = '2022-06-19T23:41:36.910Z';
+  asset_2.fileModifiedAt = new Date('2022-06-19T23:41:36.910Z');
+  asset_2.fileCreatedAt = new Date('2022-06-19T23:41:36.910Z');
+  asset_2.updatedAt = new Date('2022-06-19T23:41:36.910Z');
   asset_2.isFavorite = false;
   asset_2.isArchived = false;
   asset_2.mimeType = 'image/jpeg';

+ 2 - 2
server/apps/immich/src/api-v1/asset/dto/create-asset.dto.ts

@@ -16,10 +16,10 @@ export class CreateAssetDto {
   assetType!: AssetType;
 
   @IsNotEmpty()
-  fileCreatedAt!: string;
+  fileCreatedAt!: Date;
 
   @IsNotEmpty()
-  fileModifiedAt!: string;
+  fileModifiedAt!: Date;
 
   @IsNotEmpty()
   isFavorite!: boolean;

+ 3 - 3
server/apps/microservices/src/processors/metadata-extraction.processor.ts

@@ -214,7 +214,7 @@ export class MetadataExtractionProcessor {
     }
 
     await this.exifRepository.upsert(newExif, { conflictPaths: ['assetId'] });
-    await this.assetRepository.save({ id: asset.id, fileCreatedAt: fileCreatedAt?.toISOString() });
+    await this.assetRepository.save({ id: asset.id, fileCreatedAt: fileCreatedAt || undefined });
 
     return true;
   }
@@ -227,9 +227,9 @@ export class MetadataExtractionProcessor {
     const videoTags = data.format.tags;
     if (videoTags) {
       if (videoTags['com.apple.quicktime.creationdate']) {
-        fileCreatedAt = String(videoTags['com.apple.quicktime.creationdate']);
+        fileCreatedAt = new Date(videoTags['com.apple.quicktime.creationdate']);
       } else if (videoTags['creation_time']) {
-        fileCreatedAt = String(videoTags['creation_time']);
+        fileCreatedAt = new Date(videoTags['creation_time']);
       }
     }
 

+ 5 - 0
server/immich-openapi-specs.json

@@ -4450,12 +4450,15 @@
             "type": "boolean"
           },
           "fileCreatedAt": {
+            "format": "date-time",
             "type": "string"
           },
           "fileModifiedAt": {
+            "format": "date-time",
             "type": "string"
           },
           "updatedAt": {
+            "format": "date-time",
             "type": "string"
           },
           "isFavorite": {
@@ -5783,9 +5786,11 @@
             "type": "string"
           },
           "fileCreatedAt": {
+            "format": "date-time",
             "type": "string"
           },
           "fileModifiedAt": {
+            "format": "date-time",
             "type": "string"
           },
           "isFavorite": {

+ 2 - 2
server/libs/domain/src/asset/asset.repository.ts

@@ -15,8 +15,8 @@ export interface LivePhotoSearchOptions {
 
 export interface MapMarkerSearchOptions {
   isFavorite?: boolean;
-  fileCreatedBefore?: string;
-  fileCreatedAfter?: string;
+  fileCreatedBefore?: Date;
+  fileCreatedAfter?: Date;
 }
 
 export interface MapMarker {

+ 8 - 8
server/libs/domain/src/asset/dto/map-marker.dto.ts

@@ -1,7 +1,7 @@
 import { ApiProperty } from '@nestjs/swagger';
 import { toBoolean } from 'apps/immich/src/utils/transform.util';
-import { Transform } from 'class-transformer';
-import { IsBoolean, IsISO8601, IsOptional } from 'class-validator';
+import { Transform, Type } from 'class-transformer';
+import { IsBoolean, IsDate, IsOptional } from 'class-validator';
 
 export class MapMarkerDto {
   @ApiProperty()
@@ -10,13 +10,13 @@ export class MapMarkerDto {
   @Transform(toBoolean)
   isFavorite?: boolean;
 
-  @ApiProperty({ format: 'date-time' })
   @IsOptional()
-  @IsISO8601({ strict: true, strictSeparator: true })
-  fileCreatedAfter?: string;
+  @IsDate()
+  @Type(() => Date)
+  fileCreatedAfter?: Date;
 
-  @ApiProperty({ format: 'date-time' })
   @IsOptional()
-  @IsISO8601({ strict: true, strictSeparator: true })
-  fileCreatedBefore?: string;
+  @IsDate()
+  @Type(() => Date)
+  fileCreatedBefore?: Date;
 }

+ 3 - 3
server/libs/domain/src/asset/response-dto/asset-response.dto.ts

@@ -16,9 +16,9 @@ export class AssetResponseDto {
   originalPath!: string;
   originalFileName!: string;
   resized!: boolean;
-  fileCreatedAt!: string;
-  fileModifiedAt!: string;
-  updatedAt!: string;
+  fileCreatedAt!: Date;
+  fileModifiedAt!: Date;
+  updatedAt!: Date;
   isFavorite!: boolean;
   isArchived!: boolean;
   mimeType!: string | null;

+ 2 - 2
server/libs/domain/src/storage-template/storage-template.core.ts

@@ -107,7 +107,7 @@ export class StorageTemplateCore {
       this.render(
         template,
         {
-          fileCreatedAt: new Date().toISOString(),
+          fileCreatedAt: new Date(),
           originalPath: '/upload/test/IMG_123.jpg',
           type: AssetType.IMAGE,
         } as AssetEntity,
@@ -140,7 +140,7 @@ export class StorageTemplateCore {
       filetypefull: asset.type == AssetType.IMAGE ? 'IMAGE' : 'VIDEO',
     };
 
-    const dt = luxon.DateTime.fromISO(new Date(asset.fileCreatedAt).toISOString());
+    const dt = luxon.DateTime.fromJSDate(asset.fileCreatedAt);
 
     const dateTokens = [
       ...supportedYearTokens,

+ 31 - 31
server/libs/domain/test/fixtures.ts

@@ -140,8 +140,8 @@ export const assetEntityStub = {
     id: 'asset-id',
     originalFileName: 'asset_1.jpeg',
     deviceAssetId: 'device-asset-id',
-    fileModifiedAt: '2023-02-23T05:06:29.716Z',
-    fileCreatedAt: '2023-02-23T05:06:29.716Z',
+    fileModifiedAt: new Date('2023-02-23T05:06:29.716Z'),
+    fileCreatedAt: new Date('2023-02-23T05:06:29.716Z'),
     owner: userEntityStub.user1,
     ownerId: 'user-id',
     deviceId: 'device-id',
@@ -151,8 +151,8 @@ export const assetEntityStub = {
     type: AssetType.IMAGE,
     webpPath: null,
     encodedVideoPath: null,
-    createdAt: '2023-02-23T05:06:29.716Z',
-    updatedAt: '2023-02-23T05:06:29.716Z',
+    createdAt: new Date('2023-02-23T05:06:29.716Z'),
+    updatedAt: new Date('2023-02-23T05:06:29.716Z'),
     mimeType: null,
     isFavorite: true,
     isArchived: false,
@@ -168,8 +168,8 @@ export const assetEntityStub = {
   image: Object.freeze<AssetEntity>({
     id: 'asset-id',
     deviceAssetId: 'device-asset-id',
-    fileModifiedAt: '2023-02-23T05:06:29.716Z',
-    fileCreatedAt: '2023-02-23T05:06:29.716Z',
+    fileModifiedAt: new Date('2023-02-23T05:06:29.716Z'),
+    fileCreatedAt: new Date('2023-02-23T05:06:29.716Z'),
     owner: userEntityStub.user1,
     ownerId: 'user-id',
     deviceId: 'device-id',
@@ -179,8 +179,8 @@ export const assetEntityStub = {
     type: AssetType.IMAGE,
     webpPath: null,
     encodedVideoPath: null,
-    createdAt: '2023-02-23T05:06:29.716Z',
-    updatedAt: '2023-02-23T05:06:29.716Z',
+    createdAt: new Date('2023-02-23T05:06:29.716Z'),
+    updatedAt: new Date('2023-02-23T05:06:29.716Z'),
     mimeType: null,
     isFavorite: true,
     isArchived: false,
@@ -198,8 +198,8 @@ export const assetEntityStub = {
     id: 'asset-id',
     originalFileName: 'asset-id.ext',
     deviceAssetId: 'device-asset-id',
-    fileModifiedAt: '2023-02-23T05:06:29.716Z',
-    fileCreatedAt: '2023-02-23T05:06:29.716Z',
+    fileModifiedAt: new Date('2023-02-23T05:06:29.716Z'),
+    fileCreatedAt: new Date('2023-02-23T05:06:29.716Z'),
     owner: userEntityStub.user1,
     ownerId: 'user-id',
     deviceId: 'device-id',
@@ -209,8 +209,8 @@ export const assetEntityStub = {
     type: AssetType.VIDEO,
     webpPath: null,
     encodedVideoPath: null,
-    createdAt: '2023-02-23T05:06:29.716Z',
-    updatedAt: '2023-02-23T05:06:29.716Z',
+    createdAt: new Date('2023-02-23T05:06:29.716Z'),
+    updatedAt: new Date('2023-02-23T05:06:29.716Z'),
     mimeType: null,
     isFavorite: true,
     isArchived: false,
@@ -229,8 +229,8 @@ export const assetEntityStub = {
     ownerId: authStub.user1.id,
     type: AssetType.VIDEO,
     isVisible: false,
-    fileModifiedAt: '2022-06-19T23:41:36.910Z',
-    fileCreatedAt: '2022-06-19T23:41:36.910Z',
+    fileModifiedAt: new Date('2022-06-19T23:41:36.910Z'),
+    fileCreatedAt: new Date('2022-06-19T23:41:36.910Z'),
   } as AssetEntity),
 
   livePhotoStillAsset: Object.freeze({
@@ -240,15 +240,15 @@ export const assetEntityStub = {
     type: AssetType.IMAGE,
     livePhotoVideoId: 'live-photo-motion-asset',
     isVisible: true,
-    fileModifiedAt: '2022-06-19T23:41:36.910Z',
-    fileCreatedAt: '2022-06-19T23:41:36.910Z',
+    fileModifiedAt: new Date('2022-06-19T23:41:36.910Z'),
+    fileCreatedAt: new Date('2022-06-19T23:41:36.910Z'),
   } as AssetEntity),
 
   withLocation: Object.freeze<AssetEntity>({
     id: 'asset-with-favorite-id',
     deviceAssetId: 'device-asset-id',
-    fileModifiedAt: '2023-02-23T05:06:29.716Z',
-    fileCreatedAt: '2023-02-23T05:06:29.716Z',
+    fileModifiedAt: new Date('2023-02-23T05:06:29.716Z'),
+    fileCreatedAt: new Date('2023-02-23T05:06:29.716Z'),
     owner: userEntityStub.user1,
     ownerId: 'user-id',
     deviceId: 'device-id',
@@ -259,8 +259,8 @@ export const assetEntityStub = {
     type: AssetType.IMAGE,
     webpPath: null,
     encodedVideoPath: null,
-    createdAt: '2023-02-23T05:06:29.716Z',
-    updatedAt: '2023-02-23T05:06:29.716Z',
+    createdAt: new Date('2023-02-23T05:06:29.716Z'),
+    updatedAt: new Date('2023-02-23T05:06:29.716Z'),
     mimeType: null,
     isFavorite: false,
     isArchived: false,
@@ -280,8 +280,8 @@ export const assetEntityStub = {
   sidecar: Object.freeze<AssetEntity>({
     id: 'asset-id',
     deviceAssetId: 'device-asset-id',
-    fileModifiedAt: '2023-02-23T05:06:29.716Z',
-    fileCreatedAt: '2023-02-23T05:06:29.716Z',
+    fileModifiedAt: new Date('2023-02-23T05:06:29.716Z'),
+    fileCreatedAt: new Date('2023-02-23T05:06:29.716Z'),
     owner: userEntityStub.user1,
     ownerId: 'user-id',
     deviceId: 'device-id',
@@ -291,8 +291,8 @@ export const assetEntityStub = {
     type: AssetType.IMAGE,
     webpPath: null,
     encodedVideoPath: null,
-    createdAt: '2023-02-23T05:06:29.716Z',
-    updatedAt: '2023-02-23T05:06:29.716Z',
+    createdAt: new Date('2023-02-23T05:06:29.716Z'),
+    updatedAt: new Date('2023-02-23T05:06:29.716Z'),
     mimeType: null,
     isFavorite: true,
     isArchived: false,
@@ -447,9 +447,9 @@ const assetResponse: AssetResponseDto = {
   originalPath: 'fake_path/jpeg',
   originalFileName: 'asset_1.jpeg',
   resized: false,
-  fileModifiedAt: today.toISOString(),
-  fileCreatedAt: today.toISOString(),
-  updatedAt: today.toISOString(),
+  fileModifiedAt: today,
+  fileCreatedAt: today,
+  updatedAt: today,
   isFavorite: false,
   isArchived: false,
   mimeType: 'image/jpeg',
@@ -700,10 +700,10 @@ export const sharedLinkStub = {
           originalPath: 'fake_path/jpeg',
           resizePath: '',
           checksum: Buffer.from('file hash', 'utf8'),
-          fileModifiedAt: today.toISOString(),
-          fileCreatedAt: today.toISOString(),
-          createdAt: today.toISOString(),
-          updatedAt: today.toISOString(),
+          fileModifiedAt: today,
+          fileCreatedAt: today,
+          createdAt: today,
+          updatedAt: today,
           isFavorite: false,
           isArchived: false,
           mimeType: 'image/jpeg',

+ 4 - 4
server/libs/infra/src/entities/asset.entity.ts

@@ -55,16 +55,16 @@ export class AssetEntity {
   encodedVideoPath!: string | null;
 
   @CreateDateColumn({ type: 'timestamptz' })
-  createdAt!: string;
+  createdAt!: Date;
 
   @UpdateDateColumn({ type: 'timestamptz' })
-  updatedAt!: string;
+  updatedAt!: Date;
 
   @Column({ type: 'timestamptz' })
-  fileCreatedAt!: string;
+  fileCreatedAt!: Date;
 
   @Column({ type: 'timestamptz' })
-  fileModifiedAt!: string;
+  fileModifiedAt!: Date;
 
   @Column({ type: 'boolean', default: false })
   isFavorite!: boolean;

+ 1 - 1
server/package.json

@@ -141,7 +141,7 @@
       "./libs/domain/": {
         "branches": 80,
         "functions": 87,
-        "lines": 93.8,
+        "lines": 93.7,
         "statements": 93
       }
     },