@palbase/web 1.1.1 → 1.2.1

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
@@ -1746,6 +1746,18 @@ async function listDevices(rt, userId) {
1746
1746
  }
1747
1747
 
1748
1748
  // src/messaging/group-messaging.ts
1749
+ function encodeReaction(args) {
1750
+ return encodeUtf8(
1751
+ JSON.stringify({
1752
+ v: 1,
1753
+ type: "reaction",
1754
+ client_msg_id: args.clientMsgId,
1755
+ target_client_msg_id: args.targetClientMsgId,
1756
+ emoji: args.emoji,
1757
+ op: args.op
1758
+ })
1759
+ );
1760
+ }
1749
1761
  function encodeEnvelope(args) {
1750
1762
  const env = {
1751
1763
  v: 1,
@@ -1760,18 +1772,32 @@ function decodeEnvelope(bytes) {
1760
1772
  const s = decodeUtf8(bytes);
1761
1773
  try {
1762
1774
  const o = JSON.parse(s);
1775
+ if (typeof o === "object" && o !== null && o.type === "reaction") {
1776
+ return {
1777
+ type: "reaction",
1778
+ text: null,
1779
+ clientMsgId: o.client_msg_id ?? "",
1780
+ replyTo: null,
1781
+ reaction: {
1782
+ targetClientMsgId: o.target_client_msg_id ?? "",
1783
+ emoji: o.emoji ?? "",
1784
+ op: o.op ?? "add"
1785
+ }
1786
+ };
1787
+ }
1763
1788
  if (typeof o === "object" && o !== null && o.type === "text" && typeof o.v === "number") {
1764
1789
  return {
1790
+ type: "text",
1765
1791
  text: o.text ?? null,
1766
1792
  clientMsgId: o.client_msg_id ?? "",
1767
1793
  replyTo: o.reply_to ?? null
1768
1794
  };
1769
1795
  }
1770
1796
  if (typeof o === "object" && o !== null && o.type === "text") {
1771
- return { text: o.text ?? null, clientMsgId: "", replyTo: null };
1797
+ return { type: "text", text: o.text ?? null, clientMsgId: "", replyTo: null };
1772
1798
  }
1773
1799
  if (typeof o === "object" && o !== null && o.type === "media")
1774
- return { text: null, clientMsgId: "", replyTo: null };
1800
+ return { type: "media", text: null, clientMsgId: "", replyTo: null };
1775
1801
  } catch {
1776
1802
  }
1777
1803
  return { text: s, clientMsgId: "", replyTo: null };
@@ -2023,6 +2049,56 @@ var GroupMessaging = class {
2023
2049
  }
2024
2050
  return { receipt: { serverSeq: wire.server_seq, epoch: wire.epoch }, clientMsgId };
2025
2051
  }
2052
+ /** Send a reaction (add/remove of an emoji on a target message). Encrypts a
2053
+ * `type:'reaction'` envelope at the current epoch and sends through the SAME
2054
+ * MLS application path as `sendText` (the server stays blind — a reaction is
2055
+ * just another application message). Persists the outgoing reaction row so it
2056
+ * re-folds onto its target after a reload (the own-send half of the reload
2057
+ * parity). NEVER rebases (epoch-bound like any application message). */
2058
+ async sendReaction(group, args) {
2059
+ const plaintext = encodeReaction({
2060
+ clientMsgId: args.clientMsgId,
2061
+ targetClientMsgId: args.targetClientMsgId,
2062
+ emoji: args.emoji,
2063
+ op: args.op
2064
+ });
2065
+ const ct = await this.engine.encryptApplication(fromBase64(group.rfcGroupId), plaintext);
2066
+ const body = {
2067
+ ciphertext_b64: toBase64(ct),
2068
+ client_idem_key: randomId()
2069
+ };
2070
+ const wire = await palbeRequest(
2071
+ this.rt,
2072
+ "POST",
2073
+ MessagingPaths.groupMessages(group.displayId),
2074
+ { body }
2075
+ );
2076
+ const stored = {
2077
+ id: `${group.rfcGroupId}#${wire.server_seq}`,
2078
+ direction: "outgoing",
2079
+ text: null,
2080
+ senderDeviceId: this.selfDeviceId,
2081
+ epoch: wire.epoch,
2082
+ serverSeq: wire.server_seq,
2083
+ at: Date.now(),
2084
+ clientMsgId: args.clientMsgId,
2085
+ replyTo: null,
2086
+ envelopeType: "reaction",
2087
+ reaction: {
2088
+ targetClientMsgId: args.targetClientMsgId,
2089
+ emoji: args.emoji,
2090
+ op: args.op
2091
+ }
2092
+ };
2093
+ try {
2094
+ await this.messageStore.append(group.rfcGroupId, stored);
2095
+ } catch {
2096
+ }
2097
+ return {
2098
+ receipt: { serverSeq: wire.server_seq, epoch: wire.epoch },
2099
+ clientMsgId: args.clientMsgId
2100
+ };
2101
+ }
2026
2102
  // ── The rebase loop ──
2027
2103
  async commitWithRebase(rfcGroupId, build) {
2028
2104
  const gidBytes = fromBase64(rfcGroupId);
@@ -2084,6 +2160,61 @@ var GroupMessaging = class {
2084
2160
  }
2085
2161
  };
2086
2162
 
2163
+ // src/messaging/reaction-fold.ts
2164
+ function orderLte(aEpoch, aSeq, bEpoch, bSeq) {
2165
+ if (aEpoch !== bEpoch) return aEpoch < bEpoch;
2166
+ return aSeq <= bSeq;
2167
+ }
2168
+ var ReactionFold = class {
2169
+ // Map<targetClientMsgId, Map<actorUserId, UserState>>
2170
+ states = /* @__PURE__ */ new Map();
2171
+ // Dedup set: eventClientMsgId values already applied.
2172
+ seenEvents = /* @__PURE__ */ new Set();
2173
+ ingest(e) {
2174
+ if (this.seenEvents.has(e.eventClientMsgId)) return;
2175
+ this.seenEvents.add(e.eventClientMsgId);
2176
+ let byUser = this.states.get(e.targetClientMsgId);
2177
+ if (byUser === void 0) {
2178
+ byUser = /* @__PURE__ */ new Map();
2179
+ this.states.set(e.targetClientMsgId, byUser);
2180
+ }
2181
+ const prev = byUser.get(e.actorUserId);
2182
+ if (prev !== void 0) {
2183
+ if (orderLte(e.epoch, e.serverSeq, prev.orderEpoch, prev.orderSeq)) return;
2184
+ }
2185
+ byUser.set(e.actorUserId, {
2186
+ orderEpoch: e.epoch,
2187
+ orderSeq: e.serverSeq,
2188
+ emoji: e.op === "add" ? e.emoji : null
2189
+ });
2190
+ }
2191
+ /**
2192
+ * Returns a tally of `{ emoji → sorted userIds[] }` for the given target
2193
+ * message. Users whose last event was a `remove` (emoji === null) are
2194
+ * excluded. userId arrays are sorted for deterministic output (render
2195
+ * stability + golden tests).
2196
+ */
2197
+ tally(targetClientMsgId) {
2198
+ const byUser = this.states.get(targetClientMsgId);
2199
+ if (byUser === void 0) return {};
2200
+ const out = /* @__PURE__ */ new Map();
2201
+ for (const [userId, st] of byUser) {
2202
+ if (st.emoji === null) continue;
2203
+ let users = out.get(st.emoji);
2204
+ if (users === void 0) {
2205
+ users = [];
2206
+ out.set(st.emoji, users);
2207
+ }
2208
+ users.push(userId);
2209
+ }
2210
+ const result = {};
2211
+ for (const [emoji, users] of out) {
2212
+ result[emoji] = users.sort();
2213
+ }
2214
+ return result;
2215
+ }
2216
+ };
2217
+
2087
2218
  // src/messaging/chat.ts
2088
2219
  var Chat = class {
2089
2220
  /** Stable, URL/log-safe id (the grp_ display id once active; a reserved local id while draft). */
@@ -2102,6 +2233,8 @@ var Chat = class {
2102
2233
  seenKeys = /* @__PURE__ */ new Set();
2103
2234
  /** Index: clientMsgId → { text, senderUserId } for resolveReply lookups. */
2104
2235
  byClientMsgId = /* @__PURE__ */ new Map();
2236
+ /** The single authoritative reaction fold for this chat (live + own-send + history). */
2237
+ reactionFold = new ReactionFold();
2105
2238
  loadedEarliestSeq = null;
2106
2239
  historyLoaded = false;
2107
2240
  wired = false;
@@ -2208,7 +2341,7 @@ var Chat = class {
2208
2341
  const key = this.internalKey(m.serverSeq);
2209
2342
  if (this.seenKeys.has(key)) continue;
2210
2343
  this.seenKeys.add(key);
2211
- this.messageList.push(m);
2344
+ this.messageList.push(this.applyReactionTally(m));
2212
2345
  changed = true;
2213
2346
  this.loadedEarliestSeq = Math.min(this.loadedEarliestSeq ?? m.serverSeq, m.serverSeq);
2214
2347
  }
@@ -2233,6 +2366,22 @@ var Chat = class {
2233
2366
  senderUser = await this.backend.userIdForDevice(this._group, incoming.senderDeviceId);
2234
2367
  }
2235
2368
  const direction = senderUser !== null && senderUser === this.backend.selfUserId ? "outgoing" : "incoming";
2369
+ if (incoming.envelopeType === "reaction" && incoming.reaction) {
2370
+ const actorUserId = direction === "outgoing" ? this.backend.selfUserId : senderUser;
2371
+ if (actorUserId !== null) {
2372
+ this.reactionFold.ingest({
2373
+ targetClientMsgId: incoming.reaction.targetClientMsgId,
2374
+ actorUserId,
2375
+ emoji: incoming.reaction.emoji,
2376
+ op: incoming.reaction.op,
2377
+ epoch: incoming.epoch,
2378
+ serverSeq: incoming.serverSeq,
2379
+ eventClientMsgId: incoming.clientMsgId
2380
+ });
2381
+ this.recomputeReactions(incoming.reaction.targetClientMsgId);
2382
+ }
2383
+ return;
2384
+ }
2236
2385
  const incomingClientMsgId = incoming.clientMsgId;
2237
2386
  const incomingReplyRef = incoming.replyRef;
2238
2387
  let resolvedReplyTo = null;
@@ -2248,7 +2397,10 @@ var Chat = class {
2248
2397
  serverSeq: incoming.serverSeq,
2249
2398
  sentAt: incoming.receivedAt,
2250
2399
  clientMsgId: incomingClientMsgId,
2251
- replyTo: resolvedReplyTo
2400
+ replyTo: resolvedReplyTo,
2401
+ // Attach any tally already folded for this message (a reaction that arrived
2402
+ // BEFORE its target — the dangling case — renders the moment the target lands).
2403
+ reactions: incomingClientMsgId ? this.reactionFold.tally(incomingClientMsgId) : {}
2252
2404
  };
2253
2405
  if (incomingClientMsgId && incoming.text !== null) {
2254
2406
  this.byClientMsgId.set(incomingClientMsgId, {
@@ -2264,6 +2416,35 @@ var Chat = class {
2264
2416
  );
2265
2417
  this.emit();
2266
2418
  }
2419
+ /**
2420
+ * Rebuild the target message's `reactions` from the authoritative fold and
2421
+ * re-emit. No-op when the target isn't present yet (its tally is attached the
2422
+ * moment it lands, via the append/merge paths) or when the tally is unchanged.
2423
+ */
2424
+ recomputeReactions(targetClientMsgId) {
2425
+ if (!targetClientMsgId) return;
2426
+ const tally = this.reactionFold.tally(targetClientMsgId);
2427
+ let changed = false;
2428
+ this.messageList = this.messageList.map((m) => {
2429
+ if (m.clientMsgId !== targetClientMsgId) return m;
2430
+ if (sameReactions(m.reactions, tally)) return m;
2431
+ changed = true;
2432
+ return { ...m, reactions: tally };
2433
+ });
2434
+ if (changed) this.emit();
2435
+ }
2436
+ /**
2437
+ * Overlay the authoritative fold's tally onto a message as it is appended/merged.
2438
+ * The Chat fold WINS when it has a non-empty tally; otherwise the tally already
2439
+ * attached upstream (the coordinator's page-local history fold) is preserved.
2440
+ */
2441
+ applyReactionTally(m) {
2442
+ if (!m.clientMsgId) return m;
2443
+ const tally = this.reactionFold.tally(m.clientMsgId);
2444
+ if (Object.keys(tally).length === 0) return m;
2445
+ if (sameReactions(m.reactions, tally)) return m;
2446
+ return { ...m, reactions: tally };
2447
+ }
2267
2448
  /** @internal — called by the backend's conv subscription. */
2268
2449
  applyConv(event, payload) {
2269
2450
  const userId = typeof payload.user_id === "string" ? payload.user_id : null;
@@ -2406,7 +2587,10 @@ var Chat = class {
2406
2587
  serverSeq: receipt.serverSeq,
2407
2588
  sentAt: /* @__PURE__ */ new Date(),
2408
2589
  clientMsgId,
2409
- replyTo: resolvedReplyTo
2590
+ replyTo: resolvedReplyTo,
2591
+ // Attach any tally already folded for this own-sent message (rare, but keeps
2592
+ // the dangling-target invariant uniform across every append path).
2593
+ reactions: clientMsgId ? this.reactionFold.tally(clientMsgId) : {}
2410
2594
  });
2411
2595
  this.messageList.sort((a, b) => a.serverSeq - b.serverSeq);
2412
2596
  this.emit();
@@ -2453,7 +2637,53 @@ var Chat = class {
2453
2637
  this.readWatermark = Math.max(this.readWatermark, message.serverSeq);
2454
2638
  this.emit();
2455
2639
  }
2640
+ // ── Reactions ──
2641
+ /** Add an emoji reaction to a message. No-op if the message isn't reactable
2642
+ * (empty clientMsgId — a legacy/system row). The reaction folds locally with
2643
+ * the server receipt's `(epoch, serverSeq)` so the target's tally updates
2644
+ * instantly; the durable echo on the next pump is a fold no-op (dedup on the
2645
+ * SAME wire clientMsgId). Never appends a bubble. */
2646
+ async react(message, emoji) {
2647
+ await this.sendReaction(message, emoji, "add");
2648
+ }
2649
+ /** Remove this user's emoji reaction from a message (op:'remove'). */
2650
+ async unreact(message, emoji) {
2651
+ await this.sendReaction(message, emoji, "remove");
2652
+ }
2653
+ async sendReaction(message, emoji, op) {
2654
+ if (!message.clientMsgId) return;
2655
+ const group = await this.materializeIfNeeded();
2656
+ const clientMsgId = mintClientMsgId();
2657
+ const { receipt } = await this.backend.sendReaction(group, {
2658
+ clientMsgId,
2659
+ targetClientMsgId: message.clientMsgId,
2660
+ emoji,
2661
+ op
2662
+ });
2663
+ this.reactionFold.ingest({
2664
+ targetClientMsgId: message.clientMsgId,
2665
+ actorUserId: this.backend.selfUserId,
2666
+ emoji,
2667
+ op,
2668
+ epoch: receipt.epoch,
2669
+ serverSeq: receipt.serverSeq,
2670
+ eventClientMsgId: clientMsgId
2671
+ });
2672
+ this.recomputeReactions(message.clientMsgId);
2673
+ }
2456
2674
  };
2675
+ function sameReactions(a, b) {
2676
+ const ak = Object.keys(a);
2677
+ const bk = Object.keys(b);
2678
+ if (ak.length !== bk.length) return false;
2679
+ for (const k of ak) {
2680
+ const av = a[k];
2681
+ const bv = b[k];
2682
+ if (!bv || av === void 0 || av.length !== bv.length) return false;
2683
+ for (let i = 0; i < av.length; i++) if (av[i] !== bv[i]) return false;
2684
+ }
2685
+ return true;
2686
+ }
2457
2687
 
2458
2688
  // src/messaging/delivery-source.ts
2459
2689
  var MessageHub = class {
@@ -2483,6 +2713,11 @@ var MessageHub = class {
2483
2713
  };
2484
2714
  }
2485
2715
  };
2716
+ function decodeSenderDeviceId(sender) {
2717
+ if (sender.length === 0) return null;
2718
+ const id = decodeUtf8(sender);
2719
+ return id.length > 0 ? id : null;
2720
+ }
2486
2721
  var MessageDeliverySource = class {
2487
2722
  constructor(rt, engine, hub, registry, messageStore, deviceId, selfUserId) {
2488
2723
  this.rt = rt;
@@ -2612,12 +2847,15 @@ var MessageDeliverySource = class {
2612
2847
  try {
2613
2848
  const received = await this.engine.processIncoming(fromBase64(group.rfcGroupId), blob);
2614
2849
  if (received.type === "application") {
2615
- const { text, clientMsgId, replyTo } = decodeEnvelope(received.data);
2850
+ const decoded = decodeEnvelope(received.data);
2851
+ const { text, clientMsgId, replyTo } = decoded;
2852
+ const isReaction = decoded.type === "reaction" && decoded.reaction != null;
2853
+ const senderDeviceId = row.sender_device_id ?? decodeSenderDeviceId(received.sender);
2616
2854
  const stored = {
2617
2855
  id: `${group.rfcGroupId}#${row.server_seq}`,
2618
2856
  direction: "incoming",
2619
2857
  text,
2620
- senderDeviceId: row.sender_device_id ?? null,
2858
+ senderDeviceId,
2621
2859
  epoch: row.epoch,
2622
2860
  serverSeq: row.server_seq,
2623
2861
  at: Date.now(),
@@ -2627,7 +2865,19 @@ var MessageDeliverySource = class {
2627
2865
  previewBody: replyTo.preview?.body ?? null,
2628
2866
  previewAuthorUserId: replyTo.preview?.author_user_id ?? null,
2629
2867
  previewKind: replyTo.preview?.kind ?? "text"
2630
- } : null
2868
+ } : null,
2869
+ // Thread the reaction discriminator + fields through the persisted row so
2870
+ // a reaction folded LIVE re-folds onto its target after a reload (the
2871
+ // reload-parity boundary — mirrors iOS T3). Omitted for non-reactions →
2872
+ // old rows hydrate as `'text'`/no-reaction (backward-compat).
2873
+ ...isReaction && decoded.reaction ? {
2874
+ envelopeType: "reaction",
2875
+ reaction: {
2876
+ targetClientMsgId: decoded.reaction.targetClientMsgId,
2877
+ emoji: decoded.reaction.emoji,
2878
+ op: decoded.reaction.op
2879
+ }
2880
+ } : {}
2631
2881
  };
2632
2882
  try {
2633
2883
  await this.messageStore.append(group.rfcGroupId, stored);
@@ -2638,12 +2888,14 @@ var MessageDeliverySource = class {
2638
2888
  kind: "application",
2639
2889
  group,
2640
2890
  text,
2641
- senderDeviceId: row.sender_device_id ?? null,
2891
+ senderDeviceId,
2642
2892
  epoch: row.epoch,
2643
2893
  serverSeq: row.server_seq,
2644
2894
  receivedAt: /* @__PURE__ */ new Date(),
2645
2895
  clientMsgId,
2646
- replyRef: replyTo
2896
+ replyRef: replyTo,
2897
+ envelopeType: decoded.type ?? "text",
2898
+ reaction: isReaction ? decoded.reaction : null
2647
2899
  });
2648
2900
  return true;
2649
2901
  }
@@ -4647,46 +4899,14 @@ var MessagingCoordinator = class {
4647
4899
  const r = await this.resolve();
4648
4900
  return r.groups.sendText(group, text, replyTo);
4649
4901
  }
4902
+ async sendReaction(group, args) {
4903
+ const r = await this.resolve();
4904
+ return r.groups.sendReaction(group, args);
4905
+ }
4650
4906
  async history(group, limit, before) {
4651
4907
  const r = await this.resolve();
4652
4908
  const rows = await r.messageStore.history(group.rfcGroupId, limit, before);
4653
- const lookup = /* @__PURE__ */ new Map();
4654
- for (const s of rows) {
4655
- const cid = s.clientMsgId ?? "";
4656
- if (cid && s.text !== null) {
4657
- const senderUserId = s.direction === "outgoing" ? this.selfUserId : "";
4658
- lookup.set(cid, { text: s.text, senderUserId });
4659
- }
4660
- }
4661
- return rows.map((s) => this.toChatMessage(group, s, (id) => lookup.get(id) ?? null));
4662
- }
4663
- toChatMessage(group, s, lookup) {
4664
- const clientMsgId = s.clientMsgId ?? "";
4665
- let replyTo = null;
4666
- if (s.replyTo && lookup) {
4667
- const ref = {
4668
- v: 1,
4669
- client_msg_id: s.replyTo.clientMsgId,
4670
- preview: {
4671
- kind: s.replyTo.previewKind,
4672
- author_user_id: s.replyTo.previewAuthorUserId ?? "",
4673
- body: s.replyTo.previewBody ?? void 0,
4674
- body_truncated: false
4675
- }
4676
- };
4677
- replyTo = resolveReply(ref, lookup);
4678
- }
4679
- return {
4680
- id: `${group.displayId}#${s.serverSeq}`,
4681
- kind: s.text != null ? "text" : "system",
4682
- direction: s.direction,
4683
- senderUserId: s.direction === "outgoing" ? this.selfUserId : null,
4684
- text: s.text,
4685
- serverSeq: s.serverSeq,
4686
- sentAt: new Date(s.at),
4687
- clientMsgId,
4688
- replyTo
4689
- };
4909
+ return projectHistory(group.displayId, rows, this.selfUserId);
4690
4910
  }
4691
4911
  async members(group) {
4692
4912
  const r = await this.resolve();
@@ -4763,6 +4983,64 @@ var MessagingCoordinator = class {
4763
4983
  return res.devices.map((d) => d.device_id);
4764
4984
  }
4765
4985
  };
4986
+ function projectHistory(displayId, rows, selfUserId, resolveActor) {
4987
+ const fold = new ReactionFold();
4988
+ for (const s of rows) {
4989
+ if (s.envelopeType !== "reaction" || !s.reaction) continue;
4990
+ const actor = s.direction === "outgoing" ? selfUserId : resolveActor?.(s.senderDeviceId ?? null) ?? null;
4991
+ if (actor === null) continue;
4992
+ fold.ingest({
4993
+ targetClientMsgId: s.reaction.targetClientMsgId,
4994
+ actorUserId: actor,
4995
+ emoji: s.reaction.emoji,
4996
+ op: s.reaction.op,
4997
+ epoch: s.epoch,
4998
+ serverSeq: s.serverSeq,
4999
+ eventClientMsgId: s.clientMsgId ?? `${s.id}`
5000
+ });
5001
+ }
5002
+ const lookup = /* @__PURE__ */ new Map();
5003
+ for (const s of rows) {
5004
+ if (s.envelopeType === "reaction") continue;
5005
+ const cid = s.clientMsgId ?? "";
5006
+ if (cid && s.text !== null) {
5007
+ const senderUserId = s.direction === "outgoing" ? selfUserId : "";
5008
+ lookup.set(cid, { text: s.text, senderUserId });
5009
+ }
5010
+ }
5011
+ const out = [];
5012
+ for (const s of rows) {
5013
+ if (s.envelopeType === "reaction") continue;
5014
+ const clientMsgId = s.clientMsgId ?? "";
5015
+ let replyTo = null;
5016
+ if (s.replyTo) {
5017
+ const ref = {
5018
+ v: 1,
5019
+ client_msg_id: s.replyTo.clientMsgId,
5020
+ preview: {
5021
+ kind: s.replyTo.previewKind,
5022
+ author_user_id: s.replyTo.previewAuthorUserId ?? "",
5023
+ body: s.replyTo.previewBody ?? void 0,
5024
+ body_truncated: false
5025
+ }
5026
+ };
5027
+ replyTo = resolveReply(ref, (id) => lookup.get(id) ?? null);
5028
+ }
5029
+ out.push({
5030
+ id: `${displayId}#${s.serverSeq}`,
5031
+ kind: s.text != null ? "text" : "system",
5032
+ direction: s.direction,
5033
+ senderUserId: s.direction === "outgoing" ? selfUserId : null,
5034
+ text: s.text,
5035
+ serverSeq: s.serverSeq,
5036
+ sentAt: new Date(s.at),
5037
+ clientMsgId,
5038
+ replyTo,
5039
+ reactions: clientMsgId ? fold.tally(clientMsgId) : {}
5040
+ });
5041
+ }
5042
+ return out;
5043
+ }
4766
5044
 
4767
5045
  // src/messaging/facade.ts
4768
5046
  var PalbeMessaging = class {
@@ -5615,7 +5893,7 @@ function localStorageSessionStorage(key = DEFAULT_KEY) {
5615
5893
  }
5616
5894
 
5617
5895
  // src/version.ts
5618
- var VERSION = "1.1.1";
5896
+ var VERSION = "1.2.1";
5619
5897
 
5620
5898
  // src/internal.ts
5621
5899
  function getRuntime() {