@drodil/backstage-plugin-qeta-backend 3.51.1 → 3.52.0

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.
@@ -12,13 +12,14 @@ var EntitiesStore = require('./stores/EntitiesStore.cjs.js');
12
12
  var TemplatesStore = require('./stores/TemplatesStore.cjs.js');
13
13
  var AttachmentsStore = require('./stores/AttachmentsStore.cjs.js');
14
14
  var BadgesStore = require('./stores/BadgesStore.cjs.js');
15
+ var HelpersStore = require('./stores/HelpersStore.cjs.js');
15
16
 
16
17
  const migrationsDir = backendPluginApi.resolvePackagePath(
17
18
  "@drodil/backstage-plugin-qeta-backend",
18
19
  "migrations"
19
20
  );
20
21
  class DatabaseQetaStore {
21
- constructor(postsStore, answersStore, commentsStore, collectionsStore, statsStore, tagsStore, usersStore, entitiesStore, templatesStore, attachmentsStore, badgesStore) {
22
+ constructor(postsStore, answersStore, commentsStore, collectionsStore, statsStore, tagsStore, usersStore, entitiesStore, templatesStore, attachmentsStore, badgesStore, helpersStore) {
22
23
  this.postsStore = postsStore;
23
24
  this.answersStore = answersStore;
24
25
  this.commentsStore = commentsStore;
@@ -30,6 +31,10 @@ class DatabaseQetaStore {
30
31
  this.templatesStore = templatesStore;
31
32
  this.attachmentsStore = attachmentsStore;
32
33
  this.badgesStore = badgesStore;
34
+ this.helpersStore = helpersStore;
35
+ }
36
+ async getTimeline(user_ref, options, filters) {
37
+ return this.helpersStore.getTimeline(user_ref, options, filters);
33
38
  }
34
39
  static async create({
35
40
  database,
@@ -69,6 +74,7 @@ class DatabaseQetaStore {
69
74
  );
70
75
  const statsStore = new StatsStore.StatsStore(client);
71
76
  const badgesStore = new BadgesStore.BadgesStore(client);
77
+ const helpersStore = new HelpersStore.HelpersStore(client);
72
78
  postsStore.setAnswersStore(answersStore);
73
79
  return new DatabaseQetaStore(
74
80
  postsStore,
@@ -81,7 +87,8 @@ class DatabaseQetaStore {
81
87
  entitiesStore,
82
88
  templatesStore,
83
89
  attachmentsStore,
84
- badgesStore
90
+ badgesStore,
91
+ helpersStore
85
92
  );
86
93
  }
87
94
  async getPosts(user_ref, options, filters, opts) {
@@ -1 +1 @@
1
- {"version":3,"file":"DatabaseQetaStore.cjs.js","sources":["../../src/database/DatabaseQetaStore.ts"],"sourcesContent":["import {\n DatabaseService,\n resolvePackagePath,\n} from '@backstage/backend-plugin-api';\n\nimport {\n AnswerOptions,\n Answers,\n AttachmentParameters,\n AwardBadgeResult,\n CollectionOptions,\n CollectionPostRank,\n Collections,\n CommentOptions,\n EntitiesResponse,\n EntityResponse,\n MaybeAnswer,\n MaybeCollection,\n MaybePost,\n PostOptions,\n PostReview,\n Posts,\n QetaStore,\n Templates,\n UserResponse,\n UsersResponse,\n} from './QetaStore';\nimport { Badge, UserBadge } from '@drodil/backstage-plugin-qeta-common';\nimport {\n AIResponse,\n AnswersQuery,\n Attachment,\n Collection,\n Comment as QetaComment,\n EntitiesQuery,\n EntityLinks,\n GlobalStat,\n Post,\n PostStatus,\n PostType,\n PostsQuery,\n Statistic,\n StatisticsRequestParameters,\n TagResponse,\n TagsQuery,\n TagsResponse,\n Template,\n UserCollectionsResponse,\n UserEntitiesResponse,\n UsersQuery,\n UserStat,\n UserTagsResponse,\n UserUsersResponse,\n} from '@drodil/backstage-plugin-qeta-common';\nimport { QetaFilters } from '../service/util';\nimport { PermissionCriteria } from '@backstage/plugin-permission-common';\nimport { TagDatabase } from '@drodil/backstage-plugin-qeta-node';\nimport { PostsStore } from './stores/PostsStore';\nimport { AnswersStore } from './stores/AnswersStore';\nimport { CommentsStore } from './stores/CommentsStore';\nimport { CollectionsStore } from './stores/CollectionsStore';\nimport { StatsStore } from './stores/StatsStore';\nimport { TagsStore } from './stores/TagsStore';\nimport { UsersStore } from './stores/UsersStore';\nimport { EntitiesStore } from './stores/EntitiesStore';\nimport { TemplatesStore } from './stores/TemplatesStore';\nimport { AttachmentsStore } from './stores/AttachmentsStore';\nimport { BadgesStore } from './stores/BadgesStore';\n\nconst migrationsDir = resolvePackagePath(\n '@drodil/backstage-plugin-qeta-backend',\n 'migrations',\n);\n\n// Local interfaces removed, imported from stores\n\nexport class DatabaseQetaStore implements QetaStore {\n private constructor(\n private readonly postsStore: PostsStore,\n private readonly answersStore: AnswersStore,\n private readonly commentsStore: CommentsStore,\n private readonly collectionsStore: CollectionsStore,\n private readonly statsStore: StatsStore,\n private readonly tagsStore: TagsStore,\n private readonly usersStore: UsersStore,\n private readonly entitiesStore: EntitiesStore,\n private readonly templatesStore: TemplatesStore,\n private readonly attachmentsStore: AttachmentsStore,\n private readonly badgesStore: BadgesStore,\n ) {}\n\n static async create({\n database,\n skipMigrations,\n tagDatabase,\n }: {\n database: DatabaseService;\n skipMigrations?: boolean;\n tagDatabase?: TagDatabase;\n }): Promise<DatabaseQetaStore> {\n const client = await database.getClient();\n\n if (!database.migrations?.skip && !skipMigrations) {\n await client.migrate.latest({\n directory: migrationsDir,\n });\n }\n\n const commentsStore = new CommentsStore(client);\n const tagsStore = new TagsStore(client, tagDatabase);\n const entitiesStore = new EntitiesStore(client);\n const usersStore = new UsersStore(client);\n const templatesStore = new TemplatesStore(client, tagsStore, entitiesStore);\n const attachmentsStore = new AttachmentsStore(client);\n const postsStore = new PostsStore(\n client,\n commentsStore,\n tagsStore,\n entitiesStore,\n attachmentsStore,\n tagDatabase,\n );\n const answersStore = new AnswersStore(\n client,\n commentsStore,\n postsStore,\n attachmentsStore,\n );\n const collectionsStore = new CollectionsStore(\n client,\n postsStore,\n attachmentsStore,\n );\n const statsStore = new StatsStore(client);\n const badgesStore = new BadgesStore(client);\n\n postsStore.setAnswersStore(answersStore);\n\n return new DatabaseQetaStore(\n postsStore,\n answersStore,\n commentsStore,\n collectionsStore,\n statsStore,\n tagsStore,\n usersStore,\n entitiesStore,\n templatesStore,\n attachmentsStore,\n badgesStore,\n );\n }\n\n async getPosts(\n user_ref: string,\n options: PostsQuery,\n filters?: PermissionCriteria<QetaFilters>,\n opts?: PostOptions,\n ): Promise<Posts> {\n return this.postsStore.getPosts(user_ref, options, filters, opts);\n }\n\n async getPost(\n user_ref: string,\n id: number,\n recordView?: boolean,\n options?: PostOptions,\n ): Promise<MaybePost> {\n return this.postsStore.getPost(user_ref, id, recordView, options);\n }\n\n async getPostByAnswerId(\n user_ref: string,\n answerId: number,\n recordView?: boolean,\n options?: PostOptions,\n ): Promise<MaybePost> {\n return this.postsStore.getPostByAnswerId(\n user_ref,\n answerId,\n recordView,\n options,\n );\n }\n\n async createPost(options: {\n user_ref: string;\n title: string;\n content: string;\n created: Date;\n author?: string;\n tags?: string[];\n entities?: string[];\n images?: number[];\n anonymous?: boolean;\n type?: PostType;\n headerImage?: string;\n url?: string;\n status?: PostStatus;\n opts?: PostOptions;\n }): Promise<Post> {\n return this.postsStore.createPost(options);\n }\n\n async updatePost(options: {\n user_ref: string;\n id: number;\n title?: string;\n content?: string;\n author?: string;\n tags?: string[];\n entities?: string[];\n images?: number[];\n headerImage?: string;\n url?: string;\n status?: PostStatus;\n opts?: PostOptions;\n }): Promise<MaybePost> {\n return this.postsStore.updatePost(options);\n }\n\n async deletePost(id: number, permanently?: boolean): Promise<boolean> {\n return this.postsStore.deletePost(id, permanently);\n }\n\n async votePost(\n user_ref: string,\n postId: number,\n score: number,\n ): Promise<boolean> {\n return this.postsStore.votePost(user_ref, postId, score);\n }\n\n async deletePostVote(user_ref: string, postId: number): Promise<boolean> {\n return this.postsStore.deletePostVote(user_ref, postId);\n }\n\n async favoritePost(user_ref: string, postId: number): Promise<boolean> {\n return this.postsStore.favoritePost(user_ref, postId);\n }\n\n async unfavoritePost(user_ref: string, postId: number): Promise<boolean> {\n return this.postsStore.unfavoritePost(user_ref, postId);\n }\n\n async getUsersWhoFavoritedPost(postId: number): Promise<string[]> {\n return this.postsStore.getUsersWhoFavoritedPost(postId);\n }\n\n async getAnswers(\n user_ref: string,\n options: AnswersQuery,\n filters?: PermissionCriteria<QetaFilters>,\n opts?: AnswerOptions,\n ): Promise<Answers> {\n return this.answersStore.getAnswers(user_ref, options, filters, opts);\n }\n\n async getAnswer(\n answerId: number,\n user_ref: string,\n options?: AnswerOptions,\n ): Promise<MaybeAnswer> {\n return this.answersStore.getAnswer(answerId, user_ref, options);\n }\n\n async answerPost(\n user_ref: string,\n questionId: number,\n answer: string,\n created: Date,\n images?: number[],\n anonymous?: boolean,\n options?: AnswerOptions,\n ): Promise<MaybeAnswer> {\n return this.answersStore.answerPost(\n user_ref,\n questionId,\n answer,\n created,\n images,\n anonymous,\n options,\n );\n }\n\n async updateAnswer(\n user_ref: string,\n questionId: number,\n answerId: number,\n answer: string,\n author?: string,\n images?: number[],\n options?: AnswerOptions,\n ): Promise<MaybeAnswer> {\n return this.answersStore.updateAnswer(\n user_ref,\n questionId,\n answerId,\n answer,\n author,\n images,\n options,\n );\n }\n\n async deleteAnswer(id: number): Promise<boolean> {\n return this.answersStore.deleteAnswer(id);\n }\n\n async voteAnswer(\n user_ref: string,\n answerId: number,\n score: number,\n ): Promise<boolean> {\n return this.answersStore.voteAnswer(user_ref, answerId, score);\n }\n\n async deleteAnswerVote(user_ref: string, answerId: number): Promise<boolean> {\n return this.answersStore.deleteAnswerVote(user_ref, answerId);\n }\n\n async markAnswerCorrect(postId: number, answerId: number): Promise<boolean> {\n return this.answersStore.markAnswerCorrect(postId, answerId);\n }\n\n async markAnswerIncorrect(\n postId: number,\n answerId: number,\n ): Promise<boolean> {\n return this.answersStore.markAnswerIncorrect(postId, answerId);\n }\n\n async clickPost(user_ref: string, postId: number): Promise<void> {\n const vote = await this.postsStore.getPostVote(user_ref, postId);\n const score = (vote?.score || 0) + 1;\n await this.postsStore.votePost(user_ref, postId, score);\n }\n\n async commentPost(\n post_id: number,\n user_ref: string,\n content: string,\n created: Date,\n ): Promise<MaybePost> {\n await this.commentsStore.commentPost(post_id, user_ref, content, created);\n return this.getPost(user_ref, post_id);\n }\n\n async commentAnswer(\n answer_id: number,\n user_ref: string,\n content: string,\n created: Date,\n ): Promise<MaybeAnswer> {\n await this.commentsStore.commentAnswer(\n answer_id,\n user_ref,\n content,\n created,\n );\n return this.getAnswer(answer_id, user_ref);\n }\n\n async updatePostComment(\n post_id: number,\n id: number,\n user_ref: string,\n content: string,\n ): Promise<MaybePost> {\n await this.commentsStore.updatePostComment(post_id, id, user_ref, content);\n return this.getPost(user_ref, post_id);\n }\n\n async updateAnswerComment(\n answer_id: number,\n id: number,\n user_ref: string,\n content: string,\n ): Promise<MaybeAnswer> {\n await this.commentsStore.updateAnswerComment(\n answer_id,\n id,\n user_ref,\n content,\n );\n return this.getAnswer(answer_id, user_ref);\n }\n\n async deletePostComment(\n post_id: number,\n id: number,\n user_ref: string,\n ): Promise<MaybePost> {\n await this.commentsStore.deletePostComment(post_id, id);\n return this.getPost(user_ref, post_id);\n }\n\n async deleteAnswerComment(\n answer_id: number,\n id: number,\n user_ref: string,\n ): Promise<MaybeAnswer> {\n await this.commentsStore.deleteAnswerComment(answer_id, id);\n return this.getAnswer(answer_id, user_ref);\n }\n\n async getCollections(\n user_ref: string,\n options: PostsQuery,\n opts?: CollectionOptions,\n ): Promise<Collections> {\n return this.collectionsStore.getCollections(user_ref, options, opts);\n }\n\n async getCollection(\n user_ref: string,\n id: number,\n options?: CollectionOptions,\n ): Promise<MaybeCollection> {\n return this.collectionsStore.getCollection(user_ref, id, options);\n }\n\n async createCollection(options: {\n user_ref: string;\n title: string;\n description?: string;\n created: Date;\n images?: number[];\n headerImage?: string;\n opts?: CollectionOptions;\n }): Promise<Collection> {\n return this.collectionsStore.createCollection(\n options,\n ) as Promise<Collection>;\n }\n\n async updateCollection(options: {\n id: number;\n user_ref: string;\n title: string;\n description?: string;\n images?: number[];\n headerImage?: string;\n opts?: CollectionOptions;\n }): Promise<MaybeCollection> {\n return this.collectionsStore.updateCollection(options);\n }\n\n async deleteCollection(id: number): Promise<boolean> {\n return this.collectionsStore.deleteCollection(id);\n }\n\n async addPostToCollection(\n user_ref: string,\n id: number,\n postId: number,\n options?: CollectionOptions,\n ): Promise<MaybeCollection> {\n return this.collectionsStore.addPostToCollection(\n user_ref,\n id,\n postId,\n options,\n );\n }\n\n async removePostFromCollection(\n user_ref: string,\n id: number,\n postId: number,\n options?: CollectionOptions,\n ): Promise<MaybeCollection> {\n return this.collectionsStore.removePostFromCollection(\n user_ref,\n id,\n postId,\n options,\n );\n }\n\n async getUsersForCollection(collectionId: number): Promise<string[]> {\n return this.collectionsStore.getUsersForCollection(collectionId);\n }\n\n async followCollection(\n user_ref: string,\n collectionId: number,\n ): Promise<boolean> {\n return this.collectionsStore.followCollection(user_ref, collectionId);\n }\n\n async unfollowCollection(\n user_ref: string,\n collectionId: number,\n ): Promise<boolean> {\n return this.collectionsStore.unfollowCollection(user_ref, collectionId);\n }\n\n async getUserCollections(\n user_ref: string,\n options?: CollectionOptions,\n ): Promise<UserCollectionsResponse> {\n return this.collectionsStore.getUserCollections(user_ref, options);\n }\n\n async getPostRank(\n collectionId: number,\n postId: number,\n ): Promise<number | null> {\n return this.collectionsStore.getPostRank(collectionId, postId);\n }\n\n async getTopRankedPostId(\n collectionId: number,\n ): Promise<CollectionPostRank | null> {\n return this.collectionsStore.getTopRankedPostId(collectionId);\n }\n\n async getBottomRankedPostId(\n collectionId: number,\n ): Promise<CollectionPostRank | null> {\n return this.collectionsStore.getBottomRankedPostId(collectionId);\n }\n\n async getNextRankedPostId(\n collectionId: number,\n postId: number,\n ): Promise<CollectionPostRank | null> {\n return this.collectionsStore.getNextRankedPostId(collectionId, postId);\n }\n\n async getPreviousRankedPostId(\n collectionId: number,\n postId: number,\n ): Promise<CollectionPostRank | null> {\n return this.collectionsStore.getPreviousRankedPostId(collectionId, postId);\n }\n\n async updatePostRank(\n collectionId: number,\n postId: number,\n rank: number,\n ): Promise<void> {\n return this.collectionsStore.updatePostRank(collectionId, postId, rank);\n }\n\n async getTags(\n options?: { noDescription?: boolean; ids?: number[] } & TagsQuery,\n filters?: PermissionCriteria<QetaFilters>,\n ): Promise<TagsResponse> {\n return this.tagsStore.getTags(options, filters);\n }\n\n async getTagExperts(tags: string[]): Promise<string[]> {\n return this.tagsStore.getTagExperts(tags);\n }\n\n async getTag(tag: string): Promise<TagResponse | null> {\n return this.tagsStore.getTag(tag);\n }\n\n async getTagById(id: number): Promise<TagResponse | null> {\n return this.tagsStore.getTagById(id);\n }\n\n async createTag(\n tag: string,\n description?: string,\n experts?: string[],\n ): Promise<TagResponse | null> {\n return this.tagsStore.createTag(tag, description, experts);\n }\n\n async updateTag(\n id: number,\n description?: string,\n experts?: string[],\n ): Promise<TagResponse | null> {\n return this.tagsStore.updateTag(id, description, experts);\n }\n\n async deleteTag(id: number): Promise<boolean> {\n return this.tagsStore.deleteTag(id);\n }\n\n async getEntities(\n options?: { entityRefs?: string[] } & EntitiesQuery,\n ): Promise<EntitiesResponse> {\n return this.entitiesStore.getEntities(options);\n }\n\n async getEntity(entity_ref: string): Promise<EntityResponse | null> {\n return this.entitiesStore.getEntity(entity_ref);\n }\n\n async getUsers(\n options?: { entityRefs?: string[] } & UsersQuery,\n ): Promise<UsersResponse> {\n return this.usersStore.getUsers(options);\n }\n\n async getUser(user_ref: string): Promise<UserResponse | null> {\n return this.usersStore.getUser(user_ref);\n }\n\n async getUserTags(\n user_ref: string,\n filters?: PermissionCriteria<QetaFilters>,\n ): Promise<UserTagsResponse> {\n return this.tagsStore.getUserTags(user_ref, filters);\n }\n\n async followTag(user_ref: string, tag: string): Promise<boolean> {\n return this.tagsStore.followTag(user_ref, tag);\n }\n\n async unfollowTag(user_ref: string, tag: string): Promise<boolean> {\n return this.tagsStore.unfollowTag(user_ref, tag);\n }\n\n async getUserEntities(user_ref: string): Promise<UserEntitiesResponse> {\n return this.entitiesStore.getUserEntities(user_ref);\n }\n\n async followEntity(user_ref: string, entityRef: string): Promise<boolean> {\n return this.entitiesStore.followEntity(user_ref, entityRef);\n }\n\n async unfollowEntity(user_ref: string, entityRef: string): Promise<boolean> {\n return this.entitiesStore.unfollowEntity(user_ref, entityRef);\n }\n\n async getUsersForTags(tags: string[]): Promise<string[]> {\n return this.tagsStore.getUsersForTags(tags);\n }\n\n async getUsersForEntities(entityRefs: string[]): Promise<string[]> {\n return this.entitiesStore.getUsersForEntities(entityRefs);\n }\n\n async getFollowedUsers(user_ref: string): Promise<UserUsersResponse> {\n return this.usersStore.getFollowedUsers(user_ref);\n }\n\n async followUser(\n user_ref: string,\n followedUserRef: string,\n ): Promise<boolean> {\n return this.usersStore.followUser(user_ref, followedUserRef);\n }\n\n async unfollowUser(\n user_ref: string,\n followedUserRef: string,\n ): Promise<boolean> {\n return this.usersStore.unfollowUser(user_ref, followedUserRef);\n }\n\n async getGlobalStats(): Promise<GlobalStat[]> {\n return this.statsStore.getGlobalStats();\n }\n\n async getUserStats(user_ref: string): Promise<UserStat[]> {\n return this.statsStore.getUserStats(user_ref);\n }\n\n async getTemplates(): Promise<Templates> {\n return this.templatesStore.getTemplates();\n }\n\n async getTemplate(id: number): Promise<Template | null> {\n return this.templatesStore.getTemplate(id);\n }\n\n async createTemplate(options: {\n title: string;\n description: string;\n questionTitle?: string;\n questionContent?: string;\n tags?: string[];\n entities?: string[];\n }): Promise<Template> {\n return this.templatesStore.createTemplate(options);\n }\n\n async deleteTemplate(id: number): Promise<boolean> {\n return this.templatesStore.deleteTemplate(id);\n }\n\n async updateTemplate(options: {\n id: number;\n title: string;\n description: string;\n questionTitle?: string;\n questionContent?: string;\n tags?: string[];\n entities?: string[];\n }): Promise<Template | null> {\n return this.templatesStore.updateTemplate(options);\n }\n\n async reviewPost(\n user_ref: string,\n postId: number,\n status: 'valid' | 'obsolete',\n comment?: string,\n ): Promise<MaybePost> {\n return this.postsStore.reviewPost(user_ref, postId, status, comment);\n }\n\n async getPostReviews(postId: number): Promise<PostReview[]> {\n return this.postsStore.getPostReviews(postId);\n }\n\n async getAIAnswer(postId: number): Promise<AIResponse | null> {\n return this.postsStore.getAIAnswer(postId);\n }\n\n async saveAIAnswer(postId: number, response: AIResponse): Promise<void> {\n return this.postsStore.saveAIAnswer(postId, response);\n }\n\n async deleteAIAnswer(postId: number): Promise<boolean> {\n return this.postsStore.deleteAIAnswer(postId);\n }\n\n async postAttachment({\n uuid,\n locationType,\n locationUri,\n extension,\n mimeType,\n binaryImage,\n path,\n creator,\n }: AttachmentParameters): Promise<Attachment> {\n return this.attachmentsStore.postAttachment({\n uuid,\n locationType,\n locationUri,\n extension,\n mimeType,\n binaryImage,\n path,\n creator,\n });\n }\n\n async getAttachment(uuid: string): Promise<Attachment | undefined> {\n return this.attachmentsStore.getAttachment(uuid);\n }\n\n async deleteAttachment(uuid: string): Promise<boolean> {\n return this.attachmentsStore.deleteAttachment(uuid);\n }\n\n async getDeletableAttachments(dayLimit: number): Promise<Attachment[]> {\n return this.attachmentsStore.getDeletableAttachments(dayLimit);\n }\n\n // Stats\n\n async getMostUpvotedPosts({\n author,\n options,\n }: StatisticsRequestParameters): Promise<Statistic[]> {\n return this.statsStore.getMostUpvotedPosts({ author, options });\n }\n\n async getTotalPosts({\n author,\n options,\n }: StatisticsRequestParameters): Promise<Statistic[]> {\n return this.statsStore.getTotalPosts({ author, options });\n }\n\n async getMostUpvotedAnswers({\n author,\n options,\n }: StatisticsRequestParameters): Promise<Statistic[]> {\n return this.statsStore.getMostUpvotedAnswers({ author, options });\n }\n\n async getMostUpvotedCorrectAnswers({\n author,\n options,\n }: StatisticsRequestParameters): Promise<Statistic[]> {\n return this.statsStore.getMostUpvotedCorrectAnswers({ author, options });\n }\n\n async getTotalAnswers({\n author,\n options,\n }: StatisticsRequestParameters): Promise<Statistic[]> {\n return this.statsStore.getTotalAnswers({ author, options });\n }\n\n async getCount(\n table: string,\n filters?: { author?: string; type?: PostType },\n ): Promise<number> {\n return this.statsStore.getCount(table, filters);\n }\n\n async saveGlobalStats(date: Date): Promise<void> {\n return this.statsStore.saveGlobalStats(date);\n }\n\n async saveUserStats(userRef: string, date: Date): Promise<void> {\n return this.statsStore.saveUserStats(userRef, date);\n }\n\n async getTotalViews(\n user_ref: string,\n lastDays?: number,\n excludeUser?: boolean,\n ): Promise<number> {\n return this.statsStore.getTotalViews(user_ref, lastDays, excludeUser);\n }\n\n async getBadges(): Promise<Badge[]> {\n return this.badgesStore.getBadges();\n }\n\n async getBadge(key: string): Promise<Badge | undefined> {\n return this.badgesStore.getBadge(key);\n }\n\n async getUserBadges(userRef: string): Promise<UserBadge[]> {\n return this.badgesStore.getUserBadges(userRef);\n }\n\n async awardBadge(\n userRef: string,\n badgeKey: string,\n uniqueKey?: string,\n ): Promise<AwardBadgeResult | null> {\n return this.badgesStore.awardBadge(userRef, badgeKey, uniqueKey);\n }\n\n async createBadge(badge: Omit<Badge, 'id'>): Promise<void> {\n return this.badgesStore.createBadge(badge);\n }\n\n async suggestPosts(\n user_ref: string,\n title: string,\n content: string,\n tags?: string[],\n entities?: string[],\n filters?: PermissionCriteria<QetaFilters>,\n opts?: PostOptions,\n ): Promise<Posts> {\n return this.postsStore.suggestPosts(\n user_ref,\n title,\n content,\n tags,\n entities,\n filters,\n opts,\n );\n }\n\n async cleanStats(days: number, date: Date): Promise<void> {\n return this.statsStore.cleanStats(days, date);\n }\n\n async getUsersCount(): Promise<number> {\n return this.usersStore.getUsersCount();\n }\n\n async getFollowingUsers(user_ref: string): Promise<string[]> {\n return this.usersStore.getFollowingUsers(user_ref);\n }\n\n async getEntityLinks(): Promise<EntityLinks[]> {\n return this.entitiesStore.getEntityLinks();\n }\n\n async getComments(\n options?: { ids?: number[] },\n opts?: CommentOptions,\n ): Promise<QetaComment[]> {\n return this.commentsStore.getComments(options, opts);\n }\n\n async getComment(\n commentId: number,\n opts?: CommentOptions & { postId?: number; answerId?: number },\n ): Promise<QetaComment | null> {\n return this.commentsStore.getComment(commentId, opts);\n }\n}\n"],"names":["resolvePackagePath","CommentsStore","TagsStore","EntitiesStore","UsersStore","TemplatesStore","AttachmentsStore","PostsStore","AnswersStore","CollectionsStore","StatsStore","BadgesStore"],"mappings":"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"}
1
+ {"version":3,"file":"DatabaseQetaStore.cjs.js","sources":["../../src/database/DatabaseQetaStore.ts"],"sourcesContent":["import {\n DatabaseService,\n resolvePackagePath,\n} from '@backstage/backend-plugin-api';\n\nimport {\n AnswerOptions,\n Answers,\n AttachmentParameters,\n AwardBadgeResult,\n CollectionOptions,\n CollectionPostRank,\n Collections,\n CommentOptions,\n EntitiesResponse,\n EntityResponse,\n MaybeAnswer,\n MaybeCollection,\n MaybePost,\n PostOptions,\n PostReview,\n Posts,\n QetaStore,\n Templates,\n UserResponse,\n UsersResponse,\n TimelineFilters,\n} from './QetaStore';\nimport { Badge, UserBadge } from '@drodil/backstage-plugin-qeta-common';\nimport {\n AIResponse,\n AnswersQuery,\n Attachment,\n Collection,\n Comment as QetaComment,\n EntitiesQuery,\n EntityLinks,\n GlobalStat,\n Post,\n PostStatus,\n PostType,\n PostsQuery,\n Statistic,\n StatisticsRequestParameters,\n TagResponse,\n TagsQuery,\n TagsResponse,\n Template,\n UserCollectionsResponse,\n UserEntitiesResponse,\n UsersQuery,\n UserStat,\n UserTagsResponse,\n UserUsersResponse,\n TimelineOptions,\n TimelineResponse,\n} from '@drodil/backstage-plugin-qeta-common';\nimport { QetaFilters } from '../service/util';\nimport { PermissionCriteria } from '@backstage/plugin-permission-common';\nimport { TagDatabase } from '@drodil/backstage-plugin-qeta-node';\nimport { PostsStore } from './stores/PostsStore';\nimport { AnswersStore } from './stores/AnswersStore';\nimport { CommentsStore } from './stores/CommentsStore';\nimport { CollectionsStore } from './stores/CollectionsStore';\nimport { StatsStore } from './stores/StatsStore';\nimport { TagsStore } from './stores/TagsStore';\nimport { UsersStore } from './stores/UsersStore';\nimport { EntitiesStore } from './stores/EntitiesStore';\nimport { TemplatesStore } from './stores/TemplatesStore';\nimport { AttachmentsStore } from './stores/AttachmentsStore';\nimport { BadgesStore } from './stores/BadgesStore';\nimport { HelpersStore } from './stores/HelpersStore';\n\nconst migrationsDir = resolvePackagePath(\n '@drodil/backstage-plugin-qeta-backend',\n 'migrations',\n);\n\n// Local interfaces removed, imported from stores\n\nexport class DatabaseQetaStore implements QetaStore {\n private constructor(\n private readonly postsStore: PostsStore,\n private readonly answersStore: AnswersStore,\n private readonly commentsStore: CommentsStore,\n private readonly collectionsStore: CollectionsStore,\n private readonly statsStore: StatsStore,\n private readonly tagsStore: TagsStore,\n private readonly usersStore: UsersStore,\n private readonly entitiesStore: EntitiesStore,\n private readonly templatesStore: TemplatesStore,\n private readonly attachmentsStore: AttachmentsStore,\n private readonly badgesStore: BadgesStore,\n private readonly helpersStore: HelpersStore,\n ) {}\n\n async getTimeline(\n user_ref: string,\n options: TimelineOptions,\n filters?: TimelineFilters,\n ): Promise<TimelineResponse> {\n return this.helpersStore.getTimeline(user_ref, options, filters);\n }\n\n static async create({\n database,\n skipMigrations,\n tagDatabase,\n }: {\n database: DatabaseService;\n skipMigrations?: boolean;\n tagDatabase?: TagDatabase;\n }): Promise<DatabaseQetaStore> {\n const client = await database.getClient();\n\n if (!database.migrations?.skip && !skipMigrations) {\n await client.migrate.latest({\n directory: migrationsDir,\n });\n }\n\n const commentsStore = new CommentsStore(client);\n const tagsStore = new TagsStore(client, tagDatabase);\n const entitiesStore = new EntitiesStore(client);\n const usersStore = new UsersStore(client);\n const templatesStore = new TemplatesStore(client, tagsStore, entitiesStore);\n const attachmentsStore = new AttachmentsStore(client);\n const postsStore = new PostsStore(\n client,\n commentsStore,\n tagsStore,\n entitiesStore,\n attachmentsStore,\n tagDatabase,\n );\n const answersStore = new AnswersStore(\n client,\n commentsStore,\n postsStore,\n attachmentsStore,\n );\n const collectionsStore = new CollectionsStore(\n client,\n postsStore,\n attachmentsStore,\n );\n const statsStore = new StatsStore(client);\n const badgesStore = new BadgesStore(client);\n const helpersStore = new HelpersStore(client);\n\n postsStore.setAnswersStore(answersStore);\n\n return new DatabaseQetaStore(\n postsStore,\n answersStore,\n commentsStore,\n collectionsStore,\n statsStore,\n tagsStore,\n usersStore,\n entitiesStore,\n templatesStore,\n attachmentsStore,\n badgesStore,\n helpersStore,\n );\n }\n\n async getPosts(\n user_ref: string,\n options: PostsQuery,\n filters?: PermissionCriteria<QetaFilters>,\n opts?: PostOptions,\n ): Promise<Posts> {\n return this.postsStore.getPosts(user_ref, options, filters, opts);\n }\n\n async getPost(\n user_ref: string,\n id: number,\n recordView?: boolean,\n options?: PostOptions,\n ): Promise<MaybePost> {\n return this.postsStore.getPost(user_ref, id, recordView, options);\n }\n\n async getPostByAnswerId(\n user_ref: string,\n answerId: number,\n recordView?: boolean,\n options?: PostOptions,\n ): Promise<MaybePost> {\n return this.postsStore.getPostByAnswerId(\n user_ref,\n answerId,\n recordView,\n options,\n );\n }\n\n async createPost(options: {\n user_ref: string;\n title: string;\n content: string;\n created: Date;\n author?: string;\n tags?: string[];\n entities?: string[];\n images?: number[];\n anonymous?: boolean;\n type?: PostType;\n headerImage?: string;\n url?: string;\n status?: PostStatus;\n opts?: PostOptions;\n }): Promise<Post> {\n return this.postsStore.createPost(options);\n }\n\n async updatePost(options: {\n user_ref: string;\n id: number;\n title?: string;\n content?: string;\n author?: string;\n tags?: string[];\n entities?: string[];\n images?: number[];\n headerImage?: string;\n url?: string;\n status?: PostStatus;\n opts?: PostOptions;\n }): Promise<MaybePost> {\n return this.postsStore.updatePost(options);\n }\n\n async deletePost(id: number, permanently?: boolean): Promise<boolean> {\n return this.postsStore.deletePost(id, permanently);\n }\n\n async votePost(\n user_ref: string,\n postId: number,\n score: number,\n ): Promise<boolean> {\n return this.postsStore.votePost(user_ref, postId, score);\n }\n\n async deletePostVote(user_ref: string, postId: number): Promise<boolean> {\n return this.postsStore.deletePostVote(user_ref, postId);\n }\n\n async favoritePost(user_ref: string, postId: number): Promise<boolean> {\n return this.postsStore.favoritePost(user_ref, postId);\n }\n\n async unfavoritePost(user_ref: string, postId: number): Promise<boolean> {\n return this.postsStore.unfavoritePost(user_ref, postId);\n }\n\n async getUsersWhoFavoritedPost(postId: number): Promise<string[]> {\n return this.postsStore.getUsersWhoFavoritedPost(postId);\n }\n\n async getAnswers(\n user_ref: string,\n options: AnswersQuery,\n filters?: PermissionCriteria<QetaFilters>,\n opts?: AnswerOptions,\n ): Promise<Answers> {\n return this.answersStore.getAnswers(user_ref, options, filters, opts);\n }\n\n async getAnswer(\n answerId: number,\n user_ref: string,\n options?: AnswerOptions,\n ): Promise<MaybeAnswer> {\n return this.answersStore.getAnswer(answerId, user_ref, options);\n }\n\n async answerPost(\n user_ref: string,\n questionId: number,\n answer: string,\n created: Date,\n images?: number[],\n anonymous?: boolean,\n options?: AnswerOptions,\n ): Promise<MaybeAnswer> {\n return this.answersStore.answerPost(\n user_ref,\n questionId,\n answer,\n created,\n images,\n anonymous,\n options,\n );\n }\n\n async updateAnswer(\n user_ref: string,\n questionId: number,\n answerId: number,\n answer: string,\n author?: string,\n images?: number[],\n options?: AnswerOptions,\n ): Promise<MaybeAnswer> {\n return this.answersStore.updateAnswer(\n user_ref,\n questionId,\n answerId,\n answer,\n author,\n images,\n options,\n );\n }\n\n async deleteAnswer(id: number): Promise<boolean> {\n return this.answersStore.deleteAnswer(id);\n }\n\n async voteAnswer(\n user_ref: string,\n answerId: number,\n score: number,\n ): Promise<boolean> {\n return this.answersStore.voteAnswer(user_ref, answerId, score);\n }\n\n async deleteAnswerVote(user_ref: string, answerId: number): Promise<boolean> {\n return this.answersStore.deleteAnswerVote(user_ref, answerId);\n }\n\n async markAnswerCorrect(postId: number, answerId: number): Promise<boolean> {\n return this.answersStore.markAnswerCorrect(postId, answerId);\n }\n\n async markAnswerIncorrect(\n postId: number,\n answerId: number,\n ): Promise<boolean> {\n return this.answersStore.markAnswerIncorrect(postId, answerId);\n }\n\n async clickPost(user_ref: string, postId: number): Promise<void> {\n const vote = await this.postsStore.getPostVote(user_ref, postId);\n const score = (vote?.score || 0) + 1;\n await this.postsStore.votePost(user_ref, postId, score);\n }\n\n async commentPost(\n post_id: number,\n user_ref: string,\n content: string,\n created: Date,\n ): Promise<MaybePost> {\n await this.commentsStore.commentPost(post_id, user_ref, content, created);\n return this.getPost(user_ref, post_id);\n }\n\n async commentAnswer(\n answer_id: number,\n user_ref: string,\n content: string,\n created: Date,\n ): Promise<MaybeAnswer> {\n await this.commentsStore.commentAnswer(\n answer_id,\n user_ref,\n content,\n created,\n );\n return this.getAnswer(answer_id, user_ref);\n }\n\n async updatePostComment(\n post_id: number,\n id: number,\n user_ref: string,\n content: string,\n ): Promise<MaybePost> {\n await this.commentsStore.updatePostComment(post_id, id, user_ref, content);\n return this.getPost(user_ref, post_id);\n }\n\n async updateAnswerComment(\n answer_id: number,\n id: number,\n user_ref: string,\n content: string,\n ): Promise<MaybeAnswer> {\n await this.commentsStore.updateAnswerComment(\n answer_id,\n id,\n user_ref,\n content,\n );\n return this.getAnswer(answer_id, user_ref);\n }\n\n async deletePostComment(\n post_id: number,\n id: number,\n user_ref: string,\n ): Promise<MaybePost> {\n await this.commentsStore.deletePostComment(post_id, id);\n return this.getPost(user_ref, post_id);\n }\n\n async deleteAnswerComment(\n answer_id: number,\n id: number,\n user_ref: string,\n ): Promise<MaybeAnswer> {\n await this.commentsStore.deleteAnswerComment(answer_id, id);\n return this.getAnswer(answer_id, user_ref);\n }\n\n async getCollections(\n user_ref: string,\n options: PostsQuery,\n opts?: CollectionOptions,\n ): Promise<Collections> {\n return this.collectionsStore.getCollections(user_ref, options, opts);\n }\n\n async getCollection(\n user_ref: string,\n id: number,\n options?: CollectionOptions,\n ): Promise<MaybeCollection> {\n return this.collectionsStore.getCollection(user_ref, id, options);\n }\n\n async createCollection(options: {\n user_ref: string;\n title: string;\n description?: string;\n created: Date;\n images?: number[];\n headerImage?: string;\n opts?: CollectionOptions;\n }): Promise<Collection> {\n return this.collectionsStore.createCollection(\n options,\n ) as Promise<Collection>;\n }\n\n async updateCollection(options: {\n id: number;\n user_ref: string;\n title: string;\n description?: string;\n images?: number[];\n headerImage?: string;\n opts?: CollectionOptions;\n }): Promise<MaybeCollection> {\n return this.collectionsStore.updateCollection(options);\n }\n\n async deleteCollection(id: number): Promise<boolean> {\n return this.collectionsStore.deleteCollection(id);\n }\n\n async addPostToCollection(\n user_ref: string,\n id: number,\n postId: number,\n options?: CollectionOptions,\n ): Promise<MaybeCollection> {\n return this.collectionsStore.addPostToCollection(\n user_ref,\n id,\n postId,\n options,\n );\n }\n\n async removePostFromCollection(\n user_ref: string,\n id: number,\n postId: number,\n options?: CollectionOptions,\n ): Promise<MaybeCollection> {\n return this.collectionsStore.removePostFromCollection(\n user_ref,\n id,\n postId,\n options,\n );\n }\n\n async getUsersForCollection(collectionId: number): Promise<string[]> {\n return this.collectionsStore.getUsersForCollection(collectionId);\n }\n\n async followCollection(\n user_ref: string,\n collectionId: number,\n ): Promise<boolean> {\n return this.collectionsStore.followCollection(user_ref, collectionId);\n }\n\n async unfollowCollection(\n user_ref: string,\n collectionId: number,\n ): Promise<boolean> {\n return this.collectionsStore.unfollowCollection(user_ref, collectionId);\n }\n\n async getUserCollections(\n user_ref: string,\n options?: CollectionOptions,\n ): Promise<UserCollectionsResponse> {\n return this.collectionsStore.getUserCollections(user_ref, options);\n }\n\n async getPostRank(\n collectionId: number,\n postId: number,\n ): Promise<number | null> {\n return this.collectionsStore.getPostRank(collectionId, postId);\n }\n\n async getTopRankedPostId(\n collectionId: number,\n ): Promise<CollectionPostRank | null> {\n return this.collectionsStore.getTopRankedPostId(collectionId);\n }\n\n async getBottomRankedPostId(\n collectionId: number,\n ): Promise<CollectionPostRank | null> {\n return this.collectionsStore.getBottomRankedPostId(collectionId);\n }\n\n async getNextRankedPostId(\n collectionId: number,\n postId: number,\n ): Promise<CollectionPostRank | null> {\n return this.collectionsStore.getNextRankedPostId(collectionId, postId);\n }\n\n async getPreviousRankedPostId(\n collectionId: number,\n postId: number,\n ): Promise<CollectionPostRank | null> {\n return this.collectionsStore.getPreviousRankedPostId(collectionId, postId);\n }\n\n async updatePostRank(\n collectionId: number,\n postId: number,\n rank: number,\n ): Promise<void> {\n return this.collectionsStore.updatePostRank(collectionId, postId, rank);\n }\n\n async getTags(\n options?: { noDescription?: boolean; ids?: number[] } & TagsQuery,\n filters?: PermissionCriteria<QetaFilters>,\n ): Promise<TagsResponse> {\n return this.tagsStore.getTags(options, filters);\n }\n\n async getTagExperts(tags: string[]): Promise<string[]> {\n return this.tagsStore.getTagExperts(tags);\n }\n\n async getTag(tag: string): Promise<TagResponse | null> {\n return this.tagsStore.getTag(tag);\n }\n\n async getTagById(id: number): Promise<TagResponse | null> {\n return this.tagsStore.getTagById(id);\n }\n\n async createTag(\n tag: string,\n description?: string,\n experts?: string[],\n ): Promise<TagResponse | null> {\n return this.tagsStore.createTag(tag, description, experts);\n }\n\n async updateTag(\n id: number,\n description?: string,\n experts?: string[],\n ): Promise<TagResponse | null> {\n return this.tagsStore.updateTag(id, description, experts);\n }\n\n async deleteTag(id: number): Promise<boolean> {\n return this.tagsStore.deleteTag(id);\n }\n\n async getEntities(\n options?: { entityRefs?: string[] } & EntitiesQuery,\n ): Promise<EntitiesResponse> {\n return this.entitiesStore.getEntities(options);\n }\n\n async getEntity(entity_ref: string): Promise<EntityResponse | null> {\n return this.entitiesStore.getEntity(entity_ref);\n }\n\n async getUsers(\n options?: { entityRefs?: string[] } & UsersQuery,\n ): Promise<UsersResponse> {\n return this.usersStore.getUsers(options);\n }\n\n async getUser(user_ref: string): Promise<UserResponse | null> {\n return this.usersStore.getUser(user_ref);\n }\n\n async getUserTags(\n user_ref: string,\n filters?: PermissionCriteria<QetaFilters>,\n ): Promise<UserTagsResponse> {\n return this.tagsStore.getUserTags(user_ref, filters);\n }\n\n async followTag(user_ref: string, tag: string): Promise<boolean> {\n return this.tagsStore.followTag(user_ref, tag);\n }\n\n async unfollowTag(user_ref: string, tag: string): Promise<boolean> {\n return this.tagsStore.unfollowTag(user_ref, tag);\n }\n\n async getUserEntities(user_ref: string): Promise<UserEntitiesResponse> {\n return this.entitiesStore.getUserEntities(user_ref);\n }\n\n async followEntity(user_ref: string, entityRef: string): Promise<boolean> {\n return this.entitiesStore.followEntity(user_ref, entityRef);\n }\n\n async unfollowEntity(user_ref: string, entityRef: string): Promise<boolean> {\n return this.entitiesStore.unfollowEntity(user_ref, entityRef);\n }\n\n async getUsersForTags(tags: string[]): Promise<string[]> {\n return this.tagsStore.getUsersForTags(tags);\n }\n\n async getUsersForEntities(entityRefs: string[]): Promise<string[]> {\n return this.entitiesStore.getUsersForEntities(entityRefs);\n }\n\n async getFollowedUsers(user_ref: string): Promise<UserUsersResponse> {\n return this.usersStore.getFollowedUsers(user_ref);\n }\n\n async followUser(\n user_ref: string,\n followedUserRef: string,\n ): Promise<boolean> {\n return this.usersStore.followUser(user_ref, followedUserRef);\n }\n\n async unfollowUser(\n user_ref: string,\n followedUserRef: string,\n ): Promise<boolean> {\n return this.usersStore.unfollowUser(user_ref, followedUserRef);\n }\n\n async getGlobalStats(): Promise<GlobalStat[]> {\n return this.statsStore.getGlobalStats();\n }\n\n async getUserStats(user_ref: string): Promise<UserStat[]> {\n return this.statsStore.getUserStats(user_ref);\n }\n\n async getTemplates(): Promise<Templates> {\n return this.templatesStore.getTemplates();\n }\n\n async getTemplate(id: number): Promise<Template | null> {\n return this.templatesStore.getTemplate(id);\n }\n\n async createTemplate(options: {\n title: string;\n description: string;\n questionTitle?: string;\n questionContent?: string;\n tags?: string[];\n entities?: string[];\n }): Promise<Template> {\n return this.templatesStore.createTemplate(options);\n }\n\n async deleteTemplate(id: number): Promise<boolean> {\n return this.templatesStore.deleteTemplate(id);\n }\n\n async updateTemplate(options: {\n id: number;\n title: string;\n description: string;\n questionTitle?: string;\n questionContent?: string;\n tags?: string[];\n entities?: string[];\n }): Promise<Template | null> {\n return this.templatesStore.updateTemplate(options);\n }\n\n async reviewPost(\n user_ref: string,\n postId: number,\n status: 'valid' | 'obsolete',\n comment?: string,\n ): Promise<MaybePost> {\n return this.postsStore.reviewPost(user_ref, postId, status, comment);\n }\n\n async getPostReviews(postId: number): Promise<PostReview[]> {\n return this.postsStore.getPostReviews(postId);\n }\n\n async getAIAnswer(postId: number): Promise<AIResponse | null> {\n return this.postsStore.getAIAnswer(postId);\n }\n\n async saveAIAnswer(postId: number, response: AIResponse): Promise<void> {\n return this.postsStore.saveAIAnswer(postId, response);\n }\n\n async deleteAIAnswer(postId: number): Promise<boolean> {\n return this.postsStore.deleteAIAnswer(postId);\n }\n\n async postAttachment({\n uuid,\n locationType,\n locationUri,\n extension,\n mimeType,\n binaryImage,\n path,\n creator,\n }: AttachmentParameters): Promise<Attachment> {\n return this.attachmentsStore.postAttachment({\n uuid,\n locationType,\n locationUri,\n extension,\n mimeType,\n binaryImage,\n path,\n creator,\n });\n }\n\n async getAttachment(uuid: string): Promise<Attachment | undefined> {\n return this.attachmentsStore.getAttachment(uuid);\n }\n\n async deleteAttachment(uuid: string): Promise<boolean> {\n return this.attachmentsStore.deleteAttachment(uuid);\n }\n\n async getDeletableAttachments(dayLimit: number): Promise<Attachment[]> {\n return this.attachmentsStore.getDeletableAttachments(dayLimit);\n }\n\n // Stats\n\n async getMostUpvotedPosts({\n author,\n options,\n }: StatisticsRequestParameters): Promise<Statistic[]> {\n return this.statsStore.getMostUpvotedPosts({ author, options });\n }\n\n async getTotalPosts({\n author,\n options,\n }: StatisticsRequestParameters): Promise<Statistic[]> {\n return this.statsStore.getTotalPosts({ author, options });\n }\n\n async getMostUpvotedAnswers({\n author,\n options,\n }: StatisticsRequestParameters): Promise<Statistic[]> {\n return this.statsStore.getMostUpvotedAnswers({ author, options });\n }\n\n async getMostUpvotedCorrectAnswers({\n author,\n options,\n }: StatisticsRequestParameters): Promise<Statistic[]> {\n return this.statsStore.getMostUpvotedCorrectAnswers({ author, options });\n }\n\n async getTotalAnswers({\n author,\n options,\n }: StatisticsRequestParameters): Promise<Statistic[]> {\n return this.statsStore.getTotalAnswers({ author, options });\n }\n\n async getCount(\n table: string,\n filters?: { author?: string; type?: PostType },\n ): Promise<number> {\n return this.statsStore.getCount(table, filters);\n }\n\n async saveGlobalStats(date: Date): Promise<void> {\n return this.statsStore.saveGlobalStats(date);\n }\n\n async saveUserStats(userRef: string, date: Date): Promise<void> {\n return this.statsStore.saveUserStats(userRef, date);\n }\n\n async getTotalViews(\n user_ref: string,\n lastDays?: number,\n excludeUser?: boolean,\n ): Promise<number> {\n return this.statsStore.getTotalViews(user_ref, lastDays, excludeUser);\n }\n\n async getBadges(): Promise<Badge[]> {\n return this.badgesStore.getBadges();\n }\n\n async getBadge(key: string): Promise<Badge | undefined> {\n return this.badgesStore.getBadge(key);\n }\n\n async getUserBadges(userRef: string): Promise<UserBadge[]> {\n return this.badgesStore.getUserBadges(userRef);\n }\n\n async awardBadge(\n userRef: string,\n badgeKey: string,\n uniqueKey?: string,\n ): Promise<AwardBadgeResult | null> {\n return this.badgesStore.awardBadge(userRef, badgeKey, uniqueKey);\n }\n\n async createBadge(badge: Omit<Badge, 'id'>): Promise<void> {\n return this.badgesStore.createBadge(badge);\n }\n\n async suggestPosts(\n user_ref: string,\n title: string,\n content: string,\n tags?: string[],\n entities?: string[],\n filters?: PermissionCriteria<QetaFilters>,\n opts?: PostOptions,\n ): Promise<Posts> {\n return this.postsStore.suggestPosts(\n user_ref,\n title,\n content,\n tags,\n entities,\n filters,\n opts,\n );\n }\n\n async cleanStats(days: number, date: Date): Promise<void> {\n return this.statsStore.cleanStats(days, date);\n }\n\n async getUsersCount(): Promise<number> {\n return this.usersStore.getUsersCount();\n }\n\n async getFollowingUsers(user_ref: string): Promise<string[]> {\n return this.usersStore.getFollowingUsers(user_ref);\n }\n\n async getEntityLinks(): Promise<EntityLinks[]> {\n return this.entitiesStore.getEntityLinks();\n }\n\n async getComments(\n options?: { ids?: number[] },\n opts?: CommentOptions,\n ): Promise<QetaComment[]> {\n return this.commentsStore.getComments(options, opts);\n }\n\n async getComment(\n commentId: number,\n opts?: CommentOptions & { postId?: number; answerId?: number },\n ): Promise<QetaComment | null> {\n return this.commentsStore.getComment(commentId, opts);\n }\n}\n"],"names":["resolvePackagePath","CommentsStore","TagsStore","EntitiesStore","UsersStore","TemplatesStore","AttachmentsStore","PostsStore","AnswersStore","CollectionsStore","StatsStore","BadgesStore","HelpersStore"],"mappings":"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"}
@@ -0,0 +1,173 @@
1
+ 'use strict';
2
+
3
+ var BaseStore = require('./BaseStore.cjs.js');
4
+
5
+ class HelpersStore extends BaseStore.BaseStore {
6
+ async getTimeline(_user_ref, options, filters) {
7
+ const limit = options.limit ?? 10;
8
+ const offset = options.offset ?? 0;
9
+ const collectionsQuery = this.db("collections").select(
10
+ this.db.raw("'collection' as type"),
11
+ "collections.id",
12
+ "collections.owner as author",
13
+ "collections.created as date",
14
+ this.db.raw("'created' as action"),
15
+ this.db.raw("CAST(null as TEXT) as content"),
16
+ this.db.raw('CAST(null as INTEGER) as "postId"'),
17
+ this.db.raw('CAST(null as INTEGER) as "answerId"'),
18
+ "collections.headerImage",
19
+ "collections.title",
20
+ this.db.raw('CAST(null as TEXT) as "postTitle"'),
21
+ this.db.raw('CAST(null as TEXT) as "postType"')
22
+ );
23
+ if (filters?.collections) {
24
+ this.parseFilter(
25
+ filters.collections,
26
+ collectionsQuery,
27
+ this.db,
28
+ "collection"
29
+ );
30
+ }
31
+ const postsQuery = this.db("posts").select(
32
+ this.db.raw("'post' as type"),
33
+ "id",
34
+ "author",
35
+ "created as date",
36
+ this.db.raw("'created' as action"),
37
+ "content",
38
+ "id as postId",
39
+ this.db.raw('CAST(null as INTEGER) as "answerId"'),
40
+ "headerImage",
41
+ "title",
42
+ "title as postTitle",
43
+ "type as postType"
44
+ ).where("status", "active");
45
+ if (filters?.posts) {
46
+ this.parseFilter(filters.posts, postsQuery, this.db, "post");
47
+ }
48
+ const postsUpdateQuery = this.db("posts").select(
49
+ this.db.raw("'post' as type"),
50
+ "id",
51
+ "updatedBy as author",
52
+ "updated as date",
53
+ this.db.raw("'updated' as action"),
54
+ "content",
55
+ "id as postId",
56
+ this.db.raw('CAST(null as INTEGER) as "answerId"'),
57
+ "headerImage",
58
+ "title",
59
+ "title as postTitle",
60
+ "type as postType"
61
+ ).where("status", "active").whereNotNull("updated").whereRaw("updated > created");
62
+ if (filters?.posts) {
63
+ this.parseFilter(filters.posts, postsUpdateQuery, this.db, "post");
64
+ }
65
+ const answersQuery = this.db("answers").leftJoin("posts", "answers.postId", "posts.id").select(
66
+ this.db.raw("'answer' as type"),
67
+ "answers.id",
68
+ "answers.author",
69
+ "answers.created as date",
70
+ this.db.raw("'created' as action"),
71
+ "answers.content",
72
+ "answers.postId",
73
+ "answers.id as answerId",
74
+ this.db.raw('CAST(null as TEXT) as "headerImage"'),
75
+ this.db.raw('CAST(null as TEXT) as "title"'),
76
+ "posts.title as postTitle",
77
+ "posts.type as postType"
78
+ ).where("posts.status", "active");
79
+ if (filters?.posts) {
80
+ this.parseFilter(filters.posts, answersQuery, this.db, "post");
81
+ }
82
+ if (filters?.answers) {
83
+ this.parseFilter(filters.answers, answersQuery, this.db, "answer");
84
+ }
85
+ const answersUpdateQuery = this.db("answers").leftJoin("posts", "answers.postId", "posts.id").select(
86
+ this.db.raw("'answer' as type"),
87
+ "answers.id",
88
+ "answers.updatedBy as author",
89
+ "answers.updated as date",
90
+ this.db.raw("'updated' as action"),
91
+ "answers.content",
92
+ "answers.postId",
93
+ "answers.id as answerId",
94
+ this.db.raw('CAST(null as TEXT) as "headerImage"'),
95
+ this.db.raw('CAST(null as TEXT) as "title"'),
96
+ "posts.title as postTitle",
97
+ "posts.type as postType"
98
+ ).where("posts.status", "active").whereNotNull("answers.updated").whereRaw("answers.updated > answers.created");
99
+ if (filters?.posts) {
100
+ this.parseFilter(filters.posts, answersUpdateQuery, this.db, "post");
101
+ }
102
+ if (filters?.answers) {
103
+ this.parseFilter(filters.answers, answersUpdateQuery, this.db, "answer");
104
+ }
105
+ const commentsQuery = this.db("comments").leftJoin("posts", "comments.postId", "posts.id").leftJoin("answers", "comments.answerId", "answers.id").leftJoin("posts as answerPosts", "answers.postId", "answerPosts.id").select(
106
+ this.db.raw("'comment' as type"),
107
+ "comments.id",
108
+ "comments.author",
109
+ "comments.created as date",
110
+ this.db.raw("'created' as action"),
111
+ "comments.content",
112
+ this.db.raw(
113
+ 'COALESCE("comments"."postId", "answers"."postId") as "postId"'
114
+ ),
115
+ "comments.answerId",
116
+ this.db.raw('CAST(null as TEXT) as "headerImage"'),
117
+ this.db.raw('CAST(null as TEXT) as "title"'),
118
+ this.db.raw(
119
+ 'COALESCE("posts"."title", "answerPosts"."title") as "postTitle"'
120
+ ),
121
+ this.db.raw(
122
+ 'COALESCE("posts"."type", "answerPosts"."type") as "postType"'
123
+ )
124
+ ).where((builder) => {
125
+ builder.where("posts.status", "active").orWhere("answerPosts.status", "active");
126
+ });
127
+ if (filters?.comments) {
128
+ this.parseFilter(filters.comments, commentsQuery, this.db, "comments");
129
+ }
130
+ const unionQuery = this.db.union([
131
+ postsQuery,
132
+ postsUpdateQuery,
133
+ answersQuery,
134
+ answersUpdateQuery,
135
+ commentsQuery,
136
+ collectionsQuery
137
+ ]).orderBy("date", "desc").limit(limit).offset(offset);
138
+ const rows = await unionQuery;
139
+ let total;
140
+ if (options.includeTotal) {
141
+ const subQuery = this.db.union([
142
+ postsQuery.clone().clearSelect().select("id"),
143
+ postsUpdateQuery.clone().clearSelect().select("id"),
144
+ answersQuery.clone().clearSelect().select("answers.id"),
145
+ answersUpdateQuery.clone().clearSelect().select("answers.id"),
146
+ commentsQuery.clone().clearSelect().select("comments.id"),
147
+ collectionsQuery.clone().clearSelect().select("collections.id")
148
+ ]);
149
+ const totalResult = await this.db.count("* as total").from(subQuery.as("t"));
150
+ total = Number(totalResult[0].total);
151
+ }
152
+ return {
153
+ items: rows.map((row) => ({
154
+ type: row.type,
155
+ id: row.id,
156
+ author: row.author,
157
+ date: new Date(row.date),
158
+ action: row.action,
159
+ content: row.content,
160
+ postId: row.postId,
161
+ answerId: row.answerId,
162
+ headerImage: row.headerImage,
163
+ title: row.title,
164
+ postTitle: row.postTitle,
165
+ postType: row.postType
166
+ })),
167
+ total
168
+ };
169
+ }
170
+ }
171
+
172
+ exports.HelpersStore = HelpersStore;
173
+ //# sourceMappingURL=HelpersStore.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HelpersStore.cjs.js","sources":["../../../src/database/stores/HelpersStore.ts"],"sourcesContent":["import { BaseStore } from './BaseStore';\nimport { TimelineFilters } from '../QetaStore';\nimport {\n TimelineOptions,\n TimelineResponse,\n} from '@drodil/backstage-plugin-qeta-common';\n\nexport class HelpersStore extends BaseStore {\n async getTimeline(\n _user_ref: string,\n options: TimelineOptions,\n filters?: TimelineFilters,\n ): Promise<TimelineResponse> {\n const limit = options.limit ?? 10;\n const offset = options.offset ?? 0;\n\n const collectionsQuery = this.db('collections').select(\n this.db.raw(\"'collection' as type\"),\n 'collections.id',\n 'collections.owner as author',\n 'collections.created as date',\n this.db.raw(\"'created' as action\"),\n this.db.raw('CAST(null as TEXT) as content'),\n this.db.raw('CAST(null as INTEGER) as \"postId\"'),\n this.db.raw('CAST(null as INTEGER) as \"answerId\"'),\n 'collections.headerImage',\n 'collections.title',\n this.db.raw('CAST(null as TEXT) as \"postTitle\"'),\n this.db.raw('CAST(null as TEXT) as \"postType\"'),\n );\n if (filters?.collections) {\n this.parseFilter(\n filters.collections,\n collectionsQuery,\n this.db,\n 'collection',\n );\n }\n\n const postsQuery = this.db('posts')\n .select(\n this.db.raw(\"'post' as type\"),\n 'id',\n 'author',\n 'created as date',\n this.db.raw(\"'created' as action\"),\n 'content',\n 'id as postId',\n this.db.raw('CAST(null as INTEGER) as \"answerId\"'),\n 'headerImage',\n 'title',\n 'title as postTitle',\n 'type as postType',\n )\n .where('status', 'active');\n if (filters?.posts) {\n this.parseFilter(filters.posts, postsQuery, this.db, 'post');\n }\n\n const postsUpdateQuery = this.db('posts')\n .select(\n this.db.raw(\"'post' as type\"),\n 'id',\n 'updatedBy as author',\n 'updated as date',\n this.db.raw(\"'updated' as action\"),\n 'content',\n 'id as postId',\n this.db.raw('CAST(null as INTEGER) as \"answerId\"'),\n 'headerImage',\n 'title',\n 'title as postTitle',\n 'type as postType',\n )\n .where('status', 'active')\n .whereNotNull('updated')\n .whereRaw('updated > created');\n if (filters?.posts) {\n this.parseFilter(filters.posts, postsUpdateQuery, this.db, 'post');\n }\n\n const answersQuery = this.db('answers')\n .leftJoin('posts', 'answers.postId', 'posts.id')\n .select(\n this.db.raw(\"'answer' as type\"),\n 'answers.id',\n 'answers.author',\n 'answers.created as date',\n this.db.raw(\"'created' as action\"),\n 'answers.content',\n 'answers.postId',\n 'answers.id as answerId',\n this.db.raw('CAST(null as TEXT) as \"headerImage\"'),\n this.db.raw('CAST(null as TEXT) as \"title\"'),\n 'posts.title as postTitle',\n 'posts.type as postType',\n )\n .where('posts.status', 'active');\n if (filters?.posts) {\n this.parseFilter(filters.posts, answersQuery, this.db, 'post');\n }\n if (filters?.answers) {\n this.parseFilter(filters.answers, answersQuery, this.db, 'answer');\n }\n\n const answersUpdateQuery = this.db('answers')\n .leftJoin('posts', 'answers.postId', 'posts.id')\n .select(\n this.db.raw(\"'answer' as type\"),\n 'answers.id',\n 'answers.updatedBy as author',\n 'answers.updated as date',\n this.db.raw(\"'updated' as action\"),\n 'answers.content',\n 'answers.postId',\n 'answers.id as answerId',\n this.db.raw('CAST(null as TEXT) as \"headerImage\"'),\n this.db.raw('CAST(null as TEXT) as \"title\"'),\n 'posts.title as postTitle',\n 'posts.type as postType',\n )\n .where('posts.status', 'active')\n .whereNotNull('answers.updated')\n .whereRaw('answers.updated > answers.created');\n if (filters?.posts) {\n this.parseFilter(filters.posts, answersUpdateQuery, this.db, 'post');\n }\n if (filters?.answers) {\n this.parseFilter(filters.answers, answersUpdateQuery, this.db, 'answer');\n }\n\n const commentsQuery = this.db('comments')\n .leftJoin('posts', 'comments.postId', 'posts.id')\n .leftJoin('answers', 'comments.answerId', 'answers.id')\n .leftJoin('posts as answerPosts', 'answers.postId', 'answerPosts.id')\n .select(\n this.db.raw(\"'comment' as type\"),\n 'comments.id',\n 'comments.author',\n 'comments.created as date',\n this.db.raw(\"'created' as action\"),\n 'comments.content',\n this.db.raw(\n 'COALESCE(\"comments\".\"postId\", \"answers\".\"postId\") as \"postId\"',\n ),\n 'comments.answerId',\n this.db.raw('CAST(null as TEXT) as \"headerImage\"'),\n this.db.raw('CAST(null as TEXT) as \"title\"'),\n this.db.raw(\n 'COALESCE(\"posts\".\"title\", \"answerPosts\".\"title\") as \"postTitle\"',\n ),\n this.db.raw(\n 'COALESCE(\"posts\".\"type\", \"answerPosts\".\"type\") as \"postType\"',\n ),\n )\n .where(builder => {\n builder\n .where('posts.status', 'active')\n .orWhere('answerPosts.status', 'active');\n });\n if (filters?.comments) {\n this.parseFilter(filters.comments, commentsQuery, this.db, 'comments');\n }\n\n const unionQuery = this.db\n .union([\n postsQuery,\n postsUpdateQuery,\n answersQuery,\n answersUpdateQuery,\n commentsQuery,\n collectionsQuery,\n ])\n .orderBy('date', 'desc')\n .limit(limit)\n .offset(offset);\n\n const rows = await unionQuery;\n let total;\n\n if (options.includeTotal) {\n const subQuery = this.db.union([\n postsQuery.clone().clearSelect().select('id'),\n postsUpdateQuery.clone().clearSelect().select('id'),\n answersQuery.clone().clearSelect().select('answers.id'),\n answersUpdateQuery.clone().clearSelect().select('answers.id'),\n commentsQuery.clone().clearSelect().select('comments.id'),\n collectionsQuery.clone().clearSelect().select('collections.id'),\n ]);\n const totalResult = await this.db\n .count('* as total')\n .from(subQuery.as('t'));\n total = Number((totalResult[0] as any).total);\n }\n\n return {\n items: rows.map((row: any) => ({\n type: row.type,\n id: row.id,\n author: row.author,\n date: new Date(row.date),\n action: row.action,\n content: row.content,\n postId: row.postId,\n answerId: row.answerId,\n headerImage: row.headerImage,\n title: row.title,\n postTitle: row.postTitle,\n postType: row.postType,\n })),\n total,\n };\n }\n}\n"],"names":["BaseStore"],"mappings":"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"}
@@ -349,7 +349,6 @@ class PostsStore extends BaseStore.BaseStore {
349
349
  ...entityPosts.posts
350
350
  ];
351
351
  const uniquePosts = Array.from(new Set(allPosts.map((p) => p.id))).map((id) => allPosts.find((p) => p.id === id)).filter((p) => p !== void 0);
352
- console.log(`Unique posts: ${uniquePosts.map((p) => p.id).join(", ")}`);
353
352
  return { posts: uniquePosts.slice(0, 5), total: uniquePosts.length };
354
353
  }
355
354
  async getPost(user_ref, id, recordView, options) {
@@ -1 +1 @@
1
- {"version":3,"file":"PostsStore.cjs.js","sources":["../../../src/database/stores/PostsStore.ts"],"sourcesContent":["import {\n AIResponse,\n Answer,\n Comment as QetaComment,\n filterTags,\n Post,\n PostReview,\n PostsQuery,\n PostStatus,\n PostType,\n} from '@drodil/backstage-plugin-qeta-common';\nimport { MaybePost, PostOptions, Posts } from '../QetaStore';\nimport { QetaFilters } from '../../service/util';\nimport { Knex } from 'knex';\nimport { AnswersStore } from './AnswersStore';\nimport { CommentsStore } from './CommentsStore';\nimport { TagsStore } from './TagsStore';\nimport { EntitiesStore } from './EntitiesStore';\nimport { AttachmentsStore } from './AttachmentsStore';\nimport { PermissionCriteria } from '@backstage/plugin-permission-common';\nimport { TAGS } from '../../tagDb';\nimport { BaseStore } from './BaseStore';\nimport { TagDatabase } from '@drodil/backstage-plugin-qeta-node';\n\nimport { removeStopwords, eng } from 'stopword';\n\nexport interface RawPostEntity {\n id: number;\n author: string;\n title: string;\n content: string;\n status: string;\n created: Date | string;\n updated: Date | string;\n updatedBy: string;\n score: number | string;\n views: number | string;\n answersCount: number | string;\n correctAnswers: number | string;\n commentsCount: number | string;\n favorite: number | string;\n trend: number | string;\n anonymous: boolean;\n type: 'question' | 'article' | 'link';\n headerImage: string;\n url: string | null;\n published: Date | string | null;\n obsolete: number | string | boolean;\n last_interaction?: Date | string;\n}\n\nexport interface RawPostVoteEntity {\n postId: number;\n author: string;\n score: number;\n timestamp: Date;\n}\n\nexport interface RawPostAIAnswer {\n id: number;\n answer: string;\n created: Date;\n}\n\nexport class PostsStore extends BaseStore {\n private answersStore?: AnswersStore;\n\n constructor(\n protected readonly db: Knex,\n private readonly commentsStore: CommentsStore,\n private readonly tagsStore: TagsStore,\n private readonly entitiesStore: EntitiesStore,\n private readonly attachmentsStore: AttachmentsStore,\n private readonly tagDatabase?: TagDatabase,\n ) {\n super(db);\n }\n\n setAnswersStore(answersStore: AnswersStore) {\n this.answersStore = answersStore;\n }\n\n async getAIAnswer(postId: number): Promise<AIResponse | null> {\n const row = await this.db('post_ai_answers')\n .where('postId', postId)\n .first();\n if (!row) {\n return null;\n }\n return {\n answer: row.answer,\n created: row.created,\n };\n }\n\n async saveAIAnswer(postId: number, response: AIResponse): Promise<void> {\n await this.db\n .insert({\n postId,\n answer: response.answer,\n created: response.created,\n })\n .into('post_ai_answers')\n .onConflict('postId')\n .merge();\n }\n\n async deleteAIAnswer(postId: number): Promise<boolean> {\n const deleted = await this.db('post_ai_answers')\n .where('postId', postId)\n .del();\n return deleted > 0;\n }\n\n async reviewPost(\n user_ref: string,\n postId: number,\n status: 'valid' | 'obsolete',\n comment?: string,\n ): Promise<MaybePost> {\n await this.db('post_reviews').insert({\n post_id: postId,\n reviewer: user_ref,\n status,\n comment,\n created: new Date(),\n });\n\n if (status === 'obsolete') {\n await this.db('posts').where('id', postId).update({ status: 'obsolete' });\n } else {\n await this.db('posts').where('id', postId).update({ status: 'active' });\n }\n\n return this.getPost(user_ref, postId, false, {\n includeHealth: true,\n reviewThresholdMs: 15552000000, // 180 days default\n });\n }\n\n async getPostReviews(postId: number): Promise<PostReview[]> {\n const rows = await this.db('post_reviews')\n .where('post_id', postId)\n .orderBy('created', 'desc')\n .select('*');\n\n return rows.map(row => ({\n id: row.id,\n postId: row.post_id,\n reviewer: row.reviewer,\n status: row.status,\n comment: row.comment,\n created: new Date(row.created),\n }));\n }\n\n async getPosts(\n user_ref: string,\n options: PostsQuery,\n filters?: PermissionCriteria<QetaFilters>,\n opts?: PostOptions,\n ): Promise<Posts> {\n const {\n includeTotal = true,\n includeDraftFilter = true,\n includeHealth = false,\n } = opts ?? {};\n const query = this.getPostsBaseQuery(user_ref, options);\n if (options.type) {\n query.where('posts.type', options.type);\n }\n\n if (options.obsolete !== undefined) {\n if (options.obsolete) {\n query.where('posts.status', 'obsolete');\n } else {\n query.where(q => {\n q.whereNot('posts.status', 'obsolete');\n });\n }\n }\n\n if (options.fromDate && options.toDate) {\n query.whereBetween('posts.created', [\n `${options.fromDate} 00:00:00.000+00`,\n `${options.toDate} 23:59:59.999+00`,\n ]);\n } else if (options.fromDate) {\n query.where('posts.created', '>=', `${options.fromDate} 00:00:00.000+00`);\n } else if (options.toDate) {\n query.where('posts.created', '<=', `${options.toDate} 23:59:59.999+00`);\n }\n\n if (options.author) {\n if (Array.isArray(options.author)) {\n query.whereIn('posts.author', options.author);\n } else {\n query.where('posts.author', '=', options.author);\n }\n }\n\n if (options.excludeAuthors) {\n query.whereNotIn('posts.author', options.excludeAuthors);\n }\n\n if (options.status) {\n if (options.status === 'draft') {\n query.where('posts.author', '=', user_ref);\n }\n query.where('posts.status', '=', options.status);\n } else if (includeDraftFilter) {\n query.where(q => {\n q.whereIn('posts.status', ['active', 'obsolete']).orWhere(q2 => {\n q2.where('posts.status', 'draft').where(\n 'posts.author',\n '=',\n user_ref,\n );\n });\n });\n }\n\n if (filters) {\n this.parseFilter(filters, query, this.db);\n }\n\n if (options.searchQuery) {\n this.applySearchQuery(\n query,\n ['posts.title', 'posts.content'],\n options.searchQuery,\n );\n }\n\n if (options.tags) {\n const tags = filterTags(options.tags);\n if (options.tagsRelation === 'or') {\n query.innerJoin('post_tags', 'posts.id', 'post_tags.postId');\n query.innerJoin('tags', 'post_tags.tagId', 'tags.id');\n query.whereIn('tags.tag', tags);\n } else {\n tags?.forEach((t: string, i: number) => {\n query.innerJoin(`post_tags AS qt${i}`, 'posts.id', `qt${i}.postId`);\n query.innerJoin(`tags AS t${i}`, `qt${i}.tagId`, `t${i}.id`);\n query.where(`t${i}.tag`, '=', t);\n });\n }\n }\n\n if (options.entities) {\n const entityValues = Array.isArray(options.entities)\n ? options.entities\n : [options.entities];\n if (options.entitiesRelation === 'or') {\n query\n .innerJoin('post_entities', 'posts.id', 'post_entities.postId')\n .innerJoin('entities', 'post_entities.entityId', 'entities.id')\n .whereIn('entities.entity_ref', entityValues);\n } else {\n entityValues.forEach((t: string, i: number) => {\n query.innerJoin(\n `post_entities AS pe${i}`,\n 'posts.id',\n `pe${i}.postId`,\n );\n query.innerJoin(`entities AS e${i}`, `pe${i}.entityId`, `e${i}.id`);\n query.where(`e${i}.entity_ref`, '=', t);\n });\n }\n }\n\n if (options.collectionId) {\n query.innerJoin(\n 'collection_posts',\n 'posts.id',\n 'collection_posts.postId',\n );\n query.where('collection_posts.collectionId', options.collectionId);\n if (options.orderBy === 'rank') {\n query.select('collection_posts.rank');\n }\n } else if (opts?.collectionIds) {\n query.innerJoin(\n 'collection_posts',\n 'posts.id',\n 'collection_posts.postId',\n );\n query.whereIn('collection_posts.collectionId', opts.collectionIds);\n if (options.orderBy === 'rank') {\n query.select('collection_posts.rank');\n }\n } else if (options.orderBy === 'rank') {\n query.innerJoin(\n 'collection_posts',\n 'posts.id',\n 'collection_posts.postId',\n );\n query.select('collection_posts.rank');\n }\n if (options.orderBy === 'rank') {\n query.groupBy('posts.id', 'collection_posts.rank');\n }\n\n if (options.noAnswers) {\n query.where('answersCount', 0);\n }\n\n if (options.hasAnswers) {\n query.where('answersCount', '>', 0);\n }\n\n if (options.noCorrectAnswer) {\n query.where('correctAnswers', 0);\n }\n\n if (options.noVotes) {\n query.where('score', 0);\n }\n\n if (options.favorite) {\n query.where('user_favorite.user', '=', user_ref);\n query.whereNotNull('user_favorite.postId');\n }\n\n if (options.includeTrend || options.orderBy === 'trend') {\n query.select(\n this.db.raw(\n `(\n posts.score * 200 + \n posts.\"answersCount\" * 100 +\n posts.\"favoritesCount\" * 50 +\n posts.views * 10 +\n posts.\"commentsCount\" * 30\n ) / \n POWER(\n EXTRACT(EPOCH FROM (now() - posts.created)) / 172800 + 1,\n 1.5\n ) as trend`,\n ),\n );\n }\n\n if (includeHealth || options.reviewNeeded) {\n const func = this.db.client.config.client === 'pg' ? 'GREATEST' : 'MAX';\n const lastInteractionQuery = `${func}(\n posts.created,\n COALESCE((SELECT MAX(created) FROM answers WHERE answers.\"postId\" = posts.id), posts.created),\n COALESCE((SELECT MAX(created) FROM comments WHERE comments.\"postId\" = posts.id), posts.created),\n COALESCE((SELECT MAX(ac.created) FROM answers a JOIN comments ac ON ac.\"answerId\" = a.id WHERE a.\"postId\" = posts.id), posts.created),\n COALESCE((SELECT MAX(created) FROM post_reviews WHERE post_reviews.post_id = posts.id), posts.created)\n )`;\n\n query.select(this.db.raw(`${lastInteractionQuery} as last_interaction`));\n\n const reviewThresholdMs = opts?.reviewThresholdMs || 0;\n if (options.reviewNeeded && reviewThresholdMs > 0) {\n const thresholdDate = new Date(Date.now() - reviewThresholdMs);\n const thresholdParam = thresholdDate.toISOString();\n query.whereRaw(`${lastInteractionQuery} < ?`, [thresholdParam]);\n }\n if (options.reviewNeeded) {\n query.whereNotIn('posts.status', ['deleted', 'obsolete']);\n }\n }\n\n if (options.ids) {\n query.whereIn('posts.id', options.ids);\n }\n\n const totalQuery = query.clone();\n\n if (options.random) {\n query.orderByRaw('RANDOM()');\n } else if (options.orderBy) {\n query.orderBy(options.orderBy, options.order ? options.order : 'desc');\n } else {\n query.orderBy('created', 'desc');\n }\n\n if (options.limit) {\n query.limit(options.limit);\n }\n\n if (options.offset) {\n query.offset(options.offset);\n }\n\n const results = await Promise.all([\n query,\n includeTotal\n ? this.db(totalQuery.as('totalQuery')).count('* as CNT').first()\n : undefined,\n ]);\n const rows = results[0] as RawPostEntity[];\n const total = this.mapToInteger((results[1] as any)?.CNT);\n\n return {\n posts: await this.mapPostEntities(rows, user_ref, {\n ...opts,\n includeAnswers: options.includeAnswers ?? opts?.includeAnswers,\n includeVotes: options.includeVotes ?? opts?.includeVotes,\n includeEntities: options.includeEntities ?? opts?.includeEntities,\n includeAttachments:\n options.includeAttachments ?? opts?.includeAttachments,\n includeExperts: options.includeExperts ?? opts?.includeExperts,\n includeHealth: options.includeHealth ?? opts?.includeHealth,\n }),\n total,\n };\n }\n\n async suggestPosts(\n user_ref: string,\n title: string,\n content: string,\n tags?: string[],\n entities?: string[],\n filters?: PermissionCriteria<QetaFilters>,\n opts?: PostOptions,\n ): Promise<Posts> {\n const titleWords = removeStopwords(title.split(/\\s+/g), eng).join(' ');\n const contentWords = removeStopwords(content.split(/\\s+/g), eng).join(' ');\n\n const [titlePosts, contentPosts, tagPosts, entityPosts] = await Promise.all(\n [\n titleWords && titleWords.length > 0\n ? this.getPosts(\n user_ref,\n {\n searchQuery: titleWords,\n limit: 5,\n type: 'question',\n status: 'active',\n excludeAuthors: [user_ref],\n },\n filters,\n opts,\n )\n : Promise.resolve({ posts: [], total: 0 }),\n contentWords && contentWords.length > 0\n ? this.getPosts(\n user_ref,\n {\n searchQuery: contentWords,\n limit: 5,\n type: 'question',\n status: 'active',\n excludeAuthors: [user_ref],\n },\n filters,\n opts,\n )\n : Promise.resolve({ posts: [], total: 0 }),\n tags && tags.length > 0\n ? this.getPosts(\n user_ref,\n {\n limit: 5,\n type: 'question',\n tags: tags,\n tagsRelation: 'or',\n status: 'active',\n excludeAuthors: [user_ref],\n },\n filters,\n opts,\n )\n : Promise.resolve({ posts: [], total: 0 }),\n entities && entities.length > 0\n ? this.getPosts(\n user_ref,\n {\n limit: 5,\n type: 'question',\n entities: entities,\n entitiesRelation: 'or',\n status: 'active',\n excludeAuthors: [user_ref],\n },\n filters,\n opts,\n )\n : Promise.resolve({ posts: [], total: 0 }),\n ],\n );\n\n const allPosts = [\n ...titlePosts.posts,\n ...contentPosts.posts,\n ...tagPosts.posts,\n ...entityPosts.posts,\n ];\n\n const uniquePosts = Array.from(new Set(allPosts.map(p => p.id)))\n .map(id => allPosts.find(p => p.id === id))\n .filter((p): p is Post => p !== undefined);\n\n console.log(`Unique posts: ${uniquePosts.map(p => p.id).join(', ')}`);\n return { posts: uniquePosts.slice(0, 5), total: uniquePosts.length };\n }\n\n async getPost(\n user_ref: string,\n id: number,\n recordView?: boolean,\n options?: PostOptions,\n ): Promise<MaybePost> {\n const query = this.getPostsBaseQuery(user_ref).where('posts.id', '=', id);\n\n if (options?.includeHealth) {\n const func = this.db.client.config.client === 'pg' ? 'GREATEST' : 'MAX';\n const lastInteractionQuery = `${func}(\n posts.created,\n COALESCE((SELECT MAX(created) FROM answers WHERE answers.\"postId\" = posts.id), posts.created),\n COALESCE((SELECT MAX(created) FROM comments WHERE comments.\"postId\" = posts.id), posts.created),\n COALESCE((SELECT MAX(ac.created) FROM answers a JOIN comments ac ON ac.\"answerId\" = a.id WHERE a.\"postId\" = posts.id), posts.created),\n COALESCE((SELECT MAX(created) FROM post_reviews WHERE post_reviews.post_id = posts.id), posts.created)\n )`;\n query.select(this.db.raw(`${lastInteractionQuery} as last_interaction`));\n }\n\n const rows = await query;\n\n if (!rows || rows.length === 0) {\n return null;\n }\n const post = rows[0] as unknown as RawPostEntity;\n\n if ((recordView === undefined || recordView) && post.status === 'active') {\n this.recordPostView(id, user_ref);\n }\n const posts = await this.mapPostEntities(\n [rows[0] as unknown as RawPostEntity],\n user_ref,\n options,\n );\n return posts[0];\n }\n\n async getPostByAnswerId(\n user_ref: string,\n answerId: number,\n recordView?: boolean,\n options?: PostOptions,\n ): Promise<MaybePost> {\n const rows = await this.getPostsBaseQuery(user_ref)\n .join('answers', 'posts.id', 'answers.postId')\n .where('answers.id', '=', answerId)\n .select('posts.*');\n if (!rows || rows.length === 0) {\n return null;\n }\n if (recordView === undefined || recordView) {\n this.recordPostView(rows[0].id, user_ref);\n }\n const posts = await this.mapPostEntities(\n [rows[0] as unknown as RawPostEntity],\n user_ref,\n options,\n );\n return posts[0];\n }\n\n async createPost(options: {\n user_ref: string;\n title: string;\n content: string;\n created: Date;\n author?: string;\n tags?: string[];\n entities?: string[];\n images?: number[];\n anonymous?: boolean;\n type?: PostType;\n headerImage?: string;\n url?: string;\n status?: PostStatus;\n opts?: PostOptions;\n }): Promise<Post> {\n const {\n user_ref,\n title,\n content,\n author,\n created,\n tags,\n entities,\n images,\n anonymous,\n type = 'question',\n headerImage,\n url,\n opts,\n status = 'active',\n } = options;\n const posts = await this.db\n .insert(\n {\n author: author ?? user_ref,\n title,\n content,\n created,\n anonymous: anonymous ?? false,\n type: type ?? 'question',\n headerImage,\n url,\n status,\n published: status === 'active' ? created : null,\n },\n ['id'],\n )\n .into('posts')\n .returning([\n 'id',\n 'author',\n 'title',\n 'content',\n 'created',\n 'anonymous',\n 'type',\n 'status',\n 'url',\n ]);\n\n await Promise.all([\n this.addTags(posts[0].id, tags),\n this.addEntities(posts[0].id, entities),\n ]);\n\n await this.updateAttachments(\n 'postId',\n content ?? '',\n images ?? [],\n posts[0].id,\n headerImage,\n );\n\n return (await this.mapPostEntities([posts[0]], user_ref, opts))[0];\n }\n\n async updatePost(options: {\n id: number;\n user_ref: string;\n title?: string;\n content?: string;\n author?: string;\n tags?: string[];\n entities?: string[];\n images?: number[];\n headerImage?: string;\n url?: string;\n setUpdatedBy?: boolean;\n status?: PostStatus;\n opts?: PostOptions;\n }): Promise<MaybePost> {\n const {\n id,\n user_ref,\n title,\n content,\n author,\n tags,\n entities,\n images,\n headerImage,\n url,\n setUpdatedBy = true,\n opts,\n status = 'active',\n } = options;\n\n // Check if this is a transition from draft to active\n const currentPost = await this.db('posts')\n .select('status', 'published')\n .where('id', '=', id)\n .first();\n\n const shouldSetPublished =\n currentPost &&\n currentPost.status === 'draft' &&\n status === 'active' &&\n !currentPost.published;\n\n const query = this.db('posts').where('posts.id', '=', id);\n const rows = await query.update({\n title,\n content,\n headerImage,\n author,\n url,\n updatedBy: setUpdatedBy ? user_ref : undefined,\n updated: setUpdatedBy ? new Date() : undefined,\n status,\n published: shouldSetPublished ? new Date() : undefined,\n });\n\n if (!rows) {\n return null;\n }\n\n await Promise.all([\n this.addTags(id, tags, true),\n this.addEntities(id, entities, true),\n ]);\n\n await this.updateAttachments(\n 'postId',\n content ?? '',\n images ?? [],\n id,\n headerImage,\n );\n\n return await this.getPost(user_ref, id, false, opts);\n }\n\n async deletePost(id: number, permanently?: boolean): Promise<boolean> {\n if (permanently) {\n const rows = await this.db('posts').where('id', '=', id).delete();\n return rows > 0;\n }\n const rows = await this.db('posts').where('id', '=', id).update({\n status: 'deleted',\n });\n return rows > 0;\n }\n\n async votePost(\n user_ref: string,\n postId: number,\n score: number,\n ): Promise<boolean> {\n await this.db('post_votes')\n .where('author', '=', user_ref)\n .where('postId', '=', postId)\n .delete();\n\n await this.db\n .insert({\n author: user_ref,\n postId,\n score,\n timestamp: new Date(),\n })\n .into('post_votes');\n\n await this.db('posts')\n .where('id', '=', postId)\n .update({\n score: this.db('post_votes')\n .where('postId', '=', postId)\n .select(this.db.raw('COALESCE(SUM(score), 0)')),\n });\n return true;\n }\n\n async getPostVote(\n user_ref: string,\n postId: number,\n ): Promise<RawPostVoteEntity | undefined> {\n return await this.db<RawPostVoteEntity>('post_votes')\n .where('author', '=', user_ref)\n .where('postId', '=', postId)\n .first();\n }\n\n async deletePostVote(user_ref: string, postId: number): Promise<boolean> {\n const rows = await this.db('post_votes')\n .where('author', '=', user_ref)\n .where('postId', '=', postId)\n .delete();\n\n if (rows > 0) {\n await this.db('posts')\n .where('id', '=', postId)\n .update({\n score: this.db('post_votes')\n .where('postId', '=', postId)\n .select(this.db.raw('COALESCE(SUM(score), 0)')),\n });\n }\n return rows > 0;\n }\n\n async favoritePost(user_ref: string, postId: number): Promise<boolean> {\n await this.db\n .insert({\n user: user_ref,\n postId,\n })\n .into('user_favorite');\n await this.db('posts').where('id', postId).increment('favoritesCount', 1);\n return true;\n }\n\n async unfavoritePost(user_ref: string, postId: number): Promise<boolean> {\n const rows = await this.db('user_favorite')\n .where('user', user_ref)\n .where('postId', postId)\n .delete();\n if (rows > 0) {\n await this.db('posts').where('id', postId).decrement('favoritesCount', 1);\n }\n return true;\n }\n\n async getUsersWhoFavoritedPost(postId: number): Promise<string[]> {\n const users = await this.db('user_favorite')\n .where('postId', postId)\n .select('user');\n return users.map(user => user.user);\n }\n\n private async mapPostEntities(\n rows: RawPostEntity[],\n user_ref: string,\n options?: PostOptions,\n ): Promise<Post[]> {\n if (rows.length === 0) {\n return [];\n }\n\n const postIds = rows.map(r => r.id);\n const {\n includeTags = true,\n includeAnswers = true,\n includeVotes = true,\n includeEntities = true,\n includeComments = true,\n includeAttachments = true,\n includeExperts = true,\n includeCollections = true,\n includeHealth = false,\n } = options ?? {};\n\n const [\n tags,\n votes,\n entities,\n comments,\n attachments,\n experts,\n answers,\n collections,\n ] = await Promise.all([\n includeTags\n ? this.tagsStore.getRelatedTags(\n postIds,\n 'post_tags',\n 'postId',\n options?.tagsFilter,\n )\n : undefined,\n includeVotes\n ? this.db<RawPostVoteEntity>('post_votes')\n .whereIn('postId', postIds)\n .select()\n : undefined,\n includeEntities\n ? this.entitiesStore.getRelatedEntities(\n postIds,\n 'post_entities',\n 'postId',\n )\n : undefined,\n includeComments\n ? this.commentsStore.getPostComments(postIds, options?.commentsFilter)\n : undefined,\n includeAttachments\n ? this.attachmentsStore.getAttachments(postIds, 'postId')\n : undefined,\n includeExperts\n ? this.db('tag_experts')\n .leftJoin('post_tags', 'tag_experts.tagId', 'post_tags.tagId')\n .whereIn('post_tags.postId', postIds)\n .select('post_tags.postId', 'tag_experts.entityRef')\n : undefined,\n includeAnswers && this.answersStore\n ? this.answersStore.getPostAnswers(postIds, user_ref, {\n ...options,\n includePost: false,\n filter: options?.answersFilter,\n })\n : undefined,\n includeCollections\n ? this.db('collection_posts')\n .whereIn('postId', postIds)\n .select('postId', 'collectionId')\n : undefined,\n ]);\n\n const tagsMap = tags ?? new Map<number, string[]>();\n\n const votesMap = new Map<number, RawPostVoteEntity[]>();\n votes?.forEach((v: RawPostVoteEntity) => {\n const ps = votesMap.get(v.postId) || [];\n ps.push(v);\n votesMap.set(v.postId, ps);\n });\n\n const entitiesMap = entities ?? new Map<number, string[]>();\n\n const commentsMap = new Map<number, QetaComment[]>();\n (comments as unknown as (QetaComment & { postId: number })[])?.forEach(\n c => {\n const ps = commentsMap.get(c.postId) || [];\n ps.push(c);\n commentsMap.set(c.postId, ps);\n },\n );\n\n const attachmentsMap = attachments ?? new Map<number, number[]>();\n\n const expertsMap = new Map<number, string[]>();\n experts?.forEach((e: any) => {\n const ps = expertsMap.get(e.postId) || [];\n ps.push(e.entityRef);\n expertsMap.set(e.postId, ps);\n });\n\n const answersMap = new Map<number, Answer[]>();\n answers?.forEach((a: Answer) => {\n const ps = answersMap.get(a.postId) || [];\n ps.push(a);\n answersMap.set(a.postId, ps);\n });\n\n const collectionsMap = new Map<number, number[]>();\n (collections as any)?.forEach((c: any) => {\n const cs = collectionsMap.get(c.postId) || [];\n cs.push(c.collectionId);\n collectionsMap.set(c.postId, cs);\n });\n\n return rows.map(val => {\n const postVotes = votesMap.get(val.id) || [];\n const post: Post = {\n id: val.id,\n author:\n val.anonymous && val.author !== user_ref ? 'anonymous' : val.author,\n own: val.author === user_ref,\n title: val.title,\n content: val.content,\n created: val.created as Date,\n updated: val.updated as Date,\n updatedBy: val.updatedBy,\n status: val.status as PostStatus,\n score: this.mapToInteger(val.score),\n views: this.mapToInteger(val.views),\n answersCount: this.mapToInteger(val.answersCount),\n correctAnswer: this.mapToBoolean(val.correctAnswers),\n commentsCount: this.mapToInteger(val.commentsCount),\n favorite: this.mapToInteger(val.favorite) > 0,\n tags: tagsMap.get(val.id),\n answers: answersMap.get(val.id),\n votes: postVotes.map(v => ({\n author: v.author,\n score: v.score,\n timestamp: v.timestamp,\n })),\n entities: entitiesMap.get(val.id),\n trend: this.mapToInteger(val.trend),\n comments: commentsMap.get(val.id),\n ownVote: postVotes.find(v => v.author === user_ref)?.score,\n anonymous: val.anonymous,\n type: val.type,\n headerImage: val.headerImage,\n url: val.url ?? undefined,\n images: attachmentsMap.get(val.id),\n experts: expertsMap.get(val.id),\n published: val.published ? (val.published as Date) : undefined,\n collectionIds: collectionsMap.get(val.id),\n };\n\n if (includeHealth || options?.reviewNeeded) {\n const reviewThreshold =\n options?.reviewThresholdMs || 180 * 24 * 60 * 60 * 1000;\n const lastInteraction = val.last_interaction\n ? new Date(val.last_interaction)\n : new Date(val.updated || val.created);\n const now = Date.now();\n const diff = now - lastInteraction.getTime();\n\n let score = 100;\n if (reviewThreshold > 0) {\n score = Math.max(\n 0,\n Math.min(100, Math.floor(100 - (diff / reviewThreshold) * 25)),\n );\n }\n if (val.status === 'obsolete') {\n score = 0;\n }\n post.healthScore = score;\n\n if (reviewThreshold > 0 && val.status !== 'obsolete') {\n post.needsReview = diff >= reviewThreshold;\n }\n }\n\n return post;\n });\n }\n\n private getPostsBaseQuery(user: string, opts?: PostsQuery) {\n const q = this.db<RawPostEntity>('posts')\n .leftJoin('user_favorite', function joinUserFavorite() {\n this.on('posts.id', '=', 'user_favorite.postId').andOnVal(\n 'user_favorite.user',\n '=',\n user,\n );\n })\n .select(\n 'posts.*',\n this.db.raw(\n `CASE WHEN user_favorite.${\n this.db.client.config.client === 'pg' ? '\"postId\"' : 'postId'\n } IS NOT NULL THEN 1 ELSE 0 END as favorite`,\n ),\n );\n\n if (opts?.favorite) {\n q.whereNotNull('user_favorite.postId');\n }\n\n return q;\n }\n\n private async recordPostView(\n postId: number,\n user_ref: string,\n ): Promise<void> {\n await this.db\n .insert({\n author: user_ref,\n postId,\n timestamp: new Date(),\n })\n .into('post_views');\n\n await this.db('posts').where('id', postId).increment('views', 1);\n }\n\n private async addTags(\n id: number,\n tagsInput?: string[],\n removeOld?: boolean,\n tableName: string = 'post_tags',\n columnName: string = 'postId',\n ) {\n const tags = filterTags(tagsInput);\n if (removeOld) {\n await this.db(tableName).where(columnName, '=', id).delete();\n }\n\n if (!tags || tags.length === 0) {\n return;\n }\n const existingTags = await this.db('tags')\n .whereIn('tag', tags)\n .returning('id')\n .select();\n const newTags = tags.filter(t => !existingTags.some(e => e.tag === t));\n const allTags: Record<string, string> = {\n ...TAGS,\n ...(await this.tagDatabase?.getTags()),\n };\n\n const tagIds = (\n await Promise.all(\n [...new Set(newTags)].map(async tag => {\n const trimmed = tag.trim();\n const description = trimmed in allTags ? allTags[trimmed] : undefined;\n\n return this.db\n .insert({ tag: trimmed, description })\n .into('tags')\n .returning('id')\n .onConflict('tag')\n .ignore();\n }),\n )\n )\n .flat()\n .map(tag => tag.id)\n .concat(existingTags.map(t => t.id));\n\n await Promise.all(\n tagIds.map(async tagId => {\n await this.db\n .insert({ [columnName]: id, tagId })\n .into(tableName)\n .onConflict()\n .ignore();\n }),\n );\n }\n\n private async addEntities(\n id: number,\n entitiesInput?: string[],\n removeOld?: boolean,\n tableName: string = 'post_entities',\n columnName: string = 'postId',\n ) {\n if (removeOld) {\n await this.db(tableName).where(columnName, '=', id).delete();\n }\n\n const regex = /\\w+:\\w+\\/\\w+/;\n const entities =\n entitiesInput\n ?.filter(t => regex.test(t))\n .map(t => t.toLowerCase())\n .filter(t => t.length > 0) ?? [];\n\n if (!entities || entities.length === 0) {\n return;\n }\n\n const existingEntities = await this.db('entities')\n .whereIn('entity_ref', entities)\n .returning('id')\n .select();\n const newEntities = entities.filter(\n t => !existingEntities.some(e => e.entity_ref === t),\n );\n\n const entityIds = (\n await Promise.all(\n [...new Set(newEntities)].map(async entityRef =>\n this.db\n .insert({ entity_ref: entityRef })\n .into('entities')\n .returning('id')\n .onConflict('entity_ref')\n .ignore(),\n ),\n )\n )\n .flat()\n .map(entity => entity.id)\n .concat(existingEntities.map(c => c.id));\n\n await Promise.all(\n entityIds.map(async entityId => {\n await this.db\n .insert({ [columnName]: id, entityId })\n .into(tableName)\n .onConflict()\n .ignore();\n }),\n );\n }\n}\n"],"names":["BaseStore","filterTags","removeStopwords","eng","rows","TAGS"],"mappings":"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"}
1
+ {"version":3,"file":"PostsStore.cjs.js","sources":["../../../src/database/stores/PostsStore.ts"],"sourcesContent":["import {\n AIResponse,\n Answer,\n Comment as QetaComment,\n filterTags,\n Post,\n PostReview,\n PostsQuery,\n PostStatus,\n PostType,\n} from '@drodil/backstage-plugin-qeta-common';\nimport { MaybePost, PostOptions, Posts } from '../QetaStore';\nimport { QetaFilters } from '../../service/util';\nimport { Knex } from 'knex';\nimport { AnswersStore } from './AnswersStore';\nimport { CommentsStore } from './CommentsStore';\nimport { TagsStore } from './TagsStore';\nimport { EntitiesStore } from './EntitiesStore';\nimport { AttachmentsStore } from './AttachmentsStore';\nimport { PermissionCriteria } from '@backstage/plugin-permission-common';\nimport { TAGS } from '../../tagDb';\nimport { BaseStore } from './BaseStore';\nimport { TagDatabase } from '@drodil/backstage-plugin-qeta-node';\n\nimport { removeStopwords, eng } from 'stopword';\n\nexport interface RawPostEntity {\n id: number;\n author: string;\n title: string;\n content: string;\n status: string;\n created: Date | string;\n updated: Date | string;\n updatedBy: string;\n score: number | string;\n views: number | string;\n answersCount: number | string;\n correctAnswers: number | string;\n commentsCount: number | string;\n favorite: number | string;\n trend: number | string;\n anonymous: boolean;\n type: 'question' | 'article' | 'link';\n headerImage: string;\n url: string | null;\n published: Date | string | null;\n obsolete: number | string | boolean;\n last_interaction?: Date | string;\n}\n\nexport interface RawPostVoteEntity {\n postId: number;\n author: string;\n score: number;\n timestamp: Date;\n}\n\nexport interface RawPostAIAnswer {\n id: number;\n answer: string;\n created: Date;\n}\n\nexport class PostsStore extends BaseStore {\n private answersStore?: AnswersStore;\n\n constructor(\n protected readonly db: Knex,\n private readonly commentsStore: CommentsStore,\n private readonly tagsStore: TagsStore,\n private readonly entitiesStore: EntitiesStore,\n private readonly attachmentsStore: AttachmentsStore,\n private readonly tagDatabase?: TagDatabase,\n ) {\n super(db);\n }\n\n setAnswersStore(answersStore: AnswersStore) {\n this.answersStore = answersStore;\n }\n\n async getAIAnswer(postId: number): Promise<AIResponse | null> {\n const row = await this.db('post_ai_answers')\n .where('postId', postId)\n .first();\n if (!row) {\n return null;\n }\n return {\n answer: row.answer,\n created: row.created,\n };\n }\n\n async saveAIAnswer(postId: number, response: AIResponse): Promise<void> {\n await this.db\n .insert({\n postId,\n answer: response.answer,\n created: response.created,\n })\n .into('post_ai_answers')\n .onConflict('postId')\n .merge();\n }\n\n async deleteAIAnswer(postId: number): Promise<boolean> {\n const deleted = await this.db('post_ai_answers')\n .where('postId', postId)\n .del();\n return deleted > 0;\n }\n\n async reviewPost(\n user_ref: string,\n postId: number,\n status: 'valid' | 'obsolete',\n comment?: string,\n ): Promise<MaybePost> {\n await this.db('post_reviews').insert({\n post_id: postId,\n reviewer: user_ref,\n status,\n comment,\n created: new Date(),\n });\n\n if (status === 'obsolete') {\n await this.db('posts').where('id', postId).update({ status: 'obsolete' });\n } else {\n await this.db('posts').where('id', postId).update({ status: 'active' });\n }\n\n return this.getPost(user_ref, postId, false, {\n includeHealth: true,\n reviewThresholdMs: 15552000000, // 180 days default\n });\n }\n\n async getPostReviews(postId: number): Promise<PostReview[]> {\n const rows = await this.db('post_reviews')\n .where('post_id', postId)\n .orderBy('created', 'desc')\n .select('*');\n\n return rows.map(row => ({\n id: row.id,\n postId: row.post_id,\n reviewer: row.reviewer,\n status: row.status,\n comment: row.comment,\n created: new Date(row.created),\n }));\n }\n\n async getPosts(\n user_ref: string,\n options: PostsQuery,\n filters?: PermissionCriteria<QetaFilters>,\n opts?: PostOptions,\n ): Promise<Posts> {\n const {\n includeTotal = true,\n includeDraftFilter = true,\n includeHealth = false,\n } = opts ?? {};\n const query = this.getPostsBaseQuery(user_ref, options);\n if (options.type) {\n query.where('posts.type', options.type);\n }\n\n if (options.obsolete !== undefined) {\n if (options.obsolete) {\n query.where('posts.status', 'obsolete');\n } else {\n query.where(q => {\n q.whereNot('posts.status', 'obsolete');\n });\n }\n }\n\n if (options.fromDate && options.toDate) {\n query.whereBetween('posts.created', [\n `${options.fromDate} 00:00:00.000+00`,\n `${options.toDate} 23:59:59.999+00`,\n ]);\n } else if (options.fromDate) {\n query.where('posts.created', '>=', `${options.fromDate} 00:00:00.000+00`);\n } else if (options.toDate) {\n query.where('posts.created', '<=', `${options.toDate} 23:59:59.999+00`);\n }\n\n if (options.author) {\n if (Array.isArray(options.author)) {\n query.whereIn('posts.author', options.author);\n } else {\n query.where('posts.author', '=', options.author);\n }\n }\n\n if (options.excludeAuthors) {\n query.whereNotIn('posts.author', options.excludeAuthors);\n }\n\n if (options.status) {\n if (options.status === 'draft') {\n query.where('posts.author', '=', user_ref);\n }\n query.where('posts.status', '=', options.status);\n } else if (includeDraftFilter) {\n query.where(q => {\n q.whereIn('posts.status', ['active', 'obsolete']).orWhere(q2 => {\n q2.where('posts.status', 'draft').where(\n 'posts.author',\n '=',\n user_ref,\n );\n });\n });\n }\n\n if (filters) {\n this.parseFilter(filters, query, this.db);\n }\n\n if (options.searchQuery) {\n this.applySearchQuery(\n query,\n ['posts.title', 'posts.content'],\n options.searchQuery,\n );\n }\n\n if (options.tags) {\n const tags = filterTags(options.tags);\n if (options.tagsRelation === 'or') {\n query.innerJoin('post_tags', 'posts.id', 'post_tags.postId');\n query.innerJoin('tags', 'post_tags.tagId', 'tags.id');\n query.whereIn('tags.tag', tags);\n } else {\n tags?.forEach((t: string, i: number) => {\n query.innerJoin(`post_tags AS qt${i}`, 'posts.id', `qt${i}.postId`);\n query.innerJoin(`tags AS t${i}`, `qt${i}.tagId`, `t${i}.id`);\n query.where(`t${i}.tag`, '=', t);\n });\n }\n }\n\n if (options.entities) {\n const entityValues = Array.isArray(options.entities)\n ? options.entities\n : [options.entities];\n if (options.entitiesRelation === 'or') {\n query\n .innerJoin('post_entities', 'posts.id', 'post_entities.postId')\n .innerJoin('entities', 'post_entities.entityId', 'entities.id')\n .whereIn('entities.entity_ref', entityValues);\n } else {\n entityValues.forEach((t: string, i: number) => {\n query.innerJoin(\n `post_entities AS pe${i}`,\n 'posts.id',\n `pe${i}.postId`,\n );\n query.innerJoin(`entities AS e${i}`, `pe${i}.entityId`, `e${i}.id`);\n query.where(`e${i}.entity_ref`, '=', t);\n });\n }\n }\n\n if (options.collectionId) {\n query.innerJoin(\n 'collection_posts',\n 'posts.id',\n 'collection_posts.postId',\n );\n query.where('collection_posts.collectionId', options.collectionId);\n if (options.orderBy === 'rank') {\n query.select('collection_posts.rank');\n }\n } else if (opts?.collectionIds) {\n query.innerJoin(\n 'collection_posts',\n 'posts.id',\n 'collection_posts.postId',\n );\n query.whereIn('collection_posts.collectionId', opts.collectionIds);\n if (options.orderBy === 'rank') {\n query.select('collection_posts.rank');\n }\n } else if (options.orderBy === 'rank') {\n query.innerJoin(\n 'collection_posts',\n 'posts.id',\n 'collection_posts.postId',\n );\n query.select('collection_posts.rank');\n }\n if (options.orderBy === 'rank') {\n query.groupBy('posts.id', 'collection_posts.rank');\n }\n\n if (options.noAnswers) {\n query.where('answersCount', 0);\n }\n\n if (options.hasAnswers) {\n query.where('answersCount', '>', 0);\n }\n\n if (options.noCorrectAnswer) {\n query.where('correctAnswers', 0);\n }\n\n if (options.noVotes) {\n query.where('score', 0);\n }\n\n if (options.favorite) {\n query.where('user_favorite.user', '=', user_ref);\n query.whereNotNull('user_favorite.postId');\n }\n\n if (options.includeTrend || options.orderBy === 'trend') {\n query.select(\n this.db.raw(\n `(\n posts.score * 200 + \n posts.\"answersCount\" * 100 +\n posts.\"favoritesCount\" * 50 +\n posts.views * 10 +\n posts.\"commentsCount\" * 30\n ) / \n POWER(\n EXTRACT(EPOCH FROM (now() - posts.created)) / 172800 + 1,\n 1.5\n ) as trend`,\n ),\n );\n }\n\n if (includeHealth || options.reviewNeeded) {\n const func = this.db.client.config.client === 'pg' ? 'GREATEST' : 'MAX';\n const lastInteractionQuery = `${func}(\n posts.created,\n COALESCE((SELECT MAX(created) FROM answers WHERE answers.\"postId\" = posts.id), posts.created),\n COALESCE((SELECT MAX(created) FROM comments WHERE comments.\"postId\" = posts.id), posts.created),\n COALESCE((SELECT MAX(ac.created) FROM answers a JOIN comments ac ON ac.\"answerId\" = a.id WHERE a.\"postId\" = posts.id), posts.created),\n COALESCE((SELECT MAX(created) FROM post_reviews WHERE post_reviews.post_id = posts.id), posts.created)\n )`;\n\n query.select(this.db.raw(`${lastInteractionQuery} as last_interaction`));\n\n const reviewThresholdMs = opts?.reviewThresholdMs || 0;\n if (options.reviewNeeded && reviewThresholdMs > 0) {\n const thresholdDate = new Date(Date.now() - reviewThresholdMs);\n const thresholdParam = thresholdDate.toISOString();\n query.whereRaw(`${lastInteractionQuery} < ?`, [thresholdParam]);\n }\n if (options.reviewNeeded) {\n query.whereNotIn('posts.status', ['deleted', 'obsolete']);\n }\n }\n\n if (options.ids) {\n query.whereIn('posts.id', options.ids);\n }\n\n const totalQuery = query.clone();\n\n if (options.random) {\n query.orderByRaw('RANDOM()');\n } else if (options.orderBy) {\n query.orderBy(options.orderBy, options.order ? options.order : 'desc');\n } else {\n query.orderBy('created', 'desc');\n }\n\n if (options.limit) {\n query.limit(options.limit);\n }\n\n if (options.offset) {\n query.offset(options.offset);\n }\n\n const results = await Promise.all([\n query,\n includeTotal\n ? this.db(totalQuery.as('totalQuery')).count('* as CNT').first()\n : undefined,\n ]);\n const rows = results[0] as RawPostEntity[];\n const total = this.mapToInteger((results[1] as any)?.CNT);\n\n return {\n posts: await this.mapPostEntities(rows, user_ref, {\n ...opts,\n includeAnswers: options.includeAnswers ?? opts?.includeAnswers,\n includeVotes: options.includeVotes ?? opts?.includeVotes,\n includeEntities: options.includeEntities ?? opts?.includeEntities,\n includeAttachments:\n options.includeAttachments ?? opts?.includeAttachments,\n includeExperts: options.includeExperts ?? opts?.includeExperts,\n includeHealth: options.includeHealth ?? opts?.includeHealth,\n }),\n total,\n };\n }\n\n async suggestPosts(\n user_ref: string,\n title: string,\n content: string,\n tags?: string[],\n entities?: string[],\n filters?: PermissionCriteria<QetaFilters>,\n opts?: PostOptions,\n ): Promise<Posts> {\n const titleWords = removeStopwords(title.split(/\\s+/g), eng).join(' ');\n const contentWords = removeStopwords(content.split(/\\s+/g), eng).join(' ');\n\n const [titlePosts, contentPosts, tagPosts, entityPosts] = await Promise.all(\n [\n titleWords && titleWords.length > 0\n ? this.getPosts(\n user_ref,\n {\n searchQuery: titleWords,\n limit: 5,\n type: 'question',\n status: 'active',\n excludeAuthors: [user_ref],\n },\n filters,\n opts,\n )\n : Promise.resolve({ posts: [], total: 0 }),\n contentWords && contentWords.length > 0\n ? this.getPosts(\n user_ref,\n {\n searchQuery: contentWords,\n limit: 5,\n type: 'question',\n status: 'active',\n excludeAuthors: [user_ref],\n },\n filters,\n opts,\n )\n : Promise.resolve({ posts: [], total: 0 }),\n tags && tags.length > 0\n ? this.getPosts(\n user_ref,\n {\n limit: 5,\n type: 'question',\n tags: tags,\n tagsRelation: 'or',\n status: 'active',\n excludeAuthors: [user_ref],\n },\n filters,\n opts,\n )\n : Promise.resolve({ posts: [], total: 0 }),\n entities && entities.length > 0\n ? this.getPosts(\n user_ref,\n {\n limit: 5,\n type: 'question',\n entities: entities,\n entitiesRelation: 'or',\n status: 'active',\n excludeAuthors: [user_ref],\n },\n filters,\n opts,\n )\n : Promise.resolve({ posts: [], total: 0 }),\n ],\n );\n\n const allPosts = [\n ...titlePosts.posts,\n ...contentPosts.posts,\n ...tagPosts.posts,\n ...entityPosts.posts,\n ];\n\n const uniquePosts = Array.from(new Set(allPosts.map(p => p.id)))\n .map(id => allPosts.find(p => p.id === id))\n .filter((p): p is Post => p !== undefined);\n return { posts: uniquePosts.slice(0, 5), total: uniquePosts.length };\n }\n\n async getPost(\n user_ref: string,\n id: number,\n recordView?: boolean,\n options?: PostOptions,\n ): Promise<MaybePost> {\n const query = this.getPostsBaseQuery(user_ref).where('posts.id', '=', id);\n\n if (options?.includeHealth) {\n const func = this.db.client.config.client === 'pg' ? 'GREATEST' : 'MAX';\n const lastInteractionQuery = `${func}(\n posts.created,\n COALESCE((SELECT MAX(created) FROM answers WHERE answers.\"postId\" = posts.id), posts.created),\n COALESCE((SELECT MAX(created) FROM comments WHERE comments.\"postId\" = posts.id), posts.created),\n COALESCE((SELECT MAX(ac.created) FROM answers a JOIN comments ac ON ac.\"answerId\" = a.id WHERE a.\"postId\" = posts.id), posts.created),\n COALESCE((SELECT MAX(created) FROM post_reviews WHERE post_reviews.post_id = posts.id), posts.created)\n )`;\n query.select(this.db.raw(`${lastInteractionQuery} as last_interaction`));\n }\n\n const rows = await query;\n\n if (!rows || rows.length === 0) {\n return null;\n }\n const post = rows[0] as unknown as RawPostEntity;\n\n if ((recordView === undefined || recordView) && post.status === 'active') {\n this.recordPostView(id, user_ref);\n }\n const posts = await this.mapPostEntities(\n [rows[0] as unknown as RawPostEntity],\n user_ref,\n options,\n );\n return posts[0];\n }\n\n async getPostByAnswerId(\n user_ref: string,\n answerId: number,\n recordView?: boolean,\n options?: PostOptions,\n ): Promise<MaybePost> {\n const rows = await this.getPostsBaseQuery(user_ref)\n .join('answers', 'posts.id', 'answers.postId')\n .where('answers.id', '=', answerId)\n .select('posts.*');\n if (!rows || rows.length === 0) {\n return null;\n }\n if (recordView === undefined || recordView) {\n this.recordPostView(rows[0].id, user_ref);\n }\n const posts = await this.mapPostEntities(\n [rows[0] as unknown as RawPostEntity],\n user_ref,\n options,\n );\n return posts[0];\n }\n\n async createPost(options: {\n user_ref: string;\n title: string;\n content: string;\n created: Date;\n author?: string;\n tags?: string[];\n entities?: string[];\n images?: number[];\n anonymous?: boolean;\n type?: PostType;\n headerImage?: string;\n url?: string;\n status?: PostStatus;\n opts?: PostOptions;\n }): Promise<Post> {\n const {\n user_ref,\n title,\n content,\n author,\n created,\n tags,\n entities,\n images,\n anonymous,\n type = 'question',\n headerImage,\n url,\n opts,\n status = 'active',\n } = options;\n const posts = await this.db\n .insert(\n {\n author: author ?? user_ref,\n title,\n content,\n created,\n anonymous: anonymous ?? false,\n type: type ?? 'question',\n headerImage,\n url,\n status,\n published: status === 'active' ? created : null,\n },\n ['id'],\n )\n .into('posts')\n .returning([\n 'id',\n 'author',\n 'title',\n 'content',\n 'created',\n 'anonymous',\n 'type',\n 'status',\n 'url',\n ]);\n\n await Promise.all([\n this.addTags(posts[0].id, tags),\n this.addEntities(posts[0].id, entities),\n ]);\n\n await this.updateAttachments(\n 'postId',\n content ?? '',\n images ?? [],\n posts[0].id,\n headerImage,\n );\n\n return (await this.mapPostEntities([posts[0]], user_ref, opts))[0];\n }\n\n async updatePost(options: {\n id: number;\n user_ref: string;\n title?: string;\n content?: string;\n author?: string;\n tags?: string[];\n entities?: string[];\n images?: number[];\n headerImage?: string;\n url?: string;\n setUpdatedBy?: boolean;\n status?: PostStatus;\n opts?: PostOptions;\n }): Promise<MaybePost> {\n const {\n id,\n user_ref,\n title,\n content,\n author,\n tags,\n entities,\n images,\n headerImage,\n url,\n setUpdatedBy = true,\n opts,\n status = 'active',\n } = options;\n\n // Check if this is a transition from draft to active\n const currentPost = await this.db('posts')\n .select('status', 'published')\n .where('id', '=', id)\n .first();\n\n const shouldSetPublished =\n currentPost &&\n currentPost.status === 'draft' &&\n status === 'active' &&\n !currentPost.published;\n\n const query = this.db('posts').where('posts.id', '=', id);\n const rows = await query.update({\n title,\n content,\n headerImage,\n author,\n url,\n updatedBy: setUpdatedBy ? user_ref : undefined,\n updated: setUpdatedBy ? new Date() : undefined,\n status,\n published: shouldSetPublished ? new Date() : undefined,\n });\n\n if (!rows) {\n return null;\n }\n\n await Promise.all([\n this.addTags(id, tags, true),\n this.addEntities(id, entities, true),\n ]);\n\n await this.updateAttachments(\n 'postId',\n content ?? '',\n images ?? [],\n id,\n headerImage,\n );\n\n return await this.getPost(user_ref, id, false, opts);\n }\n\n async deletePost(id: number, permanently?: boolean): Promise<boolean> {\n if (permanently) {\n const rows = await this.db('posts').where('id', '=', id).delete();\n return rows > 0;\n }\n const rows = await this.db('posts').where('id', '=', id).update({\n status: 'deleted',\n });\n return rows > 0;\n }\n\n async votePost(\n user_ref: string,\n postId: number,\n score: number,\n ): Promise<boolean> {\n await this.db('post_votes')\n .where('author', '=', user_ref)\n .where('postId', '=', postId)\n .delete();\n\n await this.db\n .insert({\n author: user_ref,\n postId,\n score,\n timestamp: new Date(),\n })\n .into('post_votes');\n\n await this.db('posts')\n .where('id', '=', postId)\n .update({\n score: this.db('post_votes')\n .where('postId', '=', postId)\n .select(this.db.raw('COALESCE(SUM(score), 0)')),\n });\n return true;\n }\n\n async getPostVote(\n user_ref: string,\n postId: number,\n ): Promise<RawPostVoteEntity | undefined> {\n return await this.db<RawPostVoteEntity>('post_votes')\n .where('author', '=', user_ref)\n .where('postId', '=', postId)\n .first();\n }\n\n async deletePostVote(user_ref: string, postId: number): Promise<boolean> {\n const rows = await this.db('post_votes')\n .where('author', '=', user_ref)\n .where('postId', '=', postId)\n .delete();\n\n if (rows > 0) {\n await this.db('posts')\n .where('id', '=', postId)\n .update({\n score: this.db('post_votes')\n .where('postId', '=', postId)\n .select(this.db.raw('COALESCE(SUM(score), 0)')),\n });\n }\n return rows > 0;\n }\n\n async favoritePost(user_ref: string, postId: number): Promise<boolean> {\n await this.db\n .insert({\n user: user_ref,\n postId,\n })\n .into('user_favorite');\n await this.db('posts').where('id', postId).increment('favoritesCount', 1);\n return true;\n }\n\n async unfavoritePost(user_ref: string, postId: number): Promise<boolean> {\n const rows = await this.db('user_favorite')\n .where('user', user_ref)\n .where('postId', postId)\n .delete();\n if (rows > 0) {\n await this.db('posts').where('id', postId).decrement('favoritesCount', 1);\n }\n return true;\n }\n\n async getUsersWhoFavoritedPost(postId: number): Promise<string[]> {\n const users = await this.db('user_favorite')\n .where('postId', postId)\n .select('user');\n return users.map(user => user.user);\n }\n\n private async mapPostEntities(\n rows: RawPostEntity[],\n user_ref: string,\n options?: PostOptions,\n ): Promise<Post[]> {\n if (rows.length === 0) {\n return [];\n }\n\n const postIds = rows.map(r => r.id);\n const {\n includeTags = true,\n includeAnswers = true,\n includeVotes = true,\n includeEntities = true,\n includeComments = true,\n includeAttachments = true,\n includeExperts = true,\n includeCollections = true,\n includeHealth = false,\n } = options ?? {};\n\n const [\n tags,\n votes,\n entities,\n comments,\n attachments,\n experts,\n answers,\n collections,\n ] = await Promise.all([\n includeTags\n ? this.tagsStore.getRelatedTags(\n postIds,\n 'post_tags',\n 'postId',\n options?.tagsFilter,\n )\n : undefined,\n includeVotes\n ? this.db<RawPostVoteEntity>('post_votes')\n .whereIn('postId', postIds)\n .select()\n : undefined,\n includeEntities\n ? this.entitiesStore.getRelatedEntities(\n postIds,\n 'post_entities',\n 'postId',\n )\n : undefined,\n includeComments\n ? this.commentsStore.getPostComments(postIds, options?.commentsFilter)\n : undefined,\n includeAttachments\n ? this.attachmentsStore.getAttachments(postIds, 'postId')\n : undefined,\n includeExperts\n ? this.db('tag_experts')\n .leftJoin('post_tags', 'tag_experts.tagId', 'post_tags.tagId')\n .whereIn('post_tags.postId', postIds)\n .select('post_tags.postId', 'tag_experts.entityRef')\n : undefined,\n includeAnswers && this.answersStore\n ? this.answersStore.getPostAnswers(postIds, user_ref, {\n ...options,\n includePost: false,\n filter: options?.answersFilter,\n })\n : undefined,\n includeCollections\n ? this.db('collection_posts')\n .whereIn('postId', postIds)\n .select('postId', 'collectionId')\n : undefined,\n ]);\n\n const tagsMap = tags ?? new Map<number, string[]>();\n\n const votesMap = new Map<number, RawPostVoteEntity[]>();\n votes?.forEach((v: RawPostVoteEntity) => {\n const ps = votesMap.get(v.postId) || [];\n ps.push(v);\n votesMap.set(v.postId, ps);\n });\n\n const entitiesMap = entities ?? new Map<number, string[]>();\n\n const commentsMap = new Map<number, QetaComment[]>();\n (comments as unknown as (QetaComment & { postId: number })[])?.forEach(\n c => {\n const ps = commentsMap.get(c.postId) || [];\n ps.push(c);\n commentsMap.set(c.postId, ps);\n },\n );\n\n const attachmentsMap = attachments ?? new Map<number, number[]>();\n\n const expertsMap = new Map<number, string[]>();\n experts?.forEach((e: any) => {\n const ps = expertsMap.get(e.postId) || [];\n ps.push(e.entityRef);\n expertsMap.set(e.postId, ps);\n });\n\n const answersMap = new Map<number, Answer[]>();\n answers?.forEach((a: Answer) => {\n const ps = answersMap.get(a.postId) || [];\n ps.push(a);\n answersMap.set(a.postId, ps);\n });\n\n const collectionsMap = new Map<number, number[]>();\n (collections as any)?.forEach((c: any) => {\n const cs = collectionsMap.get(c.postId) || [];\n cs.push(c.collectionId);\n collectionsMap.set(c.postId, cs);\n });\n\n return rows.map(val => {\n const postVotes = votesMap.get(val.id) || [];\n const post: Post = {\n id: val.id,\n author:\n val.anonymous && val.author !== user_ref ? 'anonymous' : val.author,\n own: val.author === user_ref,\n title: val.title,\n content: val.content,\n created: val.created as Date,\n updated: val.updated as Date,\n updatedBy: val.updatedBy,\n status: val.status as PostStatus,\n score: this.mapToInteger(val.score),\n views: this.mapToInteger(val.views),\n answersCount: this.mapToInteger(val.answersCount),\n correctAnswer: this.mapToBoolean(val.correctAnswers),\n commentsCount: this.mapToInteger(val.commentsCount),\n favorite: this.mapToInteger(val.favorite) > 0,\n tags: tagsMap.get(val.id),\n answers: answersMap.get(val.id),\n votes: postVotes.map(v => ({\n author: v.author,\n score: v.score,\n timestamp: v.timestamp,\n })),\n entities: entitiesMap.get(val.id),\n trend: this.mapToInteger(val.trend),\n comments: commentsMap.get(val.id),\n ownVote: postVotes.find(v => v.author === user_ref)?.score,\n anonymous: val.anonymous,\n type: val.type,\n headerImage: val.headerImage,\n url: val.url ?? undefined,\n images: attachmentsMap.get(val.id),\n experts: expertsMap.get(val.id),\n published: val.published ? (val.published as Date) : undefined,\n collectionIds: collectionsMap.get(val.id),\n };\n\n if (includeHealth || options?.reviewNeeded) {\n const reviewThreshold =\n options?.reviewThresholdMs || 180 * 24 * 60 * 60 * 1000;\n const lastInteraction = val.last_interaction\n ? new Date(val.last_interaction)\n : new Date(val.updated || val.created);\n const now = Date.now();\n const diff = now - lastInteraction.getTime();\n\n let score = 100;\n if (reviewThreshold > 0) {\n score = Math.max(\n 0,\n Math.min(100, Math.floor(100 - (diff / reviewThreshold) * 25)),\n );\n }\n if (val.status === 'obsolete') {\n score = 0;\n }\n post.healthScore = score;\n\n if (reviewThreshold > 0 && val.status !== 'obsolete') {\n post.needsReview = diff >= reviewThreshold;\n }\n }\n\n return post;\n });\n }\n\n private getPostsBaseQuery(user: string, opts?: PostsQuery) {\n const q = this.db<RawPostEntity>('posts')\n .leftJoin('user_favorite', function joinUserFavorite() {\n this.on('posts.id', '=', 'user_favorite.postId').andOnVal(\n 'user_favorite.user',\n '=',\n user,\n );\n })\n .select(\n 'posts.*',\n this.db.raw(\n `CASE WHEN user_favorite.${\n this.db.client.config.client === 'pg' ? '\"postId\"' : 'postId'\n } IS NOT NULL THEN 1 ELSE 0 END as favorite`,\n ),\n );\n\n if (opts?.favorite) {\n q.whereNotNull('user_favorite.postId');\n }\n\n return q;\n }\n\n private async recordPostView(\n postId: number,\n user_ref: string,\n ): Promise<void> {\n await this.db\n .insert({\n author: user_ref,\n postId,\n timestamp: new Date(),\n })\n .into('post_views');\n\n await this.db('posts').where('id', postId).increment('views', 1);\n }\n\n private async addTags(\n id: number,\n tagsInput?: string[],\n removeOld?: boolean,\n tableName: string = 'post_tags',\n columnName: string = 'postId',\n ) {\n const tags = filterTags(tagsInput);\n if (removeOld) {\n await this.db(tableName).where(columnName, '=', id).delete();\n }\n\n if (!tags || tags.length === 0) {\n return;\n }\n const existingTags = await this.db('tags')\n .whereIn('tag', tags)\n .returning('id')\n .select();\n const newTags = tags.filter(t => !existingTags.some(e => e.tag === t));\n const allTags: Record<string, string> = {\n ...TAGS,\n ...(await this.tagDatabase?.getTags()),\n };\n\n const tagIds = (\n await Promise.all(\n [...new Set(newTags)].map(async tag => {\n const trimmed = tag.trim();\n const description = trimmed in allTags ? allTags[trimmed] : undefined;\n\n return this.db\n .insert({ tag: trimmed, description })\n .into('tags')\n .returning('id')\n .onConflict('tag')\n .ignore();\n }),\n )\n )\n .flat()\n .map(tag => tag.id)\n .concat(existingTags.map(t => t.id));\n\n await Promise.all(\n tagIds.map(async tagId => {\n await this.db\n .insert({ [columnName]: id, tagId })\n .into(tableName)\n .onConflict()\n .ignore();\n }),\n );\n }\n\n private async addEntities(\n id: number,\n entitiesInput?: string[],\n removeOld?: boolean,\n tableName: string = 'post_entities',\n columnName: string = 'postId',\n ) {\n if (removeOld) {\n await this.db(tableName).where(columnName, '=', id).delete();\n }\n\n const regex = /\\w+:\\w+\\/\\w+/;\n const entities =\n entitiesInput\n ?.filter(t => regex.test(t))\n .map(t => t.toLowerCase())\n .filter(t => t.length > 0) ?? [];\n\n if (!entities || entities.length === 0) {\n return;\n }\n\n const existingEntities = await this.db('entities')\n .whereIn('entity_ref', entities)\n .returning('id')\n .select();\n const newEntities = entities.filter(\n t => !existingEntities.some(e => e.entity_ref === t),\n );\n\n const entityIds = (\n await Promise.all(\n [...new Set(newEntities)].map(async entityRef =>\n this.db\n .insert({ entity_ref: entityRef })\n .into('entities')\n .returning('id')\n .onConflict('entity_ref')\n .ignore(),\n ),\n )\n )\n .flat()\n .map(entity => entity.id)\n .concat(existingEntities.map(c => c.id));\n\n await Promise.all(\n entityIds.map(async entityId => {\n await this.db\n .insert({ [columnName]: id, entityId })\n .into(tableName)\n .onConflict()\n .ignore();\n }),\n );\n }\n}\n"],"names":["BaseStore","filterTags","removeStopwords","eng","rows","TAGS"],"mappings":"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"}
@@ -520,6 +520,49 @@ const helperRoutes = (router, options) => {
520
520
  });
521
521
  response.json(entity);
522
522
  });
523
+ router.get(`/timeline`, async (request, response) => {
524
+ const username = await permissionMgr.getUsername(request, true);
525
+ const limit = request.query.limit ? Number.parseInt(request.query.limit, 10) : 10;
526
+ const offset = request.query.offset ? Number.parseInt(request.query.offset, 10) : 0;
527
+ const includeTotal = request.query.includeTotal === "true";
528
+ const [filter, commentsFilter, answersFilter, collectionsFilter] = await Promise.all([
529
+ permissionMgr.getAuthorizeConditions(request, backstagePluginQetaCommon.qetaReadPostPermission, {
530
+ allowServicePrincipal: true
531
+ }),
532
+ permissionMgr.getAuthorizeConditions(
533
+ request,
534
+ backstagePluginQetaCommon.qetaReadCommentPermission,
535
+ {
536
+ allowServicePrincipal: true
537
+ }
538
+ ),
539
+ permissionMgr.getAuthorizeConditions(
540
+ request,
541
+ backstagePluginQetaCommon.qetaReadAnswerPermission,
542
+ {
543
+ allowServicePrincipal: true
544
+ }
545
+ ),
546
+ permissionMgr.getAuthorizeConditions(
547
+ request,
548
+ backstagePluginQetaCommon.qetaReadCollectionPermission,
549
+ {
550
+ allowServicePrincipal: true
551
+ }
552
+ )
553
+ ]);
554
+ const timeline = await database.getTimeline(
555
+ username,
556
+ { limit, offset, includeTotal },
557
+ {
558
+ posts: filter,
559
+ answers: answersFilter,
560
+ comments: commentsFilter,
561
+ collections: collectionsFilter
562
+ }
563
+ );
564
+ response.json(timeline);
565
+ });
523
566
  };
524
567
 
525
568
  exports.helperRoutes = helperRoutes;
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.cjs.js","sources":["../../../src/service/routes/helpers.ts"],"sourcesContent":["import { Request, Router } from 'express';\nimport {\n DeleteMetadataSchema,\n DraftQuestionSchema,\n EntitiesQuerySchema,\n RouteOptions,\n TagsQuerySchema,\n UsersQuerySchema,\n} from '../types';\nimport { mapAdditionalFields } from '../util';\nimport { parseEntityRef, stringifyEntityRef } from '@backstage/catalog-model';\nimport {\n filterTags,\n getSupportedEntityKinds,\n isValidTag,\n qetaCreateTagPermission,\n qetaDeleteTagPermission,\n qetaEditTagPermission,\n qetaReadTagPermission,\n TagsQuery,\n} from '@drodil/backstage-plugin-qeta-common';\nimport Ajv from 'ajv';\nimport addFormats from 'ajv-formats';\nimport { eng, removeStopwords } from 'stopword';\nimport { CATALOG_FILTER_EXISTS } from '@backstage/catalog-client';\n\nconst ajv = new Ajv({ coerceTypes: 'array' });\naddFormats(ajv);\n\nexport const helperRoutes = (router: Router, options: RouteOptions) => {\n const {\n database,\n catalog,\n auth,\n config,\n httpAuth,\n auditor,\n logger,\n permissionMgr,\n aiHandler,\n } = options;\n\n const supportedKinds = getSupportedEntityKinds(config);\n\n const validateEntityRef = (entityRef: string, kind?: string) => {\n try {\n const valid = parseEntityRef(entityRef);\n if (\n kind &&\n valid.kind.toLocaleLowerCase('en-US') !==\n kind.toLocaleLowerCase('en-US')\n ) {\n throw new Error(`Expected kind: ${kind}`);\n }\n } catch (error) {\n throw new Error(`Invalid entityRef: ${entityRef}`);\n }\n };\n\n router.get('/users', async (request, response) => {\n const validateQuery = ajv.compile(UsersQuerySchema);\n if (!validateQuery(request.query)) {\n response\n .status(400)\n .send({ errors: validateQuery.errors, type: 'query' });\n return;\n }\n\n let entityRefs: string[] | undefined;\n if (request.query.searchQuery) {\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: await httpAuth.credentials(request),\n targetPluginId: 'catalog',\n });\n const users = await catalog.queryEntities(\n {\n filter: { kind: 'User' },\n fields: ['kind', 'metadata.name', 'metadata.namespace'],\n fullTextFilter: {\n term: String(request.query.searchQuery),\n fields: [\n 'metadata.name',\n 'metadata.title',\n 'spec.profile.displayName',\n ],\n },\n },\n { token },\n );\n entityRefs = users.items\n .map(user => {\n try {\n return stringifyEntityRef(user);\n } catch (_e) {\n return null;\n }\n })\n .filter((e): e is string => e !== null);\n }\n\n const users = await database.getUsers({ entityRefs, ...request.query });\n response.json(users);\n });\n\n router.get('/users/followed', async (request, response) => {\n const username = await permissionMgr.getUsername(request, false);\n const users = await database.getFollowedUsers(username);\n response.json(users);\n });\n\n router.put('/users/follow/:userRef(*)', async (request, response) => {\n const { userRef } = request.params;\n validateEntityRef(userRef, 'user');\n const username = await permissionMgr.getUsername(request, false);\n await database.followUser(username, userRef);\n\n auditor?.createEvent({\n eventId: 'follow-user',\n severityLevel: 'low',\n request,\n meta: {\n userRef,\n },\n });\n\n response.status(204).send();\n });\n\n router.delete('/users/follow/:userRef(*)', async (request, response) => {\n const { userRef } = request.params;\n validateEntityRef(userRef, 'user');\n const username = await permissionMgr.getUsername(request, false);\n await database.unfollowUser(username, userRef);\n\n auditor?.createEvent({\n eventId: 'unfollow-user',\n severityLevel: 'low',\n request,\n meta: {\n userRef,\n },\n });\n\n response.status(204).send();\n });\n\n // GET /tags\n router.get('/tags', async (request, response) => {\n const validateQuery = ajv.compile(TagsQuerySchema);\n if (!validateQuery(request.query)) {\n response\n .status(400)\n .send({ errors: validateQuery.errors, type: 'query' });\n return;\n }\n\n const filter = await permissionMgr.getAuthorizeConditions(\n request,\n qetaReadTagPermission,\n { allowServicePrincipal: true },\n );\n\n const opts = request.query as TagsQuery;\n const tags = await database.getTags(opts, filter);\n\n await mapAdditionalFields(request, tags.tags, options, {\n checkRights: opts.checkAccess ?? false,\n });\n\n response.json(tags);\n });\n\n router.get('/tags/followed', async (request, response) => {\n const username = await permissionMgr.getUsername(request, false);\n const filter = await permissionMgr.getAuthorizeConditions(\n request,\n qetaReadTagPermission,\n { allowServicePrincipal: true },\n );\n const tags = await database.getUserTags(username, filter);\n\n response.json(tags);\n });\n\n router.put('/tags/follow/:tag', async (request, response) => {\n const { tag } = request.params;\n const username = await permissionMgr.getUsername(request, false);\n await database.followTag(username, tag);\n\n auditor?.createEvent({\n eventId: 'follow-tag',\n severityLevel: 'low',\n request,\n meta: {\n tag,\n },\n });\n\n response.status(204).send();\n });\n\n router.delete('/tags/follow/:tag', async (request, response) => {\n const { tag } = request.params;\n const username = await permissionMgr.getUsername(request, false);\n await database.unfollowTag(username, tag);\n\n auditor?.createEvent({\n eventId: 'unfollow-tag',\n severityLevel: 'low',\n request,\n meta: {\n tag,\n },\n });\n response.status(204).send();\n });\n\n const getSuggestedTags = async (\n request: Request,\n title: string,\n content: string,\n entities?: string[],\n ) => {\n const suggestedTags: string[] = [];\n if (entities && entities.length > 0) {\n try {\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: await httpAuth.credentials(request),\n targetPluginId: 'catalog',\n });\n const entityResponse = await catalog.getEntitiesByRefs(\n {\n entityRefs: entities,\n fields: ['metadata.tags'],\n filter: {\n 'metadata.tags': CATALOG_FILTER_EXISTS,\n },\n },\n { token },\n );\n const entityTags = entityResponse.items\n .flatMap(e => e?.metadata?.tags)\n .filter((t): t is string => !!t)\n .map(tag => tag.toLocaleLowerCase())\n .filter(filterTags)\n .slice(0, 5);\n suggestedTags.push(...entityTags);\n } catch (_error) {\n // Just ignore\n }\n }\n\n try {\n if (aiHandler?.suggestTags) {\n const { tags } = await aiHandler.suggestTags(title, content);\n suggestedTags.unshift(...tags);\n return [...new Set(suggestedTags)]\n .filter(filterTags)\n .map(tag => tag.toLocaleLowerCase())\n .slice(0, 10);\n }\n } catch (_error) {\n // NOOP: Fallback to database suggestions\n }\n\n const cleanWords = (words: string[]): string[] =>\n removeStopwords(words, [...eng]);\n\n const { tags: existingTags } = await database.getTags();\n\n const titleLower = title.toLocaleLowerCase();\n const titleWords = cleanWords(\n titleLower.split(/\\s+/).map(word => word.toLocaleLowerCase()),\n );\n const contentLower = content.toLocaleLowerCase();\n const contentWords = cleanWords(\n contentLower.split(/\\s+/).map(word => word.toLocaleLowerCase()),\n );\n\n existingTags.forEach(tag => {\n if (\n titleLower.includes(tag.tag.toLocaleLowerCase()) ||\n contentLower.includes(tag.tag.toLocaleLowerCase())\n ) {\n suggestedTags.push(tag.tag);\n return;\n }\n\n const descriptionWords = cleanWords(\n tag.description?.toLocaleLowerCase().split(/\\s+/) || [],\n );\n\n if (\n titleWords.some(word => descriptionWords.includes(word)) ||\n contentWords.some(word => descriptionWords.includes(word))\n ) {\n suggestedTags.push(tag.tag);\n }\n });\n\n return [...new Set(suggestedTags)].filter(filterTags).slice(0, 10);\n };\n\n router.post('/tags/suggest', async (request, response) => {\n const validateRequestBody = ajv.compile(DraftQuestionSchema);\n if (!validateRequestBody(request.body)) {\n response.status(400).send({ errors: validateRequestBody.errors });\n return;\n }\n\n try {\n const suggestedTags = await getSuggestedTags(\n request,\n request.body.title,\n request.body.content,\n request.body.entities,\n );\n\n const allTags = request.body.tags\n ? [...new Set([...request.body.tags, ...suggestedTags])]\n : suggestedTags;\n\n const uniqueTags = [...new Set(allTags)];\n\n response.json({ tags: uniqueTags });\n } catch (error) {\n logger.error(`Failed to generate tag suggestions: ${error}`);\n response\n .status(500)\n .json({ error: 'Failed to generate tag suggestions' });\n }\n });\n\n router.get('/tags/:tag', async (request, response) => {\n const tag = await database.getTag(request.params.tag);\n if (!tag) {\n response.sendStatus(404);\n return;\n }\n await permissionMgr.authorize(\n request,\n [{ permission: qetaReadTagPermission, resource: tag }],\n { throwOnDeny: true },\n );\n await mapAdditionalFields(request, [tag], options);\n auditor?.createEvent({\n eventId: 'read-tag',\n severityLevel: 'low',\n request,\n meta: { tagId: tag.id, tag: tag.tag },\n });\n response.json(tag);\n });\n\n router.post('/tags/:tag', async (request, response) => {\n const tagId = Number.parseInt(request.params.tag, 10);\n if (Number.isNaN(tagId)) {\n response.status(400).send({ errors: 'Invalid tag id', type: 'body' });\n return;\n }\n\n const tag = await database.getTagById(tagId);\n if (!tag) {\n response.sendStatus(404);\n return;\n }\n await permissionMgr.authorize(\n request,\n [{ permission: qetaEditTagPermission, resource: tag }],\n { throwOnDeny: true },\n );\n\n const description = request.body.description;\n const experts = request.body.experts;\n if (experts) {\n const isMod = await permissionMgr.isModerator(request);\n if (!isMod) {\n response.sendStatus(401);\n return;\n }\n }\n const resp = await database.updateTag(tagId, description, experts);\n await mapAdditionalFields(request, resp ? [resp] : [], options);\n auditor?.createEvent({\n eventId: 'update-tag',\n severityLevel: 'medium',\n request,\n meta: {\n ...resp,\n tagId: tag.id,\n },\n });\n\n response.json(resp);\n });\n\n router.put('/tags', async (request, response) => {\n await permissionMgr.authorize(\n request,\n [{ permission: qetaCreateTagPermission }],\n { throwOnDeny: true },\n );\n\n const existing = await database.getTag(request.body.tag);\n if (existing) {\n response.status(409).send({ errors: 'Tag already exists', type: 'body' });\n return;\n }\n\n if (!isValidTag(request.body.tag)) {\n response.status(400).send({ errors: 'Invalid tag', type: 'body' });\n return;\n }\n\n const description = request.body.description;\n const experts = request.body.experts;\n if (experts) {\n const isMod = await permissionMgr.isModerator(request);\n if (!isMod) {\n response.sendStatus(401);\n return;\n }\n }\n\n const tag = await database.createTag(\n request.body.tag,\n description,\n experts,\n );\n if (!tag) {\n response.sendStatus(500);\n return;\n }\n await mapAdditionalFields(request, [tag], options);\n auditor?.createEvent({\n eventId: 'create-tag',\n severityLevel: 'medium',\n request,\n meta: {\n ...tag,\n tagId: tag.id,\n },\n });\n response.status(201).json(tag);\n });\n\n router.delete('/tags/:tag', async (request, response) => {\n const tagId = Number.parseInt(request.params.tag, 10);\n const validateRequestBody = ajv.compile(DeleteMetadataSchema);\n if (Number.isNaN(tagId) || !validateRequestBody(request.body)) {\n response.status(400).send({ errors: 'Invalid tag id', type: 'body' });\n return;\n }\n\n const tag = await database.getTagById(tagId);\n await permissionMgr.authorize(\n request,\n [{ permission: qetaDeleteTagPermission, resource: tag! }],\n { throwOnDeny: true },\n );\n const deleted = await database.deleteTag(tagId);\n\n if (deleted) {\n auditor?.createEvent({\n eventId: 'delete-tag',\n severityLevel: 'medium',\n request,\n meta: {\n tagId,\n reason: request.body.reason,\n },\n });\n }\n // Response\n response.sendStatus(deleted ? 204 : 404);\n });\n\n router.get('/entities', async (request, response) => {\n const validateQuery = ajv.compile(EntitiesQuerySchema);\n if (!validateQuery(request.query)) {\n response\n .status(400)\n .send({ errors: validateQuery.errors, type: 'query' });\n return;\n }\n\n let entityRefs: string[] | undefined;\n if (request.query.searchQuery) {\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: await httpAuth.credentials(request),\n targetPluginId: 'catalog',\n });\n const entities = await catalog.queryEntities(\n {\n filter: {\n kind: supportedKinds,\n },\n fields: ['kind', 'metadata.name', 'metadata.namespace'],\n fullTextFilter: {\n term: String(request.query.searchQuery),\n fields: [\n 'metadata.name',\n 'metadata.title',\n 'metadata.description',\n 'spec.profile.displayName',\n ],\n },\n },\n { token },\n );\n entityRefs = entities.items\n .map(entity => {\n try {\n return stringifyEntityRef(entity);\n } catch (_e) {\n return null;\n }\n })\n .filter((e): e is string => e !== null);\n }\n\n const entities = await database.getEntities({\n entityRefs,\n ...request.query,\n });\n response.json(entities);\n });\n\n router.post('/entities/suggest', async (request, response) => {\n const validateRequestBody = ajv.compile(DraftQuestionSchema);\n if (!validateRequestBody(request.body)) {\n response.status(400).send({ errors: validateRequestBody.errors });\n return;\n }\n\n try {\n const suggestedTags = await getSuggestedTags(\n request,\n request.body.title,\n request.body.content,\n request.body.entities,\n );\n\n const allTags = request.body.tags\n ? [...new Set([...request.body.tags, ...suggestedTags])]\n : suggestedTags;\n\n if (!allTags.length) {\n response.json({ entities: [] });\n return;\n }\n\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: await httpAuth.credentials(request),\n targetPluginId: 'catalog',\n });\n const entities = await catalog.queryEntities(\n {\n filter: {\n 'metadata.tags': allTags,\n kind: supportedKinds,\n },\n },\n { token },\n );\n\n const notSetEntities = entities.items.filter(entity => {\n const ref = stringifyEntityRef(entity);\n return !request.body.entities?.includes(ref);\n });\n\n response.json({ entities: notSetEntities });\n } catch (error) {\n logger.error(`Failed to generate entity suggestions: ${error}`);\n response\n .status(500)\n .json({ error: 'Failed to generate entity suggestions' });\n }\n });\n\n router.get('/entities/followed', async (request, response) => {\n const username = await permissionMgr.getUsername(request, false);\n const tags = await database.getUserEntities(username);\n response.json(tags);\n });\n\n router.get('/entities/links', async (request, response) => {\n const credentials = await httpAuth.credentials(request, {\n allow: ['service'],\n });\n if (!credentials) {\n response.sendStatus(401);\n return;\n }\n\n const links = await database.getEntityLinks();\n response.json(links);\n });\n\n router.put('/entities/follow/:entityRef(*)', async (request, response) => {\n const { entityRef } = request.params;\n validateEntityRef(entityRef);\n const username = await permissionMgr.getUsername(request, false);\n await database.followEntity(username, entityRef);\n auditor?.createEvent({\n eventId: 'follow-entity',\n severityLevel: 'low',\n request,\n meta: {\n entityRef,\n },\n });\n response.status(204).send();\n });\n\n router.delete('/entities/follow/:entityRef(*)', async (request, response) => {\n const { entityRef } = request.params;\n validateEntityRef(entityRef);\n const username = await permissionMgr.getUsername(request, false);\n await database.unfollowEntity(username, entityRef);\n auditor?.createEvent({\n eventId: 'unfollow-entity',\n severityLevel: 'low',\n request,\n meta: {\n entityRef,\n },\n });\n response.status(204).send();\n });\n\n router.get('/entities/:entityRef(*)', async (request, response) => {\n validateEntityRef(request.params.entityRef);\n const entity = await database.getEntity(request.params.entityRef);\n if (entity === null) {\n response.sendStatus(404);\n return;\n }\n auditor?.createEvent({\n eventId: 'read-entity',\n severityLevel: 'low',\n request,\n meta: { entityRef: request.params.entityRef },\n });\n response.json(entity);\n });\n};\n"],"names":["Ajv","addFormats","getSupportedEntityKinds","parseEntityRef","UsersQuerySchema","users","stringifyEntityRef","TagsQuerySchema","qetaReadTagPermission","mapAdditionalFields","CATALOG_FILTER_EXISTS","filterTags","removeStopwords","eng","DraftQuestionSchema","qetaEditTagPermission","qetaCreateTagPermission","isValidTag","DeleteMetadataSchema","qetaDeleteTagPermission","EntitiesQuerySchema","entities"],"mappings":"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"}
1
+ {"version":3,"file":"helpers.cjs.js","sources":["../../../src/service/routes/helpers.ts"],"sourcesContent":["import { Request, Router } from 'express';\nimport {\n DeleteMetadataSchema,\n DraftQuestionSchema,\n EntitiesQuerySchema,\n RouteOptions,\n TagsQuerySchema,\n UsersQuerySchema,\n} from '../types';\nimport { mapAdditionalFields } from '../util';\nimport { parseEntityRef, stringifyEntityRef } from '@backstage/catalog-model';\nimport {\n filterTags,\n getSupportedEntityKinds,\n isValidTag,\n qetaCreateTagPermission,\n qetaDeleteTagPermission,\n qetaEditTagPermission,\n qetaReadAnswerPermission,\n qetaReadCollectionPermission,\n qetaReadCommentPermission,\n qetaReadPostPermission,\n qetaReadTagPermission,\n TagsQuery,\n} from '@drodil/backstage-plugin-qeta-common';\nimport Ajv from 'ajv';\nimport addFormats from 'ajv-formats';\nimport { eng, removeStopwords } from 'stopword';\nimport { CATALOG_FILTER_EXISTS } from '@backstage/catalog-client';\n\nconst ajv = new Ajv({ coerceTypes: 'array' });\naddFormats(ajv);\n\nexport const helperRoutes = (router: Router, options: RouteOptions) => {\n const {\n database,\n catalog,\n auth,\n config,\n httpAuth,\n auditor,\n logger,\n permissionMgr,\n aiHandler,\n } = options;\n\n const supportedKinds = getSupportedEntityKinds(config);\n\n const validateEntityRef = (entityRef: string, kind?: string) => {\n try {\n const valid = parseEntityRef(entityRef);\n if (\n kind &&\n valid.kind.toLocaleLowerCase('en-US') !==\n kind.toLocaleLowerCase('en-US')\n ) {\n throw new Error(`Expected kind: ${kind}`);\n }\n } catch (error) {\n throw new Error(`Invalid entityRef: ${entityRef}`);\n }\n };\n\n router.get('/users', async (request, response) => {\n const validateQuery = ajv.compile(UsersQuerySchema);\n if (!validateQuery(request.query)) {\n response\n .status(400)\n .send({ errors: validateQuery.errors, type: 'query' });\n return;\n }\n\n let entityRefs: string[] | undefined;\n if (request.query.searchQuery) {\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: await httpAuth.credentials(request),\n targetPluginId: 'catalog',\n });\n const users = await catalog.queryEntities(\n {\n filter: { kind: 'User' },\n fields: ['kind', 'metadata.name', 'metadata.namespace'],\n fullTextFilter: {\n term: String(request.query.searchQuery),\n fields: [\n 'metadata.name',\n 'metadata.title',\n 'spec.profile.displayName',\n ],\n },\n },\n { token },\n );\n entityRefs = users.items\n .map(user => {\n try {\n return stringifyEntityRef(user);\n } catch (_e) {\n return null;\n }\n })\n .filter((e): e is string => e !== null);\n }\n\n const users = await database.getUsers({ entityRefs, ...request.query });\n response.json(users);\n });\n\n router.get('/users/followed', async (request, response) => {\n const username = await permissionMgr.getUsername(request, false);\n const users = await database.getFollowedUsers(username);\n response.json(users);\n });\n\n router.put('/users/follow/:userRef(*)', async (request, response) => {\n const { userRef } = request.params;\n validateEntityRef(userRef, 'user');\n const username = await permissionMgr.getUsername(request, false);\n await database.followUser(username, userRef);\n\n auditor?.createEvent({\n eventId: 'follow-user',\n severityLevel: 'low',\n request,\n meta: {\n userRef,\n },\n });\n\n response.status(204).send();\n });\n\n router.delete('/users/follow/:userRef(*)', async (request, response) => {\n const { userRef } = request.params;\n validateEntityRef(userRef, 'user');\n const username = await permissionMgr.getUsername(request, false);\n await database.unfollowUser(username, userRef);\n\n auditor?.createEvent({\n eventId: 'unfollow-user',\n severityLevel: 'low',\n request,\n meta: {\n userRef,\n },\n });\n\n response.status(204).send();\n });\n\n // GET /tags\n router.get('/tags', async (request, response) => {\n const validateQuery = ajv.compile(TagsQuerySchema);\n if (!validateQuery(request.query)) {\n response\n .status(400)\n .send({ errors: validateQuery.errors, type: 'query' });\n return;\n }\n\n const filter = await permissionMgr.getAuthorizeConditions(\n request,\n qetaReadTagPermission,\n { allowServicePrincipal: true },\n );\n\n const opts = request.query as TagsQuery;\n const tags = await database.getTags(opts, filter);\n\n await mapAdditionalFields(request, tags.tags, options, {\n checkRights: opts.checkAccess ?? false,\n });\n\n response.json(tags);\n });\n\n router.get('/tags/followed', async (request, response) => {\n const username = await permissionMgr.getUsername(request, false);\n const filter = await permissionMgr.getAuthorizeConditions(\n request,\n qetaReadTagPermission,\n { allowServicePrincipal: true },\n );\n const tags = await database.getUserTags(username, filter);\n\n response.json(tags);\n });\n\n router.put('/tags/follow/:tag', async (request, response) => {\n const { tag } = request.params;\n const username = await permissionMgr.getUsername(request, false);\n await database.followTag(username, tag);\n\n auditor?.createEvent({\n eventId: 'follow-tag',\n severityLevel: 'low',\n request,\n meta: {\n tag,\n },\n });\n\n response.status(204).send();\n });\n\n router.delete('/tags/follow/:tag', async (request, response) => {\n const { tag } = request.params;\n const username = await permissionMgr.getUsername(request, false);\n await database.unfollowTag(username, tag);\n\n auditor?.createEvent({\n eventId: 'unfollow-tag',\n severityLevel: 'low',\n request,\n meta: {\n tag,\n },\n });\n response.status(204).send();\n });\n\n const getSuggestedTags = async (\n request: Request,\n title: string,\n content: string,\n entities?: string[],\n ) => {\n const suggestedTags: string[] = [];\n if (entities && entities.length > 0) {\n try {\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: await httpAuth.credentials(request),\n targetPluginId: 'catalog',\n });\n const entityResponse = await catalog.getEntitiesByRefs(\n {\n entityRefs: entities,\n fields: ['metadata.tags'],\n filter: {\n 'metadata.tags': CATALOG_FILTER_EXISTS,\n },\n },\n { token },\n );\n const entityTags = entityResponse.items\n .flatMap(e => e?.metadata?.tags)\n .filter((t): t is string => !!t)\n .map(tag => tag.toLocaleLowerCase())\n .filter(filterTags)\n .slice(0, 5);\n suggestedTags.push(...entityTags);\n } catch (_error) {\n // Just ignore\n }\n }\n\n try {\n if (aiHandler?.suggestTags) {\n const { tags } = await aiHandler.suggestTags(title, content);\n suggestedTags.unshift(...tags);\n return [...new Set(suggestedTags)]\n .filter(filterTags)\n .map(tag => tag.toLocaleLowerCase())\n .slice(0, 10);\n }\n } catch (_error) {\n // NOOP: Fallback to database suggestions\n }\n\n const cleanWords = (words: string[]): string[] =>\n removeStopwords(words, [...eng]);\n\n const { tags: existingTags } = await database.getTags();\n\n const titleLower = title.toLocaleLowerCase();\n const titleWords = cleanWords(\n titleLower.split(/\\s+/).map(word => word.toLocaleLowerCase()),\n );\n const contentLower = content.toLocaleLowerCase();\n const contentWords = cleanWords(\n contentLower.split(/\\s+/).map(word => word.toLocaleLowerCase()),\n );\n\n existingTags.forEach(tag => {\n if (\n titleLower.includes(tag.tag.toLocaleLowerCase()) ||\n contentLower.includes(tag.tag.toLocaleLowerCase())\n ) {\n suggestedTags.push(tag.tag);\n return;\n }\n\n const descriptionWords = cleanWords(\n tag.description?.toLocaleLowerCase().split(/\\s+/) || [],\n );\n\n if (\n titleWords.some(word => descriptionWords.includes(word)) ||\n contentWords.some(word => descriptionWords.includes(word))\n ) {\n suggestedTags.push(tag.tag);\n }\n });\n\n return [...new Set(suggestedTags)].filter(filterTags).slice(0, 10);\n };\n\n router.post('/tags/suggest', async (request, response) => {\n const validateRequestBody = ajv.compile(DraftQuestionSchema);\n if (!validateRequestBody(request.body)) {\n response.status(400).send({ errors: validateRequestBody.errors });\n return;\n }\n\n try {\n const suggestedTags = await getSuggestedTags(\n request,\n request.body.title,\n request.body.content,\n request.body.entities,\n );\n\n const allTags = request.body.tags\n ? [...new Set([...request.body.tags, ...suggestedTags])]\n : suggestedTags;\n\n const uniqueTags = [...new Set(allTags)];\n\n response.json({ tags: uniqueTags });\n } catch (error) {\n logger.error(`Failed to generate tag suggestions: ${error}`);\n response\n .status(500)\n .json({ error: 'Failed to generate tag suggestions' });\n }\n });\n\n router.get('/tags/:tag', async (request, response) => {\n const tag = await database.getTag(request.params.tag);\n if (!tag) {\n response.sendStatus(404);\n return;\n }\n await permissionMgr.authorize(\n request,\n [{ permission: qetaReadTagPermission, resource: tag }],\n { throwOnDeny: true },\n );\n await mapAdditionalFields(request, [tag], options);\n auditor?.createEvent({\n eventId: 'read-tag',\n severityLevel: 'low',\n request,\n meta: { tagId: tag.id, tag: tag.tag },\n });\n response.json(tag);\n });\n\n router.post('/tags/:tag', async (request, response) => {\n const tagId = Number.parseInt(request.params.tag, 10);\n if (Number.isNaN(tagId)) {\n response.status(400).send({ errors: 'Invalid tag id', type: 'body' });\n return;\n }\n\n const tag = await database.getTagById(tagId);\n if (!tag) {\n response.sendStatus(404);\n return;\n }\n await permissionMgr.authorize(\n request,\n [{ permission: qetaEditTagPermission, resource: tag }],\n { throwOnDeny: true },\n );\n\n const description = request.body.description;\n const experts = request.body.experts;\n if (experts) {\n const isMod = await permissionMgr.isModerator(request);\n if (!isMod) {\n response.sendStatus(401);\n return;\n }\n }\n const resp = await database.updateTag(tagId, description, experts);\n await mapAdditionalFields(request, resp ? [resp] : [], options);\n auditor?.createEvent({\n eventId: 'update-tag',\n severityLevel: 'medium',\n request,\n meta: {\n ...resp,\n tagId: tag.id,\n },\n });\n\n response.json(resp);\n });\n\n router.put('/tags', async (request, response) => {\n await permissionMgr.authorize(\n request,\n [{ permission: qetaCreateTagPermission }],\n { throwOnDeny: true },\n );\n\n const existing = await database.getTag(request.body.tag);\n if (existing) {\n response.status(409).send({ errors: 'Tag already exists', type: 'body' });\n return;\n }\n\n if (!isValidTag(request.body.tag)) {\n response.status(400).send({ errors: 'Invalid tag', type: 'body' });\n return;\n }\n\n const description = request.body.description;\n const experts = request.body.experts;\n if (experts) {\n const isMod = await permissionMgr.isModerator(request);\n if (!isMod) {\n response.sendStatus(401);\n return;\n }\n }\n\n const tag = await database.createTag(\n request.body.tag,\n description,\n experts,\n );\n if (!tag) {\n response.sendStatus(500);\n return;\n }\n await mapAdditionalFields(request, [tag], options);\n auditor?.createEvent({\n eventId: 'create-tag',\n severityLevel: 'medium',\n request,\n meta: {\n ...tag,\n tagId: tag.id,\n },\n });\n response.status(201).json(tag);\n });\n\n router.delete('/tags/:tag', async (request, response) => {\n const tagId = Number.parseInt(request.params.tag, 10);\n const validateRequestBody = ajv.compile(DeleteMetadataSchema);\n if (Number.isNaN(tagId) || !validateRequestBody(request.body)) {\n response.status(400).send({ errors: 'Invalid tag id', type: 'body' });\n return;\n }\n\n const tag = await database.getTagById(tagId);\n await permissionMgr.authorize(\n request,\n [{ permission: qetaDeleteTagPermission, resource: tag! }],\n { throwOnDeny: true },\n );\n const deleted = await database.deleteTag(tagId);\n\n if (deleted) {\n auditor?.createEvent({\n eventId: 'delete-tag',\n severityLevel: 'medium',\n request,\n meta: {\n tagId,\n reason: request.body.reason,\n },\n });\n }\n // Response\n response.sendStatus(deleted ? 204 : 404);\n });\n\n router.get('/entities', async (request, response) => {\n const validateQuery = ajv.compile(EntitiesQuerySchema);\n if (!validateQuery(request.query)) {\n response\n .status(400)\n .send({ errors: validateQuery.errors, type: 'query' });\n return;\n }\n\n let entityRefs: string[] | undefined;\n if (request.query.searchQuery) {\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: await httpAuth.credentials(request),\n targetPluginId: 'catalog',\n });\n const entities = await catalog.queryEntities(\n {\n filter: {\n kind: supportedKinds,\n },\n fields: ['kind', 'metadata.name', 'metadata.namespace'],\n fullTextFilter: {\n term: String(request.query.searchQuery),\n fields: [\n 'metadata.name',\n 'metadata.title',\n 'metadata.description',\n 'spec.profile.displayName',\n ],\n },\n },\n { token },\n );\n entityRefs = entities.items\n .map(entity => {\n try {\n return stringifyEntityRef(entity);\n } catch (_e) {\n return null;\n }\n })\n .filter((e): e is string => e !== null);\n }\n\n const entities = await database.getEntities({\n entityRefs,\n ...request.query,\n });\n response.json(entities);\n });\n\n router.post('/entities/suggest', async (request, response) => {\n const validateRequestBody = ajv.compile(DraftQuestionSchema);\n if (!validateRequestBody(request.body)) {\n response.status(400).send({ errors: validateRequestBody.errors });\n return;\n }\n\n try {\n const suggestedTags = await getSuggestedTags(\n request,\n request.body.title,\n request.body.content,\n request.body.entities,\n );\n\n const allTags = request.body.tags\n ? [...new Set([...request.body.tags, ...suggestedTags])]\n : suggestedTags;\n\n if (!allTags.length) {\n response.json({ entities: [] });\n return;\n }\n\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: await httpAuth.credentials(request),\n targetPluginId: 'catalog',\n });\n const entities = await catalog.queryEntities(\n {\n filter: {\n 'metadata.tags': allTags,\n kind: supportedKinds,\n },\n },\n { token },\n );\n\n const notSetEntities = entities.items.filter(entity => {\n const ref = stringifyEntityRef(entity);\n return !request.body.entities?.includes(ref);\n });\n\n response.json({ entities: notSetEntities });\n } catch (error) {\n logger.error(`Failed to generate entity suggestions: ${error}`);\n response\n .status(500)\n .json({ error: 'Failed to generate entity suggestions' });\n }\n });\n\n router.get('/entities/followed', async (request, response) => {\n const username = await permissionMgr.getUsername(request, false);\n const tags = await database.getUserEntities(username);\n response.json(tags);\n });\n\n router.get('/entities/links', async (request, response) => {\n const credentials = await httpAuth.credentials(request, {\n allow: ['service'],\n });\n if (!credentials) {\n response.sendStatus(401);\n return;\n }\n\n const links = await database.getEntityLinks();\n response.json(links);\n });\n\n router.put('/entities/follow/:entityRef(*)', async (request, response) => {\n const { entityRef } = request.params;\n validateEntityRef(entityRef);\n const username = await permissionMgr.getUsername(request, false);\n await database.followEntity(username, entityRef);\n auditor?.createEvent({\n eventId: 'follow-entity',\n severityLevel: 'low',\n request,\n meta: {\n entityRef,\n },\n });\n response.status(204).send();\n });\n\n router.delete('/entities/follow/:entityRef(*)', async (request, response) => {\n const { entityRef } = request.params;\n validateEntityRef(entityRef);\n const username = await permissionMgr.getUsername(request, false);\n await database.unfollowEntity(username, entityRef);\n auditor?.createEvent({\n eventId: 'unfollow-entity',\n severityLevel: 'low',\n request,\n meta: {\n entityRef,\n },\n });\n response.status(204).send();\n });\n\n router.get('/entities/:entityRef(*)', async (request, response) => {\n validateEntityRef(request.params.entityRef);\n const entity = await database.getEntity(request.params.entityRef);\n if (entity === null) {\n response.sendStatus(404);\n return;\n }\n auditor?.createEvent({\n eventId: 'read-entity',\n severityLevel: 'low',\n request,\n meta: { entityRef: request.params.entityRef },\n });\n response.json(entity);\n });\n\n // GET /timeline\n router.get(`/timeline`, async (request, response) => {\n const username = await permissionMgr.getUsername(request, true);\n const limit = request.query.limit\n ? Number.parseInt(request.query.limit as string, 10)\n : 10;\n const offset = request.query.offset\n ? Number.parseInt(request.query.offset as string, 10)\n : 0;\n const includeTotal = request.query.includeTotal === 'true';\n\n const [filter, commentsFilter, answersFilter, collectionsFilter] =\n await Promise.all([\n permissionMgr.getAuthorizeConditions(request, qetaReadPostPermission, {\n allowServicePrincipal: true,\n }),\n permissionMgr.getAuthorizeConditions(\n request,\n qetaReadCommentPermission,\n {\n allowServicePrincipal: true,\n },\n ),\n permissionMgr.getAuthorizeConditions(\n request,\n qetaReadAnswerPermission,\n {\n allowServicePrincipal: true,\n },\n ),\n permissionMgr.getAuthorizeConditions(\n request,\n qetaReadCollectionPermission,\n {\n allowServicePrincipal: true,\n },\n ),\n ]);\n\n const timeline = await database.getTimeline(\n username,\n { limit, offset, includeTotal },\n {\n posts: filter,\n answers: answersFilter,\n comments: commentsFilter,\n collections: collectionsFilter,\n },\n );\n response.json(timeline);\n });\n};\n"],"names":["Ajv","addFormats","getSupportedEntityKinds","parseEntityRef","UsersQuerySchema","users","stringifyEntityRef","TagsQuerySchema","qetaReadTagPermission","mapAdditionalFields","CATALOG_FILTER_EXISTS","filterTags","removeStopwords","eng","DraftQuestionSchema","qetaEditTagPermission","qetaCreateTagPermission","isValidTag","DeleteMetadataSchema","qetaDeleteTagPermission","EntitiesQuerySchema","entities","qetaReadPostPermission","qetaReadCommentPermission","qetaReadAnswerPermission","qetaReadCollectionPermission"],"mappings":"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"}
@@ -1,9 +1,10 @@
1
1
  'use strict';
2
2
 
3
- var types = require('../types.cjs.js');
3
+ var types$1 = require('../types.cjs.js');
4
4
  var backstagePluginQetaCommon = require('@drodil/backstage-plugin-qeta-common');
5
5
  var Ajv = require('ajv');
6
6
  var addFormats = require('ajv-formats');
7
+ var types = require('@backstage/types');
7
8
 
8
9
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
9
10
 
@@ -13,7 +14,11 @@ var addFormats__default = /*#__PURE__*/_interopDefaultCompat(addFormats);
13
14
  const ajv = new Ajv__default.default({ coerceTypes: "array" });
14
15
  addFormats__default.default(ajv);
15
16
  const suggestionRoutes = (router, options) => {
16
- const { database, permissionMgr } = options;
17
+ const { database, permissionMgr, config } = options;
18
+ const postsOlderThan = config.getOptional(
19
+ "qeta.contentHealth.postsOlderThan"
20
+ ) ?? { months: 6 };
21
+ const reviewThresholdMs = types.durationToMilliseconds(postsOlderThan);
17
22
  const includeNothingOptions = {
18
23
  includeVotes: false,
19
24
  includeTags: false,
@@ -264,6 +269,19 @@ const suggestionRoutes = (router, options) => {
264
269
  link
265
270
  }));
266
271
  };
272
+ const getPostsNeedingReview = async (username, filter) => {
273
+ const posts = await database.getPosts(
274
+ username,
275
+ { reviewNeeded: true, includeHealth: true, limit: 5 },
276
+ filter,
277
+ { ...includeNothingOptions, reviewThresholdMs }
278
+ );
279
+ return posts.posts.map((post) => ({
280
+ id: `r_${post.id}`,
281
+ type: "needsReview",
282
+ post
283
+ }));
284
+ };
267
285
  const getRandomPosts = async (username, limit, filter) => {
268
286
  const posts = await database.getPosts(
269
287
  username,
@@ -278,7 +296,7 @@ const suggestionRoutes = (router, options) => {
278
296
  }));
279
297
  };
280
298
  router.get("/suggestions", async (request, response) => {
281
- const validateQuery = ajv.compile(types.SuggestionsQuerySchema);
299
+ const validateQuery = ajv.compile(types$1.SuggestionsQuerySchema);
282
300
  if (!validateQuery(request.query)) {
283
301
  response.status(400).send({ errors: validateQuery.errors, type: "query" });
284
302
  return;
@@ -292,7 +310,11 @@ const suggestionRoutes = (router, options) => {
292
310
  request,
293
311
  backstagePluginQetaCommon.qetaReadPostPermission
294
312
  );
295
- const raw = await Promise.all([
313
+ const canReviewResults = await permissionMgr.authorizeBoolean(request, [
314
+ { permission: backstagePluginQetaCommon.qetaCreatePostReviewPermission }
315
+ ]);
316
+ const canReview = canReviewResults[0] ?? false;
317
+ const promises = [
296
318
  getNotCorrectQuestions(username, filter),
297
319
  getNewTagQuestions(username, filter),
298
320
  getNewTagArticles(username, filter),
@@ -303,8 +325,10 @@ const suggestionRoutes = (router, options) => {
303
325
  getNewUserQuestions(username, filter),
304
326
  getNewUserArticles(username, filter),
305
327
  getNewUserLinks(username, filter),
306
- getUsersDraftPosts(username, filter)
307
- ]);
328
+ getUsersDraftPosts(username, filter),
329
+ canReview ? getPostsNeedingReview(username, filter) : Promise.resolve([])
330
+ ];
331
+ const raw = await Promise.all(promises);
308
332
  const suggestionsRaw = raw.flat().reduce((acc, cur) => {
309
333
  if (!acc.some((s) => s.id === cur.id)) {
310
334
  acc.push(cur);
@@ -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 NewArticleSuggestion,\n NewLinkSuggestion,\n NewQuestionSuggestion,\n NoCorrectAnswerSuggestion,\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';\n\nconst ajv = new Ajv({ coerceTypes: 'array' });\naddFormats(ajv);\n\nexport const suggestionRoutes = (router: Router, options: RouteOptions) => {\n const { database, permissionMgr } = options;\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 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 const raw = await Promise.all([\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 ]);\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","SuggestionsQuerySchema","qetaReadPostPermission"],"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 {\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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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drodil/backstage-plugin-qeta-backend",
3
- "version": "3.51.1",
3
+ "version": "3.52.0",
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.51.1",
70
- "@drodil/backstage-plugin-qeta-node": "^3.51.1",
69
+ "@drodil/backstage-plugin-qeta-common": "^3.52.0",
70
+ "@drodil/backstage-plugin-qeta-node": "^3.52.0",
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.51.1",
109
- "@drodil/backstage-plugin-qeta-backend-module-openai": "^3.51.1",
110
- "@drodil/backstage-plugin-search-backend-module-qeta": "^3.51.1",
108
+ "@drodil/backstage-plugin-catalog-backend-module-qeta": "^3.52.0",
109
+ "@drodil/backstage-plugin-qeta-backend-module-openai": "^3.52.0",
110
+ "@drodil/backstage-plugin-search-backend-module-qeta": "^3.52.0",
111
111
  "@types/sanitize-html": "^2.9.5",
112
112
  "@types/stopword": "^2.0.3",
113
113
  "@types/supertest": "^2.0.12",