Skip to content

Commit c6f8ad2

Browse files
committed
Use Record instead of Map for user settings
The syntax of using Map was getting frustrating for tests, so use Record instead. Record is just a javascript object, and so keys are always strings (despite the type of Record<>), and so just use strings for IDs within user settings keys.
1 parent badb704 commit c6f8ad2

15 files changed

+647
-317
lines changed

src/app/domain/entityStore/entities/UserSettingsEntity.ts

Lines changed: 3 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,10 @@
1-
import { entityFromPkOnlyEntity } from '@symphoniacloud/dynamodb-entity-store'
1+
import { entityFromPkOnlyEntity, typePredicateParser } from '@symphoniacloud/dynamodb-entity-store'
22
import { USER_SETTINGS } from '../entityTypes'
3-
import { PersistedUserSettings } from '../../types/UserSettings'
4-
import { DynamoDBValues } from '@symphoniacloud/dynamodb-entity-store/dist/cjs/entities'
5-
import { parseDynamoDBDictToMap } from '../entityStoreEntitySupport'
6-
import { identity } from '../../../util/functional'
7-
8-
export function parseUserSettings(item: DynamoDBValues): PersistedUserSettings {
9-
// TODO - check things actually exist
10-
return {
11-
userId: item.userId,
12-
github: {
13-
accounts: parseDynamoDBDictToMap(
14-
Number.parseInt,
15-
(value) => ({
16-
...value,
17-
repos: parseDynamoDBDictToMap(
18-
Number.parseInt,
19-
(value) => ({
20-
...value,
21-
workflows: parseDynamoDBDictToMap(Number.parseInt, identity, value.workflows ?? {})
22-
}),
23-
value.repos ?? {}
24-
)
25-
}),
26-
item.github.accounts
27-
)
28-
}
29-
}
30-
}
3+
import { isUserSettings, PersistedUserSettings } from '../../types/UserSettings'
314

325
export const UserSettingsEntity = entityFromPkOnlyEntity({
336
type: USER_SETTINGS,
34-
parse: parseUserSettings,
7+
parse: typePredicateParser(isUserSettings, USER_SETTINGS),
358
pk(source: Pick<PersistedUserSettings, 'userId'>) {
369
return `USERID#${source.userId}`
3710
}

src/app/domain/types/UserSettings.ts

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { GithubAccountId, GithubRepoId, GithubUserId, GithubWorkflowId, isGithubUserId } from './GithubKeys'
1+
import { GithubUserId, isGithubUserId } from './GithubKeys'
22
import { isNotNullObject } from '../../util/types'
33

44
export type UserSetting = 'visible' | 'notify'
@@ -19,10 +19,16 @@ export function isUserSettings(x: unknown): x is PersistedUserSettings {
1919
)
2020
}
2121

22+
// Various types here use a string for Record key, rather than GithubAccountID, etc.
23+
// That's because JavaScript always uses strings for object keys, even if the Record type says number
24+
// An earlier version of this code used Maps to keep the strong typing of the ID keys
25+
// but it made the code more verbose - especially for tests - so I decided just to suck it up
26+
// and go with string ID keys
27+
2228
export interface PersistedUserSettings {
2329
userId: GithubUserId
2430
github: {
25-
accounts: Map<GithubAccountId, PersistedGithubAccountSettings>
31+
accounts: Record<string, PersistedGithubAccountSettings>
2632
}
2733
}
2834

@@ -32,11 +38,11 @@ export interface PersistedVisibleAndNotifyConfigurable {
3238
}
3339

3440
export interface PersistedGithubAccountSettings extends PersistedVisibleAndNotifyConfigurable {
35-
repos: Map<GithubRepoId, PersistedGithubRepoSettings>
41+
repos: Record<string, PersistedGithubRepoSettings>
3642
}
3743

3844
export interface PersistedGithubRepoSettings extends PersistedVisibleAndNotifyConfigurable {
39-
workflows: Map<GithubWorkflowId, PersistedGithubWorkflowSettings>
45+
workflows: Record<string, PersistedGithubWorkflowSettings>
4046
}
4147

4248
export type PersistedGithubWorkflowSettings = PersistedVisibleAndNotifyConfigurable
@@ -46,27 +52,28 @@ export type PersistedGithubWorkflowSettings = PersistedVisibleAndNotifyConfigura
4652
export interface CalculatedUserSettings {
4753
userId: GithubUserId
4854
github: {
49-
accounts: Map<GithubAccountId, CalculatedGithubAccountSettings>
55+
accounts: Record<string, CalculatedGithubAccountSettings>
5056
}
5157
}
5258

5359
export type CalculatedVisibleAndNotifyConfigurable = Required<PersistedVisibleAndNotifyConfigurable>
5460

5561
export interface CalculatedGithubAccountSettings extends CalculatedVisibleAndNotifyConfigurable {
56-
repos: Map<GithubRepoId, CalculatedGithubRepoSettings>
62+
repos: Record<string, CalculatedGithubRepoSettings>
5763
}
5864

5965
export interface CalculatedGithubRepoSettings extends CalculatedVisibleAndNotifyConfigurable {
60-
workflows: Map<GithubWorkflowId, CalculatedGithubWorkflowSettings>
66+
workflows: Record<string, CalculatedGithubWorkflowSettings>
6167
}
6268

6369
export type CalculatedGithubWorkflowSettings = CalculatedVisibleAndNotifyConfigurable
6470

6571
// ***
6672

6773
export interface DisplayableUserSettings {
74+
userId: GithubUserId
6875
github: {
69-
accounts: Map<GithubAccountId, DisplayableGithubAccountSettings>
76+
accounts: Record<string, DisplayableGithubAccountSettings>
7077
}
7178
}
7279

@@ -77,11 +84,11 @@ export interface Displayable {
7784
export interface DisplayableGithubAccountSettings
7885
extends CalculatedVisibleAndNotifyConfigurable,
7986
Displayable {
80-
repos: Map<GithubRepoId, DisplayableGithubRepoSettings>
87+
repos: Record<string, DisplayableGithubRepoSettings>
8188
}
8289

8390
export interface DisplayableGithubRepoSettings extends CalculatedVisibleAndNotifyConfigurable, Displayable {
84-
workflows: Map<GithubWorkflowId, DisplayableGithubWorkflowSettings>
91+
workflows: Record<string, DisplayableGithubWorkflowSettings>
8592
}
8693

8794
export type DisplayableGithubWorkflowSettings = CalculatedGithubWorkflowSettings & Displayable

src/app/domain/user/calculatedUserSettings.ts

Lines changed: 33 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import {
22
CalculatedGithubAccountSettings,
33
CalculatedGithubRepoSettings,
4-
CalculatedGithubWorkflowSettings,
54
CalculatedUserSettings,
65
CalculatedVisibleAndNotifyConfigurable,
76
PersistedGithubAccountSettings,
@@ -10,7 +9,7 @@ import {
109
PersistedVisibleAndNotifyConfigurable
1110
} from '../types/UserSettings'
1211
import { GithubWorkflow } from '../types/GithubWorkflow'
13-
import { GithubAccountId, GithubRepoId, GithubRepoKey, GithubWorkflowId } from '../types/GithubKeys'
12+
import { GithubAccountId, GithubRepoKey } from '../types/GithubKeys'
1413
import {
1514
findUniqueAccountIds,
1615
findUniqueRepoIdsForAccount,
@@ -23,16 +22,14 @@ export function calculateUserSettings(
2322
settings: PersistedUserSettings,
2423
allWorkflows: GithubWorkflow[]
2524
): CalculatedUserSettings {
26-
const accountEntries: [GithubAccountId, CalculatedGithubAccountSettings][] = findUniqueAccountIds(
27-
allWorkflows
28-
).map((id) => {
29-
return [id, calculateAccountSettings(settings.github.accounts.get(id), id, allWorkflows)]
30-
})
31-
3225
return {
3326
userId: settings.userId,
3427
github: {
35-
accounts: new Map<GithubAccountId, CalculatedGithubAccountSettings>(accountEntries)
28+
accounts: Object.fromEntries(
29+
findUniqueAccountIds(allWorkflows).map((id) => {
30+
return [id, calculateAccountSettings(settings.github.accounts[id], id, allWorkflows)]
31+
})
32+
)
3633
}
3734
}
3835
}
@@ -43,27 +40,23 @@ export function calculateAccountSettings(
4340
allWorkflows: GithubWorkflow[]
4441
): CalculatedGithubAccountSettings {
4542
const visibleAndNotify = calculateVisibleAndNotifyConfigurable(settings, DEFAULT_ACCOUNT_NOTIFY)
43+
const repos = visibleAndNotify.visible
44+
? Object.fromEntries(
45+
findUniqueRepoIdsForAccount(allWorkflows, accountId).map((repoId) => {
46+
return [
47+
repoId,
48+
calculateRepoSettings(
49+
settings?.repos[repoId],
50+
{ ownerId: accountId, repoId },
51+
allWorkflows,
52+
visibleAndNotify.notify
53+
)
54+
]
55+
})
56+
)
57+
: {}
4658

47-
if (!visibleAndNotify.visible) {
48-
return { ...visibleAndNotify, repos: new Map<GithubRepoId, CalculatedGithubRepoSettings>() }
49-
}
50-
51-
return {
52-
...visibleAndNotify,
53-
repos: new Map<GithubRepoId, CalculatedGithubRepoSettings>(
54-
findUniqueRepoIdsForAccount(allWorkflows, accountId).map((repoId) => {
55-
return [
56-
repoId,
57-
calculateRepoSettings(
58-
settings?.repos.get(repoId),
59-
{ ownerId: accountId, repoId },
60-
allWorkflows,
61-
visibleAndNotify.notify
62-
)
63-
]
64-
})
65-
)
66-
}
59+
return { ...visibleAndNotify, repos }
6760
}
6861

6962
export function calculateRepoSettings(
@@ -73,22 +66,18 @@ export function calculateRepoSettings(
7366
defaultNotify: boolean
7467
): CalculatedGithubRepoSettings {
7568
const visibleAndNotify = calculateVisibleAndNotifyConfigurable(repoSettings, defaultNotify)
69+
const workflows = visibleAndNotify.visible
70+
? Object.fromEntries(
71+
findWorkflowsForRepo(allWorkflows, repoKey).map((wf) => {
72+
return [
73+
wf.workflowId,
74+
calculateWorkflowSettings(repoSettings?.workflows[wf.workflowId], visibleAndNotify.notify)
75+
]
76+
})
77+
)
78+
: {}
7679

77-
if (!visibleAndNotify.visible) {
78-
return { ...visibleAndNotify, workflows: new Map<GithubWorkflowId, CalculatedGithubWorkflowSettings>() }
79-
}
80-
81-
return {
82-
...visibleAndNotify,
83-
workflows: new Map<GithubWorkflowId, CalculatedGithubWorkflowSettings>(
84-
findWorkflowsForRepo(allWorkflows, repoKey).map((wf) => {
85-
return [
86-
wf.workflowId,
87-
calculateWorkflowSettings(repoSettings?.workflows.get(wf.workflowId), visibleAndNotify.notify)
88-
]
89-
})
90-
)
91-
}
80+
return { ...visibleAndNotify, workflows }
9281
}
9382

9483
export const calculateWorkflowSettings = calculateVisibleAndNotifyConfigurable

src/app/domain/user/displayableUserSettings.ts

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,7 @@ import {
1010
PersistedUserSettings
1111
} from '../types/UserSettings'
1212
import { GithubWorkflow } from '../types/GithubWorkflow'
13-
import {
14-
GithubAccountId,
15-
GithubRepoId,
16-
GithubRepoKey,
17-
GithubWorkflowId,
18-
GithubWorkflowKey
19-
} from '../types/GithubKeys'
13+
import { GithubAccountId, GithubRepoKey, GithubWorkflowKey } from '../types/GithubKeys'
2014
import { findAccountName, findRepoName, findWorkflowName } from '../github/githubWorkflow'
2115
import { calculateUserSettings } from './calculatedUserSettings'
2216

@@ -32,11 +26,12 @@ function toDisplayableUserSettings(
3226
workflows: GithubWorkflow[]
3327
): DisplayableUserSettings {
3428
return {
29+
userId: userSettings.userId,
3530
github: {
36-
accounts: new Map<GithubAccountId, DisplayableGithubAccountSettings>(
37-
Array.from(userSettings.github.accounts.entries()).map(([accountId, accountSettings]) => [
31+
accounts: Object.fromEntries(
32+
Object.entries(userSettings.github.accounts).map(([accountId, accountSettings]) => [
3833
accountId,
39-
toDisplayableAccountSettings(accountId, accountSettings, workflows)
34+
toDisplayableAccountSettings(Number(accountId), accountSettings, workflows)
4035
])
4136
)
4237
}
@@ -51,13 +46,13 @@ export function toDisplayableAccountSettings(
5146
return {
5247
...accountSettings,
5348
name: findAccountName(allWorkflows, accountId),
54-
repos: new Map<GithubRepoId, DisplayableGithubRepoSettings>(
55-
Array.from(accountSettings.repos.entries()).map(([repoId, repoSettings]) => [
49+
repos: Object.fromEntries(
50+
Object.entries(accountSettings.repos).map(([repoId, repoSettings]) => [
5651
repoId,
5752
toDisplayableRepoSettings(
5853
{
5954
ownerId: accountId,
60-
repoId
55+
repoId: Number(repoId)
6156
},
6257
repoSettings,
6358
allWorkflows
@@ -75,10 +70,14 @@ export function toDisplayableRepoSettings(
7570
return {
7671
...repoSettings,
7772
name: findRepoName(allWorkflows, repoKey),
78-
workflows: new Map<GithubWorkflowId, DisplayableGithubWorkflowSettings>(
79-
Array.from(repoSettings.workflows.entries()).map(([workflowId, workflowSettings]) => [
73+
workflows: Object.fromEntries(
74+
Object.entries(repoSettings.workflows).map(([workflowId, workflowSettings]) => [
8075
workflowId,
81-
toDisplayableWorkflowSettings({ ...repoKey, workflowId }, workflowSettings, allWorkflows)
76+
toDisplayableWorkflowSettings(
77+
{ ...repoKey, workflowId: Number(workflowId) },
78+
workflowSettings,
79+
allWorkflows
80+
)
8281
])
8382
)
8483
}

src/app/domain/user/persistedUserSettings.ts

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,9 @@ import {
66
PersistedUserSettings,
77
UserSetting
88
} from '../types/UserSettings'
9-
import {
10-
GithubAccountId,
11-
GithubRepoId,
12-
GithubRepoKey,
13-
GithubUserId,
14-
GithubWorkflowId,
15-
GithubWorkflowKey
16-
} from '../types/GithubKeys'
9+
import { GithubAccountId, GithubRepoKey, GithubUserId, GithubWorkflowKey } from '../types/GithubKeys'
1710
import { UserSettingsEntity } from '../entityStore/entities/UserSettingsEntity'
18-
import { getFromMapOrSetNewAndReturn } from '../../util/collections'
11+
import { getOrSetNewAndReturn } from '../../util/collections'
1912

2013
function userSettingsEntity(appState: AppState) {
2114
return appState.entityStore.for(UserSettingsEntity)
@@ -46,7 +39,7 @@ function initialUserSettings(userId: GithubUserId): PersistedUserSettings {
4639
return {
4740
userId,
4841
github: {
49-
accounts: new Map<GithubAccountId, PersistedGithubAccountSettings>()
42+
accounts: {}
5043
}
5144
}
5245
}
@@ -117,8 +110,8 @@ function getOrCreateAndReturnAccountSettings(
117110
settings: PersistedUserSettings,
118111
accountId: GithubAccountId
119112
): PersistedGithubAccountSettings {
120-
return getFromMapOrSetNewAndReturn(settings.github.accounts, accountId, () => ({
121-
repos: new Map<GithubRepoId, PersistedGithubRepoSettings>()
113+
return getOrSetNewAndReturn(settings.github.accounts, `${accountId}`, () => ({
114+
repos: {}
122115
}))
123116
}
124117

@@ -127,8 +120,8 @@ function getOrCreateAndReturnRepoSettings(
127120
repoKey: GithubRepoKey
128121
): PersistedGithubRepoSettings {
129122
const accountSettings = getOrCreateAndReturnAccountSettings(settings, repoKey.ownerId)
130-
return getFromMapOrSetNewAndReturn(accountSettings.repos, repoKey.repoId, () => ({
131-
workflows: new Map<GithubWorkflowId, PersistedGithubWorkflowSettings>()
123+
return getOrSetNewAndReturn(accountSettings.repos, `${repoKey.repoId}`, () => ({
124+
workflows: {}
132125
}))
133126
}
134127

@@ -137,5 +130,5 @@ function getOrCreateAndReturnWorkflowSettings(
137130
workflowKey: GithubWorkflowKey
138131
): PersistedGithubWorkflowSettings {
139132
const repoSettings = getOrCreateAndReturnRepoSettings(settings, workflowKey)
140-
return getFromMapOrSetNewAndReturn(repoSettings.workflows, workflowKey.workflowId, () => ({}))
133+
return getOrSetNewAndReturn(repoSettings.workflows, `${workflowKey.workflowId}`, () => ({}))
141134
}

src/app/domain/user/userNotifyable.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,9 @@ export async function getWorkflowNotifyEnabledForUser(
2828
await getUserSettings(appState, userId),
2929
await getWorkflowsForUser(appState, userId)
3030
)
31-
const yesNotify = userSettings.github.accounts
32-
.get(workflow.ownerId)
33-
?.repos.get(workflow.repoId)
34-
?.workflows.get(workflow.workflowId)?.notify
31+
const yesNotify =
32+
userSettings.github.accounts[workflow.ownerId]?.repos[workflow.repoId]?.workflows[workflow.workflowId]
33+
.notify
3534
if (yesNotify === undefined) {
3635
logger.warn(`No calculated user notify setting for workflow`, { workflow, userSettings })
3736
return false

src/app/domain/user/userVisible.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,7 @@ export async function getRecentActiveBranchesForUser(appState: AppState, userId:
9494
function toVisibleEvents(allEvents: GithubWorkflowRunEvent[], userSettings: CalculatedUserSettings) {
9595
const visibleEvents = allEvents.filter(
9696
({ ownerId, repoId, workflowId }) =>
97-
userSettings.github.accounts.get(ownerId)?.repos.get(repoId)?.workflows.get(workflowId)?.visible ??
98-
false
97+
userSettings.github.accounts[ownerId]?.repos[repoId]?.workflows[workflowId]?.visible ?? false
9998
)
10099
return {
101100
allEvents,
@@ -106,7 +105,7 @@ function toVisibleEvents(allEvents: GithubWorkflowRunEvent[], userSettings: Calc
106105

107106
function toVisiblePushes(allEvents: GithubPush[], userSettings: CalculatedUserSettings) {
108107
const visibleEvents = allEvents.filter(
109-
({ ownerId, repoId }) => userSettings.github.accounts.get(ownerId)?.repos.get(repoId)?.visible ?? false
108+
({ ownerId, repoId }) => userSettings.github.accounts[ownerId]?.repos[repoId]?.visible ?? false
110109
)
111110
return {
112111
allEvents,

0 commit comments

Comments
 (0)