@fluidframework/presence 2.32.0 → 2.33.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.
Files changed (153) hide show
  1. package/README.md +24 -24
  2. package/dist/alpha.d.ts +29 -25
  3. package/dist/baseTypes.d.ts +3 -3
  4. package/dist/baseTypes.js.map +1 -1
  5. package/dist/broadcastControls.d.ts +1 -1
  6. package/dist/broadcastControls.js.map +1 -1
  7. package/dist/datastorePresenceManagerFactory.d.ts +5 -5
  8. package/dist/datastorePresenceManagerFactory.d.ts.map +1 -1
  9. package/dist/datastorePresenceManagerFactory.js +6 -6
  10. package/dist/datastorePresenceManagerFactory.js.map +1 -1
  11. package/dist/experimentalAccess.d.ts +4 -4
  12. package/dist/experimentalAccess.d.ts.map +1 -1
  13. package/dist/experimentalAccess.js +6 -6
  14. package/dist/experimentalAccess.js.map +1 -1
  15. package/dist/exposedInternalTypes.d.ts +1 -1
  16. package/dist/exposedInternalTypes.js.map +1 -1
  17. package/dist/exposedUtilityTypes.d.ts +0 -8
  18. package/dist/exposedUtilityTypes.d.ts.map +1 -1
  19. package/dist/exposedUtilityTypes.js.map +1 -1
  20. package/dist/index.d.ts +8 -7
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +6 -8
  23. package/dist/index.js.map +1 -1
  24. package/dist/internalTypes.d.ts +3 -3
  25. package/dist/internalTypes.d.ts.map +1 -1
  26. package/dist/internalTypes.js.map +1 -1
  27. package/dist/internalUtils.d.ts +5 -0
  28. package/dist/internalUtils.d.ts.map +1 -1
  29. package/dist/internalUtils.js +8 -1
  30. package/dist/internalUtils.js.map +1 -1
  31. package/dist/latestMapValueManager.d.ts +57 -39
  32. package/dist/latestMapValueManager.d.ts.map +1 -1
  33. package/dist/latestMapValueManager.js +48 -39
  34. package/dist/latestMapValueManager.js.map +1 -1
  35. package/dist/latestValueManager.d.ts +38 -20
  36. package/dist/latestValueManager.d.ts.map +1 -1
  37. package/dist/latestValueManager.js +32 -28
  38. package/dist/latestValueManager.js.map +1 -1
  39. package/dist/latestValueTypes.d.ts +9 -10
  40. package/dist/latestValueTypes.d.ts.map +1 -1
  41. package/dist/latestValueTypes.js.map +1 -1
  42. package/dist/notificationsManager.d.ts +15 -10
  43. package/dist/notificationsManager.d.ts.map +1 -1
  44. package/dist/notificationsManager.js +8 -5
  45. package/dist/notificationsManager.js.map +1 -1
  46. package/dist/presence.d.ts +82 -66
  47. package/dist/presence.d.ts.map +1 -1
  48. package/dist/presence.js +5 -5
  49. package/dist/presence.js.map +1 -1
  50. package/dist/presenceDatastoreManager.d.ts +12 -10
  51. package/dist/presenceDatastoreManager.d.ts.map +1 -1
  52. package/dist/presenceDatastoreManager.js +10 -8
  53. package/dist/presenceDatastoreManager.js.map +1 -1
  54. package/dist/presenceManager.d.ts +2 -2
  55. package/dist/presenceManager.d.ts.map +1 -1
  56. package/dist/presenceManager.js +14 -22
  57. package/dist/presenceManager.js.map +1 -1
  58. package/dist/presenceStates.d.ts +14 -13
  59. package/dist/presenceStates.d.ts.map +1 -1
  60. package/dist/presenceStates.js +22 -15
  61. package/dist/presenceStates.js.map +1 -1
  62. package/dist/stateDatastore.d.ts +5 -4
  63. package/dist/stateDatastore.d.ts.map +1 -1
  64. package/dist/stateDatastore.js.map +1 -1
  65. package/dist/stateFactory.d.ts +22 -0
  66. package/dist/stateFactory.d.ts.map +1 -0
  67. package/dist/stateFactory.js +25 -0
  68. package/dist/stateFactory.js.map +1 -0
  69. package/dist/systemWorkspace.d.ts +7 -7
  70. package/dist/systemWorkspace.d.ts.map +1 -1
  71. package/dist/systemWorkspace.js +23 -23
  72. package/dist/systemWorkspace.js.map +1 -1
  73. package/dist/types.d.ts +50 -33
  74. package/dist/types.d.ts.map +1 -1
  75. package/dist/types.js +0 -1
  76. package/dist/types.js.map +1 -1
  77. package/lib/alpha.d.ts +29 -25
  78. package/lib/baseTypes.d.ts +3 -3
  79. package/lib/baseTypes.js.map +1 -1
  80. package/lib/broadcastControls.d.ts +1 -1
  81. package/lib/broadcastControls.js.map +1 -1
  82. package/lib/datastorePresenceManagerFactory.d.ts +5 -5
  83. package/lib/datastorePresenceManagerFactory.d.ts.map +1 -1
  84. package/lib/datastorePresenceManagerFactory.js +4 -4
  85. package/lib/datastorePresenceManagerFactory.js.map +1 -1
  86. package/lib/experimentalAccess.d.ts +4 -4
  87. package/lib/experimentalAccess.d.ts.map +1 -1
  88. package/lib/experimentalAccess.js +4 -4
  89. package/lib/experimentalAccess.js.map +1 -1
  90. package/lib/exposedInternalTypes.d.ts +1 -1
  91. package/lib/exposedInternalTypes.js.map +1 -1
  92. package/lib/exposedUtilityTypes.d.ts +0 -8
  93. package/lib/exposedUtilityTypes.d.ts.map +1 -1
  94. package/lib/exposedUtilityTypes.js.map +1 -1
  95. package/lib/index.d.ts +8 -7
  96. package/lib/index.d.ts.map +1 -1
  97. package/lib/index.js +4 -5
  98. package/lib/index.js.map +1 -1
  99. package/lib/internalTypes.d.ts +3 -3
  100. package/lib/internalTypes.d.ts.map +1 -1
  101. package/lib/internalTypes.js.map +1 -1
  102. package/lib/internalUtils.d.ts +5 -0
  103. package/lib/internalUtils.d.ts.map +1 -1
  104. package/lib/internalUtils.js +6 -0
  105. package/lib/internalUtils.js.map +1 -1
  106. package/lib/latestMapValueManager.d.ts +57 -39
  107. package/lib/latestMapValueManager.d.ts.map +1 -1
  108. package/lib/latestMapValueManager.js +47 -38
  109. package/lib/latestMapValueManager.js.map +1 -1
  110. package/lib/latestValueManager.d.ts +38 -20
  111. package/lib/latestValueManager.d.ts.map +1 -1
  112. package/lib/latestValueManager.js +31 -27
  113. package/lib/latestValueManager.js.map +1 -1
  114. package/lib/latestValueTypes.d.ts +9 -10
  115. package/lib/latestValueTypes.d.ts.map +1 -1
  116. package/lib/latestValueTypes.js.map +1 -1
  117. package/lib/notificationsManager.d.ts +15 -10
  118. package/lib/notificationsManager.d.ts.map +1 -1
  119. package/lib/notificationsManager.js +8 -5
  120. package/lib/notificationsManager.js.map +1 -1
  121. package/lib/presence.d.ts +82 -66
  122. package/lib/presence.d.ts.map +1 -1
  123. package/lib/presence.js +4 -4
  124. package/lib/presence.js.map +1 -1
  125. package/lib/presenceDatastoreManager.d.ts +12 -10
  126. package/lib/presenceDatastoreManager.d.ts.map +1 -1
  127. package/lib/presenceDatastoreManager.js +10 -8
  128. package/lib/presenceDatastoreManager.js.map +1 -1
  129. package/lib/presenceManager.d.ts +2 -2
  130. package/lib/presenceManager.d.ts.map +1 -1
  131. package/lib/presenceManager.js +14 -22
  132. package/lib/presenceManager.js.map +1 -1
  133. package/lib/presenceStates.d.ts +14 -13
  134. package/lib/presenceStates.d.ts.map +1 -1
  135. package/lib/presenceStates.js +22 -15
  136. package/lib/presenceStates.js.map +1 -1
  137. package/lib/stateDatastore.d.ts +5 -4
  138. package/lib/stateDatastore.d.ts.map +1 -1
  139. package/lib/stateDatastore.js.map +1 -1
  140. package/lib/stateFactory.d.ts +22 -0
  141. package/lib/stateFactory.d.ts.map +1 -0
  142. package/lib/stateFactory.js +22 -0
  143. package/lib/stateFactory.js.map +1 -0
  144. package/lib/systemWorkspace.d.ts +7 -7
  145. package/lib/systemWorkspace.d.ts.map +1 -1
  146. package/lib/systemWorkspace.js +24 -24
  147. package/lib/systemWorkspace.js.map +1 -1
  148. package/lib/tsdoc-metadata.json +1 -1
  149. package/lib/types.d.ts +50 -33
  150. package/lib/types.d.ts.map +1 -1
  151. package/lib/types.js +0 -1
  152. package/lib/types.js.map +1 -1
  153. package/package.json +19 -19
@@ -3,28 +3,27 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
  import type { Listenable } from "@fluidframework/core-interfaces";
6
- import type { JsonDeserialized, JsonSerializable } from "@fluidframework/core-interfaces/internal/exposedUtilityTypes";
6
+ import type { DeepReadonly, JsonDeserialized, JsonSerializable } from "@fluidframework/core-interfaces/internal/exposedUtilityTypes";
7
7
  import type { BroadcastControls, BroadcastControlSettings } from "./broadcastControls.js";
8
8
  import type { InternalTypes } from "./exposedInternalTypes.js";
9
- import type { InternalUtilityTypes } from "./exposedUtilityTypes.js";
10
- import type { LatestValueClientData, LatestValueData, LatestValueMetadata } from "./latestValueTypes.js";
11
- import type { ClientSessionId, ISessionClient } from "./presence.js";
9
+ import type { LatestClientData, LatestData, LatestMetadata } from "./latestValueTypes.js";
10
+ import type { AttendeeId, Attendee, Presence } from "./presence.js";
12
11
  /**
13
12
  * Collection of latest known values for a specific client.
14
13
  *
15
14
  * @sealed
16
15
  * @alpha
17
16
  */
18
- export interface LatestMapValueClientData<T, Keys extends string | number, SpecificSessionClientId extends ClientSessionId = ClientSessionId> {
17
+ export interface LatestMapClientData<T, Keys extends string | number, SpecificAttendeeId extends AttendeeId = AttendeeId> {
19
18
  /**
20
- * Associated client.
19
+ * Associated attendee.
21
20
  */
22
- client: ISessionClient<SpecificSessionClientId>;
21
+ attendee: Attendee<SpecificAttendeeId>;
23
22
  /**
24
23
  * @privateRemarks This could be regular map currently as no Map is
25
24
  * stored internally and a new instance is created for every request.
26
25
  */
27
- items: ReadonlyMap<Keys, LatestValueData<T>>;
26
+ items: ReadonlyMap<Keys, LatestData<T>>;
28
27
  }
29
28
  /**
30
29
  * State of a single item value, its key, and its metadata.
@@ -32,7 +31,7 @@ export interface LatestMapValueClientData<T, Keys extends string | number, Speci
32
31
  * @sealed
33
32
  * @alpha
34
33
  */
35
- export interface LatestMapItemValueClientData<T, K extends string | number> extends LatestValueClientData<T> {
34
+ export interface LatestMapItemUpdatedClientData<T, K extends string | number> extends LatestClientData<T> {
36
35
  key: K;
37
36
  }
38
37
  /**
@@ -42,15 +41,15 @@ export interface LatestMapItemValueClientData<T, K extends string | number> exte
42
41
  * @alpha
43
42
  */
44
43
  export interface LatestMapItemRemovedClientData<K extends string | number> {
45
- client: ISessionClient;
44
+ attendee: Attendee;
46
45
  key: K;
47
- metadata: LatestValueMetadata;
46
+ metadata: LatestMetadata;
48
47
  }
49
48
  /**
50
49
  * @sealed
51
50
  * @alpha
52
51
  */
53
- export interface LatestMapValueManagerEvents<T, K extends string | number> {
52
+ export interface LatestMapRawEvents<T, K extends string | number> {
54
53
  /**
55
54
  * Raised when any item's value for remote client is updated.
56
55
  * @param updates - Map of one or more values updated.
@@ -59,21 +58,21 @@ export interface LatestMapValueManagerEvents<T, K extends string | number> {
59
58
  *
60
59
  * @eventProperty
61
60
  */
62
- updated: (updates: LatestMapValueClientData<T, K>) => void;
61
+ remoteUpdated: (updates: LatestMapClientData<T, K>) => void;
63
62
  /**
64
63
  * Raised when specific item's value of remote client is updated.
65
64
  * @param updatedItem - Updated item value.
66
65
  *
67
66
  * @eventProperty
68
67
  */
69
- itemUpdated: (updatedItem: LatestMapItemValueClientData<T, K>) => void;
68
+ remoteItemUpdated: (updatedItem: LatestMapItemUpdatedClientData<T, K>) => void;
70
69
  /**
71
70
  * Raised when specific item of remote client is removed.
72
71
  * @param removedItem - Removed item.
73
72
  *
74
73
  * @eventProperty
75
74
  */
76
- itemRemoved: (removedItem: LatestMapItemRemovedClientData<K>) => void;
75
+ remoteItemRemoved: (removedItem: LatestMapItemRemovedClientData<K>) => void;
77
76
  /**
78
77
  * Raised when specific local item's value is updated.
79
78
  * @param updatedItem - Updated item value.
@@ -81,7 +80,7 @@ export interface LatestMapValueManagerEvents<T, K extends string | number> {
81
80
  * @eventProperty
82
81
  */
83
82
  localItemUpdated: (updatedItem: {
84
- value: InternalUtilityTypes.FullyReadonly<JsonSerializable<T> & JsonDeserialized<T>>;
83
+ value: DeepReadonly<JsonSerializable<T> & JsonDeserialized<T>>;
85
84
  key: K;
86
85
  }) => void;
87
86
  /**
@@ -100,14 +99,14 @@ export interface LatestMapValueManagerEvents<T, K extends string | number> {
100
99
  * @sealed
101
100
  * @alpha
102
101
  */
103
- export interface ValueMap<K extends string | number, V> {
102
+ export interface StateMap<K extends string | number, V> {
104
103
  /**
105
- * ${@link ValueMap.delete}s all elements in the ValueMap.
104
+ * ${@link StateMap.delete}s all elements in the StateMap.
106
105
  * @remarks This is not yet implemented.
107
106
  */
108
107
  clear(): void;
109
108
  /**
110
- * @returns true if an element in the ValueMap existed and has been removed, or false if
109
+ * @returns true if an element in the StateMap existed and has been removed, or false if
111
110
  * the element does not exist.
112
111
  * @remarks No entry is fully removed. Instead an undefined placeholder is locally and
113
112
  * transmitted to all other clients. For better performance limit the number of deleted
@@ -117,20 +116,20 @@ export interface ValueMap<K extends string | number, V> {
117
116
  */
118
117
  delete(key: K): boolean;
119
118
  /**
120
- * Executes a provided function once per each key/value pair in the ValueMap, in arbitrary order.
119
+ * Executes a provided function once per each key/value pair in the StateMap, in arbitrary order.
121
120
  */
122
- forEach(callbackfn: (value: InternalUtilityTypes.FullyReadonly<JsonDeserialized<V>>, key: K, map: ValueMap<K, V>) => void, thisArg?: unknown): void;
121
+ forEach(callbackfn: (value: DeepReadonly<JsonDeserialized<V>>, key: K, map: StateMap<K, V>) => void, thisArg?: unknown): void;
123
122
  /**
124
- * Returns a specified element from the ValueMap object.
123
+ * Returns a specified element from the StateMap object.
125
124
  * @returns Returns the element associated with the specified key. If no element is associated with the specified key, undefined is returned.
126
125
  */
127
- get(key: K): InternalUtilityTypes.FullyReadonly<JsonDeserialized<V>> | undefined;
126
+ get(key: K): DeepReadonly<JsonDeserialized<V>> | undefined;
128
127
  /**
129
128
  * @returns boolean indicating whether an element with the specified key exists or not.
130
129
  */
131
130
  has(key: K): boolean;
132
131
  /**
133
- * Adds a new element with a specified key and value to the ValueMap. If an element with the same key already exists, the element will be updated.
132
+ * Adds a new element with a specified key and value to the StateMap. If an element with the same key already exists, the element will be updated.
134
133
  * The value will be transmitted to all other connected clients.
135
134
  *
136
135
  * @remarks Manager assumes ownership of the value and its references.
@@ -139,7 +138,7 @@ export interface ValueMap<K extends string | number, V> {
139
138
  */
140
139
  set(key: K, value: JsonSerializable<V> & JsonDeserialized<V>): this;
141
140
  /**
142
- * @returns the number of elements in the ValueMap.
141
+ * @returns the number of elements in the StateMap.
143
142
  */
144
143
  readonly size: number;
145
144
  /**
@@ -154,21 +153,25 @@ export interface ValueMap<K extends string | number, V> {
154
153
  keys(): IterableIterator<K>;
155
154
  }
156
155
  /**
157
- * Value manager that provides a `Map` of latest known values from this client to
156
+ * State that provides a `Map` of latest known values from this client to
158
157
  * others and read access to their values.
159
158
  * Entries in the map may vary over time and by client, but all values are expected to
160
159
  * be of the same type, which may be a union type.
161
160
  *
162
- * @remarks Create using {@link LatestMap} registered to {@link PresenceStates}.
161
+ * @remarks Create using {@link StateFactory.latestMap} registered to {@link StatesWorkspace}.
163
162
  *
164
163
  * @sealed
165
164
  * @alpha
166
165
  */
167
- export interface LatestMapValueManager<T, Keys extends string | number = string | number> {
166
+ export interface LatestMapRaw<T, Keys extends string | number = string | number> {
168
167
  /**
169
- * Events for LatestMap value manager.
168
+ * Containing {@link Presence}
170
169
  */
171
- readonly events: Listenable<LatestMapValueManagerEvents<T, Keys>>;
170
+ readonly presence: Presence;
171
+ /**
172
+ * Events for LatestMapRaw.
173
+ */
174
+ readonly events: Listenable<LatestMapRawEvents<T, Keys>>;
172
175
  /**
173
176
  * Controls for management of sending updates.
174
177
  */
@@ -176,26 +179,41 @@ export interface LatestMapValueManager<T, Keys extends string | number = string
176
179
  /**
177
180
  * Current value map for this client.
178
181
  */
179
- readonly local: ValueMap<Keys, T>;
182
+ readonly local: StateMap<Keys, T>;
180
183
  /**
181
184
  * Iterable access to remote clients' map of values.
182
185
  */
183
- clientValues(): IterableIterator<LatestMapValueClientData<T, Keys>>;
186
+ getRemotes(): IterableIterator<LatestMapClientData<T, Keys>>;
184
187
  /**
185
- * Array of known remote clients.
188
+ * Array of {@link Attendee}s that have provided states.
186
189
  */
187
- clients(): ISessionClient[];
190
+ getStateAttendees(): Attendee[];
188
191
  /**
189
192
  * Access to a specific client's map of values.
190
193
  */
191
- clientValue(client: ISessionClient): ReadonlyMap<Keys, LatestValueData<T>>;
194
+ getRemote(attendee: Attendee): ReadonlyMap<Keys, LatestData<T>>;
195
+ }
196
+ /**
197
+ * Arguments that are passed to the {@link StateFactory.latestMap} function.
198
+ *
199
+ * @alpha
200
+ */
201
+ export interface LatestMapArguments<T, Keys extends string | number = string | number> {
202
+ /**
203
+ * The initial value of the local state.
204
+ */
205
+ local?: {
206
+ [K in Keys]: JsonSerializable<T> & JsonDeserialized<T>;
207
+ };
208
+ /**
209
+ * See {@link BroadcastControlSettings}.
210
+ */
211
+ settings?: BroadcastControlSettings | undefined;
192
212
  }
193
213
  /**
194
- * Factory for creating a {@link LatestMapValueManager}.
214
+ * Factory for creating a {@link LatestMapRaw} State object.
195
215
  *
196
216
  * @alpha
197
217
  */
198
- export declare function LatestMap<T extends object, Keys extends string | number = string | number, RegistrationKey extends string = string>(initialValues?: {
199
- [K in Keys]: JsonSerializable<T> & JsonDeserialized<T>;
200
- }, controls?: BroadcastControlSettings): InternalTypes.ManagerFactory<RegistrationKey, InternalTypes.MapValueState<T, Keys>, LatestMapValueManager<T, Keys>>;
218
+ export declare function latestMap<T, Keys extends string | number = string | number, RegistrationKey extends string = string>(args?: LatestMapArguments<T, Keys>): InternalTypes.ManagerFactory<RegistrationKey, InternalTypes.MapValueState<T, Keys>, LatestMapRaw<T, Keys>>;
201
219
  //# sourceMappingURL=latestMapValueManager.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"latestMapValueManager.d.ts","sourceRoot":"","sources":["../src/latestMapValueManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAElE,OAAO,KAAK,EACX,gBAAgB,EAChB,gBAAgB,EAChB,MAAM,8DAA8D,CAAC;AAEtE,OAAO,KAAK,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAE1F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAGrE,OAAO,KAAK,EACX,qBAAqB,EACrB,eAAe,EACf,mBAAmB,EACnB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAyB,MAAM,eAAe,CAAC;AAI5F;;;;;GAKG;AACH,MAAM,WAAW,wBAAwB,CACxC,CAAC,EACD,IAAI,SAAS,MAAM,GAAG,MAAM,EAC5B,uBAAuB,SAAS,eAAe,GAAG,eAAe;IAEjE;;OAEG;IACH,MAAM,EAAE,cAAc,CAAC,uBAAuB,CAAC,CAAC;IAEhD;;;OAGG;IACH,KAAK,EAAE,WAAW,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;CAC7C;AAED;;;;;GAKG;AACH,MAAM,WAAW,4BAA4B,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,GAAG,MAAM,CACzE,SAAQ,qBAAqB,CAAC,CAAC,CAAC;IAChC,GAAG,EAAE,CAAC,CAAC;CACP;AAED;;;;;GAKG;AACH,MAAM,WAAW,8BAA8B,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM;IACxE,MAAM,EAAE,cAAc,CAAC;IACvB,GAAG,EAAE,CAAC,CAAC;IACP,QAAQ,EAAE,mBAAmB,CAAC;CAC9B;AAED;;;GAGG;AACH,MAAM,WAAW,2BAA2B,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,GAAG,MAAM;IACxE;;;;;;;OAOG;IACH,OAAO,EAAE,CAAC,OAAO,EAAE,wBAAwB,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC;IAE3D;;;;;OAKG;IACH,WAAW,EAAE,CAAC,WAAW,EAAE,4BAA4B,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC;IAEvE;;;;;OAKG;IACH,WAAW,EAAE,CAAC,WAAW,EAAE,8BAA8B,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;IAEtE;;;;;OAKG;IACH,gBAAgB,EAAE,CAAC,WAAW,EAAE;QAC/B,KAAK,EAAE,oBAAoB,CAAC,aAAa,CAAC,gBAAgB,CAAC,CAAC,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC;QACrF,GAAG,EAAE,CAAC,CAAC;KACP,KAAK,IAAI,CAAC;IAEX;;;;;OAKG;IACH,gBAAgB,EAAE,CAAC,WAAW,EAAE;QAC/B,GAAG,EAAE,CAAC,CAAC;KACP,KAAK,IAAI,CAAC;CACX;AAED;;;;;GAKG;AACH,MAAM,WAAW,QAAQ,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,CAAC;IACrD;;;OAGG;IACH,KAAK,IAAI,IAAI,CAAC;IAEd;;;;;;;;OAQG;IACH,MAAM,CAAC,GAAG,EAAE,CAAC,GAAG,OAAO,CAAC;IAExB;;OAEG;IACH,OAAO,CACN,UAAU,EAAE,CACX,KAAK,EAAE,oBAAoB,CAAC,aAAa,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,EAC9D,GAAG,EAAE,CAAC,EACN,GAAG,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,KACf,IAAI,EACT,OAAO,CAAC,EAAE,OAAO,GACf,IAAI,CAAC;IAER;;;OAGG;IACH,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,oBAAoB,CAAC,aAAa,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;IAEjF;;OAEG;IACH,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,OAAO,CAAC;IAErB;;;;;;;OAOG;IACH,GAAG,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAEpE;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB;;OAEG;IAGH;;OAEG;IAGH;;OAEG;IACH,IAAI,IAAI,gBAAgB,CAAC,CAAC,CAAC,CAAC;CAM5B;AAiGD;;;;;;;;;;GAUG;AACH,MAAM,WAAW,qBAAqB,CAAC,CAAC,EAAE,IAAI,SAAS,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM;IACvF;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC,2BAA2B,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;IAElE;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,CAAC;IAErC;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IAClC;;OAEG;IACH,YAAY,IAAI,gBAAgB,CAAC,wBAAwB,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;IACpE;;OAEG;IACH,OAAO,IAAI,cAAc,EAAE,CAAC;IAC5B;;OAEG;IACH,WAAW,CAAC,MAAM,EAAE,cAAc,GAAG,WAAW,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;CAC3E;AA+ID;;;;GAIG;AACH,wBAAgB,SAAS,CACxB,CAAC,SAAS,MAAM,EAChB,IAAI,SAAS,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,EAC9C,eAAe,SAAS,MAAM,GAAG,MAAM,EAEvC,aAAa,CAAC,EAAE;KACd,CAAC,IAAI,IAAI,GAAG,gBAAgB,CAAC,CAAC,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC;CACtD,EACD,QAAQ,CAAC,EAAE,wBAAwB,GACjC,aAAa,CAAC,cAAc,CAC9B,eAAe,EACf,aAAa,CAAC,aAAa,CAAC,CAAC,EAAE,IAAI,CAAC,EACpC,qBAAqB,CAAC,CAAC,EAAE,IAAI,CAAC,CAC9B,CAsCA"}
1
+ {"version":3,"file":"latestMapValueManager.d.ts","sourceRoot":"","sources":["../src/latestMapValueManager.ts"],"names":[],"mappings":"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"}
@@ -4,7 +4,7 @@
4
4
  */
5
5
  import { createEmitter } from "@fluid-internal/client-utils";
6
6
  import { OptionalBroadcastControl } from "./broadcastControls.js";
7
- import { objectEntries, objectKeys } from "./internalUtils.js";
7
+ import { asDeeplyReadonly, objectEntries, objectKeys } from "./internalUtils.js";
8
8
  import { datastoreFromHandle } from "./stateDatastore.js";
9
9
  import { brandIVM } from "./valueManager.js";
10
10
  class ValueMapImpl {
@@ -51,12 +51,12 @@ class ValueMapImpl {
51
51
  forEach(callbackfn, thisArg) {
52
52
  for (const [key, item] of objectEntries(this.value.items)) {
53
53
  if (item.value !== undefined) {
54
- callbackfn(item.value, key, this);
54
+ callbackfn(asDeeplyReadonly(item.value), key, this);
55
55
  }
56
56
  }
57
57
  }
58
58
  get(key) {
59
- return this.value.items[key]?.value;
59
+ return asDeeplyReadonly(this.value.items[key]?.value);
60
60
  }
61
61
  has(key) {
62
62
  return this.value.items[key]?.value !== undefined;
@@ -67,7 +67,7 @@ class ValueMapImpl {
67
67
  this.value.items[key] = { rev: 0, timestamp: 0, value };
68
68
  }
69
69
  this.updateItem(key, value);
70
- this.emitter.emit("localItemUpdated", { key, value });
70
+ this.emitter.emit("localItemUpdated", { key, value: asDeeplyReadonly(value) });
71
71
  return this;
72
72
  }
73
73
  get size() {
@@ -83,7 +83,7 @@ class ValueMapImpl {
83
83
  return keys[Symbol.iterator]();
84
84
  }
85
85
  }
86
- class LatestMapValueManagerImpl {
86
+ class LatestMapRawValueManagerImpl {
87
87
  constructor(key, datastore, value, controlSettings) {
88
88
  this.key = key;
89
89
  this.datastore = datastore;
@@ -96,46 +96,49 @@ class LatestMapValueManagerImpl {
96
96
  });
97
97
  });
98
98
  }
99
- *clientValues() {
99
+ get presence() {
100
+ return this.datastore.presence;
101
+ }
102
+ *getRemotes() {
100
103
  const allKnownStates = this.datastore.knownValues(this.key);
101
- for (const clientSessionId of objectKeys(allKnownStates.states)) {
102
- if (clientSessionId !== allKnownStates.self) {
103
- const client = this.datastore.lookupClient(clientSessionId);
104
- const items = this.clientValue(client);
105
- yield { client, items };
104
+ for (const attendeeId of objectKeys(allKnownStates.states)) {
105
+ if (attendeeId !== allKnownStates.self) {
106
+ const attendee = this.datastore.lookupClient(attendeeId);
107
+ const items = this.getRemote(attendee);
108
+ yield { attendee, items };
106
109
  }
107
110
  }
108
111
  }
109
- clients() {
112
+ getStateAttendees() {
110
113
  const allKnownStates = this.datastore.knownValues(this.key);
111
114
  return objectKeys(allKnownStates.states)
112
- .filter((clientSessionId) => clientSessionId !== allKnownStates.self)
113
- .map((clientSessionId) => this.datastore.lookupClient(clientSessionId));
115
+ .filter((attendeeId) => attendeeId !== allKnownStates.self)
116
+ .map((attendeeId) => this.datastore.lookupClient(attendeeId));
114
117
  }
115
- clientValue(client) {
118
+ getRemote(attendee) {
116
119
  const allKnownStates = this.datastore.knownValues(this.key);
117
- const clientSessionId = client.sessionId;
118
- const clientStateMap = allKnownStates.states[clientSessionId];
120
+ const attendeeId = attendee.attendeeId;
121
+ const clientStateMap = allKnownStates.states[attendeeId];
119
122
  if (clientStateMap === undefined) {
120
- throw new Error("No entry for client");
123
+ throw new Error("No entry for attendee");
121
124
  }
122
125
  const items = new Map();
123
126
  for (const [key, item] of objectEntries(clientStateMap.items)) {
124
127
  const value = item.value;
125
128
  if (value !== undefined) {
126
129
  items.set(key, {
127
- value,
130
+ value: asDeeplyReadonly(value),
128
131
  metadata: { revision: item.rev, timestamp: item.timestamp },
129
132
  });
130
133
  }
131
134
  }
132
135
  return items;
133
136
  }
134
- update(client, _received, value) {
137
+ update(attendee, _received, value) {
135
138
  const allKnownStates = this.datastore.knownValues(this.key);
136
- const clientSessionId = client.sessionId;
137
- const currentState = (allKnownStates.states[clientSessionId] ??=
138
- // New client - prepare new client state directory
139
+ const attendeeId = attendee.attendeeId;
140
+ const currentState = (allKnownStates.states[attendeeId] ??=
141
+ // New attendee - prepare new attendee state directory
139
142
  {
140
143
  rev: value.rev,
141
144
  items: {},
@@ -157,7 +160,7 @@ class LatestMapValueManagerImpl {
157
160
  currentState.rev = value.rev;
158
161
  }
159
162
  const allUpdates = {
160
- client,
163
+ attendee,
161
164
  items: new Map(),
162
165
  };
163
166
  const postUpdateActions = [];
@@ -168,47 +171,53 @@ class LatestMapValueManagerImpl {
168
171
  currentState.items[key] = item;
169
172
  const metadata = { revision: item.rev, timestamp: item.timestamp };
170
173
  if (item.value !== undefined) {
171
- const itemValue = item.value;
174
+ const itemValue = asDeeplyReadonly(item.value);
172
175
  const updatedItem = {
173
- client,
176
+ attendee,
174
177
  key,
175
178
  value: itemValue,
176
179
  metadata,
177
180
  };
178
- postUpdateActions.push(() => this.events.emit("itemUpdated", updatedItem));
181
+ postUpdateActions.push(() => this.events.emit("remoteItemUpdated", updatedItem));
179
182
  allUpdates.items.set(key, { value: itemValue, metadata });
180
183
  }
181
184
  else if (hadPriorValue !== undefined) {
182
- postUpdateActions.push(() => this.events.emit("itemRemoved", {
183
- client,
185
+ postUpdateActions.push(() => this.events.emit("remoteItemRemoved", {
186
+ attendee,
184
187
  key,
185
188
  metadata,
186
189
  }));
187
190
  }
188
191
  }
189
- this.datastore.update(this.key, clientSessionId, currentState);
190
- postUpdateActions.push(() => this.events.emit("updated", allUpdates));
192
+ this.datastore.update(this.key, attendeeId, currentState);
193
+ postUpdateActions.push(() => this.events.emit("remoteUpdated", allUpdates));
191
194
  return postUpdateActions;
192
195
  }
193
196
  }
194
197
  /**
195
- * Factory for creating a {@link LatestMapValueManager}.
198
+ * Factory for creating a {@link LatestMapRaw} State object.
196
199
  *
197
200
  * @alpha
198
201
  */
199
- export function LatestMap(initialValues, controls) {
202
+ export function latestMap(args) {
203
+ const settings = args?.settings;
204
+ const initialValues = args?.local;
200
205
  const timestamp = Date.now();
201
206
  const value = { rev: 0, items: {} };
202
- // LatestMapValueManager takes ownership of values within initialValues.
207
+ // LatestMapRaw takes ownership of values within initialValues.
203
208
  if (initialValues !== undefined) {
204
209
  for (const key of objectKeys(initialValues)) {
205
- value.items[key] = { rev: 0, timestamp, value: initialValues[key] };
210
+ value.items[key] = {
211
+ rev: 0,
212
+ timestamp,
213
+ value: initialValues[key],
214
+ };
206
215
  }
207
216
  }
208
217
  const factory = (key, datastoreHandle) => ({
209
- initialData: { value, allowableUpdateLatencyMs: controls?.allowableUpdateLatencyMs },
210
- manager: brandIVM(new LatestMapValueManagerImpl(key, datastoreFromHandle(datastoreHandle), value, controls)),
218
+ initialData: { value, allowableUpdateLatencyMs: settings?.allowableUpdateLatencyMs },
219
+ manager: brandIVM(new LatestMapRawValueManagerImpl(key, datastoreFromHandle(datastoreHandle), value, settings)),
211
220
  });
212
- return Object.assign(factory, { instanceBase: LatestMapValueManagerImpl });
221
+ return Object.assign(factory, { instanceBase: LatestMapRawValueManagerImpl });
213
222
  }
214
223
  //# sourceMappingURL=latestMapValueManager.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"latestMapValueManager.js","sourceRoot":"","sources":["../src/latestMapValueManager.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { createEmitter } from \"@fluid-internal/client-utils\";\nimport type { Listenable } from \"@fluidframework/core-interfaces\";\nimport type { IEmitter } from \"@fluidframework/core-interfaces/internal\";\nimport type {\n\tJsonDeserialized,\n\tJsonSerializable,\n} from \"@fluidframework/core-interfaces/internal/exposedUtilityTypes\";\n\nimport type { BroadcastControls, BroadcastControlSettings } from \"./broadcastControls.js\";\nimport { OptionalBroadcastControl } from \"./broadcastControls.js\";\nimport type { InternalTypes } from \"./exposedInternalTypes.js\";\nimport type { InternalUtilityTypes } from \"./exposedUtilityTypes.js\";\nimport type { PostUpdateAction, ValueManager } from \"./internalTypes.js\";\nimport { objectEntries, objectKeys } from \"./internalUtils.js\";\nimport type {\n\tLatestValueClientData,\n\tLatestValueData,\n\tLatestValueMetadata,\n} from \"./latestValueTypes.js\";\nimport type { ClientSessionId, ISessionClient, SpecificSessionClient } from \"./presence.js\";\nimport { datastoreFromHandle, type StateDatastore } from \"./stateDatastore.js\";\nimport { brandIVM } from \"./valueManager.js\";\n\n/**\n * Collection of latest known values for a specific client.\n *\n * @sealed\n * @alpha\n */\nexport interface LatestMapValueClientData<\n\tT,\n\tKeys extends string | number,\n\tSpecificSessionClientId extends ClientSessionId = ClientSessionId,\n> {\n\t/**\n\t * Associated client.\n\t */\n\tclient: ISessionClient<SpecificSessionClientId>;\n\n\t/**\n\t * @privateRemarks This could be regular map currently as no Map is\n\t * stored internally and a new instance is created for every request.\n\t */\n\titems: ReadonlyMap<Keys, LatestValueData<T>>;\n}\n\n/**\n * State of a single item value, its key, and its metadata.\n *\n * @sealed\n * @alpha\n */\nexport interface LatestMapItemValueClientData<T, K extends string | number>\n\textends LatestValueClientData<T> {\n\tkey: K;\n}\n\n/**\n * Identifier and metadata for a removed item.\n *\n * @sealed\n * @alpha\n */\nexport interface LatestMapItemRemovedClientData<K extends string | number> {\n\tclient: ISessionClient;\n\tkey: K;\n\tmetadata: LatestValueMetadata;\n}\n\n/**\n * @sealed\n * @alpha\n */\nexport interface LatestMapValueManagerEvents<T, K extends string | number> {\n\t/**\n\t * Raised when any item's value for remote client is updated.\n\t * @param updates - Map of one or more values updated.\n\t *\n\t * @remarks The event does not include item removals.\n\t *\n\t * @eventProperty\n\t */\n\tupdated: (updates: LatestMapValueClientData<T, K>) => void;\n\n\t/**\n\t * Raised when specific item's value of remote client is updated.\n\t * @param updatedItem - Updated item value.\n\t *\n\t * @eventProperty\n\t */\n\titemUpdated: (updatedItem: LatestMapItemValueClientData<T, K>) => void;\n\n\t/**\n\t * Raised when specific item of remote client is removed.\n\t * @param removedItem - Removed item.\n\t *\n\t * @eventProperty\n\t */\n\titemRemoved: (removedItem: LatestMapItemRemovedClientData<K>) => void;\n\n\t/**\n\t * Raised when specific local item's value is updated.\n\t * @param updatedItem - Updated item value.\n\t *\n\t * @eventProperty\n\t */\n\tlocalItemUpdated: (updatedItem: {\n\t\tvalue: InternalUtilityTypes.FullyReadonly<JsonSerializable<T> & JsonDeserialized<T>>;\n\t\tkey: K;\n\t}) => void;\n\n\t/**\n\t * Raised when specific local item is removed.\n\t * @param removedItem - Removed item.\n\t *\n\t * @eventProperty\n\t */\n\tlocalItemRemoved: (removedItem: {\n\t\tkey: K;\n\t}) => void;\n}\n\n/**\n * Map of local client's values. Modifications are transmitted to all other connected clients.\n *\n * @sealed\n * @alpha\n */\nexport interface ValueMap<K extends string | number, V> {\n\t/**\n\t * ${@link ValueMap.delete}s all elements in the ValueMap.\n\t * @remarks This is not yet implemented.\n\t */\n\tclear(): void;\n\n\t/**\n\t * @returns true if an element in the ValueMap existed and has been removed, or false if\n\t * the element does not exist.\n\t * @remarks No entry is fully removed. Instead an undefined placeholder is locally and\n\t * transmitted to all other clients. For better performance limit the number of deleted\n\t * entries and reuse keys when possible.\n\t * @privateRemarks In the future we may add a mechanism to remove the placeholder, at least\n\t * from transmissions after sufficient time has passed.\n\t */\n\tdelete(key: K): boolean;\n\n\t/**\n\t * Executes a provided function once per each key/value pair in the ValueMap, in arbitrary order.\n\t */\n\tforEach(\n\t\tcallbackfn: (\n\t\t\tvalue: InternalUtilityTypes.FullyReadonly<JsonDeserialized<V>>,\n\t\t\tkey: K,\n\t\t\tmap: ValueMap<K, V>,\n\t\t) => void,\n\t\tthisArg?: unknown,\n\t): void;\n\n\t/**\n\t * Returns a specified element from the ValueMap object.\n\t * @returns Returns the element associated with the specified key. If no element is associated with the specified key, undefined is returned.\n\t */\n\tget(key: K): InternalUtilityTypes.FullyReadonly<JsonDeserialized<V>> | undefined;\n\n\t/**\n\t * @returns boolean indicating whether an element with the specified key exists or not.\n\t */\n\thas(key: K): boolean;\n\n\t/**\n\t * Adds a new element with a specified key and value to the ValueMap. If an element with the same key already exists, the element will be updated.\n\t * The value will be transmitted to all other connected clients.\n\t *\n\t * @remarks Manager assumes ownership of the value and its references.\n\t * Make a deep clone before setting, if needed. No comparison is done to detect changes; all\n\t * sets are transmitted.\n\t */\n\tset(key: K, value: JsonSerializable<V> & JsonDeserialized<V>): this;\n\n\t/**\n\t * @returns the number of elements in the ValueMap.\n\t */\n\treadonly size: number;\n\n\t/**\n\t * Returns an iterable of entries in the map.\n\t */\n\t// [Symbol.iterator](): IterableIterator<[K, InternalUtilityTypes.FullyReadonly<JsonDeserialized<V>>]>;\n\n\t/**\n\t * Returns an iterable of key, value pairs for every entry in the map.\n\t */\n\t// entries(): IterableIterator<[K, InternalUtilityTypes.FullyReadonly<JsonDeserialized<V>>]>;\n\n\t/**\n\t * Returns an iterable of keys in the map.\n\t */\n\tkeys(): IterableIterator<K>;\n\n\t/**\n\t * Returns an iterable of values in the map.\n\t */\n\t// values(): IterableIterator<InternalUtilityTypes.FullyReadonly<JsonDeserialized<V>>>;\n}\n\nclass ValueMapImpl<T, K extends string | number> implements ValueMap<K, T> {\n\tprivate countDefined: number;\n\tpublic constructor(\n\t\tprivate readonly value: InternalTypes.MapValueState<T, K>,\n\t\tprivate readonly emitter: IEmitter<\n\t\t\tPick<LatestMapValueManagerEvents<T, K>, \"localItemUpdated\" | \"localItemRemoved\">\n\t\t>,\n\t\tprivate readonly localUpdate: (\n\t\t\tupdates: InternalTypes.MapValueState<\n\t\t\t\tT,\n\t\t\t\t// This should be `K`, but will only work if properties are optional.\n\t\t\t\tstring | number\n\t\t\t>,\n\t\t) => void,\n\t) {\n\t\t// All initial items are expected to be defined.\n\t\t// TODO assert all defined and/or update type.\n\t\tthis.countDefined = Object.keys(value.items).length;\n\t}\n\n\t/**\n\t * Note: caller must ensure key exists in this.value.items.\n\t */\n\tprivate updateItem(key: K, value: InternalTypes.ValueOptionalState<T>[\"value\"]): void {\n\t\tthis.value.rev += 1;\n\t\t// Caller is required to ensure key exists.\n\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\tconst item = this.value.items[key]!;\n\t\titem.rev += 1;\n\t\titem.timestamp = Date.now();\n\t\tif (value === undefined) {\n\t\t\tdelete item.value;\n\t\t} else {\n\t\t\titem.value = value;\n\t\t}\n\t\tconst update = { rev: this.value.rev, items: { [key]: item } };\n\t\tthis.localUpdate(update);\n\t}\n\n\tpublic clear(): void {\n\t\tthrow new Error(\"Method not implemented.\");\n\t}\n\tpublic delete(key: K): boolean {\n\t\tconst { items } = this.value;\n\t\tconst hasKey = items[key]?.value !== undefined;\n\t\tif (hasKey) {\n\t\t\tthis.countDefined -= 1;\n\t\t\tthis.updateItem(key, undefined);\n\t\t\tthis.emitter.emit(\"localItemRemoved\", { key });\n\t\t}\n\t\treturn hasKey;\n\t}\n\tpublic forEach(\n\t\tcallbackfn: (\n\t\t\tvalue: InternalUtilityTypes.FullyReadonly<JsonDeserialized<T>>,\n\t\t\tkey: K,\n\t\t\tmap: ValueMap<K, T>,\n\t\t) => void,\n\t\tthisArg?: unknown,\n\t): void {\n\t\tfor (const [key, item] of objectEntries(this.value.items)) {\n\t\t\tif (item.value !== undefined) {\n\t\t\t\tcallbackfn(item.value, key, this);\n\t\t\t}\n\t\t}\n\t}\n\tpublic get(key: K): InternalUtilityTypes.FullyReadonly<JsonDeserialized<T>> | undefined {\n\t\treturn this.value.items[key]?.value;\n\t}\n\tpublic has(key: K): boolean {\n\t\treturn this.value.items[key]?.value !== undefined;\n\t}\n\tpublic set(key: K, value: JsonSerializable<T> & JsonDeserialized<T>): this {\n\t\tif (!(key in this.value.items)) {\n\t\t\tthis.countDefined += 1;\n\t\t\tthis.value.items[key] = { rev: 0, timestamp: 0, value };\n\t\t}\n\t\tthis.updateItem(key, value);\n\t\tthis.emitter.emit(\"localItemUpdated\", { key, value });\n\t\treturn this;\n\t}\n\tpublic get size(): number {\n\t\treturn this.countDefined;\n\t}\n\tpublic keys(): IterableIterator<K> {\n\t\tconst keys: K[] = [];\n\t\tfor (const [key, item] of objectEntries(this.value.items)) {\n\t\t\tif (item.value !== undefined) {\n\t\t\t\tkeys.push(key);\n\t\t\t}\n\t\t}\n\t\treturn keys[Symbol.iterator]();\n\t}\n}\n\n/**\n * Value manager that provides a `Map` of latest known values from this client to\n * others and read access to their values.\n * Entries in the map may vary over time and by client, but all values are expected to\n * be of the same type, which may be a union type.\n *\n * @remarks Create using {@link LatestMap} registered to {@link PresenceStates}.\n *\n * @sealed\n * @alpha\n */\nexport interface LatestMapValueManager<T, Keys extends string | number = string | number> {\n\t/**\n\t * Events for LatestMap value manager.\n\t */\n\treadonly events: Listenable<LatestMapValueManagerEvents<T, Keys>>;\n\n\t/**\n\t * Controls for management of sending updates.\n\t */\n\treadonly controls: BroadcastControls;\n\n\t/**\n\t * Current value map for this client.\n\t */\n\treadonly local: ValueMap<Keys, T>;\n\t/**\n\t * Iterable access to remote clients' map of values.\n\t */\n\tclientValues(): IterableIterator<LatestMapValueClientData<T, Keys>>;\n\t/**\n\t * Array of known remote clients.\n\t */\n\tclients(): ISessionClient[];\n\t/**\n\t * Access to a specific client's map of values.\n\t */\n\tclientValue(client: ISessionClient): ReadonlyMap<Keys, LatestValueData<T>>;\n}\n\nclass LatestMapValueManagerImpl<\n\tT,\n\tRegistrationKey extends string,\n\tKeys extends string | number = string | number,\n> implements\n\t\tLatestMapValueManager<T, Keys>,\n\t\tRequired<ValueManager<T, InternalTypes.MapValueState<T, Keys>>>\n{\n\tpublic readonly events = createEmitter<LatestMapValueManagerEvents<T, Keys>>();\n\tpublic readonly controls: OptionalBroadcastControl;\n\n\tpublic constructor(\n\t\tprivate readonly key: RegistrationKey,\n\t\tprivate readonly datastore: StateDatastore<\n\t\t\tRegistrationKey,\n\t\t\tInternalTypes.MapValueState<T, Keys>\n\t\t>,\n\t\tpublic readonly value: InternalTypes.MapValueState<T, Keys>,\n\t\tcontrolSettings: BroadcastControlSettings | undefined,\n\t) {\n\t\tthis.controls = new OptionalBroadcastControl(controlSettings);\n\n\t\tthis.local = new ValueMapImpl<T, Keys>(\n\t\t\tvalue,\n\t\t\tthis.events,\n\t\t\t(updates: InternalTypes.MapValueState<T, Keys>) => {\n\t\t\t\tdatastore.localUpdate(key, updates, {\n\t\t\t\t\tallowableUpdateLatencyMs: this.controls.allowableUpdateLatencyMs,\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\t}\n\n\tpublic readonly local: ValueMap<Keys, T>;\n\n\tpublic *clientValues(): IterableIterator<LatestMapValueClientData<T, Keys>> {\n\t\tconst allKnownStates = this.datastore.knownValues(this.key);\n\t\tfor (const clientSessionId of objectKeys(allKnownStates.states)) {\n\t\t\tif (clientSessionId !== allKnownStates.self) {\n\t\t\t\tconst client = this.datastore.lookupClient(clientSessionId);\n\t\t\t\tconst items = this.clientValue(client);\n\t\t\t\tyield { client, items };\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic clients(): ISessionClient[] {\n\t\tconst allKnownStates = this.datastore.knownValues(this.key);\n\t\treturn objectKeys(allKnownStates.states)\n\t\t\t.filter((clientSessionId) => clientSessionId !== allKnownStates.self)\n\t\t\t.map((clientSessionId) => this.datastore.lookupClient(clientSessionId));\n\t}\n\n\tpublic clientValue(client: ISessionClient): ReadonlyMap<Keys, LatestValueData<T>> {\n\t\tconst allKnownStates = this.datastore.knownValues(this.key);\n\t\tconst clientSessionId = client.sessionId;\n\t\tconst clientStateMap = allKnownStates.states[clientSessionId];\n\t\tif (clientStateMap === undefined) {\n\t\t\tthrow new Error(\"No entry for client\");\n\t\t}\n\t\tconst items = new Map<Keys, LatestValueData<T>>();\n\t\tfor (const [key, item] of objectEntries(clientStateMap.items)) {\n\t\t\tconst value = item.value;\n\t\t\tif (value !== undefined) {\n\t\t\t\titems.set(key, {\n\t\t\t\t\tvalue,\n\t\t\t\t\tmetadata: { revision: item.rev, timestamp: item.timestamp },\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn items;\n\t}\n\n\tpublic update<SpecificSessionClientId extends ClientSessionId>(\n\t\tclient: SpecificSessionClient<SpecificSessionClientId>,\n\t\t_received: number,\n\t\tvalue: InternalTypes.MapValueState<T, string | number>,\n\t): PostUpdateAction[] {\n\t\tconst allKnownStates = this.datastore.knownValues(this.key);\n\t\tconst clientSessionId: SpecificSessionClientId = client.sessionId;\n\t\tconst currentState = (allKnownStates.states[clientSessionId] ??=\n\t\t\t// New client - prepare new client state directory\n\t\t\t{\n\t\t\t\trev: value.rev,\n\t\t\t\titems: {} as unknown as InternalTypes.MapValueState<T, Keys>[\"items\"],\n\t\t\t});\n\t\t// Accumulate individual update keys\n\t\tconst updatedItemKeys: Keys[] = [];\n\t\tfor (const [key, item] of objectEntries(value.items)) {\n\t\t\t// TODO: Key validation needs to be added here.\n\t\t\tconst validKey = key as Keys;\n\t\t\tif (!(key in currentState.items) || currentState.items[validKey].rev < item.rev) {\n\t\t\t\tupdatedItemKeys.push(validKey);\n\t\t\t}\n\t\t}\n\n\t\tif (updatedItemKeys.length === 0) {\n\t\t\treturn [];\n\t\t}\n\n\t\t// Store updates\n\t\tif (value.rev > currentState.rev) {\n\t\t\tcurrentState.rev = value.rev;\n\t\t}\n\t\tconst allUpdates = {\n\t\t\tclient,\n\t\t\titems: new Map<Keys, LatestValueData<T>>(),\n\t\t};\n\t\tconst postUpdateActions: PostUpdateAction[] = [];\n\t\tfor (const key of updatedItemKeys) {\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\tconst item = value.items[key]!;\n\t\t\tconst hadPriorValue = currentState.items[key]?.value;\n\t\t\tcurrentState.items[key] = item;\n\t\t\tconst metadata = { revision: item.rev, timestamp: item.timestamp };\n\t\t\tif (item.value !== undefined) {\n\t\t\t\tconst itemValue = item.value;\n\t\t\t\tconst updatedItem = {\n\t\t\t\t\tclient,\n\t\t\t\t\tkey,\n\t\t\t\t\tvalue: itemValue,\n\t\t\t\t\tmetadata,\n\t\t\t\t};\n\t\t\t\tpostUpdateActions.push(() => this.events.emit(\"itemUpdated\", updatedItem));\n\t\t\t\tallUpdates.items.set(key, { value: itemValue, metadata });\n\t\t\t} else if (hadPriorValue !== undefined) {\n\t\t\t\tpostUpdateActions.push(() =>\n\t\t\t\t\tthis.events.emit(\"itemRemoved\", {\n\t\t\t\t\t\tclient,\n\t\t\t\t\t\tkey,\n\t\t\t\t\t\tmetadata,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tthis.datastore.update(this.key, clientSessionId, currentState);\n\t\tpostUpdateActions.push(() => this.events.emit(\"updated\", allUpdates));\n\t\treturn postUpdateActions;\n\t}\n}\n\n/**\n * Factory for creating a {@link LatestMapValueManager}.\n *\n * @alpha\n */\nexport function LatestMap<\n\tT extends object,\n\tKeys extends string | number = string | number,\n\tRegistrationKey extends string = string,\n>(\n\tinitialValues?: {\n\t\t[K in Keys]: JsonSerializable<T> & JsonDeserialized<T>;\n\t},\n\tcontrols?: BroadcastControlSettings,\n): InternalTypes.ManagerFactory<\n\tRegistrationKey,\n\tInternalTypes.MapValueState<T, Keys>,\n\tLatestMapValueManager<T, Keys>\n> {\n\tconst timestamp = Date.now();\n\tconst value: InternalTypes.MapValueState<\n\t\tT,\n\t\t// This should be `Keys`, but will only work if properties are optional.\n\t\tstring | number\n\t> = { rev: 0, items: {} };\n\t// LatestMapValueManager takes ownership of values within initialValues.\n\tif (initialValues !== undefined) {\n\t\tfor (const key of objectKeys(initialValues)) {\n\t\t\tvalue.items[key] = { rev: 0, timestamp, value: initialValues[key] };\n\t\t}\n\t}\n\tconst factory = (\n\t\tkey: RegistrationKey,\n\t\tdatastoreHandle: InternalTypes.StateDatastoreHandle<\n\t\t\tRegistrationKey,\n\t\t\tInternalTypes.MapValueState<T, Keys>\n\t\t>,\n\t): {\n\t\tinitialData: { value: typeof value; allowableUpdateLatencyMs: number | undefined };\n\t\tmanager: InternalTypes.StateValue<LatestMapValueManager<T, Keys>>;\n\t} => ({\n\t\tinitialData: { value, allowableUpdateLatencyMs: controls?.allowableUpdateLatencyMs },\n\t\tmanager: brandIVM<\n\t\t\tLatestMapValueManagerImpl<T, RegistrationKey, Keys>,\n\t\t\tT,\n\t\t\tInternalTypes.MapValueState<T, Keys>\n\t\t>(\n\t\t\tnew LatestMapValueManagerImpl(\n\t\t\t\tkey,\n\t\t\t\tdatastoreFromHandle(datastoreHandle),\n\t\t\t\tvalue,\n\t\t\t\tcontrols,\n\t\t\t),\n\t\t),\n\t});\n\treturn Object.assign(factory, { instanceBase: LatestMapValueManagerImpl });\n}\n"]}
1
+ {"version":3,"file":"latestMapValueManager.js","sourceRoot":"","sources":["../src/latestMapValueManager.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { createEmitter } from \"@fluid-internal/client-utils\";\nimport type { Listenable } from \"@fluidframework/core-interfaces\";\nimport type { IEmitter } from \"@fluidframework/core-interfaces/internal\";\nimport type {\n\tDeepReadonly,\n\tJsonDeserialized,\n\tJsonSerializable,\n} from \"@fluidframework/core-interfaces/internal/exposedUtilityTypes\";\n\nimport type { BroadcastControls, BroadcastControlSettings } from \"./broadcastControls.js\";\nimport { OptionalBroadcastControl } from \"./broadcastControls.js\";\nimport type { InternalTypes } from \"./exposedInternalTypes.js\";\nimport type { PostUpdateAction, ValueManager } from \"./internalTypes.js\";\nimport { asDeeplyReadonly, objectEntries, objectKeys } from \"./internalUtils.js\";\nimport type { LatestClientData, LatestData, LatestMetadata } from \"./latestValueTypes.js\";\nimport type { AttendeeId, Attendee, Presence, SpecificAttendee } from \"./presence.js\";\nimport { datastoreFromHandle, type StateDatastore } from \"./stateDatastore.js\";\nimport { brandIVM } from \"./valueManager.js\";\n\n/**\n * Collection of latest known values for a specific client.\n *\n * @sealed\n * @alpha\n */\nexport interface LatestMapClientData<\n\tT,\n\tKeys extends string | number,\n\tSpecificAttendeeId extends AttendeeId = AttendeeId,\n> {\n\t/**\n\t * Associated attendee.\n\t */\n\tattendee: Attendee<SpecificAttendeeId>;\n\n\t/**\n\t * @privateRemarks This could be regular map currently as no Map is\n\t * stored internally and a new instance is created for every request.\n\t */\n\titems: ReadonlyMap<Keys, LatestData<T>>;\n}\n\n/**\n * State of a single item value, its key, and its metadata.\n *\n * @sealed\n * @alpha\n */\nexport interface LatestMapItemUpdatedClientData<T, K extends string | number>\n\textends LatestClientData<T> {\n\tkey: K;\n}\n\n/**\n * Identifier and metadata for a removed item.\n *\n * @sealed\n * @alpha\n */\nexport interface LatestMapItemRemovedClientData<K extends string | number> {\n\tattendee: Attendee;\n\tkey: K;\n\tmetadata: LatestMetadata;\n}\n\n/**\n * @sealed\n * @alpha\n */\nexport interface LatestMapRawEvents<T, K extends string | number> {\n\t/**\n\t * Raised when any item's value for remote client is updated.\n\t * @param updates - Map of one or more values updated.\n\t *\n\t * @remarks The event does not include item removals.\n\t *\n\t * @eventProperty\n\t */\n\tremoteUpdated: (updates: LatestMapClientData<T, K>) => void;\n\n\t/**\n\t * Raised when specific item's value of remote client is updated.\n\t * @param updatedItem - Updated item value.\n\t *\n\t * @eventProperty\n\t */\n\tremoteItemUpdated: (updatedItem: LatestMapItemUpdatedClientData<T, K>) => void;\n\n\t/**\n\t * Raised when specific item of remote client is removed.\n\t * @param removedItem - Removed item.\n\t *\n\t * @eventProperty\n\t */\n\tremoteItemRemoved: (removedItem: LatestMapItemRemovedClientData<K>) => void;\n\n\t/**\n\t * Raised when specific local item's value is updated.\n\t * @param updatedItem - Updated item value.\n\t *\n\t * @eventProperty\n\t */\n\tlocalItemUpdated: (updatedItem: {\n\t\tvalue: DeepReadonly<JsonSerializable<T> & JsonDeserialized<T>>;\n\t\tkey: K;\n\t}) => void;\n\n\t/**\n\t * Raised when specific local item is removed.\n\t * @param removedItem - Removed item.\n\t *\n\t * @eventProperty\n\t */\n\tlocalItemRemoved: (removedItem: {\n\t\tkey: K;\n\t}) => void;\n}\n\n/**\n * Map of local client's values. Modifications are transmitted to all other connected clients.\n *\n * @sealed\n * @alpha\n */\nexport interface StateMap<K extends string | number, V> {\n\t/**\n\t * ${@link StateMap.delete}s all elements in the StateMap.\n\t * @remarks This is not yet implemented.\n\t */\n\tclear(): void;\n\n\t/**\n\t * @returns true if an element in the StateMap existed and has been removed, or false if\n\t * the element does not exist.\n\t * @remarks No entry is fully removed. Instead an undefined placeholder is locally and\n\t * transmitted to all other clients. For better performance limit the number of deleted\n\t * entries and reuse keys when possible.\n\t * @privateRemarks In the future we may add a mechanism to remove the placeholder, at least\n\t * from transmissions after sufficient time has passed.\n\t */\n\tdelete(key: K): boolean;\n\n\t/**\n\t * Executes a provided function once per each key/value pair in the StateMap, in arbitrary order.\n\t */\n\tforEach(\n\t\tcallbackfn: (\n\t\t\tvalue: DeepReadonly<JsonDeserialized<V>>,\n\t\t\tkey: K,\n\t\t\tmap: StateMap<K, V>,\n\t\t) => void,\n\t\tthisArg?: unknown,\n\t): void;\n\n\t/**\n\t * Returns a specified element from the StateMap object.\n\t * @returns Returns the element associated with the specified key. If no element is associated with the specified key, undefined is returned.\n\t */\n\tget(key: K): DeepReadonly<JsonDeserialized<V>> | undefined;\n\n\t/**\n\t * @returns boolean indicating whether an element with the specified key exists or not.\n\t */\n\thas(key: K): boolean;\n\n\t/**\n\t * Adds a new element with a specified key and value to the StateMap. If an element with the same key already exists, the element will be updated.\n\t * The value will be transmitted to all other connected clients.\n\t *\n\t * @remarks Manager assumes ownership of the value and its references.\n\t * Make a deep clone before setting, if needed. No comparison is done to detect changes; all\n\t * sets are transmitted.\n\t */\n\tset(key: K, value: JsonSerializable<V> & JsonDeserialized<V>): this;\n\n\t/**\n\t * @returns the number of elements in the StateMap.\n\t */\n\treadonly size: number;\n\n\t/**\n\t * Returns an iterable of entries in the map.\n\t */\n\t// [Symbol.iterator](): IterableIterator<[K, DeepReadonly<JsonDeserialized<V>>]>;\n\n\t/**\n\t * Returns an iterable of key, value pairs for every entry in the map.\n\t */\n\t// entries(): IterableIterator<[K, DeepReadonly<JsonDeserialized<V>>]>;\n\n\t/**\n\t * Returns an iterable of keys in the map.\n\t */\n\tkeys(): IterableIterator<K>;\n\n\t/**\n\t * Returns an iterable of values in the map.\n\t */\n\t// values(): IterableIterator<DeepReadonly<JsonDeserialized<V>>>;\n}\n\nclass ValueMapImpl<T, K extends string | number> implements StateMap<K, T> {\n\tprivate countDefined: number;\n\tpublic constructor(\n\t\tprivate readonly value: InternalTypes.MapValueState<T, K>,\n\t\tprivate readonly emitter: IEmitter<\n\t\t\tPick<LatestMapRawEvents<T, K>, \"localItemUpdated\" | \"localItemRemoved\">\n\t\t>,\n\t\tprivate readonly localUpdate: (\n\t\t\tupdates: InternalTypes.MapValueState<\n\t\t\t\tT,\n\t\t\t\t// This should be `K`, but will only work if properties are optional.\n\t\t\t\tstring | number\n\t\t\t>,\n\t\t) => void,\n\t) {\n\t\t// All initial items are expected to be defined.\n\t\t// TODO assert all defined and/or update type.\n\t\tthis.countDefined = Object.keys(value.items).length;\n\t}\n\n\t/**\n\t * Note: caller must ensure key exists in this.value.items.\n\t */\n\tprivate updateItem(key: K, value: InternalTypes.ValueOptionalState<T>[\"value\"]): void {\n\t\tthis.value.rev += 1;\n\t\t// Caller is required to ensure key exists.\n\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\tconst item = this.value.items[key]!;\n\t\titem.rev += 1;\n\t\titem.timestamp = Date.now();\n\t\tif (value === undefined) {\n\t\t\tdelete item.value;\n\t\t} else {\n\t\t\titem.value = value;\n\t\t}\n\t\tconst update = { rev: this.value.rev, items: { [key]: item } };\n\t\tthis.localUpdate(update);\n\t}\n\n\tpublic clear(): void {\n\t\tthrow new Error(\"Method not implemented.\");\n\t}\n\tpublic delete(key: K): boolean {\n\t\tconst { items } = this.value;\n\t\tconst hasKey = items[key]?.value !== undefined;\n\t\tif (hasKey) {\n\t\t\tthis.countDefined -= 1;\n\t\t\tthis.updateItem(key, undefined);\n\t\t\tthis.emitter.emit(\"localItemRemoved\", { key });\n\t\t}\n\t\treturn hasKey;\n\t}\n\tpublic forEach(\n\t\tcallbackfn: (\n\t\t\tvalue: DeepReadonly<JsonDeserialized<T>>,\n\t\t\tkey: K,\n\t\t\tmap: StateMap<K, T>,\n\t\t) => void,\n\t\tthisArg?: unknown,\n\t): void {\n\t\tfor (const [key, item] of objectEntries(this.value.items)) {\n\t\t\tif (item.value !== undefined) {\n\t\t\t\tcallbackfn(asDeeplyReadonly(item.value), key, this);\n\t\t\t}\n\t\t}\n\t}\n\tpublic get(key: K): DeepReadonly<JsonDeserialized<T>> | undefined {\n\t\treturn asDeeplyReadonly(this.value.items[key]?.value);\n\t}\n\tpublic has(key: K): boolean {\n\t\treturn this.value.items[key]?.value !== undefined;\n\t}\n\tpublic set(key: K, value: JsonSerializable<T> & JsonDeserialized<T>): this {\n\t\tif (!(key in this.value.items)) {\n\t\t\tthis.countDefined += 1;\n\t\t\tthis.value.items[key] = { rev: 0, timestamp: 0, value };\n\t\t}\n\t\tthis.updateItem(key, value);\n\t\tthis.emitter.emit(\"localItemUpdated\", { key, value: asDeeplyReadonly(value) });\n\t\treturn this;\n\t}\n\tpublic get size(): number {\n\t\treturn this.countDefined;\n\t}\n\tpublic keys(): IterableIterator<K> {\n\t\tconst keys: K[] = [];\n\t\tfor (const [key, item] of objectEntries(this.value.items)) {\n\t\t\tif (item.value !== undefined) {\n\t\t\t\tkeys.push(key);\n\t\t\t}\n\t\t}\n\t\treturn keys[Symbol.iterator]();\n\t}\n}\n\n/**\n * State that provides a `Map` of latest known values from this client to\n * others and read access to their values.\n * Entries in the map may vary over time and by client, but all values are expected to\n * be of the same type, which may be a union type.\n *\n * @remarks Create using {@link StateFactory.latestMap} registered to {@link StatesWorkspace}.\n *\n * @sealed\n * @alpha\n */\nexport interface LatestMapRaw<T, Keys extends string | number = string | number> {\n\t/**\n\t * Containing {@link Presence}\n\t */\n\treadonly presence: Presence;\n\n\t/**\n\t * Events for LatestMapRaw.\n\t */\n\treadonly events: Listenable<LatestMapRawEvents<T, Keys>>;\n\n\t/**\n\t * Controls for management of sending updates.\n\t */\n\treadonly controls: BroadcastControls;\n\n\t/**\n\t * Current value map for this client.\n\t */\n\treadonly local: StateMap<Keys, T>;\n\t/**\n\t * Iterable access to remote clients' map of values.\n\t */\n\tgetRemotes(): IterableIterator<LatestMapClientData<T, Keys>>;\n\t/**\n\t * Array of {@link Attendee}s that have provided states.\n\t */\n\tgetStateAttendees(): Attendee[];\n\t/**\n\t * Access to a specific client's map of values.\n\t */\n\tgetRemote(attendee: Attendee): ReadonlyMap<Keys, LatestData<T>>;\n}\n\nclass LatestMapRawValueManagerImpl<\n\tT,\n\tRegistrationKey extends string,\n\tKeys extends string | number = string | number,\n> implements\n\t\tLatestMapRaw<T, Keys>,\n\t\tRequired<ValueManager<T, InternalTypes.MapValueState<T, Keys>>>\n{\n\tpublic readonly events = createEmitter<LatestMapRawEvents<T, Keys>>();\n\tpublic readonly controls: OptionalBroadcastControl;\n\n\tpublic constructor(\n\t\tprivate readonly key: RegistrationKey,\n\t\tprivate readonly datastore: StateDatastore<\n\t\t\tRegistrationKey,\n\t\t\tInternalTypes.MapValueState<T, Keys>\n\t\t>,\n\t\tpublic readonly value: InternalTypes.MapValueState<T, Keys>,\n\t\tcontrolSettings: BroadcastControlSettings | undefined,\n\t) {\n\t\tthis.controls = new OptionalBroadcastControl(controlSettings);\n\n\t\tthis.local = new ValueMapImpl<T, Keys>(\n\t\t\tvalue,\n\t\t\tthis.events,\n\t\t\t(updates: InternalTypes.MapValueState<T, Keys>) => {\n\t\t\t\tdatastore.localUpdate(key, updates, {\n\t\t\t\t\tallowableUpdateLatencyMs: this.controls.allowableUpdateLatencyMs,\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\t}\n\n\tpublic get presence(): Presence {\n\t\treturn this.datastore.presence;\n\t}\n\n\tpublic readonly local: StateMap<Keys, T>;\n\n\tpublic *getRemotes(): IterableIterator<LatestMapClientData<T, Keys>> {\n\t\tconst allKnownStates = this.datastore.knownValues(this.key);\n\t\tfor (const attendeeId of objectKeys(allKnownStates.states)) {\n\t\t\tif (attendeeId !== allKnownStates.self) {\n\t\t\t\tconst attendee = this.datastore.lookupClient(attendeeId);\n\t\t\t\tconst items = this.getRemote(attendee);\n\t\t\t\tyield { attendee, items };\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic getStateAttendees(): Attendee[] {\n\t\tconst allKnownStates = this.datastore.knownValues(this.key);\n\t\treturn objectKeys(allKnownStates.states)\n\t\t\t.filter((attendeeId) => attendeeId !== allKnownStates.self)\n\t\t\t.map((attendeeId) => this.datastore.lookupClient(attendeeId));\n\t}\n\n\tpublic getRemote(attendee: Attendee): ReadonlyMap<Keys, LatestData<T>> {\n\t\tconst allKnownStates = this.datastore.knownValues(this.key);\n\t\tconst attendeeId = attendee.attendeeId;\n\t\tconst clientStateMap = allKnownStates.states[attendeeId];\n\t\tif (clientStateMap === undefined) {\n\t\t\tthrow new Error(\"No entry for attendee\");\n\t\t}\n\t\tconst items = new Map<Keys, LatestData<T>>();\n\t\tfor (const [key, item] of objectEntries(clientStateMap.items)) {\n\t\t\tconst value = item.value;\n\t\t\tif (value !== undefined) {\n\t\t\t\titems.set(key, {\n\t\t\t\t\tvalue: asDeeplyReadonly(value),\n\t\t\t\t\tmetadata: { revision: item.rev, timestamp: item.timestamp },\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn items;\n\t}\n\n\tpublic update<SpecificAttendeeId extends AttendeeId>(\n\t\tattendee: SpecificAttendee<SpecificAttendeeId>,\n\t\t_received: number,\n\t\tvalue: InternalTypes.MapValueState<T, string | number>,\n\t): PostUpdateAction[] {\n\t\tconst allKnownStates = this.datastore.knownValues(this.key);\n\t\tconst attendeeId: SpecificAttendeeId = attendee.attendeeId;\n\t\tconst currentState = (allKnownStates.states[attendeeId] ??=\n\t\t\t// New attendee - prepare new attendee state directory\n\t\t\t{\n\t\t\t\trev: value.rev,\n\t\t\t\titems: {} as unknown as InternalTypes.MapValueState<T, Keys>[\"items\"],\n\t\t\t});\n\t\t// Accumulate individual update keys\n\t\tconst updatedItemKeys: Keys[] = [];\n\t\tfor (const [key, item] of objectEntries(value.items)) {\n\t\t\t// TODO: Key validation needs to be added here.\n\t\t\tconst validKey = key as Keys;\n\t\t\tif (!(key in currentState.items) || currentState.items[validKey].rev < item.rev) {\n\t\t\t\tupdatedItemKeys.push(validKey);\n\t\t\t}\n\t\t}\n\n\t\tif (updatedItemKeys.length === 0) {\n\t\t\treturn [];\n\t\t}\n\n\t\t// Store updates\n\t\tif (value.rev > currentState.rev) {\n\t\t\tcurrentState.rev = value.rev;\n\t\t}\n\t\tconst allUpdates = {\n\t\t\tattendee,\n\t\t\titems: new Map<Keys, LatestData<T>>(),\n\t\t};\n\t\tconst postUpdateActions: PostUpdateAction[] = [];\n\t\tfor (const key of updatedItemKeys) {\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\tconst item = value.items[key]!;\n\t\t\tconst hadPriorValue = currentState.items[key]?.value;\n\t\t\tcurrentState.items[key] = item;\n\t\t\tconst metadata = { revision: item.rev, timestamp: item.timestamp };\n\t\t\tif (item.value !== undefined) {\n\t\t\t\tconst itemValue = asDeeplyReadonly(item.value);\n\t\t\t\tconst updatedItem = {\n\t\t\t\t\tattendee,\n\t\t\t\t\tkey,\n\t\t\t\t\tvalue: itemValue,\n\t\t\t\t\tmetadata,\n\t\t\t\t};\n\t\t\t\tpostUpdateActions.push(() => this.events.emit(\"remoteItemUpdated\", updatedItem));\n\t\t\t\tallUpdates.items.set(key, { value: itemValue, metadata });\n\t\t\t} else if (hadPriorValue !== undefined) {\n\t\t\t\tpostUpdateActions.push(() =>\n\t\t\t\t\tthis.events.emit(\"remoteItemRemoved\", {\n\t\t\t\t\t\tattendee,\n\t\t\t\t\t\tkey,\n\t\t\t\t\t\tmetadata,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tthis.datastore.update(this.key, attendeeId, currentState);\n\t\tpostUpdateActions.push(() => this.events.emit(\"remoteUpdated\", allUpdates));\n\t\treturn postUpdateActions;\n\t}\n}\n\n/**\n * Arguments that are passed to the {@link StateFactory.latestMap} function.\n *\n * @alpha\n */\nexport interface LatestMapArguments<T, Keys extends string | number = string | number> {\n\t/**\n\t * The initial value of the local state.\n\t */\n\tlocal?: {\n\t\t[K in Keys]: JsonSerializable<T> & JsonDeserialized<T>;\n\t};\n\n\t/**\n\t * See {@link BroadcastControlSettings}.\n\t */\n\tsettings?: BroadcastControlSettings | undefined;\n}\n\n/**\n * Factory for creating a {@link LatestMapRaw} State object.\n *\n * @alpha\n */\nexport function latestMap<\n\tT,\n\tKeys extends string | number = string | number,\n\tRegistrationKey extends string = string,\n>(\n\targs?: LatestMapArguments<T, Keys>,\n): InternalTypes.ManagerFactory<\n\tRegistrationKey,\n\tInternalTypes.MapValueState<T, Keys>,\n\tLatestMapRaw<T, Keys>\n> {\n\tconst settings = args?.settings;\n\tconst initialValues = args?.local;\n\n\tconst timestamp = Date.now();\n\tconst value: InternalTypes.MapValueState<\n\t\tT,\n\t\t// This should be `Keys`, but will only work if properties are optional.\n\t\tstring | number\n\t> = { rev: 0, items: {} };\n\t// LatestMapRaw takes ownership of values within initialValues.\n\tif (initialValues !== undefined) {\n\t\tfor (const key of objectKeys(initialValues)) {\n\t\t\tvalue.items[key] = {\n\t\t\t\trev: 0,\n\t\t\t\ttimestamp,\n\t\t\t\tvalue: initialValues[key],\n\t\t\t};\n\t\t}\n\t}\n\tconst factory = (\n\t\tkey: RegistrationKey,\n\t\tdatastoreHandle: InternalTypes.StateDatastoreHandle<\n\t\t\tRegistrationKey,\n\t\t\tInternalTypes.MapValueState<T, Keys>\n\t\t>,\n\t): {\n\t\tinitialData: { value: typeof value; allowableUpdateLatencyMs: number | undefined };\n\t\tmanager: InternalTypes.StateValue<LatestMapRaw<T, Keys>>;\n\t} => ({\n\t\tinitialData: { value, allowableUpdateLatencyMs: settings?.allowableUpdateLatencyMs },\n\t\tmanager: brandIVM<\n\t\t\tLatestMapRawValueManagerImpl<T, RegistrationKey, Keys>,\n\t\t\tT,\n\t\t\tInternalTypes.MapValueState<T, Keys>\n\t\t>(\n\t\t\tnew LatestMapRawValueManagerImpl(\n\t\t\t\tkey,\n\t\t\t\tdatastoreFromHandle(datastoreHandle),\n\t\t\t\tvalue,\n\t\t\t\tsettings,\n\t\t\t),\n\t\t),\n\t});\n\treturn Object.assign(factory, { instanceBase: LatestMapRawValueManagerImpl });\n}\n"]}