use typeorm entities for kysely types

This commit is contained in:
mertalev 2025-01-02 18:20:13 -05:00
parent 88bf0615fe
commit 5ebb8e1a33
No known key found for this signature in database
GPG Key ID: 3A2B5BFC678DBC80
40 changed files with 377 additions and 846 deletions

266
server/package-lock.json generated
View File

@ -44,6 +44,7 @@
"js-yaml": "^4.1.0",
"kysely": "^0.27.3",
"kysely-postgres-js": "^2.0.0",
"kysely-typeorm": "^0.1.0",
"lodash": "^4.17.21",
"luxon": "^3.4.2",
"nest-commander": "^3.11.1",
@ -102,7 +103,6 @@
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-unicorn": "^56.0.1",
"globals": "^15.9.0",
"kysely-codegen": "^0.16.3",
"mock-fs": "^5.2.0",
"pngjs": "^7.0.0",
"prettier": "^3.0.2",
@ -9180,102 +9180,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/git-diff": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/git-diff/-/git-diff-2.0.6.tgz",
"integrity": "sha512-/Iu4prUrydE3Pb3lCBMbcSNIf81tgGt0W1ZwknnyF62t3tHmtiJTRj0f+1ZIhp3+Rh0ktz1pJVoa7ZXUCskivA==",
"dev": true,
"dependencies": {
"chalk": "^2.3.2",
"diff": "^3.5.0",
"loglevel": "^1.6.1",
"shelljs": "^0.8.1",
"shelljs.exec": "^1.1.7"
},
"engines": {
"node": ">= 4.8.0"
}
},
"node_modules/git-diff/node_modules/ansi-styles": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
"dev": true,
"dependencies": {
"color-convert": "^1.9.0"
},
"engines": {
"node": ">=4"
}
},
"node_modules/git-diff/node_modules/chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"dev": true,
"dependencies": {
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
"supports-color": "^5.3.0"
},
"engines": {
"node": ">=4"
}
},
"node_modules/git-diff/node_modules/color-convert": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
"dev": true,
"dependencies": {
"color-name": "1.1.3"
}
},
"node_modules/git-diff/node_modules/color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
"dev": true
},
"node_modules/git-diff/node_modules/diff": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
"integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
"dev": true,
"engines": {
"node": ">=0.3.1"
}
},
"node_modules/git-diff/node_modules/escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
"dev": true,
"engines": {
"node": ">=0.8.0"
}
},
"node_modules/git-diff/node_modules/has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
"dev": true,
"engines": {
"node": ">=4"
}
},
"node_modules/git-diff/node_modules/supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
"dev": true,
"dependencies": {
"has-flag": "^3.0.0"
},
"engines": {
"node": ">=4"
}
},
"node_modules/glob": {
"version": "10.4.5",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
@ -9717,15 +9621,6 @@
"node": ">=12.0.0"
}
},
"node_modules/interpret": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz",
"integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==",
"dev": true,
"engines": {
"node": ">= 0.10"
}
},
"node_modules/ioredis": {
"version": "5.4.1",
"resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.4.1.tgz",
@ -10165,83 +10060,6 @@
"node": ">=14.0.0"
}
},
"node_modules/kysely-codegen": {
"version": "0.16.3",
"resolved": "https://registry.npmjs.org/kysely-codegen/-/kysely-codegen-0.16.3.tgz",
"integrity": "sha512-SOOF3AhrsjREJuRewXmKl0nb6CkEzpP7VavHXzWdfIdIdfoJnlWlozuZhgMsYoIFmzL8aG4skvKGXF/dF3mbwg==",
"dev": true,
"dependencies": {
"chalk": "4.1.2",
"dotenv": "^16.4.5",
"dotenv-expand": "^11.0.6",
"git-diff": "^2.0.6",
"micromatch": "^4.0.8",
"minimist": "^1.2.8",
"pluralize": "^8.0.0"
},
"bin": {
"kysely-codegen": "dist/cli/bin.js"
},
"peerDependencies": {
"@libsql/kysely-libsql": "^0.3.0",
"@tediousjs/connection-string": "^0.5.0",
"better-sqlite3": ">=7.6.2",
"kysely": "^0.27.0",
"kysely-bun-sqlite": "^0.3.2",
"kysely-bun-worker": "^0.5.3",
"mysql2": "^2.3.3 || ^3.0.0",
"pg": "^8.8.0",
"tarn": "^3.0.0",
"tedious": "^18.0.0"
},
"peerDependenciesMeta": {
"@libsql/kysely-libsql": {
"optional": true
},
"@tediousjs/connection-string": {
"optional": true
},
"better-sqlite3": {
"optional": true
},
"kysely": {
"optional": false
},
"kysely-bun-sqlite": {
"optional": true
},
"kysely-bun-worker": {
"optional": true
},
"mysql2": {
"optional": true
},
"pg": {
"optional": true
},
"tarn": {
"optional": true
},
"tedious": {
"optional": true
}
}
},
"node_modules/kysely-codegen/node_modules/dotenv-expand": {
"version": "11.0.6",
"resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-11.0.6.tgz",
"integrity": "sha512-8NHi73otpWsZGBSZwwknTXS5pqMOrk9+Ssrna8xCaxkzEpU9OTf9R5ArQGVw03//Zmk9MOwLPng9WwndvpAJ5g==",
"dev": true,
"dependencies": {
"dotenv": "^16.4.4"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://dotenvx.com"
}
},
"node_modules/kysely-postgres-js": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/kysely-postgres-js/-/kysely-postgres-js-2.0.0.tgz",
@ -10251,6 +10069,16 @@
"postgres": ">= 3.4.0 < 4"
}
},
"node_modules/kysely-typeorm": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/kysely-typeorm/-/kysely-typeorm-0.1.0.tgz",
"integrity": "sha512-YLqkHKG9kL46KPzU4mNBO1mzTQctxO963gEG49PJevxmiPzOz2+W6ge3rR8KjGtsY6kZ/xBIibt9cMWfEGobGQ==",
"license": "MIT",
"peerDependencies": {
"kysely": ">= 0.24.0 < 1",
"typeorm": ">= 0.3.0 < 0.4.0"
}
},
"node_modules/lazystream": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz",
@ -10424,19 +10252,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/loglevel": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.9.1.tgz",
"integrity": "sha512-hP3I3kCrDIMuRwAwHltphhDM1r8i55H33GgqjXbrisuJhF4kRhW1dNuxsRklp4bXl8DSdLaNLuiL4A/LWRfxvg==",
"dev": true,
"engines": {
"node": ">= 0.6.0"
},
"funding": {
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/loglevel"
}
},
"node_modules/long": {
"version": "5.2.3",
"resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz",
@ -12730,18 +12545,6 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/rechoir": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
"integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==",
"dev": true,
"dependencies": {
"resolve": "^1.1.6"
},
"engines": {
"node": ">= 0.10"
}
},
"node_modules/redis-errors": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz",
@ -13425,53 +13228,6 @@
"node": ">=8"
}
},
"node_modules/shelljs": {
"version": "0.8.5",
"resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz",
"integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==",
"dev": true,
"dependencies": {
"glob": "^7.0.0",
"interpret": "^1.0.0",
"rechoir": "^0.6.2"
},
"bin": {
"shjs": "bin/shjs"
},
"engines": {
"node": ">=4"
}
},
"node_modules/shelljs.exec": {
"version": "1.1.8",
"resolved": "https://registry.npmjs.org/shelljs.exec/-/shelljs.exec-1.1.8.tgz",
"integrity": "sha512-vFILCw+lzUtiwBAHV8/Ex8JsFjelFMdhONIsgKNLgTzeRckp2AOYRQtHJE/9LhNvdMmE27AGtzWx0+DHpwIwSw==",
"dev": true,
"engines": {
"node": ">= 4.0.0"
}
},
"node_modules/shelljs/node_modules/glob": {
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
"deprecated": "Glob versions prior to v9 are no longer supported",
"dev": true,
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.1.1",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
},
"engines": {
"node": "*"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/shimmer": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz",

View File

@ -69,6 +69,7 @@
"js-yaml": "^4.1.0",
"kysely": "^0.27.3",
"kysely-postgres-js": "^2.0.0",
"kysely-typeorm": "^0.1.0",
"lodash": "^4.17.21",
"luxon": "^3.4.2",
"nest-commander": "^3.11.1",
@ -127,7 +128,6 @@
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-unicorn": "^56.0.1",
"globals": "^15.9.0",
"kysely-codegen": "^0.16.3",
"mock-fs": "^5.2.0",
"pngjs": "^7.0.0",
"prettier": "^3.0.2",

439
server/src/db.d.ts vendored
View File

@ -1,439 +0,0 @@
/**
* This file was generated by kysely-codegen.
* Please do not edit it manually.
*/
import type { ColumnType } from 'kysely';
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 AssetsStatusEnum = 'active' | 'deleted' | 'trashed';
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<string, bigint | number | string, bigint | number | string>;
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 Sourcetype = 'exif' | 'machine-learning';
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>;
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<string>;
ownerId: string;
updatedAt: Generated<Timestamp>;
}
export interface AlbumsAssetsAssets {
albumsId: string;
assetsId: string;
}
export interface AlbumsSharedUsersUsers {
albumsId: string;
role: Generated<string>;
usersId: string;
}
export interface ApiKeys {
createdAt: Generated<Timestamp>;
id: Generated<string>;
key: string;
name: string;
permissions: string[];
updatedAt: Generated<Timestamp>;
userId: string;
}
export interface AssetFaces {
assetId: string;
boundingBoxX1: Generated<number>;
boundingBoxX2: Generated<number>;
boundingBoxY1: Generated<number>;
boundingBoxY2: Generated<number>;
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: string;
updatedAt: Generated<Timestamp>;
}
export interface AssetJobStatus {
assetId: string;
duplicatesDetectedAt: Timestamp | null;
facesRecognizedAt: Timestamp | null;
metadataExtractedAt: Timestamp | null;
previewAt: Timestamp | null;
thumbnailAt: Timestamp | null;
}
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>;
isArchived: Generated<boolean>;
isExternal: Generated<boolean>;
isFavorite: Generated<boolean>;
isOffline: Generated<boolean>;
isVisible: Generated<boolean>;
libraryId: string | null;
livePhotoVideoId: string | null;
localDateTime: Timestamp;
originalFileName: string;
originalPath: string;
ownerId: string;
sidecarPath: string | null;
stackId: string | null;
status: Generated<AssetsStatusEnum>;
thumbhash: Buffer | null;
type: string;
updatedAt: Generated<Timestamp>;
}
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;
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;
earthCoord: Generated<string | null>;
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>;
}
export interface Memories {
createdAt: Generated<Timestamp>;
data: Json;
deletedAt: Timestamp | null;
id: Generated<string>;
isSaved: Generated<boolean>;
memoryAt: Timestamp;
ownerId: string;
seenAt: Timestamp | null;
type: string;
updatedAt: Generated<Timestamp>;
}
export interface MemoriesAssetsAssets {
assetsId: string;
memoriesId: string;
}
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 Partners {
createdAt: Generated<Timestamp>;
inTimeline: Generated<boolean>;
sharedById: string;
sharedWithId: string;
updatedAt: Generated<Timestamp>;
}
export interface Person {
birthDate: Timestamp | null;
createdAt: Generated<Timestamp>;
faceAssetId: string | null;
id: Generated<string>;
isHidden: Generated<boolean>;
name: Generated<string>;
ownerId: string;
thumbnailPath: Generated<string>;
updatedAt: Generated<Timestamp>;
}
export interface Sessions {
createdAt: Generated<Timestamp>;
deviceOS: Generated<string>;
deviceType: Generated<string>;
id: Generated<string>;
token: string;
updatedAt: Generated<Timestamp>;
userId: 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: string;
userId: string;
}
export interface SmartInfo {
assetId: string;
objects: string[] | null;
smartInfoTextSearchableColumn: Generated<string>;
tags: string[] | null;
}
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>;
userId: string;
value: string;
}
export interface TagsClosure {
id_ancestor: string;
id_descendant: string;
}
export interface UserMetadata {
key: string;
userId: string;
value: Json;
}
export interface Users {
createdAt: Generated<Timestamp>;
deletedAt: Timestamp | null;
email: string;
id: Generated<string>;
isAdmin: Generated<boolean>;
name: Generated<string>;
oauthId: Generated<string>;
password: Generated<string>;
profileChangedAt: Generated<Timestamp>;
profileImagePath: Generated<string>;
quotaSizeInBytes: Int8 | null;
quotaUsageInBytes: Generated<Int8>;
shouldChangePassword: Generated<boolean>;
status: Generated<string>;
storageLabel: string | null;
updatedAt: 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 DB {
activity: Activity;
albums: Albums;
albums_assets_assets: AlbumsAssetsAssets;
albums_shared_users_users: AlbumsSharedUsersUsers;
api_keys: ApiKeys;
asset_faces: AssetFaces;
asset_files: AssetFiles;
asset_job_status: AssetJobStatus;
asset_stack: AssetStack;
assets: Assets;
audit: Audit;
exif: Exif;
face_search: FaceSearch;
geodata_places: GeodataPlaces;
libraries: Libraries;
memories: Memories;
memories_assets_assets: MemoriesAssetsAssets;
migrations: Migrations;
move_history: MoveHistory;
naturalearth_countries: NaturalearthCountries;
partners: Partners;
person: Person;
sessions: Sessions;
shared_link__asset: SharedLinkAsset;
shared_links: SharedLinks;
smart_info: SmartInfo;
smart_search: SmartSearch;
socket_io_attachments: SocketIoAttachments;
system_config: SystemConfig;
system_metadata: SystemMetadata;
tag_asset: TagAsset;
tags: Tags;
tags_closure: TagsClosure;
user_metadata: UserMetadata;
users: Users;
'vectors.pg_vector_index_stat': VectorsPgVectorIndexStat;
}

View File

@ -1,3 +1,4 @@
import type { Generated, NonAttribute } from 'kysely-typeorm';
import { AlbumEntity } from 'src/entities/album.entity';
import { AssetEntity } from 'src/entities/asset.entity';
import { UserEntity } from 'src/entities/user.entity';
@ -17,13 +18,13 @@ import {
@Check(`("comment" IS NULL AND "isLiked" = true) OR ("comment" IS NOT NULL AND "isLiked" = false)`)
export class ActivityEntity {
@PrimaryGeneratedColumn('uuid')
id!: string;
id!: Generated<string>;
@CreateDateColumn({ type: 'timestamptz' })
createdAt!: Date;
createdAt!: Generated<Date>;
@UpdateDateColumn({ type: 'timestamptz' })
updatedAt!: Date;
updatedAt!: Generated<Date>;
@Column()
albumId!: string;
@ -35,17 +36,17 @@ export class ActivityEntity {
assetId!: string | null;
@Column({ type: 'text', default: null })
comment!: string | null;
comment!: Generated<string> | null;
@Column({ type: 'boolean', default: false })
isLiked!: boolean;
isLiked!: Generated<boolean>;
@ManyToOne(() => AssetEntity, { onDelete: 'CASCADE', onUpdate: 'CASCADE', nullable: true })
asset!: AssetEntity | null;
asset!: NonAttribute<AssetEntity | null>;
@ManyToOne(() => UserEntity, { onDelete: 'CASCADE', onUpdate: 'CASCADE' })
user!: UserEntity;
user!: NonAttribute<UserEntity>;
@ManyToOne(() => AlbumEntity, { onDelete: 'CASCADE', onUpdate: 'CASCADE' })
album!: AlbumEntity;
album!: NonAttribute<AlbumEntity>;
}

View File

@ -0,0 +1,23 @@
import type { NonAttribute } from 'kysely-typeorm';
import { AlbumEntity } from 'src/entities/album.entity';
import { AssetEntity } from 'src/entities/asset.entity';
import { Entity, Index, JoinColumn, ManyToOne, PrimaryColumn } from 'typeorm';
@Entity('albums_assets_assets')
export class AlbumAssetEntity {
@PrimaryColumn('uuid')
@Index('IDX_e590fa396c6898fcd4a50e4092')
albumsId!: string;
@ManyToOne(() => AlbumEntity, { onDelete: 'CASCADE', onUpdate: 'CASCADE' })
@JoinColumn({ name: 'albumsId' })
album!: NonAttribute<AlbumEntity>;
@PrimaryColumn('uuid')
@Index('IDX_4bd1303d199f4e72ccdf998c62')
assetsId!: string;
@ManyToOne(() => AssetEntity, { onDelete: 'CASCADE', onUpdate: 'CASCADE' })
@JoinColumn({ name: 'assetsId' })
asset!: NonAttribute<AssetEntity>;
}

View File

@ -1,3 +1,4 @@
import type { Generated, NonAttribute } from 'kysely-typeorm';
import { AlbumEntity } from 'src/entities/album.entity';
import { UserEntity } from 'src/entities/user.entity';
import { AlbumUserRole } from 'src/enum';
@ -16,12 +17,12 @@ export class AlbumUserEntity {
@JoinColumn({ name: 'albumsId' })
@ManyToOne(() => AlbumEntity, { onDelete: 'CASCADE', onUpdate: 'CASCADE', nullable: false })
album!: AlbumEntity;
album!: NonAttribute<AlbumEntity>;
@JoinColumn({ name: 'usersId' })
@ManyToOne(() => UserEntity, { onDelete: 'CASCADE', onUpdate: 'CASCADE', nullable: false })
user!: UserEntity;
user!: NonAttribute<UserEntity>;
@Column({ type: 'varchar', default: AlbumUserRole.EDITOR })
role!: AlbumUserRole;
role!: Generated<AlbumUserRole>;
}

View File

@ -1,3 +1,4 @@
import type { Generated, NonAttribute } from 'kysely-typeorm';
import { AlbumUserEntity } from 'src/entities/album-user.entity';
import { AssetEntity } from 'src/entities/asset.entity';
import { SharedLinkEntity } from 'src/entities/shared-link.entity';
@ -19,48 +20,48 @@ import {
@Entity('albums')
export class AlbumEntity {
@PrimaryGeneratedColumn('uuid')
id!: string;
id!: Generated<string>;
@ManyToOne(() => UserEntity, { onDelete: 'CASCADE', onUpdate: 'CASCADE', nullable: false })
owner!: UserEntity;
owner!: NonAttribute<UserEntity>;
@Column()
ownerId!: string;
@Column({ default: 'Untitled Album' })
albumName!: string;
albumName!: Generated<string>;
@Column({ type: 'text', default: '' })
description!: string;
description!: Generated<string>;
@CreateDateColumn({ type: 'timestamptz' })
createdAt!: Date;
createdAt!: Generated<Date>;
@UpdateDateColumn({ type: 'timestamptz' })
updatedAt!: Date;
updatedAt!: Generated<Date>;
@DeleteDateColumn({ type: 'timestamptz' })
deletedAt!: Date | null;
@ManyToOne(() => AssetEntity, { nullable: true, onDelete: 'SET NULL', onUpdate: 'CASCADE' })
albumThumbnailAsset!: AssetEntity | null;
albumThumbnailAsset!: NonAttribute<AssetEntity | null>;
@Column({ comment: 'Asset ID to be used as thumbnail', nullable: true })
albumThumbnailAssetId!: string | null;
@OneToMany(() => AlbumUserEntity, ({ album }) => album, { cascade: true, onDelete: 'CASCADE' })
albumUsers!: AlbumUserEntity[];
albumUsers!: NonAttribute<AlbumUserEntity[]>;
@ManyToMany(() => AssetEntity, (asset) => asset.albums)
@JoinTable({ synchronize: false })
assets!: AssetEntity[];
assets!: NonAttribute<AssetEntity[]>;
@OneToMany(() => SharedLinkEntity, (link) => link.album)
sharedLinks!: SharedLinkEntity[];
sharedLinks!: NonAttribute<SharedLinkEntity[]>;
@Column({ default: true })
isActivityEnabled!: boolean;
isActivityEnabled!: Generated<boolean>;
@Column({ type: 'varchar', default: AssetOrder.DESC })
order!: AssetOrder;
order!: Generated<AssetOrder>;
}

View File

@ -1,3 +1,4 @@
import { Generated, NonAttribute } from 'kysely-typeorm';
import { UserEntity } from 'src/entities/user.entity';
import { Permission } from 'src/enum';
import { Column, CreateDateColumn, Entity, ManyToOne, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm';
@ -5,7 +6,7 @@ import { Column, CreateDateColumn, Entity, ManyToOne, PrimaryGeneratedColumn, Up
@Entity('api_keys')
export class APIKeyEntity {
@PrimaryGeneratedColumn('uuid')
id!: string;
id!: Generated<string>;
@Column()
name!: string;
@ -14,7 +15,7 @@ export class APIKeyEntity {
key?: string;
@ManyToOne(() => UserEntity, { onUpdate: 'CASCADE', onDelete: 'CASCADE' })
user?: UserEntity;
user!: NonAttribute<UserEntity>;
@Column()
userId!: string;
@ -23,8 +24,8 @@ export class APIKeyEntity {
permissions!: Permission[];
@CreateDateColumn({ type: 'timestamptz' })
createdAt!: Date;
createdAt!: Generated<Date>;
@UpdateDateColumn({ type: 'timestamptz' })
updatedAt!: Date;
updatedAt!: Generated<Date>;
}

View File

@ -1,3 +1,4 @@
import { Generated, NonAttribute } from 'kysely-typeorm';
import { AssetEntity } from 'src/entities/asset.entity';
import { FaceSearchEntity } from 'src/entities/face-search.entity';
import { PersonEntity } from 'src/entities/person.entity';
@ -9,7 +10,7 @@ import { Column, Entity, Index, ManyToOne, OneToOne, PrimaryGeneratedColumn } fr
@Index(['personId', 'assetId'])
export class AssetFaceEntity {
@PrimaryGeneratedColumn('uuid')
id!: string;
id!: Generated<string>;
@Column()
assetId!: string;
@ -18,36 +19,36 @@ export class AssetFaceEntity {
personId!: string | null;
@OneToOne(() => FaceSearchEntity, (faceSearchEntity) => faceSearchEntity.face, { cascade: ['insert'] })
faceSearch?: FaceSearchEntity;
faceSearch!: NonAttribute<FaceSearchEntity>;
@Column({ default: 0, type: 'int' })
imageWidth!: number;
imageWidth!: Generated<number>;
@Column({ default: 0, type: 'int' })
imageHeight!: number;
imageHeight!: Generated<number>;
@Column({ default: 0, type: 'int' })
boundingBoxX1!: number;
boundingBoxX1!: Generated<number>;
@Column({ default: 0, type: 'int' })
boundingBoxY1!: number;
boundingBoxY1!: Generated<number>;
@Column({ default: 0, type: 'int' })
boundingBoxX2!: number;
boundingBoxX2!: Generated<number>;
@Column({ default: 0, type: 'int' })
boundingBoxY2!: number;
boundingBoxY2!: Generated<number>;
@Column({ default: SourceType.MACHINE_LEARNING, type: 'enum', enum: SourceType })
sourceType!: SourceType;
sourceType!: Generated<SourceType>;
@ManyToOne(() => AssetEntity, (asset) => asset.faces, { onDelete: 'CASCADE', onUpdate: 'CASCADE' })
asset!: AssetEntity;
asset!: NonAttribute<AssetEntity>;
@ManyToOne(() => PersonEntity, (person) => person.faces, {
onDelete: 'SET NULL',
onUpdate: 'CASCADE',
nullable: true,
})
person!: PersonEntity | null;
person!: NonAttribute<PersonEntity | null>;
}

View File

@ -1,3 +1,4 @@
import { Generated, NonAttribute } from 'kysely-typeorm';
import { AssetEntity } from 'src/entities/asset.entity';
import { AssetFileType } from 'src/enum';
import {
@ -15,20 +16,20 @@ import {
@Entity('asset_files')
export class AssetFileEntity {
@PrimaryGeneratedColumn('uuid')
id!: string;
id!: Generated<string>;
@Index('IDX_asset_files_assetId')
@Column()
assetId!: string;
@ManyToOne(() => AssetEntity, { onDelete: 'CASCADE', onUpdate: 'CASCADE' })
asset?: AssetEntity;
asset!: NonAttribute<AssetEntity>;
@CreateDateColumn({ type: 'timestamptz' })
createdAt!: Date;
createdAt!: Generated<Date>;
@UpdateDateColumn({ type: 'timestamptz' })
updatedAt!: Date;
updatedAt!: Generated<Date>;
@Column()
type!: AssetFileType;

View File

@ -1,3 +1,4 @@
import { NonAttribute } from 'kysely-typeorm';
import { AssetEntity } from 'src/entities/asset.entity';
import { Column, Entity, JoinColumn, OneToOne, PrimaryColumn } from 'typeorm';
@ -5,7 +6,7 @@ import { Column, Entity, JoinColumn, OneToOne, PrimaryColumn } from 'typeorm';
export class AssetJobStatusEntity {
@OneToOne(() => AssetEntity, { onDelete: 'CASCADE', onUpdate: 'CASCADE' })
@JoinColumn()
asset!: AssetEntity;
asset!: NonAttribute<AssetEntity>;
@PrimaryColumn()
assetId!: string;

View File

@ -1,6 +1,7 @@
import { DeduplicateJoinsPlugin, ExpressionBuilder, Kysely, Selectable, SelectQueryBuilder, sql } from 'kysely';
import { Generated, NonAttribute } from 'kysely-typeorm';
import { jsonArrayFrom, jsonObjectFrom } from 'kysely/helpers/postgres';
import { Assets, DB } from 'src/db';
import { Assets, DB } from 'src/entities';
import { AlbumEntity } from 'src/entities/album.entity';
import { AssetFaceEntity } from 'src/entities/asset-face.entity';
import { AssetFileEntity } from 'src/entities/asset-files.entity';
@ -51,19 +52,19 @@ export const ASSET_CHECKSUM_CONSTRAINT = 'UQ_assets_owner_checksum';
// For all assets, each originalpath must be unique per user and library
export class AssetEntity {
@PrimaryGeneratedColumn('uuid')
id!: string;
id!: Generated<string>;
@Column()
deviceAssetId!: string;
@ManyToOne(() => UserEntity, { onDelete: 'CASCADE', onUpdate: 'CASCADE', nullable: false })
owner!: UserEntity;
owner!: NonAttribute<UserEntity>;
@Column()
ownerId!: string;
@ManyToOne(() => LibraryEntity, { onDelete: 'CASCADE', onUpdate: 'CASCADE' })
library?: LibraryEntity | null;
library!: NonAttribute<LibraryEntity | null>;
@Column({ nullable: true })
libraryId?: string | null;
@ -75,25 +76,25 @@ export class AssetEntity {
type!: AssetType;
@Column({ type: 'enum', enum: AssetStatus, default: AssetStatus.ACTIVE })
status!: AssetStatus;
status!: Generated<AssetStatus>;
@Column()
originalPath!: string;
@OneToMany(() => AssetFileEntity, (assetFile) => assetFile.asset)
files!: AssetFileEntity[];
files!: NonAttribute<AssetFileEntity[]>;
@Column({ type: 'bytea', nullable: true })
thumbhash!: Buffer | null;
@Column({ type: 'varchar', nullable: true, default: '' })
encodedVideoPath!: string | null;
encodedVideoPath!: Generated<string> | null;
@CreateDateColumn({ type: 'timestamptz' })
createdAt!: Date;
createdAt!: Generated<Date>;
@UpdateDateColumn({ type: 'timestamptz' })
updatedAt!: Date;
updatedAt!: Generated<Date>;
@DeleteDateColumn({ type: 'timestamptz', nullable: true })
deletedAt!: Date | null;
@ -109,16 +110,16 @@ export class AssetEntity {
fileModifiedAt!: Date;
@Column({ type: 'boolean', default: false })
isFavorite!: boolean;
isFavorite!: Generated<boolean>;
@Column({ type: 'boolean', default: false })
isArchived!: boolean;
isArchived!: Generated<boolean>;
@Column({ type: 'boolean', default: false })
isExternal!: boolean;
isExternal!: Generated<boolean>;
@Column({ type: 'boolean', default: false })
isOffline!: boolean;
isOffline!: Generated<boolean>;
@Column({ type: 'bytea' })
@Index()
@ -128,11 +129,11 @@ export class AssetEntity {
duration!: string | null;
@Column({ type: 'boolean', default: true })
isVisible!: boolean;
isVisible!: Generated<boolean>;
@ManyToOne(() => AssetEntity, { nullable: true, onUpdate: 'CASCADE', onDelete: 'SET NULL' })
@JoinColumn()
livePhotoVideo!: AssetEntity | null;
livePhotoVideo!: NonAttribute<AssetEntity | null>;
@Column({ nullable: true })
livePhotoVideoId!: string | null;
@ -145,34 +146,34 @@ export class AssetEntity {
sidecarPath!: string | null;
@OneToOne(() => ExifEntity, (exifEntity) => exifEntity.asset)
exifInfo?: ExifEntity;
exifInfo!: NonAttribute<ExifEntity>;
@OneToOne(() => SmartSearchEntity, (smartSearchEntity) => smartSearchEntity.asset)
smartSearch?: SmartSearchEntity;
smartSearch!: NonAttribute<SmartSearchEntity>;
@ManyToMany(() => TagEntity, (tag) => tag.assets, { cascade: true })
@JoinTable({ name: 'tag_asset', synchronize: false })
tags!: TagEntity[];
tags!: NonAttribute<TagEntity[]>;
@ManyToMany(() => SharedLinkEntity, (link) => link.assets, { cascade: true })
@JoinTable({ name: 'shared_link__asset' })
sharedLinks!: SharedLinkEntity[];
sharedLinks!: NonAttribute<SharedLinkEntity[]>;
@ManyToMany(() => AlbumEntity, (album) => album.assets, { onDelete: 'CASCADE', onUpdate: 'CASCADE' })
albums?: AlbumEntity[];
albums!: NonAttribute<AlbumEntity[]>;
@OneToMany(() => AssetFaceEntity, (assetFace) => assetFace.asset)
faces!: AssetFaceEntity[];
faces!: NonAttribute<AssetFaceEntity[]>;
@Column({ nullable: true })
stackId?: string | null;
@ManyToOne(() => StackEntity, { nullable: true, onDelete: 'SET NULL', onUpdate: 'CASCADE' })
@JoinColumn()
stack?: StackEntity | null;
stack!: NonAttribute<StackEntity | null>;
@OneToOne(() => AssetJobStatusEntity, (jobStatus) => jobStatus.asset, { nullable: true })
jobStatus?: AssetJobStatusEntity;
jobStatus!: NonAttribute<AssetJobStatusEntity>;
@Index('IDX_assets_duplicateId')
@Column({ type: 'uuid', nullable: true })

View File

@ -1,3 +1,4 @@
import { Generated } from 'kysely-typeorm';
import { DatabaseAction, EntityType } from 'src/enum';
import { Column, CreateDateColumn, Entity, Index, PrimaryGeneratedColumn } from 'typeorm';
@ -5,7 +6,7 @@ import { Column, CreateDateColumn, Entity, Index, PrimaryGeneratedColumn } from
@Index('IDX_ownerId_createdAt', ['ownerId', 'createdAt'])
export class AuditEntity {
@PrimaryGeneratedColumn('increment')
id!: number;
id!: Generated<number>;
@Column()
entityType!: EntityType;
@ -20,5 +21,5 @@ export class AuditEntity {
ownerId!: string;
@CreateDateColumn({ type: 'timestamptz' })
createdAt!: Date;
createdAt!: Generated<Date>;
}

View File

@ -1,3 +1,4 @@
import { Generated, NonAttribute } from 'kysely-typeorm';
import { AssetEntity } from 'src/entities/asset.entity';
import { Index, JoinColumn, OneToOne, PrimaryColumn } from 'typeorm';
import { Column } from 'typeorm/decorator/columns/Column.js';
@ -7,14 +8,14 @@ import { Entity } from 'typeorm/decorator/entity/Entity.js';
export class ExifEntity {
@OneToOne(() => AssetEntity, { onDelete: 'CASCADE', nullable: true })
@JoinColumn()
asset?: AssetEntity;
asset!: NonAttribute<AssetEntity>;
@PrimaryColumn()
assetId!: string;
/* General info */
@Column({ type: 'text', default: '' })
description!: string; // or caption
description!: Generated<string>; // or caption
@Column({ type: 'integer', nullable: true })
exifImageWidth!: number | null;

View File

@ -1,3 +1,4 @@
import { NonAttribute } from 'kysely-typeorm';
import { AssetFaceEntity } from 'src/entities/asset-face.entity';
import { Column, Entity, Index, JoinColumn, OneToOne, PrimaryColumn } from 'typeorm';
@ -5,7 +6,7 @@ import { Column, Entity, Index, JoinColumn, OneToOne, PrimaryColumn } from 'type
export class FaceSearchEntity {
@OneToOne(() => AssetFaceEntity, { onDelete: 'CASCADE', nullable: true })
@JoinColumn({ name: 'faceId', referencedColumnName: 'id' })
face?: AssetFaceEntity;
face?: NonAttribute<AssetFaceEntity>;
@PrimaryColumn()
faceId!: string;

View File

@ -1,4 +1,6 @@
import { KyselifyEntity } from 'kysely-typeorm';
import { ActivityEntity } from 'src/entities/activity.entity';
import { AlbumAssetEntity } from 'src/entities/album-asset.entity';
import { AlbumUserEntity } from 'src/entities/album-user.entity';
import { AlbumEntity } from 'src/entities/album.entity';
import { APIKeyEntity } from 'src/entities/api-key.entity';
@ -11,16 +13,20 @@ import { ExifEntity } from 'src/entities/exif.entity';
import { FaceSearchEntity } from 'src/entities/face-search.entity';
import { GeodataPlacesEntity } from 'src/entities/geodata-places.entity';
import { LibraryEntity } from 'src/entities/library.entity';
import { MemoryAssetEntity } from 'src/entities/memory-asset.entity';
import { MemoryEntity } from 'src/entities/memory.entity';
import { MoveEntity } from 'src/entities/move.entity';
import { NaturalEarthCountriesEntity } from 'src/entities/natural-earth-countries.entity';
import { PartnerEntity } from 'src/entities/partner.entity';
import { PersonEntity } from 'src/entities/person.entity';
import { SessionEntity } from 'src/entities/session.entity';
import { SharedLinkAssetEntity } from 'src/entities/shared-link-asset.entity';
import { SharedLinkEntity } from 'src/entities/shared-link.entity';
import { SmartSearchEntity } from 'src/entities/smart-search.entity';
import { StackEntity } from 'src/entities/stack.entity';
import { SystemMetadataEntity } from 'src/entities/system-metadata.entity';
import { TagAssetEntity } from 'src/entities/tag-asset.entity';
import { TagClosureEntity } from 'src/entities/tag-closure.entity';
import { TagEntity } from 'src/entities/tag.entity';
import { UserMetadataEntity } from 'src/entities/user-metadata.entity';
import { UserEntity } from 'src/entities/user.entity';
@ -48,6 +54,8 @@ export const entities = [
SmartSearchEntity,
StackEntity,
SystemMetadataEntity,
TagAssetEntity,
TagClosureEntity,
TagEntity,
UserEntity,
UserMetadataEntity,
@ -55,3 +63,70 @@ export const entities = [
LibraryEntity,
VersionHistoryEntity,
];
export type Activity = KyselifyEntity<ActivityEntity>;
export type Albums = KyselifyEntity<AlbumEntity>;
export type AlbumsAssetsAssets = KyselifyEntity<AlbumAssetEntity>;
export type AlbumsSharedUsersUsers = KyselifyEntity<AlbumUserEntity>;
export type ApiKeys = KyselifyEntity<APIKeyEntity>;
export type AssetFaces = KyselifyEntity<AssetFaceEntity>;
export type AssetFiles = KyselifyEntity<AssetFileEntity>;
export type AssetJobStatus = KyselifyEntity<AssetJobStatusEntity>;
export type Assets = KyselifyEntity<AssetEntity>;
export type AssetStack = KyselifyEntity<StackEntity>;
export type Audit = KyselifyEntity<AuditEntity>;
export type Exif = KyselifyEntity<ExifEntity>;
export type FaceSearch = KyselifyEntity<FaceSearchEntity>;
export type GeodataPlaces = KyselifyEntity<GeodataPlacesEntity>;
export type Libraries = KyselifyEntity<LibraryEntity>;
export type Memories = KyselifyEntity<MemoryEntity>;
export type MemoriesAssetsAssets = KyselifyEntity<MemoryAssetEntity>;
export type MoveHistory = KyselifyEntity<MoveEntity>;
export type NaturalearthCountries = KyselifyEntity<NaturalEarthCountriesEntity>;
export type Partners = KyselifyEntity<PartnerEntity>;
export type Person = KyselifyEntity<PersonEntity>;
export type Sessions = KyselifyEntity<SessionEntity>;
export type SharedLinkAsset = KyselifyEntity<SharedLinkAssetEntity>;
export type SharedLinks = KyselifyEntity<SharedLinkEntity>;
export type SmartSearch = KyselifyEntity<SmartSearchEntity>;
export type SystemMetadata = KyselifyEntity<SystemMetadataEntity>;
export type TagAsset = KyselifyEntity<TagAssetEntity>;
export type Tags = KyselifyEntity<TagEntity>;
export type TagsClosure = KyselifyEntity<TagClosureEntity>;
export type UserMetadata = KyselifyEntity<UserMetadataEntity>;
export type Users = KyselifyEntity<UserEntity>;
export interface DB {
activity: Activity;
albums: Albums;
albums_assets_assets: AlbumsAssetsAssets;
albums_shared_users_users: AlbumsSharedUsersUsers;
api_keys: ApiKeys;
asset_faces: AssetFaces;
asset_files: AssetFiles;
asset_job_status: AssetJobStatus;
asset_stack: AssetStack;
assets: Assets;
audit: Audit;
exif: Exif;
face_search: FaceSearch;
geodata_places: GeodataPlaces;
libraries: Libraries;
memories: Memories;
memories_assets_assets: MemoriesAssetsAssets;
move_history: MoveHistory;
naturalearth_countries: NaturalearthCountries;
partners: Partners;
person: Person;
sessions: Sessions;
shared_link__asset: SharedLinkAsset;
shared_links: SharedLinks;
smart_search: SmartSearch;
system_metadata: SystemMetadata;
tag_asset: TagAsset;
tags: Tags;
tags_closure: TagsClosure;
user_metadata: UserMetadata;
users: Users;
// 'vectors.pg_vector_index_stat': VectorsPgVectorIndexStat;
}

View File

@ -1,3 +1,4 @@
import { Generated, NonAttribute } from 'kysely-typeorm';
import { AssetEntity } from 'src/entities/asset.entity';
import { UserEntity } from 'src/entities/user.entity';
import {
@ -15,17 +16,17 @@ import {
@Entity('libraries')
export class LibraryEntity {
@PrimaryGeneratedColumn('uuid')
id!: string;
id!: Generated<string>;
@Column()
name!: string;
@OneToMany(() => AssetEntity, (asset) => asset.library)
@JoinTable()
assets!: AssetEntity[];
assets!: NonAttribute<AssetEntity[]>;
@ManyToOne(() => UserEntity, { onDelete: 'CASCADE', onUpdate: 'CASCADE', nullable: false })
owner!: UserEntity;
owner!: NonAttribute<UserEntity>;
@Column()
ownerId!: string;
@ -37,10 +38,10 @@ export class LibraryEntity {
exclusionPatterns!: string[];
@CreateDateColumn({ type: 'timestamptz' })
createdAt!: Date;
createdAt!: Generated<Date>;
@UpdateDateColumn({ type: 'timestamptz' })
updatedAt!: Date;
updatedAt!: Generated<Date>;
@DeleteDateColumn({ type: 'timestamptz' })
deletedAt?: Date;

View File

@ -0,0 +1,23 @@
import type { NonAttribute } from 'kysely-typeorm';
import { AssetEntity } from 'src/entities/asset.entity';
import { MemoryEntity } from 'src/entities/memory.entity';
import { Entity, Index, JoinColumn, ManyToOne, PrimaryColumn } from 'typeorm';
@Entity('memories_assets_assets')
export class MemoryAssetEntity {
@PrimaryColumn('uuid')
@Index('IDX_984e5c9ab1f04d34538cd32334')
memoriesId!: string;
@ManyToOne(() => MemoryEntity, { onDelete: 'CASCADE', onUpdate: 'CASCADE' })
@JoinColumn({ name: 'memoriesId' })
memory!: NonAttribute<MemoryEntity>;
@PrimaryColumn('uuid')
@Index('IDX_6942ecf52d75d4273de19d2c16')
assetsId!: string;
@ManyToOne(() => AssetEntity, { onDelete: 'CASCADE', onUpdate: 'CASCADE' })
@JoinColumn({ name: 'assetsId' })
asset!: NonAttribute<AssetEntity>;
}

View File

@ -1,3 +1,4 @@
import { Generated, NonAttribute } from 'kysely-typeorm';
import { AssetEntity } from 'src/entities/asset.entity';
import { UserEntity } from 'src/entities/user.entity';
import { MemoryType } from 'src/enum';
@ -22,19 +23,19 @@ export interface MemoryData {
@Entity('memories')
export class MemoryEntity<T extends MemoryType = MemoryType> {
@PrimaryGeneratedColumn('uuid')
id!: string;
id!: Generated<string>;
@CreateDateColumn({ type: 'timestamptz' })
createdAt!: Date;
createdAt!: Generated<Date>;
@UpdateDateColumn({ type: 'timestamptz' })
updatedAt!: Date;
updatedAt!: Generated<Date>;
@DeleteDateColumn({ type: 'timestamptz' })
deletedAt?: Date;
@ManyToOne(() => UserEntity, { onDelete: 'CASCADE', onUpdate: 'CASCADE', nullable: false })
owner!: UserEntity;
owner!: NonAttribute<UserEntity>;
@Column()
ownerId!: string;
@ -47,7 +48,7 @@ export class MemoryEntity<T extends MemoryType = MemoryType> {
/** unless set to true, will be automatically deleted in the future */
@Column({ default: false })
isSaved!: boolean;
isSaved!: Generated<boolean>;
/** memories are sorted in ascending order by this value */
@Column({ type: 'timestamptz' })
@ -59,5 +60,5 @@ export class MemoryEntity<T extends MemoryType = MemoryType> {
@ManyToMany(() => AssetEntity)
@JoinTable()
assets!: AssetEntity[];
assets!: NonAttribute<AssetEntity[]>;
}

View File

@ -1,3 +1,4 @@
import { Generated } from 'kysely-typeorm';
import { PathType } from 'src/enum';
import { Column, Entity, PrimaryGeneratedColumn, Unique } from 'typeorm';
@ -8,7 +9,7 @@ import { Column, Entity, PrimaryGeneratedColumn, Unique } from 'typeorm';
@Unique('UQ_newPath', ['newPath'])
export class MoveEntity {
@PrimaryGeneratedColumn('uuid')
id!: string;
id!: Generated<string>;
@Column({ type: 'varchar' })
entityId!: string;

View File

@ -1,9 +1,10 @@
import { GeneratedAlways } from 'kysely-typeorm';
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
@Entity('naturalearth_countries', { synchronize: false })
export class NaturalEarthCountriesEntity {
@PrimaryGeneratedColumn('identity', { generatedIdentity: 'ALWAYS' })
id!: number;
id!: GeneratedAlways<number>;
@Column({ type: 'varchar', length: 50 })
admin!: string;
@ -21,7 +22,7 @@ export class NaturalEarthCountriesEntity {
@Entity('naturalearth_countries_tmp', { synchronize: false })
export class NaturalEarthCountriesTempEntity {
@PrimaryGeneratedColumn('identity', { generatedIdentity: 'ALWAYS' })
id!: number;
id!: GeneratedAlways<number>;
@Column({ type: 'varchar', length: 50 })
admin!: string;

View File

@ -1,3 +1,4 @@
import { Generated, NonAttribute } from 'kysely-typeorm';
import { UserEntity } from 'src/entities/user.entity';
import { Column, CreateDateColumn, Entity, JoinColumn, ManyToOne, PrimaryColumn, UpdateDateColumn } from 'typeorm';
@ -11,18 +12,18 @@ export class PartnerEntity {
@ManyToOne(() => UserEntity, { onDelete: 'CASCADE', eager: true })
@JoinColumn({ name: 'sharedById' })
sharedBy!: UserEntity;
sharedBy!: NonAttribute<UserEntity>;
@ManyToOne(() => UserEntity, { onDelete: 'CASCADE', eager: true })
@JoinColumn({ name: 'sharedWithId' })
sharedWith!: UserEntity;
sharedWith!: NonAttribute<UserEntity>;
@CreateDateColumn({ type: 'timestamptz' })
createdAt!: Date;
createdAt!: Generated<Date>;
@UpdateDateColumn({ type: 'timestamptz' })
updatedAt!: Date;
updatedAt!: Generated<Date>;
@Column({ type: 'boolean', default: false })
inTimeline!: boolean;
inTimeline!: Generated<boolean>;
}

View File

@ -1,3 +1,4 @@
import { Generated, NonAttribute } from 'kysely-typeorm';
import { AssetFaceEntity } from 'src/entities/asset-face.entity';
import { UserEntity } from 'src/entities/user.entity';
import {
@ -15,38 +16,38 @@ import {
@Check(`"birthDate" <= CURRENT_DATE`)
export class PersonEntity {
@PrimaryGeneratedColumn('uuid')
id!: string;
id!: Generated<string>;
@CreateDateColumn({ type: 'timestamptz' })
createdAt!: Date;
createdAt!: Generated<Date>;
@UpdateDateColumn({ type: 'timestamptz' })
updatedAt!: Date;
updatedAt!: Generated<Date>;
@Column()
ownerId!: string;
@ManyToOne(() => UserEntity, { onDelete: 'CASCADE', onUpdate: 'CASCADE', nullable: false })
owner!: UserEntity;
owner!: NonAttribute<UserEntity>;
@Column({ default: '' })
name!: string;
name!: Generated<string>;
@Column({ type: 'date', nullable: true })
birthDate!: string | null;
@Column({ default: '' })
thumbnailPath!: string;
thumbnailPath!: Generated<string>;
@Column({ nullable: true })
faceAssetId!: string | null;
@ManyToOne(() => AssetFaceEntity, { onDelete: 'SET NULL', nullable: true })
faceAsset!: AssetFaceEntity | null;
faceAsset!: NonAttribute<AssetFaceEntity | null>;
@OneToMany(() => AssetFaceEntity, (assetFace) => assetFace.person)
faces!: AssetFaceEntity[];
faces!: NonAttribute<AssetFaceEntity[]>;
@Column({ default: false })
isHidden!: boolean;
isHidden!: Generated<boolean>;
}

View File

@ -1,10 +1,11 @@
import { Generated, NonAttribute } from 'kysely-typeorm';
import { UserEntity } from 'src/entities/user.entity';
import { Column, CreateDateColumn, Entity, ManyToOne, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm';
@Entity('sessions')
export class SessionEntity {
@PrimaryGeneratedColumn('uuid')
id!: string;
id!: Generated<string>;
@Column({ select: false })
token!: string;
@ -13,17 +14,17 @@ export class SessionEntity {
userId!: string;
@ManyToOne(() => UserEntity, { onUpdate: 'CASCADE', onDelete: 'CASCADE' })
user!: UserEntity;
user!: NonAttribute<UserEntity>;
@CreateDateColumn({ type: 'timestamptz' })
createdAt!: Date;
createdAt!: Generated<Date>;
@UpdateDateColumn({ type: 'timestamptz' })
updatedAt!: Date;
updatedAt!: Generated<Date>;
@Column({ default: '' })
deviceType!: string;
deviceType!: Generated<string>;
@Column({ default: '' })
deviceOS!: string;
deviceOS!: Generated<string>;
}

View File

@ -0,0 +1,23 @@
import type { NonAttribute } from 'kysely-typeorm';
import { AssetEntity } from 'src/entities/asset.entity';
import { SharedLinkEntity } from 'src/entities/shared-link.entity';
import { Entity, Index, JoinColumn, ManyToOne, PrimaryColumn } from 'typeorm';
@Entity('shared_link__asset')
export class SharedLinkAssetEntity {
@PrimaryColumn('uuid')
@Index('IDX_5b7decce6c8d3db9593d6111a6')
assetsId!: string;
@ManyToOne(() => AssetEntity, { onDelete: 'CASCADE', onUpdate: 'CASCADE' })
@JoinColumn({ name: 'assetsId' })
asset!: NonAttribute<AssetEntity>;
@PrimaryColumn('uuid')
@Index('IDX_c9fab4aa97ffd1b034f3d6581a')
sharedLinksId!: string;
@ManyToOne(() => SharedLinkEntity, { onDelete: 'CASCADE', onUpdate: 'CASCADE' })
@JoinColumn({ name: 'sharedLinksId' })
sharedLink!: NonAttribute<SharedLinkEntity>;
}

View File

@ -1,3 +1,4 @@
import { Generated, NonAttribute } from 'kysely-typeorm';
import { AlbumEntity } from 'src/entities/album.entity';
import { AssetEntity } from 'src/entities/asset.entity';
import { UserEntity } from 'src/entities/user.entity';
@ -17,7 +18,7 @@ import {
@Unique('UQ_sharedlink_key', ['key'])
export class SharedLinkEntity {
@PrimaryGeneratedColumn('uuid')
id!: string;
id!: Generated<string>;
@Column({ type: 'varchar', nullable: true })
description!: string | null;
@ -29,7 +30,7 @@ export class SharedLinkEntity {
userId!: string;
@ManyToOne(() => UserEntity, { onDelete: 'CASCADE', onUpdate: 'CASCADE' })
user!: UserEntity;
user!: NonAttribute<UserEntity>;
@Index('IDX_sharedlink_key')
@Column({ type: 'bytea' })
@ -45,20 +46,20 @@ export class SharedLinkEntity {
expiresAt!: Date | null;
@Column({ type: 'boolean', default: false })
allowUpload!: boolean;
allowUpload!: Generated<boolean>;
@Column({ type: 'boolean', default: true })
allowDownload!: boolean;
allowDownload!: Generated<boolean>;
@Column({ type: 'boolean', default: true })
showExif!: boolean;
showExif!: Generated<boolean>;
@ManyToMany(() => AssetEntity, (asset) => asset.sharedLinks, { onDelete: 'CASCADE', onUpdate: 'CASCADE' })
assets!: AssetEntity[];
assets!: NonAttribute<AssetEntity[]>;
@Index('IDX_sharedlink_albumId')
@ManyToOne(() => AlbumEntity, (album) => album.sharedLinks, { onDelete: 'CASCADE', onUpdate: 'CASCADE' })
album?: AlbumEntity;
album!: NonAttribute<AlbumEntity>;
@Column({ type: 'varchar', nullable: true })
albumId!: string | null;

View File

@ -1,3 +1,4 @@
import { NonAttribute } from 'kysely-typeorm';
import { AssetEntity } from 'src/entities/asset.entity';
import { Column, Entity, Index, JoinColumn, OneToOne, PrimaryColumn } from 'typeorm';
@ -5,7 +6,7 @@ import { Column, Entity, Index, JoinColumn, OneToOne, PrimaryColumn } from 'type
export class SmartSearchEntity {
@OneToOne(() => AssetEntity, { onDelete: 'CASCADE', nullable: true })
@JoinColumn({ name: 'assetId', referencedColumnName: 'id' })
asset?: AssetEntity;
asset!: NonAttribute<AssetEntity>;
@PrimaryColumn()
assetId!: string;

View File

@ -1,3 +1,4 @@
import { Generated, NonAttribute } from 'kysely-typeorm';
import { AssetEntity } from 'src/entities/asset.entity';
import { UserEntity } from 'src/entities/user.entity';
import { Column, Entity, JoinColumn, ManyToOne, OneToMany, OneToOne, PrimaryGeneratedColumn } from 'typeorm';
@ -5,21 +6,21 @@ import { Column, Entity, JoinColumn, ManyToOne, OneToMany, OneToOne, PrimaryGene
@Entity('asset_stack')
export class StackEntity {
@PrimaryGeneratedColumn('uuid')
id!: string;
id!: Generated<string>;
@ManyToOne(() => UserEntity, { onDelete: 'CASCADE', onUpdate: 'CASCADE' })
owner!: UserEntity;
owner!: NonAttribute<UserEntity>;
@Column()
ownerId!: string;
@OneToMany(() => AssetEntity, (asset) => asset.stack)
assets!: AssetEntity[];
assets!: NonAttribute<AssetEntity[]>;
@OneToOne(() => AssetEntity)
@JoinColumn()
//TODO: Add constraint to ensure primary asset exists in the assets array
primaryAsset!: AssetEntity;
primaryAsset!: NonAttribute<AssetEntity>;
@Column({ nullable: false })
primaryAssetId!: string;

View File

@ -0,0 +1,24 @@
import { NonAttribute } from 'kysely-typeorm';
import { AssetEntity } from 'src/entities/asset.entity';
import { TagEntity } from 'src/entities/tag.entity';
import { Entity, Index, JoinColumn, ManyToOne, PrimaryColumn } from 'typeorm';
@Entity('tag_asset')
@Index('IDX_tag_asset_assetsId_tagsId', ['assetsId', 'tagsId'])
export class TagAssetEntity {
@Index('IDX_f8e8a9e893cb5c54907f1b798e')
@PrimaryColumn('uuid')
assetsId!: string;
@ManyToOne(() => AssetEntity, { onDelete: 'CASCADE', onUpdate: 'CASCADE' })
@JoinColumn({ name: 'assetsId' })
asset!: NonAttribute<AssetEntity>;
@Index('IDX_e99f31ea4cdf3a2c35c7287eb4')
@PrimaryColumn('uuid')
tagsId!: string;
@ManyToOne(() => TagEntity, { onDelete: 'CASCADE', onUpdate: 'CASCADE' })
@JoinColumn({ name: 'tagsId' })
tag!: NonAttribute<TagEntity>;
}

View File

@ -0,0 +1,21 @@
import { TagEntity } from 'src/entities/tag.entity';
import { Entity, Index, JoinColumn, ManyToOne, PrimaryColumn } from 'typeorm';
@Entity('tags_closure')
export class TagClosureEntity {
@Index('IDX_15fbcbc67663c6bfc07b354c22')
@PrimaryColumn('uuid')
id_ancestor!: string;
@ManyToOne(() => TagEntity, { onDelete: 'CASCADE' })
@JoinColumn({ name: 'id_ancestor' })
ancestor!: TagEntity;
@Index('IDX_b1a2a7ed45c29179b5ad51548a')
@PrimaryColumn('uuid')
id_descendant!: string;
@ManyToOne(() => TagEntity, { onDelete: 'CASCADE' })
@JoinColumn({ name: 'id_descendant' })
descendant!: TagEntity;
}

View File

@ -1,3 +1,4 @@
import { Generated, NonAttribute } from 'kysely-typeorm';
import { AssetEntity } from 'src/entities/asset.entity';
import { UserEntity } from 'src/entities/user.entity';
import {
@ -19,35 +20,35 @@ import {
@Tree('closure-table')
export class TagEntity {
@PrimaryGeneratedColumn('uuid')
id!: string;
id!: Generated<string>;
@Column()
value!: string;
@CreateDateColumn({ type: 'timestamptz' })
createdAt!: Date;
createdAt!: Generated<Date>;
@UpdateDateColumn({ type: 'timestamptz' })
updatedAt!: Date;
updatedAt!: Generated<Date>;
@Column({ type: 'varchar', nullable: true, default: null })
color!: string | null;
color!: Generated<string> | null;
@Column({ nullable: true })
parentId?: string;
@TreeParent({ onDelete: 'CASCADE' })
parent?: TagEntity;
parent!: NonAttribute<TagEntity>;
@TreeChildren()
children?: TagEntity[];
@ManyToOne(() => UserEntity, (user) => user.tags, { onUpdate: 'CASCADE', onDelete: 'CASCADE' })
user?: UserEntity;
user!: NonAttribute<UserEntity>;
@Column()
userId!: string;
@ManyToMany(() => AssetEntity, (asset) => asset.tags, { onUpdate: 'CASCADE', onDelete: 'CASCADE' })
assets?: AssetEntity[];
assets!: NonAttribute<AssetEntity[]>;
}

View File

@ -1,3 +1,4 @@
import { NonAttribute } from 'kysely-typeorm';
import { UserEntity } from 'src/entities/user.entity';
import { UserAvatarColor, UserMetadataKey } from 'src/enum';
import { HumanReadableSize } from 'src/utils/bytes';
@ -9,7 +10,7 @@ export class UserMetadataEntity<T extends keyof UserMetadata = UserMetadataKey>
userId!: string;
@ManyToOne(() => UserEntity, (user) => user.metadata, { onUpdate: 'CASCADE', onDelete: 'CASCADE' })
user!: UserEntity;
user!: NonAttribute<UserEntity>;
@PrimaryColumn({ type: 'varchar' })
key!: T;

View File

@ -1,3 +1,4 @@
import { Generated, NonAttribute } from 'kysely-typeorm';
import { AssetEntity } from 'src/entities/asset.entity';
import { TagEntity } from 'src/entities/tag.entity';
import { UserMetadataEntity } from 'src/entities/user-metadata.entity';
@ -15,59 +16,59 @@ import {
@Entity('users')
export class UserEntity {
@PrimaryGeneratedColumn('uuid')
id!: string;
id!: Generated<string>;
@Column({ default: '' })
name!: string;
name!: Generated<string>;
@Column({ default: false })
isAdmin!: boolean;
isAdmin!: Generated<boolean>;
@Column({ unique: true })
email!: string;
@Column({ type: 'varchar', unique: true, default: null })
storageLabel!: string | null;
storageLabel!: Generated<string> | null;
@Column({ default: '', select: false })
password?: string;
password?: Generated<string>;
@Column({ default: '' })
oauthId!: string;
oauthId!: Generated<string>;
@Column({ default: '' })
profileImagePath!: string;
profileImagePath!: Generated<string>;
@Column({ default: true })
shouldChangePassword!: boolean;
shouldChangePassword!: Generated<boolean>;
@CreateDateColumn({ type: 'timestamptz' })
createdAt!: Date;
createdAt!: Generated<Date>;
@DeleteDateColumn({ type: 'timestamptz' })
deletedAt!: Date | null;
@Column({ type: 'varchar', default: UserStatus.ACTIVE })
status!: UserStatus;
status!: Generated<UserStatus>;
@UpdateDateColumn({ type: 'timestamptz' })
updatedAt!: Date;
updatedAt!: Generated<Date>;
@OneToMany(() => TagEntity, (tag) => tag.user)
tags!: TagEntity[];
tags!: NonAttribute<TagEntity[]>;
@OneToMany(() => AssetEntity, (asset) => asset.owner)
assets!: AssetEntity[];
assets!: NonAttribute<AssetEntity[]>;
@Column({ type: 'bigint', nullable: true })
quotaSizeInBytes!: number | null;
@Column({ type: 'bigint', default: 0 })
quotaUsageInBytes!: number;
quotaUsageInBytes!: Generated<number>;
@OneToMany(() => UserMetadataEntity, (metadata) => metadata.user)
metadata!: UserMetadataEntity[];
metadata!: NonAttribute<UserMetadataEntity[]>;
@Column({ type: 'timestamptz', default: () => 'CURRENT_TIMESTAMP' })
profileChangedAt!: Date;
profileChangedAt!: Generated<Date>;
}

View File

@ -1,12 +1,13 @@
import { Generated } from 'kysely-typeorm';
import { Column, CreateDateColumn, Entity, PrimaryGeneratedColumn } from 'typeorm';
@Entity('version_history')
export class VersionHistoryEntity {
@PrimaryGeneratedColumn('uuid')
id!: string;
id!: Generated<string>;
@CreateDateColumn({ type: 'timestamptz' })
createdAt!: Date;
createdAt!: Generated<Date>;
@Column()
version!: string;

View File

@ -1,5 +1,5 @@
import { Insertable, Updateable } from 'kysely';
import { AssetFiles, AssetJobStatus, Assets, Exif } from 'src/db';
import { AssetFiles, AssetJobStatus, Assets, Exif } from 'src/entities';
import { AssetEntity } from 'src/entities/asset.entity';
import { AssetFileType, AssetOrder, AssetStatus, AssetType } from 'src/enum';
import { AssetSearchOptions, SearchExploreItem } from 'src/interfaces/search.interface';

View File

@ -4,8 +4,8 @@ import { Insertable, Kysely, Updateable, sql } from 'kysely';
import { isEmpty, isUndefined, omitBy } from 'lodash';
import { InjectKysely } from 'nestjs-kysely';
import { ASSET_FILE_CONFLICT_KEYS, EXIF_CONFLICT_KEYS, JOB_STATUS_CONFLICT_KEYS } from 'src/constants';
import { AssetFiles, AssetJobStatus, Assets, DB, Exif } from 'src/db';
import { Chunked, ChunkedArray, DummyValue, GenerateSql } from 'src/decorators';
import { AssetFiles, AssetJobStatus, Assets, DB, Exif } from 'src/entities';
import {
AssetEntity,
hasPeople,

View File

@ -2,8 +2,8 @@ import { Inject, Injectable } from '@nestjs/common';
import { Kysely, OrderByDirectionExpression, sql } from 'kysely';
import { InjectKysely } from 'nestjs-kysely';
import { randomUUID } from 'node:crypto';
import { DB } from 'src/db';
import { DummyValue, GenerateSql } from 'src/decorators';
import { DB } from 'src/entities';
import { AssetEntity, searchAssetBuilder } from 'src/entities/asset.entity';
import { GeodataPlacesEntity } from 'src/entities/geodata-places.entity';
import { AssetType } from 'src/enum';
@ -221,7 +221,7 @@ export class SearchRepository implements ISearchRepository {
.where('assets.ownerId', '=', anyUuid(userIds))
.where('assets.isVisible', '=', true)
.where('assets.isArchived', '=', false)
.where('assets.type', '=', 'IMAGE')
.where('assets.type', '=', AssetType.IMAGE)
.where('assets.deletedAt', 'is', null)
.orderBy('city')
.limit(1);
@ -238,7 +238,7 @@ export class SearchRepository implements ISearchRepository {
.where('assets.ownerId', '=', anyUuid(userIds))
.where('assets.isVisible', '=', true)
.where('assets.isArchived', '=', false)
.where('assets.type', '=', 'IMAGE')
.where('assets.type', '=', AssetType.IMAGE)
.where('assets.deletedAt', 'is', null)
.whereRef('exif.city', '>', 'cte.city')
.orderBy('city')

View File

@ -1,7 +1,7 @@
import { Kysely } from 'kysely';
import { InjectKysely } from 'nestjs-kysely';
import { DB } from 'src/db';
import { DummyValue, GenerateSql } from 'src/decorators';
import { DB } from 'src/entities';
import { AssetEntity, withExif } from 'src/entities/asset.entity';
import { IViewRepository } from 'src/interfaces/view.interface';
import { asUuid } from 'src/utils/database';

View File

@ -8,8 +8,8 @@ import { constants } from 'node:fs/promises';
import path from 'node:path';
import { SystemConfig } from 'src/config';
import { StorageCore } from 'src/cores/storage.core';
import { Exif } from 'src/db';
import { OnEvent, OnJob } from 'src/decorators';
import { Exif } from 'src/entities';
import { AssetFaceEntity } from 'src/entities/asset-face.entity';
import { AssetEntity } from 'src/entities/asset.entity';
import { PersonEntity } from 'src/entities/person.entity';

View File

@ -1,6 +1,6 @@
import { Expression, RawBuilder, sql, ValueExpression } from 'kysely';
import { InsertObject } from 'node_modules/kysely/dist/cjs';
import { DB } from 'src/db';
import { DB } from 'src/entities';
import { Between, DataSource, LessThanOrEqual, MoreThanOrEqual } from 'typeorm';
/**