@automerge/automerge-repo-react-hooks 2.5.2-alpha.6 → 2.5.3

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.
package/dist/index.js CHANGED
@@ -6692,139 +6692,67 @@ const DEFAULT_HEARTBEAT_INTERVAL_MS = 15_000;
6692
6692
  const DEFAULT_PEER_TTL_MS = 3 * DEFAULT_HEARTBEAT_INTERVAL_MS;
6693
6693
  const PRESENCE_MESSAGE_MARKER = "__presence";
6694
6694
 
6695
- function unique(items) {
6696
- return Array.from(new Set(items));
6697
- }
6698
-
6695
+ /**
6696
+ * A grouped view of peer states.
6697
+ */
6699
6698
  class PeerStateView {
6700
6699
  value;
6701
6700
  constructor(value) {
6702
6701
  this.value = value;
6703
6702
  }
6704
6703
  /**
6705
- * Get all users.
6706
- *
6707
- * @returns Array of user presence {@link State}s
6708
- */
6709
- get users() {
6710
- const userIds = unique(Object.values(this.value).map(peerState => peerState.userId));
6711
- return userIds.map(u => this.getUserState(u));
6712
- }
6713
- /**
6714
- * Get all devices.
6715
- *
6716
- * @returns Array of device presence {@link State}s
6717
- */
6718
- get devices() {
6719
- const deviceIds = unique(Object.values(this.value).map(peerState => peerState.deviceId));
6720
- return deviceIds.map(d => this.getDeviceState(d));
6721
- }
6722
- /**
6723
- * Get all peers.
6724
- *
6725
- * @returns Array of peer presence {@link State}s
6726
- */
6727
- get peers() {
6728
- return Object.values(this.value);
6729
- }
6730
- /**
6731
- * Get all peer ids for this user.
6732
- *
6733
- * @param userId
6734
- * @returns Array of peer ids for this user
6735
- */
6736
- getUserPeers(userId) {
6737
- return Object.values(this.value)
6738
- .filter(peerState => peerState.userId === userId)
6739
- .map(peerState => peerState.peerId);
6740
- }
6741
- /**
6742
- * Get all peers for this device.
6743
- *
6744
- * @param deviceId
6745
- * @returns Array of peer ids for this device
6746
- */
6747
- getDevicePeers(deviceId) {
6748
- return Object.values(this.value)
6749
- .filter(peerState => peerState.deviceId === deviceId)
6750
- .map(peerState => peerState.peerId);
6751
- }
6752
- /**
6753
- * Return the most-recently-seen peer from this group.
6704
+ * Get the presence state of all peers. By default, each peer is its own
6705
+ * group, but presence activity can be aggregated by arbitrary criteria.
6754
6706
  *
6755
- * @param peers
6756
- * @returns id of most recently seen peer
6707
+ * @param opts
6708
+ * @returns presence state for all groups
6757
6709
  */
6758
- getLastSeenPeer(peers) {
6759
- let freshestLastSeenAt;
6760
- return peers.reduce((freshest, curr) => {
6761
- const lastSeenAt = this.value[curr]?.lastSeenAt;
6762
- if (!lastSeenAt) {
6763
- return freshest;
6764
- }
6765
- if (!freshest || lastSeenAt > freshestLastSeenAt) {
6766
- freshestLastSeenAt = lastSeenAt;
6767
- return curr;
6710
+ getStates(opts) {
6711
+ const groupingFn = opts?.groupingFn ?? peerIdentity;
6712
+ const summaryFn = opts?.summaryFn ??
6713
+ getLastActivePeer;
6714
+ const statesByKey = Object.values(this.value).reduce((byKey, curr) => {
6715
+ const key = groupingFn(curr);
6716
+ if (!(key in byKey)) {
6717
+ byKey[key] = [];
6768
6718
  }
6769
- return freshest;
6770
- }, undefined);
6719
+ byKey[key].push(curr);
6720
+ return byKey;
6721
+ }, {});
6722
+ return Object.entries(statesByKey).reduce((result, [key, states]) => {
6723
+ result[key] = summaryFn(states);
6724
+ return result;
6725
+ }, {});
6771
6726
  }
6772
- /**
6773
- * Return the peer from this group that sent a state update most recently
6774
- *
6775
- * @param peers
6776
- * @returns id of most recently seen peer
6777
- */
6778
- getLastActivePeer(peers) {
6779
- let freshestLastActiveAt;
6780
- return peers.reduce((freshest, curr) => {
6781
- const lastActiveAt = this.value[curr]?.lastActiveAt;
6782
- if (!lastActiveAt) {
6783
- return freshest;
6784
- }
6785
- if (!freshest || lastActiveAt > freshestLastActiveAt) {
6786
- freshestLastActiveAt = lastActiveAt;
6787
- return curr;
6788
- }
6727
+ }
6728
+ /**
6729
+ * Get the peerId of this peer.
6730
+ *
6731
+ * @param peer
6732
+ * @returns peer id
6733
+ */
6734
+ function peerIdentity(peer) {
6735
+ return peer.peerId;
6736
+ }
6737
+ /**
6738
+ * Find the peer that most recently sent a state update.
6739
+ *
6740
+ * @param peers
6741
+ * @returns id of most recently active peer
6742
+ */
6743
+ function getLastActivePeer(peers) {
6744
+ let freshestLastActiveAt;
6745
+ return peers.reduce((freshest, curr) => {
6746
+ const lastActiveAt = curr.lastActiveAt;
6747
+ if (!lastActiveAt) {
6789
6748
  return freshest;
6790
- }, undefined);
6791
- }
6792
- /**
6793
- * Get current ephemeral state value for this user's most-recently-active
6794
- * peer.
6795
- *
6796
- * @param userId
6797
- * @returns user's {@link State}
6798
- */
6799
- getUserState(userId) {
6800
- const peers = this.getUserPeers(userId);
6801
- if (!peers) {
6802
- return undefined;
6803
6749
  }
6804
- const peer = this.getLastActivePeer(peers);
6805
- if (!peer) {
6806
- return undefined;
6807
- }
6808
- return this.value[peer];
6809
- }
6810
- /**
6811
- * Get current ephemeral state value for this device's most-recently-active
6812
- * peer.
6813
- *
6814
- * @param deviceId
6815
- * @returns device's {@link State}
6816
- */
6817
- getDeviceState(deviceId) {
6818
- const peers = this.getDevicePeers(deviceId);
6819
- if (!peers) {
6820
- return undefined;
6750
+ if (!freshest || lastActiveAt > freshestLastActiveAt) {
6751
+ freshestLastActiveAt = lastActiveAt;
6752
+ return curr;
6821
6753
  }
6822
- const peer = this.getLastActivePeer(peers);
6823
- if (!peer) {
6824
- return undefined;
6825
- }
6826
- return this.value[peer];
6827
- }
6754
+ return freshest;
6755
+ }, undefined);
6828
6756
  }
6829
6757
 
6830
6758
  class PeerPresenceInfo {
@@ -6867,7 +6795,7 @@ class PeerPresenceInfo {
6867
6795
  * @param peerId
6868
6796
  * @param value
6869
6797
  */
6870
- update({ peerId, deviceId, userId, value, }) {
6798
+ update({ peerId, value }) {
6871
6799
  const peerState = this.#peerStates.value[peerId];
6872
6800
  const existingState = peerState?.value ?? {};
6873
6801
  const now = Date.now();
@@ -6875,10 +6803,8 @@ class PeerPresenceInfo {
6875
6803
  ...this.#peerStates.value,
6876
6804
  [peerId]: {
6877
6805
  peerId,
6878
- deviceId,
6879
- userId,
6880
- lastActiveAt: now,
6881
6806
  lastSeenAt: now,
6807
+ lastActiveAt: now,
6882
6808
  value: {
6883
6809
  ...existingState,
6884
6810
  ...value,
@@ -6933,8 +6859,6 @@ class PeerPresenceInfo {
6933
6859
  */
6934
6860
  class Presence extends EventEmitter {
6935
6861
  #handle;
6936
- deviceId;
6937
- userId;
6938
6862
  #peers;
6939
6863
  #localState;
6940
6864
  #heartbeatMs;
@@ -6949,13 +6873,11 @@ class Presence extends EventEmitter {
6949
6873
  * @param config see {@link PresenceConfig}
6950
6874
  * @returns
6951
6875
  */
6952
- constructor({ handle, deviceId, userId, }) {
6876
+ constructor({ handle }) {
6953
6877
  super();
6954
6878
  this.#handle = handle;
6955
6879
  this.#peers = new PeerPresenceInfo(DEFAULT_PEER_TTL_MS);
6956
6880
  this.#localState = {};
6957
- this.userId = userId;
6958
- this.deviceId = deviceId;
6959
6881
  }
6960
6882
  /**
6961
6883
  * Start listening to ephemeral messages on the handle, broadcast initial
@@ -6979,7 +6901,6 @@ class Presence extends EventEmitter {
6979
6901
  return;
6980
6902
  }
6981
6903
  const message = envelope[PRESENCE_MESSAGE_MARKER];
6982
- const { deviceId, userId } = message;
6983
6904
  if (!this.#peers.has(peerId)) {
6984
6905
  this.announce();
6985
6906
  }
@@ -6995,15 +6916,11 @@ class Presence extends EventEmitter {
6995
6916
  case "update":
6996
6917
  this.#peers.update({
6997
6918
  peerId,
6998
- deviceId,
6999
- userId,
7000
6919
  value: { [message.channel]: message.value },
7001
6920
  });
7002
6921
  this.emit("update", {
7003
6922
  type: "update",
7004
6923
  peerId,
7005
- deviceId,
7006
- userId,
7007
6924
  channel: message.channel,
7008
6925
  value: message.value,
7009
6926
  });
@@ -7011,15 +6928,11 @@ class Presence extends EventEmitter {
7011
6928
  case "snapshot":
7012
6929
  this.#peers.update({
7013
6930
  peerId,
7014
- deviceId,
7015
- userId,
7016
6931
  value: message.state,
7017
6932
  });
7018
6933
  this.emit("snapshot", {
7019
6934
  type: "snapshot",
7020
6935
  peerId,
7021
- deviceId,
7022
- userId,
7023
6936
  state: message.state,
7024
6937
  });
7025
6938
  break;
@@ -7114,8 +7027,6 @@ class Presence extends EventEmitter {
7114
7027
  }
7115
7028
  doBroadcast(type, extra) {
7116
7029
  this.send({
7117
- userId: this.userId,
7118
- deviceId: this.deviceId,
7119
7030
  type,
7120
7031
  ...extra,
7121
7032
  });
@@ -7168,8 +7079,6 @@ class Presence extends EventEmitter {
7168
7079
 
7169
7080
  function usePresence({
7170
7081
  handle,
7171
- userId,
7172
- deviceId,
7173
7082
  initialState,
7174
7083
  heartbeatMs,
7175
7084
  peerTtlMs
@@ -7181,9 +7090,7 @@ function usePresence({
7181
7090
  peerTtlMs
7182
7091
  });
7183
7092
  const firstInitialState = useRef(initialState);
7184
- const [presence] = useState(
7185
- () => new Presence({ handle, userId, deviceId })
7186
- );
7093
+ const [presence] = useState(() => new Presence({ handle }));
7187
7094
  useEffect(() => {
7188
7095
  presence.start({
7189
7096
  initialState: firstInitialState.current,
@@ -7197,7 +7104,7 @@ function usePresence({
7197
7104
  return () => {
7198
7105
  presence.stop();
7199
7106
  };
7200
- }, [presence, userId, deviceId, firstInitialState, firstOpts]);
7107
+ }, [presence, firstInitialState, firstOpts]);
7201
7108
  const start = useCallback(
7202
7109
  (config) => {
7203
7110
  const initialState2 = config?.initialState ?? presence.getLocalState();