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

hicommonwealth / commonwealth / 16179246405

09 Jul 2025 08:13PM UTC coverage: 40.02% (+0.004%) from 40.016%
16179246405

Pull #12605

github

web-flow
Merge 368b52512 into eb7356236
Pull Request #12605: Added migration to deduplicate names

1859 of 5032 branches covered (36.94%)

Branch coverage included in aggregate %.

5 of 5 new or added lines in 1 file covered. (100.0%)

3 existing lines in 2 files now uncovered.

3294 of 7844 relevant lines covered (41.99%)

36.9 hits per line

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

73.33
/libs/model/src/aggregates/user/UpdateUser.command.ts
1
import { InvalidInput, type Command } from '@hicommonwealth/core';
2
import * as schemas from '@hicommonwealth/schemas';
3
import { DEFAULT_NAME } from '@hicommonwealth/shared';
4
import { models } from '../../database';
5
import { authVerified } from '../../middleware/auth';
6
import { mustExist } from '../../middleware/guards';
7
import { decodeContent, emitEvent, getDelta, updateTags } from '../../utils';
8

9
export function UpdateUser(): Command<typeof schemas.UpdateUser> {
10
  return {
1✔
11
    ...schemas.UpdateUser,
12
    auth: [authVerified()],
13
    body: async ({ actor, payload }) => {
14
      // comparing number to string since command convention requires string id
15
      if (actor.user.id != payload.id)
1!
16
        throw new InvalidInput('Invalid user id');
×
17

18
      const { id, profile, tag_ids } = payload;
1✔
19
      const {
20
        slug,
21
        name,
22
        email,
23
        website,
24
        avatar_url,
25
        socials,
26
        bio: rawBio,
27
        background_image,
28
      } = profile;
1✔
29

30
      const user = (
1✔
31
        await models.User.findOne({
32
          where: { id },
33
          include: {
34
            model: models.ProfileTags,
35
          },
36
        })
37
      )?.toJSON();
38
      mustExist('User', user);
1✔
39

40
      const is_welcome_onboard_flow_complete = !!(
1✔
41
        user.is_welcome_onboard_flow_complete ||
3✔
42
        (name && name !== DEFAULT_NAME)
43
      );
44

45
      const promotional_emails_enabled =
46
        payload.promotional_emails_enabled ??
1✔
47
        user.promotional_emails_enabled ??
48
        false;
49

50
      const notify_user_name_change =
51
        payload.notify_user_name_change ??
1!
52
        user.notify_user_name_change ??
53
        false;
54

55
      const user_delta = getDelta(user, {
1✔
56
        is_welcome_onboard_flow_complete,
57
        promotional_emails_enabled,
58
        notify_user_name_change,
59
        profile: {
60
          email,
61
          slug,
62
          name,
63
          bio: rawBio && decodeContent(rawBio),
1!
64
          website,
65
          avatar_url,
66
          socials,
67
          background_image,
68
        },
69
      });
70

71
      const tags_delta = tag_ids
1!
72
        ? getDelta(
73
            { tag_ids: user.ProfileTags?.map((t) => t.tag_id) },
×
74
            {
75
              tag_ids,
76
            },
77
          )
78
        : {};
79

80
      const update_user = Object.keys(user_delta).length;
1✔
81
      const update_tags = Object.keys(tags_delta).length;
1✔
82

83
      if (update_user || update_tags) {
1!
84
        const updated = await models.sequelize.transaction(
1✔
85
          async (transaction) => {
86
            if (update_tags)
1!
87
              await updateTags(tag_ids!, user.id!, 'user_id', transaction);
×
88

89
            if (update_user) {
1!
90
              // TODO: utility to deep merge deltas
91
              const updates = {
1✔
92
                ...user_delta,
93
                profile: {
94
                  ...user.profile,
95
                  ...user_delta.profile,
96
                  background_image: {
97
                    ...user.profile.background_image,
98
                    ...user_delta.profile?.background_image,
99
                  },
100
                },
101
              };
102
              if (updates.profile.bio === '') {
1!
103
                updates.profile.bio = null;
×
104
              }
105
              const [, rows] = await models.User.update(updates, {
1✔
106
                where: { id: user.id },
107
                returning: true,
108
                transaction,
109
              });
110
              const updated_user = rows.at(0);
1✔
111

112
              // emit sign-up flow completed event when:
113
              if (updated_user && user_delta.is_welcome_onboard_flow_complete) {
1!
114
                await emitEvent(
1✔
115
                  models.Outbox,
116
                  [
117
                    {
118
                      event_name: 'SignUpFlowCompleted',
119
                      event_payload: {
120
                        user_id: id,
121
                        address: actor.address!,
122
                        referred_by_address: user.referred_by_address,
123
                        created_at: updated_user.created_at!,
124
                      },
125
                    },
126
                  ],
127
                  transaction,
128
                );
129
              }
130
              return updated_user;
1✔
UNCOV
131
            } else return user;
×
132
          },
133
        );
134

135
        return updated!;
1✔
136
      }
137

138
      // nothing changed
UNCOV
139
      return user;
×
140
    },
141
  };
142
}
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