From e556e65515ecd23ef77d84db0747ec47e1d77c33 Mon Sep 17 00:00:00 2001 From: Kristaps Fabians Geikins Date: Thu, 10 Oct 2024 10:41:30 +0300 Subject: [PATCH] chore(server): core IoC 39 - getFavoriteStreamsCollectionFactory --- .../modules/core/domain/streams/operations.ts | 22 ++++ .../modules/core/graph/resolvers/streams.ts | 8 +- .../modules/core/repositories/streams.ts | 120 +++++++++--------- .../server/modules/core/services/streams.js | 30 ----- .../modules/core/services/streams/favorite.ts | 37 ++++++ 5 files changed, 124 insertions(+), 93 deletions(-) create mode 100644 packages/server/modules/core/services/streams/favorite.ts diff --git a/packages/server/modules/core/domain/streams/operations.ts b/packages/server/modules/core/domain/streams/operations.ts index 36ed220f09..51372d5283 100644 --- a/packages/server/modules/core/domain/streams/operations.ts +++ b/packages/server/modules/core/domain/streams/operations.ts @@ -97,6 +97,21 @@ export type GetDiscoverableStreamsPage = ( params: GetDiscoverableStreamsParams ) => Promise +export type GetFavoritedStreamsPage = (params: { + userId: string + cursor?: string | null + limit?: number + streamIdWhitelist?: Optional +}) => Promise<{ + streams: Stream[] + cursor: Nullable +}> + +export type GetFavoritedStreamsCount = ( + userId: string, + streamIdWhitelist?: Optional +) => Promise + export type RevokeStreamPermissions = (params: { streamId: string userId: string @@ -202,3 +217,10 @@ export type GetDiscoverableStreams = ( totalCount: number items: Stream[] }> + +export type GetFavoriteStreamsCollection = (params: { + userId: string + limit?: number | undefined + cursor?: string | null | undefined + streamIdWhitelist?: string[] | undefined +}) => Promise<{ totalCount: number; cursor: Nullable; items: Stream[] }> diff --git a/packages/server/modules/core/graph/resolvers/streams.ts b/packages/server/modules/core/graph/resolvers/streams.ts index d272b2999a..4a5e4c05a8 100644 --- a/packages/server/modules/core/graph/resolvers/streams.ts +++ b/packages/server/modules/core/graph/resolvers/streams.ts @@ -1,7 +1,6 @@ import { getStreamUsers, favoriteStream, - getFavoriteStreamsCollection, getActiveUserStreamFavoriteDate, getStreamFavoritesCount, getOwnedFavoritesCount @@ -34,6 +33,8 @@ import { getDiscoverableStreamsPage, countDiscoverableStreamsFactory, legacyGetStreamsFactory, + getFavoritedStreamsCountFactory, + getFavoritedStreamsPageFactory, getStreamCollaboratorsFactory } from '@/modules/core/repositories/streams' import { @@ -86,7 +87,12 @@ import { validateStreamAccessFactory } from '@/modules/core/services/streams/access' import { getDiscoverableStreamsFactory } from '@/modules/core/services/streams/discoverableStreams' +import { getFavoriteStreamsCollectionFactory } from '@/modules/core/services/streams/favorite' +const getFavoriteStreamsCollection = getFavoriteStreamsCollectionFactory({ + getFavoritedStreamsCount: getFavoritedStreamsCountFactory({ db }), + getFavoritedStreamsPage: getFavoritedStreamsPageFactory({ db }) +}) const saveActivity = saveActivityFactory({ db }) const getStream = getStreamFactory({ db }) const createStreamReturnRecord = createStreamReturnRecordFactory({ diff --git a/packages/server/modules/core/repositories/streams.ts b/packages/server/modules/core/repositories/streams.ts index 464bc91213..b1af13c8e5 100644 --- a/packages/server/modules/core/repositories/streams.ts +++ b/packages/server/modules/core/repositories/streams.ts @@ -84,14 +84,17 @@ import { GetDiscoverableStreamsParams, CountDiscoverableStreams, GetDiscoverableStreamsPage, - LegacyGetStreams + LegacyGetStreams, + GetFavoritedStreamsPage, + GetFavoritedStreamsCount } from '@/modules/core/domain/streams/operations' export type { StreamWithOptionalRole, StreamWithCommitId } const tables = { streams: (db: Knex) => db(Streams.name), streamAcl: (db: Knex) => db(StreamAcl.name), - streamCommits: (db: Knex) => db(StreamCommits.name) + streamCommits: (db: Knex) => db(StreamCommits.name), + streamFavorites: (db: Knex) => db(StreamFavorites.name) } /** @@ -256,32 +259,32 @@ export const getCommitStreamFactory = * Get base query for finding or counting user favorited streams * @param {string} userId The user's ID */ -function getFavoritedStreamsQueryBase< - Result = Array ->(userId: string, streamIdWhitelist?: Optional) { - if (!userId) - throw new InvalidArgumentError( - 'User ID must be specified to retrieve favorited streams' - ) +const getFavoritedStreamsQueryBaseFactory = + (deps: { db: Knex }) => (userId: string, streamIdWhitelist?: Optional) => { + if (!userId) + throw new InvalidArgumentError( + 'User ID must be specified to retrieve favorited streams' + ) - const query = StreamFavorites.knex() - .where(StreamFavorites.col.userId, userId) - .innerJoin(Streams.name, Streams.col.id, StreamFavorites.col.streamId) - .leftJoin(StreamAcl.name, (q) => - q - .on(StreamAcl.col.resourceId, '=', StreamFavorites.col.streamId) - .andOnVal(StreamAcl.col.userId, userId) - ) - .andWhere((q) => - q.where(Streams.col.isPublic, true).orWhereNotNull(StreamAcl.col.resourceId) - ) + const query = tables + .streamFavorites(deps.db) + .where(StreamFavorites.col.userId, userId) + .innerJoin(Streams.name, Streams.col.id, StreamFavorites.col.streamId) + .leftJoin(StreamAcl.name, (q) => + q + .on(StreamAcl.col.resourceId, '=', StreamFavorites.col.streamId) + .andOnVal(StreamAcl.col.userId, userId) + ) + .andWhere((q) => + q.where(Streams.col.isPublic, true).orWhereNotNull(StreamAcl.col.resourceId) + ) - if (streamIdWhitelist?.length) { - query.whereIn(Streams.col.id, streamIdWhitelist) - } + if (streamIdWhitelist?.length) { + query.whereIn(Streams.col.id, streamIdWhitelist) + } - return query -} + return query + } /** * Get favorited streams @@ -290,52 +293,45 @@ function getFavoritedStreamsQueryBase< * @param {string} [p.cursor] ISO8601 timestamp after which to look for favoirtes * @param {number} [p.limit] Defaults to 25 */ -export async function getFavoritedStreams(params: { - userId: string - cursor?: string - limit?: number - streamIdWhitelist?: Optional -}) { - const { userId, cursor, limit, streamIdWhitelist } = params - const finalLimit = _.clamp(limit || 25, 1, 25) - const query = getFavoritedStreamsQueryBase< - Array - >(userId, streamIdWhitelist) - query - .select([ - ...STREAM_WITH_OPTIONAL_ROLE_COLUMNS, - { favoritedDate: StreamFavorites.col.createdAt }, - { favCursor: StreamFavorites.col.cursor } - ]) - .limit(finalLimit) - .orderBy(StreamFavorites.col.cursor, 'desc') +export const getFavoritedStreamsPageFactory = + (deps: { db: Knex }): GetFavoritedStreamsPage => + async (params) => { + const { userId, cursor, limit, streamIdWhitelist } = params + const finalLimit = _.clamp(limit || 25, 1, 25) + const query = getFavoritedStreamsQueryBaseFactory(deps)(userId, streamIdWhitelist) + query + .select< + Array + >([ + ...STREAM_WITH_OPTIONAL_ROLE_COLUMNS, + { favoritedDate: StreamFavorites.col.createdAt }, + { favCursor: StreamFavorites.col.cursor } + ]) + .limit(finalLimit) + .orderBy(StreamFavorites.col.cursor, 'desc') - if (cursor) query.andWhere(StreamFavorites.col.cursor, '<', cursor) + if (cursor) query.andWhere(StreamFavorites.col.cursor, '<', cursor) - const rows = await query + const rows = await query - return { - streams: rows, - cursor: rows.length > 0 ? rows[rows.length - 1].favCursor : null + return { + streams: rows, + cursor: rows.length > 0 ? rows[rows.length - 1].favCursor : null + } } -} /** * Get total amount of streams favorited by user */ -export async function getFavoritedStreamsCount( - userId: string, - streamIdWhitelist?: Optional -) { - const query = getFavoritedStreamsQueryBase<[{ count: string }]>( - userId, - streamIdWhitelist - ) - query.count() +export const getFavoritedStreamsCountFactory = + (deps: { db: Knex }): GetFavoritedStreamsCount => + async (userId: string, streamIdWhitelist?: Optional) => { + const query = getFavoritedStreamsQueryBaseFactory(deps)(userId, streamIdWhitelist) + query.count() - const [res] = await query - return parseInt(res.count) -} + const [res] = await query + return parseInt(res.count) + } /** * Set stream as favorited/unfavorited for a specific user diff --git a/packages/server/modules/core/services/streams.js b/packages/server/modules/core/services/streams.js index a1824d7995..40ddc621bb 100644 --- a/packages/server/modules/core/services/streams.js +++ b/packages/server/modules/core/services/streams.js @@ -1,9 +1,5 @@ -'use strict' -const _ = require('lodash') const { StreamAcl, knex } = require('@/modules/core/dbSchema') const { - getFavoritedStreams, - getFavoritedStreamsCount, setStreamFavorited, canUserFavoriteStream, getStreamFactory @@ -71,32 +67,6 @@ module.exports = { return await getStream({ streamId, userId }) }, - /** - * Get user favorited streams & metadata - * @param {Object} p - * @param {string} p.userId - * @param {number} [p.limit] Defaults to 25 - * @param {string|null} [p.cursor] Optionally specify date after which to look for favorites - * @param {string[] | undefined} [p.streamIdWhitelist] Optionally specify a list of stream IDs to filter by - * @returns - */ - async getFavoriteStreamsCollection({ userId, limit, cursor, streamIdWhitelist }) { - limit = _.clamp(limit || 25, 1, 25) - - // Get total count of favorited streams - const totalCount = await getFavoritedStreamsCount(userId, streamIdWhitelist) - - // Get paginated streams - const { cursor: finalCursor, streams } = await getFavoritedStreams({ - userId, - cursor, - limit, - streamIdWhitelist - }) - - return { totalCount, cursor: finalCursor, items: streams } - }, - /** * Get active user stream favorite date (using dataloader) * @param {Object} p diff --git a/packages/server/modules/core/services/streams/favorite.ts b/packages/server/modules/core/services/streams/favorite.ts new file mode 100644 index 0000000000..8d61d10637 --- /dev/null +++ b/packages/server/modules/core/services/streams/favorite.ts @@ -0,0 +1,37 @@ +import { + GetFavoritedStreamsCount, + GetFavoritedStreamsPage, + GetFavoriteStreamsCollection +} from '@/modules/core/domain/streams/operations' +import { clamp } from 'lodash' + +/** + * Get user favorited streams & metadata + * @param {Object} p + * @param {string} p.userId + * @param {number} [p.limit] Defaults to 25 + * @param {string|null} [p.cursor] Optionally specify date after which to look for favorites + * @param {string[] | undefined} [p.streamIdWhitelist] Optionally specify a list of stream IDs to filter by + * @returns + */ +export const getFavoriteStreamsCollectionFactory = + (deps: { + getFavoritedStreamsCount: GetFavoritedStreamsCount + getFavoritedStreamsPage: GetFavoritedStreamsPage + }): GetFavoriteStreamsCollection => + async ({ userId, limit, cursor, streamIdWhitelist }) => { + limit = clamp(limit || 25, 1, 25) + + // Get total count of favorited streams + const totalCount = await deps.getFavoritedStreamsCount(userId, streamIdWhitelist) + + // Get paginated streams + const { cursor: finalCursor, streams } = await deps.getFavoritedStreamsPage({ + userId, + cursor, + limit, + streamIdWhitelist + }) + + return { totalCount, cursor: finalCursor, items: streams } + }