• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

hicommonwealth / commonwealth / 15559623773

10 Jun 2025 12:34PM UTC coverage: 40.748% (-0.08%) from 40.827%
15559623773

push

github

web-flow
Merge pull request #12366 from hicommonwealth/rotorsoft/12364-topic-gate-getthreadsbyids

Adds new query for single ids and protect private topics

1771 of 4719 branches covered (37.53%)

Branch coverage included in aggregate %.

0 of 18 new or added lines in 4 files covered. (0.0%)

2 existing lines in 2 files now uncovered.

3206 of 7495 relevant lines covered (42.78%)

37.45 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/libs/model/src/aggregates/thread/GetThreadsByIds.query.ts
1
import { InvalidInput, Query } from '@hicommonwealth/core';
2
import * as schemas from '@hicommonwealth/schemas';
3
import { Op } from 'sequelize';
4
import { z } from 'zod';
5
import { models, sequelize } from '../../database';
6
import { authOptional } from '../../middleware';
7

8
export function GetThreadsByIds(): Query<typeof schemas.GetThreadsByIds> {
9
  return {
×
10
    ...schemas.GetThreadsByIds,
11
    auth: [authOptional],
12
    secure: true,
13
    body: async ({ payload }) => {
14
      const { community_id, thread_ids } = payload;
×
15
      if (thread_ids === '') return [];
×
16

17
      let parsedThreadIds: number[];
18

19
      try {
×
20
        parsedThreadIds = z
×
21
          .string()
22
          .transform((ids) =>
23
            ids.split(',').map((id) => parseInt(id.trim(), 10)),
×
24
          )
25
          .parse(thread_ids);
26
      } catch (e) {
27
        throw new InvalidInput('Invalid thread_ids format');
×
28
      }
29

30
      // TODO: add gating filters if needed, just used in thread linking atm
UNCOV
31
      const threads = await models.Thread.findAll({
×
32
        where: {
33
          ...(community_id && { community_id }),
×
34
          id: { [Op.in]: parsedThreadIds },
35
        },
36

37
        include: [
38
          {
39
            model: models.Address,
40
            as: 'Address',
41
            include: [
42
              {
43
                model: models.User,
44
                as: 'User',
45
                required: true,
46
                attributes: ['id', 'profile', 'tier'],
47
              },
48
            ],
49
          },
50
          {
51
            model: models.Address,
52
            as: 'collaborators',
53
            include: [
54
              {
55
                model: models.User,
56
                as: 'User',
57
                required: true,
58
                attributes: ['id', 'profile', 'tier'],
59
              },
60
            ],
61
          },
62
          {
63
            model: models.Topic,
64
            as: 'topic',
65
            required: true,
66
          },
67
          {
68
            model: models.Reaction,
69
            as: 'reactions',
70
            include: [
71
              {
72
                model: models.Address,
73
                as: 'Address',
74
                required: true,
75
                include: [
76
                  {
77
                    model: models.User,
78
                    as: 'User',
79
                    required: true,
80
                    attributes: ['id', 'profile', 'tier'],
81
                  },
82
                ],
83
              },
84
            ],
85
          },
86
          {
87
            model: models.ContestAction,
88
            where: {
89
              action: 'upvoted',
90
            },
91
            required: false,
92
            attributes: ['content_id', 'thread_id'],
93
            include: [
94
              {
95
                model: models.Contest,
96
                on: {
97
                  contest_id: sequelize.where(
98
                    sequelize.col('"ContestActions".contest_id'),
99
                    '=',
100
                    sequelize.col('"ContestActions->Contest".contest_id'),
101
                  ),
102
                  contest_address: sequelize.where(
103
                    sequelize.col('"ContestActions".contest_address'),
104
                    '=',
105
                    sequelize.col('"ContestActions->Contest".contest_address'),
106
                  ),
107
                },
108
                attributes: [
109
                  'contest_id',
110
                  'contest_address',
111
                  'score',
112
                  'start_time',
113
                  'end_time',
114
                ],
115
                include: [
116
                  {
117
                    model: models.ContestManager,
118
                    attributes: ['name', 'cancelled', 'interval'],
119
                  },
120
                ],
121
              },
122
            ],
123
          },
124
          {
125
            model: models.ThreadVersionHistory,
126
          },
127
        ],
128
      });
129

130
      return threads!.map(
×
131
        (t) => t.toJSON() as z.infer<typeof schemas.ThreadView>,
×
132
      );
133
    },
134
  };
135
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc