mirror of
				https://github.com/immich-app/immich.git
				synced 2025-11-03 19:29:32 -05:00 
			
		
		
		
	chore(server): typeorm definitions fix part 3 (#1796)
* chore(server): tidy up exif typeorm entity definition * chore(server): tidy up shared link typeorm entity definition * chore(server): tidy up smart info typeorm entity definition * chore(server): tidy up tag typeorm entity definition * ci: add job that checks typeorm migrations are correct and up-to-date
This commit is contained in:
		
							parent
							
								
									5d3e8f17d1
								
							
						
					
					
						commit
						d1ea6a897e
					
				
							
								
								
									
										45
									
								
								.github/workflows/test.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										45
									
								
								.github/workflows/test.yml
									
									
									
									
										vendored
									
									
								
							@ -79,6 +79,51 @@ jobs:
 | 
				
			|||||||
          echo "Changed files: ${{ steps.verify-changed-files.outputs.changed_files }}"
 | 
					          echo "Changed files: ${{ steps.verify-changed-files.outputs.changed_files }}"
 | 
				
			||||||
          exit 1
 | 
					          exit 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  generated-typeorm-migrations-up-to-date:
 | 
				
			||||||
 | 
					    name: Check generated TypeORM migrations are up-to-date
 | 
				
			||||||
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
 | 
					    services:
 | 
				
			||||||
 | 
					      postgres:
 | 
				
			||||||
 | 
					        image: postgres
 | 
				
			||||||
 | 
					        env:
 | 
				
			||||||
 | 
					          POSTGRES_PASSWORD: postgres
 | 
				
			||||||
 | 
					          POSTGRES_USER: postgres
 | 
				
			||||||
 | 
					          POSTGRES_DB: immich
 | 
				
			||||||
 | 
					        options: >-
 | 
				
			||||||
 | 
					          --health-cmd pg_isready
 | 
				
			||||||
 | 
					          --health-interval 10s
 | 
				
			||||||
 | 
					          --health-timeout 5s
 | 
				
			||||||
 | 
					          --health-retries 5
 | 
				
			||||||
 | 
					        ports:
 | 
				
			||||||
 | 
					          - 5432:5432
 | 
				
			||||||
 | 
					    steps:
 | 
				
			||||||
 | 
					      - uses: actions/checkout@v3
 | 
				
			||||||
 | 
					      - name: Install server dependencies
 | 
				
			||||||
 | 
					        run: |
 | 
				
			||||||
 | 
					          cd server
 | 
				
			||||||
 | 
					          npm ci
 | 
				
			||||||
 | 
					      - name: Run existing migrations
 | 
				
			||||||
 | 
					        run: |
 | 
				
			||||||
 | 
					          cd server
 | 
				
			||||||
 | 
					          npm run typeorm:migrations:run
 | 
				
			||||||
 | 
					      - name: Generate new migrations
 | 
				
			||||||
 | 
					        continue-on-error: true
 | 
				
			||||||
 | 
					        run: |
 | 
				
			||||||
 | 
					          cd server
 | 
				
			||||||
 | 
					          npm run typeorm:migrations:generate ./libs/infra/src/db/migrations/TestMigration
 | 
				
			||||||
 | 
					      - name: Find file changes
 | 
				
			||||||
 | 
					        uses: tj-actions/verify-changed-files@v13.1
 | 
				
			||||||
 | 
					        id: verify-changed-files
 | 
				
			||||||
 | 
					        with:
 | 
				
			||||||
 | 
					          files: |
 | 
				
			||||||
 | 
					            server/libs/infra/src/db/migrations/
 | 
				
			||||||
 | 
					      - name: Verify files have not changed
 | 
				
			||||||
 | 
					        if: steps.verify-changed-files.outputs.files_changed == 'true'
 | 
				
			||||||
 | 
					        run: |
 | 
				
			||||||
 | 
					          echo "ERROR: Generated files not up to date!"
 | 
				
			||||||
 | 
					          echo "Changed files: ${{ steps.verify-changed-files.outputs.changed_files }}"
 | 
				
			||||||
 | 
					          exit 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  mobile-integration-tests:
 | 
					  mobile-integration-tests:
 | 
				
			||||||
    name: Run mobile end-to-end integration tests
 | 
					    name: Run mobile end-to-end integration tests
 | 
				
			||||||
    runs-on: macos-latest
 | 
					    runs-on: macos-latest
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										1
									
								
								mobile/openapi/doc/ExifResponseDto.md
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1
									
								
								mobile/openapi/doc/ExifResponseDto.md
									
									
									
										generated
									
									
									
								
							@ -8,7 +8,6 @@ import 'package:openapi/api.dart';
 | 
				
			|||||||
## Properties
 | 
					## Properties
 | 
				
			||||||
Name | Type | Description | Notes
 | 
					Name | Type | Description | Notes
 | 
				
			||||||
------------ | ------------- | ------------- | -------------
 | 
					------------ | ------------- | ------------- | -------------
 | 
				
			||||||
**id** | **int** |  | [optional] 
 | 
					 | 
				
			||||||
**fileSizeInByte** | **int** |  | [optional] 
 | 
					**fileSizeInByte** | **int** |  | [optional] 
 | 
				
			||||||
**make** | **String** |  | [optional] 
 | 
					**make** | **String** |  | [optional] 
 | 
				
			||||||
**model** | **String** |  | [optional] 
 | 
					**model** | **String** |  | [optional] 
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										1
									
								
								mobile/openapi/doc/SmartInfoResponseDto.md
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1
									
								
								mobile/openapi/doc/SmartInfoResponseDto.md
									
									
									
										generated
									
									
									
								
							@ -8,7 +8,6 @@ import 'package:openapi/api.dart';
 | 
				
			|||||||
## Properties
 | 
					## Properties
 | 
				
			||||||
Name | Type | Description | Notes
 | 
					Name | Type | Description | Notes
 | 
				
			||||||
------------ | ------------- | ------------- | -------------
 | 
					------------ | ------------- | ------------- | -------------
 | 
				
			||||||
**id** | **String** |  | [optional] 
 | 
					 | 
				
			||||||
**tags** | **List<String>** |  | [optional] [default to const []]
 | 
					**tags** | **List<String>** |  | [optional] [default to const []]
 | 
				
			||||||
**objects** | **List<String>** |  | [optional] [default to const []]
 | 
					**objects** | **List<String>** |  | [optional] [default to const []]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										13
									
								
								mobile/openapi/lib/model/exif_response_dto.dart
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										13
									
								
								mobile/openapi/lib/model/exif_response_dto.dart
									
									
									
										generated
									
									
									
								
							@ -13,7 +13,6 @@ part of openapi.api;
 | 
				
			|||||||
class ExifResponseDto {
 | 
					class ExifResponseDto {
 | 
				
			||||||
  /// Returns a new [ExifResponseDto] instance.
 | 
					  /// Returns a new [ExifResponseDto] instance.
 | 
				
			||||||
  ExifResponseDto({
 | 
					  ExifResponseDto({
 | 
				
			||||||
    this.id,
 | 
					 | 
				
			||||||
    this.fileSizeInByte,
 | 
					    this.fileSizeInByte,
 | 
				
			||||||
    this.make,
 | 
					    this.make,
 | 
				
			||||||
    this.model,
 | 
					    this.model,
 | 
				
			||||||
@ -35,8 +34,6 @@ class ExifResponseDto {
 | 
				
			|||||||
    this.country,
 | 
					    this.country,
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  int? id;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  int? fileSizeInByte;
 | 
					  int? fileSizeInByte;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  String? make;
 | 
					  String? make;
 | 
				
			||||||
@ -77,7 +74,6 @@ class ExifResponseDto {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  bool operator ==(Object other) => identical(this, other) || other is ExifResponseDto &&
 | 
					  bool operator ==(Object other) => identical(this, other) || other is ExifResponseDto &&
 | 
				
			||||||
     other.id == id &&
 | 
					 | 
				
			||||||
     other.fileSizeInByte == fileSizeInByte &&
 | 
					     other.fileSizeInByte == fileSizeInByte &&
 | 
				
			||||||
     other.make == make &&
 | 
					     other.make == make &&
 | 
				
			||||||
     other.model == model &&
 | 
					     other.model == model &&
 | 
				
			||||||
@ -101,7 +97,6 @@ class ExifResponseDto {
 | 
				
			|||||||
  @override
 | 
					  @override
 | 
				
			||||||
  int get hashCode =>
 | 
					  int get hashCode =>
 | 
				
			||||||
    // ignore: unnecessary_parenthesis
 | 
					    // ignore: unnecessary_parenthesis
 | 
				
			||||||
    (id == null ? 0 : id!.hashCode) +
 | 
					 | 
				
			||||||
    (fileSizeInByte == null ? 0 : fileSizeInByte!.hashCode) +
 | 
					    (fileSizeInByte == null ? 0 : fileSizeInByte!.hashCode) +
 | 
				
			||||||
    (make == null ? 0 : make!.hashCode) +
 | 
					    (make == null ? 0 : make!.hashCode) +
 | 
				
			||||||
    (model == null ? 0 : model!.hashCode) +
 | 
					    (model == null ? 0 : model!.hashCode) +
 | 
				
			||||||
@ -123,15 +118,10 @@ class ExifResponseDto {
 | 
				
			|||||||
    (country == null ? 0 : country!.hashCode);
 | 
					    (country == null ? 0 : country!.hashCode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  String toString() => 'ExifResponseDto[id=$id, fileSizeInByte=$fileSizeInByte, make=$make, model=$model, imageName=$imageName, exifImageWidth=$exifImageWidth, exifImageHeight=$exifImageHeight, orientation=$orientation, dateTimeOriginal=$dateTimeOriginal, modifyDate=$modifyDate, lensModel=$lensModel, fNumber=$fNumber, focalLength=$focalLength, iso=$iso, exposureTime=$exposureTime, latitude=$latitude, longitude=$longitude, city=$city, state=$state, country=$country]';
 | 
					  String toString() => 'ExifResponseDto[fileSizeInByte=$fileSizeInByte, make=$make, model=$model, imageName=$imageName, exifImageWidth=$exifImageWidth, exifImageHeight=$exifImageHeight, orientation=$orientation, dateTimeOriginal=$dateTimeOriginal, modifyDate=$modifyDate, lensModel=$lensModel, fNumber=$fNumber, focalLength=$focalLength, iso=$iso, exposureTime=$exposureTime, latitude=$latitude, longitude=$longitude, city=$city, state=$state, country=$country]';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Map<String, dynamic> toJson() {
 | 
					  Map<String, dynamic> toJson() {
 | 
				
			||||||
    final json = <String, dynamic>{};
 | 
					    final json = <String, dynamic>{};
 | 
				
			||||||
    if (this.id != null) {
 | 
					 | 
				
			||||||
      json[r'id'] = this.id;
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
      // json[r'id'] = null;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (this.fileSizeInByte != null) {
 | 
					    if (this.fileSizeInByte != null) {
 | 
				
			||||||
      json[r'fileSizeInByte'] = this.fileSizeInByte;
 | 
					      json[r'fileSizeInByte'] = this.fileSizeInByte;
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
@ -249,7 +239,6 @@ class ExifResponseDto {
 | 
				
			|||||||
      }());
 | 
					      }());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      return ExifResponseDto(
 | 
					      return ExifResponseDto(
 | 
				
			||||||
        id: mapValueOfType<int>(json, r'id'),
 | 
					 | 
				
			||||||
        fileSizeInByte: mapValueOfType<int>(json, r'fileSizeInByte'),
 | 
					        fileSizeInByte: mapValueOfType<int>(json, r'fileSizeInByte'),
 | 
				
			||||||
        make: mapValueOfType<String>(json, r'make'),
 | 
					        make: mapValueOfType<String>(json, r'make'),
 | 
				
			||||||
        model: mapValueOfType<String>(json, r'model'),
 | 
					        model: mapValueOfType<String>(json, r'model'),
 | 
				
			||||||
 | 
				
			|||||||
@ -13,46 +13,30 @@ part of openapi.api;
 | 
				
			|||||||
class SmartInfoResponseDto {
 | 
					class SmartInfoResponseDto {
 | 
				
			||||||
  /// Returns a new [SmartInfoResponseDto] instance.
 | 
					  /// Returns a new [SmartInfoResponseDto] instance.
 | 
				
			||||||
  SmartInfoResponseDto({
 | 
					  SmartInfoResponseDto({
 | 
				
			||||||
    this.id,
 | 
					 | 
				
			||||||
    this.tags = const [],
 | 
					    this.tags = const [],
 | 
				
			||||||
    this.objects = const [],
 | 
					    this.objects = const [],
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ///
 | 
					 | 
				
			||||||
  /// 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? id;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  List<String>? tags;
 | 
					  List<String>? tags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  List<String>? objects;
 | 
					  List<String>? objects;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  bool operator ==(Object other) => identical(this, other) || other is SmartInfoResponseDto &&
 | 
					  bool operator ==(Object other) => identical(this, other) || other is SmartInfoResponseDto &&
 | 
				
			||||||
     other.id == id &&
 | 
					 | 
				
			||||||
     other.tags == tags &&
 | 
					     other.tags == tags &&
 | 
				
			||||||
     other.objects == objects;
 | 
					     other.objects == objects;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  int get hashCode =>
 | 
					  int get hashCode =>
 | 
				
			||||||
    // ignore: unnecessary_parenthesis
 | 
					    // ignore: unnecessary_parenthesis
 | 
				
			||||||
    (id == null ? 0 : id!.hashCode) +
 | 
					 | 
				
			||||||
    (tags == null ? 0 : tags!.hashCode) +
 | 
					    (tags == null ? 0 : tags!.hashCode) +
 | 
				
			||||||
    (objects == null ? 0 : objects!.hashCode);
 | 
					    (objects == null ? 0 : objects!.hashCode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  String toString() => 'SmartInfoResponseDto[id=$id, tags=$tags, objects=$objects]';
 | 
					  String toString() => 'SmartInfoResponseDto[tags=$tags, objects=$objects]';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Map<String, dynamic> toJson() {
 | 
					  Map<String, dynamic> toJson() {
 | 
				
			||||||
    final json = <String, dynamic>{};
 | 
					    final json = <String, dynamic>{};
 | 
				
			||||||
    if (this.id != null) {
 | 
					 | 
				
			||||||
      json[r'id'] = this.id;
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
      // json[r'id'] = null;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (this.tags != null) {
 | 
					    if (this.tags != null) {
 | 
				
			||||||
      json[r'tags'] = this.tags;
 | 
					      json[r'tags'] = this.tags;
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
@ -85,7 +69,6 @@ class SmartInfoResponseDto {
 | 
				
			|||||||
      }());
 | 
					      }());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      return SmartInfoResponseDto(
 | 
					      return SmartInfoResponseDto(
 | 
				
			||||||
        id: mapValueOfType<String>(json, r'id'),
 | 
					 | 
				
			||||||
        tags: json[r'tags'] is List
 | 
					        tags: json[r'tags'] is List
 | 
				
			||||||
            ? (json[r'tags'] as List).cast<String>()
 | 
					            ? (json[r'tags'] as List).cast<String>()
 | 
				
			||||||
            : const [],
 | 
					            : const [],
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										5
									
								
								mobile/openapi/test/exif_response_dto_test.dart
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										5
									
								
								mobile/openapi/test/exif_response_dto_test.dart
									
									
									
										generated
									
									
									
								
							@ -16,11 +16,6 @@ void main() {
 | 
				
			|||||||
  // final instance = ExifResponseDto();
 | 
					  // final instance = ExifResponseDto();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  group('test ExifResponseDto', () {
 | 
					  group('test ExifResponseDto', () {
 | 
				
			||||||
    // int id
 | 
					 | 
				
			||||||
    test('to test the property `id`', () async {
 | 
					 | 
				
			||||||
      // TODO
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // int fileSizeInByte
 | 
					    // int fileSizeInByte
 | 
				
			||||||
    test('to test the property `fileSizeInByte`', () async {
 | 
					    test('to test the property `fileSizeInByte`', () async {
 | 
				
			||||||
      // TODO
 | 
					      // TODO
 | 
				
			||||||
 | 
				
			|||||||
@ -16,11 +16,6 @@ void main() {
 | 
				
			|||||||
  // final instance = SmartInfoResponseDto();
 | 
					  // final instance = SmartInfoResponseDto();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  group('test SmartInfoResponseDto', () {
 | 
					  group('test SmartInfoResponseDto', () {
 | 
				
			||||||
    // String id
 | 
					 | 
				
			||||||
    test('to test the property `id`', () async {
 | 
					 | 
				
			||||||
      // TODO
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // List<String> tags (default value: const [])
 | 
					    // List<String> tags (default value: const [])
 | 
				
			||||||
    test('to test the property `tags`', () async {
 | 
					    test('to test the property `tags`', () async {
 | 
				
			||||||
      // TODO
 | 
					      // TODO
 | 
				
			||||||
 | 
				
			|||||||
@ -253,7 +253,7 @@ export class MetadataExtractionProcessor {
 | 
				
			|||||||
    if (this.isGeocodeInitialized) {
 | 
					    if (this.isGeocodeInitialized) {
 | 
				
			||||||
      const { latitude, longitude } = job.data;
 | 
					      const { latitude, longitude } = job.data;
 | 
				
			||||||
      const { country, state, city } = await this.reverseGeocodeExif(latitude, longitude);
 | 
					      const { country, state, city } = await this.reverseGeocodeExif(latitude, longitude);
 | 
				
			||||||
      await this.exifRepository.update({ id: job.data.exifId }, { city, state, country });
 | 
					      await this.exifRepository.update({ assetId: job.data.assetId }, { city, state, country });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -3136,12 +3136,6 @@
 | 
				
			|||||||
      "ExifResponseDto": {
 | 
					      "ExifResponseDto": {
 | 
				
			||||||
        "type": "object",
 | 
					        "type": "object",
 | 
				
			||||||
        "properties": {
 | 
					        "properties": {
 | 
				
			||||||
          "id": {
 | 
					 | 
				
			||||||
            "type": "integer",
 | 
					 | 
				
			||||||
            "nullable": true,
 | 
					 | 
				
			||||||
            "default": null,
 | 
					 | 
				
			||||||
            "format": "int64"
 | 
					 | 
				
			||||||
          },
 | 
					 | 
				
			||||||
          "fileSizeInByte": {
 | 
					          "fileSizeInByte": {
 | 
				
			||||||
            "type": "integer",
 | 
					            "type": "integer",
 | 
				
			||||||
            "nullable": true,
 | 
					            "nullable": true,
 | 
				
			||||||
@ -3245,9 +3239,6 @@
 | 
				
			|||||||
      "SmartInfoResponseDto": {
 | 
					      "SmartInfoResponseDto": {
 | 
				
			||||||
        "type": "object",
 | 
					        "type": "object",
 | 
				
			||||||
        "properties": {
 | 
					        "properties": {
 | 
				
			||||||
          "id": {
 | 
					 | 
				
			||||||
            "type": "string"
 | 
					 | 
				
			||||||
          },
 | 
					 | 
				
			||||||
          "tags": {
 | 
					          "tags": {
 | 
				
			||||||
            "nullable": true,
 | 
					            "nullable": true,
 | 
				
			||||||
            "type": "array",
 | 
					            "type": "array",
 | 
				
			||||||
 | 
				
			|||||||
@ -2,8 +2,6 @@ import { ExifEntity } from '@app/infra/db/entities';
 | 
				
			|||||||
import { ApiProperty } from '@nestjs/swagger';
 | 
					import { ApiProperty } from '@nestjs/swagger';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export class ExifResponseDto {
 | 
					export class ExifResponseDto {
 | 
				
			||||||
  @ApiProperty({ type: 'integer', format: 'int64' })
 | 
					 | 
				
			||||||
  id?: number | null = null;
 | 
					 | 
				
			||||||
  make?: string | null = null;
 | 
					  make?: string | null = null;
 | 
				
			||||||
  model?: string | null = null;
 | 
					  model?: string | null = null;
 | 
				
			||||||
  imageName?: string | null = null;
 | 
					  imageName?: string | null = null;
 | 
				
			||||||
@ -29,7 +27,6 @@ export class ExifResponseDto {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
export function mapExif(entity: ExifEntity): ExifResponseDto {
 | 
					export function mapExif(entity: ExifEntity): ExifResponseDto {
 | 
				
			||||||
  return {
 | 
					  return {
 | 
				
			||||||
    id: entity.id,
 | 
					 | 
				
			||||||
    make: entity.make,
 | 
					    make: entity.make,
 | 
				
			||||||
    model: entity.model,
 | 
					    model: entity.model,
 | 
				
			||||||
    imageName: entity.imageName,
 | 
					    imageName: entity.imageName,
 | 
				
			||||||
 | 
				
			|||||||
@ -1,14 +1,12 @@
 | 
				
			|||||||
import { SmartInfoEntity } from '@app/infra/db/entities';
 | 
					import { SmartInfoEntity } from '@app/infra/db/entities';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export class SmartInfoResponseDto {
 | 
					export class SmartInfoResponseDto {
 | 
				
			||||||
  id?: string;
 | 
					 | 
				
			||||||
  tags?: string[] | null;
 | 
					  tags?: string[] | null;
 | 
				
			||||||
  objects?: string[] | null;
 | 
					  objects?: string[] | null;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function mapSmartInfo(entity: SmartInfoEntity): SmartInfoResponseDto {
 | 
					export function mapSmartInfo(entity: SmartInfoEntity): SmartInfoResponseDto {
 | 
				
			||||||
  return {
 | 
					  return {
 | 
				
			||||||
    id: entity.id,
 | 
					 | 
				
			||||||
    tags: entity.tags,
 | 
					    tags: entity.tags,
 | 
				
			||||||
    objects: entity.objects,
 | 
					    objects: entity.objects,
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
				
			|||||||
@ -25,7 +25,7 @@ export interface IVideoLengthExtractionProcessor {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface IReverseGeocodingProcessor {
 | 
					export interface IReverseGeocodingProcessor {
 | 
				
			||||||
  exifId: number;
 | 
					  assetId: string;
 | 
				
			||||||
  latitude: number;
 | 
					  latitude: number;
 | 
				
			||||||
  longitude: number;
 | 
					  longitude: number;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -119,7 +119,6 @@ export const assetEntityStub = {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const assetInfo: ExifResponseDto = {
 | 
					const assetInfo: ExifResponseDto = {
 | 
				
			||||||
  id: 1,
 | 
					 | 
				
			||||||
  make: 'camera-make',
 | 
					  make: 'camera-make',
 | 
				
			||||||
  model: 'camera-model',
 | 
					  model: 'camera-model',
 | 
				
			||||||
  imageName: 'fancy-image',
 | 
					  imageName: 'fancy-image',
 | 
				
			||||||
@ -155,7 +154,6 @@ const assetResponse: AssetResponseDto = {
 | 
				
			|||||||
  isFavorite: false,
 | 
					  isFavorite: false,
 | 
				
			||||||
  mimeType: 'image/jpeg',
 | 
					  mimeType: 'image/jpeg',
 | 
				
			||||||
  smartInfo: {
 | 
					  smartInfo: {
 | 
				
			||||||
    id: 'should-be-a-number',
 | 
					 | 
				
			||||||
    tags: [],
 | 
					    tags: [],
 | 
				
			||||||
    objects: ['a', 'b', 'c'],
 | 
					    objects: ['a', 'b', 'c'],
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
@ -391,7 +389,6 @@ export const sharedLinkStub = {
 | 
				
			|||||||
          isFavorite: false,
 | 
					          isFavorite: false,
 | 
				
			||||||
          mimeType: 'image/jpeg',
 | 
					          mimeType: 'image/jpeg',
 | 
				
			||||||
          smartInfo: {
 | 
					          smartInfo: {
 | 
				
			||||||
            id: 'should-be-a-number',
 | 
					 | 
				
			||||||
            assetId: 'id_1',
 | 
					            assetId: 'id_1',
 | 
				
			||||||
            tags: [],
 | 
					            tags: [],
 | 
				
			||||||
            objects: ['a', 'b', 'c'],
 | 
					            objects: ['a', 'b', 'c'],
 | 
				
			||||||
@ -405,7 +402,6 @@ export const sharedLinkStub = {
 | 
				
			|||||||
          livePhotoVideoId: null,
 | 
					          livePhotoVideoId: null,
 | 
				
			||||||
          exifInfo: {
 | 
					          exifInfo: {
 | 
				
			||||||
            livePhotoCID: null,
 | 
					            livePhotoCID: null,
 | 
				
			||||||
            id: 1,
 | 
					 | 
				
			||||||
            assetId: 'id_1',
 | 
					            assetId: 'id_1',
 | 
				
			||||||
            description: 'description',
 | 
					            description: 'description',
 | 
				
			||||||
            exifImageWidth: 500,
 | 
					            exifImageWidth: 500,
 | 
				
			||||||
 | 
				
			|||||||
@ -1,20 +1,19 @@
 | 
				
			|||||||
import { Index, JoinColumn, OneToOne } from 'typeorm';
 | 
					import { Index, JoinColumn, OneToOne, PrimaryColumn } from 'typeorm';
 | 
				
			||||||
import { Column } from 'typeorm/decorator/columns/Column';
 | 
					import { Column } from 'typeorm/decorator/columns/Column';
 | 
				
			||||||
import { PrimaryGeneratedColumn } from 'typeorm/decorator/columns/PrimaryGeneratedColumn';
 | 
					 | 
				
			||||||
import { Entity } from 'typeorm/decorator/entity/Entity';
 | 
					import { Entity } from 'typeorm/decorator/entity/Entity';
 | 
				
			||||||
import { AssetEntity } from './asset.entity';
 | 
					import { AssetEntity } from './asset.entity';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Entity('exif')
 | 
					@Entity('exif')
 | 
				
			||||||
export class ExifEntity {
 | 
					export class ExifEntity {
 | 
				
			||||||
  @PrimaryGeneratedColumn()
 | 
					  @OneToOne(() => AssetEntity, { onDelete: 'CASCADE', nullable: true })
 | 
				
			||||||
  id!: number;
 | 
					  @JoinColumn()
 | 
				
			||||||
 | 
					  asset?: AssetEntity;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @Index({ unique: true })
 | 
					  @PrimaryColumn()
 | 
				
			||||||
  @Column({ type: 'uuid' })
 | 
					 | 
				
			||||||
  assetId!: string;
 | 
					  assetId!: string;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /* General info */
 | 
					  /* General info */
 | 
				
			||||||
  @Column({ type: 'text', nullable: true, default: '' })
 | 
					  @Column({ type: 'text', default: '' })
 | 
				
			||||||
  description!: string; // or caption
 | 
					  description!: string; // or caption
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @Column({ type: 'integer', nullable: true })
 | 
					  @Column({ type: 'integer', nullable: true })
 | 
				
			||||||
@ -83,10 +82,6 @@ export class ExifEntity {
 | 
				
			|||||||
  @Column({ type: 'float8', nullable: true })
 | 
					  @Column({ type: 'float8', nullable: true })
 | 
				
			||||||
  fps?: number | null;
 | 
					  fps?: number | null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @OneToOne(() => AssetEntity, { onDelete: 'CASCADE', nullable: true })
 | 
					 | 
				
			||||||
  @JoinColumn({ name: 'assetId', referencedColumnName: 'id' })
 | 
					 | 
				
			||||||
  asset?: AssetEntity;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  @Index('exif_text_searchable', { synchronize: false })
 | 
					  @Index('exif_text_searchable', { synchronize: false })
 | 
				
			||||||
  @Column({
 | 
					  @Column({
 | 
				
			||||||
    type: 'tsvector',
 | 
					    type: 'tsvector',
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,13 @@
 | 
				
			|||||||
import { Column, Entity, Index, ManyToMany, ManyToOne, PrimaryGeneratedColumn, Unique } from 'typeorm';
 | 
					import {
 | 
				
			||||||
 | 
					  Column,
 | 
				
			||||||
 | 
					  CreateDateColumn,
 | 
				
			||||||
 | 
					  Entity,
 | 
				
			||||||
 | 
					  Index,
 | 
				
			||||||
 | 
					  ManyToMany,
 | 
				
			||||||
 | 
					  ManyToOne,
 | 
				
			||||||
 | 
					  PrimaryGeneratedColumn,
 | 
				
			||||||
 | 
					  Unique,
 | 
				
			||||||
 | 
					} from 'typeorm';
 | 
				
			||||||
import { AlbumEntity } from './album.entity';
 | 
					import { AlbumEntity } from './album.entity';
 | 
				
			||||||
import { AssetEntity } from './asset.entity';
 | 
					import { AssetEntity } from './asset.entity';
 | 
				
			||||||
import { UserEntity } from './user.entity';
 | 
					import { UserEntity } from './user.entity';
 | 
				
			||||||
@ -25,7 +34,7 @@ export class SharedLinkEntity {
 | 
				
			|||||||
  @Column()
 | 
					  @Column()
 | 
				
			||||||
  type!: SharedLinkType;
 | 
					  type!: SharedLinkType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @Column({ type: 'timestamptz' })
 | 
					  @CreateDateColumn({ type: 'timestamptz' })
 | 
				
			||||||
  createdAt!: string;
 | 
					  createdAt!: string;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @Column({ type: 'timestamptz', nullable: true })
 | 
					  @Column({ type: 'timestamptz', nullable: true })
 | 
				
			||||||
@ -56,5 +65,3 @@ export enum SharedLinkType {
 | 
				
			|||||||
   */
 | 
					   */
 | 
				
			||||||
  INDIVIDUAL = 'INDIVIDUAL',
 | 
					  INDIVIDUAL = 'INDIVIDUAL',
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
// npm run typeorm -- migration:generate ./libs/infra/src/db/AddMorePermissionToSharedLink -d ./libs/infra/src/db/config/database.config.ts
 | 
					 | 
				
			||||||
 | 
				
			|||||||
@ -1,13 +1,13 @@
 | 
				
			|||||||
import { Column, Entity, Index, JoinColumn, OneToOne, PrimaryGeneratedColumn } from 'typeorm';
 | 
					import { Column, Entity, JoinColumn, OneToOne, PrimaryColumn } from 'typeorm';
 | 
				
			||||||
import { AssetEntity } from './asset.entity';
 | 
					import { AssetEntity } from './asset.entity';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Entity('smart_info')
 | 
					@Entity('smart_info')
 | 
				
			||||||
export class SmartInfoEntity {
 | 
					export class SmartInfoEntity {
 | 
				
			||||||
  @PrimaryGeneratedColumn()
 | 
					  @OneToOne(() => AssetEntity, { onDelete: 'CASCADE', nullable: true })
 | 
				
			||||||
  id!: string;
 | 
					  @JoinColumn({ name: 'assetId', referencedColumnName: 'id' })
 | 
				
			||||||
 | 
					  asset?: AssetEntity;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @Index({ unique: true })
 | 
					  @PrimaryColumn()
 | 
				
			||||||
  @Column({ type: 'uuid' })
 | 
					 | 
				
			||||||
  assetId!: string;
 | 
					  assetId!: string;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @Column({ type: 'text', array: true, nullable: true })
 | 
					  @Column({ type: 'text', array: true, nullable: true })
 | 
				
			||||||
@ -15,8 +15,4 @@ export class SmartInfoEntity {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  @Column({ type: 'text', array: true, nullable: true })
 | 
					  @Column({ type: 'text', array: true, nullable: true })
 | 
				
			||||||
  objects!: string[] | null;
 | 
					  objects!: string[] | null;
 | 
				
			||||||
 | 
					 | 
				
			||||||
  @OneToOne(() => AssetEntity, { onDelete: 'CASCADE', nullable: true })
 | 
					 | 
				
			||||||
  @JoinColumn({ name: 'assetId', referencedColumnName: 'id' })
 | 
					 | 
				
			||||||
  asset?: AssetEntity;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -14,6 +14,9 @@ export class TagEntity {
 | 
				
			|||||||
  @Column()
 | 
					  @Column()
 | 
				
			||||||
  name!: string;
 | 
					  name!: string;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @ManyToOne(() => UserEntity, (user) => user.tags)
 | 
				
			||||||
 | 
					  user!: UserEntity;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @Column()
 | 
					  @Column()
 | 
				
			||||||
  userId!: string;
 | 
					  userId!: string;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -22,9 +25,6 @@ export class TagEntity {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  @ManyToMany(() => AssetEntity, (asset) => asset.tags)
 | 
					  @ManyToMany(() => AssetEntity, (asset) => asset.tags)
 | 
				
			||||||
  assets!: AssetEntity[];
 | 
					  assets!: AssetEntity[];
 | 
				
			||||||
 | 
					 | 
				
			||||||
  @ManyToOne(() => UserEntity, (user) => user.tags)
 | 
					 | 
				
			||||||
  user!: UserEntity;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export enum TagType {
 | 
					export enum TagType {
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					import { MigrationInterface, QueryRunner } from "typeorm";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export class ExifEntityDefinitionFixes1676848629119 implements MigrationInterface {
 | 
				
			||||||
 | 
					    name = 'ExifEntityDefinitionFixes1676848629119'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public async up(queryRunner: QueryRunner): Promise<void> {
 | 
				
			||||||
 | 
					        await queryRunner.query(`ALTER TABLE "exif" ALTER COLUMN "description" SET NOT NULL`);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        await queryRunner.query(`DROP INDEX "public"."IDX_c0117fdbc50b917ef9067740c4"`);
 | 
				
			||||||
 | 
					        await queryRunner.query(`ALTER TABLE "exif" DROP CONSTRAINT "PK_28663352d85078ad0046dafafaa"`);
 | 
				
			||||||
 | 
					        await queryRunner.query(`ALTER TABLE "exif" DROP COLUMN "id"`);
 | 
				
			||||||
 | 
					        await queryRunner.query(`ALTER TABLE "exif" DROP CONSTRAINT "FK_c0117fdbc50b917ef9067740c44"`);
 | 
				
			||||||
 | 
					        await queryRunner.query(`ALTER TABLE "exif" ADD CONSTRAINT "PK_c0117fdbc50b917ef9067740c44" PRIMARY KEY ("assetId")`);
 | 
				
			||||||
 | 
					        await queryRunner.query(`ALTER TABLE "exif" ADD CONSTRAINT "FK_c0117fdbc50b917ef9067740c44" FOREIGN KEY ("assetId") REFERENCES "assets"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public async down(queryRunner: QueryRunner): Promise<void> {
 | 
				
			||||||
 | 
					        await queryRunner.query(`ALTER TABLE "exif" ALTER COLUMN "description" DROP NOT NULL`);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        await queryRunner.query(`ALTER TABLE "exif" DROP CONSTRAINT "FK_c0117fdbc50b917ef9067740c44"`);
 | 
				
			||||||
 | 
					        await queryRunner.query(`ALTER TABLE "exif" DROP CONSTRAINT "PK_c0117fdbc50b917ef9067740c44"`);
 | 
				
			||||||
 | 
					        await queryRunner.query(`ALTER TABLE "exif" ADD CONSTRAINT "FK_c0117fdbc50b917ef9067740c44" FOREIGN KEY ("assetId") REFERENCES "assets"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
 | 
				
			||||||
 | 
					        await queryRunner.query(`ALTER TABLE "exif" ADD "id" SERIAL NOT NULL`);
 | 
				
			||||||
 | 
					        await queryRunner.query(`ALTER TABLE "exif" ADD CONSTRAINT "PK_28663352d85078ad0046dafafaa" PRIMARY KEY ("id")`);
 | 
				
			||||||
 | 
					        await queryRunner.query(`CREATE UNIQUE INDEX "IDX_c0117fdbc50b917ef9067740c4" ON "exif" ("assetId") `);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					import { MigrationInterface, QueryRunner } from "typeorm";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export class SharedLinkEntityDefinitionFixes1676848694786 implements MigrationInterface {
 | 
				
			||||||
 | 
					    name = 'SharedLinkEntityDefinitionFixes1676848694786'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public async up(queryRunner: QueryRunner): Promise<void> {
 | 
				
			||||||
 | 
					        await queryRunner.query(`ALTER TABLE "shared_links" ALTER COLUMN "createdAt" SET DEFAULT now()`);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public async down(queryRunner: QueryRunner): Promise<void> {
 | 
				
			||||||
 | 
					        await queryRunner.query(`ALTER TABLE "shared_links" ALTER COLUMN "createdAt" DROP DEFAULT`);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					import { MigrationInterface, QueryRunner } from "typeorm";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export class SmartInfoEntityDefinitionFixes1676852143506 implements MigrationInterface {
 | 
				
			||||||
 | 
					    name = 'SmartInfoEntityDefinitionFixes1676852143506'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public async up(queryRunner: QueryRunner): Promise<void> {
 | 
				
			||||||
 | 
					        await queryRunner.query(`DROP INDEX "public"."IDX_5e3753aadd956110bf3ec0244a"`);
 | 
				
			||||||
 | 
					        await queryRunner.query(`ALTER TABLE "smart_info" DROP CONSTRAINT "PK_0beace66440e9713f5c40470e46"`);
 | 
				
			||||||
 | 
					        await queryRunner.query(`ALTER TABLE "smart_info" DROP COLUMN "id"`);
 | 
				
			||||||
 | 
					        await queryRunner.query(`ALTER TABLE "smart_info" DROP CONSTRAINT "FK_5e3753aadd956110bf3ec0244ac"`);
 | 
				
			||||||
 | 
					        await queryRunner.query(`ALTER TABLE "smart_info" ADD CONSTRAINT "PK_5e3753aadd956110bf3ec0244ac" PRIMARY KEY ("assetId")`);
 | 
				
			||||||
 | 
					        await queryRunner.query(`ALTER TABLE "smart_info" ADD CONSTRAINT "FK_5e3753aadd956110bf3ec0244ac" FOREIGN KEY ("assetId") REFERENCES "assets"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public async down(queryRunner: QueryRunner): Promise<void> {
 | 
				
			||||||
 | 
					        await queryRunner.query(`ALTER TABLE "smart_info" DROP CONSTRAINT "FK_5e3753aadd956110bf3ec0244ac"`);
 | 
				
			||||||
 | 
					        await queryRunner.query(`ALTER TABLE "smart_info" DROP CONSTRAINT "PK_5e3753aadd956110bf3ec0244ac"`);
 | 
				
			||||||
 | 
					        await queryRunner.query(`ALTER TABLE "smart_info" ADD CONSTRAINT "FK_5e3753aadd956110bf3ec0244ac" FOREIGN KEY ("assetId") REFERENCES "assets"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
 | 
				
			||||||
 | 
					        await queryRunner.query(`ALTER TABLE "smart_info" ADD "id" SERIAL NOT NULL`);
 | 
				
			||||||
 | 
					        await queryRunner.query(`ALTER TABLE "smart_info" ADD CONSTRAINT "PK_0beace66440e9713f5c40470e46" PRIMARY KEY ("id")`);
 | 
				
			||||||
 | 
					        await queryRunner.query(`CREATE UNIQUE INDEX "IDX_5e3753aadd956110bf3ec0244a" ON "smart_info" ("assetId") `);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										12
									
								
								web/src/api/open-api/api.ts
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										12
									
								
								web/src/api/open-api/api.ts
									
									
									
										generated
									
									
									
								
							@ -1054,12 +1054,6 @@ export interface EditSharedLinkDto {
 | 
				
			|||||||
 * @interface ExifResponseDto
 | 
					 * @interface ExifResponseDto
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export interface ExifResponseDto {
 | 
					export interface ExifResponseDto {
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * 
 | 
					 | 
				
			||||||
     * @type {number}
 | 
					 | 
				
			||||||
     * @memberof ExifResponseDto
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    'id'?: number | null;
 | 
					 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * 
 | 
					     * 
 | 
				
			||||||
     * @type {number}
 | 
					     * @type {number}
 | 
				
			||||||
@ -1730,12 +1724,6 @@ export interface SignUpDto {
 | 
				
			|||||||
 * @interface SmartInfoResponseDto
 | 
					 * @interface SmartInfoResponseDto
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export interface SmartInfoResponseDto {
 | 
					export interface SmartInfoResponseDto {
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * 
 | 
					 | 
				
			||||||
     * @type {string}
 | 
					 | 
				
			||||||
     * @memberof SmartInfoResponseDto
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    'id'?: string;
 | 
					 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * 
 | 
					     * 
 | 
				
			||||||
     * @type {Array<string>}
 | 
					     * @type {Array<string>}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user