File tree Expand file tree Collapse file tree 3 files changed +65
-3
lines changed Expand file tree Collapse file tree 3 files changed +65
-3
lines changed Original file line number Diff line number Diff line change
1
+ /**
2
+ * Like [`Map.groupBy`][0], but the result's values aren't arrays.
3
+ *
4
+ * If multiple values resolve to the same key, an error is thrown.
5
+ *
6
+ * [0]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/groupBy
7
+ *
8
+ * @template T
9
+ * @template K
10
+ * @param {Iterable<T> } items
11
+ * @param {(item: T) => K } callbackFn
12
+ * @returns {Map<K, T> }
13
+ */
14
+ export function keyBy ( items , callbackFn ) {
15
+ /** @type {Map<K, T> } */ const result = new Map ( )
16
+ for ( const item of items ) {
17
+ const key = callbackFn ( item )
18
+ if ( result . has ( key ) ) {
19
+ throw new Error ( `keyBy found duplicate key ${ JSON . stringify ( key ) } ` )
20
+ }
21
+ result . set ( key , item )
22
+ }
23
+ return result
24
+ }
Original file line number Diff line number Diff line change 9
9
projectKeyToId ,
10
10
projectKeyToProjectInviteId ,
11
11
} from './utils.js'
12
+ import { keyBy } from './lib/key-by.js'
12
13
import { abortSignalAny } from './lib/ponyfills.js'
13
14
import timingSafeEqual from './lib/timing-safe-equal.js'
14
15
import { ROLES , isRoleIdForNewInvite } from './roles.js'
@@ -279,6 +280,8 @@ export class MemberApi extends TypedEmitter {
279
280
this . #dataTypes. deviceInfo . getMany ( ) ,
280
281
] )
281
282
283
+ const deviceInfoByConfigCoreId = keyBy ( allDeviceInfo , ( { docId } ) => docId )
284
+
282
285
return Promise . all (
283
286
[ ...allRoles . entries ( ) ] . map ( async ( [ deviceId , role ] ) => {
284
287
/** @type {MemberInfo } */
@@ -290,9 +293,7 @@ export class MemberApi extends TypedEmitter {
290
293
'config'
291
294
)
292
295
293
- const deviceInfo = allDeviceInfo . find (
294
- ( { docId } ) => docId === configCoreId
295
- )
296
+ const deviceInfo = deviceInfoByConfigCoreId . get ( configCoreId )
296
297
297
298
memberInfo . name = deviceInfo ?. name
298
299
memberInfo . deviceType = deviceInfo ?. deviceType
Original file line number Diff line number Diff line change
1
+ import assert from 'node:assert/strict'
2
+ import test from 'node:test'
3
+ import { keyBy } from '../../src/lib/key-by.js'
4
+
5
+ test ( 'returns an empty map if passed an empty iterable' , ( ) => {
6
+ assert . deepEqual (
7
+ keyBy ( [ ] , ( ) => {
8
+ throw new Error ( 'Should not be called' )
9
+ } ) ,
10
+ new Map ( )
11
+ )
12
+ } )
13
+
14
+ test ( 'keys a list of items by a key function' , ( ) => {
15
+ const items = [
16
+ { id : 1 , name : 'foo' } ,
17
+ { id : 2 , name : 'bar' } ,
18
+ { id : 3 , name : 'baz' } ,
19
+ ]
20
+ const result = keyBy ( items , ( item ) => item . id )
21
+ assert . deepEqual (
22
+ result ,
23
+ new Map ( [
24
+ [ 1 , items [ 0 ] ] ,
25
+ [ 2 , items [ 1 ] ] ,
26
+ [ 3 , items [ 2 ] ] ,
27
+ ] )
28
+ )
29
+ } )
30
+
31
+ test ( 'duplicate keys' , ( ) => {
32
+ const items = [
33
+ { id : 1 , name : 'foo' } ,
34
+ { id : 1 , name : 'bar' } ,
35
+ ]
36
+ assert . throws ( ( ) => keyBy ( items , ( item ) => item . id ) )
37
+ } )
You can’t perform that action at this time.
0 commit comments