From 5ebb8e1a33af4913d3498bbb756f1cde5080230e Mon Sep 17 00:00:00 2001 From: mertalev <101130780+mertalev@users.noreply.github.com> Date: Thu, 2 Jan 2025 18:20:13 -0500 Subject: [PATCH] use typeorm entities for kysely types --- server/package-lock.json | 266 +---------- server/package.json | 2 +- server/src/db.d.ts | 439 ------------------ server/src/entities/activity.entity.ts | 17 +- server/src/entities/album-asset.entity.ts | 23 + server/src/entities/album-user.entity.ts | 7 +- server/src/entities/album.entity.ts | 25 +- server/src/entities/api-key.entity.ts | 9 +- server/src/entities/asset-face.entity.ts | 23 +- server/src/entities/asset-files.entity.ts | 9 +- .../src/entities/asset-job-status.entity.ts | 3 +- server/src/entities/asset.entity.ts | 47 +- server/src/entities/audit.entity.ts | 5 +- server/src/entities/exif.entity.ts | 5 +- server/src/entities/face-search.entity.ts | 3 +- server/src/entities/index.ts | 75 +++ server/src/entities/library.entity.ts | 11 +- server/src/entities/memory-asset.entity.ts | 23 + server/src/entities/memory.entity.ts | 13 +- server/src/entities/move.entity.ts | 3 +- .../natural-earth-countries.entity.ts | 5 +- server/src/entities/partner.entity.ts | 11 +- server/src/entities/person.entity.ts | 19 +- server/src/entities/session.entity.ts | 13 +- .../src/entities/shared-link-asset.entity.ts | 23 + server/src/entities/shared-link.entity.ts | 15 +- server/src/entities/smart-search.entity.ts | 3 +- server/src/entities/stack.entity.ts | 9 +- server/src/entities/tag-asset.entity.ts | 24 + server/src/entities/tag-closure.entity.ts | 21 + server/src/entities/tag.entity.ts | 15 +- server/src/entities/user-metadata.entity.ts | 3 +- server/src/entities/user.entity.ts | 33 +- server/src/entities/version-history.entity.ts | 5 +- server/src/interfaces/asset.interface.ts | 2 +- server/src/repositories/asset.repository.ts | 2 +- server/src/repositories/search.repository.ts | 6 +- server/src/repositories/view-repository.ts | 2 +- server/src/services/metadata.service.ts | 2 +- server/src/utils/database.ts | 2 +- 40 files changed, 377 insertions(+), 846 deletions(-) delete mode 100644 server/src/db.d.ts create mode 100644 server/src/entities/album-asset.entity.ts create mode 100644 server/src/entities/memory-asset.entity.ts create mode 100644 server/src/entities/shared-link-asset.entity.ts create mode 100644 server/src/entities/tag-asset.entity.ts create mode 100644 server/src/entities/tag-closure.entity.ts diff --git a/server/package-lock.json b/server/package-lock.json index 3291c690db..6fecaf3747 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -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", diff --git a/server/package.json b/server/package.json index 9ecedb156f..a5528ce042 100644 --- a/server/package.json +++ b/server/package.json @@ -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", diff --git a/server/src/db.d.ts b/server/src/db.d.ts deleted file mode 100644 index 454c5176de..0000000000 --- a/server/src/db.d.ts +++ /dev/null @@ -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 = ArrayTypeImpl extends (infer U)[] ? U[] : ArrayTypeImpl; - -export type ArrayTypeImpl = T extends ColumnType ? ColumnType : T[]; - -export type AssetsStatusEnum = 'active' | 'deleted' | 'trashed'; - -export type Generated = - T extends ColumnType ? ColumnType : ColumnType; - -export type Int8 = ColumnType; - -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; - -export interface Activity { - albumId: string; - assetId: string | null; - comment: string | null; - createdAt: Generated; - id: Generated; - isLiked: Generated; - updatedAt: Generated; - userId: string; -} - -export interface Albums { - albumName: Generated; - /** - * Asset ID to be used as thumbnail - */ - albumThumbnailAssetId: string | null; - createdAt: Generated; - deletedAt: Timestamp | null; - description: Generated; - id: Generated; - isActivityEnabled: Generated; - order: Generated; - ownerId: string; - updatedAt: Generated; -} - -export interface AlbumsAssetsAssets { - albumsId: string; - assetsId: string; -} - -export interface AlbumsSharedUsersUsers { - albumsId: string; - role: Generated; - usersId: string; -} - -export interface ApiKeys { - createdAt: Generated; - id: Generated; - key: string; - name: string; - permissions: string[]; - updatedAt: Generated; - userId: string; -} - -export interface AssetFaces { - assetId: string; - boundingBoxX1: Generated; - boundingBoxX2: Generated; - boundingBoxY1: Generated; - boundingBoxY2: Generated; - id: Generated; - imageHeight: Generated; - imageWidth: Generated; - personId: string | null; - sourceType: Generated; -} - -export interface AssetFiles { - assetId: string; - createdAt: Generated; - id: Generated; - path: string; - type: string; - updatedAt: Generated; -} - -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; - deletedAt: Timestamp | null; - deviceAssetId: string; - deviceId: string; - duplicateId: string | null; - duration: string | null; - encodedVideoPath: Generated; - fileCreatedAt: Timestamp; - fileModifiedAt: Timestamp; - id: Generated; - isArchived: Generated; - isExternal: Generated; - isFavorite: Generated; - isOffline: Generated; - isVisible: Generated; - libraryId: string | null; - livePhotoVideoId: string | null; - localDateTime: Timestamp; - originalFileName: string; - originalPath: string; - ownerId: string; - sidecarPath: string | null; - stackId: string | null; - status: Generated; - thumbhash: Buffer | null; - type: string; - updatedAt: Generated; -} - -export interface AssetStack { - id: Generated; - ownerId: string; - primaryAssetId: string; -} - -export interface Audit { - action: string; - createdAt: Generated; - entityId: string; - entityType: string; - id: Generated; - 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; - 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; - id: number; - latitude: number; - longitude: number; - modificationDate: Timestamp; - name: string; -} - -export interface Libraries { - createdAt: Generated; - deletedAt: Timestamp | null; - exclusionPatterns: string[]; - id: Generated; - importPaths: string[]; - name: string; - ownerId: string; - refreshedAt: Timestamp | null; - updatedAt: Generated; -} - -export interface Memories { - createdAt: Generated; - data: Json; - deletedAt: Timestamp | null; - id: Generated; - isSaved: Generated; - memoryAt: Timestamp; - ownerId: string; - seenAt: Timestamp | null; - type: string; - updatedAt: Generated; -} - -export interface MemoriesAssetsAssets { - assetsId: string; - memoriesId: string; -} - -export interface Migrations { - id: Generated; - name: string; - timestamp: Int8; -} - -export interface MoveHistory { - entityId: string; - id: Generated; - newPath: string; - oldPath: string; - pathType: string; -} - -export interface NaturalearthCountries { - admin: string; - admin_a3: string; - coordinates: string; - id: Generated; - type: string; -} - -export interface Partners { - createdAt: Generated; - inTimeline: Generated; - sharedById: string; - sharedWithId: string; - updatedAt: Generated; -} - -export interface Person { - birthDate: Timestamp | null; - createdAt: Generated; - faceAssetId: string | null; - id: Generated; - isHidden: Generated; - name: Generated; - ownerId: string; - thumbnailPath: Generated; - updatedAt: Generated; -} - -export interface Sessions { - createdAt: Generated; - deviceOS: Generated; - deviceType: Generated; - id: Generated; - token: string; - updatedAt: Generated; - userId: string; -} - -export interface SharedLinkAsset { - assetsId: string; - sharedLinksId: string; -} - -export interface SharedLinks { - albumId: string | null; - allowDownload: Generated; - allowUpload: Generated; - createdAt: Generated; - description: string | null; - expiresAt: Timestamp | null; - id: Generated; - key: Buffer; - password: string | null; - showExif: Generated; - type: string; - userId: string; -} - -export interface SmartInfo { - assetId: string; - objects: string[] | null; - smartInfoTextSearchableColumn: Generated; - tags: string[] | null; -} - -export interface SmartSearch { - assetId: string; - embedding: string; -} - -export interface SocketIoAttachments { - created_at: Generated; - id: Generated; - 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; - id: Generated; - parentId: string | null; - updatedAt: Generated; - 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; - deletedAt: Timestamp | null; - email: string; - id: Generated; - isAdmin: Generated; - name: Generated; - oauthId: Generated; - password: Generated; - profileChangedAt: Generated; - profileImagePath: Generated; - quotaSizeInBytes: Int8 | null; - quotaUsageInBytes: Generated; - shouldChangePassword: Generated; - status: Generated; - storageLabel: string | null; - updatedAt: Generated; -} - -export interface VectorsPgVectorIndexStat { - idx_growing: ArrayType | null; - idx_indexing: boolean | null; - idx_options: string | null; - idx_sealed: ArrayType | 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; -} diff --git a/server/src/entities/activity.entity.ts b/server/src/entities/activity.entity.ts index 8de76ac894..892b66b956 100644 --- a/server/src/entities/activity.entity.ts +++ b/server/src/entities/activity.entity.ts @@ -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; @CreateDateColumn({ type: 'timestamptz' }) - createdAt!: Date; + createdAt!: Generated; @UpdateDateColumn({ type: 'timestamptz' }) - updatedAt!: Date; + updatedAt!: Generated; @Column() albumId!: string; @@ -35,17 +36,17 @@ export class ActivityEntity { assetId!: string | null; @Column({ type: 'text', default: null }) - comment!: string | null; + comment!: Generated | null; @Column({ type: 'boolean', default: false }) - isLiked!: boolean; + isLiked!: Generated; @ManyToOne(() => AssetEntity, { onDelete: 'CASCADE', onUpdate: 'CASCADE', nullable: true }) - asset!: AssetEntity | null; + asset!: NonAttribute; @ManyToOne(() => UserEntity, { onDelete: 'CASCADE', onUpdate: 'CASCADE' }) - user!: UserEntity; + user!: NonAttribute; @ManyToOne(() => AlbumEntity, { onDelete: 'CASCADE', onUpdate: 'CASCADE' }) - album!: AlbumEntity; + album!: NonAttribute; } diff --git a/server/src/entities/album-asset.entity.ts b/server/src/entities/album-asset.entity.ts new file mode 100644 index 0000000000..ecc5e52613 --- /dev/null +++ b/server/src/entities/album-asset.entity.ts @@ -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; + + @PrimaryColumn('uuid') + @Index('IDX_4bd1303d199f4e72ccdf998c62') + assetsId!: string; + + @ManyToOne(() => AssetEntity, { onDelete: 'CASCADE', onUpdate: 'CASCADE' }) + @JoinColumn({ name: 'assetsId' }) + asset!: NonAttribute; +} diff --git a/server/src/entities/album-user.entity.ts b/server/src/entities/album-user.entity.ts index e75b3cd43e..a815172083 100644 --- a/server/src/entities/album-user.entity.ts +++ b/server/src/entities/album-user.entity.ts @@ -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; @JoinColumn({ name: 'usersId' }) @ManyToOne(() => UserEntity, { onDelete: 'CASCADE', onUpdate: 'CASCADE', nullable: false }) - user!: UserEntity; + user!: NonAttribute; @Column({ type: 'varchar', default: AlbumUserRole.EDITOR }) - role!: AlbumUserRole; + role!: Generated; } diff --git a/server/src/entities/album.entity.ts b/server/src/entities/album.entity.ts index 5aec5a0f47..330b69359f 100644 --- a/server/src/entities/album.entity.ts +++ b/server/src/entities/album.entity.ts @@ -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; @ManyToOne(() => UserEntity, { onDelete: 'CASCADE', onUpdate: 'CASCADE', nullable: false }) - owner!: UserEntity; + owner!: NonAttribute; @Column() ownerId!: string; @Column({ default: 'Untitled Album' }) - albumName!: string; + albumName!: Generated; @Column({ type: 'text', default: '' }) - description!: string; + description!: Generated; @CreateDateColumn({ type: 'timestamptz' }) - createdAt!: Date; + createdAt!: Generated; @UpdateDateColumn({ type: 'timestamptz' }) - updatedAt!: Date; + updatedAt!: Generated; @DeleteDateColumn({ type: 'timestamptz' }) deletedAt!: Date | null; @ManyToOne(() => AssetEntity, { nullable: true, onDelete: 'SET NULL', onUpdate: 'CASCADE' }) - albumThumbnailAsset!: AssetEntity | null; + albumThumbnailAsset!: NonAttribute; @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; @ManyToMany(() => AssetEntity, (asset) => asset.albums) @JoinTable({ synchronize: false }) - assets!: AssetEntity[]; + assets!: NonAttribute; @OneToMany(() => SharedLinkEntity, (link) => link.album) - sharedLinks!: SharedLinkEntity[]; + sharedLinks!: NonAttribute; @Column({ default: true }) - isActivityEnabled!: boolean; + isActivityEnabled!: Generated; @Column({ type: 'varchar', default: AssetOrder.DESC }) - order!: AssetOrder; + order!: Generated; } diff --git a/server/src/entities/api-key.entity.ts b/server/src/entities/api-key.entity.ts index 998ee4f8ef..cb2f917dd9 100644 --- a/server/src/entities/api-key.entity.ts +++ b/server/src/entities/api-key.entity.ts @@ -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; @Column() name!: string; @@ -14,7 +15,7 @@ export class APIKeyEntity { key?: string; @ManyToOne(() => UserEntity, { onUpdate: 'CASCADE', onDelete: 'CASCADE' }) - user?: UserEntity; + user!: NonAttribute; @Column() userId!: string; @@ -23,8 +24,8 @@ export class APIKeyEntity { permissions!: Permission[]; @CreateDateColumn({ type: 'timestamptz' }) - createdAt!: Date; + createdAt!: Generated; @UpdateDateColumn({ type: 'timestamptz' }) - updatedAt!: Date; + updatedAt!: Generated; } diff --git a/server/src/entities/asset-face.entity.ts b/server/src/entities/asset-face.entity.ts index 3a4e916cba..61a9fee412 100644 --- a/server/src/entities/asset-face.entity.ts +++ b/server/src/entities/asset-face.entity.ts @@ -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; @Column() assetId!: string; @@ -18,36 +19,36 @@ export class AssetFaceEntity { personId!: string | null; @OneToOne(() => FaceSearchEntity, (faceSearchEntity) => faceSearchEntity.face, { cascade: ['insert'] }) - faceSearch?: FaceSearchEntity; + faceSearch!: NonAttribute; @Column({ default: 0, type: 'int' }) - imageWidth!: number; + imageWidth!: Generated; @Column({ default: 0, type: 'int' }) - imageHeight!: number; + imageHeight!: Generated; @Column({ default: 0, type: 'int' }) - boundingBoxX1!: number; + boundingBoxX1!: Generated; @Column({ default: 0, type: 'int' }) - boundingBoxY1!: number; + boundingBoxY1!: Generated; @Column({ default: 0, type: 'int' }) - boundingBoxX2!: number; + boundingBoxX2!: Generated; @Column({ default: 0, type: 'int' }) - boundingBoxY2!: number; + boundingBoxY2!: Generated; @Column({ default: SourceType.MACHINE_LEARNING, type: 'enum', enum: SourceType }) - sourceType!: SourceType; + sourceType!: Generated; @ManyToOne(() => AssetEntity, (asset) => asset.faces, { onDelete: 'CASCADE', onUpdate: 'CASCADE' }) - asset!: AssetEntity; + asset!: NonAttribute; @ManyToOne(() => PersonEntity, (person) => person.faces, { onDelete: 'SET NULL', onUpdate: 'CASCADE', nullable: true, }) - person!: PersonEntity | null; + person!: NonAttribute; } diff --git a/server/src/entities/asset-files.entity.ts b/server/src/entities/asset-files.entity.ts index a8a6ddfee1..4ff7960551 100644 --- a/server/src/entities/asset-files.entity.ts +++ b/server/src/entities/asset-files.entity.ts @@ -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; @Index('IDX_asset_files_assetId') @Column() assetId!: string; @ManyToOne(() => AssetEntity, { onDelete: 'CASCADE', onUpdate: 'CASCADE' }) - asset?: AssetEntity; + asset!: NonAttribute; @CreateDateColumn({ type: 'timestamptz' }) - createdAt!: Date; + createdAt!: Generated; @UpdateDateColumn({ type: 'timestamptz' }) - updatedAt!: Date; + updatedAt!: Generated; @Column() type!: AssetFileType; diff --git a/server/src/entities/asset-job-status.entity.ts b/server/src/entities/asset-job-status.entity.ts index 353055df43..34e13f9a05 100644 --- a/server/src/entities/asset-job-status.entity.ts +++ b/server/src/entities/asset-job-status.entity.ts @@ -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; @PrimaryColumn() assetId!: string; diff --git a/server/src/entities/asset.entity.ts b/server/src/entities/asset.entity.ts index 7da3b9457c..8b26e7b587 100644 --- a/server/src/entities/asset.entity.ts +++ b/server/src/entities/asset.entity.ts @@ -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; @Column() deviceAssetId!: string; @ManyToOne(() => UserEntity, { onDelete: 'CASCADE', onUpdate: 'CASCADE', nullable: false }) - owner!: UserEntity; + owner!: NonAttribute; @Column() ownerId!: string; @ManyToOne(() => LibraryEntity, { onDelete: 'CASCADE', onUpdate: 'CASCADE' }) - library?: LibraryEntity | null; + library!: NonAttribute; @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; @Column() originalPath!: string; @OneToMany(() => AssetFileEntity, (assetFile) => assetFile.asset) - files!: AssetFileEntity[]; + files!: NonAttribute; @Column({ type: 'bytea', nullable: true }) thumbhash!: Buffer | null; @Column({ type: 'varchar', nullable: true, default: '' }) - encodedVideoPath!: string | null; + encodedVideoPath!: Generated | null; @CreateDateColumn({ type: 'timestamptz' }) - createdAt!: Date; + createdAt!: Generated; @UpdateDateColumn({ type: 'timestamptz' }) - updatedAt!: Date; + updatedAt!: Generated; @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; @Column({ type: 'boolean', default: false }) - isArchived!: boolean; + isArchived!: Generated; @Column({ type: 'boolean', default: false }) - isExternal!: boolean; + isExternal!: Generated; @Column({ type: 'boolean', default: false }) - isOffline!: boolean; + isOffline!: Generated; @Column({ type: 'bytea' }) @Index() @@ -128,11 +129,11 @@ export class AssetEntity { duration!: string | null; @Column({ type: 'boolean', default: true }) - isVisible!: boolean; + isVisible!: Generated; @ManyToOne(() => AssetEntity, { nullable: true, onUpdate: 'CASCADE', onDelete: 'SET NULL' }) @JoinColumn() - livePhotoVideo!: AssetEntity | null; + livePhotoVideo!: NonAttribute; @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; @OneToOne(() => SmartSearchEntity, (smartSearchEntity) => smartSearchEntity.asset) - smartSearch?: SmartSearchEntity; + smartSearch!: NonAttribute; @ManyToMany(() => TagEntity, (tag) => tag.assets, { cascade: true }) @JoinTable({ name: 'tag_asset', synchronize: false }) - tags!: TagEntity[]; + tags!: NonAttribute; @ManyToMany(() => SharedLinkEntity, (link) => link.assets, { cascade: true }) @JoinTable({ name: 'shared_link__asset' }) - sharedLinks!: SharedLinkEntity[]; + sharedLinks!: NonAttribute; @ManyToMany(() => AlbumEntity, (album) => album.assets, { onDelete: 'CASCADE', onUpdate: 'CASCADE' }) - albums?: AlbumEntity[]; + albums!: NonAttribute; @OneToMany(() => AssetFaceEntity, (assetFace) => assetFace.asset) - faces!: AssetFaceEntity[]; + faces!: NonAttribute; @Column({ nullable: true }) stackId?: string | null; @ManyToOne(() => StackEntity, { nullable: true, onDelete: 'SET NULL', onUpdate: 'CASCADE' }) @JoinColumn() - stack?: StackEntity | null; + stack!: NonAttribute; @OneToOne(() => AssetJobStatusEntity, (jobStatus) => jobStatus.asset, { nullable: true }) - jobStatus?: AssetJobStatusEntity; + jobStatus!: NonAttribute; @Index('IDX_assets_duplicateId') @Column({ type: 'uuid', nullable: true }) diff --git a/server/src/entities/audit.entity.ts b/server/src/entities/audit.entity.ts index 7f51e17585..6520bda989 100644 --- a/server/src/entities/audit.entity.ts +++ b/server/src/entities/audit.entity.ts @@ -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; @Column() entityType!: EntityType; @@ -20,5 +21,5 @@ export class AuditEntity { ownerId!: string; @CreateDateColumn({ type: 'timestamptz' }) - createdAt!: Date; + createdAt!: Generated; } diff --git a/server/src/entities/exif.entity.ts b/server/src/entities/exif.entity.ts index c9c29d732a..45c01409e7 100644 --- a/server/src/entities/exif.entity.ts +++ b/server/src/entities/exif.entity.ts @@ -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; @PrimaryColumn() assetId!: string; /* General info */ @Column({ type: 'text', default: '' }) - description!: string; // or caption + description!: Generated; // or caption @Column({ type: 'integer', nullable: true }) exifImageWidth!: number | null; diff --git a/server/src/entities/face-search.entity.ts b/server/src/entities/face-search.entity.ts index 2887453862..50d8ed85cd 100644 --- a/server/src/entities/face-search.entity.ts +++ b/server/src/entities/face-search.entity.ts @@ -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; @PrimaryColumn() faceId!: string; diff --git a/server/src/entities/index.ts b/server/src/entities/index.ts index 75e92038ac..f95c499025 100644 --- a/server/src/entities/index.ts +++ b/server/src/entities/index.ts @@ -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; +export type Albums = KyselifyEntity; +export type AlbumsAssetsAssets = KyselifyEntity; +export type AlbumsSharedUsersUsers = KyselifyEntity; +export type ApiKeys = KyselifyEntity; +export type AssetFaces = KyselifyEntity; +export type AssetFiles = KyselifyEntity; +export type AssetJobStatus = KyselifyEntity; +export type Assets = KyselifyEntity; +export type AssetStack = KyselifyEntity; +export type Audit = KyselifyEntity; +export type Exif = KyselifyEntity; +export type FaceSearch = KyselifyEntity; +export type GeodataPlaces = KyselifyEntity; +export type Libraries = KyselifyEntity; +export type Memories = KyselifyEntity; +export type MemoriesAssetsAssets = KyselifyEntity; +export type MoveHistory = KyselifyEntity; +export type NaturalearthCountries = KyselifyEntity; +export type Partners = KyselifyEntity; +export type Person = KyselifyEntity; +export type Sessions = KyselifyEntity; +export type SharedLinkAsset = KyselifyEntity; +export type SharedLinks = KyselifyEntity; +export type SmartSearch = KyselifyEntity; +export type SystemMetadata = KyselifyEntity; +export type TagAsset = KyselifyEntity; +export type Tags = KyselifyEntity; +export type TagsClosure = KyselifyEntity; +export type UserMetadata = KyselifyEntity; +export type Users = KyselifyEntity; + +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; +} diff --git a/server/src/entities/library.entity.ts b/server/src/entities/library.entity.ts index a6053e4213..707641a53b 100644 --- a/server/src/entities/library.entity.ts +++ b/server/src/entities/library.entity.ts @@ -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; @Column() name!: string; @OneToMany(() => AssetEntity, (asset) => asset.library) @JoinTable() - assets!: AssetEntity[]; + assets!: NonAttribute; @ManyToOne(() => UserEntity, { onDelete: 'CASCADE', onUpdate: 'CASCADE', nullable: false }) - owner!: UserEntity; + owner!: NonAttribute; @Column() ownerId!: string; @@ -37,10 +38,10 @@ export class LibraryEntity { exclusionPatterns!: string[]; @CreateDateColumn({ type: 'timestamptz' }) - createdAt!: Date; + createdAt!: Generated; @UpdateDateColumn({ type: 'timestamptz' }) - updatedAt!: Date; + updatedAt!: Generated; @DeleteDateColumn({ type: 'timestamptz' }) deletedAt?: Date; diff --git a/server/src/entities/memory-asset.entity.ts b/server/src/entities/memory-asset.entity.ts new file mode 100644 index 0000000000..d278c8738a --- /dev/null +++ b/server/src/entities/memory-asset.entity.ts @@ -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; + + @PrimaryColumn('uuid') + @Index('IDX_6942ecf52d75d4273de19d2c16') + assetsId!: string; + + @ManyToOne(() => AssetEntity, { onDelete: 'CASCADE', onUpdate: 'CASCADE' }) + @JoinColumn({ name: 'assetsId' }) + asset!: NonAttribute; +} diff --git a/server/src/entities/memory.entity.ts b/server/src/entities/memory.entity.ts index c8121dd32e..91e8cf70ac 100644 --- a/server/src/entities/memory.entity.ts +++ b/server/src/entities/memory.entity.ts @@ -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 { @PrimaryGeneratedColumn('uuid') - id!: string; + id!: Generated; @CreateDateColumn({ type: 'timestamptz' }) - createdAt!: Date; + createdAt!: Generated; @UpdateDateColumn({ type: 'timestamptz' }) - updatedAt!: Date; + updatedAt!: Generated; @DeleteDateColumn({ type: 'timestamptz' }) deletedAt?: Date; @ManyToOne(() => UserEntity, { onDelete: 'CASCADE', onUpdate: 'CASCADE', nullable: false }) - owner!: UserEntity; + owner!: NonAttribute; @Column() ownerId!: string; @@ -47,7 +48,7 @@ export class MemoryEntity { /** unless set to true, will be automatically deleted in the future */ @Column({ default: false }) - isSaved!: boolean; + isSaved!: Generated; /** memories are sorted in ascending order by this value */ @Column({ type: 'timestamptz' }) @@ -59,5 +60,5 @@ export class MemoryEntity { @ManyToMany(() => AssetEntity) @JoinTable() - assets!: AssetEntity[]; + assets!: NonAttribute; } diff --git a/server/src/entities/move.entity.ts b/server/src/entities/move.entity.ts index 5cdef5d22e..0c03792d55 100644 --- a/server/src/entities/move.entity.ts +++ b/server/src/entities/move.entity.ts @@ -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; @Column({ type: 'varchar' }) entityId!: string; diff --git a/server/src/entities/natural-earth-countries.entity.ts b/server/src/entities/natural-earth-countries.entity.ts index 0f97132045..5dee0e6ae1 100644 --- a/server/src/entities/natural-earth-countries.entity.ts +++ b/server/src/entities/natural-earth-countries.entity.ts @@ -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; @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; @Column({ type: 'varchar', length: 50 }) admin!: string; diff --git a/server/src/entities/partner.entity.ts b/server/src/entities/partner.entity.ts index 189f6f51a7..81e8b1adf9 100644 --- a/server/src/entities/partner.entity.ts +++ b/server/src/entities/partner.entity.ts @@ -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; @ManyToOne(() => UserEntity, { onDelete: 'CASCADE', eager: true }) @JoinColumn({ name: 'sharedWithId' }) - sharedWith!: UserEntity; + sharedWith!: NonAttribute; @CreateDateColumn({ type: 'timestamptz' }) - createdAt!: Date; + createdAt!: Generated; @UpdateDateColumn({ type: 'timestamptz' }) - updatedAt!: Date; + updatedAt!: Generated; @Column({ type: 'boolean', default: false }) - inTimeline!: boolean; + inTimeline!: Generated; } diff --git a/server/src/entities/person.entity.ts b/server/src/entities/person.entity.ts index 5efbcbfa0b..e16bcb51e4 100644 --- a/server/src/entities/person.entity.ts +++ b/server/src/entities/person.entity.ts @@ -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; @CreateDateColumn({ type: 'timestamptz' }) - createdAt!: Date; + createdAt!: Generated; @UpdateDateColumn({ type: 'timestamptz' }) - updatedAt!: Date; + updatedAt!: Generated; @Column() ownerId!: string; @ManyToOne(() => UserEntity, { onDelete: 'CASCADE', onUpdate: 'CASCADE', nullable: false }) - owner!: UserEntity; + owner!: NonAttribute; @Column({ default: '' }) - name!: string; + name!: Generated; @Column({ type: 'date', nullable: true }) birthDate!: string | null; @Column({ default: '' }) - thumbnailPath!: string; + thumbnailPath!: Generated; @Column({ nullable: true }) faceAssetId!: string | null; @ManyToOne(() => AssetFaceEntity, { onDelete: 'SET NULL', nullable: true }) - faceAsset!: AssetFaceEntity | null; + faceAsset!: NonAttribute; @OneToMany(() => AssetFaceEntity, (assetFace) => assetFace.person) - faces!: AssetFaceEntity[]; + faces!: NonAttribute; @Column({ default: false }) - isHidden!: boolean; + isHidden!: Generated; } diff --git a/server/src/entities/session.entity.ts b/server/src/entities/session.entity.ts index 1cc9ad9857..e7c454a6de 100644 --- a/server/src/entities/session.entity.ts +++ b/server/src/entities/session.entity.ts @@ -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; @Column({ select: false }) token!: string; @@ -13,17 +14,17 @@ export class SessionEntity { userId!: string; @ManyToOne(() => UserEntity, { onUpdate: 'CASCADE', onDelete: 'CASCADE' }) - user!: UserEntity; + user!: NonAttribute; @CreateDateColumn({ type: 'timestamptz' }) - createdAt!: Date; + createdAt!: Generated; @UpdateDateColumn({ type: 'timestamptz' }) - updatedAt!: Date; + updatedAt!: Generated; @Column({ default: '' }) - deviceType!: string; + deviceType!: Generated; @Column({ default: '' }) - deviceOS!: string; + deviceOS!: Generated; } diff --git a/server/src/entities/shared-link-asset.entity.ts b/server/src/entities/shared-link-asset.entity.ts new file mode 100644 index 0000000000..a380901c4e --- /dev/null +++ b/server/src/entities/shared-link-asset.entity.ts @@ -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; + + @PrimaryColumn('uuid') + @Index('IDX_c9fab4aa97ffd1b034f3d6581a') + sharedLinksId!: string; + + @ManyToOne(() => SharedLinkEntity, { onDelete: 'CASCADE', onUpdate: 'CASCADE' }) + @JoinColumn({ name: 'sharedLinksId' }) + sharedLink!: NonAttribute; +} diff --git a/server/src/entities/shared-link.entity.ts b/server/src/entities/shared-link.entity.ts index 1fed44b301..39720e7e62 100644 --- a/server/src/entities/shared-link.entity.ts +++ b/server/src/entities/shared-link.entity.ts @@ -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; @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; @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; @Column({ type: 'boolean', default: true }) - allowDownload!: boolean; + allowDownload!: Generated; @Column({ type: 'boolean', default: true }) - showExif!: boolean; + showExif!: Generated; @ManyToMany(() => AssetEntity, (asset) => asset.sharedLinks, { onDelete: 'CASCADE', onUpdate: 'CASCADE' }) - assets!: AssetEntity[]; + assets!: NonAttribute; @Index('IDX_sharedlink_albumId') @ManyToOne(() => AlbumEntity, (album) => album.sharedLinks, { onDelete: 'CASCADE', onUpdate: 'CASCADE' }) - album?: AlbumEntity; + album!: NonAttribute; @Column({ type: 'varchar', nullable: true }) albumId!: string | null; diff --git a/server/src/entities/smart-search.entity.ts b/server/src/entities/smart-search.entity.ts index 66017152ea..51d1e63d1e 100644 --- a/server/src/entities/smart-search.entity.ts +++ b/server/src/entities/smart-search.entity.ts @@ -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; @PrimaryColumn() assetId!: string; diff --git a/server/src/entities/stack.entity.ts b/server/src/entities/stack.entity.ts index 883f5cf246..a8bc6267f9 100644 --- a/server/src/entities/stack.entity.ts +++ b/server/src/entities/stack.entity.ts @@ -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; @ManyToOne(() => UserEntity, { onDelete: 'CASCADE', onUpdate: 'CASCADE' }) - owner!: UserEntity; + owner!: NonAttribute; @Column() ownerId!: string; @OneToMany(() => AssetEntity, (asset) => asset.stack) - assets!: AssetEntity[]; + assets!: NonAttribute; @OneToOne(() => AssetEntity) @JoinColumn() //TODO: Add constraint to ensure primary asset exists in the assets array - primaryAsset!: AssetEntity; + primaryAsset!: NonAttribute; @Column({ nullable: false }) primaryAssetId!: string; diff --git a/server/src/entities/tag-asset.entity.ts b/server/src/entities/tag-asset.entity.ts new file mode 100644 index 0000000000..7f038a69af --- /dev/null +++ b/server/src/entities/tag-asset.entity.ts @@ -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; + + @Index('IDX_e99f31ea4cdf3a2c35c7287eb4') + @PrimaryColumn('uuid') + tagsId!: string; + + @ManyToOne(() => TagEntity, { onDelete: 'CASCADE', onUpdate: 'CASCADE' }) + @JoinColumn({ name: 'tagsId' }) + tag!: NonAttribute; +} diff --git a/server/src/entities/tag-closure.entity.ts b/server/src/entities/tag-closure.entity.ts new file mode 100644 index 0000000000..04d8c0b359 --- /dev/null +++ b/server/src/entities/tag-closure.entity.ts @@ -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; +} diff --git a/server/src/entities/tag.entity.ts b/server/src/entities/tag.entity.ts index ebcc6853c9..720423fdef 100644 --- a/server/src/entities/tag.entity.ts +++ b/server/src/entities/tag.entity.ts @@ -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; @Column() value!: string; @CreateDateColumn({ type: 'timestamptz' }) - createdAt!: Date; + createdAt!: Generated; @UpdateDateColumn({ type: 'timestamptz' }) - updatedAt!: Date; + updatedAt!: Generated; @Column({ type: 'varchar', nullable: true, default: null }) - color!: string | null; + color!: Generated | null; @Column({ nullable: true }) parentId?: string; @TreeParent({ onDelete: 'CASCADE' }) - parent?: TagEntity; + parent!: NonAttribute; @TreeChildren() children?: TagEntity[]; @ManyToOne(() => UserEntity, (user) => user.tags, { onUpdate: 'CASCADE', onDelete: 'CASCADE' }) - user?: UserEntity; + user!: NonAttribute; @Column() userId!: string; @ManyToMany(() => AssetEntity, (asset) => asset.tags, { onUpdate: 'CASCADE', onDelete: 'CASCADE' }) - assets?: AssetEntity[]; + assets!: NonAttribute; } diff --git a/server/src/entities/user-metadata.entity.ts b/server/src/entities/user-metadata.entity.ts index c342cb71f8..261aab583b 100644 --- a/server/src/entities/user-metadata.entity.ts +++ b/server/src/entities/user-metadata.entity.ts @@ -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 userId!: string; @ManyToOne(() => UserEntity, (user) => user.metadata, { onUpdate: 'CASCADE', onDelete: 'CASCADE' }) - user!: UserEntity; + user!: NonAttribute; @PrimaryColumn({ type: 'varchar' }) key!: T; diff --git a/server/src/entities/user.entity.ts b/server/src/entities/user.entity.ts index ea446be390..a605740ebf 100644 --- a/server/src/entities/user.entity.ts +++ b/server/src/entities/user.entity.ts @@ -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; @Column({ default: '' }) - name!: string; + name!: Generated; @Column({ default: false }) - isAdmin!: boolean; + isAdmin!: Generated; @Column({ unique: true }) email!: string; @Column({ type: 'varchar', unique: true, default: null }) - storageLabel!: string | null; + storageLabel!: Generated | null; @Column({ default: '', select: false }) - password?: string; + password?: Generated; @Column({ default: '' }) - oauthId!: string; + oauthId!: Generated; @Column({ default: '' }) - profileImagePath!: string; + profileImagePath!: Generated; @Column({ default: true }) - shouldChangePassword!: boolean; + shouldChangePassword!: Generated; @CreateDateColumn({ type: 'timestamptz' }) - createdAt!: Date; + createdAt!: Generated; @DeleteDateColumn({ type: 'timestamptz' }) deletedAt!: Date | null; @Column({ type: 'varchar', default: UserStatus.ACTIVE }) - status!: UserStatus; + status!: Generated; @UpdateDateColumn({ type: 'timestamptz' }) - updatedAt!: Date; + updatedAt!: Generated; @OneToMany(() => TagEntity, (tag) => tag.user) - tags!: TagEntity[]; + tags!: NonAttribute; @OneToMany(() => AssetEntity, (asset) => asset.owner) - assets!: AssetEntity[]; + assets!: NonAttribute; @Column({ type: 'bigint', nullable: true }) quotaSizeInBytes!: number | null; @Column({ type: 'bigint', default: 0 }) - quotaUsageInBytes!: number; + quotaUsageInBytes!: Generated; @OneToMany(() => UserMetadataEntity, (metadata) => metadata.user) - metadata!: UserMetadataEntity[]; + metadata!: NonAttribute; @Column({ type: 'timestamptz', default: () => 'CURRENT_TIMESTAMP' }) - profileChangedAt!: Date; + profileChangedAt!: Generated; } diff --git a/server/src/entities/version-history.entity.ts b/server/src/entities/version-history.entity.ts index edccd9aed6..06ba31f636 100644 --- a/server/src/entities/version-history.entity.ts +++ b/server/src/entities/version-history.entity.ts @@ -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; @CreateDateColumn({ type: 'timestamptz' }) - createdAt!: Date; + createdAt!: Generated; @Column() version!: string; diff --git a/server/src/interfaces/asset.interface.ts b/server/src/interfaces/asset.interface.ts index 5abaf9af26..3b38ad5a5c 100644 --- a/server/src/interfaces/asset.interface.ts +++ b/server/src/interfaces/asset.interface.ts @@ -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'; diff --git a/server/src/repositories/asset.repository.ts b/server/src/repositories/asset.repository.ts index 9ad8bf0a6c..83245513f4 100644 --- a/server/src/repositories/asset.repository.ts +++ b/server/src/repositories/asset.repository.ts @@ -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, diff --git a/server/src/repositories/search.repository.ts b/server/src/repositories/search.repository.ts index 0c01f3409d..8563d5ee52 100644 --- a/server/src/repositories/search.repository.ts +++ b/server/src/repositories/search.repository.ts @@ -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') diff --git a/server/src/repositories/view-repository.ts b/server/src/repositories/view-repository.ts index 13a042a174..b0c187aa8c 100644 --- a/server/src/repositories/view-repository.ts +++ b/server/src/repositories/view-repository.ts @@ -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'; diff --git a/server/src/services/metadata.service.ts b/server/src/services/metadata.service.ts index 15ea990235..68112b574a 100644 --- a/server/src/services/metadata.service.ts +++ b/server/src/services/metadata.service.ts @@ -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'; diff --git a/server/src/utils/database.ts b/server/src/utils/database.ts index ec96466a86..7c83b1876c 100644 --- a/server/src/utils/database.ts +++ b/server/src/utils/database.ts @@ -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'; /**