@drodil/backstage-plugin-qeta-backend 3.55.0 → 3.55.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"statistics.cjs.js","sources":["../../../src/service/routes/statistics.ts"],"sourcesContent":["import { Router } from 'express';\nimport { stringDateTime } from '../util';\nimport {\n Statistic,\n StatisticResponse,\n StatisticsOptions,\n} from '@drodil/backstage-plugin-qeta-common';\nimport { RouteOptions } from '../types';\n\nexport const statisticRoutes = (router: Router, options: RouteOptions) => {\n const { database, permissionMgr } = options;\n\n const getSummary = async (user_ref?: string) => {\n const results = await Promise.all([\n database.getCount('posts', { author: user_ref, type: 'question' }),\n database.getCount('answers', { author: user_ref }),\n user_ref\n ? database.getTotalViews(user_ref)\n : database.getCount('post_views'),\n database.getCount('comments', { author: user_ref }),\n database.getCount('post_votes', { author: user_ref }),\n database.getCount('answer_votes', { author: user_ref }),\n database.getCount('posts', { author: user_ref, type: 'article' }),\n !user_ref ? database.getUsersCount() : undefined,\n !user_ref ? database.getCount('tags') : undefined,\n database.getCount('posts', { author: user_ref, type: 'link' }),\n ]);\n return {\n totalQuestions: results[0],\n totalAnswers: results[1],\n totalViews: results[2],\n totalComments: results[3],\n totalVotes: results[4] + results[5],\n totalArticles: results[6],\n totalUsers: results[7],\n totalTags: results[8],\n totalLinks: results[9],\n };\n };\n\n router.get('/statistics/user/impact', async (request, response) => {\n const userRef = await permissionMgr.getUsername(request);\n const userImpact = await database.getTotalViews(userRef, undefined, true);\n const userImpactWeek = await database.getTotalViews(userRef, 7, true);\n return response\n .status(200)\n .json({ impact: userImpact, lastWeekImpact: userImpactWeek });\n });\n\n router.get('/statistics/global', async (_req, response) => {\n const globalStats = await database.getGlobalStats();\n let summary = await getSummary();\n if (!summary) {\n summary = {\n totalAnswers: 0,\n totalArticles: 0,\n totalLinks: 0,\n totalComments: 0,\n totalQuestions: 0,\n totalViews: 0,\n totalVotes: 0,\n totalTags: 0,\n totalUsers: 0,\n };\n }\n let todayStatsAdded = false;\n const statistics = globalStats.map(g => {\n const d = new Date(g.date);\n if (d.toDateString() !== new Date().toDateString()) {\n return g;\n }\n todayStatsAdded = true;\n return {\n date: d,\n ...summary,\n };\n });\n\n if (!todayStatsAdded) {\n statistics.push({ date: new Date(), ...summary });\n }\n\n return response.status(200).json({ statistics, summary });\n });\n\n router.get('/statistics/user/:userRef(*)', async (req, response) => {\n const userRef = req.params.userRef;\n const userStats = await database.getUserStats(userRef);\n let summary = await database.getUser(userRef);\n let todayStatsAdded = false;\n const statistics = userStats.map(g => {\n const d = new Date(g.date);\n if (!summary || d.toDateString() !== new Date().toDateString()) {\n return g;\n }\n todayStatsAdded = true;\n return {\n date: d,\n ...summary,\n };\n });\n\n if (!todayStatsAdded) {\n if (!summary) {\n summary = {\n userRef: userRef,\n totalViews: 0,\n totalQuestions: 0,\n totalAnswers: 0,\n totalComments: 0,\n totalVotes: 0,\n totalArticles: 0,\n totalFollowers: 0,\n totalLinks: 0,\n reputation: 0,\n answerScore: 0,\n postScore: 0,\n correctAnswers: 0,\n };\n }\n\n if (userStats.length === 0) {\n statistics.push({ date: new Date(), ...summary });\n }\n }\n\n return response.status(200).json({ statistics, summary });\n });\n\n // GET /statistics/posts/top-upvoted-users?period=x&limit=x\n router.get(\n '/statistics/posts/top-upvoted-users',\n async (request, response) => {\n const { period, limit } = request.query;\n const userRef = await permissionMgr.getUsername(request);\n\n const statsOptions: StatisticsOptions = {\n period: period && stringDateTime(period?.toString()),\n limit: Number(limit),\n type: 'question',\n };\n\n const mostUpvotedQuestions: Statistic[] =\n await database.getMostUpvotedPosts({\n options: statsOptions,\n });\n\n const rankingResponse = {\n ranking: mostUpvotedQuestions,\n loggedUser: {},\n } as StatisticResponse;\n\n const findLoggerUserInData = mostUpvotedQuestions.find(userStats => {\n return userStats.author === userRef;\n });\n\n if (!findLoggerUserInData) {\n const loggedUserUpvotedQuestions = await database.getMostUpvotedPosts({\n author: userRef,\n options: statsOptions,\n });\n\n if (loggedUserUpvotedQuestions) {\n rankingResponse.loggedUser!.author =\n loggedUserUpvotedQuestions.length > 0\n ? loggedUserUpvotedQuestions[0].author\n : userRef;\n\n rankingResponse.loggedUser!.total =\n loggedUserUpvotedQuestions.length > 0\n ? loggedUserUpvotedQuestions[0].total\n : 0;\n\n rankingResponse.loggedUser!.position =\n mostUpvotedQuestions.length === 1\n ? 0\n : mostUpvotedQuestions.length + 1;\n }\n } else {\n rankingResponse.loggedUser = findLoggerUserInData;\n }\n\n return response.status(200).json(rankingResponse);\n },\n );\n\n // GET /statistics/answers/top-upvoted-users?period=x&limit=x\n router.get(\n '/statistics/answers/top-upvoted-users',\n async (request, response) => {\n const { period, limit } = request.query;\n const userRef = await permissionMgr.getUsername(request);\n\n const statsOptions: StatisticsOptions = {\n period: period && stringDateTime(period?.toString()),\n limit: Number(limit),\n };\n\n const mostUpvotedAnswers: Statistic[] =\n await database.getMostUpvotedAnswers({\n options: statsOptions,\n });\n\n const rankingResponse = {\n ranking: mostUpvotedAnswers,\n loggedUser: {},\n } as StatisticResponse;\n\n const findLoggerUserInData = mostUpvotedAnswers.find(userStats => {\n return userStats.author === userRef;\n });\n\n if (!findLoggerUserInData) {\n const loggedUserUpvotedAnswers = await database.getMostUpvotedAnswers({\n author: userRef,\n options: statsOptions,\n });\n\n if (loggedUserUpvotedAnswers) {\n rankingResponse.loggedUser!.author =\n loggedUserUpvotedAnswers.length > 0\n ? loggedUserUpvotedAnswers[0].author\n : userRef;\n\n rankingResponse.loggedUser!.total =\n loggedUserUpvotedAnswers.length > 0\n ? loggedUserUpvotedAnswers[0].total\n : 0;\n\n rankingResponse.loggedUser!.position =\n mostUpvotedAnswers.length === 1 ? 0 : mostUpvotedAnswers.length + 1;\n }\n } else {\n rankingResponse.loggedUser = findLoggerUserInData;\n }\n\n return response.status(200).json(rankingResponse);\n },\n );\n\n // GET /statistics/answers/top-correct-upvoted-users?period=x&limit=x\n router.get(\n '/statistics/answers/top-correct-upvoted-users',\n async (request, response) => {\n const { period, limit } = request.query;\n const userRef = await permissionMgr.getUsername(request);\n\n const statsOptions: StatisticsOptions = {\n period: period && stringDateTime(period?.toString()),\n limit: Number(limit),\n };\n\n const mostUpvotedCorrectAnswers: Statistic[] =\n await database.getMostUpvotedCorrectAnswers({\n options: statsOptions,\n });\n\n const rankingResponse = {\n ranking: mostUpvotedCorrectAnswers,\n loggedUser: {},\n } as StatisticResponse;\n\n const findLoggerUserInData = mostUpvotedCorrectAnswers.find(userStats => {\n return userStats.author === userRef;\n });\n\n if (!findLoggerUserInData) {\n const loggedUserUpvotedCorrectAnswers =\n await database.getMostUpvotedCorrectAnswers({\n author: userRef,\n options: statsOptions,\n });\n\n if (loggedUserUpvotedCorrectAnswers) {\n rankingResponse.loggedUser!.author =\n loggedUserUpvotedCorrectAnswers.length > 0\n ? loggedUserUpvotedCorrectAnswers[0].author\n : userRef;\n\n rankingResponse.loggedUser!.total =\n loggedUserUpvotedCorrectAnswers.length > 0\n ? loggedUserUpvotedCorrectAnswers[0].total\n : 0;\n\n rankingResponse.loggedUser!.position =\n mostUpvotedCorrectAnswers.length === 1\n ? 0\n : mostUpvotedCorrectAnswers.length + 1;\n }\n } else {\n rankingResponse.loggedUser = findLoggerUserInData;\n }\n\n return response.status(200).json(rankingResponse);\n },\n );\n\n // GET /statistics/posts/most-questions?period=x&limit=x\n router.get('/statistics/posts/most-questions', async (request, response) => {\n const { period, limit } = request.query;\n const userRef = await permissionMgr.getUsername(request);\n\n const statsOptions: StatisticsOptions = {\n period: period && stringDateTime(period?.toString()),\n limit: Number(limit),\n type: 'question',\n };\n\n const mostQuestions: Statistic[] = await database.getTotalPosts({\n options: statsOptions,\n });\n\n const rankingResponse = {\n ranking: mostQuestions,\n loggedUser: {},\n } as StatisticResponse;\n\n const findLoggerUserInData = mostQuestions.find(userStats => {\n return userStats.author === userRef;\n });\n\n if (!findLoggerUserInData) {\n const loggedUserQuestions = await database.getTotalPosts({\n author: userRef,\n options: statsOptions,\n });\n\n if (loggedUserQuestions) {\n rankingResponse.loggedUser!.author =\n loggedUserQuestions.length > 0\n ? loggedUserQuestions[0].author\n : userRef;\n\n rankingResponse.loggedUser!.total =\n loggedUserQuestions.length > 0 ? loggedUserQuestions[0].total : 0;\n\n rankingResponse.loggedUser!.position =\n mostQuestions.length === 1 ? 0 : mostQuestions.length + 1;\n }\n } else {\n rankingResponse.loggedUser = findLoggerUserInData;\n }\n\n return response.status(200).json(rankingResponse);\n });\n\n // GET /statistics/answers/most-answers?period=x&limit=x\n router.get('/statistics/answers/most-answers', async (request, response) => {\n const { period, limit } = request.query;\n const userRef = await permissionMgr.getUsername(request);\n\n const statsOptions: StatisticsOptions = {\n period: period && stringDateTime(period?.toString()),\n limit: Number(limit),\n };\n\n const mostAnswers: Statistic[] = await database.getTotalAnswers({\n options: statsOptions,\n });\n\n const rankingResponse = {\n ranking: mostAnswers,\n loggedUser: {},\n } as StatisticResponse;\n\n const findLoggerUserInData = mostAnswers.find(userStats => {\n return userStats.author === userRef;\n });\n\n if (!findLoggerUserInData) {\n const loggedUserQuestions = await database.getTotalAnswers({\n author: userRef,\n options: statsOptions,\n });\n\n if (loggedUserQuestions) {\n rankingResponse.loggedUser!.author =\n loggedUserQuestions.length > 0\n ? loggedUserQuestions[0].author\n : userRef;\n\n rankingResponse.loggedUser!.total =\n loggedUserQuestions.length > 0 ? loggedUserQuestions[0].total : 0;\n\n rankingResponse.loggedUser!.position =\n mostAnswers.length === 1 ? 0 : mostAnswers.length + 1;\n }\n } else {\n rankingResponse.loggedUser = findLoggerUserInData;\n }\n\n return response.status(200).json(rankingResponse);\n });\n};\n"],"names":["stringDateTime"],"mappings":"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"}
1
+ {"version":3,"file":"statistics.cjs.js","sources":["../../../src/service/routes/statistics.ts"],"sourcesContent":["import { Router } from 'express';\nimport { stringDateTime } from '../util';\nimport { getCachedData } from './routeUtil';\nimport {\n Statistic,\n StatisticResponse,\n StatisticsOptions,\n} from '@drodil/backstage-plugin-qeta-common';\nimport { RouteOptions } from '../types';\n\nexport const statisticRoutes = (router: Router, options: RouteOptions) => {\n const { database, permissionMgr } = options;\n\n const getSummary = async (user_ref?: string) => {\n const results = await Promise.all([\n database.getCount('posts', { author: user_ref, type: 'question' }),\n database.getCount('answers', { author: user_ref }),\n user_ref\n ? database.getTotalViews(user_ref)\n : database.getCount('post_views'),\n database.getCount('comments', { author: user_ref }),\n database.getCount('post_votes', { author: user_ref }),\n database.getCount('answer_votes', { author: user_ref }),\n database.getCount('posts', { author: user_ref, type: 'article' }),\n !user_ref ? database.getUsersCount() : undefined,\n !user_ref ? database.getCount('tags') : undefined,\n database.getCount('posts', { author: user_ref, type: 'link' }),\n ]);\n return {\n totalQuestions: results[0],\n totalAnswers: results[1],\n totalViews: results[2],\n totalComments: results[3],\n totalVotes: results[4] + results[5],\n totalArticles: results[6],\n totalUsers: results[7],\n totalTags: results[8],\n totalLinks: results[9],\n };\n };\n\n router.get('/statistics/user/impact', async (request, response) => {\n const userRef = await permissionMgr.getUsername(request);\n const key = `qeta:statistics:impact:${userRef}`;\n const ttl = 300 * 1000;\n\n const impact = await getCachedData(\n options.cache,\n key,\n ttl,\n async () => {\n const userImpact = await database.getTotalViews(\n userRef,\n undefined,\n true,\n );\n const userImpactWeek = await database.getTotalViews(userRef, 7, true);\n return { impact: userImpact, lastWeekImpact: userImpactWeek };\n },\n options.logger,\n );\n\n return response.status(200).json(impact);\n });\n\n router.get('/statistics/global', async (_req, response) => {\n const key = 'qeta:statistics:global';\n const ttl = 3600 * 1000;\n\n const data = await getCachedData(\n options.cache,\n key,\n ttl,\n async () => {\n const globalStats = await database.getGlobalStats();\n let summary = await getSummary();\n if (!summary) {\n summary = {\n totalAnswers: 0,\n totalArticles: 0,\n totalLinks: 0,\n totalComments: 0,\n totalQuestions: 0,\n totalViews: 0,\n totalVotes: 0,\n totalTags: 0,\n totalUsers: 0,\n };\n }\n let todayStatsAdded = false;\n const statistics = globalStats.map(g => {\n const d = new Date(g.date);\n if (d.toDateString() !== new Date().toDateString()) {\n return g;\n }\n todayStatsAdded = true;\n return {\n date: d,\n ...summary!,\n };\n });\n\n if (!todayStatsAdded) {\n statistics.push({ date: new Date(), ...summary! });\n }\n return { statistics, summary };\n },\n options.logger,\n );\n return response.json(data);\n });\n\n router.get('/statistics/user/:userRef(*)', async (req, response) => {\n const userRef = req.params.userRef;\n const key = `qeta:statistics:user:${userRef}`;\n const ttl = 3600 * 1000;\n\n const data = await getCachedData(\n options.cache,\n key,\n ttl,\n async () => {\n const userStats = await database.getUserStats(userRef);\n let summary = await database.getUser(userRef);\n let todayStatsAdded = false;\n const statistics = userStats.map(g => {\n const d = new Date(g.date);\n if (!summary || d.toDateString() !== new Date().toDateString()) {\n return g;\n }\n todayStatsAdded = true;\n return {\n date: d,\n ...summary,\n };\n });\n\n if (!todayStatsAdded) {\n if (!summary) {\n summary = {\n userRef: userRef,\n totalViews: 0,\n totalQuestions: 0,\n totalAnswers: 0,\n totalComments: 0,\n totalVotes: 0,\n totalArticles: 0,\n totalFollowers: 0,\n totalLinks: 0,\n reputation: 0,\n answerScore: 0,\n postScore: 0,\n correctAnswers: 0,\n };\n }\n\n if (userStats.length === 0) {\n statistics.push({ date: new Date(), ...summary });\n }\n }\n return { statistics, summary };\n },\n options.logger,\n );\n\n return response.status(200).json(data);\n });\n\n // GET /statistics/posts/top-upvoted-users?period=x&limit=x\n router.get(\n '/statistics/posts/top-upvoted-users',\n async (request, response) => {\n const { period, limit } = request.query;\n const userRef = await permissionMgr.getUsername(request);\n\n const statsOptions: StatisticsOptions = {\n period: period && stringDateTime(period?.toString()),\n limit: Number(limit),\n type: 'question',\n };\n\n const mostUpvotedQuestions: Statistic[] =\n await database.getMostUpvotedPosts({\n options: statsOptions,\n });\n\n const rankingResponse = {\n ranking: mostUpvotedQuestions,\n loggedUser: {},\n } as StatisticResponse;\n\n const findLoggerUserInData = mostUpvotedQuestions.find(userStats => {\n return userStats.author === userRef;\n });\n\n if (!findLoggerUserInData) {\n const loggedUserUpvotedQuestions = await database.getMostUpvotedPosts({\n author: userRef,\n options: statsOptions,\n });\n\n if (loggedUserUpvotedQuestions) {\n rankingResponse.loggedUser!.author =\n loggedUserUpvotedQuestions.length > 0\n ? loggedUserUpvotedQuestions[0].author\n : userRef;\n\n rankingResponse.loggedUser!.total =\n loggedUserUpvotedQuestions.length > 0\n ? loggedUserUpvotedQuestions[0].total\n : 0;\n\n rankingResponse.loggedUser!.position =\n mostUpvotedQuestions.length === 1\n ? 0\n : mostUpvotedQuestions.length + 1;\n }\n } else {\n rankingResponse.loggedUser = findLoggerUserInData;\n }\n\n return response.status(200).json(rankingResponse);\n },\n );\n\n // GET /statistics/answers/top-upvoted-users?period=x&limit=x\n router.get(\n '/statistics/answers/top-upvoted-users',\n async (request, response) => {\n const { period, limit } = request.query;\n const userRef = await permissionMgr.getUsername(request);\n\n const statsOptions: StatisticsOptions = {\n period: period && stringDateTime(period?.toString()),\n limit: Number(limit),\n };\n\n const mostUpvotedAnswers: Statistic[] =\n await database.getMostUpvotedAnswers({\n options: statsOptions,\n });\n\n const rankingResponse = {\n ranking: mostUpvotedAnswers,\n loggedUser: {},\n } as StatisticResponse;\n\n const findLoggerUserInData = mostUpvotedAnswers.find(userStats => {\n return userStats.author === userRef;\n });\n\n if (!findLoggerUserInData) {\n const loggedUserUpvotedAnswers = await database.getMostUpvotedAnswers({\n author: userRef,\n options: statsOptions,\n });\n\n if (loggedUserUpvotedAnswers) {\n rankingResponse.loggedUser!.author =\n loggedUserUpvotedAnswers.length > 0\n ? loggedUserUpvotedAnswers[0].author\n : userRef;\n\n rankingResponse.loggedUser!.total =\n loggedUserUpvotedAnswers.length > 0\n ? loggedUserUpvotedAnswers[0].total\n : 0;\n\n rankingResponse.loggedUser!.position =\n mostUpvotedAnswers.length === 1 ? 0 : mostUpvotedAnswers.length + 1;\n }\n } else {\n rankingResponse.loggedUser = findLoggerUserInData;\n }\n\n return response.status(200).json(rankingResponse);\n },\n );\n\n // GET /statistics/answers/top-correct-upvoted-users?period=x&limit=x\n router.get(\n '/statistics/answers/top-correct-upvoted-users',\n async (request, response) => {\n const { period, limit } = request.query;\n const userRef = await permissionMgr.getUsername(request);\n\n const statsOptions: StatisticsOptions = {\n period: period && stringDateTime(period?.toString()),\n limit: Number(limit),\n };\n\n const mostUpvotedCorrectAnswers: Statistic[] =\n await database.getMostUpvotedCorrectAnswers({\n options: statsOptions,\n });\n\n const rankingResponse = {\n ranking: mostUpvotedCorrectAnswers,\n loggedUser: {},\n } as StatisticResponse;\n\n const findLoggerUserInData = mostUpvotedCorrectAnswers.find(userStats => {\n return userStats.author === userRef;\n });\n\n if (!findLoggerUserInData) {\n const loggedUserUpvotedCorrectAnswers =\n await database.getMostUpvotedCorrectAnswers({\n author: userRef,\n options: statsOptions,\n });\n\n if (loggedUserUpvotedCorrectAnswers) {\n rankingResponse.loggedUser!.author =\n loggedUserUpvotedCorrectAnswers.length > 0\n ? loggedUserUpvotedCorrectAnswers[0].author\n : userRef;\n\n rankingResponse.loggedUser!.total =\n loggedUserUpvotedCorrectAnswers.length > 0\n ? loggedUserUpvotedCorrectAnswers[0].total\n : 0;\n\n rankingResponse.loggedUser!.position =\n mostUpvotedCorrectAnswers.length === 1\n ? 0\n : mostUpvotedCorrectAnswers.length + 1;\n }\n } else {\n rankingResponse.loggedUser = findLoggerUserInData;\n }\n\n return response.status(200).json(rankingResponse);\n },\n );\n\n // GET /statistics/posts/most-questions?period=x&limit=x\n router.get('/statistics/posts/most-questions', async (request, response) => {\n const { period, limit } = request.query;\n const userRef = await permissionMgr.getUsername(request);\n\n const statsOptions: StatisticsOptions = {\n period: period && stringDateTime(period?.toString()),\n limit: Number(limit),\n type: 'question',\n };\n\n const mostQuestions: Statistic[] = await database.getTotalPosts({\n options: statsOptions,\n });\n\n const rankingResponse = {\n ranking: mostQuestions,\n loggedUser: {},\n } as StatisticResponse;\n\n const findLoggerUserInData = mostQuestions.find(userStats => {\n return userStats.author === userRef;\n });\n\n if (!findLoggerUserInData) {\n const loggedUserQuestions = await database.getTotalPosts({\n author: userRef,\n options: statsOptions,\n });\n\n if (loggedUserQuestions) {\n rankingResponse.loggedUser!.author =\n loggedUserQuestions.length > 0\n ? loggedUserQuestions[0].author\n : userRef;\n\n rankingResponse.loggedUser!.total =\n loggedUserQuestions.length > 0 ? loggedUserQuestions[0].total : 0;\n\n rankingResponse.loggedUser!.position =\n mostQuestions.length === 1 ? 0 : mostQuestions.length + 1;\n }\n } else {\n rankingResponse.loggedUser = findLoggerUserInData;\n }\n\n return response.status(200).json(rankingResponse);\n });\n\n // GET /statistics/answers/most-answers?period=x&limit=x\n router.get('/statistics/answers/most-answers', async (request, response) => {\n const { period, limit } = request.query;\n const userRef = await permissionMgr.getUsername(request);\n\n const statsOptions: StatisticsOptions = {\n period: period && stringDateTime(period?.toString()),\n limit: Number(limit),\n };\n\n const mostAnswers: Statistic[] = await database.getTotalAnswers({\n options: statsOptions,\n });\n\n const rankingResponse = {\n ranking: mostAnswers,\n loggedUser: {},\n } as StatisticResponse;\n\n const findLoggerUserInData = mostAnswers.find(userStats => {\n return userStats.author === userRef;\n });\n\n if (!findLoggerUserInData) {\n const loggedUserQuestions = await database.getTotalAnswers({\n author: userRef,\n options: statsOptions,\n });\n\n if (loggedUserQuestions) {\n rankingResponse.loggedUser!.author =\n loggedUserQuestions.length > 0\n ? loggedUserQuestions[0].author\n : userRef;\n\n rankingResponse.loggedUser!.total =\n loggedUserQuestions.length > 0 ? loggedUserQuestions[0].total : 0;\n\n rankingResponse.loggedUser!.position =\n mostAnswers.length === 1 ? 0 : mostAnswers.length + 1;\n }\n } else {\n rankingResponse.loggedUser = findLoggerUserInData;\n }\n\n return response.status(200).json(rankingResponse);\n });\n};\n"],"names":["getCachedData","stringDateTime"],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var types$1 = require('../types.cjs.js');
4
+ var routeUtil = require('./routeUtil.cjs.js');
4
5
  var backstagePluginQetaCommon = require('@drodil/backstage-plugin-qeta-common');
5
6
  var Ajv = require('ajv');
6
7
  var addFormats = require('ajv-formats');
@@ -295,25 +296,7 @@ const suggestionRoutes = (router, options) => {
295
296
  post
296
297
  }));
297
298
  };
298
- router.get("/suggestions", async (request, response) => {
299
- const validateQuery = ajv.compile(types$1.SuggestionsQuerySchema);
300
- if (!validateQuery(request.query)) {
301
- response.status(400).send({ errors: validateQuery.errors, type: "query" });
302
- return;
303
- }
304
- const username = await permissionMgr.getUsername(request, false);
305
- let limit = Number(request.query.limit);
306
- if (isNaN(limit)) {
307
- limit = 5;
308
- }
309
- const filter = await permissionMgr.getAuthorizeConditions(
310
- request,
311
- backstagePluginQetaCommon.qetaReadPostPermission
312
- );
313
- const canReviewResults = await permissionMgr.authorizeBoolean(request, [
314
- { permission: backstagePluginQetaCommon.qetaCreatePostReviewPermission }
315
- ]);
316
- const canReview = canReviewResults[0] ?? false;
299
+ const getSuggestions = async (username, limit, filter, canReview) => {
317
300
  const promises = [
318
301
  getNotCorrectQuestions(username, filter),
319
302
  getNewTagQuestions(username, filter),
@@ -338,7 +321,38 @@ const suggestionRoutes = (router, options) => {
338
321
  if (suggestionsRaw.length < limit) {
339
322
  suggestionsRaw.push(...await getRandomPosts(username, limit, filter));
340
323
  }
341
- const suggestions = suggestionsRaw.sort(() => 0.5 - Math.random()).slice(0, limit);
324
+ return suggestionsRaw.sort(() => 0.5 - Math.random()).slice(0, limit);
325
+ };
326
+ router.get("/suggestions", async (request, response) => {
327
+ const validateQuery = ajv.compile(types$1.SuggestionsQuerySchema);
328
+ if (!validateQuery(request.query)) {
329
+ response.status(400).send({ errors: validateQuery.errors, type: "query" });
330
+ return;
331
+ }
332
+ const username = await permissionMgr.getUsername(request, false);
333
+ let limit = Number(request.query.limit);
334
+ if (isNaN(limit)) {
335
+ limit = 5;
336
+ }
337
+ const filter = await permissionMgr.getAuthorizeConditions(
338
+ request,
339
+ backstagePluginQetaCommon.qetaReadPostPermission
340
+ );
341
+ const canReviewResults = await permissionMgr.authorizeBoolean(request, [
342
+ { permission: backstagePluginQetaCommon.qetaCreatePostReviewPermission }
343
+ ]);
344
+ const canReview = canReviewResults[0] ?? false;
345
+ const key = `qeta:suggestions:${username}:${limit}`;
346
+ const ttl = 3600 * 1e3;
347
+ const suggestions = await routeUtil.getCachedData(
348
+ options.cache,
349
+ key,
350
+ ttl,
351
+ async () => {
352
+ return await getSuggestions(username, limit, filter, canReview);
353
+ },
354
+ options.logger
355
+ );
342
356
  response.json({ suggestions });
343
357
  });
344
358
  };
@@ -1 +1 @@
1
- {"version":3,"file":"suggestions.cjs.js","sources":["../../../src/service/routes/suggestions.ts"],"sourcesContent":["import { Router } from 'express';\nimport { RouteOptions, SuggestionsQuerySchema } from '../types';\nimport { QetaFilters } from '../util';\nimport {\n Article,\n DraftPostSuggestion,\n Link,\n NeedsReviewSuggestion,\n NewArticleSuggestion,\n NewLinkSuggestion,\n NewQuestionSuggestion,\n NoCorrectAnswerSuggestion,\n qetaCreatePostReviewPermission,\n qetaReadPostPermission,\n Question,\n RandomPostSuggestion,\n Suggestion,\n} from '@drodil/backstage-plugin-qeta-common';\nimport Ajv from 'ajv';\nimport addFormats from 'ajv-formats';\nimport { PostOptions } from '../../database/QetaStore';\nimport { PermissionCriteria } from '@backstage/plugin-permission-common';\nimport { durationToMilliseconds, HumanDuration } from '@backstage/types';\n\nconst ajv = new Ajv({ coerceTypes: 'array' });\naddFormats(ajv);\n\nexport const suggestionRoutes = (router: Router, options: RouteOptions) => {\n const { database, permissionMgr, config } = options;\n\n const postsOlderThan = config.getOptional<HumanDuration>(\n 'qeta.contentHealth.postsOlderThan',\n ) ?? { months: 6 };\n const reviewThresholdMs = durationToMilliseconds(postsOlderThan);\n\n const includeNothingOptions: PostOptions = {\n includeVotes: false,\n includeTags: false,\n includeComments: false,\n includeEntities: false,\n includeAnswers: false,\n includeAttachments: false,\n };\n\n const getFromDate = (days: number = 7) => {\n const date = new Date(Date.now() - 1000 * 60 * 60 * 24 * days);\n return date.toISOString().split('T')[0];\n };\n\n const getNotCorrectQuestions = async (\n username: string,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<NoCorrectAnswerSuggestion[]> => {\n const questions = await database.getPosts(\n username,\n {\n author: username,\n hasAnswers: true,\n noCorrectAnswer: true,\n type: 'question',\n },\n filter,\n includeNothingOptions,\n );\n\n return questions.posts.map(question => ({\n id: `noq_${question.id}`,\n type: 'noCorrectAnswer',\n question: question as Question,\n }));\n };\n\n const getNewTagQuestions = async (\n username: string,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<NewQuestionSuggestion[]> => {\n const userTags = await database.getUserTags(username);\n if (userTags.tags.length === 0) {\n return [];\n }\n const questions = await database.getPosts(\n username,\n {\n tags: userTags.tags,\n tagsRelation: 'or',\n type: 'question',\n fromDate: getFromDate(),\n excludeAuthors: [username],\n },\n filter,\n includeNothingOptions,\n );\n return questions.posts.map(question => ({\n id: `q_${question.id}`,\n type: 'newQuestion',\n question: question as Question,\n }));\n };\n\n const getNewEntityQuestions = async (\n username: string,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<NewQuestionSuggestion[]> => {\n const userEntities = await database.getUserEntities(username);\n if (userEntities.entityRefs.length === 0) {\n return [];\n }\n const questions = await database.getPosts(\n username,\n {\n entities: userEntities.entityRefs,\n entitiesRelation: 'or',\n type: 'question',\n fromDate: getFromDate(),\n excludeAuthors: [username],\n },\n filter,\n includeNothingOptions,\n );\n return questions.posts.map(question => ({\n id: `q_${question.id}`,\n type: 'newQuestion',\n question: question as Question,\n }));\n };\n\n const getNewTagArticles = async (\n username: string,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<NewArticleSuggestion[]> => {\n const userTags = await database.getUserTags(username);\n if (userTags.tags.length === 0) {\n return [];\n }\n const articles = await database.getPosts(\n username,\n {\n tags: userTags.tags,\n tagsRelation: 'or',\n type: 'article',\n fromDate: getFromDate(),\n excludeAuthors: [username],\n },\n filter,\n includeNothingOptions,\n );\n return articles.posts.map(article => ({\n id: `a_${article.id}`,\n type: 'newArticle',\n article: article as Article,\n }));\n };\n\n const getNewEntityArticles = async (\n username: string,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<NewArticleSuggestion[]> => {\n const userEntities = await database.getUserEntities(username);\n if (userEntities.entityRefs.length === 0) {\n return [];\n }\n const articles = await database.getPosts(\n username,\n {\n entities: userEntities.entityRefs,\n entitiesRelation: 'or',\n type: 'article',\n fromDate: getFromDate(),\n excludeAuthors: [username],\n },\n filter,\n includeNothingOptions,\n );\n return articles.posts.map(article => ({\n id: `a_${article.id}`,\n type: 'newArticle',\n article: article as Article,\n }));\n };\n\n const getNewUserQuestions = async (\n username: string,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<NewQuestionSuggestion[]> => {\n const followedUsers = await database.getFollowedUsers(username);\n if (followedUsers.followedUserRefs.length === 0) {\n return [];\n }\n const questions = await database.getPosts(\n username,\n {\n author: followedUsers.followedUserRefs,\n type: 'question',\n fromDate: getFromDate(),\n excludeAuthors: [username],\n },\n filter,\n includeNothingOptions,\n );\n return questions.posts.map(question => ({\n id: `q_${question.id}`,\n type: 'newQuestion',\n question: question as Question,\n }));\n };\n\n const getUsersDraftPosts = async (\n username: string,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<DraftPostSuggestion[]> => {\n const draftPosts = await database.getPosts(\n username,\n {\n status: 'draft',\n author: username,\n },\n filter,\n includeNothingOptions,\n );\n\n return draftPosts.posts.map(post => ({\n id: `p_${post.id}`,\n type: 'draftPost',\n post,\n }));\n };\n\n const getNewUserArticles = async (\n username: string,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<NewArticleSuggestion[]> => {\n const followedUsers = await database.getFollowedUsers(username);\n if (followedUsers.followedUserRefs.length === 0) {\n return [];\n }\n const articles = await database.getPosts(\n username,\n {\n author: followedUsers.followedUserRefs,\n type: 'article',\n fromDate: getFromDate(),\n excludeAuthors: [username],\n },\n filter,\n includeNothingOptions,\n );\n return articles.posts.map(article => ({\n id: `a_${article.id}`,\n type: 'newArticle',\n article: article as Article,\n }));\n };\n\n const getNewTagLinks = async (\n username: string,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<NewLinkSuggestion[]> => {\n const userTags = await database.getUserTags(username);\n if (userTags.tags.length === 0) {\n return [];\n }\n const links = await database.getPosts(\n username,\n {\n tags: userTags.tags,\n tagsRelation: 'or',\n type: 'link',\n fromDate: getFromDate(),\n excludeAuthors: [username],\n },\n filter,\n includeNothingOptions,\n );\n return links.posts.map(link => ({\n id: `q_${link.id}`,\n type: 'newLink',\n link: link as Link,\n }));\n };\n\n const getNewEntityLinks = async (\n username: string,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<NewLinkSuggestion[]> => {\n const userEntities = await database.getUserEntities(username);\n if (userEntities.entityRefs.length === 0) {\n return [];\n }\n const links = await database.getPosts(\n username,\n {\n entities: userEntities.entityRefs,\n entitiesRelation: 'or',\n type: 'link',\n fromDate: getFromDate(),\n excludeAuthors: [username],\n },\n filter,\n includeNothingOptions,\n );\n return links.posts.map(link => ({\n id: `l_${link.id}`,\n type: 'newLink',\n link: link as Link,\n }));\n };\n\n const getNewUserLinks = async (\n username: string,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<NewLinkSuggestion[]> => {\n const followedUsers = await database.getFollowedUsers(username);\n if (followedUsers.followedUserRefs.length === 0) {\n return [];\n }\n const links = await database.getPosts(\n username,\n {\n author: followedUsers.followedUserRefs,\n type: 'link',\n fromDate: getFromDate(),\n excludeAuthors: [username],\n },\n filter,\n includeNothingOptions,\n );\n return links.posts.map(link => ({\n id: `l_${link.id}`,\n type: 'newLink',\n link: link as Link,\n }));\n };\n\n const getPostsNeedingReview = async (\n username: string,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<NeedsReviewSuggestion[]> => {\n const posts = await database.getPosts(\n username,\n { reviewNeeded: true, includeHealth: true, limit: 5 },\n filter,\n { ...includeNothingOptions, reviewThresholdMs },\n );\n return posts.posts.map(post => ({\n id: `r_${post.id}`,\n type: 'needsReview',\n post,\n }));\n };\n\n const getRandomPosts = async (\n username: string,\n limit: number,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<RandomPostSuggestion[]> => {\n const posts = await database.getPosts(\n username,\n { random: true, limit },\n filter,\n includeNothingOptions,\n );\n return posts.posts.map(post => ({\n id: `p_${post.id}`,\n type: 'randomPost',\n post,\n }));\n };\n\n router.get('/suggestions', async (request, response) => {\n const validateQuery = ajv.compile(SuggestionsQuerySchema);\n if (!validateQuery(request.query)) {\n response\n .status(400)\n .send({ errors: validateQuery.errors, type: 'query' });\n return;\n }\n const username = await permissionMgr.getUsername(request, false);\n let limit = Number(request.query.limit);\n if (isNaN(limit)) {\n limit = 5;\n }\n\n const filter = await permissionMgr.getAuthorizeConditions(\n request,\n qetaReadPostPermission,\n );\n\n // Check if user has review permissions\n const canReviewResults = await permissionMgr.authorizeBoolean(request, [\n { permission: qetaCreatePostReviewPermission },\n ]);\n const canReview = canReviewResults[0] ?? false;\n\n const promises: Promise<Suggestion[]>[] = [\n getNotCorrectQuestions(username, filter),\n getNewTagQuestions(username, filter),\n getNewTagArticles(username, filter),\n getNewTagLinks(username, filter),\n getNewEntityQuestions(username, filter),\n getNewEntityArticles(username, filter),\n getNewEntityLinks(username, filter),\n getNewUserQuestions(username, filter),\n getNewUserArticles(username, filter),\n getNewUserLinks(username, filter),\n getUsersDraftPosts(username, filter),\n canReview ? getPostsNeedingReview(username, filter) : Promise.resolve([]),\n ];\n\n const raw = await Promise.all(promises);\n\n const suggestionsRaw = raw\n .flat()\n .reduce((acc: Suggestion[], cur: Suggestion) => {\n if (!acc.some(s => s.id === cur.id)) {\n acc.push(cur);\n }\n return acc;\n }, []);\n\n if (suggestionsRaw.length < limit) {\n suggestionsRaw.push(...(await getRandomPosts(username, limit, filter)));\n }\n\n const suggestions = suggestionsRaw\n .sort(() => 0.5 - Math.random())\n .slice(0, limit);\n response.json({ suggestions });\n });\n};\n"],"names":["Ajv","addFormats","durationToMilliseconds","SuggestionsQuerySchema","qetaReadPostPermission","qetaCreatePostReviewPermission"],"mappings":"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"}
1
+ {"version":3,"file":"suggestions.cjs.js","sources":["../../../src/service/routes/suggestions.ts"],"sourcesContent":["import { Router } from 'express';\nimport { RouteOptions, SuggestionsQuerySchema } from '../types';\nimport { QetaFilters } from '../util';\nimport { getCachedData } from './routeUtil';\nimport {\n Article,\n DraftPostSuggestion,\n Link,\n NeedsReviewSuggestion,\n NewArticleSuggestion,\n NewLinkSuggestion,\n NewQuestionSuggestion,\n NoCorrectAnswerSuggestion,\n qetaCreatePostReviewPermission,\n qetaReadPostPermission,\n Question,\n RandomPostSuggestion,\n Suggestion,\n} from '@drodil/backstage-plugin-qeta-common';\nimport Ajv from 'ajv';\nimport addFormats from 'ajv-formats';\nimport { PostOptions } from '../../database/QetaStore';\nimport { PermissionCriteria } from '@backstage/plugin-permission-common';\nimport { durationToMilliseconds, HumanDuration } from '@backstage/types';\n\nconst ajv = new Ajv({ coerceTypes: 'array' });\naddFormats(ajv);\n\nexport const suggestionRoutes = (router: Router, options: RouteOptions) => {\n const { database, permissionMgr, config } = options;\n\n const postsOlderThan = config.getOptional<HumanDuration>(\n 'qeta.contentHealth.postsOlderThan',\n ) ?? { months: 6 };\n const reviewThresholdMs = durationToMilliseconds(postsOlderThan);\n\n const includeNothingOptions: PostOptions = {\n includeVotes: false,\n includeTags: false,\n includeComments: false,\n includeEntities: false,\n includeAnswers: false,\n includeAttachments: false,\n };\n\n const getFromDate = (days: number = 7) => {\n const date = new Date(Date.now() - 1000 * 60 * 60 * 24 * days);\n return date.toISOString().split('T')[0];\n };\n\n const getNotCorrectQuestions = async (\n username: string,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<NoCorrectAnswerSuggestion[]> => {\n const questions = await database.getPosts(\n username,\n {\n author: username,\n hasAnswers: true,\n noCorrectAnswer: true,\n type: 'question',\n },\n filter,\n includeNothingOptions,\n );\n\n return questions.posts.map(question => ({\n id: `noq_${question.id}`,\n type: 'noCorrectAnswer',\n question: question as Question,\n }));\n };\n\n const getNewTagQuestions = async (\n username: string,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<NewQuestionSuggestion[]> => {\n const userTags = await database.getUserTags(username);\n if (userTags.tags.length === 0) {\n return [];\n }\n const questions = await database.getPosts(\n username,\n {\n tags: userTags.tags,\n tagsRelation: 'or',\n type: 'question',\n fromDate: getFromDate(),\n excludeAuthors: [username],\n },\n filter,\n includeNothingOptions,\n );\n return questions.posts.map(question => ({\n id: `q_${question.id}`,\n type: 'newQuestion',\n question: question as Question,\n }));\n };\n\n const getNewEntityQuestions = async (\n username: string,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<NewQuestionSuggestion[]> => {\n const userEntities = await database.getUserEntities(username);\n if (userEntities.entityRefs.length === 0) {\n return [];\n }\n const questions = await database.getPosts(\n username,\n {\n entities: userEntities.entityRefs,\n entitiesRelation: 'or',\n type: 'question',\n fromDate: getFromDate(),\n excludeAuthors: [username],\n },\n filter,\n includeNothingOptions,\n );\n return questions.posts.map(question => ({\n id: `q_${question.id}`,\n type: 'newQuestion',\n question: question as Question,\n }));\n };\n\n const getNewTagArticles = async (\n username: string,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<NewArticleSuggestion[]> => {\n const userTags = await database.getUserTags(username);\n if (userTags.tags.length === 0) {\n return [];\n }\n const articles = await database.getPosts(\n username,\n {\n tags: userTags.tags,\n tagsRelation: 'or',\n type: 'article',\n fromDate: getFromDate(),\n excludeAuthors: [username],\n },\n filter,\n includeNothingOptions,\n );\n return articles.posts.map(article => ({\n id: `a_${article.id}`,\n type: 'newArticle',\n article: article as Article,\n }));\n };\n\n const getNewEntityArticles = async (\n username: string,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<NewArticleSuggestion[]> => {\n const userEntities = await database.getUserEntities(username);\n if (userEntities.entityRefs.length === 0) {\n return [];\n }\n const articles = await database.getPosts(\n username,\n {\n entities: userEntities.entityRefs,\n entitiesRelation: 'or',\n type: 'article',\n fromDate: getFromDate(),\n excludeAuthors: [username],\n },\n filter,\n includeNothingOptions,\n );\n return articles.posts.map(article => ({\n id: `a_${article.id}`,\n type: 'newArticle',\n article: article as Article,\n }));\n };\n\n const getNewUserQuestions = async (\n username: string,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<NewQuestionSuggestion[]> => {\n const followedUsers = await database.getFollowedUsers(username);\n if (followedUsers.followedUserRefs.length === 0) {\n return [];\n }\n const questions = await database.getPosts(\n username,\n {\n author: followedUsers.followedUserRefs,\n type: 'question',\n fromDate: getFromDate(),\n excludeAuthors: [username],\n },\n filter,\n includeNothingOptions,\n );\n return questions.posts.map(question => ({\n id: `q_${question.id}`,\n type: 'newQuestion',\n question: question as Question,\n }));\n };\n\n const getUsersDraftPosts = async (\n username: string,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<DraftPostSuggestion[]> => {\n const draftPosts = await database.getPosts(\n username,\n {\n status: 'draft',\n author: username,\n },\n filter,\n includeNothingOptions,\n );\n\n return draftPosts.posts.map(post => ({\n id: `p_${post.id}`,\n type: 'draftPost',\n post,\n }));\n };\n\n const getNewUserArticles = async (\n username: string,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<NewArticleSuggestion[]> => {\n const followedUsers = await database.getFollowedUsers(username);\n if (followedUsers.followedUserRefs.length === 0) {\n return [];\n }\n const articles = await database.getPosts(\n username,\n {\n author: followedUsers.followedUserRefs,\n type: 'article',\n fromDate: getFromDate(),\n excludeAuthors: [username],\n },\n filter,\n includeNothingOptions,\n );\n return articles.posts.map(article => ({\n id: `a_${article.id}`,\n type: 'newArticle',\n article: article as Article,\n }));\n };\n\n const getNewTagLinks = async (\n username: string,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<NewLinkSuggestion[]> => {\n const userTags = await database.getUserTags(username);\n if (userTags.tags.length === 0) {\n return [];\n }\n const links = await database.getPosts(\n username,\n {\n tags: userTags.tags,\n tagsRelation: 'or',\n type: 'link',\n fromDate: getFromDate(),\n excludeAuthors: [username],\n },\n filter,\n includeNothingOptions,\n );\n return links.posts.map(link => ({\n id: `q_${link.id}`,\n type: 'newLink',\n link: link as Link,\n }));\n };\n\n const getNewEntityLinks = async (\n username: string,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<NewLinkSuggestion[]> => {\n const userEntities = await database.getUserEntities(username);\n if (userEntities.entityRefs.length === 0) {\n return [];\n }\n const links = await database.getPosts(\n username,\n {\n entities: userEntities.entityRefs,\n entitiesRelation: 'or',\n type: 'link',\n fromDate: getFromDate(),\n excludeAuthors: [username],\n },\n filter,\n includeNothingOptions,\n );\n return links.posts.map(link => ({\n id: `l_${link.id}`,\n type: 'newLink',\n link: link as Link,\n }));\n };\n\n const getNewUserLinks = async (\n username: string,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<NewLinkSuggestion[]> => {\n const followedUsers = await database.getFollowedUsers(username);\n if (followedUsers.followedUserRefs.length === 0) {\n return [];\n }\n const links = await database.getPosts(\n username,\n {\n author: followedUsers.followedUserRefs,\n type: 'link',\n fromDate: getFromDate(),\n excludeAuthors: [username],\n },\n filter,\n includeNothingOptions,\n );\n return links.posts.map(link => ({\n id: `l_${link.id}`,\n type: 'newLink',\n link: link as Link,\n }));\n };\n\n const getPostsNeedingReview = async (\n username: string,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<NeedsReviewSuggestion[]> => {\n const posts = await database.getPosts(\n username,\n { reviewNeeded: true, includeHealth: true, limit: 5 },\n filter,\n { ...includeNothingOptions, reviewThresholdMs },\n );\n return posts.posts.map(post => ({\n id: `r_${post.id}`,\n type: 'needsReview',\n post,\n }));\n };\n\n const getRandomPosts = async (\n username: string,\n limit: number,\n filter?: PermissionCriteria<QetaFilters>,\n ): Promise<RandomPostSuggestion[]> => {\n const posts = await database.getPosts(\n username,\n { random: true, limit },\n filter,\n includeNothingOptions,\n );\n return posts.posts.map(post => ({\n id: `p_${post.id}`,\n type: 'randomPost',\n post,\n }));\n };\n\n const getSuggestions = async (\n username: string,\n limit: number,\n filter?: PermissionCriteria<QetaFilters>,\n canReview?: boolean,\n ): Promise<Suggestion[]> => {\n const promises: Promise<Suggestion[]>[] = [\n getNotCorrectQuestions(username, filter),\n getNewTagQuestions(username, filter),\n getNewTagArticles(username, filter),\n getNewTagLinks(username, filter),\n getNewEntityQuestions(username, filter),\n getNewEntityArticles(username, filter),\n getNewEntityLinks(username, filter),\n getNewUserQuestions(username, filter),\n getNewUserArticles(username, filter),\n getNewUserLinks(username, filter),\n getUsersDraftPosts(username, filter),\n canReview ? getPostsNeedingReview(username, filter) : Promise.resolve([]),\n ];\n\n const raw = await Promise.all(promises);\n\n const suggestionsRaw = raw\n .flat()\n .reduce((acc: Suggestion[], cur: Suggestion) => {\n if (!acc.some(s => s.id === cur.id)) {\n acc.push(cur);\n }\n return acc;\n }, []);\n\n if (suggestionsRaw.length < limit) {\n suggestionsRaw.push(...(await getRandomPosts(username, limit, filter)));\n }\n\n return suggestionsRaw.sort(() => 0.5 - Math.random()).slice(0, limit);\n };\n\n router.get('/suggestions', async (request, response) => {\n const validateQuery = ajv.compile(SuggestionsQuerySchema);\n if (!validateQuery(request.query)) {\n response\n .status(400)\n .send({ errors: validateQuery.errors, type: 'query' });\n return;\n }\n const username = await permissionMgr.getUsername(request, false);\n let limit = Number(request.query.limit);\n if (isNaN(limit)) {\n limit = 5;\n }\n\n const filter = await permissionMgr.getAuthorizeConditions(\n request,\n qetaReadPostPermission,\n );\n\n const canReviewResults = await permissionMgr.authorizeBoolean(request, [\n { permission: qetaCreatePostReviewPermission },\n ]);\n const canReview = canReviewResults[0] ?? false;\n\n const key = `qeta:suggestions:${username}:${limit}`;\n const ttl = 3600 * 1000;\n\n const suggestions = await getCachedData(\n options.cache,\n key,\n ttl,\n async () => {\n return await getSuggestions(username, limit, filter, canReview);\n },\n options.logger,\n );\n\n response.json({ suggestions });\n });\n};\n"],"names":["Ajv","addFormats","durationToMilliseconds","SuggestionsQuerySchema","qetaReadPostPermission","qetaCreatePostReviewPermission","getCachedData"],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * @param {import('knex').Knex} knex
3
+ */
4
+ exports.up = async function up(knex) {
5
+ await knex.schema.alterTable('post_tags', table => {
6
+ table.index('tagId');
7
+ });
8
+
9
+ await knex.schema.alterTable('post_entities', table => {
10
+ table.index('entityId');
11
+ });
12
+
13
+ await knex.schema.alterTable('posts', table => {
14
+ table.index('score');
15
+ table.index('views');
16
+ });
17
+
18
+ await knex.schema.alterTable('post_votes', table => {
19
+ table.index('author');
20
+ });
21
+ };
22
+
23
+ /**
24
+ * @param {import('knex').Knex} knex
25
+ */
26
+ exports.down = async function down(knex) {
27
+ await knex.schema.alterTable('post_tags', table => {
28
+ table.dropIndex('tagId');
29
+ });
30
+
31
+ await knex.schema.alterTable('post_entities', table => {
32
+ table.dropIndex('entityId');
33
+ });
34
+
35
+ await knex.schema.alterTable('posts', table => {
36
+ table.dropIndex('score');
37
+ table.dropIndex('views');
38
+ });
39
+
40
+ await knex.schema.alterTable('post_votes', table => {
41
+ table.dropIndex('author');
42
+ });
43
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drodil/backstage-plugin-qeta-backend",
3
- "version": "3.55.0",
3
+ "version": "3.55.1",
4
4
  "description": "Backstage.io Q&A plugin backend",
5
5
  "keywords": [
6
6
  "backstage",
@@ -66,8 +66,8 @@
66
66
  "@backstage/plugin-permission-node": "^0.10.7",
67
67
  "@backstage/plugin-signals-node": "^0.1.27",
68
68
  "@backstage/types": "^1.2.2",
69
- "@drodil/backstage-plugin-qeta-common": "^3.55.0",
70
- "@drodil/backstage-plugin-qeta-node": "^3.55.0",
69
+ "@drodil/backstage-plugin-qeta-common": "^3.55.1",
70
+ "@drodil/backstage-plugin-qeta-node": "^3.55.1",
71
71
  "@smithy/node-http-handler": "^4.0.2",
72
72
  "@types/express": "*",
73
73
  "@types/mime-types": "^2.1.4",
@@ -105,9 +105,9 @@
105
105
  "@backstage/plugin-search-backend-module-pg": "^0.5.51",
106
106
  "@backstage/plugin-signals-backend": "^0.3.11",
107
107
  "@backstage/plugin-techdocs-backend": "^2.1.3",
108
- "@drodil/backstage-plugin-catalog-backend-module-qeta": "^3.55.0",
109
- "@drodil/backstage-plugin-qeta-backend-module-openai": "^3.55.0",
110
- "@drodil/backstage-plugin-search-backend-module-qeta": "^3.55.0",
108
+ "@drodil/backstage-plugin-catalog-backend-module-qeta": "^3.55.1",
109
+ "@drodil/backstage-plugin-qeta-backend-module-openai": "^3.55.1",
110
+ "@drodil/backstage-plugin-search-backend-module-qeta": "^3.55.1",
111
111
  "@types/sanitize-html": "^2.9.5",
112
112
  "@types/stopword": "^2.0.3",
113
113
  "@types/supertest": "^2.0.12",