mirror of
https://github.com/immich-app/immich.git
synced 2025-07-09 03:04:16 -04:00
refactor: database types (#19624)
This commit is contained in:
parent
09cbc5d3f4
commit
e60bc3c304
@ -29,7 +29,6 @@
|
||||
"migrations:run": "node ./dist/bin/migrations.js run",
|
||||
"schema:drop": "node ./dist/bin/migrations.js query 'DROP schema public cascade; CREATE schema public;'",
|
||||
"schema:reset": "npm run schema:drop && npm run migrations:run",
|
||||
"kysely:codegen": "npx kysely-codegen --include-pattern=\"(public|vectors).*\" --dialect postgres --url postgres://postgres:postgres@localhost/immich --log-level debug --out-file=./src/db.d.ts",
|
||||
"sync:open-api": "node ./dist/bin/sync-open-api.js",
|
||||
"sync:sql": "node ./dist/bin/sync-sql.js",
|
||||
"email:dev": "email dev -p 3050 --dir src/emails",
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { Selectable } from 'kysely';
|
||||
import { Albums, Exif as DatabaseExif } from 'src/db';
|
||||
import { MapAsset } from 'src/dtos/asset-response.dto';
|
||||
import {
|
||||
AlbumUserRole,
|
||||
@ -13,6 +12,8 @@ import {
|
||||
UserAvatarColor,
|
||||
UserStatus,
|
||||
} from 'src/enum';
|
||||
import { AlbumTable } from 'src/schema/tables/album.table';
|
||||
import { ExifTable } from 'src/schema/tables/exif.table';
|
||||
import { UserMetadataItem } from 'src/types';
|
||||
|
||||
export type AuthUser = {
|
||||
@ -193,7 +194,7 @@ export type SharedLink = {
|
||||
userId: string;
|
||||
};
|
||||
|
||||
export type Album = Selectable<Albums> & {
|
||||
export type Album = Selectable<AlbumTable> & {
|
||||
owner: User;
|
||||
assets: MapAsset[];
|
||||
};
|
||||
@ -239,7 +240,7 @@ export type Session = {
|
||||
pinExpiresAt: Date | null;
|
||||
};
|
||||
|
||||
export type Exif = Omit<Selectable<DatabaseExif>, 'updatedAt' | 'updateId'>;
|
||||
export type Exif = Omit<Selectable<ExifTable>, 'updatedAt' | 'updateId'>;
|
||||
|
||||
export type Person = {
|
||||
createdAt: Date;
|
||||
|
540
server/src/db.d.ts
vendored
540
server/src/db.d.ts
vendored
@ -1,540 +0,0 @@
|
||||
/**
|
||||
* This file was generated by kysely-codegen.
|
||||
* Please do not edit it manually.
|
||||
*/
|
||||
|
||||
import type { ColumnType } from 'kysely';
|
||||
import {
|
||||
AlbumUserRole,
|
||||
AssetFileType,
|
||||
AssetOrder,
|
||||
AssetStatus,
|
||||
AssetType,
|
||||
AssetVisibility,
|
||||
MemoryType,
|
||||
NotificationLevel,
|
||||
NotificationType,
|
||||
Permission,
|
||||
SharedLinkType,
|
||||
SourceType,
|
||||
SyncEntityType,
|
||||
} from 'src/enum';
|
||||
import { MemoryAssetAuditTable } from 'src/schema/tables/memory-asset-audit.table';
|
||||
import { MemoryAssetTable } from 'src/schema/tables/memory-asset.table';
|
||||
import { MemoryAuditTable } from 'src/schema/tables/memory-audit.table';
|
||||
import { UserTable } from 'src/schema/tables/user.table';
|
||||
import { UserMetadataItem } from 'src/types';
|
||||
|
||||
export type ArrayType<T> = ArrayTypeImpl<T> extends (infer U)[] ? U[] : ArrayTypeImpl<T>;
|
||||
|
||||
export type ArrayTypeImpl<T> = T extends ColumnType<infer S, infer I, infer U> ? ColumnType<S[], I[], U[]> : T[];
|
||||
|
||||
export type Generated<T> =
|
||||
T extends ColumnType<infer S, infer I, infer U> ? ColumnType<S, I | undefined, U> : ColumnType<T, T | undefined, T>;
|
||||
|
||||
export type Int8 = ColumnType<number>;
|
||||
|
||||
export type Json = JsonValue;
|
||||
|
||||
export type JsonArray = JsonValue[];
|
||||
|
||||
export type JsonObject = {
|
||||
[x: string]: JsonValue | undefined;
|
||||
};
|
||||
|
||||
export type JsonPrimitive = boolean | number | string | null;
|
||||
|
||||
export type JsonValue = JsonArray | JsonObject | JsonPrimitive;
|
||||
|
||||
export type Timestamp = ColumnType<Date, Date | string, Date | string>;
|
||||
|
||||
export interface Activity {
|
||||
albumId: string;
|
||||
assetId: string | null;
|
||||
comment: string | null;
|
||||
createdAt: Generated<Timestamp>;
|
||||
id: Generated<string>;
|
||||
isLiked: Generated<boolean>;
|
||||
updatedAt: Generated<Timestamp>;
|
||||
updateId: Generated<string>;
|
||||
userId: string;
|
||||
}
|
||||
|
||||
export interface Albums {
|
||||
albumName: Generated<string>;
|
||||
/**
|
||||
* Asset ID to be used as thumbnail
|
||||
*/
|
||||
albumThumbnailAssetId: string | null;
|
||||
createdAt: Generated<Timestamp>;
|
||||
deletedAt: Timestamp | null;
|
||||
description: Generated<string>;
|
||||
id: Generated<string>;
|
||||
isActivityEnabled: Generated<boolean>;
|
||||
order: Generated<AssetOrder>;
|
||||
ownerId: string;
|
||||
updatedAt: Generated<Timestamp>;
|
||||
updateId: Generated<string>;
|
||||
}
|
||||
|
||||
export interface AlbumsAudit {
|
||||
deletedAt: Generated<Timestamp>;
|
||||
id: Generated<string>;
|
||||
albumId: string;
|
||||
userId: string;
|
||||
}
|
||||
|
||||
export interface AlbumUsersAudit {
|
||||
deletedAt: Generated<Timestamp>;
|
||||
id: Generated<string>;
|
||||
albumId: string;
|
||||
userId: string;
|
||||
}
|
||||
|
||||
export interface AlbumsAssetsAssets {
|
||||
albumsId: string;
|
||||
assetsId: string;
|
||||
createdAt: Generated<Timestamp>;
|
||||
updatedAt: Generated<Timestamp>;
|
||||
updateId: Generated<string>;
|
||||
}
|
||||
|
||||
export interface AlbumAssetsAudit {
|
||||
deletedAt: Generated<Timestamp>;
|
||||
id: Generated<string>;
|
||||
albumId: string;
|
||||
assetId: string;
|
||||
}
|
||||
|
||||
export interface AlbumsSharedUsersUsers {
|
||||
albumsId: string;
|
||||
role: Generated<AlbumUserRole>;
|
||||
usersId: string;
|
||||
createId: Generated<string>;
|
||||
createdAt: Generated<Timestamp>;
|
||||
updateId: Generated<string>;
|
||||
updatedAt: Generated<Timestamp>;
|
||||
}
|
||||
|
||||
export interface ApiKeys {
|
||||
createdAt: Generated<Timestamp>;
|
||||
id: Generated<string>;
|
||||
key: string;
|
||||
name: string;
|
||||
permissions: Permission[];
|
||||
updatedAt: Generated<Timestamp>;
|
||||
updateId: Generated<string>;
|
||||
userId: string;
|
||||
}
|
||||
|
||||
export interface AssetFaces {
|
||||
assetId: string;
|
||||
boundingBoxX1: Generated<number>;
|
||||
boundingBoxX2: Generated<number>;
|
||||
boundingBoxY1: Generated<number>;
|
||||
boundingBoxY2: Generated<number>;
|
||||
deletedAt: Timestamp | null;
|
||||
id: Generated<string>;
|
||||
imageHeight: Generated<number>;
|
||||
imageWidth: Generated<number>;
|
||||
personId: string | null;
|
||||
sourceType: Generated<SourceType>;
|
||||
}
|
||||
|
||||
export interface AssetFiles {
|
||||
assetId: string;
|
||||
createdAt: Generated<Timestamp>;
|
||||
id: Generated<string>;
|
||||
path: string;
|
||||
type: AssetFileType;
|
||||
updatedAt: Generated<Timestamp>;
|
||||
updateId: Generated<string>;
|
||||
}
|
||||
|
||||
export interface AssetJobStatus {
|
||||
assetId: string;
|
||||
duplicatesDetectedAt: Timestamp | null;
|
||||
facesRecognizedAt: Timestamp | null;
|
||||
metadataExtractedAt: Timestamp | null;
|
||||
previewAt: Timestamp | null;
|
||||
thumbnailAt: Timestamp | null;
|
||||
}
|
||||
|
||||
export interface AssetsAudit {
|
||||
deletedAt: Generated<Timestamp>;
|
||||
id: Generated<string>;
|
||||
assetId: string;
|
||||
ownerId: string;
|
||||
}
|
||||
|
||||
export interface Assets {
|
||||
checksum: Buffer;
|
||||
createdAt: Generated<Timestamp>;
|
||||
deletedAt: Timestamp | null;
|
||||
deviceAssetId: string;
|
||||
deviceId: string;
|
||||
duplicateId: string | null;
|
||||
duration: string | null;
|
||||
encodedVideoPath: Generated<string | null>;
|
||||
fileCreatedAt: Timestamp;
|
||||
fileModifiedAt: Timestamp;
|
||||
id: Generated<string>;
|
||||
isExternal: Generated<boolean>;
|
||||
isFavorite: Generated<boolean>;
|
||||
isOffline: Generated<boolean>;
|
||||
visibility: Generated<AssetVisibility>;
|
||||
libraryId: string | null;
|
||||
livePhotoVideoId: string | null;
|
||||
localDateTime: Timestamp;
|
||||
originalFileName: string;
|
||||
originalPath: string;
|
||||
ownerId: string;
|
||||
sidecarPath: string | null;
|
||||
stackId: string | null;
|
||||
status: Generated<AssetStatus>;
|
||||
thumbhash: Buffer | null;
|
||||
type: AssetType;
|
||||
updatedAt: Generated<Timestamp>;
|
||||
updateId: Generated<string>;
|
||||
}
|
||||
|
||||
export interface AssetStack {
|
||||
id: Generated<string>;
|
||||
ownerId: string;
|
||||
primaryAssetId: string;
|
||||
}
|
||||
|
||||
export interface Audit {
|
||||
action: string;
|
||||
createdAt: Generated<Timestamp>;
|
||||
entityId: string;
|
||||
entityType: string;
|
||||
id: Generated<number>;
|
||||
ownerId: string;
|
||||
}
|
||||
|
||||
export interface Exif {
|
||||
assetId: string;
|
||||
updateId: Generated<string>;
|
||||
updatedAt: Generated<Timestamp>;
|
||||
autoStackId: string | null;
|
||||
bitsPerSample: number | null;
|
||||
city: string | null;
|
||||
colorspace: string | null;
|
||||
country: string | null;
|
||||
dateTimeOriginal: Timestamp | null;
|
||||
description: Generated<string>;
|
||||
exifImageHeight: number | null;
|
||||
exifImageWidth: number | null;
|
||||
exposureTime: string | null;
|
||||
fileSizeInByte: Int8 | null;
|
||||
fNumber: number | null;
|
||||
focalLength: number | null;
|
||||
fps: number | null;
|
||||
iso: number | null;
|
||||
latitude: number | null;
|
||||
lensModel: string | null;
|
||||
livePhotoCID: string | null;
|
||||
longitude: number | null;
|
||||
make: string | null;
|
||||
model: string | null;
|
||||
modifyDate: Timestamp | null;
|
||||
orientation: string | null;
|
||||
profileDescription: string | null;
|
||||
projectionType: string | null;
|
||||
rating: number | null;
|
||||
state: string | null;
|
||||
timeZone: string | null;
|
||||
}
|
||||
|
||||
export interface FaceSearch {
|
||||
embedding: string;
|
||||
faceId: string;
|
||||
}
|
||||
|
||||
export interface GeodataPlaces {
|
||||
admin1Code: string | null;
|
||||
admin1Name: string | null;
|
||||
admin2Code: string | null;
|
||||
admin2Name: string | null;
|
||||
alternateNames: string | null;
|
||||
countryCode: string;
|
||||
id: number;
|
||||
latitude: number;
|
||||
longitude: number;
|
||||
modificationDate: Timestamp;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface Libraries {
|
||||
createdAt: Generated<Timestamp>;
|
||||
deletedAt: Timestamp | null;
|
||||
exclusionPatterns: string[];
|
||||
id: Generated<string>;
|
||||
importPaths: string[];
|
||||
name: string;
|
||||
ownerId: string;
|
||||
refreshedAt: Timestamp | null;
|
||||
updatedAt: Generated<Timestamp>;
|
||||
updateId: Generated<string>;
|
||||
}
|
||||
|
||||
export interface Memories {
|
||||
createdAt: Generated<Timestamp>;
|
||||
data: object;
|
||||
deletedAt: Timestamp | null;
|
||||
hideAt: Timestamp | null;
|
||||
id: Generated<string>;
|
||||
isSaved: Generated<boolean>;
|
||||
memoryAt: Timestamp;
|
||||
ownerId: string;
|
||||
seenAt: Timestamp | null;
|
||||
showAt: Timestamp | null;
|
||||
type: MemoryType;
|
||||
updatedAt: Generated<Timestamp>;
|
||||
updateId: Generated<string>;
|
||||
}
|
||||
|
||||
export interface Notifications {
|
||||
id: Generated<string>;
|
||||
createdAt: Generated<Timestamp>;
|
||||
updatedAt: Generated<Timestamp>;
|
||||
deletedAt: Timestamp | null;
|
||||
updateId: Generated<string>;
|
||||
userId: string;
|
||||
level: Generated<NotificationLevel>;
|
||||
type: NotificationType;
|
||||
title: string;
|
||||
description: string | null;
|
||||
data: any | null;
|
||||
readAt: Timestamp | null;
|
||||
}
|
||||
|
||||
export interface Migrations {
|
||||
id: Generated<number>;
|
||||
name: string;
|
||||
timestamp: Int8;
|
||||
}
|
||||
|
||||
export interface MoveHistory {
|
||||
entityId: string;
|
||||
id: Generated<string>;
|
||||
newPath: string;
|
||||
oldPath: string;
|
||||
pathType: string;
|
||||
}
|
||||
|
||||
export interface NaturalearthCountries {
|
||||
admin: string;
|
||||
admin_a3: string;
|
||||
coordinates: string;
|
||||
id: Generated<number>;
|
||||
type: string;
|
||||
}
|
||||
|
||||
export interface PartnersAudit {
|
||||
deletedAt: Generated<Timestamp>;
|
||||
id: Generated<string>;
|
||||
sharedById: string;
|
||||
sharedWithId: string;
|
||||
}
|
||||
|
||||
export interface Partners {
|
||||
createdAt: Generated<Timestamp>;
|
||||
createId: Generated<string>;
|
||||
inTimeline: Generated<boolean>;
|
||||
sharedById: string;
|
||||
sharedWithId: string;
|
||||
updatedAt: Generated<Timestamp>;
|
||||
updateId: Generated<string>;
|
||||
}
|
||||
|
||||
export interface Person {
|
||||
birthDate: Timestamp | null;
|
||||
color: string | null;
|
||||
createdAt: Generated<Timestamp>;
|
||||
faceAssetId: string | null;
|
||||
id: Generated<string>;
|
||||
isFavorite: Generated<boolean>;
|
||||
isHidden: Generated<boolean>;
|
||||
name: Generated<string>;
|
||||
ownerId: string;
|
||||
thumbnailPath: Generated<string>;
|
||||
updatedAt: Generated<Timestamp>;
|
||||
updateId: Generated<string>;
|
||||
}
|
||||
|
||||
export interface Sessions {
|
||||
createdAt: Generated<Timestamp>;
|
||||
deviceOS: Generated<string>;
|
||||
deviceType: Generated<string>;
|
||||
id: Generated<string>;
|
||||
parentId: string | null;
|
||||
expiresAt: Date | null;
|
||||
token: string;
|
||||
updatedAt: Generated<Timestamp>;
|
||||
updateId: Generated<string>;
|
||||
userId: string;
|
||||
pinExpiresAt: Timestamp | null;
|
||||
}
|
||||
|
||||
export interface SessionSyncCheckpoints {
|
||||
ack: string;
|
||||
createdAt: Generated<Timestamp>;
|
||||
sessionId: string;
|
||||
type: SyncEntityType;
|
||||
updatedAt: Generated<Timestamp>;
|
||||
updateId: Generated<string>;
|
||||
}
|
||||
|
||||
export interface SharedLinkAsset {
|
||||
assetsId: string;
|
||||
sharedLinksId: string;
|
||||
}
|
||||
|
||||
export interface SharedLinks {
|
||||
albumId: string | null;
|
||||
allowDownload: Generated<boolean>;
|
||||
allowUpload: Generated<boolean>;
|
||||
createdAt: Generated<Timestamp>;
|
||||
description: string | null;
|
||||
expiresAt: Timestamp | null;
|
||||
id: Generated<string>;
|
||||
key: Buffer;
|
||||
password: string | null;
|
||||
showExif: Generated<boolean>;
|
||||
type: SharedLinkType;
|
||||
userId: string;
|
||||
}
|
||||
|
||||
export interface SmartSearch {
|
||||
assetId: string;
|
||||
embedding: string;
|
||||
}
|
||||
|
||||
export interface SocketIoAttachments {
|
||||
created_at: Generated<Timestamp | null>;
|
||||
id: Generated<Int8>;
|
||||
payload: Buffer | null;
|
||||
}
|
||||
|
||||
export interface SystemConfig {
|
||||
key: string;
|
||||
value: string | null;
|
||||
}
|
||||
|
||||
export interface SystemMetadata {
|
||||
key: string;
|
||||
value: Json;
|
||||
}
|
||||
|
||||
export interface TagAsset {
|
||||
assetsId: string;
|
||||
tagsId: string;
|
||||
}
|
||||
|
||||
export interface Tags {
|
||||
color: string | null;
|
||||
createdAt: Generated<Timestamp>;
|
||||
id: Generated<string>;
|
||||
parentId: string | null;
|
||||
updatedAt: Generated<Timestamp>;
|
||||
updateId: Generated<string>;
|
||||
userId: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
export interface TagsClosure {
|
||||
id_ancestor: string;
|
||||
id_descendant: string;
|
||||
}
|
||||
|
||||
export interface TypeormMetadata {
|
||||
database: string | null;
|
||||
name: string | null;
|
||||
schema: string | null;
|
||||
table: string | null;
|
||||
type: string;
|
||||
value: string | null;
|
||||
}
|
||||
|
||||
export interface UserMetadata extends UserMetadataItem {
|
||||
userId: string;
|
||||
}
|
||||
|
||||
export interface UsersAudit {
|
||||
id: Generated<string>;
|
||||
userId: string;
|
||||
deletedAt: Generated<Timestamp>;
|
||||
}
|
||||
|
||||
export interface VectorsPgVectorIndexStat {
|
||||
idx_growing: ArrayType<Int8> | null;
|
||||
idx_indexing: boolean | null;
|
||||
idx_options: string | null;
|
||||
idx_sealed: ArrayType<Int8> | null;
|
||||
idx_size: Int8 | null;
|
||||
idx_status: string | null;
|
||||
idx_tuples: Int8 | null;
|
||||
idx_write: Int8 | null;
|
||||
indexname: string | null;
|
||||
indexrelid: number | null;
|
||||
tablename: string | null;
|
||||
tablerelid: number | null;
|
||||
}
|
||||
|
||||
export interface VersionHistory {
|
||||
createdAt: Generated<Timestamp>;
|
||||
id: Generated<string>;
|
||||
version: string;
|
||||
}
|
||||
|
||||
export interface DB {
|
||||
activity: Activity;
|
||||
albums: Albums;
|
||||
albums_audit: AlbumsAudit;
|
||||
albums_assets_assets: AlbumsAssetsAssets;
|
||||
album_assets_audit: AlbumAssetsAudit;
|
||||
albums_shared_users_users: AlbumsSharedUsersUsers;
|
||||
album_users_audit: AlbumUsersAudit;
|
||||
api_keys: ApiKeys;
|
||||
asset_faces: AssetFaces;
|
||||
asset_files: AssetFiles;
|
||||
asset_job_status: AssetJobStatus;
|
||||
asset_stack: AssetStack;
|
||||
assets: Assets;
|
||||
assets_audit: AssetsAudit;
|
||||
audit: Audit;
|
||||
exif: Exif;
|
||||
face_search: FaceSearch;
|
||||
geodata_places: GeodataPlaces;
|
||||
libraries: Libraries;
|
||||
memories: Memories;
|
||||
memories_audit: MemoryAuditTable;
|
||||
memories_assets_assets: MemoryAssetTable;
|
||||
memory_assets_audit: MemoryAssetAuditTable;
|
||||
migrations: Migrations;
|
||||
notifications: Notifications;
|
||||
move_history: MoveHistory;
|
||||
naturalearth_countries: NaturalearthCountries;
|
||||
partners_audit: PartnersAudit;
|
||||
partners: Partners;
|
||||
person: Person;
|
||||
sessions: Sessions;
|
||||
session_sync_checkpoints: SessionSyncCheckpoints;
|
||||
shared_link__asset: SharedLinkAsset;
|
||||
shared_links: SharedLinks;
|
||||
smart_search: SmartSearch;
|
||||
socket_io_attachments: SocketIoAttachments;
|
||||
system_config: SystemConfig;
|
||||
system_metadata: SystemMetadata;
|
||||
tag_asset: TagAsset;
|
||||
tags: Tags;
|
||||
tags_closure: TagsClosure;
|
||||
typeorm_metadata: TypeormMetadata;
|
||||
user_metadata: UserMetadata;
|
||||
users: UserTable;
|
||||
users_audit: UsersAudit;
|
||||
'vectors.pg_vector_index_stat': VectorsPgVectorIndexStat;
|
||||
version_history: VersionHistory;
|
||||
}
|
@ -4,10 +4,10 @@ import { IsArray, IsInt, IsNotEmpty, IsNumber, IsString, Max, Min, ValidateNeste
|
||||
import { Selectable } from 'kysely';
|
||||
import { DateTime } from 'luxon';
|
||||
import { AssetFace, Person } from 'src/database';
|
||||
import { AssetFaces } from 'src/db';
|
||||
import { PropertyLifecycle } from 'src/decorators';
|
||||
import { AuthDto } from 'src/dtos/auth.dto';
|
||||
import { SourceType } from 'src/enum';
|
||||
import { AssetFaceTable } from 'src/schema/tables/asset-face.table';
|
||||
import { asDateString } from 'src/utils/date';
|
||||
import {
|
||||
IsDateStringFormat,
|
||||
@ -232,7 +232,7 @@ export function mapPerson(person: Person): PersonResponseDto {
|
||||
};
|
||||
}
|
||||
|
||||
export function mapFacesWithoutPerson(face: Selectable<AssetFaces>): AssetFaceWithoutPersonResponseDto {
|
||||
export function mapFacesWithoutPerson(face: Selectable<AssetFaceTable>): AssetFaceWithoutPersonResponseDto {
|
||||
return {
|
||||
id: face.id,
|
||||
imageHeight: face.imageHeight,
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Kysely, sql } from 'kysely';
|
||||
import { InjectKysely } from 'nestjs-kysely';
|
||||
import { DB } from 'src/db';
|
||||
import { ChunkedSet, DummyValue, GenerateSql } from 'src/decorators';
|
||||
import { AlbumUserRole, AssetVisibility } from 'src/enum';
|
||||
import { DB } from 'src/schema';
|
||||
import { asUuid } from 'src/utils/database';
|
||||
|
||||
class ActivityAccess {
|
||||
|
@ -3,9 +3,10 @@ import { Insertable, Kysely, NotNull, sql } from 'kysely';
|
||||
import { jsonObjectFrom } from 'kysely/helpers/postgres';
|
||||
import { InjectKysely } from 'nestjs-kysely';
|
||||
import { columns } from 'src/database';
|
||||
import { Activity, DB } from 'src/db';
|
||||
import { DummyValue, GenerateSql } from 'src/decorators';
|
||||
import { AssetVisibility } from 'src/enum';
|
||||
import { DB } from 'src/schema';
|
||||
import { ActivityTable } from 'src/schema/tables/activity.table';
|
||||
import { asUuid } from 'src/utils/database';
|
||||
|
||||
export interface ActivitySearch {
|
||||
@ -48,7 +49,7 @@ export class ActivityRepository {
|
||||
}
|
||||
|
||||
@GenerateSql({ params: [{ albumId: DummyValue.UUID, userId: DummyValue.UUID }] })
|
||||
async create(activity: Insertable<Activity>) {
|
||||
async create(activity: Insertable<ActivityTable>) {
|
||||
return this.db
|
||||
.insertInto('activity')
|
||||
.values(activity)
|
||||
|
@ -1,9 +1,10 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Insertable, Kysely, Updateable } from 'kysely';
|
||||
import { InjectKysely } from 'nestjs-kysely';
|
||||
import { AlbumsSharedUsersUsers, DB } from 'src/db';
|
||||
import { DummyValue, GenerateSql } from 'src/decorators';
|
||||
import { AlbumUserRole } from 'src/enum';
|
||||
import { DB } from 'src/schema';
|
||||
import { AlbumUserTable } from 'src/schema/tables/album-user.table';
|
||||
|
||||
export type AlbumPermissionId = {
|
||||
albumsId: string;
|
||||
@ -15,7 +16,7 @@ export class AlbumUserRepository {
|
||||
constructor(@InjectKysely() private db: Kysely<DB>) {}
|
||||
|
||||
@GenerateSql({ params: [{ usersId: DummyValue.UUID, albumsId: DummyValue.UUID }] })
|
||||
create(albumUser: Insertable<AlbumsSharedUsersUsers>) {
|
||||
create(albumUser: Insertable<AlbumUserTable>) {
|
||||
return this.db
|
||||
.insertInto('albums_shared_users_users')
|
||||
.values(albumUser)
|
||||
@ -24,7 +25,7 @@ export class AlbumUserRepository {
|
||||
}
|
||||
|
||||
@GenerateSql({ params: [{ usersId: DummyValue.UUID, albumsId: DummyValue.UUID }, { role: AlbumUserRole.VIEWER }] })
|
||||
update({ usersId, albumsId }: AlbumPermissionId, dto: Updateable<AlbumsSharedUsersUsers>) {
|
||||
update({ usersId, albumsId }: AlbumPermissionId, dto: Updateable<AlbumUserTable>) {
|
||||
return this.db
|
||||
.updateTable('albums_shared_users_users')
|
||||
.set(dto)
|
||||
|
@ -3,9 +3,10 @@ import { ExpressionBuilder, Insertable, Kysely, NotNull, sql, Updateable } from
|
||||
import { jsonArrayFrom, jsonObjectFrom } from 'kysely/helpers/postgres';
|
||||
import { InjectKysely } from 'nestjs-kysely';
|
||||
import { columns, Exif } from 'src/database';
|
||||
import { Albums, DB } from 'src/db';
|
||||
import { Chunked, ChunkedArray, ChunkedSet, DummyValue, GenerateSql } from 'src/decorators';
|
||||
import { AlbumUserCreateDto } from 'src/dtos/album.dto';
|
||||
import { DB } from 'src/schema';
|
||||
import { AlbumTable } from 'src/schema/tables/album.table';
|
||||
import { withDefaultVisibility } from 'src/utils/database';
|
||||
|
||||
export interface AlbumAssetCount {
|
||||
@ -269,7 +270,7 @@ export class AlbumRepository {
|
||||
await this.addAssets(this.db, albumId, assetIds);
|
||||
}
|
||||
|
||||
create(album: Insertable<Albums>, assetIds: string[], albumUsers: AlbumUserCreateDto[]) {
|
||||
create(album: Insertable<AlbumTable>, assetIds: string[], albumUsers: AlbumUserCreateDto[]) {
|
||||
return this.db.transaction().execute(async (tx) => {
|
||||
const newAlbum = await tx.insertInto('albums').values(album).returning('albums.id').executeTakeFirst();
|
||||
|
||||
@ -302,7 +303,7 @@ export class AlbumRepository {
|
||||
});
|
||||
}
|
||||
|
||||
update(id: string, album: Updateable<Albums>) {
|
||||
update(id: string, album: Updateable<AlbumTable>) {
|
||||
return this.db
|
||||
.updateTable('albums')
|
||||
.set(album)
|
||||
|
@ -3,19 +3,20 @@ import { Insertable, Kysely, Updateable } from 'kysely';
|
||||
import { jsonObjectFrom } from 'kysely/helpers/postgres';
|
||||
import { InjectKysely } from 'nestjs-kysely';
|
||||
import { columns } from 'src/database';
|
||||
import { ApiKeys, DB } from 'src/db';
|
||||
import { DummyValue, GenerateSql } from 'src/decorators';
|
||||
import { DB } from 'src/schema';
|
||||
import { ApiKeyTable } from 'src/schema/tables/api-key.table';
|
||||
import { asUuid } from 'src/utils/database';
|
||||
|
||||
@Injectable()
|
||||
export class ApiKeyRepository {
|
||||
constructor(@InjectKysely() private db: Kysely<DB>) {}
|
||||
|
||||
create(dto: Insertable<ApiKeys>) {
|
||||
create(dto: Insertable<ApiKeyTable>) {
|
||||
return this.db.insertInto('api_keys').values(dto).returning(columns.apiKey).executeTakeFirstOrThrow();
|
||||
}
|
||||
|
||||
async update(userId: string, id: string, dto: Updateable<ApiKeys>) {
|
||||
async update(userId: string, id: string, dto: Updateable<ApiKeyTable>) {
|
||||
return this.db
|
||||
.updateTable('api_keys')
|
||||
.set(dto)
|
||||
|
@ -3,9 +3,9 @@ import { Kysely } from 'kysely';
|
||||
import { jsonArrayFrom } from 'kysely/helpers/postgres';
|
||||
import { InjectKysely } from 'nestjs-kysely';
|
||||
import { Asset, columns } from 'src/database';
|
||||
import { DB } from 'src/db';
|
||||
import { DummyValue, GenerateSql } from 'src/decorators';
|
||||
import { AssetFileType, AssetType, AssetVisibility } from 'src/enum';
|
||||
import { DB } from 'src/schema';
|
||||
import { StorageAsset } from 'src/types';
|
||||
import {
|
||||
anyUuid,
|
||||
|
@ -3,9 +3,13 @@ import { Insertable, Kysely, NotNull, Selectable, UpdateResult, Updateable, sql
|
||||
import { isEmpty, isUndefined, omitBy } from 'lodash';
|
||||
import { InjectKysely } from 'nestjs-kysely';
|
||||
import { Stack } from 'src/database';
|
||||
import { AssetFiles, AssetJobStatus, Assets, DB, Exif } from 'src/db';
|
||||
import { Chunked, ChunkedArray, DummyValue, GenerateSql } from 'src/decorators';
|
||||
import { AssetFileType, AssetOrder, AssetStatus, AssetType, AssetVisibility } from 'src/enum';
|
||||
import { DB } from 'src/schema';
|
||||
import { AssetFileTable } from 'src/schema/tables/asset-files.table';
|
||||
import { AssetJobStatusTable } from 'src/schema/tables/asset-job-status.table';
|
||||
import { AssetTable } from 'src/schema/tables/asset.table';
|
||||
import { ExifTable } from 'src/schema/tables/exif.table';
|
||||
import {
|
||||
anyUuid,
|
||||
asUuid,
|
||||
@ -110,7 +114,7 @@ interface GetByIdsRelations {
|
||||
export class AssetRepository {
|
||||
constructor(@InjectKysely() private db: Kysely<DB>) {}
|
||||
|
||||
async upsertExif(exif: Insertable<Exif>): Promise<void> {
|
||||
async upsertExif(exif: Insertable<ExifTable>): Promise<void> {
|
||||
const value = { ...exif, assetId: asUuid(exif.assetId) };
|
||||
await this.db
|
||||
.insertInto('exif')
|
||||
@ -157,7 +161,7 @@ export class AssetRepository {
|
||||
|
||||
@GenerateSql({ params: [[DummyValue.UUID], { model: DummyValue.STRING }] })
|
||||
@Chunked()
|
||||
async updateAllExif(ids: string[], options: Updateable<Exif>): Promise<void> {
|
||||
async updateAllExif(ids: string[], options: Updateable<ExifTable>): Promise<void> {
|
||||
if (ids.length === 0) {
|
||||
return;
|
||||
}
|
||||
@ -165,7 +169,7 @@ export class AssetRepository {
|
||||
await this.db.updateTable('exif').set(options).where('assetId', 'in', ids).execute();
|
||||
}
|
||||
|
||||
async upsertJobStatus(...jobStatus: Insertable<AssetJobStatus>[]): Promise<void> {
|
||||
async upsertJobStatus(...jobStatus: Insertable<AssetJobStatusTable>[]): Promise<void> {
|
||||
if (jobStatus.length === 0) {
|
||||
return;
|
||||
}
|
||||
@ -191,11 +195,11 @@ export class AssetRepository {
|
||||
.execute();
|
||||
}
|
||||
|
||||
create(asset: Insertable<Assets>) {
|
||||
create(asset: Insertable<AssetTable>) {
|
||||
return this.db.insertInto('assets').values(asset).returningAll().executeTakeFirstOrThrow();
|
||||
}
|
||||
|
||||
createAll(assets: Insertable<Assets>[]) {
|
||||
createAll(assets: Insertable<AssetTable>[]) {
|
||||
return this.db.insertInto('assets').values(assets).returningAll().execute();
|
||||
}
|
||||
|
||||
@ -375,18 +379,18 @@ export class AssetRepository {
|
||||
|
||||
@GenerateSql({ params: [[DummyValue.UUID], { deviceId: DummyValue.STRING }] })
|
||||
@Chunked()
|
||||
async updateAll(ids: string[], options: Updateable<Assets>): Promise<void> {
|
||||
async updateAll(ids: string[], options: Updateable<AssetTable>): Promise<void> {
|
||||
if (ids.length === 0) {
|
||||
return;
|
||||
}
|
||||
await this.db.updateTable('assets').set(options).where('id', '=', anyUuid(ids)).execute();
|
||||
}
|
||||
|
||||
async updateByLibraryId(libraryId: string, options: Updateable<Assets>): Promise<void> {
|
||||
async updateByLibraryId(libraryId: string, options: Updateable<AssetTable>): Promise<void> {
|
||||
await this.db.updateTable('assets').set(options).where('libraryId', '=', asUuid(libraryId)).execute();
|
||||
}
|
||||
|
||||
async update(asset: Updateable<Assets> & { id: string }) {
|
||||
async update(asset: Updateable<AssetTable> & { id: string }) {
|
||||
const value = omitBy(asset, isUndefined);
|
||||
delete value.id;
|
||||
if (!isEmpty(value)) {
|
||||
@ -742,7 +746,7 @@ export class AssetRepository {
|
||||
.execute();
|
||||
}
|
||||
|
||||
async upsertFile(file: Pick<Insertable<AssetFiles>, 'assetId' | 'path' | 'type'>): Promise<void> {
|
||||
async upsertFile(file: Pick<Insertable<AssetFileTable>, 'assetId' | 'path' | 'type'>): Promise<void> {
|
||||
const value = { ...file, assetId: asUuid(file.assetId) };
|
||||
await this.db
|
||||
.insertInto('asset_files')
|
||||
@ -755,7 +759,7 @@ export class AssetRepository {
|
||||
.execute();
|
||||
}
|
||||
|
||||
async upsertFiles(files: Pick<Insertable<AssetFiles>, 'assetId' | 'path' | 'type'>[]): Promise<void> {
|
||||
async upsertFiles(files: Pick<Insertable<AssetFileTable>, 'assetId' | 'path' | 'type'>[]): Promise<void> {
|
||||
if (files.length === 0) {
|
||||
return;
|
||||
}
|
||||
@ -772,7 +776,7 @@ export class AssetRepository {
|
||||
.execute();
|
||||
}
|
||||
|
||||
async deleteFiles(files: Pick<Selectable<AssetFiles>, 'id'>[]): Promise<void> {
|
||||
async deleteFiles(files: Pick<Selectable<AssetFileTable>, 'id'>[]): Promise<void> {
|
||||
if (files.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Kysely } from 'kysely';
|
||||
import { InjectKysely } from 'nestjs-kysely';
|
||||
import { DB } from 'src/db';
|
||||
import { DummyValue, GenerateSql } from 'src/decorators';
|
||||
import { DatabaseAction, EntityType } from 'src/enum';
|
||||
import { DB } from 'src/schema';
|
||||
|
||||
export interface AuditSearch {
|
||||
action?: DatabaseAction;
|
||||
|
@ -15,11 +15,11 @@ import {
|
||||
VECTORCHORD_VERSION_RANGE,
|
||||
VECTORS_VERSION_RANGE,
|
||||
} from 'src/constants';
|
||||
import { DB } from 'src/db';
|
||||
import { GenerateSql } from 'src/decorators';
|
||||
import { DatabaseExtension, DatabaseLock, VectorIndex } from 'src/enum';
|
||||
import { ConfigRepository } from 'src/repositories/config.repository';
|
||||
import { LoggingRepository } from 'src/repositories/logging.repository';
|
||||
import { DB } from 'src/schema';
|
||||
import { ExtensionVersion, VectorExtension, VectorUpdateResult } from 'src/types';
|
||||
import { vectorIndexQuery } from 'src/utils/database';
|
||||
import { isValidInteger } from 'src/validation';
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Kysely } from 'kysely';
|
||||
import { InjectKysely } from 'nestjs-kysely';
|
||||
import { DB } from 'src/db';
|
||||
import { AssetVisibility } from 'src/enum';
|
||||
import { DB } from 'src/schema';
|
||||
import { anyUuid } from 'src/utils/database';
|
||||
|
||||
const builder = (db: Kysely<DB>) =>
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Kysely, NotNull, sql } from 'kysely';
|
||||
import { InjectKysely } from 'nestjs-kysely';
|
||||
import { DB } from 'src/db';
|
||||
import { Chunked, DummyValue, GenerateSql } from 'src/decorators';
|
||||
import { MapAsset } from 'src/dtos/asset-response.dto';
|
||||
import { AssetType, VectorIndex } from 'src/enum';
|
||||
import { probes } from 'src/repositories/database.repository';
|
||||
import { DB } from 'src/schema';
|
||||
import { anyUuid, asUuid, withDefaultVisibility } from 'src/utils/database';
|
||||
|
||||
interface DuplicateSearch {
|
||||
|
@ -1,10 +1,11 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Insertable, Kysely, sql, Updateable } from 'kysely';
|
||||
import { InjectKysely } from 'nestjs-kysely';
|
||||
import { DB, Libraries } from 'src/db';
|
||||
import { DummyValue, GenerateSql } from 'src/decorators';
|
||||
import { LibraryStatsResponseDto } from 'src/dtos/library.dto';
|
||||
import { AssetType, AssetVisibility } from 'src/enum';
|
||||
import { DB } from 'src/schema';
|
||||
import { LibraryTable } from 'src/schema/tables/library.table';
|
||||
|
||||
export enum AssetSyncResult {
|
||||
DO_NOTHING,
|
||||
@ -47,7 +48,7 @@ export class LibraryRepository {
|
||||
.execute();
|
||||
}
|
||||
|
||||
create(library: Insertable<Libraries>) {
|
||||
create(library: Insertable<LibraryTable>) {
|
||||
return this.db.insertInto('libraries').values(library).returningAll().executeTakeFirstOrThrow();
|
||||
}
|
||||
|
||||
@ -59,7 +60,7 @@ export class LibraryRepository {
|
||||
await this.db.updateTable('libraries').set({ deletedAt: new Date() }).where('libraries.id', '=', id).execute();
|
||||
}
|
||||
|
||||
update(id: string, library: Updateable<Libraries>) {
|
||||
update(id: string, library: Updateable<LibraryTable>) {
|
||||
return this.db
|
||||
.updateTable('libraries')
|
||||
.set(library)
|
||||
|
@ -6,12 +6,14 @@ import { createReadStream, existsSync } from 'node:fs';
|
||||
import { readFile } from 'node:fs/promises';
|
||||
import readLine from 'node:readline';
|
||||
import { citiesFile } from 'src/constants';
|
||||
import { DB, GeodataPlaces, NaturalearthCountries } from 'src/db';
|
||||
import { DummyValue, GenerateSql } from 'src/decorators';
|
||||
import { AssetVisibility, SystemMetadataKey } from 'src/enum';
|
||||
import { ConfigRepository } from 'src/repositories/config.repository';
|
||||
import { LoggingRepository } from 'src/repositories/logging.repository';
|
||||
import { SystemMetadataRepository } from 'src/repositories/system-metadata.repository';
|
||||
import { DB } from 'src/schema';
|
||||
import { GeodataPlacesTable } from 'src/schema/tables/geodata-places.table';
|
||||
import { NaturalEarthCountriesTable } from 'src/schema/tables/natural-earth-countries.table';
|
||||
|
||||
export interface MapMarkerSearchOptions {
|
||||
isArchived?: boolean;
|
||||
@ -38,8 +40,8 @@ export interface MapMarker extends ReverseGeocodeResult {
|
||||
}
|
||||
|
||||
interface MapDB extends DB {
|
||||
geodata_places_tmp: GeodataPlaces;
|
||||
naturalearth_countries_tmp: NaturalearthCountries;
|
||||
geodata_places_tmp: GeodataPlacesTable;
|
||||
naturalearth_countries_tmp: NaturalEarthCountriesTable;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
@ -193,11 +195,11 @@ export class MapRepository {
|
||||
return;
|
||||
}
|
||||
|
||||
const entities: Insertable<NaturalearthCountries>[] = [];
|
||||
const entities: Insertable<NaturalEarthCountriesTable>[] = [];
|
||||
for (const feature of geoJSONData.features) {
|
||||
for (const entry of feature.geometry.coordinates) {
|
||||
const coordinates: number[][][] = feature.geometry.type === 'MultiPolygon' ? entry[0] : entry;
|
||||
const featureRecord: Insertable<NaturalearthCountries> = {
|
||||
const featureRecord: Insertable<NaturalEarthCountriesTable> = {
|
||||
admin: feature.properties.ADMIN,
|
||||
admin_a3: feature.properties.ADM0_A3,
|
||||
type: feature.properties.TYPE,
|
||||
|
@ -3,10 +3,11 @@ import { Insertable, Kysely, sql, Updateable } from 'kysely';
|
||||
import { jsonArrayFrom } from 'kysely/helpers/postgres';
|
||||
import { DateTime } from 'luxon';
|
||||
import { InjectKysely } from 'nestjs-kysely';
|
||||
import { DB, Memories } from 'src/db';
|
||||
import { Chunked, ChunkedSet, DummyValue, GenerateSql } from 'src/decorators';
|
||||
import { MemorySearchDto } from 'src/dtos/memory.dto';
|
||||
import { AssetVisibility } from 'src/enum';
|
||||
import { DB } from 'src/schema';
|
||||
import { MemoryTable } from 'src/schema/tables/memory.table';
|
||||
import { IBulkAsset } from 'src/types';
|
||||
|
||||
@Injectable()
|
||||
@ -80,7 +81,7 @@ export class MemoryRepository implements IBulkAsset {
|
||||
return this.getByIdBuilder(id).executeTakeFirst();
|
||||
}
|
||||
|
||||
async create(memory: Insertable<Memories>, assetIds: Set<string>) {
|
||||
async create(memory: Insertable<MemoryTable>, assetIds: Set<string>) {
|
||||
const id = await this.db.transaction().execute(async (tx) => {
|
||||
const { id } = await tx.insertInto('memories').values(memory).returning('id').executeTakeFirstOrThrow();
|
||||
|
||||
@ -96,7 +97,7 @@ export class MemoryRepository implements IBulkAsset {
|
||||
}
|
||||
|
||||
@GenerateSql({ params: [DummyValue.UUID, { ownerId: DummyValue.UUID, isSaved: true }] })
|
||||
async update(id: string, memory: Updateable<Memories>) {
|
||||
async update(id: string, memory: Updateable<MemoryTable>) {
|
||||
await this.db.updateTable('memories').set(memory).where('id', '=', id).execute();
|
||||
return this.getByIdBuilder(id).executeTakeFirstOrThrow();
|
||||
}
|
||||
|
@ -1,15 +1,16 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Insertable, Kysely, sql, Updateable } from 'kysely';
|
||||
import { InjectKysely } from 'nestjs-kysely';
|
||||
import { DB, MoveHistory } from 'src/db';
|
||||
import { DummyValue, GenerateSql } from 'src/decorators';
|
||||
import { AssetPathType, PathType } from 'src/enum';
|
||||
import { DB } from 'src/schema';
|
||||
import { MoveTable } from 'src/schema/tables/move.table';
|
||||
|
||||
@Injectable()
|
||||
export class MoveRepository {
|
||||
constructor(@InjectKysely() private db: Kysely<DB>) {}
|
||||
|
||||
create(entity: Insertable<MoveHistory>) {
|
||||
create(entity: Insertable<MoveTable>) {
|
||||
return this.db.insertInto('move_history').values(entity).returningAll().executeTakeFirstOrThrow();
|
||||
}
|
||||
|
||||
@ -23,7 +24,7 @@ export class MoveRepository {
|
||||
.executeTakeFirst();
|
||||
}
|
||||
|
||||
update(id: string, entity: Updateable<MoveHistory>) {
|
||||
update(id: string, entity: Updateable<MoveTable>) {
|
||||
return this.db
|
||||
.updateTable('move_history')
|
||||
.set(entity)
|
||||
|
@ -2,9 +2,10 @@ import { Insertable, Kysely, Updateable } from 'kysely';
|
||||
import { DateTime } from 'luxon';
|
||||
import { InjectKysely } from 'nestjs-kysely';
|
||||
import { columns } from 'src/database';
|
||||
import { DB, Notifications } from 'src/db';
|
||||
import { DummyValue, GenerateSql } from 'src/decorators';
|
||||
import { NotificationSearchDto } from 'src/dtos/notification.dto';
|
||||
import { DB } from 'src/schema';
|
||||
import { NotificationTable } from 'src/schema/tables/notification.table';
|
||||
|
||||
export class NotificationRepository {
|
||||
constructor(@InjectKysely() private db: Kysely<DB>) {}
|
||||
@ -53,7 +54,7 @@ export class NotificationRepository {
|
||||
.execute();
|
||||
}
|
||||
|
||||
create(notification: Insertable<Notifications>) {
|
||||
create(notification: Insertable<NotificationTable>) {
|
||||
return this.db
|
||||
.insertInto('notifications')
|
||||
.values(notification)
|
||||
@ -70,7 +71,7 @@ export class NotificationRepository {
|
||||
.executeTakeFirst();
|
||||
}
|
||||
|
||||
update(id: string, notification: Updateable<Notifications>) {
|
||||
update(id: string, notification: Updateable<NotificationTable>) {
|
||||
return this.db
|
||||
.updateTable('notifications')
|
||||
.set(notification)
|
||||
@ -80,7 +81,7 @@ export class NotificationRepository {
|
||||
.executeTakeFirstOrThrow();
|
||||
}
|
||||
|
||||
async updateAll(ids: string[], notification: Updateable<Notifications>) {
|
||||
async updateAll(ids: string[], notification: Updateable<NotificationTable>) {
|
||||
await this.db.updateTable('notifications').set(notification).where('id', 'in', ids).execute();
|
||||
}
|
||||
|
||||
|
@ -3,8 +3,9 @@ import { ExpressionBuilder, Insertable, Kysely, NotNull, Updateable } from 'kyse
|
||||
import { jsonObjectFrom } from 'kysely/helpers/postgres';
|
||||
import { InjectKysely } from 'nestjs-kysely';
|
||||
import { columns } from 'src/database';
|
||||
import { DB, Partners } from 'src/db';
|
||||
import { DummyValue, GenerateSql } from 'src/decorators';
|
||||
import { DB } from 'src/schema';
|
||||
import { PartnerTable } from 'src/schema/tables/partner.table';
|
||||
|
||||
export interface PartnerIds {
|
||||
sharedById: string;
|
||||
@ -47,7 +48,7 @@ export class PartnerRepository {
|
||||
.executeTakeFirst();
|
||||
}
|
||||
|
||||
create(values: Insertable<Partners>) {
|
||||
create(values: Insertable<PartnerTable>) {
|
||||
return this.db
|
||||
.insertInto('partners')
|
||||
.values(values)
|
||||
@ -59,7 +60,7 @@ export class PartnerRepository {
|
||||
}
|
||||
|
||||
@GenerateSql({ params: [{ sharedWithId: DummyValue.UUID, sharedById: DummyValue.UUID }, { inTimeline: true }] })
|
||||
update({ sharedWithId, sharedById }: PartnerIds, values: Updateable<Partners>) {
|
||||
update({ sharedWithId, sharedById }: PartnerIds, values: Updateable<PartnerTable>) {
|
||||
return this.db
|
||||
.updateTable('partners')
|
||||
.set(values)
|
||||
|
@ -2,9 +2,12 @@ import { Injectable } from '@nestjs/common';
|
||||
import { ExpressionBuilder, Insertable, Kysely, Selectable, sql, Updateable } from 'kysely';
|
||||
import { jsonObjectFrom } from 'kysely/helpers/postgres';
|
||||
import { InjectKysely } from 'nestjs-kysely';
|
||||
import { AssetFaces, DB, FaceSearch, Person } from 'src/db';
|
||||
import { Chunked, ChunkedArray, DummyValue, GenerateSql } from 'src/decorators';
|
||||
import { AssetFileType, AssetVisibility, SourceType } from 'src/enum';
|
||||
import { DB } from 'src/schema';
|
||||
import { AssetFaceTable } from 'src/schema/tables/asset-face.table';
|
||||
import { FaceSearchTable } from 'src/schema/tables/face-search.table';
|
||||
import { PersonTable } from 'src/schema/tables/person.table';
|
||||
import { removeUndefinedKeys } from 'src/utils/database';
|
||||
import { paginationHelper, PaginationOptions } from 'src/utils/pagination';
|
||||
|
||||
@ -57,7 +60,7 @@ export interface GetAllFacesOptions {
|
||||
|
||||
export type UnassignFacesOptions = DeleteFacesOptions;
|
||||
|
||||
export type SelectFaceOptions = (keyof Selectable<AssetFaces>)[];
|
||||
export type SelectFaceOptions = (keyof Selectable<AssetFaceTable>)[];
|
||||
|
||||
const withPerson = (eb: ExpressionBuilder<DB, 'asset_faces'>) => {
|
||||
return jsonObjectFrom(
|
||||
@ -378,11 +381,11 @@ export class PersonRepository {
|
||||
.executeTakeFirstOrThrow();
|
||||
}
|
||||
|
||||
create(person: Insertable<Person>) {
|
||||
create(person: Insertable<PersonTable>) {
|
||||
return this.db.insertInto('person').values(person).returningAll().executeTakeFirstOrThrow();
|
||||
}
|
||||
|
||||
async createAll(people: Insertable<Person>[]): Promise<string[]> {
|
||||
async createAll(people: Insertable<PersonTable>[]): Promise<string[]> {
|
||||
if (people.length === 0) {
|
||||
return [];
|
||||
}
|
||||
@ -393,9 +396,9 @@ export class PersonRepository {
|
||||
|
||||
@GenerateSql({ params: [[], [], [{ faceId: DummyValue.UUID, embedding: DummyValue.VECTOR }]] })
|
||||
async refreshFaces(
|
||||
facesToAdd: (Insertable<AssetFaces> & { assetId: string })[],
|
||||
facesToAdd: (Insertable<AssetFaceTable> & { assetId: string })[],
|
||||
faceIdsToRemove: string[],
|
||||
embeddingsToAdd?: Insertable<FaceSearch>[],
|
||||
embeddingsToAdd?: Insertable<FaceSearchTable>[],
|
||||
): Promise<void> {
|
||||
let query = this.db;
|
||||
if (facesToAdd.length > 0) {
|
||||
@ -415,7 +418,7 @@ export class PersonRepository {
|
||||
await query.selectFrom(sql`(select 1)`.as('dummy')).execute();
|
||||
}
|
||||
|
||||
async update(person: Updateable<Person> & { id: string }) {
|
||||
async update(person: Updateable<PersonTable> & { id: string }) {
|
||||
return this.db
|
||||
.updateTable('person')
|
||||
.set(person)
|
||||
@ -424,7 +427,7 @@ export class PersonRepository {
|
||||
.executeTakeFirstOrThrow();
|
||||
}
|
||||
|
||||
async updateAll(people: Insertable<Person>[]): Promise<void> {
|
||||
async updateAll(people: Insertable<PersonTable>[]): Promise<void> {
|
||||
if (people.length === 0) {
|
||||
return;
|
||||
}
|
||||
@ -496,7 +499,7 @@ export class PersonRepository {
|
||||
return result?.latestDate;
|
||||
}
|
||||
|
||||
async createAssetFace(face: Insertable<AssetFaces>): Promise<void> {
|
||||
async createAssetFace(face: Insertable<AssetFaceTable>): Promise<void> {
|
||||
await this.db.insertInto('asset_faces').values(face).execute();
|
||||
}
|
||||
|
||||
|
@ -2,11 +2,12 @@ import { Injectable } from '@nestjs/common';
|
||||
import { Kysely, OrderByDirection, Selectable, sql } from 'kysely';
|
||||
import { InjectKysely } from 'nestjs-kysely';
|
||||
import { randomUUID } from 'node:crypto';
|
||||
import { DB, Exif } from 'src/db';
|
||||
import { DummyValue, GenerateSql } from 'src/decorators';
|
||||
import { MapAsset } from 'src/dtos/asset-response.dto';
|
||||
import { AssetStatus, AssetType, AssetVisibility, VectorIndex } from 'src/enum';
|
||||
import { probes } from 'src/repositories/database.repository';
|
||||
import { DB } from 'src/schema';
|
||||
import { ExifTable } from 'src/schema/tables/exif.table';
|
||||
import { anyUuid, searchAssetBuilder } from 'src/utils/database';
|
||||
import { paginationHelper } from 'src/utils/pagination';
|
||||
import { isValidInteger } from 'src/validation';
|
||||
@ -385,7 +386,7 @@ export class SearchRepository {
|
||||
.select((eb) =>
|
||||
eb
|
||||
.fn('to_jsonb', [eb.table('exif')])
|
||||
.$castTo<Selectable<Exif>>()
|
||||
.$castTo<Selectable<ExifTable>>()
|
||||
.as('exifInfo'),
|
||||
)
|
||||
.orderBy('exif.city')
|
||||
|
@ -4,8 +4,9 @@ import { jsonObjectFrom } from 'kysely/helpers/postgres';
|
||||
import { DateTime } from 'luxon';
|
||||
import { InjectKysely } from 'nestjs-kysely';
|
||||
import { columns } from 'src/database';
|
||||
import { DB, Sessions } from 'src/db';
|
||||
import { DummyValue, GenerateSql } from 'src/decorators';
|
||||
import { DB } from 'src/schema';
|
||||
import { SessionTable } from 'src/schema/tables/session.table';
|
||||
import { asUuid } from 'src/utils/database';
|
||||
|
||||
export type SessionSearchOptions = { updatedBefore: Date };
|
||||
@ -72,11 +73,11 @@ export class SessionRepository {
|
||||
.execute();
|
||||
}
|
||||
|
||||
create(dto: Insertable<Sessions>) {
|
||||
create(dto: Insertable<SessionTable>) {
|
||||
return this.db.insertInto('sessions').values(dto).returningAll().executeTakeFirstOrThrow();
|
||||
}
|
||||
|
||||
update(id: string, dto: Updateable<Sessions>) {
|
||||
update(id: string, dto: Updateable<SessionTable>) {
|
||||
return this.db
|
||||
.updateTable('sessions')
|
||||
.set(dto)
|
||||
|
@ -4,10 +4,11 @@ import { jsonObjectFrom } from 'kysely/helpers/postgres';
|
||||
import _ from 'lodash';
|
||||
import { InjectKysely } from 'nestjs-kysely';
|
||||
import { Album, columns } from 'src/database';
|
||||
import { DB, SharedLinks } from 'src/db';
|
||||
import { DummyValue, GenerateSql } from 'src/decorators';
|
||||
import { MapAsset } from 'src/dtos/asset-response.dto';
|
||||
import { SharedLinkType } from 'src/enum';
|
||||
import { DB } from 'src/schema';
|
||||
import { SharedLinkTable } from 'src/schema/tables/shared-link.table';
|
||||
|
||||
export type SharedLinkSearchOptions = {
|
||||
userId: string;
|
||||
@ -183,7 +184,7 @@ export class SharedLinkRepository {
|
||||
.executeTakeFirst();
|
||||
}
|
||||
|
||||
async create(entity: Insertable<SharedLinks> & { assetIds?: string[] }) {
|
||||
async create(entity: Insertable<SharedLinkTable> & { assetIds?: string[] }) {
|
||||
const { id } = await this.db
|
||||
.insertInto('shared_links')
|
||||
.values(_.omit(entity, 'assetIds'))
|
||||
@ -200,7 +201,7 @@ export class SharedLinkRepository {
|
||||
return this.getSharedLinks(id);
|
||||
}
|
||||
|
||||
async update(entity: Updateable<SharedLinks> & { id: string; assetIds?: string[] }) {
|
||||
async update(entity: Updateable<SharedLinkTable> & { id: string; assetIds?: string[] }) {
|
||||
const { id } = await this.db
|
||||
.updateTable('shared_links')
|
||||
.set(_.omit(entity, 'assets', 'album', 'assetIds'))
|
||||
|
@ -3,8 +3,9 @@ import { ExpressionBuilder, Kysely, Updateable } from 'kysely';
|
||||
import { jsonArrayFrom } from 'kysely/helpers/postgres';
|
||||
import { InjectKysely } from 'nestjs-kysely';
|
||||
import { columns } from 'src/database';
|
||||
import { AssetStack, DB } from 'src/db';
|
||||
import { DummyValue, GenerateSql } from 'src/decorators';
|
||||
import { DB } from 'src/schema';
|
||||
import { StackTable } from 'src/schema/tables/stack.table';
|
||||
import { asUuid, withDefaultVisibility } from 'src/utils/database';
|
||||
|
||||
export interface StackSearch {
|
||||
@ -130,7 +131,7 @@ export class StackRepository {
|
||||
await this.db.deleteFrom('asset_stack').where('id', 'in', ids).execute();
|
||||
}
|
||||
|
||||
update(id: string, entity: Updateable<AssetStack>) {
|
||||
update(id: string, entity: Updateable<StackTable>) {
|
||||
return this.db
|
||||
.updateTable('asset_stack')
|
||||
.set(entity)
|
||||
|
@ -1,9 +1,10 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Insertable, Kysely } from 'kysely';
|
||||
import { InjectKysely } from 'nestjs-kysely';
|
||||
import { DB, SessionSyncCheckpoints } from 'src/db';
|
||||
import { DummyValue, GenerateSql } from 'src/decorators';
|
||||
import { SyncEntityType } from 'src/enum';
|
||||
import { DB } from 'src/schema';
|
||||
import { SessionSyncCheckpointTable } from 'src/schema/tables/sync-checkpoint.table';
|
||||
|
||||
@Injectable()
|
||||
export class SyncCheckpointRepository {
|
||||
@ -18,7 +19,7 @@ export class SyncCheckpointRepository {
|
||||
.execute();
|
||||
}
|
||||
|
||||
upsertAll(items: Insertable<SessionSyncCheckpoints>[]) {
|
||||
upsertAll(items: Insertable<SessionSyncCheckpointTable>[]) {
|
||||
return this.db
|
||||
.insertInto('session_sync_checkpoints')
|
||||
.values(items)
|
||||
|
@ -2,8 +2,8 @@ import { Injectable } from '@nestjs/common';
|
||||
import { Kysely, SelectQueryBuilder, sql } from 'kysely';
|
||||
import { InjectKysely } from 'nestjs-kysely';
|
||||
import { columns } from 'src/database';
|
||||
import { DB } from 'src/db';
|
||||
import { DummyValue, GenerateSql } from 'src/decorators';
|
||||
import { DB } from 'src/schema';
|
||||
import { SyncAck } from 'src/types';
|
||||
|
||||
type AuditTables =
|
||||
|
@ -2,11 +2,12 @@ import { Injectable } from '@nestjs/common';
|
||||
import { Insertable, Kysely } from 'kysely';
|
||||
import { InjectKysely } from 'nestjs-kysely';
|
||||
import { readFile } from 'node:fs/promises';
|
||||
import { DB, SystemMetadata as DbSystemMetadata } from 'src/db';
|
||||
import { GenerateSql } from 'src/decorators';
|
||||
import { DB } from 'src/schema';
|
||||
import { SystemMetadataTable } from 'src/schema/tables/system-metadata.table';
|
||||
import { SystemMetadata } from 'src/types';
|
||||
|
||||
type Upsert = Insertable<DbSystemMetadata>;
|
||||
type Upsert = Insertable<SystemMetadataTable>;
|
||||
|
||||
@Injectable()
|
||||
export class SystemMetadataRepository {
|
||||
|
@ -2,9 +2,11 @@ import { Injectable } from '@nestjs/common';
|
||||
import { Insertable, Kysely, sql, Updateable } from 'kysely';
|
||||
import { InjectKysely } from 'nestjs-kysely';
|
||||
import { columns } from 'src/database';
|
||||
import { DB, TagAsset, Tags } from 'src/db';
|
||||
import { Chunked, ChunkedSet, DummyValue, GenerateSql } from 'src/decorators';
|
||||
import { LoggingRepository } from 'src/repositories/logging.repository';
|
||||
import { DB } from 'src/schema';
|
||||
import { TagAssetTable } from 'src/schema/tables/tag-asset.table';
|
||||
import { TagTable } from 'src/schema/tables/tag.table';
|
||||
|
||||
@Injectable()
|
||||
export class TagRepository {
|
||||
@ -72,12 +74,12 @@ export class TagRepository {
|
||||
}
|
||||
|
||||
@GenerateSql({ params: [{ userId: DummyValue.UUID, color: DummyValue.STRING, value: DummyValue.STRING }] })
|
||||
create(tag: Insertable<Tags>) {
|
||||
create(tag: Insertable<TagTable>) {
|
||||
return this.db.insertInto('tags').values(tag).returningAll().executeTakeFirstOrThrow();
|
||||
}
|
||||
|
||||
@GenerateSql({ params: [DummyValue.UUID, { color: DummyValue.STRING }] })
|
||||
update(id: string, dto: Updateable<Tags>) {
|
||||
update(id: string, dto: Updateable<TagTable>) {
|
||||
return this.db.updateTable('tags').set(dto).where('id', '=', id).returningAll().executeTakeFirstOrThrow();
|
||||
}
|
||||
|
||||
@ -128,7 +130,7 @@ export class TagRepository {
|
||||
|
||||
@GenerateSql({ params: [[{ assetId: DummyValue.UUID, tagsIds: [DummyValue.UUID] }]] })
|
||||
@Chunked()
|
||||
upsertAssetIds(items: Insertable<TagAsset>[]) {
|
||||
upsertAssetIds(items: Insertable<TagAssetTable>[]) {
|
||||
if (items.length === 0) {
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { Kysely } from 'kysely';
|
||||
import { InjectKysely } from 'nestjs-kysely';
|
||||
import { DB } from 'src/db';
|
||||
import { DummyValue, GenerateSql } from 'src/decorators';
|
||||
import { AssetStatus } from 'src/enum';
|
||||
import { DB } from 'src/schema';
|
||||
|
||||
export class TrashRepository {
|
||||
constructor(@InjectKysely() private db: Kysely<DB>) {}
|
||||
|
@ -4,14 +4,15 @@ import { jsonArrayFrom } from 'kysely/helpers/postgres';
|
||||
import { DateTime } from 'luxon';
|
||||
import { InjectKysely } from 'nestjs-kysely';
|
||||
import { columns } from 'src/database';
|
||||
import { DB, UserMetadata as DbUserMetadata } from 'src/db';
|
||||
import { DummyValue, GenerateSql } from 'src/decorators';
|
||||
import { AssetType, AssetVisibility, UserStatus } from 'src/enum';
|
||||
import { DB } from 'src/schema';
|
||||
import { UserMetadataTable } from 'src/schema/tables/user-metadata.table';
|
||||
import { UserTable } from 'src/schema/tables/user.table';
|
||||
import { UserMetadata, UserMetadataItem } from 'src/types';
|
||||
import { asUuid } from 'src/utils/database';
|
||||
|
||||
type Upsert = Insertable<DbUserMetadata>;
|
||||
type Upsert = Insertable<UserMetadataTable>;
|
||||
|
||||
export interface UserListFilter {
|
||||
id?: string;
|
||||
|
@ -1,8 +1,9 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Insertable, Kysely } from 'kysely';
|
||||
import { InjectKysely } from 'nestjs-kysely';
|
||||
import { DB, VersionHistory } from 'src/db';
|
||||
import { GenerateSql } from 'src/decorators';
|
||||
import { DB } from 'src/schema';
|
||||
import { VersionHistoryTable } from 'src/schema/tables/version-history.table';
|
||||
|
||||
@Injectable()
|
||||
export class VersionHistoryRepository {
|
||||
@ -18,7 +19,7 @@ export class VersionHistoryRepository {
|
||||
return this.db.selectFrom('version_history').selectAll().orderBy('createdAt', 'desc').executeTakeFirst();
|
||||
}
|
||||
|
||||
create(version: Insertable<VersionHistory>) {
|
||||
create(version: Insertable<VersionHistoryTable>) {
|
||||
return this.db.insertInto('version_history').values(version).returningAll().executeTakeFirstOrThrow();
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { Kysely } from 'kysely';
|
||||
import { InjectKysely } from 'nestjs-kysely';
|
||||
import { DB } from 'src/db';
|
||||
import { DummyValue, GenerateSql } from 'src/decorators';
|
||||
import { AssetVisibility } from 'src/enum';
|
||||
import { DB } from 'src/schema';
|
||||
import { asUuid, withExif } from 'src/utils/database';
|
||||
|
||||
export class ViewRepository {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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>;
|
||||
}
|
||||
|
@ -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>;
|
||||
}
|
||||
|
@ -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>;
|
||||
}
|
||||
|
@ -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>;
|
||||
}
|
||||
|
@ -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>;
|
||||
}
|
||||
|
@ -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>;
|
||||
}
|
||||
|
@ -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>;
|
||||
}
|
||||
|
@ -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>;
|
||||
}
|
||||
|
@ -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>;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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>;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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>;
|
||||
}
|
||||
|
@ -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>;
|
||||
}
|
||||
|
@ -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>;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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>;
|
||||
}
|
||||
|
@ -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')
|
||||
|
@ -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>;
|
||||
}
|
||||
|
@ -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>;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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>;
|
||||
}
|
||||
|
@ -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>;
|
||||
}
|
||||
|
@ -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>;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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 })
|
||||
|
@ -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>;
|
||||
}
|
||||
|
@ -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>;
|
||||
}
|
||||
|
@ -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>;
|
||||
}
|
||||
|
@ -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({
|
||||
|
@ -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;
|
||||
|
@ -6,7 +6,6 @@ import path, { basename, isAbsolute, parse } from 'node:path';
|
||||
import picomatch from 'picomatch';
|
||||
import { JOBS_LIBRARY_PAGINATION_SIZE } from 'src/constants';
|
||||
import { StorageCore } from 'src/cores/storage.core';
|
||||
import { Assets } from 'src/db';
|
||||
import { OnEvent, OnJob } from 'src/decorators';
|
||||
import {
|
||||
CreateLibraryDto,
|
||||
@ -21,6 +20,7 @@ import {
|
||||
import { AssetStatus, AssetType, DatabaseLock, ImmichWorker, JobName, JobStatus, QueueName } from 'src/enum';
|
||||
import { ArgOf } from 'src/repositories/event.repository';
|
||||
import { AssetSyncResult } from 'src/repositories/library.repository';
|
||||
import { AssetTable } from 'src/schema/tables/asset.table';
|
||||
import { BaseService } from 'src/services/base.service';
|
||||
import { JobOf } from 'src/types';
|
||||
import { mimeTypes } from 'src/utils/mime-types';
|
||||
@ -237,7 +237,7 @@ export class LibraryService extends BaseService {
|
||||
return JobStatus.FAILED;
|
||||
}
|
||||
|
||||
const assetImports: Insertable<Assets>[] = [];
|
||||
const assetImports: Insertable<AssetTable>[] = [];
|
||||
await Promise.all(
|
||||
job.paths.map((path) =>
|
||||
this.processEntity(path, library.ownerId, job.libraryId)
|
||||
|
@ -9,7 +9,6 @@ import path from 'node:path';
|
||||
import { JOBS_ASSET_PAGINATION_SIZE } from 'src/constants';
|
||||
import { StorageCore } from 'src/cores/storage.core';
|
||||
import { Asset, AssetFace } from 'src/database';
|
||||
import { AssetFaces, Exif, Person } from 'src/db';
|
||||
import { OnEvent, OnJob } from 'src/decorators';
|
||||
import {
|
||||
AssetType,
|
||||
@ -25,6 +24,9 @@ import {
|
||||
import { ArgOf } from 'src/repositories/event.repository';
|
||||
import { ReverseGeocodeResult } from 'src/repositories/map.repository';
|
||||
import { ImmichTags } from 'src/repositories/metadata.repository';
|
||||
import { AssetFaceTable } from 'src/schema/tables/asset-face.table';
|
||||
import { ExifTable } from 'src/schema/tables/exif.table';
|
||||
import { PersonTable } from 'src/schema/tables/person.table';
|
||||
import { BaseService } from 'src/services/base.service';
|
||||
import { JobItem, JobOf } from 'src/types';
|
||||
import { isFaceImportEnabled } from 'src/utils/misc';
|
||||
@ -162,7 +164,7 @@ export class MetadataService extends BaseService {
|
||||
|
||||
private async linkLivePhotos(
|
||||
asset: { id: string; type: AssetType; ownerId: string; libraryId: string | null },
|
||||
exifInfo: Insertable<Exif>,
|
||||
exifInfo: Insertable<ExifTable>,
|
||||
): Promise<void> {
|
||||
if (!exifInfo.livePhotoCID) {
|
||||
return;
|
||||
@ -240,7 +242,7 @@ export class MetadataService extends BaseService {
|
||||
}
|
||||
}
|
||||
|
||||
const exifData: Insertable<Exif> = {
|
||||
const exifData: Insertable<ExifTable> = {
|
||||
assetId: asset.id,
|
||||
|
||||
// dates
|
||||
@ -710,10 +712,10 @@ export class MetadataService extends BaseService {
|
||||
return;
|
||||
}
|
||||
|
||||
const facesToAdd: (Insertable<AssetFaces> & { assetId: string })[] = [];
|
||||
const facesToAdd: (Insertable<AssetFaceTable> & { assetId: string })[] = [];
|
||||
const existingNames = await this.personRepository.getDistinctNames(asset.ownerId, { withHidden: true });
|
||||
const existingNameMap = new Map(existingNames.map(({ id, name }) => [name.toLowerCase(), id]));
|
||||
const missing: (Insertable<Person> & { ownerId: string })[] = [];
|
||||
const missing: (Insertable<PersonTable> & { ownerId: string })[] = [];
|
||||
const missingWithFaceAsset: { id: string; ownerId: string; faceAssetId: string }[] = [];
|
||||
|
||||
const adjustedRegionInfo = this.orientRegionInfo(tags.RegionInfo, tags.Orientation);
|
||||
|
@ -2,7 +2,6 @@ import { BadRequestException, Injectable, NotFoundException } from '@nestjs/comm
|
||||
import { Insertable, Updateable } from 'kysely';
|
||||
import { JOBS_ASSET_PAGINATION_SIZE } from 'src/constants';
|
||||
import { Person } from 'src/database';
|
||||
import { AssetFaces, FaceSearch } from 'src/db';
|
||||
import { Chunked, OnJob } from 'src/decorators';
|
||||
import { BulkIdErrorReason, BulkIdResponseDto, BulkIdsDto } from 'src/dtos/asset-ids.response.dto';
|
||||
import { AuthDto } from 'src/dtos/auth.dto';
|
||||
@ -37,6 +36,8 @@ import {
|
||||
} from 'src/enum';
|
||||
import { BoundingBox } from 'src/repositories/machine-learning.repository';
|
||||
import { UpdateFacesData } from 'src/repositories/person.repository';
|
||||
import { AssetFaceTable } from 'src/schema/tables/asset-face.table';
|
||||
import { FaceSearchTable } from 'src/schema/tables/face-search.table';
|
||||
import { BaseService } from 'src/services/base.service';
|
||||
import { JobItem, JobOf } from 'src/types';
|
||||
import { ImmichFileResponse } from 'src/utils/file';
|
||||
@ -317,8 +318,8 @@ export class PersonService extends BaseService {
|
||||
);
|
||||
this.logger.debug(`${faces.length} faces detected in ${previewFile.path}`);
|
||||
|
||||
const facesToAdd: (Insertable<AssetFaces> & { id: string })[] = [];
|
||||
const embeddings: FaceSearch[] = [];
|
||||
const facesToAdd: (Insertable<AssetFaceTable> & { id: string })[] = [];
|
||||
const embeddings: FaceSearchTable[] = [];
|
||||
const mlFaceIds = new Set<string>();
|
||||
|
||||
for (const face of asset.faces) {
|
||||
|
@ -3,7 +3,6 @@ import { Insertable } from 'kysely';
|
||||
import { DateTime } from 'luxon';
|
||||
import { Writable } from 'node:stream';
|
||||
import { AUDIT_LOG_MAX_DURATION } from 'src/constants';
|
||||
import { SessionSyncCheckpoints } from 'src/db';
|
||||
import { AssetResponseDto, mapAsset } from 'src/dtos/asset-response.dto';
|
||||
import { AuthDto } from 'src/dtos/auth.dto';
|
||||
import {
|
||||
@ -17,6 +16,7 @@ import {
|
||||
SyncStreamDto,
|
||||
} from 'src/dtos/sync.dto';
|
||||
import { AssetVisibility, DatabaseAction, EntityType, Permission, SyncEntityType, SyncRequestType } from 'src/enum';
|
||||
import { SessionSyncCheckpointTable } from 'src/schema/tables/sync-checkpoint.table';
|
||||
import { BaseService } from 'src/services/base.service';
|
||||
import { SyncAck } from 'src/types';
|
||||
import { getMyPartnerIds } from 'src/utils/asset.util';
|
||||
@ -90,7 +90,7 @@ export class SyncService extends BaseService {
|
||||
return throwSessionRequired();
|
||||
}
|
||||
|
||||
const checkpoints: Record<string, Insertable<SessionSyncCheckpoints>> = {};
|
||||
const checkpoints: Record<string, Insertable<SessionSyncCheckpointTable>> = {};
|
||||
for (const ack of dto.acks) {
|
||||
const { type } = fromAck(ack);
|
||||
// TODO proper ack validation via class validator
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { BadRequestException, Injectable } from '@nestjs/common';
|
||||
import { Insertable } from 'kysely';
|
||||
import { TagAsset } from 'src/db';
|
||||
import { OnJob } from 'src/decorators';
|
||||
import { BulkIdResponseDto, BulkIdsDto } from 'src/dtos/asset-ids.response.dto';
|
||||
import { AuthDto } from 'src/dtos/auth.dto';
|
||||
@ -14,6 +13,7 @@ import {
|
||||
mapTag,
|
||||
} from 'src/dtos/tag.dto';
|
||||
import { JobName, JobStatus, Permission, QueueName } from 'src/enum';
|
||||
import { TagAssetTable } from 'src/schema/tables/tag-asset.table';
|
||||
import { BaseService } from 'src/services/base.service';
|
||||
import { addAssets, removeAssets } from 'src/utils/asset.util';
|
||||
import { upsertTags } from 'src/utils/tag';
|
||||
@ -81,7 +81,7 @@ export class TagService extends BaseService {
|
||||
this.checkAccess({ auth, permission: Permission.ASSET_UPDATE, ids: dto.assetIds }),
|
||||
]);
|
||||
|
||||
const items: Insertable<TagAsset>[] = [];
|
||||
const items: Insertable<TagAssetTable>[] = [];
|
||||
for (const tagsId of tagIds) {
|
||||
for (const assetsId of assetIds) {
|
||||
items.push({ tagsId, assetsId });
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Kysely } from 'kysely';
|
||||
import { Kysely, ColumnType as KyselyColumnType } from 'kysely';
|
||||
|
||||
export type PostgresDB = {
|
||||
pg_am: {
|
||||
@ -476,3 +476,10 @@ export enum Reason {
|
||||
MissingInSource = 'missing in source',
|
||||
MissingInTarget = 'missing in target',
|
||||
}
|
||||
|
||||
export type Timestamp = KyselyColumnType<Date, Date | string, Date | string>;
|
||||
export type Generated<T> =
|
||||
T extends KyselyColumnType<infer S, infer I, infer U>
|
||||
? KyselyColumnType<S, I | undefined, U>
|
||||
: KyselyColumnType<T, T | undefined, T>;
|
||||
export type Int8 = KyselyColumnType<number>;
|
||||
|
@ -16,9 +16,9 @@ import { jsonArrayFrom, jsonObjectFrom } from 'kysely/helpers/postgres';
|
||||
import { parse } from 'pg-connection-string';
|
||||
import postgres, { Notice } from 'postgres';
|
||||
import { columns, Exif, Person } from 'src/database';
|
||||
import { DB } from 'src/db';
|
||||
import { AssetFileType, AssetVisibility, DatabaseExtension, DatabaseSslMode } from 'src/enum';
|
||||
import { AssetSearchBuilderOptions } from 'src/repositories/search.repository';
|
||||
import { DB } from 'src/schema';
|
||||
import { DatabaseConnectionParams, VectorExtension } from 'src/types';
|
||||
|
||||
type Ssl = 'require' | 'allow' | 'prefer' | 'verify-full' | boolean | object;
|
||||
|
1
server/test/fixtures/asset.stub.ts
vendored
1
server/test/fixtures/asset.stub.ts
vendored
@ -35,6 +35,7 @@ export const stackStub = (stackId: string, assets: (MapAsset & { exifInfo: Exif
|
||||
primaryAssetId: assets[0].id,
|
||||
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
||||
updatedAt: new Date('2023-02-23T05:06:29.716Z'),
|
||||
updateId: 'uuid-v7',
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -4,7 +4,6 @@ import { DateTime } from 'luxon';
|
||||
import { createHash, randomBytes } from 'node:crypto';
|
||||
import { Writable } from 'node:stream';
|
||||
import { AssetFace } from 'src/database';
|
||||
import { Albums, AssetJobStatus, Assets, DB, Exif, FaceSearch, Memories, Person, Sessions } from 'src/db';
|
||||
import { AuthDto, LoginResponseDto } from 'src/dtos/auth.dto';
|
||||
import { AlbumUserRole, AssetType, AssetVisibility, MemoryType, SourceType, SyncRequestType } from 'src/enum';
|
||||
import { AccessRepository } from 'src/repositories/access.repository';
|
||||
@ -32,6 +31,15 @@ import { SyncRepository } from 'src/repositories/sync.repository';
|
||||
import { SystemMetadataRepository } from 'src/repositories/system-metadata.repository';
|
||||
import { UserRepository } from 'src/repositories/user.repository';
|
||||
import { VersionHistoryRepository } from 'src/repositories/version-history.repository';
|
||||
import { DB } from 'src/schema';
|
||||
import { AlbumTable } from 'src/schema/tables/album.table';
|
||||
import { AssetJobStatusTable } from 'src/schema/tables/asset-job-status.table';
|
||||
import { AssetTable } from 'src/schema/tables/asset.table';
|
||||
import { ExifTable } from 'src/schema/tables/exif.table';
|
||||
import { FaceSearchTable } from 'src/schema/tables/face-search.table';
|
||||
import { MemoryTable } from 'src/schema/tables/memory.table';
|
||||
import { PersonTable } from 'src/schema/tables/person.table';
|
||||
import { SessionTable } from 'src/schema/tables/session.table';
|
||||
import { UserTable } from 'src/schema/tables/user.table';
|
||||
import { BASE_SERVICE_DEPENDENCIES, BaseService } from 'src/services/base.service';
|
||||
import { SyncService } from 'src/services/sync.service';
|
||||
@ -125,13 +133,13 @@ export class MediumTestContext<S extends BaseService = BaseService> {
|
||||
return { partner, result };
|
||||
}
|
||||
|
||||
async newAsset(dto: Partial<Insertable<Assets>> = {}) {
|
||||
async newAsset(dto: Partial<Insertable<AssetTable>> = {}) {
|
||||
const asset = mediumFactory.assetInsert(dto);
|
||||
const result = await this.get(AssetRepository).create(asset);
|
||||
return { asset, result };
|
||||
}
|
||||
|
||||
async newMemory(dto: Partial<Insertable<Memories>> = {}) {
|
||||
async newMemory(dto: Partial<Insertable<MemoryTable>> = {}) {
|
||||
const memory = mediumFactory.memoryInsert(dto);
|
||||
const result = await this.get(MemoryRepository).create(memory, new Set<string>());
|
||||
return { memory, result };
|
||||
@ -142,12 +150,12 @@ export class MediumTestContext<S extends BaseService = BaseService> {
|
||||
return { memoryAsset: dto, result };
|
||||
}
|
||||
|
||||
async newExif(dto: Insertable<Exif>) {
|
||||
async newExif(dto: Insertable<ExifTable>) {
|
||||
const result = await this.get(AssetRepository).upsertExif(dto);
|
||||
return { result };
|
||||
}
|
||||
|
||||
async newAlbum(dto: Insertable<Albums>) {
|
||||
async newAlbum(dto: Insertable<AlbumTable>) {
|
||||
const album = mediumFactory.albumInsert(dto);
|
||||
const result = await this.get(AlbumRepository).create(album, [], []);
|
||||
return { album, result };
|
||||
@ -164,19 +172,19 @@ export class MediumTestContext<S extends BaseService = BaseService> {
|
||||
return { albumUser: { albumId, userId, role }, result };
|
||||
}
|
||||
|
||||
async newJobStatus(dto: Partial<Insertable<AssetJobStatus>> & { assetId: string }) {
|
||||
async newJobStatus(dto: Partial<Insertable<AssetJobStatusTable>> & { assetId: string }) {
|
||||
const jobStatus = mediumFactory.assetJobStatusInsert({ assetId: dto.assetId });
|
||||
const result = await this.get(AssetRepository).upsertJobStatus(jobStatus);
|
||||
return { jobStatus, result };
|
||||
}
|
||||
|
||||
async newPerson(dto: Partial<Insertable<Person>> & { ownerId: string }) {
|
||||
async newPerson(dto: Partial<Insertable<PersonTable>> & { ownerId: string }) {
|
||||
const person = mediumFactory.personInsert(dto);
|
||||
const result = await this.get(PersonRepository).create(person);
|
||||
return { person, result };
|
||||
}
|
||||
|
||||
async newSession(dto: Partial<Insertable<Sessions>> & { userId: string }) {
|
||||
async newSession(dto: Partial<Insertable<SessionTable>> & { userId: string }) {
|
||||
const session = mediumFactory.sessionInsert(dto);
|
||||
const result = await this.get(SessionRepository).create(session);
|
||||
return { session, result };
|
||||
@ -338,10 +346,10 @@ const newMockRepository = <T>(key: ClassConstructor<T>) => {
|
||||
}
|
||||
};
|
||||
|
||||
const assetInsert = (asset: Partial<Insertable<Assets>> = {}) => {
|
||||
const assetInsert = (asset: Partial<Insertable<AssetTable>> = {}) => {
|
||||
const id = asset.id || newUuid();
|
||||
const now = newDate();
|
||||
const defaults: Insertable<Assets> = {
|
||||
const defaults: Insertable<AssetTable> = {
|
||||
deviceAssetId: '',
|
||||
deviceId: '',
|
||||
originalFileName: '',
|
||||
@ -363,9 +371,9 @@ const assetInsert = (asset: Partial<Insertable<Assets>> = {}) => {
|
||||
};
|
||||
};
|
||||
|
||||
const albumInsert = (album: Partial<Insertable<Albums>> & { ownerId: string }) => {
|
||||
const albumInsert = (album: Partial<Insertable<AlbumTable>> & { ownerId: string }) => {
|
||||
const id = album.id || newUuid();
|
||||
const defaults: Omit<Insertable<Albums>, 'ownerId'> = {
|
||||
const defaults: Omit<Insertable<AlbumTable>, 'ownerId'> = {
|
||||
albumName: 'Album',
|
||||
};
|
||||
|
||||
@ -376,7 +384,7 @@ const albumInsert = (album: Partial<Insertable<Albums>> & { ownerId: string }) =
|
||||
};
|
||||
};
|
||||
|
||||
const faceInsert = (face: Partial<Insertable<FaceSearch>> & { faceId: string }) => {
|
||||
const faceInsert = (face: Partial<Insertable<FaceSearchTable>> & { faceId: string }) => {
|
||||
const defaults = {
|
||||
faceId: face.faceId,
|
||||
embedding: face.embedding || newEmbedding(),
|
||||
@ -409,10 +417,10 @@ const assetFaceInsert = (assetFace: Partial<AssetFace> & { assetId: string }) =>
|
||||
};
|
||||
|
||||
const assetJobStatusInsert = (
|
||||
job: Partial<Insertable<AssetJobStatus>> & { assetId: string },
|
||||
): Insertable<AssetJobStatus> => {
|
||||
job: Partial<Insertable<AssetJobStatusTable>> & { assetId: string },
|
||||
): Insertable<AssetJobStatusTable> => {
|
||||
const date = DateTime.now().minus({ days: 15 }).toISO();
|
||||
const defaults: Omit<Insertable<AssetJobStatus>, 'assetId'> = {
|
||||
const defaults: Omit<Insertable<AssetJobStatusTable>, 'assetId'> = {
|
||||
duplicatesDetectedAt: date,
|
||||
facesRecognizedAt: date,
|
||||
metadataExtractedAt: date,
|
||||
@ -426,7 +434,7 @@ const assetJobStatusInsert = (
|
||||
};
|
||||
};
|
||||
|
||||
const personInsert = (person: Partial<Insertable<Person>> & { ownerId: string }) => {
|
||||
const personInsert = (person: Partial<Insertable<PersonTable>> & { ownerId: string }) => {
|
||||
const defaults = {
|
||||
birthDate: person.birthDate || null,
|
||||
color: person.color || null,
|
||||
@ -449,8 +457,12 @@ const personInsert = (person: Partial<Insertable<Person>> & { ownerId: string })
|
||||
|
||||
const sha256 = (value: string) => createHash('sha256').update(value).digest('base64');
|
||||
|
||||
const sessionInsert = ({ id = newUuid(), userId, ...session }: Partial<Insertable<Sessions>> & { userId: string }) => {
|
||||
const defaults: Insertable<Sessions> = {
|
||||
const sessionInsert = ({
|
||||
id = newUuid(),
|
||||
userId,
|
||||
...session
|
||||
}: Partial<Insertable<SessionTable>> & { userId: string }) => {
|
||||
const defaults: Insertable<SessionTable> = {
|
||||
id,
|
||||
userId,
|
||||
token: sha256(id),
|
||||
@ -478,11 +490,11 @@ const userInsert = (user: Partial<Insertable<UserTable>> = {}) => {
|
||||
return { ...defaults, ...user, id };
|
||||
};
|
||||
|
||||
const memoryInsert = (memory: Partial<Insertable<Memories>> = {}) => {
|
||||
const memoryInsert = (memory: Partial<Insertable<MemoryTable>> = {}) => {
|
||||
const id = memory.id || newUuid();
|
||||
const date = newDate();
|
||||
|
||||
const defaults: Insertable<Memories> = {
|
||||
const defaults: Insertable<MemoryTable> = {
|
||||
id,
|
||||
createdAt: date,
|
||||
updatedAt: date,
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { Kysely } from 'kysely';
|
||||
import { DB } from 'src/db';
|
||||
import { ConfigRepository } from 'src/repositories/config.repository';
|
||||
import { DatabaseRepository } from 'src/repositories/database.repository';
|
||||
import { LoggingRepository } from 'src/repositories/logging.repository';
|
||||
import { DB } from 'src/schema';
|
||||
import { getKyselyConfig } from 'src/utils/database';
|
||||
import { GenericContainer, Wait } from 'testcontainers';
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Kysely } from 'kysely';
|
||||
import { DB } from 'src/db';
|
||||
import { AssetRepository } from 'src/repositories/asset.repository';
|
||||
import { LoggingRepository } from 'src/repositories/logging.repository';
|
||||
import { DB } from 'src/schema';
|
||||
import { AssetService } from 'src/services/asset.service';
|
||||
import { newMediumService } from 'test/medium.factory';
|
||||
import { factory } from 'test/small.factory';
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { BadRequestException } from '@nestjs/common';
|
||||
import { hash } from 'bcrypt';
|
||||
import { Kysely } from 'kysely';
|
||||
import { DB } from 'src/db';
|
||||
import { AuthType } from 'src/enum';
|
||||
import { AccessRepository } from 'src/repositories/access.repository';
|
||||
import { ConfigRepository } from 'src/repositories/config.repository';
|
||||
@ -13,6 +12,7 @@ import { SessionRepository } from 'src/repositories/session.repository';
|
||||
import { StorageRepository } from 'src/repositories/storage.repository';
|
||||
import { SystemMetadataRepository } from 'src/repositories/system-metadata.repository';
|
||||
import { UserRepository } from 'src/repositories/user.repository';
|
||||
import { DB } from 'src/schema';
|
||||
import { AuthService } from 'src/services/auth.service';
|
||||
import { mediumFactory, newMediumService } from 'test/medium.factory';
|
||||
import { factory } from 'test/small.factory';
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { Kysely } from 'kysely';
|
||||
import { DateTime } from 'luxon';
|
||||
import { DB } from 'src/db';
|
||||
import { AssetFileType, MemoryType } from 'src/enum';
|
||||
import { AccessRepository } from 'src/repositories/access.repository';
|
||||
import { AssetRepository } from 'src/repositories/asset.repository';
|
||||
@ -10,6 +9,7 @@ import { MemoryRepository } from 'src/repositories/memory.repository';
|
||||
import { PartnerRepository } from 'src/repositories/partner.repository';
|
||||
import { SystemMetadataRepository } from 'src/repositories/system-metadata.repository';
|
||||
import { UserRepository } from 'src/repositories/user.repository';
|
||||
import { DB } from 'src/schema';
|
||||
import { MemoryService } from 'src/services/memory.service';
|
||||
import { newMediumService } from 'test/medium.factory';
|
||||
import { factory } from 'test/small.factory';
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { Kysely } from 'kysely';
|
||||
import { DB } from 'src/db';
|
||||
import { AccessRepository } from 'src/repositories/access.repository';
|
||||
import { DatabaseRepository } from 'src/repositories/database.repository';
|
||||
import { LoggingRepository } from 'src/repositories/logging.repository';
|
||||
import { PersonRepository } from 'src/repositories/person.repository';
|
||||
import { StorageRepository } from 'src/repositories/storage.repository';
|
||||
import { DB } from 'src/schema';
|
||||
import { PersonService } from 'src/services/person.service';
|
||||
import { newMediumService } from 'test/medium.factory';
|
||||
import { factory } from 'test/small.factory';
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { Kysely } from 'kysely';
|
||||
import { DateTime } from 'luxon';
|
||||
import { DB } from 'src/db';
|
||||
import { ImmichEnvironment, JobName, JobStatus } from 'src/enum';
|
||||
import { ConfigRepository } from 'src/repositories/config.repository';
|
||||
import { CryptoRepository } from 'src/repositories/crypto.repository';
|
||||
@ -8,6 +7,7 @@ import { JobRepository } from 'src/repositories/job.repository';
|
||||
import { LoggingRepository } from 'src/repositories/logging.repository';
|
||||
import { SystemMetadataRepository } from 'src/repositories/system-metadata.repository';
|
||||
import { UserRepository } from 'src/repositories/user.repository';
|
||||
import { DB } from 'src/schema';
|
||||
import { UserService } from 'src/services/user.service';
|
||||
import { mediumFactory, newMediumService } from 'test/medium.factory';
|
||||
import { factory } from 'test/small.factory';
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { Kysely } from 'kysely';
|
||||
import { serverVersion } from 'src/constants';
|
||||
import { DB } from 'src/db';
|
||||
import { JobName } from 'src/enum';
|
||||
import { DatabaseRepository } from 'src/repositories/database.repository';
|
||||
import { JobRepository } from 'src/repositories/job.repository';
|
||||
import { LoggingRepository } from 'src/repositories/logging.repository';
|
||||
import { VersionHistoryRepository } from 'src/repositories/version-history.repository';
|
||||
import { DB } from 'src/schema';
|
||||
import { VersionService } from 'src/services/version.service';
|
||||
import { newMediumService } from 'test/medium.factory';
|
||||
import { getKyselyDB } from 'test/utils';
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Kysely } from 'kysely';
|
||||
import { DB } from 'src/db';
|
||||
import { AlbumUserRole, SyncEntityType, SyncRequestType } from 'src/enum';
|
||||
import { DB } from 'src/schema';
|
||||
import { SyncTestContext } from 'test/medium.factory';
|
||||
import { factory } from 'test/small.factory';
|
||||
import { getKyselyDB, wait } from 'test/utils';
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Kysely } from 'kysely';
|
||||
import { DB } from 'src/db';
|
||||
import { AlbumUserRole, SyncEntityType, SyncRequestType } from 'src/enum';
|
||||
import { DB } from 'src/schema';
|
||||
import { SyncTestContext } from 'test/medium.factory';
|
||||
import { factory } from 'test/small.factory';
|
||||
import { getKyselyDB, wait } from 'test/utils';
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { Kysely } from 'kysely';
|
||||
import { DB } from 'src/db';
|
||||
import { AlbumUserRole, SyncEntityType, SyncRequestType } from 'src/enum';
|
||||
import { AlbumRepository } from 'src/repositories/album.repository';
|
||||
import { AssetRepository } from 'src/repositories/asset.repository';
|
||||
import { DB } from 'src/schema';
|
||||
import { SyncTestContext } from 'test/medium.factory';
|
||||
import { getKyselyDB, wait } from 'test/utils';
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Kysely } from 'kysely';
|
||||
import { DB } from 'src/db';
|
||||
import { AlbumUserRole, SyncEntityType, SyncRequestType } from 'src/enum';
|
||||
import { AlbumUserRepository } from 'src/repositories/album-user.repository';
|
||||
import { DB } from 'src/schema';
|
||||
import { SyncTestContext } from 'test/medium.factory';
|
||||
import { getKyselyDB, wait } from 'test/utils';
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { Kysely } from 'kysely';
|
||||
import { DB } from 'src/db';
|
||||
import { AlbumUserRole, SyncEntityType, SyncRequestType } from 'src/enum';
|
||||
import { AlbumUserRepository } from 'src/repositories/album-user.repository';
|
||||
import { AlbumRepository } from 'src/repositories/album.repository';
|
||||
import { DB } from 'src/schema';
|
||||
import { SyncTestContext } from 'test/medium.factory';
|
||||
import { getKyselyDB } from 'test/utils';
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Kysely } from 'kysely';
|
||||
import { DB } from 'src/db';
|
||||
import { SyncEntityType, SyncRequestType } from 'src/enum';
|
||||
import { DB } from 'src/schema';
|
||||
import { SyncTestContext } from 'test/medium.factory';
|
||||
import { factory } from 'test/small.factory';
|
||||
import { getKyselyDB } from 'test/utils';
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Kysely } from 'kysely';
|
||||
import { DB } from 'src/db';
|
||||
import { SyncEntityType, SyncRequestType } from 'src/enum';
|
||||
import { AssetRepository } from 'src/repositories/asset.repository';
|
||||
import { DB } from 'src/schema';
|
||||
import { SyncTestContext } from 'test/medium.factory';
|
||||
import { factory } from 'test/small.factory';
|
||||
import { getKyselyDB } from 'test/utils';
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Kysely } from 'kysely';
|
||||
import { DB } from 'src/db';
|
||||
import { SyncEntityType, SyncRequestType } from 'src/enum';
|
||||
import { MemoryRepository } from 'src/repositories/memory.repository';
|
||||
import { DB } from 'src/schema';
|
||||
import { SyncTestContext } from 'test/medium.factory';
|
||||
import { getKyselyDB } from 'test/utils';
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Kysely } from 'kysely';
|
||||
import { DB } from 'src/db';
|
||||
import { SyncEntityType, SyncRequestType } from 'src/enum';
|
||||
import { MemoryRepository } from 'src/repositories/memory.repository';
|
||||
import { DB } from 'src/schema';
|
||||
import { SyncTestContext } from 'test/medium.factory';
|
||||
import { getKyselyDB } from 'test/utils';
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Kysely } from 'kysely';
|
||||
import { DB } from 'src/db';
|
||||
import { SyncEntityType, SyncRequestType } from 'src/enum';
|
||||
import { DB } from 'src/schema';
|
||||
import { SyncTestContext } from 'test/medium.factory';
|
||||
import { factory } from 'test/small.factory';
|
||||
import { getKyselyDB, wait } from 'test/utils';
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { Kysely } from 'kysely';
|
||||
import { DB } from 'src/db';
|
||||
import { SyncEntityType, SyncRequestType } from 'src/enum';
|
||||
import { AssetRepository } from 'src/repositories/asset.repository';
|
||||
import { PartnerRepository } from 'src/repositories/partner.repository';
|
||||
import { UserRepository } from 'src/repositories/user.repository';
|
||||
import { DB } from 'src/schema';
|
||||
import { SyncTestContext } from 'test/medium.factory';
|
||||
import { factory } from 'test/small.factory';
|
||||
import { getKyselyDB, wait } from 'test/utils';
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { Kysely } from 'kysely';
|
||||
import { DB } from 'src/db';
|
||||
import { SyncEntityType, SyncRequestType } from 'src/enum';
|
||||
import { PartnerRepository } from 'src/repositories/partner.repository';
|
||||
import { UserRepository } from 'src/repositories/user.repository';
|
||||
import { DB } from 'src/schema';
|
||||
import { SyncTestContext } from 'test/medium.factory';
|
||||
import { getKyselyDB } from 'test/utils';
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Kysely } from 'kysely';
|
||||
import { DB } from 'src/db';
|
||||
import { SyncEntityType, SyncRequestType } from 'src/enum';
|
||||
import { UserRepository } from 'src/repositories/user.repository';
|
||||
import { DB } from 'src/schema';
|
||||
import { SyncTestContext } from 'test/medium.factory';
|
||||
import { getKyselyDB } from 'test/utils';
|
||||
|
||||
|
@ -7,7 +7,6 @@ import { ChildProcessWithoutNullStreams } from 'node:child_process';
|
||||
import { Writable } from 'node:stream';
|
||||
import { PNG } from 'pngjs';
|
||||
import postgres from 'postgres';
|
||||
import { DB } from 'src/db';
|
||||
import { AssetUploadInterceptor } from 'src/middleware/asset-upload.interceptor';
|
||||
import { AuthGuard } from 'src/middleware/auth.guard';
|
||||
import { FileUploadInterceptor } from 'src/middleware/file-upload.interceptor';
|
||||
@ -56,6 +55,7 @@ import { TrashRepository } from 'src/repositories/trash.repository';
|
||||
import { UserRepository } from 'src/repositories/user.repository';
|
||||
import { VersionHistoryRepository } from 'src/repositories/version-history.repository';
|
||||
import { ViewRepository } from 'src/repositories/view-repository';
|
||||
import { DB } from 'src/schema';
|
||||
import { AuthService } from 'src/services/auth.service';
|
||||
import { BaseService } from 'src/services/base.service';
|
||||
import { RepositoryInterface } from 'src/types';
|
||||
|
Loading…
x
Reference in New Issue
Block a user