@calimero-network/mero-js 23.4.1 → 23.4.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.cjs CHANGED
@@ -2967,6 +2967,14 @@ var SseClient = class {
2967
2967
  this.reconnectTimer = null;
2968
2968
  this.subscribedContextIds = /* @__PURE__ */ new Set();
2969
2969
  this.subscribedGroupIds = /* @__PURE__ */ new Set();
2970
+ /**
2971
+ * The current presence of each subscribed context, as the node's replay and
2972
+ * its live deltas left it: author → that author's last `Ephemeral` data and
2973
+ * when it arrived. The node replays a context's presence once, when the
2974
+ * context is first subscribed on this connection, so a presence listener
2975
+ * that comes later would never see it; {@link presenceSeed} gives it this.
2976
+ */
2977
+ this.presence = /* @__PURE__ */ new Map();
2970
2978
  this.closed = false;
2971
2979
  this.listeners = { connect: [], event: [], error: [] };
2972
2980
  this.baseUrl = opts.baseUrl.replace(/\/+$/, "");
@@ -3132,6 +3140,7 @@ var SseClient = class {
3132
3140
  if (msg.type === "connect" && msg.session_id) {
3133
3141
  this.sessionId = msg.session_id;
3134
3142
  this.emit("connect", msg.session_id);
3143
+ this.presence.clear();
3135
3144
  if (this.subscribedContextIds.size > 0 || this.subscribedGroupIds.size > 0) {
3136
3145
  this.sendSubscription("subscribe", {
3137
3146
  contextIds: [...this.subscribedContextIds],
@@ -3151,6 +3160,7 @@ var SseClient = class {
3151
3160
  }
3152
3161
  }
3153
3162
  if (msg.result.contextId) {
3163
+ if (msg.result.type === "Ephemeral") this.notePresence(msg.result.contextId, eventData);
3154
3164
  this.emit("event", {
3155
3165
  contextId: msg.result.contextId,
3156
3166
  // Forward the event tag (sibling of `data` in core's flattened
@@ -3184,12 +3194,38 @@ var SseClient = class {
3184
3194
  await this.sendSubscription("subscribe", { contextIds: newContextIds, groupIds: newGroupIds });
3185
3195
  }
3186
3196
  }
3197
+ /** Whether this connection holds `contextId`'s events. */
3198
+ isSubscribed(contextId) {
3199
+ return this.subscribedContextIds.has(contextId);
3200
+ }
3201
+ /**
3202
+ * The presence currently known for `contextId`, as `Ephemeral` event data,
3203
+ * each entry's `ageMs` advanced by how long ago it arrived. Empty for a
3204
+ * context this connection does not hold.
3205
+ */
3206
+ presenceSeed(contextId) {
3207
+ const now = Date.now();
3208
+ return [...this.presence.get(contextId)?.values() ?? []].map(({ data, at }) => ({
3209
+ ...data,
3210
+ ageMs: (typeof data.ageMs === "number" ? data.ageMs : 0) + (now - at)
3211
+ }));
3212
+ }
3213
+ notePresence(contextId, data) {
3214
+ if (!this.subscribedContextIds.has(contextId)) return;
3215
+ const d = data;
3216
+ if (!d || typeof d.author !== "string") return;
3217
+ let byAuthor = this.presence.get(contextId);
3218
+ if (!byAuthor) this.presence.set(contextId, byAuthor = /* @__PURE__ */ new Map());
3219
+ if (d.removed) byAuthor.delete(d.author);
3220
+ else byAuthor.set(d.author, { data: d, at: Date.now() });
3221
+ }
3187
3222
  async unsubscribe(idsOrOpts) {
3188
3223
  const opts = Array.isArray(idsOrOpts) ? { contextIds: idsOrOpts } : idsOrOpts;
3189
3224
  const hadContextIds = (opts.contextIds ?? []).filter((id) => this.subscribedContextIds.has(id));
3190
3225
  const hadGroupIds = (opts.groupIds ?? []).filter((id) => this.subscribedGroupIds.has(id));
3191
3226
  for (const id of opts.contextIds ?? []) {
3192
3227
  this.subscribedContextIds.delete(id);
3228
+ this.presence.delete(id);
3193
3229
  }
3194
3230
  for (const id of opts.groupIds ?? []) {
3195
3231
  this.subscribedGroupIds.delete(id);
@@ -3527,6 +3563,11 @@ function subscribePresence(sse, contextId, handler, codec = jsonCodec()) {
3527
3563
  handler(entry);
3528
3564
  };
3529
3565
  sse.on("event", listener);
3566
+ if (sse.isSubscribed?.(contextId)) {
3567
+ for (const data of sse.presenceSeed?.(contextId) ?? []) {
3568
+ listener({ contextId, type: "Ephemeral", data });
3569
+ }
3570
+ }
3530
3571
  void sse.connect().catch(() => void 0);
3531
3572
  void sse.subscribe([contextId]).catch(() => void 0);
3532
3573
  return () => {
@@ -10832,7 +10873,7 @@ function bytes32(value, label2) {
10832
10873
  }
10833
10874
 
10834
10875
  // src/namespace-op/namespace-op.ts
10835
- var SIGNED_NAMESPACE_OP_SCHEMA_VERSION = 20;
10876
+ var SIGNED_NAMESPACE_OP_SCHEMA_VERSION = 21;
10836
10877
  var NAMESPACE_SIGN_DOMAIN = new TextEncoder().encode("calimero.namespace.v1");
10837
10878
  var NAMESPACE_OP_ROOT = 0;
10838
10879
  var ROOT_OP2 = {