mirror of
https://github.com/immich-app/immich.git
synced 2025-12-17 17:23:20 +03:00
feat: extension, triggers, functions, comments, parameters management in sql-tools (#17269)
feat: sql-tools extension, triggers, functions, comments, parameters
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import { UpdatedAtTrigger, UpdateIdColumn } from 'src/decorators';
|
||||
import { AlbumTable } from 'src/schema/tables/album.table';
|
||||
import { AssetTable } from 'src/schema/tables/asset.table';
|
||||
import { UserTable } from 'src/schema/tables/user.table';
|
||||
@@ -11,10 +12,10 @@ import {
|
||||
PrimaryGeneratedColumn,
|
||||
Table,
|
||||
UpdateDateColumn,
|
||||
UpdateIdColumn,
|
||||
} from 'src/sql-tools';
|
||||
|
||||
@Table('activity')
|
||||
@UpdatedAtTrigger('activity_updated_at')
|
||||
@Index({
|
||||
name: 'IDX_activity_like',
|
||||
columns: ['assetId', 'userId', 'albumId'],
|
||||
@@ -35,9 +36,14 @@ export class ActivityTable {
|
||||
@UpdateDateColumn()
|
||||
updatedAt!: Date;
|
||||
|
||||
@ColumnIndex('IDX_activity_update_id')
|
||||
@UpdateIdColumn()
|
||||
updateId!: string;
|
||||
@ForeignKeyColumn(() => AlbumTable, { onDelete: 'CASCADE', onUpdate: 'CASCADE' })
|
||||
albumId!: string;
|
||||
|
||||
@ForeignKeyColumn(() => UserTable, { onDelete: 'CASCADE', onUpdate: 'CASCADE' })
|
||||
userId!: string;
|
||||
|
||||
@ForeignKeyColumn(() => AssetTable, { onDelete: 'CASCADE', onUpdate: 'CASCADE', nullable: true })
|
||||
assetId!: string | null;
|
||||
|
||||
@Column({ type: 'text', default: null })
|
||||
comment!: string | null;
|
||||
@@ -45,12 +51,7 @@ export class ActivityTable {
|
||||
@Column({ type: 'boolean', default: false })
|
||||
isLiked!: boolean;
|
||||
|
||||
@ForeignKeyColumn(() => AssetTable, { onDelete: 'CASCADE', onUpdate: 'CASCADE', nullable: true })
|
||||
assetId!: string | null;
|
||||
|
||||
@ForeignKeyColumn(() => UserTable, { onDelete: 'CASCADE', onUpdate: 'CASCADE' })
|
||||
userId!: string;
|
||||
|
||||
@ForeignKeyColumn(() => AlbumTable, { onDelete: 'CASCADE', onUpdate: 'CASCADE' })
|
||||
albumId!: string;
|
||||
@ColumnIndex('IDX_activity_update_id')
|
||||
@UpdateIdColumn()
|
||||
updateId!: string;
|
||||
}
|
||||
|
||||
@@ -4,15 +4,6 @@ import { ColumnIndex, CreateDateColumn, ForeignKeyColumn, Table } from 'src/sql-
|
||||
|
||||
@Table({ name: 'albums_assets_assets', primaryConstraintName: 'PK_c67bc36fa845fb7b18e0e398180' })
|
||||
export class AlbumAssetTable {
|
||||
@ForeignKeyColumn(() => AssetTable, {
|
||||
onDelete: 'CASCADE',
|
||||
onUpdate: 'CASCADE',
|
||||
nullable: false,
|
||||
primary: true,
|
||||
})
|
||||
@ColumnIndex()
|
||||
assetsId!: string;
|
||||
|
||||
@ForeignKeyColumn(() => AlbumTable, {
|
||||
onDelete: 'CASCADE',
|
||||
onUpdate: 'CASCADE',
|
||||
@@ -22,6 +13,15 @@ export class AlbumAssetTable {
|
||||
@ColumnIndex()
|
||||
albumsId!: string;
|
||||
|
||||
@ForeignKeyColumn(() => AssetTable, {
|
||||
onDelete: 'CASCADE',
|
||||
onUpdate: 'CASCADE',
|
||||
nullable: false,
|
||||
primary: true,
|
||||
})
|
||||
@ColumnIndex()
|
||||
assetsId!: string;
|
||||
|
||||
@CreateDateColumn()
|
||||
createdAt!: Date;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { UpdatedAtTrigger, UpdateIdColumn } from 'src/decorators';
|
||||
import { AssetOrder } from 'src/enum';
|
||||
import { AssetTable } from 'src/schema/tables/asset.table';
|
||||
import { UserTable } from 'src/schema/tables/user.table';
|
||||
@@ -10,10 +11,10 @@ import {
|
||||
PrimaryGeneratedColumn,
|
||||
Table,
|
||||
UpdateDateColumn,
|
||||
UpdateIdColumn,
|
||||
} from 'src/sql-tools';
|
||||
|
||||
@Table({ name: 'albums', primaryConstraintName: 'PK_7f71c7b5bc7c87b8f94c9a93a00' })
|
||||
@UpdatedAtTrigger('albums_updated_at')
|
||||
export class AlbumTable {
|
||||
@PrimaryGeneratedColumn()
|
||||
id!: string;
|
||||
@@ -24,28 +25,33 @@ export class AlbumTable {
|
||||
@Column({ default: 'Untitled Album' })
|
||||
albumName!: string;
|
||||
|
||||
@Column({ type: 'text', default: '' })
|
||||
description!: string;
|
||||
|
||||
@CreateDateColumn()
|
||||
createdAt!: Date;
|
||||
|
||||
@ForeignKeyColumn(() => AssetTable, {
|
||||
nullable: true,
|
||||
onDelete: 'SET NULL',
|
||||
onUpdate: 'CASCADE',
|
||||
comment: 'Asset ID to be used as thumbnail',
|
||||
})
|
||||
albumThumbnailAssetId!: string;
|
||||
|
||||
@UpdateDateColumn()
|
||||
updatedAt!: Date;
|
||||
|
||||
@ColumnIndex('IDX_albums_update_id')
|
||||
@UpdateIdColumn()
|
||||
updateId?: string;
|
||||
@Column({ type: 'text', default: '' })
|
||||
description!: string;
|
||||
|
||||
@DeleteDateColumn()
|
||||
deletedAt!: Date | null;
|
||||
|
||||
@ForeignKeyColumn(() => AssetTable, { nullable: true, onDelete: 'SET NULL', onUpdate: 'CASCADE' })
|
||||
albumThumbnailAssetId!: string;
|
||||
|
||||
@Column({ type: 'boolean', default: true })
|
||||
isActivityEnabled!: boolean;
|
||||
|
||||
@Column({ default: AssetOrder.DESC })
|
||||
order!: AssetOrder;
|
||||
|
||||
@ColumnIndex('IDX_albums_update_id')
|
||||
@UpdateIdColumn()
|
||||
updateId?: string;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { UpdatedAtTrigger, UpdateIdColumn } from 'src/decorators';
|
||||
import { Permission } from 'src/enum';
|
||||
import { UserTable } from 'src/schema/tables/user.table';
|
||||
import {
|
||||
@@ -8,22 +9,19 @@ import {
|
||||
PrimaryGeneratedColumn,
|
||||
Table,
|
||||
UpdateDateColumn,
|
||||
UpdateIdColumn,
|
||||
} from 'src/sql-tools';
|
||||
|
||||
@Table('api_keys')
|
||||
@UpdatedAtTrigger('api_keys_updated_at')
|
||||
export class APIKeyTable {
|
||||
@PrimaryGeneratedColumn()
|
||||
id!: string;
|
||||
|
||||
@Column()
|
||||
name!: string;
|
||||
|
||||
@Column()
|
||||
key!: string;
|
||||
|
||||
@Column({ array: true, type: 'character varying' })
|
||||
permissions!: Permission[];
|
||||
@ForeignKeyColumn(() => UserTable, { onUpdate: 'CASCADE', onDelete: 'CASCADE' })
|
||||
userId!: string;
|
||||
|
||||
@CreateDateColumn()
|
||||
createdAt!: Date;
|
||||
@@ -31,10 +29,13 @@ export class APIKeyTable {
|
||||
@UpdateDateColumn()
|
||||
updatedAt!: Date;
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
id!: string;
|
||||
|
||||
@Column({ array: true, type: 'character varying' })
|
||||
permissions!: Permission[];
|
||||
|
||||
@ColumnIndex({ name: 'IDX_api_keys_update_id' })
|
||||
@UpdateIdColumn()
|
||||
updateId?: string;
|
||||
|
||||
@ForeignKeyColumn(() => UserTable, { onUpdate: 'CASCADE', onDelete: 'CASCADE' })
|
||||
userId!: string;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { Column, ColumnIndex, CreateDateColumn, PrimaryGeneratedColumn, Table } from 'src/sql-tools';
|
||||
import { PrimaryGeneratedUuidV7Column } from 'src/decorators';
|
||||
import { Column, ColumnIndex, CreateDateColumn, Table } from 'src/sql-tools';
|
||||
|
||||
@Table('assets_audit')
|
||||
export class AssetAuditTable {
|
||||
@PrimaryGeneratedColumn({ type: 'v7' })
|
||||
@PrimaryGeneratedUuidV7Column()
|
||||
id!: string;
|
||||
|
||||
@ColumnIndex('IDX_assets_audit_asset_id')
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
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';
|
||||
@@ -7,8 +8,11 @@ import { Column, DeleteDateColumn, ForeignKeyColumn, Index, PrimaryGeneratedColu
|
||||
@Index({ name: 'IDX_asset_faces_assetId_personId', columns: ['assetId', 'personId'] })
|
||||
@Index({ columns: ['personId', 'assetId'] })
|
||||
export class AssetFaceTable {
|
||||
@PrimaryGeneratedColumn()
|
||||
id!: string;
|
||||
@ForeignKeyColumn(() => AssetTable, { onDelete: 'CASCADE', onUpdate: 'CASCADE' })
|
||||
assetId!: string;
|
||||
|
||||
@ForeignKeyColumn(() => PersonTable, { onDelete: 'SET NULL', onUpdate: 'CASCADE', nullable: true })
|
||||
personId!: string | null;
|
||||
|
||||
@Column({ default: 0, type: 'integer' })
|
||||
imageWidth!: number;
|
||||
@@ -28,15 +32,12 @@ export class AssetFaceTable {
|
||||
@Column({ default: 0, type: 'integer' })
|
||||
boundingBoxY2!: number;
|
||||
|
||||
@Column({ default: SourceType.MACHINE_LEARNING, enumName: 'sourcetype', enum: SourceType })
|
||||
@PrimaryGeneratedColumn()
|
||||
id!: string;
|
||||
|
||||
@Column({ default: SourceType.MACHINE_LEARNING, enum: asset_face_source_type })
|
||||
sourceType!: SourceType;
|
||||
|
||||
@ForeignKeyColumn(() => AssetTable, { onDelete: 'CASCADE', onUpdate: 'CASCADE' })
|
||||
assetId!: string;
|
||||
|
||||
@ForeignKeyColumn(() => PersonTable, { onDelete: 'SET NULL', onUpdate: 'CASCADE', nullable: true })
|
||||
personId!: string | null;
|
||||
|
||||
@DeleteDateColumn()
|
||||
deletedAt!: Date | null;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { AssetEntity } from 'src/entities/asset.entity';
|
||||
import { UpdatedAtTrigger, UpdateIdColumn } from 'src/decorators';
|
||||
import { AssetFileType } from 'src/enum';
|
||||
import { AssetTable } from 'src/schema/tables/asset.table';
|
||||
import {
|
||||
Column,
|
||||
ColumnIndex,
|
||||
@@ -9,18 +10,18 @@ import {
|
||||
Table,
|
||||
Unique,
|
||||
UpdateDateColumn,
|
||||
UpdateIdColumn,
|
||||
} from 'src/sql-tools';
|
||||
|
||||
@Unique({ name: 'UQ_assetId_type', columns: ['assetId', 'type'] })
|
||||
@Table('asset_files')
|
||||
@Unique({ name: 'UQ_assetId_type', columns: ['assetId', 'type'] })
|
||||
@UpdatedAtTrigger('asset_files_updated_at')
|
||||
export class AssetFileTable {
|
||||
@PrimaryGeneratedColumn()
|
||||
id!: string;
|
||||
|
||||
@ColumnIndex('IDX_asset_files_assetId')
|
||||
@ForeignKeyColumn(() => AssetEntity, { onDelete: 'CASCADE', onUpdate: 'CASCADE' })
|
||||
assetId?: AssetEntity;
|
||||
@ForeignKeyColumn(() => AssetTable, { onDelete: 'CASCADE', onUpdate: 'CASCADE' })
|
||||
assetId?: string;
|
||||
|
||||
@CreateDateColumn()
|
||||
createdAt!: Date;
|
||||
@@ -28,13 +29,13 @@ export class AssetFileTable {
|
||||
@UpdateDateColumn()
|
||||
updatedAt!: Date;
|
||||
|
||||
@ColumnIndex('IDX_asset_files_update_id')
|
||||
@UpdateIdColumn()
|
||||
updateId?: string;
|
||||
|
||||
@Column()
|
||||
type!: AssetFileType;
|
||||
|
||||
@Column()
|
||||
path!: string;
|
||||
|
||||
@ColumnIndex('IDX_asset_files_update_id')
|
||||
@UpdateIdColumn()
|
||||
updateId?: string;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
import { UpdatedAtTrigger, UpdateIdColumn } from 'src/decorators';
|
||||
import { ASSET_CHECKSUM_CONSTRAINT } from 'src/entities/asset.entity';
|
||||
import { AssetStatus, AssetType } from 'src/enum';
|
||||
import { assets_status_enum } from 'src/schema/enums';
|
||||
import { assets_delete_audit } from 'src/schema/functions';
|
||||
import { LibraryTable } from 'src/schema/tables/library.table';
|
||||
import { StackTable } from 'src/schema/tables/stack.table';
|
||||
import { UserTable } from 'src/schema/tables/user.table';
|
||||
import {
|
||||
AfterDeleteTrigger,
|
||||
Column,
|
||||
ColumnIndex,
|
||||
CreateDateColumn,
|
||||
@@ -13,10 +17,17 @@ import {
|
||||
PrimaryGeneratedColumn,
|
||||
Table,
|
||||
UpdateDateColumn,
|
||||
UpdateIdColumn,
|
||||
} from 'src/sql-tools';
|
||||
|
||||
@Table('assets')
|
||||
@UpdatedAtTrigger('assets_updated_at')
|
||||
@AfterDeleteTrigger({
|
||||
name: 'assets_delete_audit',
|
||||
scope: 'statement',
|
||||
function: assets_delete_audit,
|
||||
referencingOldTableAs: 'old',
|
||||
when: 'pg_trigger_depth() = 0',
|
||||
})
|
||||
// Checksums must be unique per user and library
|
||||
@Index({
|
||||
name: ASSET_CHECKSUM_CONSTRAINT,
|
||||
@@ -30,7 +41,11 @@ import {
|
||||
unique: true,
|
||||
where: '("libraryId" IS NOT NULL)',
|
||||
})
|
||||
@Index({ name: 'idx_local_date_time', expression: `(("localDateTime" AT TIME ZONE 'UTC'::text))::date` })
|
||||
@Index({
|
||||
name: 'idx_local_date_time',
|
||||
expression: `(("localDateTime" at time zone 'UTC')::date)`,
|
||||
synchronize: false,
|
||||
})
|
||||
@Index({
|
||||
name: 'idx_local_date_time_month',
|
||||
expression: `(date_trunc('MONTH'::text, ("localDateTime" AT TIME ZONE 'UTC'::text)) AT TIME ZONE 'UTC'::text)`,
|
||||
@@ -38,9 +53,10 @@ import {
|
||||
@Index({ name: 'IDX_originalPath_libraryId', columns: ['originalPath', 'libraryId'] })
|
||||
@Index({ name: 'IDX_asset_id_stackId', columns: ['id', 'stackId'] })
|
||||
@Index({
|
||||
name: 'idx_originalFileName_trigram',
|
||||
name: 'idx_originalfilename_trigram',
|
||||
using: 'gin',
|
||||
expression: 'f_unaccent(("originalFileName")::text)',
|
||||
expression: 'f_unaccent("originalFileName") gin_trgm_ops',
|
||||
synchronize: false,
|
||||
})
|
||||
// For all assets, each originalpath must be unique per user and library
|
||||
export class AssetTable {
|
||||
@@ -53,75 +69,50 @@ export class AssetTable {
|
||||
@ForeignKeyColumn(() => UserTable, { onDelete: 'CASCADE', onUpdate: 'CASCADE', nullable: false })
|
||||
ownerId!: string;
|
||||
|
||||
@ForeignKeyColumn(() => LibraryTable, { onDelete: 'CASCADE', onUpdate: 'CASCADE', nullable: true })
|
||||
libraryId?: string | null;
|
||||
|
||||
@Column()
|
||||
deviceId!: string;
|
||||
|
||||
@Column()
|
||||
type!: AssetType;
|
||||
|
||||
@Column({ type: 'enum', enum: AssetStatus, default: AssetStatus.ACTIVE })
|
||||
status!: AssetStatus;
|
||||
|
||||
@Column()
|
||||
originalPath!: string;
|
||||
|
||||
@Column({ type: 'bytea', nullable: true })
|
||||
thumbhash!: Buffer | null;
|
||||
|
||||
@Column({ type: 'character varying', nullable: true, default: '' })
|
||||
encodedVideoPath!: string | null;
|
||||
|
||||
@CreateDateColumn()
|
||||
createdAt!: Date;
|
||||
|
||||
@UpdateDateColumn()
|
||||
updatedAt!: Date;
|
||||
|
||||
@ColumnIndex('IDX_assets_update_id')
|
||||
@UpdateIdColumn()
|
||||
updateId?: string;
|
||||
|
||||
@DeleteDateColumn()
|
||||
deletedAt!: Date | null;
|
||||
|
||||
@ColumnIndex('idx_asset_file_created_at')
|
||||
@Column({ type: 'timestamp with time zone', default: null })
|
||||
fileCreatedAt!: Date;
|
||||
|
||||
@Column({ type: 'timestamp with time zone', default: null })
|
||||
localDateTime!: Date;
|
||||
|
||||
@Column({ type: 'timestamp with time zone', default: null })
|
||||
fileModifiedAt!: Date;
|
||||
|
||||
@Column({ type: 'boolean', default: false })
|
||||
isFavorite!: boolean;
|
||||
|
||||
@Column({ type: 'boolean', default: false })
|
||||
isArchived!: boolean;
|
||||
@Column({ type: 'character varying', nullable: true })
|
||||
duration!: string | null;
|
||||
|
||||
@Column({ type: 'boolean', default: false })
|
||||
isExternal!: boolean;
|
||||
|
||||
@Column({ type: 'boolean', default: false })
|
||||
isOffline!: boolean;
|
||||
@Column({ type: 'character varying', nullable: true, default: '' })
|
||||
encodedVideoPath!: string | null;
|
||||
|
||||
@Column({ type: 'bytea' })
|
||||
@ColumnIndex()
|
||||
checksum!: Buffer; // sha1 checksum
|
||||
|
||||
@Column({ type: 'character varying', nullable: true })
|
||||
duration!: string | null;
|
||||
|
||||
@Column({ type: 'boolean', default: true })
|
||||
isVisible!: boolean;
|
||||
|
||||
@ForeignKeyColumn(() => AssetTable, { nullable: true, onUpdate: 'CASCADE', onDelete: 'SET NULL' })
|
||||
livePhotoVideoId!: string | null;
|
||||
|
||||
@UpdateDateColumn()
|
||||
updatedAt!: Date;
|
||||
|
||||
@CreateDateColumn()
|
||||
createdAt!: Date;
|
||||
|
||||
@Column({ type: 'boolean', default: false })
|
||||
isArchived!: boolean;
|
||||
|
||||
@Column()
|
||||
@ColumnIndex()
|
||||
originalFileName!: string;
|
||||
@@ -129,10 +120,35 @@ export class AssetTable {
|
||||
@Column({ nullable: true })
|
||||
sidecarPath!: string | null;
|
||||
|
||||
@Column({ type: 'bytea', nullable: true })
|
||||
thumbhash!: Buffer | null;
|
||||
|
||||
@Column({ type: 'boolean', default: false })
|
||||
isOffline!: boolean;
|
||||
|
||||
@ForeignKeyColumn(() => LibraryTable, { onDelete: 'CASCADE', onUpdate: 'CASCADE', nullable: true })
|
||||
libraryId?: string | null;
|
||||
|
||||
@Column({ type: 'boolean', default: false })
|
||||
isExternal!: boolean;
|
||||
|
||||
@DeleteDateColumn()
|
||||
deletedAt!: Date | null;
|
||||
|
||||
@Column({ type: 'timestamp with time zone', default: null })
|
||||
localDateTime!: Date;
|
||||
|
||||
@ForeignKeyColumn(() => StackTable, { nullable: true, onDelete: 'SET NULL', onUpdate: 'CASCADE' })
|
||||
stackId?: string | null;
|
||||
|
||||
@ColumnIndex('IDX_assets_duplicateId')
|
||||
@Column({ type: 'uuid', nullable: true })
|
||||
duplicateId!: string | null;
|
||||
|
||||
@Column({ enum: assets_status_enum, default: AssetStatus.ACTIVE })
|
||||
status!: AssetStatus;
|
||||
|
||||
@ColumnIndex('IDX_assets_update_id')
|
||||
@UpdateIdColumn()
|
||||
updateId?: string;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Column, CreateDateColumn, Index, PrimaryColumn, Table } from 'src/sql-t
|
||||
@Table('audit')
|
||||
@Index({ name: 'IDX_ownerId_createdAt', columns: ['ownerId', 'createdAt'] })
|
||||
export class AuditTable {
|
||||
@PrimaryColumn({ type: 'integer', default: 'increment', synchronize: false })
|
||||
@PrimaryColumn({ type: 'serial', synchronize: false })
|
||||
id!: number;
|
||||
|
||||
@Column()
|
||||
|
||||
@@ -1,21 +1,18 @@
|
||||
import { UpdatedAtTrigger, UpdateIdColumn } from 'src/decorators';
|
||||
import { AssetTable } from 'src/schema/tables/asset.table';
|
||||
import { Column, ColumnIndex, ForeignKeyColumn, Table, UpdateDateColumn, UpdateIdColumn } from 'src/sql-tools';
|
||||
import { Column, ColumnIndex, ForeignKeyColumn, Table, UpdateDateColumn } from 'src/sql-tools';
|
||||
|
||||
@Table('exif')
|
||||
@UpdatedAtTrigger('asset_exif_updated_at')
|
||||
export class ExifTable {
|
||||
@ForeignKeyColumn(() => AssetTable, { onDelete: 'CASCADE', primary: true })
|
||||
assetId!: string;
|
||||
|
||||
@UpdateDateColumn({ default: () => 'clock_timestamp()' })
|
||||
updatedAt?: Date;
|
||||
@Column({ type: 'character varying', nullable: true })
|
||||
make!: string | null;
|
||||
|
||||
@ColumnIndex('IDX_asset_exif_update_id')
|
||||
@UpdateIdColumn()
|
||||
updateId?: string;
|
||||
|
||||
/* General info */
|
||||
@Column({ type: 'text', default: '' })
|
||||
description!: string; // or caption
|
||||
@Column({ type: 'character varying', nullable: true })
|
||||
model!: string | null;
|
||||
|
||||
@Column({ type: 'integer', nullable: true })
|
||||
exifImageWidth!: number | null;
|
||||
@@ -35,43 +32,6 @@ export class ExifTable {
|
||||
@Column({ type: 'timestamp with time zone', nullable: true })
|
||||
modifyDate!: Date | null;
|
||||
|
||||
@Column({ type: 'character varying', nullable: true })
|
||||
timeZone!: string | null;
|
||||
|
||||
@Column({ type: 'double precision', nullable: true })
|
||||
latitude!: number | null;
|
||||
|
||||
@Column({ type: 'double precision', nullable: true })
|
||||
longitude!: number | null;
|
||||
|
||||
@Column({ type: 'character varying', nullable: true })
|
||||
projectionType!: string | null;
|
||||
|
||||
@ColumnIndex('exif_city')
|
||||
@Column({ type: 'character varying', nullable: true })
|
||||
city!: string | null;
|
||||
|
||||
@ColumnIndex('IDX_live_photo_cid')
|
||||
@Column({ type: 'character varying', nullable: true })
|
||||
livePhotoCID!: string | null;
|
||||
|
||||
@ColumnIndex('IDX_auto_stack_id')
|
||||
@Column({ type: 'character varying', nullable: true })
|
||||
autoStackId!: string | null;
|
||||
|
||||
@Column({ type: 'character varying', nullable: true })
|
||||
state!: string | null;
|
||||
|
||||
@Column({ type: 'character varying', nullable: true })
|
||||
country!: string | null;
|
||||
|
||||
/* Image info */
|
||||
@Column({ type: 'character varying', nullable: true })
|
||||
make!: string | null;
|
||||
|
||||
@Column({ type: 'character varying', nullable: true })
|
||||
model!: string | null;
|
||||
|
||||
@Column({ type: 'character varying', nullable: true })
|
||||
lensModel!: string | null;
|
||||
|
||||
@@ -84,9 +44,41 @@ export class ExifTable {
|
||||
@Column({ type: 'integer', nullable: true })
|
||||
iso!: number | null;
|
||||
|
||||
@Column({ type: 'double precision', nullable: true })
|
||||
latitude!: number | null;
|
||||
|
||||
@Column({ type: 'double precision', nullable: true })
|
||||
longitude!: number | null;
|
||||
|
||||
@ColumnIndex('exif_city')
|
||||
@Column({ type: 'character varying', nullable: true })
|
||||
city!: string | null;
|
||||
|
||||
@Column({ type: 'character varying', nullable: true })
|
||||
state!: string | null;
|
||||
|
||||
@Column({ type: 'character varying', nullable: true })
|
||||
country!: string | null;
|
||||
|
||||
@Column({ type: 'text', default: '' })
|
||||
description!: string; // or caption
|
||||
|
||||
@Column({ type: 'double precision', nullable: true })
|
||||
fps?: number | null;
|
||||
|
||||
@Column({ type: 'character varying', nullable: true })
|
||||
exposureTime!: string | null;
|
||||
|
||||
@ColumnIndex('IDX_live_photo_cid')
|
||||
@Column({ type: 'character varying', nullable: true })
|
||||
livePhotoCID!: string | null;
|
||||
|
||||
@Column({ type: 'character varying', nullable: true })
|
||||
timeZone!: string | null;
|
||||
|
||||
@Column({ type: 'character varying', nullable: true })
|
||||
projectionType!: string | null;
|
||||
|
||||
@Column({ type: 'character varying', nullable: true })
|
||||
profileDescription!: string | null;
|
||||
|
||||
@@ -96,10 +88,17 @@ export class ExifTable {
|
||||
@Column({ type: 'integer', nullable: true })
|
||||
bitsPerSample!: number | null;
|
||||
|
||||
@ColumnIndex('IDX_auto_stack_id')
|
||||
@Column({ type: 'character varying', nullable: true })
|
||||
autoStackId!: string | null;
|
||||
|
||||
@Column({ type: 'integer', nullable: true })
|
||||
rating!: number | null;
|
||||
|
||||
/* Video info */
|
||||
@Column({ type: 'double precision', nullable: true })
|
||||
fps?: number | null;
|
||||
@UpdateDateColumn({ default: () => 'clock_timestamp()' })
|
||||
updatedAt?: Date;
|
||||
|
||||
@ColumnIndex('IDX_asset_exif_update_id')
|
||||
@UpdateIdColumn()
|
||||
updateId?: string;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
import { AssetFaceTable } from 'src/schema/tables/asset-face.table';
|
||||
import { Column, ColumnIndex, ForeignKeyColumn, Table } from 'src/sql-tools';
|
||||
import { Column, ForeignKeyColumn, Index, Table } from 'src/sql-tools';
|
||||
|
||||
@Table({ name: 'face_search', primaryConstraintName: 'face_search_pkey' })
|
||||
@Index({
|
||||
name: 'face_index',
|
||||
using: 'hnsw',
|
||||
expression: `embedding vector_cosine_ops`,
|
||||
with: 'ef_construction = 300, m = 16',
|
||||
synchronize: false,
|
||||
})
|
||||
export class FaceSearchTable {
|
||||
@ForeignKeyColumn(() => AssetFaceTable, {
|
||||
onDelete: 'CASCADE',
|
||||
@@ -10,7 +17,6 @@ export class FaceSearchTable {
|
||||
})
|
||||
faceId!: string;
|
||||
|
||||
@ColumnIndex({ name: 'face_index', synchronize: false })
|
||||
@Column({ type: 'vector', array: true, length: 512, synchronize: false })
|
||||
@Column({ type: 'vector', length: 512, synchronize: false })
|
||||
embedding!: string;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,35 @@
|
||||
import { Column, Index, PrimaryColumn, Table } from 'src/sql-tools';
|
||||
|
||||
@Index({ name: 'idx_geodata_places_alternate_names', expression: 'f_unaccent("alternateNames") gin_trgm_ops' })
|
||||
@Index({ name: 'idx_geodata_places_admin1_name', expression: 'f_unaccent("admin1Name") gin_trgm_ops' })
|
||||
@Index({ name: 'idx_geodata_places_admin2_name', expression: 'f_unaccent("admin2Name") gin_trgm_ops' })
|
||||
@Index({ name: 'idx_geodata_places_name', expression: 'f_unaccent("name") gin_trgm_ops' })
|
||||
@Index({ name: 'idx_geodata_places_gist_earthcoord', expression: 'll_to_earth_public(latitude, longitude)' })
|
||||
@Table({ name: 'geodata_places' })
|
||||
@Index({
|
||||
name: 'idx_geodata_places_alternate_names',
|
||||
using: 'gin',
|
||||
expression: 'f_unaccent("alternateNames") gin_trgm_ops',
|
||||
synchronize: false,
|
||||
})
|
||||
@Index({
|
||||
name: 'idx_geodata_places_admin1_name',
|
||||
using: 'gin',
|
||||
expression: 'f_unaccent("admin1Name") gin_trgm_ops',
|
||||
synchronize: false,
|
||||
})
|
||||
@Index({
|
||||
name: 'idx_geodata_places_admin2_name',
|
||||
using: 'gin',
|
||||
expression: 'f_unaccent("admin2Name") gin_trgm_ops',
|
||||
synchronize: false,
|
||||
})
|
||||
@Index({
|
||||
name: 'idx_geodata_places_name',
|
||||
using: 'gin',
|
||||
expression: 'f_unaccent("name") gin_trgm_ops',
|
||||
synchronize: false,
|
||||
})
|
||||
@Index({
|
||||
name: 'idx_geodata_places_gist_earthcoord',
|
||||
expression: 'll_to_earth_public(latitude, longitude)',
|
||||
synchronize: false,
|
||||
})
|
||||
@Table({ name: 'idx_geodata_places', synchronize: false })
|
||||
export class GeodataPlacesTable {
|
||||
@PrimaryColumn({ type: 'integer' })
|
||||
@@ -28,41 +53,8 @@ export class GeodataPlacesTable {
|
||||
@Column({ type: 'character varying', length: 80, nullable: true })
|
||||
admin2Code!: string;
|
||||
|
||||
@Column({ type: 'character varying', nullable: true })
|
||||
admin1Name!: string;
|
||||
|
||||
@Column({ type: 'character varying', nullable: true })
|
||||
admin2Name!: string;
|
||||
|
||||
@Column({ type: 'character varying', nullable: true })
|
||||
alternateNames!: string;
|
||||
|
||||
@Column({ type: 'date' })
|
||||
modificationDate!: Date;
|
||||
}
|
||||
|
||||
@Table({ name: 'geodata_places_tmp', synchronize: false })
|
||||
export class GeodataPlacesTempEntity {
|
||||
@PrimaryColumn({ type: 'integer' })
|
||||
id!: number;
|
||||
|
||||
@Column({ type: 'character varying', length: 200 })
|
||||
name!: string;
|
||||
|
||||
@Column({ type: 'double precision' })
|
||||
longitude!: number;
|
||||
|
||||
@Column({ type: 'double precision' })
|
||||
latitude!: number;
|
||||
|
||||
@Column({ type: 'character', length: 2 })
|
||||
countryCode!: string;
|
||||
|
||||
@Column({ type: 'character varying', length: 20, nullable: true })
|
||||
admin1Code!: string;
|
||||
|
||||
@Column({ type: 'character varying', length: 80, nullable: true })
|
||||
admin2Code!: string;
|
||||
|
||||
@Column({ type: 'character varying', nullable: true })
|
||||
admin1Name!: string;
|
||||
@@ -72,7 +64,4 @@ export class GeodataPlacesTempEntity {
|
||||
|
||||
@Column({ type: 'character varying', nullable: true })
|
||||
alternateNames!: string;
|
||||
|
||||
@Column({ type: 'date' })
|
||||
modificationDate!: Date;
|
||||
}
|
||||
|
||||
@@ -1,73 +1,35 @@
|
||||
import { ActivityTable } from 'src/schema/tables/activity.table';
|
||||
import { AlbumAssetTable } from 'src/schema/tables/album-asset.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 { AssetAuditTable } from 'src/schema/tables/asset-audit.table';
|
||||
import { AssetFaceTable } from 'src/schema/tables/asset-face.table';
|
||||
import { AssetJobStatusTable } from 'src/schema/tables/asset-job-status.table';
|
||||
import { AssetTable } from 'src/schema/tables/asset.table';
|
||||
import { AuditTable } from 'src/schema/tables/audit.table';
|
||||
import { ExifTable } from 'src/schema/tables/exif.table';
|
||||
import { FaceSearchTable } from 'src/schema/tables/face-search.table';
|
||||
import { GeodataPlacesTable } from 'src/schema/tables/geodata-places.table';
|
||||
import { LibraryTable } from 'src/schema/tables/library.table';
|
||||
import { MemoryTable } from 'src/schema/tables/memory.table';
|
||||
import { MemoryAssetTable } from 'src/schema/tables/memory_asset.table';
|
||||
import { MoveTable } from 'src/schema/tables/move.table';
|
||||
import {
|
||||
NaturalEarthCountriesTable,
|
||||
NaturalEarthCountriesTempTable,
|
||||
} from 'src/schema/tables/natural-earth-countries.table';
|
||||
import { PartnerAuditTable } from 'src/schema/tables/partner-audit.table';
|
||||
import { PartnerTable } from 'src/schema/tables/partner.table';
|
||||
import { PersonTable } from 'src/schema/tables/person.table';
|
||||
import { SessionTable } from 'src/schema/tables/session.table';
|
||||
import { SharedLinkAssetTable } from 'src/schema/tables/shared-link-asset.table';
|
||||
import { SharedLinkTable } from 'src/schema/tables/shared-link.table';
|
||||
import { SmartSearchTable } from 'src/schema/tables/smart-search.table';
|
||||
import { StackTable } from 'src/schema/tables/stack.table';
|
||||
import { SessionSyncCheckpointTable } from 'src/schema/tables/sync-checkpoint.table';
|
||||
import { SystemMetadataTable } from 'src/schema/tables/system-metadata.table';
|
||||
import { TagAssetTable } from 'src/schema/tables/tag-asset.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';
|
||||
|
||||
export const tables = [
|
||||
ActivityTable,
|
||||
AlbumAssetTable,
|
||||
AlbumUserTable,
|
||||
AlbumTable,
|
||||
APIKeyTable,
|
||||
AssetAuditTable,
|
||||
AssetFaceTable,
|
||||
AssetJobStatusTable,
|
||||
AssetTable,
|
||||
AuditTable,
|
||||
ExifTable,
|
||||
FaceSearchTable,
|
||||
GeodataPlacesTable,
|
||||
LibraryTable,
|
||||
MemoryAssetTable,
|
||||
MemoryTable,
|
||||
MoveTable,
|
||||
NaturalEarthCountriesTable,
|
||||
NaturalEarthCountriesTempTable,
|
||||
PartnerAuditTable,
|
||||
PartnerTable,
|
||||
PersonTable,
|
||||
SessionTable,
|
||||
SharedLinkAssetTable,
|
||||
SharedLinkTable,
|
||||
SmartSearchTable,
|
||||
StackTable,
|
||||
SessionSyncCheckpointTable,
|
||||
SystemMetadataTable,
|
||||
TagAssetTable,
|
||||
UserAuditTable,
|
||||
UserMetadataTable,
|
||||
UserTable,
|
||||
VersionHistoryTable,
|
||||
];
|
||||
import 'src/schema/tables/activity.table';
|
||||
import 'src/schema/tables/album-asset.table';
|
||||
import 'src/schema/tables/album-user.table';
|
||||
import 'src/schema/tables/album.table';
|
||||
import 'src/schema/tables/api-key.table';
|
||||
import 'src/schema/tables/asset-audit.table';
|
||||
import 'src/schema/tables/asset-face.table';
|
||||
import 'src/schema/tables/asset-files.table';
|
||||
import 'src/schema/tables/asset-job-status.table';
|
||||
import 'src/schema/tables/asset.table';
|
||||
import 'src/schema/tables/audit.table';
|
||||
import 'src/schema/tables/exif.table';
|
||||
import 'src/schema/tables/face-search.table';
|
||||
import 'src/schema/tables/geodata-places.table';
|
||||
import 'src/schema/tables/library.table';
|
||||
import 'src/schema/tables/memory.table';
|
||||
import 'src/schema/tables/memory_asset.table';
|
||||
import 'src/schema/tables/move.table';
|
||||
import 'src/schema/tables/natural-earth-countries.table';
|
||||
import 'src/schema/tables/partner-audit.table';
|
||||
import 'src/schema/tables/partner.table';
|
||||
import 'src/schema/tables/person.table';
|
||||
import 'src/schema/tables/session.table';
|
||||
import 'src/schema/tables/shared-link-asset.table';
|
||||
import 'src/schema/tables/shared-link.table';
|
||||
import 'src/schema/tables/smart-search.table';
|
||||
import 'src/schema/tables/stack.table';
|
||||
import 'src/schema/tables/sync-checkpoint.table';
|
||||
import 'src/schema/tables/system-metadata.table';
|
||||
import 'src/schema/tables/tag-asset.table';
|
||||
import 'src/schema/tables/tag-closure.table';
|
||||
import 'src/schema/tables/user-audit.table';
|
||||
import 'src/schema/tables/user-metadata.table';
|
||||
import 'src/schema/tables/user.table';
|
||||
import 'src/schema/tables/version-history.table';
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { UpdatedAtTrigger, UpdateIdColumn } from 'src/decorators';
|
||||
import { UserTable } from 'src/schema/tables/user.table';
|
||||
import {
|
||||
Column,
|
||||
@@ -8,10 +9,10 @@ import {
|
||||
PrimaryGeneratedColumn,
|
||||
Table,
|
||||
UpdateDateColumn,
|
||||
UpdateIdColumn,
|
||||
} from 'src/sql-tools';
|
||||
|
||||
@Table('libraries')
|
||||
@UpdatedAtTrigger('libraries_updated_at')
|
||||
export class LibraryTable {
|
||||
@PrimaryGeneratedColumn()
|
||||
id!: string;
|
||||
@@ -34,13 +35,13 @@ export class LibraryTable {
|
||||
@UpdateDateColumn()
|
||||
updatedAt!: Date;
|
||||
|
||||
@ColumnIndex('IDX_libraries_update_id')
|
||||
@UpdateIdColumn()
|
||||
updateId?: string;
|
||||
|
||||
@DeleteDateColumn()
|
||||
deletedAt?: Date;
|
||||
|
||||
@Column({ type: 'timestamp with time zone', nullable: true })
|
||||
refreshedAt!: Date | null;
|
||||
|
||||
@ColumnIndex('IDX_libraries_update_id')
|
||||
@UpdateIdColumn()
|
||||
updateId?: string;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { UpdatedAtTrigger, UpdateIdColumn } from 'src/decorators';
|
||||
import { MemoryType } from 'src/enum';
|
||||
import { UserTable } from 'src/schema/tables/user.table';
|
||||
import {
|
||||
@@ -9,11 +10,11 @@ import {
|
||||
PrimaryGeneratedColumn,
|
||||
Table,
|
||||
UpdateDateColumn,
|
||||
UpdateIdColumn,
|
||||
} from 'src/sql-tools';
|
||||
import { MemoryData } from 'src/types';
|
||||
|
||||
@Table('memories')
|
||||
@UpdatedAtTrigger('memories_updated_at')
|
||||
export class MemoryTable<T extends MemoryType = MemoryType> {
|
||||
@PrimaryGeneratedColumn()
|
||||
id!: string;
|
||||
@@ -24,10 +25,6 @@ export class MemoryTable<T extends MemoryType = MemoryType> {
|
||||
@UpdateDateColumn()
|
||||
updatedAt!: Date;
|
||||
|
||||
@ColumnIndex('IDX_memories_update_id')
|
||||
@UpdateIdColumn()
|
||||
updateId?: string;
|
||||
|
||||
@DeleteDateColumn()
|
||||
deletedAt?: Date;
|
||||
|
||||
@@ -48,13 +45,17 @@ export class MemoryTable<T extends MemoryType = MemoryType> {
|
||||
@Column({ type: 'timestamp with time zone' })
|
||||
memoryAt!: Date;
|
||||
|
||||
/** when the user last viewed the memory */
|
||||
@Column({ type: 'timestamp with time zone', nullable: true })
|
||||
seenAt?: Date;
|
||||
|
||||
@Column({ type: 'timestamp with time zone', nullable: true })
|
||||
showAt?: Date;
|
||||
|
||||
@Column({ type: 'timestamp with time zone', nullable: true })
|
||||
hideAt?: Date;
|
||||
|
||||
/** when the user last viewed the memory */
|
||||
@Column({ type: 'timestamp with time zone', nullable: true })
|
||||
seenAt?: Date;
|
||||
@ColumnIndex('IDX_memories_update_id')
|
||||
@UpdateIdColumn()
|
||||
updateId?: string;
|
||||
}
|
||||
|
||||
@@ -4,11 +4,11 @@ import { ColumnIndex, ForeignKeyColumn, Table } from 'src/sql-tools';
|
||||
|
||||
@Table('memories_assets_assets')
|
||||
export class MemoryAssetTable {
|
||||
@ColumnIndex()
|
||||
@ForeignKeyColumn(() => AssetTable, { onUpdate: 'CASCADE', onDelete: 'CASCADE', primary: true })
|
||||
assetsId!: string;
|
||||
|
||||
@ColumnIndex()
|
||||
@ForeignKeyColumn(() => MemoryTable, { onUpdate: 'CASCADE', onDelete: 'CASCADE', primary: true })
|
||||
memoriesId!: string;
|
||||
|
||||
@ColumnIndex()
|
||||
@ForeignKeyColumn(() => AssetTable, { onUpdate: 'CASCADE', onDelete: 'CASCADE', primary: true })
|
||||
assetsId!: string;
|
||||
}
|
||||
|
||||
@@ -1,26 +1,8 @@
|
||||
import { Column, PrimaryColumn, PrimaryGeneratedColumn, Table } from 'src/sql-tools';
|
||||
import { Column, PrimaryGeneratedColumn, Table } from 'src/sql-tools';
|
||||
|
||||
@Table({ name: 'naturalearth_countries', synchronize: false })
|
||||
@Table({ name: 'naturalearth_countries' })
|
||||
export class NaturalEarthCountriesTable {
|
||||
@PrimaryColumn({ type: 'serial' })
|
||||
id!: number;
|
||||
|
||||
@Column({ type: 'character varying', length: 50 })
|
||||
admin!: string;
|
||||
|
||||
@Column({ type: 'character varying', length: 3 })
|
||||
admin_a3!: string;
|
||||
|
||||
@Column({ type: 'character varying', length: 50 })
|
||||
type!: string;
|
||||
|
||||
@Column({ type: 'polygon' })
|
||||
coordinates!: string;
|
||||
}
|
||||
|
||||
@Table({ name: 'naturalearth_countries_tmp', synchronize: false })
|
||||
export class NaturalEarthCountriesTempTable {
|
||||
@PrimaryGeneratedColumn()
|
||||
@PrimaryGeneratedColumn({ strategy: 'identity' })
|
||||
id!: number;
|
||||
|
||||
@Column({ type: 'character varying', length: 50 })
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { Column, ColumnIndex, CreateDateColumn, PrimaryGeneratedColumn, Table } from 'src/sql-tools';
|
||||
import { PrimaryGeneratedUuidV7Column } from 'src/decorators';
|
||||
import { Column, ColumnIndex, CreateDateColumn, Table } from 'src/sql-tools';
|
||||
|
||||
@Table('partners_audit')
|
||||
export class PartnerAuditTable {
|
||||
@PrimaryGeneratedColumn({ type: 'v7' })
|
||||
@PrimaryGeneratedUuidV7Column()
|
||||
id!: string;
|
||||
|
||||
@ColumnIndex('IDX_partners_audit_shared_by_id')
|
||||
|
||||
@@ -1,15 +1,25 @@
|
||||
import { UpdatedAtTrigger, UpdateIdColumn } from 'src/decorators';
|
||||
import { partners_delete_audit } from 'src/schema/functions';
|
||||
import { UserTable } from 'src/schema/tables/user.table';
|
||||
import {
|
||||
AfterDeleteTrigger,
|
||||
Column,
|
||||
ColumnIndex,
|
||||
CreateDateColumn,
|
||||
ForeignKeyColumn,
|
||||
Table,
|
||||
UpdateDateColumn,
|
||||
UpdateIdColumn,
|
||||
} from 'src/sql-tools';
|
||||
|
||||
@Table('partners')
|
||||
@UpdatedAtTrigger('partners_updated_at')
|
||||
@AfterDeleteTrigger({
|
||||
name: 'partners_delete_audit',
|
||||
scope: 'statement',
|
||||
function: partners_delete_audit,
|
||||
referencingOldTableAs: 'old',
|
||||
when: 'pg_trigger_depth() = 0',
|
||||
})
|
||||
export class PartnerTable {
|
||||
@ForeignKeyColumn(() => UserTable, { onDelete: 'CASCADE', primary: true })
|
||||
sharedById!: string;
|
||||
@@ -23,10 +33,10 @@ export class PartnerTable {
|
||||
@UpdateDateColumn()
|
||||
updatedAt!: Date;
|
||||
|
||||
@Column({ type: 'boolean', default: false })
|
||||
inTimeline!: boolean;
|
||||
|
||||
@ColumnIndex('IDX_partners_update_id')
|
||||
@UpdateIdColumn()
|
||||
updateId!: string;
|
||||
|
||||
@Column({ type: 'boolean', default: false })
|
||||
inTimeline!: boolean;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { UpdatedAtTrigger, UpdateIdColumn } from 'src/decorators';
|
||||
import { AssetFaceTable } from 'src/schema/tables/asset-face.table';
|
||||
import { UserTable } from 'src/schema/tables/user.table';
|
||||
import {
|
||||
@@ -9,10 +10,10 @@ import {
|
||||
PrimaryGeneratedColumn,
|
||||
Table,
|
||||
UpdateDateColumn,
|
||||
UpdateIdColumn,
|
||||
} from 'src/sql-tools';
|
||||
|
||||
@Table('person')
|
||||
@UpdatedAtTrigger('person_updated_at')
|
||||
@Check({ name: 'CHK_b0f82b0ed662bfc24fbb58bb45', expression: `"birthDate" <= CURRENT_DATE` })
|
||||
export class PersonTable {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
@@ -24,31 +25,31 @@ export class PersonTable {
|
||||
@UpdateDateColumn()
|
||||
updatedAt!: Date;
|
||||
|
||||
@ColumnIndex('IDX_person_update_id')
|
||||
@UpdateIdColumn()
|
||||
updateId!: string;
|
||||
|
||||
@ForeignKeyColumn(() => UserTable, { onDelete: 'CASCADE', onUpdate: 'CASCADE', nullable: false })
|
||||
ownerId!: string;
|
||||
|
||||
@Column({ default: '' })
|
||||
name!: string;
|
||||
|
||||
@Column({ type: 'date', nullable: true })
|
||||
birthDate!: Date | string | null;
|
||||
|
||||
@Column({ default: '' })
|
||||
thumbnailPath!: string;
|
||||
|
||||
@ForeignKeyColumn(() => AssetFaceTable, { onDelete: 'SET NULL', nullable: true })
|
||||
faceAssetId!: string | null;
|
||||
|
||||
@Column({ type: 'boolean', default: false })
|
||||
isHidden!: boolean;
|
||||
|
||||
@Column({ type: 'date', nullable: true })
|
||||
birthDate!: Date | string | null;
|
||||
|
||||
@ForeignKeyColumn(() => AssetFaceTable, { onDelete: 'SET NULL', nullable: true })
|
||||
faceAssetId!: string | null;
|
||||
|
||||
@Column({ type: 'boolean', default: false })
|
||||
isFavorite!: boolean;
|
||||
|
||||
@Column({ type: 'character varying', nullable: true, default: null })
|
||||
color?: string | null;
|
||||
|
||||
@ColumnIndex('IDX_person_update_id')
|
||||
@UpdateIdColumn()
|
||||
updateId!: string;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { UpdatedAtTrigger, UpdateIdColumn } from 'src/decorators';
|
||||
import { UserTable } from 'src/schema/tables/user.table';
|
||||
import {
|
||||
Column,
|
||||
@@ -7,10 +8,10 @@ import {
|
||||
PrimaryGeneratedColumn,
|
||||
Table,
|
||||
UpdateDateColumn,
|
||||
UpdateIdColumn,
|
||||
} from 'src/sql-tools';
|
||||
|
||||
@Table({ name: 'sessions', primaryConstraintName: 'PK_48cb6b5c20faa63157b3c1baf7f' })
|
||||
@UpdatedAtTrigger('sessions_updated_at')
|
||||
export class SessionTable {
|
||||
@PrimaryGeneratedColumn()
|
||||
id!: string;
|
||||
@@ -19,22 +20,22 @@ export class SessionTable {
|
||||
@Column()
|
||||
token!: string;
|
||||
|
||||
@ForeignKeyColumn(() => UserTable, { onUpdate: 'CASCADE', onDelete: 'CASCADE' })
|
||||
userId!: string;
|
||||
|
||||
@CreateDateColumn()
|
||||
createdAt!: Date;
|
||||
|
||||
@UpdateDateColumn()
|
||||
updatedAt!: Date;
|
||||
|
||||
@ColumnIndex('IDX_sessions_update_id')
|
||||
@UpdateIdColumn()
|
||||
updateId!: string;
|
||||
@ForeignKeyColumn(() => UserTable, { onUpdate: 'CASCADE', onDelete: 'CASCADE' })
|
||||
userId!: string;
|
||||
|
||||
@Column({ default: '' })
|
||||
deviceType!: string;
|
||||
|
||||
@Column({ default: '' })
|
||||
deviceOS!: string;
|
||||
|
||||
@ColumnIndex('IDX_sessions_update_id')
|
||||
@UpdateIdColumn()
|
||||
updateId!: string;
|
||||
}
|
||||
|
||||
@@ -20,16 +20,9 @@ export class SharedLinkTable {
|
||||
@Column({ type: 'character varying', nullable: true })
|
||||
description!: string | null;
|
||||
|
||||
@Column({ type: 'character varying', nullable: true })
|
||||
password!: string | null;
|
||||
|
||||
@ForeignKeyColumn(() => UserTable, { onDelete: 'CASCADE', onUpdate: 'CASCADE' })
|
||||
userId!: string;
|
||||
|
||||
@ColumnIndex('IDX_sharedlink_albumId')
|
||||
@ForeignKeyColumn(() => AlbumTable, { nullable: true, onDelete: 'CASCADE', onUpdate: 'CASCADE' })
|
||||
albumId!: string;
|
||||
|
||||
@ColumnIndex('IDX_sharedlink_key')
|
||||
@Column({ type: 'bytea' })
|
||||
key!: Buffer; // use to access the inidividual asset
|
||||
@@ -46,9 +39,16 @@ export class SharedLinkTable {
|
||||
@Column({ type: 'boolean', default: false })
|
||||
allowUpload!: boolean;
|
||||
|
||||
@ColumnIndex('IDX_sharedlink_albumId')
|
||||
@ForeignKeyColumn(() => AlbumTable, { nullable: true, onDelete: 'CASCADE', onUpdate: 'CASCADE' })
|
||||
albumId!: string;
|
||||
|
||||
@Column({ type: 'boolean', default: true })
|
||||
allowDownload!: boolean;
|
||||
|
||||
@Column({ type: 'boolean', default: true })
|
||||
showExif!: boolean;
|
||||
|
||||
@Column({ type: 'character varying', nullable: true })
|
||||
password!: string | null;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
import { AssetTable } from 'src/schema/tables/asset.table';
|
||||
import { Column, ColumnIndex, ForeignKeyColumn, Table } from 'src/sql-tools';
|
||||
import { Column, ForeignKeyColumn, Index, Table } from 'src/sql-tools';
|
||||
|
||||
@Table({ name: 'smart_search', primaryConstraintName: 'smart_search_pkey' })
|
||||
@Index({
|
||||
name: 'clip_index',
|
||||
using: 'hnsw',
|
||||
expression: `embedding vector_cosine_ops`,
|
||||
with: `ef_construction = 300, m = 16`,
|
||||
synchronize: false,
|
||||
})
|
||||
export class SmartSearchTable {
|
||||
@ForeignKeyColumn(() => AssetTable, {
|
||||
onDelete: 'CASCADE',
|
||||
@@ -10,7 +17,6 @@ export class SmartSearchTable {
|
||||
})
|
||||
assetId!: string;
|
||||
|
||||
@ColumnIndex({ name: 'clip_index', synchronize: false })
|
||||
@Column({ type: 'vector', array: true, length: 512, synchronize: false })
|
||||
@Column({ type: 'vector', length: 512, storage: 'external', synchronize: false })
|
||||
embedding!: string;
|
||||
}
|
||||
|
||||
@@ -7,10 +7,10 @@ export class StackTable {
|
||||
@PrimaryGeneratedColumn()
|
||||
id!: string;
|
||||
|
||||
@ForeignKeyColumn(() => UserTable, { onDelete: 'CASCADE', onUpdate: 'CASCADE' })
|
||||
ownerId!: string;
|
||||
|
||||
//TODO: Add constraint to ensure primary asset exists in the assets array
|
||||
@ForeignKeyColumn(() => AssetTable, { nullable: false, unique: true })
|
||||
primaryAssetId!: string;
|
||||
|
||||
@ForeignKeyColumn(() => UserTable, { onDelete: 'CASCADE', onUpdate: 'CASCADE' })
|
||||
ownerId!: string;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { UpdatedAtTrigger, UpdateIdColumn } from 'src/decorators';
|
||||
import { SyncEntityType } from 'src/enum';
|
||||
import { SessionTable } from 'src/schema/tables/session.table';
|
||||
import {
|
||||
@@ -8,10 +9,10 @@ import {
|
||||
PrimaryColumn,
|
||||
Table,
|
||||
UpdateDateColumn,
|
||||
UpdateIdColumn,
|
||||
} from 'src/sql-tools';
|
||||
|
||||
@Table('session_sync_checkpoints')
|
||||
@UpdatedAtTrigger('session_sync_checkpoints_updated_at')
|
||||
export class SessionSyncCheckpointTable {
|
||||
@ForeignKeyColumn(() => SessionTable, { onDelete: 'CASCADE', onUpdate: 'CASCADE', primary: true })
|
||||
sessionId!: string;
|
||||
@@ -25,10 +26,10 @@ export class SessionSyncCheckpointTable {
|
||||
@UpdateDateColumn()
|
||||
updatedAt!: Date;
|
||||
|
||||
@Column()
|
||||
ack!: string;
|
||||
|
||||
@ColumnIndex('IDX_session_sync_checkpoints_update_id')
|
||||
@UpdateIdColumn()
|
||||
updateId!: string;
|
||||
|
||||
@Column()
|
||||
ack!: string;
|
||||
}
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
import { TagTable } from 'src/schema/tables/tag.table';
|
||||
import { ColumnIndex, ForeignKeyColumn, PrimaryColumn, Table } from 'src/sql-tools';
|
||||
import { ColumnIndex, ForeignKeyColumn, Table } from 'src/sql-tools';
|
||||
|
||||
@Table('tags_closure')
|
||||
export class TagClosureTable {
|
||||
@PrimaryColumn()
|
||||
@ColumnIndex()
|
||||
@ForeignKeyColumn(() => TagTable, { onDelete: 'CASCADE', onUpdate: 'NO ACTION' })
|
||||
@ForeignKeyColumn(() => TagTable, { primary: true, onDelete: 'CASCADE', onUpdate: 'NO ACTION' })
|
||||
id_ancestor!: string;
|
||||
|
||||
@PrimaryColumn()
|
||||
@ColumnIndex()
|
||||
@ForeignKeyColumn(() => TagTable, { onDelete: 'CASCADE', onUpdate: 'NO ACTION' })
|
||||
@ForeignKeyColumn(() => TagTable, { primary: true, onDelete: 'CASCADE', onUpdate: 'NO ACTION' })
|
||||
id_descendant!: string;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { UpdatedAtTrigger, UpdateIdColumn } from 'src/decorators';
|
||||
import { UserTable } from 'src/schema/tables/user.table';
|
||||
import {
|
||||
Column,
|
||||
@@ -8,15 +9,18 @@ import {
|
||||
Table,
|
||||
Unique,
|
||||
UpdateDateColumn,
|
||||
UpdateIdColumn,
|
||||
} from 'src/sql-tools';
|
||||
|
||||
@Table('tags')
|
||||
@UpdatedAtTrigger('tags_updated_at')
|
||||
@Unique({ columns: ['userId', 'value'] })
|
||||
export class TagTable {
|
||||
@PrimaryGeneratedColumn()
|
||||
id!: string;
|
||||
|
||||
@ForeignKeyColumn(() => UserTable, { onUpdate: 'CASCADE', onDelete: 'CASCADE' })
|
||||
userId!: string;
|
||||
|
||||
@Column()
|
||||
value!: string;
|
||||
|
||||
@@ -26,16 +30,13 @@ export class TagTable {
|
||||
@UpdateDateColumn()
|
||||
updatedAt!: Date;
|
||||
|
||||
@ColumnIndex('IDX_tags_update_id')
|
||||
@UpdateIdColumn()
|
||||
updateId!: string;
|
||||
|
||||
@Column({ type: 'character varying', nullable: true, default: null })
|
||||
color!: string | null;
|
||||
|
||||
@ForeignKeyColumn(() => TagTable, { nullable: true, onDelete: 'CASCADE' })
|
||||
parentId?: string;
|
||||
|
||||
@ForeignKeyColumn(() => UserTable, { onUpdate: 'CASCADE', onDelete: 'CASCADE' })
|
||||
userId!: string;
|
||||
@ColumnIndex('IDX_tags_update_id')
|
||||
@UpdateIdColumn()
|
||||
updateId!: string;
|
||||
}
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
import { Column, ColumnIndex, CreateDateColumn, PrimaryGeneratedColumn, Table } from 'src/sql-tools';
|
||||
import { PrimaryGeneratedUuidV7Column } from 'src/decorators';
|
||||
import { Column, ColumnIndex, CreateDateColumn, Table } from 'src/sql-tools';
|
||||
|
||||
@Table('users_audit')
|
||||
export class UserAuditTable {
|
||||
@PrimaryGeneratedColumn({ type: 'v7' })
|
||||
id!: string;
|
||||
|
||||
@Column({ type: 'uuid' })
|
||||
userId!: string;
|
||||
|
||||
@ColumnIndex('IDX_users_audit_deleted_at')
|
||||
@CreateDateColumn({ default: () => 'clock_timestamp()' })
|
||||
deletedAt!: Date;
|
||||
|
||||
@PrimaryGeneratedUuidV7Column()
|
||||
id!: string;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { ColumnType } from 'kysely';
|
||||
import { UpdatedAtTrigger, UpdateIdColumn } from 'src/decorators';
|
||||
import { UserStatus } from 'src/enum';
|
||||
import { users_delete_audit } from 'src/schema/functions';
|
||||
import {
|
||||
AfterDeleteTrigger,
|
||||
Column,
|
||||
ColumnIndex,
|
||||
CreateDateColumn,
|
||||
@@ -9,7 +12,6 @@ import {
|
||||
PrimaryGeneratedColumn,
|
||||
Table,
|
||||
UpdateDateColumn,
|
||||
UpdateIdColumn,
|
||||
} from 'src/sql-tools';
|
||||
|
||||
type Timestamp = ColumnType<Date, Date | string, Date | string>;
|
||||
@@ -17,50 +19,51 @@ 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({
|
||||
name: 'users_delete_audit',
|
||||
scope: 'statement',
|
||||
function: users_delete_audit,
|
||||
referencingOldTableAs: 'old',
|
||||
when: 'pg_trigger_depth() = 0',
|
||||
})
|
||||
@Index({ name: 'IDX_users_updated_at_asc_id_asc', columns: ['updatedAt', 'id'] })
|
||||
export class UserTable {
|
||||
@PrimaryGeneratedColumn()
|
||||
id!: Generated<string>;
|
||||
|
||||
@Column({ unique: true })
|
||||
email!: string;
|
||||
|
||||
@Column({ default: '' })
|
||||
name!: Generated<string>;
|
||||
password!: Generated<string>;
|
||||
|
||||
@CreateDateColumn()
|
||||
createdAt!: Generated<Timestamp>;
|
||||
|
||||
@Column({ default: '' })
|
||||
profileImagePath!: Generated<string>;
|
||||
|
||||
@Column({ type: 'boolean', default: false })
|
||||
isAdmin!: Generated<boolean>;
|
||||
|
||||
@Column({ unique: true })
|
||||
email!: string;
|
||||
@Column({ type: 'boolean', default: true })
|
||||
shouldChangePassword!: Generated<boolean>;
|
||||
|
||||
@DeleteDateColumn()
|
||||
deletedAt!: Timestamp | null;
|
||||
|
||||
@Column({ default: '' })
|
||||
oauthId!: Generated<string>;
|
||||
|
||||
@UpdateDateColumn()
|
||||
updatedAt!: Generated<Timestamp>;
|
||||
|
||||
@Column({ unique: true, nullable: true, default: null })
|
||||
storageLabel!: string | null;
|
||||
|
||||
@Column({ default: '' })
|
||||
password!: Generated<string>;
|
||||
|
||||
@Column({ default: '' })
|
||||
oauthId!: Generated<string>;
|
||||
|
||||
@Column({ default: '' })
|
||||
profileImagePath!: Generated<string>;
|
||||
|
||||
@Column({ type: 'boolean', default: true })
|
||||
shouldChangePassword!: Generated<boolean>;
|
||||
|
||||
@CreateDateColumn()
|
||||
createdAt!: Generated<Timestamp>;
|
||||
|
||||
@UpdateDateColumn()
|
||||
updatedAt!: Generated<Timestamp>;
|
||||
|
||||
@DeleteDateColumn()
|
||||
deletedAt!: Timestamp | null;
|
||||
|
||||
@Column({ type: 'character varying', default: UserStatus.ACTIVE })
|
||||
status!: Generated<UserStatus>;
|
||||
|
||||
@ColumnIndex({ name: 'IDX_users_update_id' })
|
||||
@UpdateIdColumn()
|
||||
updateId!: Generated<string>;
|
||||
name!: Generated<string>;
|
||||
|
||||
@Column({ type: 'bigint', nullable: true })
|
||||
quotaSizeInBytes!: ColumnType<number> | null;
|
||||
@@ -68,6 +71,13 @@ export class UserTable {
|
||||
@Column({ type: 'bigint', default: 0 })
|
||||
quotaUsageInBytes!: Generated<ColumnType<number>>;
|
||||
|
||||
@Column({ type: 'character varying', default: UserStatus.ACTIVE })
|
||||
status!: Generated<UserStatus>;
|
||||
|
||||
@Column({ type: 'timestamp with time zone', default: () => 'now()' })
|
||||
profileChangedAt!: Generated<Timestamp>;
|
||||
|
||||
@ColumnIndex({ name: 'IDX_users_update_id' })
|
||||
@UpdateIdColumn()
|
||||
updateId!: Generated<string>;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user