refactor: database types (#19624)

This commit is contained in:
Jason Rasmussen 2025-06-30 13:19:16 -04:00 committed by GitHub
parent 09cbc5d3f4
commit e60bc3c304
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
99 changed files with 518 additions and 889 deletions

View file

@ -21,7 +21,7 @@ import { AlbumAuditTable } from 'src/schema/tables/album-audit.table';
import { AlbumUserAuditTable } from 'src/schema/tables/album-user-audit.table';
import { AlbumUserTable } from 'src/schema/tables/album-user.table';
import { AlbumTable } from 'src/schema/tables/album.table';
import { APIKeyTable } from 'src/schema/tables/api-key.table';
import { ApiKeyTable } from 'src/schema/tables/api-key.table';
import { AssetAuditTable } from 'src/schema/tables/asset-audit.table';
import { AssetFaceTable } from 'src/schema/tables/asset-face.table';
import { AssetFileTable } from 'src/schema/tables/asset-files.table';
@ -51,11 +51,12 @@ import { SessionSyncCheckpointTable } from 'src/schema/tables/sync-checkpoint.ta
import { SystemMetadataTable } from 'src/schema/tables/system-metadata.table';
import { TagAssetTable } from 'src/schema/tables/tag-asset.table';
import { TagClosureTable } from 'src/schema/tables/tag-closure.table';
import { TagTable } from 'src/schema/tables/tag.table';
import { UserAuditTable } from 'src/schema/tables/user-audit.table';
import { UserMetadataTable } from 'src/schema/tables/user-metadata.table';
import { UserTable } from 'src/schema/tables/user.table';
import { VersionHistoryTable } from 'src/schema/tables/version-history.table';
import { Database, Extensions } from 'src/sql-tools';
import { Database, Extensions, Generated, Int8 } from 'src/sql-tools';
@Extensions(['uuid-ossp', 'unaccent', 'cube', 'earthdistance', 'pg_trgm', 'plpgsql'])
@Database({ name: 'immich' })
@ -68,7 +69,7 @@ export class ImmichDatabase {
AlbumUserAuditTable,
AlbumUserTable,
AlbumTable,
APIKeyTable,
ApiKeyTable,
AssetAuditTable,
AssetFaceTable,
AssetJobStatusTable,
@ -96,6 +97,7 @@ export class ImmichDatabase {
StackTable,
SessionSyncCheckpointTable,
SystemMetadataTable,
TagTable,
TagAssetTable,
TagClosureTable,
UserAuditTable,
@ -122,3 +124,55 @@ export class ImmichDatabase {
enum = [assets_status_enum, asset_face_source_type, asset_visibility_enum];
}
export interface Migrations {
id: Generated<number>;
name: string;
timestamp: Int8;
}
export interface DB {
activity: ActivityTable;
albums: AlbumTable;
albums_audit: AlbumAuditTable;
albums_assets_assets: AlbumAssetTable;
album_assets_audit: AlbumAssetAuditTable;
albums_shared_users_users: AlbumUserTable;
album_users_audit: AlbumUserAuditTable;
api_keys: ApiKeyTable;
asset_faces: AssetFaceTable;
asset_files: AssetFileTable;
asset_job_status: AssetJobStatusTable;
asset_stack: StackTable;
assets: AssetTable;
assets_audit: AssetAuditTable;
audit: AuditTable;
exif: ExifTable;
face_search: FaceSearchTable;
geodata_places: GeodataPlacesTable;
libraries: LibraryTable;
memories: MemoryTable;
memories_audit: MemoryAuditTable;
memories_assets_assets: MemoryAssetTable;
memory_assets_audit: MemoryAssetAuditTable;
migrations: Migrations;
notifications: NotificationTable;
move_history: MoveTable;
naturalearth_countries: NaturalEarthCountriesTable;
partners_audit: PartnerAuditTable;
partners: PartnerTable;
person: PersonTable;
sessions: SessionTable;
session_sync_checkpoints: SessionSyncCheckpointTable;
shared_link__asset: SharedLinkAssetTable;
shared_links: SharedLinkTable;
smart_search: SmartSearchTable;
system_metadata: SystemMetadataTable;
tag_asset: TagAssetTable;
tags: TagTable;
tags_closure: TagClosureTable;
user_metadata: UserMetadataTable;
users: UserTable;
users_audit: UserAuditTable;
version_history: VersionHistoryTable;
}

View file

@ -7,9 +7,11 @@ import {
Column,
CreateDateColumn,
ForeignKeyColumn,
Generated,
Index,
PrimaryGeneratedColumn,
Table,
Timestamp,
UpdateDateColumn,
} from 'src/sql-tools';
@ -27,13 +29,13 @@ import {
})
export class ActivityTable {
@PrimaryGeneratedColumn()
id!: string;
id!: Generated<string>;
@CreateDateColumn()
createdAt!: Date;
createdAt!: Generated<Timestamp>;
@UpdateDateColumn()
updatedAt!: Date;
updatedAt!: Generated<Timestamp>;
@ForeignKeyColumn(() => AlbumTable, { onDelete: 'CASCADE', onUpdate: 'CASCADE' })
albumId!: string;
@ -48,8 +50,8 @@ export class ActivityTable {
comment!: string | null;
@Column({ type: 'boolean', default: false })
isLiked!: boolean;
isLiked!: Generated<boolean>;
@UpdateIdColumn({ indexName: 'IDX_activity_update_id' })
updateId!: string;
updateId!: Generated<string>;
}

View file

@ -1,11 +1,11 @@
import { PrimaryGeneratedUuidV7Column } from 'src/decorators';
import { AlbumTable } from 'src/schema/tables/album.table';
import { Column, CreateDateColumn, ForeignKeyColumn, Table } from 'src/sql-tools';
import { Column, CreateDateColumn, ForeignKeyColumn, Generated, Table, Timestamp } from 'src/sql-tools';
@Table('album_assets_audit')
export class AlbumAssetAuditTable {
@PrimaryGeneratedUuidV7Column()
id!: string;
id!: Generated<string>;
@ForeignKeyColumn(() => AlbumTable, {
type: 'uuid',
@ -19,5 +19,5 @@ export class AlbumAssetAuditTable {
assetId!: string;
@CreateDateColumn({ default: () => 'clock_timestamp()', indexName: 'IDX_album_assets_audit_deleted_at' })
deletedAt!: Date;
deletedAt!: Generated<Timestamp>;
}

View file

@ -2,7 +2,15 @@ import { UpdatedAtTrigger, UpdateIdColumn } from 'src/decorators';
import { album_assets_delete_audit } from 'src/schema/functions';
import { AlbumTable } from 'src/schema/tables/album.table';
import { AssetTable } from 'src/schema/tables/asset.table';
import { AfterDeleteTrigger, CreateDateColumn, ForeignKeyColumn, Table, UpdateDateColumn } from 'src/sql-tools';
import {
AfterDeleteTrigger,
CreateDateColumn,
ForeignKeyColumn,
Generated,
Table,
Timestamp,
UpdateDateColumn,
} from 'src/sql-tools';
@Table({ name: 'albums_assets_assets', primaryConstraintName: 'PK_c67bc36fa845fb7b18e0e398180' })
@UpdatedAtTrigger('album_assets_updated_at')
@ -21,11 +29,11 @@ export class AlbumAssetTable {
assetsId!: string;
@CreateDateColumn()
createdAt!: Date;
createdAt!: Generated<Timestamp>;
@UpdateDateColumn()
updatedAt!: Date;
updatedAt!: Generated<Timestamp>;
@UpdateIdColumn({ indexName: 'IDX_album_assets_update_id' })
updateId!: string;
updateId!: Generated<string>;
}

View file

@ -1,10 +1,10 @@
import { PrimaryGeneratedUuidV7Column } from 'src/decorators';
import { Column, CreateDateColumn, Table } from 'src/sql-tools';
import { Column, CreateDateColumn, Generated, Table, Timestamp } from 'src/sql-tools';
@Table('albums_audit')
export class AlbumAuditTable {
@PrimaryGeneratedUuidV7Column()
id!: string;
id!: Generated<string>;
@Column({ type: 'uuid', indexName: 'IDX_albums_audit_album_id' })
albumId!: string;
@ -13,5 +13,5 @@ export class AlbumAuditTable {
userId!: string;
@CreateDateColumn({ default: () => 'clock_timestamp()', indexName: 'IDX_albums_audit_deleted_at' })
deletedAt!: Date;
deletedAt!: Generated<Timestamp>;
}

View file

@ -1,10 +1,10 @@
import { PrimaryGeneratedUuidV7Column } from 'src/decorators';
import { Column, CreateDateColumn, Table } from 'src/sql-tools';
import { Column, CreateDateColumn, Generated, Table, Timestamp } from 'src/sql-tools';
@Table('album_users_audit')
export class AlbumUserAuditTable {
@PrimaryGeneratedUuidV7Column()
id!: string;
id!: Generated<string>;
@Column({ type: 'uuid', indexName: 'IDX_album_users_audit_album_id' })
albumId!: string;
@ -13,5 +13,5 @@ export class AlbumUserAuditTable {
userId!: string;
@CreateDateColumn({ default: () => 'clock_timestamp()', indexName: 'IDX_album_users_audit_deleted_at' })
deletedAt!: Date;
deletedAt!: Generated<Timestamp>;
}

View file

@ -9,8 +9,10 @@ import {
Column,
CreateDateColumn,
ForeignKeyColumn,
Generated,
Index,
Table,
Timestamp,
UpdateDateColumn,
} from 'src/sql-tools';
@ -50,17 +52,17 @@ export class AlbumUserTable {
usersId!: string;
@Column({ type: 'character varying', default: AlbumUserRole.EDITOR })
role!: AlbumUserRole;
role!: Generated<AlbumUserRole>;
@CreateIdColumn({ indexName: 'IDX_album_users_create_id' })
createId?: string;
createId!: Generated<string>;
@CreateDateColumn()
createdAt!: Date;
createdAt!: Generated<Timestamp>;
@UpdateIdColumn({ indexName: 'IDX_album_users_update_id' })
updateId?: string;
updateId!: Generated<string>;
@UpdateDateColumn()
updatedAt!: Date;
updatedAt!: Generated<Timestamp>;
}

View file

@ -9,8 +9,10 @@ import {
CreateDateColumn,
DeleteDateColumn,
ForeignKeyColumn,
Generated,
PrimaryGeneratedColumn,
Table,
Timestamp,
UpdateDateColumn,
} from 'src/sql-tools';
@ -25,16 +27,16 @@ import {
})
export class AlbumTable {
@PrimaryGeneratedColumn()
id!: string;
id!: Generated<string>;
@ForeignKeyColumn(() => UserTable, { onDelete: 'CASCADE', onUpdate: 'CASCADE', nullable: false })
ownerId!: string;
@Column({ default: 'Untitled Album' })
albumName!: string;
albumName!: Generated<string>;
@CreateDateColumn()
createdAt!: Date;
createdAt!: Generated<Timestamp>;
@ForeignKeyColumn(() => AssetTable, {
nullable: true,
@ -42,23 +44,23 @@ export class AlbumTable {
onUpdate: 'CASCADE',
comment: 'Asset ID to be used as thumbnail',
})
albumThumbnailAssetId!: string;
albumThumbnailAssetId!: string | null;
@UpdateDateColumn()
updatedAt!: Date;
updatedAt!: Generated<Timestamp>;
@Column({ type: 'text', default: '' })
description!: string;
description!: Generated<string>;
@DeleteDateColumn()
deletedAt!: Date | null;
deletedAt!: Timestamp | null;
@Column({ type: 'boolean', default: true })
isActivityEnabled!: boolean;
isActivityEnabled!: Generated<boolean>;
@Column({ default: AssetOrder.DESC })
order!: AssetOrder;
order!: Generated<AssetOrder>;
@UpdateIdColumn({ indexName: 'IDX_albums_update_id' })
updateId?: string;
updateId!: Generated<string>;
}

View file

@ -5,14 +5,19 @@ import {
Column,
CreateDateColumn,
ForeignKeyColumn,
Generated,
PrimaryGeneratedColumn,
Table,
Timestamp,
UpdateDateColumn,
} from 'src/sql-tools';
@Table('api_keys')
@UpdatedAtTrigger('api_keys_updated_at')
export class APIKeyTable {
export class ApiKeyTable {
@PrimaryGeneratedColumn()
id!: Generated<string>;
@Column()
name!: string;
@ -23,17 +28,14 @@ export class APIKeyTable {
userId!: string;
@CreateDateColumn()
createdAt!: Date;
createdAt!: Generated<Timestamp>;
@UpdateDateColumn()
updatedAt!: Date;
@PrimaryGeneratedColumn()
id!: string;
updatedAt!: Generated<Timestamp>;
@Column({ array: true, type: 'character varying' })
permissions!: Permission[];
@UpdateIdColumn({ indexName: 'IDX_api_keys_update_id' })
updateId?: string;
updateId!: Generated<string>;
}

View file

@ -1,10 +1,10 @@
import { PrimaryGeneratedUuidV7Column } from 'src/decorators';
import { Column, CreateDateColumn, Table } from 'src/sql-tools';
import { Column, CreateDateColumn, Generated, Table, Timestamp } from 'src/sql-tools';
@Table('assets_audit')
export class AssetAuditTable {
@PrimaryGeneratedUuidV7Column()
id!: string;
id!: Generated<string>;
@Column({ type: 'uuid', indexName: 'IDX_assets_audit_asset_id' })
assetId!: string;
@ -13,5 +13,5 @@ export class AssetAuditTable {
ownerId!: string;
@CreateDateColumn({ default: () => 'clock_timestamp()', indexName: 'IDX_assets_audit_deleted_at' })
deletedAt!: Date;
deletedAt!: Generated<Timestamp>;
}

View file

@ -2,12 +2,24 @@ import { SourceType } from 'src/enum';
import { asset_face_source_type } from 'src/schema/enums';
import { AssetTable } from 'src/schema/tables/asset.table';
import { PersonTable } from 'src/schema/tables/person.table';
import { Column, DeleteDateColumn, ForeignKeyColumn, Index, PrimaryGeneratedColumn, Table } from 'src/sql-tools';
import {
Column,
DeleteDateColumn,
ForeignKeyColumn,
Generated,
Index,
PrimaryGeneratedColumn,
Table,
Timestamp,
} from 'src/sql-tools';
@Table({ name: 'asset_faces' })
@Index({ name: 'IDX_asset_faces_assetId_personId', columns: ['assetId', 'personId'] })
@Index({ columns: ['personId', 'assetId'] })
export class AssetFaceTable {
@PrimaryGeneratedColumn()
id!: Generated<string>;
@ForeignKeyColumn(() => AssetTable, {
onDelete: 'CASCADE',
onUpdate: 'CASCADE',
@ -26,29 +38,26 @@ export class AssetFaceTable {
personId!: string | null;
@Column({ default: 0, type: 'integer' })
imageWidth!: number;
imageWidth!: Generated<number>;
@Column({ default: 0, type: 'integer' })
imageHeight!: number;
imageHeight!: Generated<number>;
@Column({ default: 0, type: 'integer' })
boundingBoxX1!: number;
boundingBoxX1!: Generated<number>;
@Column({ default: 0, type: 'integer' })
boundingBoxY1!: number;
boundingBoxY1!: Generated<number>;
@Column({ default: 0, type: 'integer' })
boundingBoxX2!: number;
boundingBoxX2!: Generated<number>;
@Column({ default: 0, type: 'integer' })
boundingBoxY2!: number;
@PrimaryGeneratedColumn()
id!: string;
boundingBoxY2!: Generated<number>;
@Column({ default: SourceType.MACHINE_LEARNING, enum: asset_face_source_type })
sourceType!: SourceType;
sourceType!: Generated<SourceType>;
@DeleteDateColumn()
deletedAt!: Date | null;
deletedAt!: Timestamp | null;
}

View file

@ -5,8 +5,10 @@ import {
Column,
CreateDateColumn,
ForeignKeyColumn,
Generated,
PrimaryGeneratedColumn,
Table,
Timestamp,
Unique,
UpdateDateColumn,
} from 'src/sql-tools';
@ -16,20 +18,20 @@ import {
@UpdatedAtTrigger('asset_files_updated_at')
export class AssetFileTable {
@PrimaryGeneratedColumn()
id!: string;
id!: Generated<string>;
@ForeignKeyColumn(() => AssetTable, {
onDelete: 'CASCADE',
onUpdate: 'CASCADE',
indexName: 'IDX_asset_files_assetId',
})
assetId?: string;
assetId!: string;
@CreateDateColumn()
createdAt!: Date;
createdAt!: Generated<Timestamp>;
@UpdateDateColumn()
updatedAt!: Date;
updatedAt!: Generated<Timestamp>;
@Column()
type!: AssetFileType;
@ -38,5 +40,5 @@ export class AssetFileTable {
path!: string;
@UpdateIdColumn({ indexName: 'IDX_asset_files_update_id' })
updateId?: string;
updateId!: Generated<string>;
}

View file

@ -1,5 +1,5 @@
import { AssetTable } from 'src/schema/tables/asset.table';
import { Column, ForeignKeyColumn, Table } from 'src/sql-tools';
import { Column, ForeignKeyColumn, Table, Timestamp } from 'src/sql-tools';
@Table('asset_job_status')
export class AssetJobStatusTable {
@ -7,17 +7,17 @@ export class AssetJobStatusTable {
assetId!: string;
@Column({ type: 'timestamp with time zone', nullable: true })
facesRecognizedAt!: Date | null;
facesRecognizedAt!: Timestamp | null;
@Column({ type: 'timestamp with time zone', nullable: true })
metadataExtractedAt!: Date | null;
metadataExtractedAt!: Timestamp | null;
@Column({ type: 'timestamp with time zone', nullable: true })
duplicatesDetectedAt!: Date | null;
duplicatesDetectedAt!: Timestamp | null;
@Column({ type: 'timestamp with time zone', nullable: true })
previewAt!: Date | null;
previewAt!: Timestamp | null;
@Column({ type: 'timestamp with time zone', nullable: true })
thumbnailAt!: Date | null;
thumbnailAt!: Timestamp | null;
}

View file

@ -11,9 +11,11 @@ import {
CreateDateColumn,
DeleteDateColumn,
ForeignKeyColumn,
Generated,
Index,
PrimaryGeneratedColumn,
Table,
Timestamp,
UpdateDateColumn,
} from 'src/sql-tools';
import { ASSET_CHECKSUM_CONSTRAINT } from 'src/utils/database';
@ -60,7 +62,7 @@ import { ASSET_CHECKSUM_CONSTRAINT } from 'src/utils/database';
// For all assets, each originalpath must be unique per user and library
export class AssetTable {
@PrimaryGeneratedColumn()
id!: string;
id!: Generated<string>;
@Column()
deviceAssetId!: string;
@ -78,13 +80,13 @@ export class AssetTable {
originalPath!: string;
@Column({ type: 'timestamp with time zone', indexName: 'idx_asset_file_created_at' })
fileCreatedAt!: Date;
fileCreatedAt!: Timestamp;
@Column({ type: 'timestamp with time zone' })
fileModifiedAt!: Date;
fileModifiedAt!: Timestamp;
@Column({ type: 'boolean', default: false })
isFavorite!: boolean;
isFavorite!: Generated<boolean>;
@Column({ type: 'character varying', nullable: true })
duration!: string | null;
@ -99,10 +101,10 @@ export class AssetTable {
livePhotoVideoId!: string | null;
@UpdateDateColumn()
updatedAt!: Date;
updatedAt!: Generated<Timestamp>;
@CreateDateColumn()
createdAt!: Date;
createdAt!: Generated<Timestamp>;
@Column({ index: true })
originalFileName!: string;
@ -114,32 +116,32 @@ export class AssetTable {
thumbhash!: Buffer | null;
@Column({ type: 'boolean', default: false })
isOffline!: boolean;
isOffline!: Generated<boolean>;
@ForeignKeyColumn(() => LibraryTable, { onDelete: 'CASCADE', onUpdate: 'CASCADE', nullable: true })
libraryId?: string | null;
libraryId!: string | null;
@Column({ type: 'boolean', default: false })
isExternal!: boolean;
isExternal!: Generated<boolean>;
@DeleteDateColumn()
deletedAt!: Date | null;
deletedAt!: Timestamp | null;
@Column({ type: 'timestamp with time zone' })
localDateTime!: Date;
localDateTime!: Timestamp;
@ForeignKeyColumn(() => StackTable, { nullable: true, onDelete: 'SET NULL', onUpdate: 'CASCADE' })
stackId?: string | null;
stackId!: string | null;
@Column({ type: 'uuid', nullable: true, indexName: 'IDX_assets_duplicateId' })
duplicateId!: string | null;
@Column({ enum: assets_status_enum, default: AssetStatus.ACTIVE })
status!: AssetStatus;
status!: Generated<AssetStatus>;
@UpdateIdColumn({ indexName: 'IDX_assets_update_id' })
updateId?: string;
updateId!: Generated<string>;
@Column({ enum: asset_visibility_enum, default: AssetVisibility.TIMELINE })
visibility!: AssetVisibility;
visibility!: Generated<AssetVisibility>;
}

View file

@ -1,11 +1,11 @@
import { DatabaseAction, EntityType } from 'src/enum';
import { Column, CreateDateColumn, Index, PrimaryColumn, Table } from 'src/sql-tools';
import { Column, CreateDateColumn, Generated, Index, PrimaryColumn, Table, Timestamp } from 'src/sql-tools';
@Table('audit')
@Index({ name: 'IDX_ownerId_createdAt', columns: ['ownerId', 'createdAt'] })
export class AuditTable {
@PrimaryColumn({ type: 'serial', synchronize: false })
id!: number;
id!: Generated<number>;
@Column()
entityType!: EntityType;
@ -20,5 +20,5 @@ export class AuditTable {
ownerId!: string;
@CreateDateColumn()
createdAt!: Date;
createdAt!: Generated<Timestamp>;
}

View file

@ -1,6 +1,6 @@
import { UpdatedAtTrigger, UpdateIdColumn } from 'src/decorators';
import { AssetTable } from 'src/schema/tables/asset.table';
import { Column, ForeignKeyColumn, Table, UpdateDateColumn } from 'src/sql-tools';
import { Column, ForeignKeyColumn, Generated, Int8, Table, Timestamp, UpdateDateColumn } from 'src/sql-tools';
@Table('exif')
@UpdatedAtTrigger('asset_exif_updated_at')
@ -21,16 +21,16 @@ export class ExifTable {
exifImageHeight!: number | null;
@Column({ type: 'bigint', nullable: true })
fileSizeInByte!: number | null;
fileSizeInByte!: Int8 | null;
@Column({ type: 'character varying', nullable: true })
orientation!: string | null;
@Column({ type: 'timestamp with time zone', nullable: true })
dateTimeOriginal!: Date | null;
dateTimeOriginal!: Timestamp | null;
@Column({ type: 'timestamp with time zone', nullable: true })
modifyDate!: Date | null;
modifyDate!: Timestamp | null;
@Column({ type: 'character varying', nullable: true })
lensModel!: string | null;
@ -60,10 +60,10 @@ export class ExifTable {
country!: string | null;
@Column({ type: 'text', default: '' })
description!: string; // or caption
description!: Generated<string>; // or caption
@Column({ type: 'double precision', nullable: true })
fps?: number | null;
fps!: number | null;
@Column({ type: 'character varying', nullable: true })
exposureTime!: string | null;
@ -93,8 +93,8 @@ export class ExifTable {
rating!: number | null;
@UpdateDateColumn({ default: () => 'clock_timestamp()' })
updatedAt?: Date;
updatedAt!: Generated<Date>;
@UpdateIdColumn({ indexName: 'IDX_asset_exif_update_id' })
updateId?: string;
updateId!: Generated<string>;
}

View file

@ -1,4 +1,4 @@
import { Column, Index, PrimaryColumn, Table } from 'src/sql-tools';
import { Column, Index, PrimaryColumn, Table, Timestamp } from 'src/sql-tools';
@Table({ name: 'geodata_places', synchronize: false })
@Index({
@ -47,20 +47,20 @@ export class GeodataPlacesTable {
countryCode!: string;
@Column({ type: 'character varying', length: 20, nullable: true })
admin1Code!: string;
admin1Code!: string | null;
@Column({ type: 'character varying', length: 80, nullable: true })
admin2Code!: string;
admin2Code!: string | null;
@Column({ type: 'date' })
modificationDate!: Date;
modificationDate!: Timestamp;
@Column({ type: 'character varying', nullable: true })
admin1Name!: string;
admin1Name!: string | null;
@Column({ type: 'character varying', nullable: true })
admin2Name!: string;
admin2Name!: string | null;
@Column({ type: 'character varying', nullable: true })
alternateNames!: string;
alternateNames!: string | null;
}

View file

@ -5,8 +5,10 @@ import {
CreateDateColumn,
DeleteDateColumn,
ForeignKeyColumn,
Generated,
PrimaryGeneratedColumn,
Table,
Timestamp,
UpdateDateColumn,
} from 'src/sql-tools';
@ -14,7 +16,7 @@ import {
@UpdatedAtTrigger('libraries_updated_at')
export class LibraryTable {
@PrimaryGeneratedColumn()
id!: string;
id!: Generated<string>;
@Column()
name!: string;
@ -29,17 +31,17 @@ export class LibraryTable {
exclusionPatterns!: string[];
@CreateDateColumn()
createdAt!: Date;
createdAt!: Generated<Timestamp>;
@UpdateDateColumn()
updatedAt!: Date;
updatedAt!: Generated<Date>;
@DeleteDateColumn()
deletedAt?: Date;
deletedAt!: Timestamp | null;
@Column({ type: 'timestamp with time zone', nullable: true })
refreshedAt!: Date | null;
refreshedAt!: Timestamp | null;
@UpdateIdColumn({ indexName: 'IDX_libraries_update_id' })
updateId?: string;
updateId!: Generated<string>;
}

View file

@ -1,13 +1,16 @@
import { ColumnType } from 'kysely';
import { UpdatedAtTrigger, UpdateIdColumn } from 'src/decorators';
import { memory_assets_delete_audit } from 'src/schema/functions';
import { AssetTable } from 'src/schema/tables/asset.table';
import { MemoryTable } from 'src/schema/tables/memory.table';
import { AfterDeleteTrigger, CreateDateColumn, ForeignKeyColumn, Table, UpdateDateColumn } from 'src/sql-tools';
type Timestamp = ColumnType<Date, Date | string, Date | string>;
type Generated<T> =
T extends ColumnType<infer S, infer I, infer U> ? ColumnType<S, I | undefined, U> : ColumnType<T, T | undefined, T>;
import {
AfterDeleteTrigger,
CreateDateColumn,
ForeignKeyColumn,
Generated,
Table,
Timestamp,
UpdateDateColumn,
} from 'src/sql-tools';
@Table('memories_assets_assets')
@UpdatedAtTrigger('memory_assets_updated_at')

View file

@ -1,10 +1,5 @@
import { ColumnType } from 'kysely';
import { PrimaryGeneratedUuidV7Column } from 'src/decorators';
import { Column, CreateDateColumn, Table } from 'src/sql-tools';
type Timestamp = ColumnType<Date, Date | string, Date | string>;
type Generated<T> =
T extends ColumnType<infer S, infer I, infer U> ? ColumnType<S, I | undefined, U> : ColumnType<T, T | undefined, T>;
import { Column, CreateDateColumn, Generated, Table, Timestamp } from 'src/sql-tools';
@Table('memories_audit')
export class MemoryAuditTable {
@ -18,5 +13,5 @@ export class MemoryAuditTable {
userId!: string;
@CreateDateColumn({ default: () => 'clock_timestamp()', indexName: 'IDX_memories_audit_deleted_at' })
deletedAt!: Timestamp;
deletedAt!: Generated<Timestamp>;
}

View file

@ -8,8 +8,10 @@ import {
CreateDateColumn,
DeleteDateColumn,
ForeignKeyColumn,
Generated,
PrimaryGeneratedColumn,
Table,
Timestamp,
UpdateDateColumn,
} from 'src/sql-tools';
@ -24,16 +26,16 @@ import {
})
export class MemoryTable {
@PrimaryGeneratedColumn()
id!: string;
id!: Generated<string>;
@CreateDateColumn()
createdAt!: Date;
createdAt!: Generated<Timestamp>;
@UpdateDateColumn()
updatedAt!: Date;
updatedAt!: Generated<Timestamp>;
@DeleteDateColumn()
deletedAt?: Date;
deletedAt!: Timestamp | null;
@ForeignKeyColumn(() => UserTable, { onDelete: 'CASCADE', onUpdate: 'CASCADE', nullable: false })
ownerId!: string;
@ -46,22 +48,22 @@ export class MemoryTable {
/** unless set to true, will be automatically deleted in the future */
@Column({ type: 'boolean', default: false })
isSaved!: boolean;
isSaved!: Generated<boolean>;
/** memories are sorted in ascending order by this value */
@Column({ type: 'timestamp with time zone' })
memoryAt!: Date;
memoryAt!: Timestamp;
/** when the user last viewed the memory */
@Column({ type: 'timestamp with time zone', nullable: true })
seenAt?: Date;
seenAt!: Timestamp | null;
@Column({ type: 'timestamp with time zone', nullable: true })
showAt?: Date;
showAt!: Timestamp | null;
@Column({ type: 'timestamp with time zone', nullable: true })
hideAt?: Date;
hideAt!: Timestamp | null;
@UpdateIdColumn({ indexName: 'IDX_memories_update_id' })
updateId?: string;
updateId!: Generated<string>;
}

View file

@ -1,5 +1,5 @@
import { PathType } from 'src/enum';
import { Column, PrimaryGeneratedColumn, Table, Unique } from 'src/sql-tools';
import { Column, Generated, PrimaryGeneratedColumn, Table, Unique } from 'src/sql-tools';
@Table('move_history')
// path lock (per entity)
@ -8,7 +8,7 @@ import { Column, PrimaryGeneratedColumn, Table, Unique } from 'src/sql-tools';
@Unique({ name: 'UQ_newPath', columns: ['newPath'] })
export class MoveTable {
@PrimaryGeneratedColumn()
id!: string;
id!: Generated<string>;
@Column({ type: 'uuid' })
entityId!: string;

View file

@ -1,9 +1,9 @@
import { Column, PrimaryGeneratedColumn, Table } from 'src/sql-tools';
import { Column, Generated, PrimaryGeneratedColumn, Table } from 'src/sql-tools';
@Table({ name: 'naturalearth_countries', primaryConstraintName: 'naturalearth_countries_pkey' })
export class NaturalEarthCountriesTable {
@PrimaryGeneratedColumn({ strategy: 'identity' })
id!: number;
id!: Generated<number>;
@Column({ type: 'character varying', length: 50 })
admin!: string;

View file

@ -6,8 +6,10 @@ import {
CreateDateColumn,
DeleteDateColumn,
ForeignKeyColumn,
Generated,
PrimaryGeneratedColumn,
Table,
Timestamp,
UpdateDateColumn,
} from 'src/sql-tools';
@ -15,28 +17,28 @@ import {
@UpdatedAtTrigger('notifications_updated_at')
export class NotificationTable {
@PrimaryGeneratedColumn()
id!: string;
id!: Generated<string>;
@CreateDateColumn()
createdAt!: Date;
createdAt!: Generated<Timestamp>;
@UpdateDateColumn()
updatedAt!: Date;
updatedAt!: Generated<Timestamp>;
@DeleteDateColumn()
deletedAt?: Date;
deletedAt!: Timestamp | null;
@UpdateIdColumn({ indexName: 'IDX_notifications_update_id' })
updateId?: string;
updateId!: Generated<string>;
@ForeignKeyColumn(() => UserTable, { onDelete: 'CASCADE', onUpdate: 'CASCADE', nullable: true })
userId!: string;
@Column({ default: NotificationLevel.Info })
level!: NotificationLevel;
level!: Generated<NotificationLevel>;
@Column({ default: NotificationLevel.Info })
type!: NotificationType;
type!: Generated<NotificationType>;
@Column({ type: 'jsonb', nullable: true })
data!: any | null;
@ -45,8 +47,8 @@ export class NotificationTable {
title!: string;
@Column({ type: 'text', nullable: true })
description!: string;
description!: string | null;
@Column({ type: 'timestamp with time zone', nullable: true })
readAt?: Date | null;
readAt!: Timestamp | null;
}

View file

@ -1,10 +1,10 @@
import { PrimaryGeneratedUuidV7Column } from 'src/decorators';
import { Column, CreateDateColumn, Table } from 'src/sql-tools';
import { Column, CreateDateColumn, Generated, Table, Timestamp } from 'src/sql-tools';
@Table('partners_audit')
export class PartnerAuditTable {
@PrimaryGeneratedUuidV7Column()
id!: string;
id!: Generated<string>;
@Column({ type: 'uuid', indexName: 'IDX_partners_audit_shared_by_id' })
sharedById!: string;
@ -13,5 +13,5 @@ export class PartnerAuditTable {
sharedWithId!: string;
@CreateDateColumn({ default: () => 'clock_timestamp()', indexName: 'IDX_partners_audit_deleted_at' })
deletedAt!: Date;
deletedAt!: Generated<Timestamp>;
}

View file

@ -1,7 +1,16 @@
import { CreateIdColumn, UpdatedAtTrigger, UpdateIdColumn } from 'src/decorators';
import { partners_delete_audit } from 'src/schema/functions';
import { UserTable } from 'src/schema/tables/user.table';
import { AfterDeleteTrigger, Column, CreateDateColumn, ForeignKeyColumn, Table, UpdateDateColumn } from 'src/sql-tools';
import {
AfterDeleteTrigger,
Column,
CreateDateColumn,
ForeignKeyColumn,
Generated,
Table,
Timestamp,
UpdateDateColumn,
} from 'src/sql-tools';
@Table('partners')
@UpdatedAtTrigger('partners_updated_at')
@ -25,17 +34,17 @@ export class PartnerTable {
sharedWithId!: string;
@CreateDateColumn()
createdAt!: Date;
createdAt!: Generated<Timestamp>;
@CreateIdColumn({ indexName: 'IDX_partners_create_id' })
createId!: string;
createId!: Generated<string>;
@UpdateDateColumn()
updatedAt!: Date;
updatedAt!: Generated<Timestamp>;
@Column({ type: 'boolean', default: false })
inTimeline!: boolean;
inTimeline!: Generated<boolean>;
@UpdateIdColumn({ indexName: 'IDX_partners_update_id' })
updateId!: string;
updateId!: Generated<string>;
}

View file

@ -6,8 +6,10 @@ import {
Column,
CreateDateColumn,
ForeignKeyColumn,
Generated,
PrimaryGeneratedColumn,
Table,
Timestamp,
UpdateDateColumn,
} from 'src/sql-tools';
@ -16,38 +18,38 @@ import {
@Check({ name: 'CHK_b0f82b0ed662bfc24fbb58bb45', expression: `"birthDate" <= CURRENT_DATE` })
export class PersonTable {
@PrimaryGeneratedColumn('uuid')
id!: string;
id!: Generated<string>;
@CreateDateColumn()
createdAt!: Date;
createdAt!: Generated<Timestamp>;
@UpdateDateColumn()
updatedAt!: Date;
updatedAt!: Generated<Timestamp>;
@ForeignKeyColumn(() => UserTable, { onDelete: 'CASCADE', onUpdate: 'CASCADE', nullable: false })
ownerId!: string;
@Column({ default: '' })
name!: string;
name!: Generated<string>;
@Column({ default: '' })
thumbnailPath!: string;
thumbnailPath!: Generated<string>;
@Column({ type: 'boolean', default: false })
isHidden!: boolean;
isHidden!: Generated<boolean>;
@Column({ type: 'date', nullable: true })
birthDate!: Date | string | null;
birthDate!: Timestamp | null;
@ForeignKeyColumn(() => AssetFaceTable, { onDelete: 'SET NULL', nullable: true })
faceAssetId!: string | null;
@Column({ type: 'boolean', default: false })
isFavorite!: boolean;
isFavorite!: Generated<boolean>;
@Column({ type: 'character varying', nullable: true, default: null })
color?: string | null;
color!: string | null;
@UpdateIdColumn({ indexName: 'IDX_person_update_id' })
updateId!: string;
updateId!: Generated<string>;
}

View file

@ -4,8 +4,10 @@ import {
Column,
CreateDateColumn,
ForeignKeyColumn,
Generated,
PrimaryGeneratedColumn,
Table,
Timestamp,
UpdateDateColumn,
} from 'src/sql-tools';
@ -13,20 +15,20 @@ import {
@UpdatedAtTrigger('sessions_updated_at')
export class SessionTable {
@PrimaryGeneratedColumn()
id!: string;
id!: Generated<string>;
// TODO convert to byte[]
@Column()
token!: string;
@CreateDateColumn()
createdAt!: Date;
createdAt!: Generated<Timestamp>;
@UpdateDateColumn()
updatedAt!: Date;
updatedAt!: Generated<Timestamp>;
@Column({ type: 'timestamp with time zone', nullable: true })
expiresAt!: Date | null;
expiresAt!: Timestamp | null;
@ForeignKeyColumn(() => UserTable, { onUpdate: 'CASCADE', onDelete: 'CASCADE' })
userId!: string;
@ -35,14 +37,14 @@ export class SessionTable {
parentId!: string | null;
@Column({ default: '' })
deviceType!: string;
deviceType!: Generated<string>;
@Column({ default: '' })
deviceOS!: string;
deviceOS!: Generated<string>;
@UpdateIdColumn({ indexName: 'IDX_sessions_update_id' })
updateId!: string;
updateId!: Generated<string>;
@Column({ type: 'timestamp with time zone', nullable: true })
pinExpiresAt!: Date | null;
pinExpiresAt!: Timestamp | null;
}

View file

@ -1,13 +1,22 @@
import { SharedLinkType } from 'src/enum';
import { AlbumTable } from 'src/schema/tables/album.table';
import { UserTable } from 'src/schema/tables/user.table';
import { Column, CreateDateColumn, ForeignKeyColumn, PrimaryGeneratedColumn, Table, Unique } from 'src/sql-tools';
import {
Column,
CreateDateColumn,
ForeignKeyColumn,
Generated,
PrimaryGeneratedColumn,
Table,
Timestamp,
Unique,
} from 'src/sql-tools';
@Table('shared_links')
@Unique({ name: 'UQ_sharedlink_key', columns: ['key'] })
export class SharedLinkTable {
@PrimaryGeneratedColumn()
id!: string;
id!: Generated<string>;
@Column({ type: 'character varying', nullable: true })
description!: string | null;
@ -22,10 +31,10 @@ export class SharedLinkTable {
type!: SharedLinkType;
@CreateDateColumn()
createdAt!: Date;
createdAt!: Generated<Timestamp>;
@Column({ type: 'timestamp with time zone', nullable: true })
expiresAt!: Date | null;
expiresAt!: Timestamp | null;
@Column({ type: 'boolean', default: false })
allowUpload!: boolean;
@ -36,13 +45,13 @@ export class SharedLinkTable {
onUpdate: 'CASCADE',
indexName: 'IDX_sharedlink_albumId',
})
albumId!: string;
albumId!: string | null;
@Column({ type: 'boolean', default: true })
allowDownload!: boolean;
allowDownload!: Generated<boolean>;
@Column({ type: 'boolean', default: true })
showExif!: boolean;
showExif!: Generated<boolean>;
@Column({ type: 'character varying', nullable: true })
password!: string | null;

View file

@ -1,11 +1,11 @@
import { AssetTable } from 'src/schema/tables/asset.table';
import { UserTable } from 'src/schema/tables/user.table';
import { ForeignKeyColumn, PrimaryGeneratedColumn, Table } from 'src/sql-tools';
import { ForeignKeyColumn, Generated, PrimaryGeneratedColumn, Table } from 'src/sql-tools';
@Table('asset_stack')
export class StackTable {
@PrimaryGeneratedColumn()
id!: string;
id!: Generated<string>;
//TODO: Add constraint to ensure primary asset exists in the assets array
@ForeignKeyColumn(() => AssetTable, { nullable: false, unique: true })

View file

@ -1,7 +1,16 @@
import { UpdatedAtTrigger, UpdateIdColumn } from 'src/decorators';
import { SyncEntityType } from 'src/enum';
import { SessionTable } from 'src/schema/tables/session.table';
import { Column, CreateDateColumn, ForeignKeyColumn, PrimaryColumn, Table, UpdateDateColumn } from 'src/sql-tools';
import {
Column,
CreateDateColumn,
ForeignKeyColumn,
Generated,
PrimaryColumn,
Table,
Timestamp,
UpdateDateColumn,
} from 'src/sql-tools';
@Table('session_sync_checkpoints')
@UpdatedAtTrigger('session_sync_checkpoints_updated_at')
@ -13,14 +22,14 @@ export class SessionSyncCheckpointTable {
type!: SyncEntityType;
@CreateDateColumn()
createdAt!: Date;
createdAt!: Generated<Timestamp>;
@UpdateDateColumn()
updatedAt!: Date;
updatedAt!: Generated<Timestamp>;
@Column()
ack!: string;
@UpdateIdColumn({ indexName: 'IDX_session_sync_checkpoints_update_id' })
updateId!: string;
updateId!: Generated<string>;
}

View file

@ -4,8 +4,10 @@ import {
Column,
CreateDateColumn,
ForeignKeyColumn,
Generated,
PrimaryGeneratedColumn,
Table,
Timestamp,
Unique,
UpdateDateColumn,
} from 'src/sql-tools';
@ -15,7 +17,7 @@ import {
@Unique({ columns: ['userId', 'value'] })
export class TagTable {
@PrimaryGeneratedColumn()
id!: string;
id!: Generated<string>;
@ForeignKeyColumn(() => UserTable, {
onUpdate: 'CASCADE',
@ -29,17 +31,17 @@ export class TagTable {
value!: string;
@CreateDateColumn()
createdAt!: Date;
createdAt!: Generated<Timestamp>;
@UpdateDateColumn()
updatedAt!: Date;
updatedAt!: Generated<Timestamp>;
@Column({ type: 'character varying', nullable: true, default: null })
color!: string | null;
@ForeignKeyColumn(() => TagTable, { nullable: true, onDelete: 'CASCADE' })
parentId?: string;
parentId!: string | null;
@UpdateIdColumn({ indexName: 'IDX_tags_update_id' })
updateId!: string;
updateId!: Generated<string>;
}

View file

@ -1,14 +1,14 @@
import { PrimaryGeneratedUuidV7Column } from 'src/decorators';
import { Column, CreateDateColumn, Table } from 'src/sql-tools';
import { Column, CreateDateColumn, Generated, Table, Timestamp } from 'src/sql-tools';
@Table('users_audit')
export class UserAuditTable {
@PrimaryGeneratedUuidV7Column()
id!: Generated<string>;
@Column({ type: 'uuid' })
userId!: string;
@CreateDateColumn({ default: () => 'clock_timestamp()', indexName: 'IDX_users_audit_deleted_at' })
deletedAt!: Date;
@PrimaryGeneratedUuidV7Column()
id!: string;
deletedAt!: Generated<Timestamp>;
}

View file

@ -7,16 +7,14 @@ import {
Column,
CreateDateColumn,
DeleteDateColumn,
Generated,
Index,
PrimaryGeneratedColumn,
Table,
Timestamp,
UpdateDateColumn,
} from 'src/sql-tools';
type Timestamp = ColumnType<Date, Date | string, Date | string>;
type Generated<T> =
T extends ColumnType<infer S, infer I, infer U> ? ColumnType<S, I | undefined, U> : ColumnType<T, T | undefined, T>;
@Table('users')
@UpdatedAtTrigger('users_updated_at')
@AfterDeleteTrigger({

View file

@ -1,12 +1,12 @@
import { Column, CreateDateColumn, PrimaryGeneratedColumn, Table } from 'src/sql-tools';
import { Column, CreateDateColumn, Generated, PrimaryGeneratedColumn, Table, Timestamp } from 'src/sql-tools';
@Table('version_history')
export class VersionHistoryTable {
@PrimaryGeneratedColumn()
id!: string;
id!: Generated<string>;
@CreateDateColumn()
createdAt!: Date;
createdAt!: Generated<Timestamp>;
@Column()
version!: string;