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:
Zack Pollard 2023-02-20 01:50:27 +00:00 committed by GitHub
parent 5d3e8f17d1
commit d1ea6a897e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 140 additions and 101 deletions

View File

@ -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

View File

@ -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]

View File

@ -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 []]

View File

@ -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'),

View File

@ -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 [],

View File

@ -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

View File

@ -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

View File

@ -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 });
} }
} }

View File

@ -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",

View File

@ -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,

View File

@ -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,
}; };

View File

@ -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;
} }

View File

@ -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,

View File

@ -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',

View File

@ -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

View File

@ -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;
} }

View File

@ -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 {

View File

@ -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") `);
}
}

View File

@ -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`);
}
}

View File

@ -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") `);
}
}

View File

@ -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>}