mirror of
https://github.com/immich-app/immich.git
synced 2025-04-08 00:56:25 +02:00
refactor: migrate stack repo to kysely (#15440)
* wip * wip: add tags * wip * sql * pr feedback * pr feedback * ergonomic * pr feedback * pr feedback
This commit is contained in:
parent
887267b133
commit
318dd32363
8 changed files with 209 additions and 364 deletions
server/src
|
@ -1,3 +1,4 @@
|
||||||
|
import { Updateable } from 'kysely';
|
||||||
import { StackEntity } from 'src/entities/stack.entity';
|
import { StackEntity } from 'src/entities/stack.entity';
|
||||||
|
|
||||||
export const IStackRepository = 'IStackRepository';
|
export const IStackRepository = 'IStackRepository';
|
||||||
|
@ -10,8 +11,8 @@ export interface StackSearch {
|
||||||
export interface IStackRepository {
|
export interface IStackRepository {
|
||||||
search(query: StackSearch): Promise<StackEntity[]>;
|
search(query: StackSearch): Promise<StackEntity[]>;
|
||||||
create(stack: { ownerId: string; assetIds: string[] }): Promise<StackEntity>;
|
create(stack: { ownerId: string; assetIds: string[] }): Promise<StackEntity>;
|
||||||
update(stack: Pick<StackEntity, 'id'> & Partial<StackEntity>): Promise<StackEntity>;
|
update(id: string, entity: Updateable<StackEntity>): Promise<StackEntity>;
|
||||||
delete(id: string): Promise<void>;
|
delete(id: string): Promise<void>;
|
||||||
deleteAll(ids: string[]): Promise<void>;
|
deleteAll(ids: string[]): Promise<void>;
|
||||||
getById(id: string): Promise<StackEntity | null>;
|
getById(id: string): Promise<StackEntity | undefined>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,257 +1,95 @@
|
||||||
-- NOTE: This file is auto generated by ./sql-generator
|
-- NOTE: This file is auto generated by ./sql-generator
|
||||||
|
|
||||||
-- StackRepository.search
|
-- StackRepository.search
|
||||||
SELECT
|
select
|
||||||
"StackEntity"."id" AS "StackEntity_id",
|
"asset_stack".*,
|
||||||
"StackEntity"."ownerId" AS "StackEntity_ownerId",
|
(
|
||||||
"StackEntity"."primaryAssetId" AS "StackEntity_primaryAssetId",
|
select
|
||||||
"StackEntity__StackEntity_assets"."id" AS "StackEntity__StackEntity_assets_id",
|
coalesce(json_agg(agg), '[]')
|
||||||
"StackEntity__StackEntity_assets"."deviceAssetId" AS "StackEntity__StackEntity_assets_deviceAssetId",
|
from
|
||||||
"StackEntity__StackEntity_assets"."ownerId" AS "StackEntity__StackEntity_assets_ownerId",
|
(
|
||||||
"StackEntity__StackEntity_assets"."libraryId" AS "StackEntity__StackEntity_assets_libraryId",
|
select
|
||||||
"StackEntity__StackEntity_assets"."deviceId" AS "StackEntity__StackEntity_assets_deviceId",
|
*
|
||||||
"StackEntity__StackEntity_assets"."type" AS "StackEntity__StackEntity_assets_type",
|
from
|
||||||
"StackEntity__StackEntity_assets"."status" AS "StackEntity__StackEntity_assets_status",
|
"assets"
|
||||||
"StackEntity__StackEntity_assets"."originalPath" AS "StackEntity__StackEntity_assets_originalPath",
|
where
|
||||||
"StackEntity__StackEntity_assets"."thumbhash" AS "StackEntity__StackEntity_assets_thumbhash",
|
"assets"."deletedAt" is null
|
||||||
"StackEntity__StackEntity_assets"."encodedVideoPath" AS "StackEntity__StackEntity_assets_encodedVideoPath",
|
and "assets"."stackId" = "asset_stack"."id"
|
||||||
"StackEntity__StackEntity_assets"."createdAt" AS "StackEntity__StackEntity_assets_createdAt",
|
) as agg
|
||||||
"StackEntity__StackEntity_assets"."updatedAt" AS "StackEntity__StackEntity_assets_updatedAt",
|
) as "assets"
|
||||||
"StackEntity__StackEntity_assets"."deletedAt" AS "StackEntity__StackEntity_assets_deletedAt",
|
from
|
||||||
"StackEntity__StackEntity_assets"."fileCreatedAt" AS "StackEntity__StackEntity_assets_fileCreatedAt",
|
"asset_stack"
|
||||||
"StackEntity__StackEntity_assets"."localDateTime" AS "StackEntity__StackEntity_assets_localDateTime",
|
where
|
||||||
"StackEntity__StackEntity_assets"."fileModifiedAt" AS "StackEntity__StackEntity_assets_fileModifiedAt",
|
"asset_stack"."ownerId" = $1
|
||||||
"StackEntity__StackEntity_assets"."isFavorite" AS "StackEntity__StackEntity_assets_isFavorite",
|
|
||||||
"StackEntity__StackEntity_assets"."isArchived" AS "StackEntity__StackEntity_assets_isArchived",
|
|
||||||
"StackEntity__StackEntity_assets"."isExternal" AS "StackEntity__StackEntity_assets_isExternal",
|
|
||||||
"StackEntity__StackEntity_assets"."isOffline" AS "StackEntity__StackEntity_assets_isOffline",
|
|
||||||
"StackEntity__StackEntity_assets"."checksum" AS "StackEntity__StackEntity_assets_checksum",
|
|
||||||
"StackEntity__StackEntity_assets"."duration" AS "StackEntity__StackEntity_assets_duration",
|
|
||||||
"StackEntity__StackEntity_assets"."isVisible" AS "StackEntity__StackEntity_assets_isVisible",
|
|
||||||
"StackEntity__StackEntity_assets"."livePhotoVideoId" AS "StackEntity__StackEntity_assets_livePhotoVideoId",
|
|
||||||
"StackEntity__StackEntity_assets"."originalFileName" AS "StackEntity__StackEntity_assets_originalFileName",
|
|
||||||
"StackEntity__StackEntity_assets"."sidecarPath" AS "StackEntity__StackEntity_assets_sidecarPath",
|
|
||||||
"StackEntity__StackEntity_assets"."stackId" AS "StackEntity__StackEntity_assets_stackId",
|
|
||||||
"StackEntity__StackEntity_assets"."duplicateId" AS "StackEntity__StackEntity_assets_duplicateId",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."assetId" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_assetId",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."description" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_description",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."exifImageWidth" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_exifImageWidth",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."exifImageHeight" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_exifImageHeight",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."fileSizeInByte" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_fileSizeInByte",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."orientation" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_orientation",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."dateTimeOriginal" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_dateTimeOriginal",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."modifyDate" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_modifyDate",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."timeZone" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_timeZone",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."latitude" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_latitude",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."longitude" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_longitude",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."projectionType" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_projectionType",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."city" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_city",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."livePhotoCID" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_livePhotoCID",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."autoStackId" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_autoStackId",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."state" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_state",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."country" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_country",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."make" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_make",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."model" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_model",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."lensModel" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_lensModel",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."fNumber" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_fNumber",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."focalLength" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_focalLength",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."iso" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_iso",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."exposureTime" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_exposureTime",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."profileDescription" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_profileDescription",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."colorspace" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_colorspace",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."bitsPerSample" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_bitsPerSample",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."rating" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_rating",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."fps" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_fps"
|
|
||||||
FROM
|
|
||||||
"asset_stack" "StackEntity"
|
|
||||||
LEFT JOIN "assets" "StackEntity__StackEntity_assets" ON "StackEntity__StackEntity_assets"."stackId" = "StackEntity"."id"
|
|
||||||
AND (
|
|
||||||
"StackEntity__StackEntity_assets"."deletedAt" IS NULL
|
|
||||||
)
|
|
||||||
LEFT JOIN "exif" "01db479afeb88793eed8e0d1dde6ccfccf1698b9" ON "01db479afeb88793eed8e0d1dde6ccfccf1698b9"."assetId" = "StackEntity__StackEntity_assets"."id"
|
|
||||||
WHERE
|
|
||||||
(("StackEntity"."ownerId" = $1))
|
|
||||||
|
|
||||||
-- StackRepository.delete
|
-- StackRepository.delete
|
||||||
SELECT DISTINCT
|
select
|
||||||
"distinctAlias"."StackEntity_id" AS "ids_StackEntity_id",
|
*,
|
||||||
"distinctAlias"."StackEntity__StackEntity_assets_fileCreatedAt"
|
|
||||||
FROM
|
|
||||||
(
|
(
|
||||||
SELECT
|
select
|
||||||
"StackEntity"."id" AS "StackEntity_id",
|
coalesce(json_agg(agg), '[]')
|
||||||
"StackEntity"."ownerId" AS "StackEntity_ownerId",
|
from
|
||||||
"StackEntity"."primaryAssetId" AS "StackEntity_primaryAssetId",
|
(
|
||||||
"StackEntity__StackEntity_assets"."id" AS "StackEntity__StackEntity_assets_id",
|
select
|
||||||
"StackEntity__StackEntity_assets"."deviceAssetId" AS "StackEntity__StackEntity_assets_deviceAssetId",
|
*,
|
||||||
"StackEntity__StackEntity_assets"."ownerId" AS "StackEntity__StackEntity_assets_ownerId",
|
(
|
||||||
"StackEntity__StackEntity_assets"."libraryId" AS "StackEntity__StackEntity_assets_libraryId",
|
select
|
||||||
"StackEntity__StackEntity_assets"."deviceId" AS "StackEntity__StackEntity_assets_deviceId",
|
coalesce(json_agg(agg), '[]')
|
||||||
"StackEntity__StackEntity_assets"."type" AS "StackEntity__StackEntity_assets_type",
|
from
|
||||||
"StackEntity__StackEntity_assets"."status" AS "StackEntity__StackEntity_assets_status",
|
(
|
||||||
"StackEntity__StackEntity_assets"."originalPath" AS "StackEntity__StackEntity_assets_originalPath",
|
select
|
||||||
"StackEntity__StackEntity_assets"."thumbhash" AS "StackEntity__StackEntity_assets_thumbhash",
|
"tags".*
|
||||||
"StackEntity__StackEntity_assets"."encodedVideoPath" AS "StackEntity__StackEntity_assets_encodedVideoPath",
|
from
|
||||||
"StackEntity__StackEntity_assets"."createdAt" AS "StackEntity__StackEntity_assets_createdAt",
|
"tags"
|
||||||
"StackEntity__StackEntity_assets"."updatedAt" AS "StackEntity__StackEntity_assets_updatedAt",
|
inner join "tag_asset" on "tags"."id" = "tag_asset"."tagsId"
|
||||||
"StackEntity__StackEntity_assets"."deletedAt" AS "StackEntity__StackEntity_assets_deletedAt",
|
where
|
||||||
"StackEntity__StackEntity_assets"."fileCreatedAt" AS "StackEntity__StackEntity_assets_fileCreatedAt",
|
"tag_asset"."assetsId" = "assets"."id"
|
||||||
"StackEntity__StackEntity_assets"."localDateTime" AS "StackEntity__StackEntity_assets_localDateTime",
|
) as agg
|
||||||
"StackEntity__StackEntity_assets"."fileModifiedAt" AS "StackEntity__StackEntity_assets_fileModifiedAt",
|
) as "tags"
|
||||||
"StackEntity__StackEntity_assets"."isFavorite" AS "StackEntity__StackEntity_assets_isFavorite",
|
from
|
||||||
"StackEntity__StackEntity_assets"."isArchived" AS "StackEntity__StackEntity_assets_isArchived",
|
"assets"
|
||||||
"StackEntity__StackEntity_assets"."isExternal" AS "StackEntity__StackEntity_assets_isExternal",
|
where
|
||||||
"StackEntity__StackEntity_assets"."isOffline" AS "StackEntity__StackEntity_assets_isOffline",
|
"assets"."deletedAt" is null
|
||||||
"StackEntity__StackEntity_assets"."checksum" AS "StackEntity__StackEntity_assets_checksum",
|
and "assets"."stackId" = "asset_stack"."id"
|
||||||
"StackEntity__StackEntity_assets"."duration" AS "StackEntity__StackEntity_assets_duration",
|
) as agg
|
||||||
"StackEntity__StackEntity_assets"."isVisible" AS "StackEntity__StackEntity_assets_isVisible",
|
) as "assets"
|
||||||
"StackEntity__StackEntity_assets"."livePhotoVideoId" AS "StackEntity__StackEntity_assets_livePhotoVideoId",
|
from
|
||||||
"StackEntity__StackEntity_assets"."originalFileName" AS "StackEntity__StackEntity_assets_originalFileName",
|
"asset_stack"
|
||||||
"StackEntity__StackEntity_assets"."sidecarPath" AS "StackEntity__StackEntity_assets_sidecarPath",
|
where
|
||||||
"StackEntity__StackEntity_assets"."stackId" AS "StackEntity__StackEntity_assets_stackId",
|
"id" = $1::uuid
|
||||||
"StackEntity__StackEntity_assets"."duplicateId" AS "StackEntity__StackEntity_assets_duplicateId",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."assetId" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_assetId",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."description" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_description",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."exifImageWidth" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_exifImageWidth",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."exifImageHeight" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_exifImageHeight",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."fileSizeInByte" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_fileSizeInByte",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."orientation" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_orientation",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."dateTimeOriginal" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_dateTimeOriginal",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."modifyDate" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_modifyDate",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."timeZone" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_timeZone",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."latitude" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_latitude",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."longitude" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_longitude",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."projectionType" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_projectionType",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."city" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_city",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."livePhotoCID" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_livePhotoCID",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."autoStackId" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_autoStackId",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."state" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_state",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."country" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_country",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."make" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_make",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."model" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_model",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."lensModel" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_lensModel",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."fNumber" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_fNumber",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."focalLength" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_focalLength",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."iso" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_iso",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."exposureTime" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_exposureTime",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."profileDescription" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_profileDescription",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."colorspace" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_colorspace",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."bitsPerSample" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_bitsPerSample",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."rating" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_rating",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."fps" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_fps",
|
|
||||||
"3e3064f11b97177a1e1ce3c77ecf32850343aba1"."id" AS "3e3064f11b97177a1e1ce3c77ecf32850343aba1_id",
|
|
||||||
"3e3064f11b97177a1e1ce3c77ecf32850343aba1"."value" AS "3e3064f11b97177a1e1ce3c77ecf32850343aba1_value",
|
|
||||||
"3e3064f11b97177a1e1ce3c77ecf32850343aba1"."createdAt" AS "3e3064f11b97177a1e1ce3c77ecf32850343aba1_createdAt",
|
|
||||||
"3e3064f11b97177a1e1ce3c77ecf32850343aba1"."updatedAt" AS "3e3064f11b97177a1e1ce3c77ecf32850343aba1_updatedAt",
|
|
||||||
"3e3064f11b97177a1e1ce3c77ecf32850343aba1"."color" AS "3e3064f11b97177a1e1ce3c77ecf32850343aba1_color",
|
|
||||||
"3e3064f11b97177a1e1ce3c77ecf32850343aba1"."parentId" AS "3e3064f11b97177a1e1ce3c77ecf32850343aba1_parentId",
|
|
||||||
"3e3064f11b97177a1e1ce3c77ecf32850343aba1"."userId" AS "3e3064f11b97177a1e1ce3c77ecf32850343aba1_userId"
|
|
||||||
FROM
|
|
||||||
"asset_stack" "StackEntity"
|
|
||||||
LEFT JOIN "assets" "StackEntity__StackEntity_assets" ON "StackEntity__StackEntity_assets"."stackId" = "StackEntity"."id"
|
|
||||||
AND (
|
|
||||||
"StackEntity__StackEntity_assets"."deletedAt" IS NULL
|
|
||||||
)
|
|
||||||
LEFT JOIN "exif" "01db479afeb88793eed8e0d1dde6ccfccf1698b9" ON "01db479afeb88793eed8e0d1dde6ccfccf1698b9"."assetId" = "StackEntity__StackEntity_assets"."id"
|
|
||||||
LEFT JOIN "tag_asset" "4f1c9474d4596aede2814ee2eb938eecf7a93b95" ON "4f1c9474d4596aede2814ee2eb938eecf7a93b95"."assetsId" = "StackEntity__StackEntity_assets"."id"
|
|
||||||
LEFT JOIN "tags" "3e3064f11b97177a1e1ce3c77ecf32850343aba1" ON "3e3064f11b97177a1e1ce3c77ecf32850343aba1"."id" = "4f1c9474d4596aede2814ee2eb938eecf7a93b95"."tagsId"
|
|
||||||
WHERE
|
|
||||||
(("StackEntity"."id" = $1))
|
|
||||||
) "distinctAlias"
|
|
||||||
ORDER BY
|
|
||||||
"distinctAlias"."StackEntity__StackEntity_assets_fileCreatedAt" ASC,
|
|
||||||
"StackEntity_id" ASC
|
|
||||||
LIMIT
|
|
||||||
1
|
|
||||||
|
|
||||||
-- StackRepository.getById
|
-- StackRepository.getById
|
||||||
SELECT DISTINCT
|
select
|
||||||
"distinctAlias"."StackEntity_id" AS "ids_StackEntity_id",
|
*,
|
||||||
"distinctAlias"."StackEntity__StackEntity_assets_fileCreatedAt"
|
|
||||||
FROM
|
|
||||||
(
|
(
|
||||||
SELECT
|
select
|
||||||
"StackEntity"."id" AS "StackEntity_id",
|
coalesce(json_agg(agg), '[]')
|
||||||
"StackEntity"."ownerId" AS "StackEntity_ownerId",
|
from
|
||||||
"StackEntity"."primaryAssetId" AS "StackEntity_primaryAssetId",
|
(
|
||||||
"StackEntity__StackEntity_assets"."id" AS "StackEntity__StackEntity_assets_id",
|
select
|
||||||
"StackEntity__StackEntity_assets"."deviceAssetId" AS "StackEntity__StackEntity_assets_deviceAssetId",
|
*,
|
||||||
"StackEntity__StackEntity_assets"."ownerId" AS "StackEntity__StackEntity_assets_ownerId",
|
(
|
||||||
"StackEntity__StackEntity_assets"."libraryId" AS "StackEntity__StackEntity_assets_libraryId",
|
select
|
||||||
"StackEntity__StackEntity_assets"."deviceId" AS "StackEntity__StackEntity_assets_deviceId",
|
coalesce(json_agg(agg), '[]')
|
||||||
"StackEntity__StackEntity_assets"."type" AS "StackEntity__StackEntity_assets_type",
|
from
|
||||||
"StackEntity__StackEntity_assets"."status" AS "StackEntity__StackEntity_assets_status",
|
(
|
||||||
"StackEntity__StackEntity_assets"."originalPath" AS "StackEntity__StackEntity_assets_originalPath",
|
select
|
||||||
"StackEntity__StackEntity_assets"."thumbhash" AS "StackEntity__StackEntity_assets_thumbhash",
|
"tags".*
|
||||||
"StackEntity__StackEntity_assets"."encodedVideoPath" AS "StackEntity__StackEntity_assets_encodedVideoPath",
|
from
|
||||||
"StackEntity__StackEntity_assets"."createdAt" AS "StackEntity__StackEntity_assets_createdAt",
|
"tags"
|
||||||
"StackEntity__StackEntity_assets"."updatedAt" AS "StackEntity__StackEntity_assets_updatedAt",
|
inner join "tag_asset" on "tags"."id" = "tag_asset"."tagsId"
|
||||||
"StackEntity__StackEntity_assets"."deletedAt" AS "StackEntity__StackEntity_assets_deletedAt",
|
where
|
||||||
"StackEntity__StackEntity_assets"."fileCreatedAt" AS "StackEntity__StackEntity_assets_fileCreatedAt",
|
"tag_asset"."assetsId" = "assets"."id"
|
||||||
"StackEntity__StackEntity_assets"."localDateTime" AS "StackEntity__StackEntity_assets_localDateTime",
|
) as agg
|
||||||
"StackEntity__StackEntity_assets"."fileModifiedAt" AS "StackEntity__StackEntity_assets_fileModifiedAt",
|
) as "tags"
|
||||||
"StackEntity__StackEntity_assets"."isFavorite" AS "StackEntity__StackEntity_assets_isFavorite",
|
from
|
||||||
"StackEntity__StackEntity_assets"."isArchived" AS "StackEntity__StackEntity_assets_isArchived",
|
"assets"
|
||||||
"StackEntity__StackEntity_assets"."isExternal" AS "StackEntity__StackEntity_assets_isExternal",
|
where
|
||||||
"StackEntity__StackEntity_assets"."isOffline" AS "StackEntity__StackEntity_assets_isOffline",
|
"assets"."deletedAt" is null
|
||||||
"StackEntity__StackEntity_assets"."checksum" AS "StackEntity__StackEntity_assets_checksum",
|
and "assets"."stackId" = "asset_stack"."id"
|
||||||
"StackEntity__StackEntity_assets"."duration" AS "StackEntity__StackEntity_assets_duration",
|
) as agg
|
||||||
"StackEntity__StackEntity_assets"."isVisible" AS "StackEntity__StackEntity_assets_isVisible",
|
) as "assets"
|
||||||
"StackEntity__StackEntity_assets"."livePhotoVideoId" AS "StackEntity__StackEntity_assets_livePhotoVideoId",
|
from
|
||||||
"StackEntity__StackEntity_assets"."originalFileName" AS "StackEntity__StackEntity_assets_originalFileName",
|
"asset_stack"
|
||||||
"StackEntity__StackEntity_assets"."sidecarPath" AS "StackEntity__StackEntity_assets_sidecarPath",
|
where
|
||||||
"StackEntity__StackEntity_assets"."stackId" AS "StackEntity__StackEntity_assets_stackId",
|
"id" = $1::uuid
|
||||||
"StackEntity__StackEntity_assets"."duplicateId" AS "StackEntity__StackEntity_assets_duplicateId",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."assetId" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_assetId",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."description" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_description",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."exifImageWidth" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_exifImageWidth",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."exifImageHeight" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_exifImageHeight",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."fileSizeInByte" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_fileSizeInByte",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."orientation" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_orientation",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."dateTimeOriginal" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_dateTimeOriginal",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."modifyDate" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_modifyDate",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."timeZone" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_timeZone",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."latitude" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_latitude",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."longitude" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_longitude",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."projectionType" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_projectionType",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."city" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_city",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."livePhotoCID" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_livePhotoCID",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."autoStackId" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_autoStackId",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."state" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_state",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."country" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_country",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."make" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_make",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."model" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_model",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."lensModel" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_lensModel",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."fNumber" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_fNumber",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."focalLength" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_focalLength",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."iso" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_iso",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."exposureTime" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_exposureTime",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."profileDescription" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_profileDescription",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."colorspace" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_colorspace",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."bitsPerSample" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_bitsPerSample",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."rating" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_rating",
|
|
||||||
"01db479afeb88793eed8e0d1dde6ccfccf1698b9"."fps" AS "01db479afeb88793eed8e0d1dde6ccfccf1698b9_fps",
|
|
||||||
"3e3064f11b97177a1e1ce3c77ecf32850343aba1"."id" AS "3e3064f11b97177a1e1ce3c77ecf32850343aba1_id",
|
|
||||||
"3e3064f11b97177a1e1ce3c77ecf32850343aba1"."value" AS "3e3064f11b97177a1e1ce3c77ecf32850343aba1_value",
|
|
||||||
"3e3064f11b97177a1e1ce3c77ecf32850343aba1"."createdAt" AS "3e3064f11b97177a1e1ce3c77ecf32850343aba1_createdAt",
|
|
||||||
"3e3064f11b97177a1e1ce3c77ecf32850343aba1"."updatedAt" AS "3e3064f11b97177a1e1ce3c77ecf32850343aba1_updatedAt",
|
|
||||||
"3e3064f11b97177a1e1ce3c77ecf32850343aba1"."color" AS "3e3064f11b97177a1e1ce3c77ecf32850343aba1_color",
|
|
||||||
"3e3064f11b97177a1e1ce3c77ecf32850343aba1"."parentId" AS "3e3064f11b97177a1e1ce3c77ecf32850343aba1_parentId",
|
|
||||||
"3e3064f11b97177a1e1ce3c77ecf32850343aba1"."userId" AS "3e3064f11b97177a1e1ce3c77ecf32850343aba1_userId"
|
|
||||||
FROM
|
|
||||||
"asset_stack" "StackEntity"
|
|
||||||
LEFT JOIN "assets" "StackEntity__StackEntity_assets" ON "StackEntity__StackEntity_assets"."stackId" = "StackEntity"."id"
|
|
||||||
AND (
|
|
||||||
"StackEntity__StackEntity_assets"."deletedAt" IS NULL
|
|
||||||
)
|
|
||||||
LEFT JOIN "exif" "01db479afeb88793eed8e0d1dde6ccfccf1698b9" ON "01db479afeb88793eed8e0d1dde6ccfccf1698b9"."assetId" = "StackEntity__StackEntity_assets"."id"
|
|
||||||
LEFT JOIN "tag_asset" "4f1c9474d4596aede2814ee2eb938eecf7a93b95" ON "4f1c9474d4596aede2814ee2eb938eecf7a93b95"."assetsId" = "StackEntity__StackEntity_assets"."id"
|
|
||||||
LEFT JOIN "tags" "3e3064f11b97177a1e1ce3c77ecf32850343aba1" ON "3e3064f11b97177a1e1ce3c77ecf32850343aba1"."id" = "4f1c9474d4596aede2814ee2eb938eecf7a93b95"."tagsId"
|
|
||||||
WHERE
|
|
||||||
(("StackEntity"."id" = $1))
|
|
||||||
) "distinctAlias"
|
|
||||||
ORDER BY
|
|
||||||
"distinctAlias"."StackEntity__StackEntity_assets_fileCreatedAt" ASC,
|
|
||||||
"StackEntity_id" ASC
|
|
||||||
LIMIT
|
|
||||||
1
|
|
||||||
|
|
|
@ -36,10 +36,7 @@ class ActivityAccess implements IActivityAccess {
|
||||||
.where('activity.id', 'in', [...activityIds])
|
.where('activity.id', 'in', [...activityIds])
|
||||||
.where('activity.userId', '=', userId)
|
.where('activity.userId', '=', userId)
|
||||||
.execute()
|
.execute()
|
||||||
.then((activities) => {
|
.then((activities) => new Set(activities.map((activity) => activity.id)));
|
||||||
console.log('activities', activities);
|
|
||||||
return new Set(activities.map((activity) => activity.id));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
|
@GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
|
||||||
|
|
|
@ -1,84 +1,113 @@
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { InjectDataSource, InjectRepository } from '@nestjs/typeorm';
|
import { ExpressionBuilder, Kysely, Updateable } from 'kysely';
|
||||||
|
import { jsonArrayFrom } from 'kysely/helpers/postgres';
|
||||||
|
import { InjectKysely } from 'nestjs-kysely';
|
||||||
|
import { DB } from 'src/db';
|
||||||
import { DummyValue, GenerateSql } from 'src/decorators';
|
import { DummyValue, GenerateSql } from 'src/decorators';
|
||||||
import { AssetEntity } from 'src/entities/asset.entity';
|
|
||||||
import { StackEntity } from 'src/entities/stack.entity';
|
import { StackEntity } from 'src/entities/stack.entity';
|
||||||
import { IStackRepository, StackSearch } from 'src/interfaces/stack.interface';
|
import { IStackRepository, StackSearch } from 'src/interfaces/stack.interface';
|
||||||
import { DataSource, In, Repository } from 'typeorm';
|
import { asUuid } from 'src/utils/database';
|
||||||
|
|
||||||
|
const withAssets = (eb: ExpressionBuilder<DB, 'asset_stack'>, withTags = false) => {
|
||||||
|
return jsonArrayFrom(
|
||||||
|
eb
|
||||||
|
.selectFrom('assets')
|
||||||
|
.selectAll()
|
||||||
|
.$if(withTags, (eb) =>
|
||||||
|
eb.select((eb) =>
|
||||||
|
jsonArrayFrom(
|
||||||
|
eb
|
||||||
|
.selectFrom('tags')
|
||||||
|
.selectAll('tags')
|
||||||
|
.innerJoin('tag_asset', 'tags.id', 'tag_asset.tagsId')
|
||||||
|
.whereRef('tag_asset.assetsId', '=', 'assets.id'),
|
||||||
|
).as('tags'),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.where('assets.deletedAt', 'is', null)
|
||||||
|
.whereRef('assets.stackId', '=', 'asset_stack.id'),
|
||||||
|
).as('assets');
|
||||||
|
};
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class StackRepository implements IStackRepository {
|
export class StackRepository implements IStackRepository {
|
||||||
constructor(
|
constructor(@InjectKysely() private db: Kysely<DB>) {}
|
||||||
@InjectDataSource() private dataSource: DataSource,
|
|
||||||
@InjectRepository(StackEntity) private repository: Repository<StackEntity>,
|
|
||||||
) {}
|
|
||||||
|
|
||||||
@GenerateSql({ params: [{ ownerId: DummyValue.UUID }] })
|
@GenerateSql({ params: [{ ownerId: DummyValue.UUID }] })
|
||||||
search(query: StackSearch): Promise<StackEntity[]> {
|
search(query: StackSearch): Promise<StackEntity[]> {
|
||||||
return this.repository.find({
|
return this.db
|
||||||
where: {
|
.selectFrom('asset_stack')
|
||||||
ownerId: query.ownerId,
|
.selectAll('asset_stack')
|
||||||
primaryAssetId: query.primaryAssetId,
|
.select(withAssets)
|
||||||
},
|
.where('asset_stack.ownerId', '=', query.ownerId)
|
||||||
relations: {
|
.$if(!!query.primaryAssetId, (eb) => eb.where('asset_stack.primaryAssetId', '=', query.primaryAssetId!))
|
||||||
assets: {
|
.execute() as unknown as Promise<StackEntity[]>;
|
||||||
exifInfo: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async create(entity: { ownerId: string; assetIds: string[] }): Promise<StackEntity> {
|
async create(entity: { ownerId: string; assetIds: string[] }): Promise<StackEntity> {
|
||||||
return this.dataSource.manager.transaction(async (manager) => {
|
return this.db.transaction().execute(async (tx) => {
|
||||||
const stackRepository = manager.getRepository(StackEntity);
|
const stacks = await tx
|
||||||
|
.selectFrom('asset_stack')
|
||||||
const stacks = await stackRepository.find({
|
.where('asset_stack.ownerId', '=', entity.ownerId)
|
||||||
where: {
|
.where('asset_stack.primaryAssetId', 'in', entity.assetIds)
|
||||||
ownerId: entity.ownerId,
|
.select('asset_stack.id')
|
||||||
primaryAssetId: In(entity.assetIds),
|
.select((eb) =>
|
||||||
},
|
jsonArrayFrom(
|
||||||
select: {
|
eb
|
||||||
id: true,
|
.selectFrom('assets')
|
||||||
assets: {
|
.select('assets.id')
|
||||||
id: true,
|
.whereRef('assets.stackId', '=', 'asset_stack.id')
|
||||||
},
|
.where('assets.deletedAt', 'is', null),
|
||||||
},
|
).as('assets'),
|
||||||
relations: {
|
)
|
||||||
assets: {
|
.execute();
|
||||||
exifInfo: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const assetIds = new Set<string>(entity.assetIds);
|
const assetIds = new Set<string>(entity.assetIds);
|
||||||
|
|
||||||
// children
|
// children
|
||||||
for (const stack of stacks) {
|
for (const stack of stacks) {
|
||||||
for (const asset of stack.assets) {
|
if (stack.assets && stack.assets.length > 0) {
|
||||||
assetIds.add(asset.id);
|
for (const asset of stack.assets) {
|
||||||
|
assetIds.add(asset.id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stacks.length > 0) {
|
if (stacks.length > 0) {
|
||||||
await stackRepository.delete({ id: In(stacks.map((stack) => stack.id)) });
|
await tx
|
||||||
|
.deleteFrom('asset_stack')
|
||||||
|
.where(
|
||||||
|
'id',
|
||||||
|
'in',
|
||||||
|
stacks.map((stack) => stack.id),
|
||||||
|
)
|
||||||
|
.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
const { id } = await stackRepository.save({
|
const newRecord = await tx
|
||||||
ownerId: entity.ownerId,
|
.insertInto('asset_stack')
|
||||||
primaryAssetId: entity.assetIds[0],
|
.values({
|
||||||
assets: [...assetIds].map((id) => ({ id }) as AssetEntity),
|
ownerId: entity.ownerId,
|
||||||
});
|
primaryAssetId: entity.assetIds[0],
|
||||||
|
})
|
||||||
|
.returning('id')
|
||||||
|
.executeTakeFirstOrThrow();
|
||||||
|
|
||||||
return stackRepository.findOneOrFail({
|
await tx
|
||||||
where: {
|
.updateTable('assets')
|
||||||
id,
|
.set({
|
||||||
},
|
stackId: newRecord.id,
|
||||||
relations: {
|
updatedAt: new Date(),
|
||||||
assets: {
|
})
|
||||||
exifInfo: true,
|
.where('id', 'in', [...assetIds])
|
||||||
},
|
.execute();
|
||||||
},
|
|
||||||
});
|
return tx
|
||||||
|
.selectFrom('asset_stack')
|
||||||
|
.selectAll('asset_stack')
|
||||||
|
.select(withAssets)
|
||||||
|
.where('id', '=', newRecord.id)
|
||||||
|
.executeTakeFirst() as unknown as Promise<StackEntity>;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,12 +120,12 @@ export class StackRepository implements IStackRepository {
|
||||||
|
|
||||||
const assetIds = stack.assets.map(({ id }) => id);
|
const assetIds = stack.assets.map(({ id }) => id);
|
||||||
|
|
||||||
await this.repository.delete(id);
|
await this.db.deleteFrom('asset_stack').where('id', '=', asUuid(id)).execute();
|
||||||
|
await this.db
|
||||||
// Update assets updatedAt
|
.updateTable('assets')
|
||||||
await this.dataSource.manager.update(AssetEntity, assetIds, {
|
.set({ stackId: null, updatedAt: new Date() })
|
||||||
updatedAt: new Date(),
|
.where('id', 'in', assetIds)
|
||||||
});
|
.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteAll(ids: string[]): Promise<void> {
|
async deleteAll(ids: string[]): Promise<void> {
|
||||||
|
@ -110,54 +139,31 @@ export class StackRepository implements IStackRepository {
|
||||||
assetIds.push(...stack.assets.map(({ id }) => id));
|
assetIds.push(...stack.assets.map(({ id }) => id));
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.repository.delete(ids);
|
await this.db
|
||||||
|
.updateTable('assets')
|
||||||
// Update assets updatedAt
|
.set({ updatedAt: new Date(), stackId: null })
|
||||||
await this.dataSource.manager.update(AssetEntity, assetIds, {
|
.where('id', 'in', assetIds)
|
||||||
updatedAt: new Date(),
|
.where('stackId', 'in', ids)
|
||||||
});
|
.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
update(entity: Partial<StackEntity>) {
|
update(id: string, entity: Updateable<StackEntity>): Promise<StackEntity> {
|
||||||
return this.save(entity);
|
return this.db
|
||||||
|
.updateTable('asset_stack')
|
||||||
|
.set(entity)
|
||||||
|
.where('id', '=', asUuid(id))
|
||||||
|
.returningAll('asset_stack')
|
||||||
|
.returning((eb) => withAssets(eb, true))
|
||||||
|
.executeTakeFirstOrThrow() as unknown as Promise<StackEntity>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@GenerateSql({ params: [DummyValue.UUID] })
|
@GenerateSql({ params: [DummyValue.UUID] })
|
||||||
async getById(id: string): Promise<StackEntity | null> {
|
getById(id: string): Promise<StackEntity | undefined> {
|
||||||
return this.repository.findOne({
|
return this.db
|
||||||
where: {
|
.selectFrom('asset_stack')
|
||||||
id,
|
.selectAll()
|
||||||
},
|
.select((eb) => withAssets(eb, true))
|
||||||
relations: {
|
.where('id', '=', asUuid(id))
|
||||||
assets: {
|
.executeTakeFirst() as Promise<StackEntity | undefined>;
|
||||||
exifInfo: true,
|
|
||||||
tags: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
order: {
|
|
||||||
assets: {
|
|
||||||
fileCreatedAt: 'ASC',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private async save(entity: Partial<StackEntity>) {
|
|
||||||
const { id } = await this.repository.save(entity);
|
|
||||||
return this.repository.findOneOrFail({
|
|
||||||
where: {
|
|
||||||
id,
|
|
||||||
},
|
|
||||||
relations: {
|
|
||||||
assets: {
|
|
||||||
exifInfo: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
order: {
|
|
||||||
assets: {
|
|
||||||
fileCreatedAt: 'ASC',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -520,7 +520,7 @@ describe(AssetService.name, () => {
|
||||||
|
|
||||||
await sut.handleAssetDeletion({ id: assetStub.primaryImage.id, deleteOnDisk: true });
|
await sut.handleAssetDeletion({ id: assetStub.primaryImage.id, deleteOnDisk: true });
|
||||||
|
|
||||||
expect(stackMock.update).toHaveBeenCalledWith({
|
expect(stackMock.update).toHaveBeenCalledWith('stack-1', {
|
||||||
id: 'stack-1',
|
id: 'stack-1',
|
||||||
primaryAssetId: 'stack-child-asset-1',
|
primaryAssetId: 'stack-child-asset-1',
|
||||||
});
|
});
|
||||||
|
|
|
@ -192,7 +192,7 @@ export class AssetService extends BaseService {
|
||||||
const stackAssetIds = asset.stack.assets.map((a) => a.id);
|
const stackAssetIds = asset.stack.assets.map((a) => a.id);
|
||||||
if (stackAssetIds.length > 2) {
|
if (stackAssetIds.length > 2) {
|
||||||
const newPrimaryAssetId = stackAssetIds.find((a) => a !== id)!;
|
const newPrimaryAssetId = stackAssetIds.find((a) => a !== id)!;
|
||||||
await this.stackRepository.update({
|
await this.stackRepository.update(asset.stack.id, {
|
||||||
id: asset.stack.id,
|
id: asset.stack.id,
|
||||||
primaryAssetId: newPrimaryAssetId,
|
primaryAssetId: newPrimaryAssetId,
|
||||||
});
|
});
|
||||||
|
|
|
@ -141,7 +141,10 @@ describe(StackService.name, () => {
|
||||||
await sut.update(authStub.admin, 'stack-id', { primaryAssetId: assetStub.image1.id });
|
await sut.update(authStub.admin, 'stack-id', { primaryAssetId: assetStub.image1.id });
|
||||||
|
|
||||||
expect(stackMock.getById).toHaveBeenCalledWith('stack-id');
|
expect(stackMock.getById).toHaveBeenCalledWith('stack-id');
|
||||||
expect(stackMock.update).toHaveBeenCalledWith({ id: 'stack-id', primaryAssetId: assetStub.image1.id });
|
expect(stackMock.update).toHaveBeenCalledWith('stack-id', {
|
||||||
|
id: 'stack-id',
|
||||||
|
primaryAssetId: assetStub.image1.id,
|
||||||
|
});
|
||||||
expect(eventMock.emit).toHaveBeenCalledWith('stack.update', {
|
expect(eventMock.emit).toHaveBeenCalledWith('stack.update', {
|
||||||
stackId: 'stack-id',
|
stackId: 'stack-id',
|
||||||
userId: authStub.admin.user.id,
|
userId: authStub.admin.user.id,
|
||||||
|
|
|
@ -39,7 +39,7 @@ export class StackService extends BaseService {
|
||||||
throw new BadRequestException('Primary asset must be in the stack');
|
throw new BadRequestException('Primary asset must be in the stack');
|
||||||
}
|
}
|
||||||
|
|
||||||
const updatedStack = await this.stackRepository.update({ id, primaryAssetId: dto.primaryAssetId });
|
const updatedStack = await this.stackRepository.update(id, { id, primaryAssetId: dto.primaryAssetId });
|
||||||
|
|
||||||
await this.eventRepository.emit('stack.update', { stackId: id, userId: auth.user.id });
|
await this.eventRepository.emit('stack.update', { stackId: id, userId: auth.user.id });
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue