@flamingo-stack/openframe-frontend-core 0.0.750 → 0.0.752

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 (82) hide show
  1. package/dist/{chunk-OFO75R2O.cjs → chunk-35RU25PJ.cjs} +130 -130
  2. package/dist/{chunk-ALPRQ3ZX.cjs → chunk-3GG3QAPT.cjs} +15 -15
  3. package/dist/{chunk-7RCTOWBA.cjs → chunk-4OTCQEP3.cjs} +28 -28
  4. package/dist/{chunk-XJ3J4UIS.cjs → chunk-4PEG4JTM.cjs} +19 -19
  5. package/dist/{chunk-3TELPOVH.cjs → chunk-7OEVVMAU.cjs} +2 -2
  6. package/dist/{chunk-CNUZLOVA.cjs → chunk-7WEGXNNS.cjs} +40 -40
  7. package/dist/{chunk-C6LPOYDM.cjs → chunk-AG4HR6Z6.cjs} +8 -8
  8. package/dist/{chunk-V3UJ6NDR.cjs → chunk-EM4OEWCM.cjs} +171 -171
  9. package/dist/{chunk-HOEVD6EN.cjs → chunk-EUQJ7QHW.cjs} +4 -4
  10. package/dist/{chunk-FP6HAJQV.cjs → chunk-G44V3UGE.cjs} +105 -105
  11. package/dist/{chunk-2YXOD2KL.cjs → chunk-H3RYUTND.cjs} +5 -0
  12. package/dist/{chunk-JPUTILTV.cjs → chunk-IPVJAML5.cjs} +94 -94
  13. package/dist/{chunk-KVSEWACW.cjs → chunk-J5G4CF2V.cjs} +28 -28
  14. package/dist/{chunk-2J2OBP4N.cjs → chunk-JI6NRWCC.cjs} +21 -21
  15. package/dist/{chunk-4O2KYY4K.cjs → chunk-KBJSZFBZ.cjs} +3 -3
  16. package/dist/{chunk-G7SBHMRR.cjs → chunk-KHKPLOU4.cjs} +69 -39
  17. package/dist/{chunk-45YRDD7W.cjs → chunk-KUVYVAS2.cjs} +22 -22
  18. package/dist/{chunk-UGCRLRCT.cjs → chunk-NO5UJLLQ.cjs} +2 -5
  19. package/dist/{chunk-WZX26ODJ.cjs → chunk-OXCGQV6B.cjs} +152 -133
  20. package/dist/{chunk-FHT7SMA7.cjs → chunk-OXEAN3EQ.cjs} +47 -47
  21. package/dist/{chunk-E3KFEOFA.cjs → chunk-P4ODFQGA.cjs} +7 -7
  22. package/dist/{chunk-AW6GP3JK.cjs → chunk-RDH63XXW.cjs} +83 -83
  23. package/dist/{chunk-CLAJIQ7E.cjs → chunk-U2AE4UG7.cjs} +19 -19
  24. package/dist/{chunk-6KEJQR6L.cjs → chunk-VD3XBUQR.cjs} +797 -797
  25. package/dist/{chunk-4FWURR3W.cjs → chunk-VUWPLQBY.cjs} +2 -2
  26. package/dist/{chunk-YL62VAHC.cjs → chunk-WQCLN27R.cjs} +6 -6
  27. package/dist/{chunk-GVETSV7H.cjs → chunk-XADJG35G.cjs} +48 -48
  28. package/dist/{chunk-BO6ZOAPB.cjs → chunk-Y6PVZRYL.cjs} +12 -12
  29. package/dist/{chunk-DGEB5GUZ.cjs → chunk-ZVOXBSDP.cjs} +2 -2
  30. package/dist/{chunk-34TWK3JE.cjs → chunk-ZYRRRKSZ.cjs} +3 -3
  31. package/dist/{cloud-tenants-E4JSG3GH.cjs → cloud-tenants-WAOMZZQ2.cjs} +13 -13
  32. package/dist/components/case-studies/index.cjs +26 -26
  33. package/dist/components/chat/hooks/use-jetstream-dialog-subscription.d.ts +7 -5
  34. package/dist/components/chat/hooks/use-jetstream-dialog-subscription.d.ts.map +1 -1
  35. package/dist/components/chat/hooks/use-jetstream-dialog-subscription.js +33 -14
  36. package/dist/components/chat/index.cjs +8 -8
  37. package/dist/components/chat/types/api.types.d.ts +27 -8
  38. package/dist/components/chat/types/api.types.d.ts.map +1 -1
  39. package/dist/components/chat/types/network.types.d.ts +2 -1
  40. package/dist/components/chat/types/network.types.d.ts.map +1 -1
  41. package/dist/components/contact/index.cjs +14 -14
  42. package/dist/components/docs/index.cjs +17 -17
  43. package/dist/components/embeds/index.cjs +14 -14
  44. package/dist/components/faq/index.cjs +15 -15
  45. package/dist/components/features/index.cjs +13 -13
  46. package/dist/components/help-center-pages/index.cjs +123 -123
  47. package/dist/components/index.cjs +64 -64
  48. package/dist/components/loading/loading-region.d.ts.map +1 -1
  49. package/dist/components/loading/loading-region.js +2 -5
  50. package/dist/components/loading/unified-skeleton.d.ts +2 -0
  51. package/dist/components/loading/unified-skeleton.d.ts.map +1 -1
  52. package/dist/components/loading/unified-skeleton.js +5 -0
  53. package/dist/components/meeting-scheduler/index.cjs +79 -79
  54. package/dist/components/navigation/index.cjs +16 -16
  55. package/dist/components/onboarding-guides/index.cjs +16 -16
  56. package/dist/components/product-demo/index.cjs +12 -12
  57. package/dist/components/related-content/index.cjs +7 -7
  58. package/dist/components/tickets/index.cjs +19 -19
  59. package/dist/components/ui/file-manager/index.cjs +30 -30
  60. package/dist/components/ui/index.cjs +13 -13
  61. package/dist/{devices-AVRQGB2N.cjs → devices-VFEPXW2N.cjs} +14 -14
  62. package/dist/{embeddable-chat-SNYQSMS7.cjs → embeddable-chat-BYQBABDV.cjs} +74 -74
  63. package/dist/hooks/index.cjs +3 -3
  64. package/dist/index.cjs +17 -17
  65. package/dist/{knowledge-S3CNISQH.cjs → knowledge-4TE7AWZX.cjs} +14 -14
  66. package/dist/{logs-WDLOKDXT.cjs → logs-3B2P3JXN.cjs} +21 -21
  67. package/dist/nats/index.cjs +2 -2
  68. package/dist/nats/nats.d.ts +33 -7
  69. package/dist/nats/nats.d.ts.map +1 -1
  70. package/dist/nats/nats.js +41 -11
  71. package/dist/{policies-STML7NEZ.cjs → policies-DVI6V22X.cjs} +17 -17
  72. package/dist/{remote-session-ZKP2W3IS.cjs → remote-session-57DGC4X3.cjs} +6 -6
  73. package/dist/{scripts-HO53VYGX.cjs → scripts-JJ2BVYQ5.cjs} +20 -20
  74. package/dist/{software-update-4VTK7LWQ.cjs → software-update-BN23RATE.cjs} +17 -17
  75. package/dist/{tickets-board-BNW4AYFL.cjs → tickets-board-EP6L3BSV.cjs} +7 -7
  76. package/package.json +1 -1
  77. package/src/components/chat/hooks/use-jetstream-dialog-subscription.ts +59 -23
  78. package/src/components/chat/types/api.types.ts +27 -8
  79. package/src/components/chat/types/network.types.ts +2 -1
  80. package/src/components/loading/loading-region.tsx +4 -9
  81. package/src/components/loading/unified-skeleton.tsx +13 -0
  82. package/src/nats/nats.ts +91 -20
package/src/nats/nats.ts CHANGED
@@ -19,14 +19,25 @@ export type JetStreamDeliverPolicy = 'new' | 'byStartSequence';
19
19
  export interface JetStreamOrderedSubscribeOptions {
20
20
  streamName: string;
21
21
  filterSubject: string;
22
+ /**
23
+ * `'byStartSequence'` delivers every retained message from `optStartSeq` on.
24
+ * `'new'` delivers only what is published after the server creates the
25
+ * consumer, which happens after the returned promise resolves: a caller that
26
+ * acts once subscribed and must see everything that follows uses a start
27
+ * sequence instead.
28
+ */
22
29
  deliverPolicy: JetStreamDeliverPolicy;
23
- /** Required when deliverPolicy === 'byStartSequence'. */
30
+ /**
31
+ * First stream sequence to deliver, for `'byStartSequence'`; ignored for
32
+ * `'new'`. Missing or 0 starts at the first message the stream retains.
33
+ */
24
34
  optStartSeq?: number;
25
35
  /**
26
36
  * Auto-cleanup the ephemeral consumer after this idle time. Defaults to
27
- * nats.ws's own. Applies to the consumer created first: nats.ws only reads it
28
- * when the start sequence is the one it was built with, so every consumer it
29
- * recreates afterwards reverts to the library default.
37
+ * nats.ws's own. nats.ws reads it only while it builds the consumer at the
38
+ * start it was asked for — `'new'`, or `optStartSeq` 0/unset — and has
39
+ * delivered nothing yet. A consumer created from `optStartSeq` ≥ 1, and any
40
+ * recreation after a delivery, gets the library default.
30
41
  */
31
42
  inactiveThresholdMs?: number;
32
43
  /** AbortSignal to tear down the consumer. */
@@ -39,10 +50,25 @@ export interface JetStreamOrderedSubscribeOptions {
39
50
  * but everything that aged out of the stream while it was gone is
40
51
  * unrecoverable from the tail, and no connection event announces it (the
41
52
  * WebSocket never dropped). Callers that keep persisted history alongside
42
- * the live tail must refetch it here, or they keep showing a snapshot from
43
- * before the gap.
53
+ * the live tail must refetch it, or they keep showing a snapshot from before
54
+ * the gap — once the recreated consumer has caught up (`onCaughtUp`), not
55
+ * here.
44
56
  */
45
57
  onRecovered?: () => void;
58
+ /**
59
+ * The consumer has delivered everything the stream held for the subject when
60
+ * it was created. Fires once for the first consumer and once more for each
61
+ * one nats.ws recreates (`onRecovered`): after `onMessage` has handled the
62
+ * last message of that backlog, straight away when it was empty, or when
63
+ * consuming failed and nothing more will arrive. In that last case a later
64
+ * consumer replays the gap over a refetch made in the meantime, and the
65
+ * refetch on ITS `onCaughtUp` clears the copies.
66
+ *
67
+ * This is the moment to refetch persisted history after a gap. A refetch
68
+ * that lands while the backlog is still arriving merges without the turns it
69
+ * is about to replay, and the replay then renders them a second time.
70
+ */
71
+ onCaughtUp?: () => void;
46
72
  }
47
73
 
48
74
  export interface JetStreamSubscriptionHandle {
@@ -187,7 +213,7 @@ export interface NatsClient {
187
213
  /**
188
214
  * Subscribe to a JetStream subject via an ephemeral OrderedConsumer (no acks).
189
215
  * Use `optStartSeq` with `deliverPolicy: 'byStartSequence'` to resume from a known offset,
190
- * or `deliverPolicy: 'new'` to live-tail.
216
+ * or `deliverPolicy: 'new'` to live-tail (see that option for where it starts).
191
217
  */
192
218
  subscribeJetStreamOrdered(
193
219
  onMessage: (msg: JsMsg) => void | Promise<void>,
@@ -355,21 +381,14 @@ function mapNatsTypeToStatus(
355
381
  function watchForRecovery(
356
382
  iter: ConsumerMessages,
357
383
  recreatedEvent: ConsumerEvents.OrderedConsumerRecreated,
358
- onRecovered?: () => void,
384
+ onRecreated: (consumerName: string) => void,
359
385
  ): void {
360
- if (!onRecovered) return;
361
386
  void (async () => {
362
387
  try {
363
388
  const status = await iter.status();
364
389
  for await (const event of status) {
365
390
  if (event.type !== recreatedEvent) continue;
366
- try {
367
- onRecovered();
368
- } catch (e) {
369
- // A caller that throws must not take the watch down with it — this
370
- // loop is the only thing reporting recoveries for this subscription.
371
- console.warn('[nats] onRecovered threw:', e);
372
- }
391
+ onRecreated(String(event.data));
373
392
  }
374
393
  } catch {
375
394
  // Status ends with the subscription — nothing left to report.
@@ -377,6 +396,16 @@ function watchForRecovery(
377
396
  })();
378
397
  }
379
398
 
399
+ /** A caller that throws must not take down the loop reporting to it — that
400
+ * loop is the only thing reporting these events for its subscription. */
401
+ function invokeCallback(name: string, callback: (() => void) | undefined): void {
402
+ try {
403
+ callback?.();
404
+ } catch (e) {
405
+ console.warn(`[nats] ${name} threw:`, e);
406
+ }
407
+ }
408
+
380
409
  export function createNatsClient(options: NatsClientOptions): NatsClient {
381
410
  let nc: NatsConnection | null = null;
382
411
  let statusLoopAbort: AbortController | null = null;
@@ -632,8 +661,11 @@ export function createNatsClient(options: NatsClientOptions): NatsClient {
632
661
  const js = conn.jetstream();
633
662
  const consumer: Consumer = await js.consumers.get(opts.streamName, {
634
663
  filterSubjects: opts.filterSubject,
635
- deliver_policy: nats.DeliverPolicy.StartSequence,
636
- opt_start_seq: opts.optStartSeq ?? 0,
664
+ // nats.ws turns a start sequence of 0 into 1, so a 'new' that fell back to
665
+ // StartSequence replayed everything the stream retains for the subject.
666
+ ...(opts.deliverPolicy === 'new'
667
+ ? { deliver_policy: nats.DeliverPolicy.New }
668
+ : { deliver_policy: nats.DeliverPolicy.StartSequence, opt_start_seq: opts.optStartSeq ?? 0 }),
637
669
  // Milliseconds, NOT nanoseconds: nats.ws runs this through its own
638
670
  // `nanos()` before it reaches the server. Pre-converting here multiplied
639
671
  // it by 1e6 twice, putting the threshold ~9.5 years out — so the ephemeral
@@ -673,6 +705,25 @@ export function createNatsClient(options: NatsClientOptions): NatsClient {
673
705
  return { unsubscribe() {} };
674
706
  }
675
707
 
708
+ // Whether the consumer delivering now still owes `onCaughtUp` its backlog.
709
+ let backlogOwed = true;
710
+ const reportCaughtUp = () => {
711
+ if (!backlogOwed || closed) return;
712
+ backlogOwed = false;
713
+ invokeCallback('onCaughtUp', opts.onCaughtUp);
714
+ };
715
+ // An empty backlog has no message to say so: it shows only in the answer to
716
+ // CONSUMER.CREATE, which `info(true)` returns without asking the server again.
717
+ const reportIfNothingPending = async (consumerName?: string) => {
718
+ try {
719
+ const info = await consumer.info(true);
720
+ if (consumerName !== undefined && info.name !== consumerName) return;
721
+ if (info.num_pending === 0) reportCaughtUp();
722
+ } catch {
723
+ // A failed lookup reports nothing: the next message with `pending === 0` does instead.
724
+ }
725
+ };
726
+
676
727
  (async () => {
677
728
  try {
678
729
  const iter = await consumer.consume();
@@ -685,7 +736,19 @@ export function createNatsClient(options: NatsClientOptions): NatsClient {
685
736
  return;
686
737
  }
687
738
  iterRef.current = iter;
688
- watchForRecovery(iter, nats.ConsumerEvents.OrderedConsumerRecreated, opts.onRecovered);
739
+ if (opts.onRecovered || opts.onCaughtUp) {
740
+ watchForRecovery(iter, nats.ConsumerEvents.OrderedConsumerRecreated, consumerName => {
741
+ backlogOwed = true;
742
+ invokeCallback('onRecovered', opts.onRecovered);
743
+ // nats.ws announces the recreated consumer before it records it as
744
+ // the current one (a promise continuation does that), so its answer
745
+ // is read once those have run — and only if it is the one announced.
746
+ setTimeout(() => {
747
+ void reportIfNothingPending(consumerName);
748
+ }, 0);
749
+ });
750
+ }
751
+ if (opts.onCaughtUp) await reportIfNothingPending();
689
752
  for await (const msg of iter) {
690
753
  if (closed) break;
691
754
  try {
@@ -693,9 +756,17 @@ export function createNatsClient(options: NatsClientOptions): NatsClient {
693
756
  } catch (e) {
694
757
  emitStatus({ status: 'error', data: e });
695
758
  }
759
+ // `pending` is what the stream still held for this consumer when it
760
+ // sent this message: 0 means the backlog ends here.
761
+ if (msg.info.pending === 0) reportCaughtUp();
696
762
  }
697
763
  } catch (e) {
698
- if (!closed) emitStatus({ status: 'error', data: e });
764
+ if (!closed) {
765
+ emitStatus({ status: 'error', data: e });
766
+ // This consumer delivers nothing more: settle what it owed rather than
767
+ // leave the caller's history at its pre-gap snapshot (see `onCaughtUp`).
768
+ reportCaughtUp();
769
+ }
699
770
  }
700
771
  })().catch((e: unknown) => emitStatus({ status: 'error', data: e }));
701
772