@flamingo-stack/openframe-frontend-core 0.0.498 → 0.0.499

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 (109) hide show
  1. package/dist/{chunk-MVORKLWX.cjs → chunk-2CEDCSYD.cjs} +32 -32
  2. package/dist/{chunk-MVORKLWX.cjs.map → chunk-2CEDCSYD.cjs.map} +1 -1
  3. package/dist/{chunk-G6ARA2HD.js → chunk-3AXJESKA.js} +3 -3
  4. package/dist/{chunk-THC3K262.cjs → chunk-44YXQBNM.cjs} +3 -3
  5. package/dist/{chunk-THC3K262.cjs.map → chunk-44YXQBNM.cjs.map} +1 -1
  6. package/dist/{chunk-TTYJAZ7P.cjs → chunk-47LHA4QI.cjs} +3 -3
  7. package/dist/{chunk-TTYJAZ7P.cjs.map → chunk-47LHA4QI.cjs.map} +1 -1
  8. package/dist/{chunk-XI44QDCD.cjs → chunk-6QVV3OLL.cjs} +40 -40
  9. package/dist/{chunk-XI44QDCD.cjs.map → chunk-6QVV3OLL.cjs.map} +1 -1
  10. package/dist/{chunk-4NIBKEED.cjs → chunk-7DUMNMED.cjs} +12 -12
  11. package/dist/{chunk-4NIBKEED.cjs.map → chunk-7DUMNMED.cjs.map} +1 -1
  12. package/dist/{chunk-6GAJETAP.js → chunk-AEZ5BXLJ.js} +4 -4
  13. package/dist/{chunk-MF3VJKHT.js → chunk-BAMTV6GL.js} +2 -2
  14. package/dist/{chunk-2R25CGSO.cjs → chunk-EP7ELZTU.cjs} +73 -73
  15. package/dist/{chunk-2R25CGSO.cjs.map → chunk-EP7ELZTU.cjs.map} +1 -1
  16. package/dist/{chunk-ZHNWWFIM.cjs → chunk-FLZTUE2T.cjs} +5 -5
  17. package/dist/{chunk-ZHNWWFIM.cjs.map → chunk-FLZTUE2T.cjs.map} +1 -1
  18. package/dist/{chunk-P47NN7RY.js → chunk-GSONSIWG.js} +28 -3
  19. package/dist/chunk-GSONSIWG.js.map +1 -0
  20. package/dist/{chunk-6WTCJI5R.js → chunk-IUP26OXG.js} +2 -2
  21. package/dist/{chunk-W24U7ZUV.cjs → chunk-KQKU4VXB.cjs} +40 -15
  22. package/dist/chunk-KQKU4VXB.cjs.map +1 -0
  23. package/dist/{chunk-ZBTIN7RC.cjs → chunk-NSDDV4F6.cjs} +40 -40
  24. package/dist/{chunk-ZBTIN7RC.cjs.map → chunk-NSDDV4F6.cjs.map} +1 -1
  25. package/dist/{chunk-KK4M4URN.js → chunk-O7JY7LRP.js} +3 -3
  26. package/dist/{chunk-XSNKSMB3.js → chunk-Q66TP2LY.js} +5 -5
  27. package/dist/{chunk-4EHQEMN4.cjs → chunk-Q6B7VAHN.cjs} +18 -18
  28. package/dist/{chunk-4EHQEMN4.cjs.map → chunk-Q6B7VAHN.cjs.map} +1 -1
  29. package/dist/{chunk-WEUNPE3S.js → chunk-QL5YB4F7.js} +2 -2
  30. package/dist/{chunk-OYPUQJJ2.js → chunk-QUFB5SDZ.js} +41 -7
  31. package/dist/{chunk-OYPUQJJ2.js.map → chunk-QUFB5SDZ.js.map} +1 -1
  32. package/dist/{chunk-2OPD6KRB.js → chunk-QWCW4Z75.js} +5 -5
  33. package/dist/{chunk-VLWVM6ZS.js → chunk-RAL274JM.js} +3 -3
  34. package/dist/{chunk-A3Z63ZL5.cjs → chunk-RBZOUGCL.cjs} +73 -73
  35. package/dist/{chunk-A3Z63ZL5.cjs.map → chunk-RBZOUGCL.cjs.map} +1 -1
  36. package/dist/{chunk-K5HHLTSG.js → chunk-SSYE7BQC.js} +2 -2
  37. package/dist/{chunk-5ZL7PA63.js → chunk-TTJSLIXA.js} +2 -2
  38. package/dist/{chunk-W4XZ3FBZ.js → chunk-UD4IT3GY.js} +6 -6
  39. package/dist/{chunk-ZEZTITQZ.cjs → chunk-V2APV4E4.cjs} +142 -108
  40. package/dist/chunk-V2APV4E4.cjs.map +1 -0
  41. package/dist/{chunk-T67MZAQJ.cjs → chunk-W42256FC.cjs} +29 -29
  42. package/dist/{chunk-T67MZAQJ.cjs.map → chunk-W42256FC.cjs.map} +1 -1
  43. package/dist/{chunk-ZTE32A7C.cjs → chunk-WJ2S6I34.cjs} +7 -7
  44. package/dist/{chunk-ZTE32A7C.cjs.map → chunk-WJ2S6I34.cjs.map} +1 -1
  45. package/dist/{chunk-MSB3PEPP.cjs → chunk-XV22URNM.cjs} +15 -15
  46. package/dist/{chunk-MSB3PEPP.cjs.map → chunk-XV22URNM.cjs.map} +1 -1
  47. package/dist/{chunk-VOOEX4IZ.js → chunk-YDNIQLAP.js} +6 -6
  48. package/dist/components/case-studies/index.cjs +10 -10
  49. package/dist/components/case-studies/index.js +4 -4
  50. package/dist/components/chat/hooks/use-jetstream-dialog-subscription.d.ts +5 -2
  51. package/dist/components/chat/hooks/use-jetstream-dialog-subscription.d.ts.map +1 -1
  52. package/dist/components/chat/index.cjs +4 -4
  53. package/dist/components/chat/index.js +3 -3
  54. package/dist/components/chat/types/api.types.d.ts +9 -2
  55. package/dist/components/chat/types/api.types.d.ts.map +1 -1
  56. package/dist/components/contact/index.cjs +5 -5
  57. package/dist/components/contact/index.js +4 -4
  58. package/dist/components/docs/index.cjs +7 -7
  59. package/dist/components/docs/index.js +6 -6
  60. package/dist/components/embeds/index.cjs +5 -5
  61. package/dist/components/embeds/index.js +4 -4
  62. package/dist/components/faq/index.cjs +6 -6
  63. package/dist/components/faq/index.js +5 -5
  64. package/dist/components/features/index.cjs +4 -4
  65. package/dist/components/features/index.js +3 -3
  66. package/dist/components/help-center-pages/index.cjs +23 -23
  67. package/dist/components/help-center-pages/index.js +14 -14
  68. package/dist/components/index.cjs +137 -137
  69. package/dist/components/index.js +12 -12
  70. package/dist/components/navigation/index.cjs +4 -4
  71. package/dist/components/navigation/index.js +3 -3
  72. package/dist/components/onboarding-guides/index.cjs +8 -8
  73. package/dist/components/onboarding-guides/index.js +7 -7
  74. package/dist/components/related-content/index.cjs +6 -6
  75. package/dist/components/related-content/index.js +5 -5
  76. package/dist/components/tickets/index.cjs +7 -7
  77. package/dist/components/tickets/index.js +6 -6
  78. package/dist/components/ui/index.cjs +4 -4
  79. package/dist/components/ui/index.js +3 -3
  80. package/dist/hooks/index.cjs +3 -3
  81. package/dist/hooks/index.js +2 -2
  82. package/dist/index.cjs +4 -4
  83. package/dist/index.js +3 -3
  84. package/dist/nats/index.cjs +2 -2
  85. package/dist/nats/index.js +1 -1
  86. package/dist/nats/nats.d.ts +18 -1
  87. package/dist/nats/nats.d.ts.map +1 -1
  88. package/package.json +1 -1
  89. package/src/components/chat/hooks/.use-jetstream-dialog-subscription.md +7 -3
  90. package/src/components/chat/hooks/use-jetstream-dialog-subscription.ts +77 -5
  91. package/src/components/chat/types/api.types.ts +9 -2
  92. package/src/nats/.nats.md +2 -2
  93. package/src/nats/nats.ts +70 -5
  94. package/dist/chunk-P47NN7RY.js.map +0 -1
  95. package/dist/chunk-W24U7ZUV.cjs.map +0 -1
  96. package/dist/chunk-ZEZTITQZ.cjs.map +0 -1
  97. /package/dist/{chunk-G6ARA2HD.js.map → chunk-3AXJESKA.js.map} +0 -0
  98. /package/dist/{chunk-6GAJETAP.js.map → chunk-AEZ5BXLJ.js.map} +0 -0
  99. /package/dist/{chunk-MF3VJKHT.js.map → chunk-BAMTV6GL.js.map} +0 -0
  100. /package/dist/{chunk-6WTCJI5R.js.map → chunk-IUP26OXG.js.map} +0 -0
  101. /package/dist/{chunk-KK4M4URN.js.map → chunk-O7JY7LRP.js.map} +0 -0
  102. /package/dist/{chunk-XSNKSMB3.js.map → chunk-Q66TP2LY.js.map} +0 -0
  103. /package/dist/{chunk-WEUNPE3S.js.map → chunk-QL5YB4F7.js.map} +0 -0
  104. /package/dist/{chunk-2OPD6KRB.js.map → chunk-QWCW4Z75.js.map} +0 -0
  105. /package/dist/{chunk-VLWVM6ZS.js.map → chunk-RAL274JM.js.map} +0 -0
  106. /package/dist/{chunk-K5HHLTSG.js.map → chunk-SSYE7BQC.js.map} +0 -0
  107. /package/dist/{chunk-5ZL7PA63.js.map → chunk-TTJSLIXA.js.map} +0 -0
  108. /package/dist/{chunk-W4XZ3FBZ.js.map → chunk-UD4IT3GY.js.map} +0 -0
  109. /package/dist/{chunk-VOOEX4IZ.js.map → chunk-YDNIQLAP.js.map} +0 -0
@@ -14,8 +14,21 @@ import {
14
14
  type UseJetStreamDialogSubscriptionReturn,
15
15
  } from '../types'
16
16
 
17
- const DEFAULT_INACTIVE_THRESHOLD_MS = 5 * 60_000
18
17
  const DEFAULT_STREAM_NAME = 'CHAT_CHUNKS'
18
+ /**
19
+ * How long the page must have been out of sight before coming back counts as an
20
+ * absence worth resyncing for. Alt-tabbing must not churn the consumer; a
21
+ * window that sat in the tray must not come back showing a stale conversation.
22
+ */
23
+ const RESYNC_AFTER_HIDDEN_MS = 10_000
24
+ /**
25
+ * Floor between two reported recoveries. Every recovery costs the caller a
26
+ * history refetch, and a consumer that cannot hold its sequence — gap, reset,
27
+ * gap — would otherwise turn a server-side fault into a refetch storm from
28
+ * every open client. Recoveries are a repair signal, not a data feed: one per
29
+ * window is enough to close the gap.
30
+ */
31
+ const RECOVERY_REPORT_FLOOR_MS = 5_000
19
32
 
20
33
  /**
21
34
  * Subscribe to a chat dialog stream via a JetStream **ephemeral OrderedConsumer**.
@@ -26,8 +39,11 @@ const DEFAULT_STREAM_NAME = 'CHAT_CHUNKS'
26
39
  * (`DeliverPolicy.New`).
27
40
  * - On reconnect, the consumer is recreated starting from the highest stream
28
41
  * sequence we've already observed + 1, so no chunk is replayed or skipped.
29
- * - Consumer is ephemeral with `AckPolicy.None` and a 5-minute inactivity
30
- * threshold (overridable via `inactiveThresholdMs`).
42
+ * - Consumer is ephemeral with `AckPolicy.None` and the client's default
43
+ * inactivity threshold (overridable via `inactiveThresholdMs`).
44
+ * - `reconnectionCount` also counts consumer recreations and post-absence
45
+ * resyncs, not just NATS reconnects — see the counter's docs. Callers refetch
46
+ * persisted history whenever it moves.
31
47
  */
32
48
  export function useJetStreamDialogSubscription({
33
49
  enabled,
@@ -48,8 +64,15 @@ export function useJetStreamDialogSubscription({
48
64
  const [isConnected, setIsConnected] = useState(false)
49
65
  const [isSubscribed, setIsSubscribed] = useState(false)
50
66
  const [reconnectionCount, setReconnectionCount] = useState(0)
67
+ // Kept apart from reconnectionCount because only the latter drives the
68
+ // subscription effect: nats.ws has already rebuilt the consumer by the time
69
+ // it reports a recovery, so tearing ours down and recreating it would be
70
+ // churn — and churn that can feed itself, since each new consumer can report
71
+ // its own recoveries. Callers see the two summed (see the return).
72
+ const [recoveryCount, setRecoveryCount] = useState(0)
51
73
  const [currentStreamSeq, setCurrentStreamSeq] = useState<number | null>(null)
52
74
 
75
+ const lastRecoveryReportRef = useRef(0)
53
76
  const clientRef = useRef<NatsClient | null>(null)
54
77
  const subscriptionRef = useRef<JetStreamSubscriptionHandle | null>(null)
55
78
  const highestStreamSeqRef = useRef<number | null>(null)
@@ -225,6 +248,36 @@ export function useJetStreamDialogSubscription({
225
248
  setCurrentStreamSeq(null)
226
249
  }, [dialogId])
227
250
 
251
+ // Coming back into view after a real absence is treated exactly like a
252
+ // reconnect, because the page cannot tell the difference from the inside.
253
+ // While it was hidden — a tray-hidden desktop window, a background tab, a
254
+ // sleeping machine — delivery may have stopped without the socket ever
255
+ // closing and without any consumer event to show for it. Nothing else will
256
+ // report that: the tail simply stays quiet, and the conversation on screen
257
+ // stays frozen at whatever was there when the window went away (the user's
258
+ // manual fix is a page refresh, which is exactly the history refetch this
259
+ // triggers). Bumping the counter rebuilds the consumer from the last sequence
260
+ // seen AND tells callers to refetch history.
261
+ useEffect(() => {
262
+ if (!enabled) return
263
+ let hiddenSince = document.visibilityState === 'hidden' ? Date.now() : 0
264
+
265
+ const onVisibilityChange = () => {
266
+ if (document.visibilityState === 'hidden') {
267
+ hiddenSince = Date.now()
268
+ return
269
+ }
270
+ const awayMs = hiddenSince === 0 ? 0 : Date.now() - hiddenSince
271
+ hiddenSince = 0
272
+ if (awayMs >= RESYNC_AFTER_HIDDEN_MS) {
273
+ setReconnectionCount((c) => c + 1)
274
+ }
275
+ }
276
+
277
+ document.addEventListener('visibilitychange', onVisibilityChange)
278
+ return () => document.removeEventListener('visibilitychange', onVisibilityChange)
279
+ }, [enabled])
280
+
228
281
  // Subscription lifecycle: (re)create the ephemeral JetStream consumer whenever
229
282
  // we transition into a connected state for a dialog, and whenever the dialog
230
283
  // changes. On reconnect we resume from highestStreamSeq + 1.
@@ -288,8 +341,17 @@ export function useJetStreamDialogSubscription({
288
341
  filterSubject,
289
342
  deliverPolicy: startSeq != null ? 'byStartSequence' : 'new',
290
343
  optStartSeq: startSeq,
291
- inactiveThresholdMs: inactiveThresholdRef.current ?? DEFAULT_INACTIVE_THRESHOLD_MS,
344
+ // Undefined when the caller did not set one: the client owns the default,
345
+ // so it is not spelled out a second time here.
346
+ inactiveThresholdMs: inactiveThresholdRef.current,
292
347
  signal: abortController.signal,
348
+ onRecovered: () => {
349
+ if (cancelled) return
350
+ const now = Date.now()
351
+ if (now - lastRecoveryReportRef.current < RECOVERY_REPORT_FLOOR_MS) return
352
+ lastRecoveryReportRef.current = now
353
+ setRecoveryCount((c) => c + 1)
354
+ },
293
355
  },
294
356
  )
295
357
 
@@ -327,5 +389,15 @@ export function useJetStreamDialogSubscription({
327
389
  }
328
390
  }, [enabled, dialogId, isConnected, streamName, topic, reconnectionCount])
329
391
 
330
- return { isConnected, isSubscribed, reconnectionCount, currentStreamSeq }
392
+ // One counter for every way the tail comes back — reconnect, consumer
393
+ // recreation, post-absence resync — because callers do the same thing for all
394
+ // of them: refetch persisted history, since the gap may predate what the
395
+ // stream still holds. The last two are the quiet ones; no connection event
396
+ // fires for either.
397
+ return {
398
+ isConnected,
399
+ isSubscribed,
400
+ reconnectionCount: reconnectionCount + recoveryCount,
401
+ currentStreamSeq,
402
+ }
331
403
  }
@@ -128,14 +128,21 @@ export interface UseJetStreamDialogSubscriptionOptions {
128
128
  maxDelayMs?: number
129
129
  multiplier?: number
130
130
  }
131
- /** Consumer inactivity threshold in ms before NATS auto-cleans it. Default: 5 minutes. */
131
+ /** Consumer inactivity threshold in ms before NATS auto-cleans it. Defaults to the
132
+ * client's, and applies only to the first consumer — recreations use nats.ws's. */
132
133
  inactiveThresholdMs?: number
133
134
  }
134
135
 
135
136
  export interface UseJetStreamDialogSubscriptionReturn {
136
137
  isConnected: boolean
137
138
  isSubscribed: boolean
138
- /** Incremented each time the underlying NATS connection reconnects. Starts at 0. */
139
+ /**
140
+ * Incremented each time the live tail is re-established: a NATS reconnect, a
141
+ * JetStream ordered-consumer recreation, or the page returning to view after
142
+ * being hidden long enough to have missed something. All three mean the same
143
+ * thing to the caller — the tail may have skipped messages, so persisted
144
+ * history has to be refetched. Starts at 0.
145
+ */
139
146
  reconnectionCount: number
140
147
  /** Highest JetStream stream sequence observed so far (null before first delivery). */
141
148
  currentStreamSeq: number | null
package/src/nats/.nats.md CHANGED
@@ -1,4 +1,4 @@
1
- <!-- source-hash: 67f40ff2bcded544220309f5fd1f87ad -->
1
+ <!-- source-hash: ba650275f2095934d2e10402f745ef2c -->
2
2
  Browser/Tauri-compatible NATS client factory built on `nats.ws`, providing typed publish, subscribe, request-reply, and JetStream ordered consumer support with connection lifecycle management.
3
3
 
4
4
  ## Key Components
@@ -11,7 +11,7 @@ Browser/Tauri-compatible NATS client factory built on `nats.ws`, providing typed
11
11
  | `NatsClientOptions` | Connection config including servers, auth, reconnect, and exponential backoff |
12
12
  | `NatsSubscribeOptions` | Per-subscription options: queue group, max messages, abort signal |
13
13
  | `NatsPublishOptions` / `NatsRequestOptions` | Optional headers and timeout for publish/request operations |
14
- | `JetStreamOrderedSubscribeOptions` | JetStream ephemeral consumer config with deliver policy and idle threshold |
14
+ | `JetStreamOrderedSubscribeOptions` | JetStream ephemeral consumer config: deliver policy, idle threshold (milliseconds — nats.ws converts to nanos itself), and `onRecovered`, which fires when the ordered consumer had to be rebuilt and the tail may have skipped messages |
15
15
  | `NatsStatus` / `NatsStatusEvent` | Union type and event shape for connection lifecycle events |
16
16
  | `JetStreamDeliverPolicy` | `'new'` or `'byStartSequence'` for ordered consumer replay |
17
17
 
package/src/nats/nats.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import type {
2
2
  ConnectionOptions,
3
3
  Consumer,
4
+ ConsumerEvents,
4
5
  ConsumerMessages,
5
6
  JsMsg,
6
7
  MsgHdrs as NatsHeaders,
@@ -19,10 +20,27 @@ export interface JetStreamOrderedSubscribeOptions {
19
20
  deliverPolicy: JetStreamDeliverPolicy
20
21
  /** Required when deliverPolicy === 'byStartSequence'. */
21
22
  optStartSeq?: number
22
- /** Auto-cleanup the ephemeral consumer after this idle time. Default: 5 minutes. */
23
+ /**
24
+ * Auto-cleanup the ephemeral consumer after this idle time. Defaults to
25
+ * nats.ws's own. Applies to the consumer created first: nats.ws only reads it
26
+ * when the start sequence is the one it was built with, so every consumer it
27
+ * recreates afterwards reverts to the library default.
28
+ */
23
29
  inactiveThresholdMs?: number
24
30
  /** AbortSignal to tear down the consumer. */
25
31
  signal?: AbortSignal
32
+ /**
33
+ * The ordered consumer had to be rebuilt: the server dropped the ephemeral
34
+ * consumer (its inactivity threshold elapsed while the page was suspended or
35
+ * offline), heartbeats were missed, or a sequence gap was detected. nats.ws
36
+ * recreates it from the last delivered sequence, so this is NOT an error —
37
+ * but everything that aged out of the stream while it was gone is
38
+ * unrecoverable from the tail, and no connection event announces it (the
39
+ * WebSocket never dropped). Callers that keep persisted history alongside
40
+ * the live tail must refetch it here, or they keep showing a snapshot from
41
+ * before the gap.
42
+ */
43
+ onRecovered?: () => void
26
44
  }
27
45
 
28
46
  export interface JetStreamSubscriptionHandle {
@@ -270,6 +288,47 @@ function mapNatsTypeToStatus(type: unknown): NatsStatus | null {
270
288
  return null
271
289
  }
272
290
 
291
+ /**
292
+ * Report an ordered consumer rebuilding itself.
293
+ *
294
+ * nats.ws announces this on the message iterator's status channel and nowhere
295
+ * else — the iterator keeps yielding, the WebSocket never drops, and nothing
296
+ * consumes that channel unless someone asks for it. That silence is what lets a
297
+ * tail resume after a suspended page having permanently missed whatever expired
298
+ * from the stream meanwhile: the recreation resumes from the last delivered
299
+ * sequence, so the gap is invisible from the tail alone.
300
+ *
301
+ * `recreatedEvent` is nats.ws's own enum value rather than a literal of ours: a
302
+ * copy that drifted from the library would kill this signal silently, which is
303
+ * the failure mode the signal exists to prevent.
304
+ *
305
+ * The status channel is closed along with the iterator, which ends this loop.
306
+ */
307
+ function watchForRecovery(
308
+ iter: ConsumerMessages,
309
+ recreatedEvent: ConsumerEvents.OrderedConsumerRecreated,
310
+ onRecovered?: () => void,
311
+ ): void {
312
+ if (!onRecovered) return
313
+ void (async () => {
314
+ try {
315
+ const status = await iter.status()
316
+ for await (const event of status) {
317
+ if (event.type !== recreatedEvent) continue
318
+ try {
319
+ onRecovered()
320
+ } catch (e) {
321
+ // A caller that throws must not take the watch down with it — this
322
+ // loop is the only thing reporting recoveries for this subscription.
323
+ console.warn('[nats] onRecovered threw:', e)
324
+ }
325
+ }
326
+ } catch {
327
+ // Status ends with the subscription — nothing left to report.
328
+ }
329
+ })()
330
+ }
331
+
273
332
  export function createNatsClient(options: NatsClientOptions): NatsClient {
274
333
  let nc: NatsConnection | null = null
275
334
  let statusLoopAbort: AbortController | null = null
@@ -524,15 +583,20 @@ export function createNatsClient(options: NatsClientOptions): NatsClient {
524
583
  return { unsubscribe() {} }
525
584
  }
526
585
 
527
- const inactiveThresholdNs =
528
- (opts.inactiveThresholdMs ?? 5 * 60_000) * 1_000_000
529
-
530
586
  const js = conn.jetstream()
531
587
  const consumer: Consumer = await js.consumers.get(opts.streamName, {
532
588
  filterSubjects: opts.filterSubject,
533
589
  deliver_policy: nats.DeliverPolicy.StartSequence,
534
590
  opt_start_seq: opts.optStartSeq ?? 0,
535
- inactive_threshold: inactiveThresholdNs,
591
+ // Milliseconds, NOT nanoseconds: nats.ws runs this through its own
592
+ // `nanos()` before it reaches the server. Pre-converting here multiplied
593
+ // it by 1e6 twice, putting the threshold ~9.5 years out — so the ephemeral
594
+ // consumer never expired. Two consequences, both silent: every reconnect
595
+ // and dialog switch orphaned a consumer server-side, and a client that
596
+ // stopped pulling never got the `consumer deleted` that drives the ordered
597
+ // consumer's self-repair. Undefined stays undefined so nats.ws applies its
598
+ // own default rather than a copy of it.
599
+ inactive_threshold: opts.inactiveThresholdMs,
536
600
  })
537
601
 
538
602
  const iterRef: { current: ConsumerMessages | null } = { current: null }
@@ -575,6 +639,7 @@ export function createNatsClient(options: NatsClientOptions): NatsClient {
575
639
  return
576
640
  }
577
641
  iterRef.current = iter
642
+ watchForRecovery(iter, nats.ConsumerEvents.OrderedConsumerRecreated, opts.onRecovered)
578
643
  for await (const msg of iter) {
579
644
  if (closed) break
580
645
  try {
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/nats/nats.ts","../src/nats/shared-connection.ts","../src/nats/nats-provider.tsx","../src/nats/use-nats-subscription.ts"],"sourcesContent":["import type {\n ConnectionOptions,\n Consumer,\n ConsumerMessages,\n JsMsg,\n MsgHdrs as NatsHeaders,\n Msg,\n NatsConnection,\n Subscription,\n} from 'nats.ws'\n\nexport type { JsMsg, Msg, Subscription } from 'nats.ws'\n\nexport type JetStreamDeliverPolicy = 'new' | 'byStartSequence'\n\nexport interface JetStreamOrderedSubscribeOptions {\n streamName: string\n filterSubject: string\n deliverPolicy: JetStreamDeliverPolicy\n /** Required when deliverPolicy === 'byStartSequence'. */\n optStartSeq?: number\n /** Auto-cleanup the ephemeral consumer after this idle time. Default: 5 minutes. */\n inactiveThresholdMs?: number\n /** AbortSignal to tear down the consumer. */\n signal?: AbortSignal\n}\n\nexport interface JetStreamSubscriptionHandle {\n unsubscribe(): void\n}\n\nexport interface NatsClientOptions {\n /**\n * NATS server URL(s), for example:\n * - \"wss://nats.example.com:443\"\n * - [\"wss://nats-1.example.com:443\", \"wss://nats-2.example.com:443\"]\n */\n servers: string | string[]\n\n /**\n * Connection name (shows up in NATS monitoring).\n */\n name?: string\n\n /**\n * Auth options (pick one: token or user/pass).\n */\n token?: string\n user?: string\n pass?: string\n\n /**\n * Reconnect behavior.\n */\n reconnect?: boolean\n maxReconnectAttempts?: number\n reconnectTimeWaitMs?: number\n\n /**\n * Exponential backoff for reconnect delays.\n * When set, uses `reconnectDelayHandler` from nats.ws under the hood,\n * overriding `reconnectTimeWaitMs`.\n */\n exponentialBackoff?: {\n /** Initial delay in ms (default: 1000) */\n initialDelayMs?: number\n /** Maximum delay cap in ms (default: 30000) */\n maxDelayMs?: number\n /** Multiplier per attempt (default: 2) */\n multiplier?: number\n /** Add random jitter 0-50% of delay to prevent thundering herd (default: true) */\n jitter?: boolean\n }\n\n /**\n * Ping behavior (keep-alive).\n */\n pingIntervalMs?: number\n maxPingOut?: number\n\n /**\n * Optional inbox prefix (useful if you want to isolate request/reply inboxes).\n */\n inboxPrefix?: string\n\n /**\n * Connection timeout in milliseconds (maps to `nats.ws` connect option `timeout`).\n * If you see `NatsError: TIMEOUT` during connect, increase this.\n */\n connectTimeoutMs?: number\n}\n\nexport interface NatsSubscribeOptions {\n /**\n * Queue group for load-balancing messages across subscribers.\n */\n queue?: string\n\n /**\n * Auto-unsubscribe after receiving this many messages.\n */\n max?: number\n\n /**\n * Abort signal to stop message iteration and unsubscribe.\n */\n signal?: AbortSignal\n}\n\nexport type NatsHeadersInit = Record<string, string> | NatsHeaders | undefined\n\nexport interface NatsPublishOptions {\n headers?: NatsHeadersInit\n}\n\nexport interface NatsRequestOptions {\n timeoutMs?: number\n headers?: NatsHeadersInit\n}\n\nexport interface NatsSubscriptionHandle {\n readonly subscription: Subscription\n unsubscribe(): void\n}\n\nexport type NatsStatus =\n | 'connecting'\n | 'connected'\n | 'disconnected'\n | 'reconnecting'\n | 'closed'\n | 'error'\n\nexport interface NatsStatusEvent {\n status: NatsStatus\n data?: unknown\n}\n\nexport interface NatsClient {\n connect(): Promise<void>\n close(): Promise<void>\n\n isConnected(): boolean\n\n publishBytes(subject: string, payload: Uint8Array, options?: NatsPublishOptions): void\n publishString(subject: string, payload: string, options?: NatsPublishOptions): void\n publishJson<T>(subject: string, payload: T, options?: NatsPublishOptions): void\n\n requestBytes(subject: string, payload: Uint8Array, options?: NatsRequestOptions): Promise<Msg>\n requestString(subject: string, payload: string, options?: NatsRequestOptions): Promise<string>\n requestJson<TResponse, TRequest = unknown>(\n subject: string,\n payload: TRequest,\n options?: NatsRequestOptions,\n ): Promise<TResponse>\n\n subscribeBytes(\n subject: string,\n onMessage: (msg: Msg) => void | Promise<void>,\n options?: NatsSubscribeOptions,\n ): NatsSubscriptionHandle\n subscribeString(\n subject: string,\n onMessage: (payload: string, msg: Msg) => void | Promise<void>,\n options?: NatsSubscribeOptions,\n ): NatsSubscriptionHandle\n subscribeJson<T>(\n subject: string,\n onMessage: (payload: T, msg: Msg) => void | Promise<void>,\n options?: NatsSubscribeOptions,\n ): NatsSubscriptionHandle\n\n /**\n * Subscribe to a JetStream subject via an ephemeral OrderedConsumer (no acks).\n * Use `optStartSeq` with `deliverPolicy: 'byStartSequence'` to resume from a known offset,\n * or `deliverPolicy: 'new'` to live-tail.\n */\n subscribeJetStreamOrdered(\n onMessage: (msg: JsMsg) => void | Promise<void>,\n options: JetStreamOrderedSubscribeOptions,\n ): Promise<JetStreamSubscriptionHandle>\n\n onStatus(listener: (event: NatsStatusEvent) => void): () => void\n}\n\nfunction assertClientSide(): void {\n // This wrapper is meant for browser/Tauri usage via WebSockets.\n // Keep it safe to import from Next.js server bundles by throwing only when used.\n if (typeof window === 'undefined') {\n throw new Error('NATS client can only connect from the browser/runtime with WebSocket support (window is undefined).')\n }\n}\n\nasync function importNats(): Promise<typeof import('nats.ws')> {\n // Browser/Tauri only: always use the websocket client (no Node-only deps).\n return await import('nats.ws')\n}\n\nfunction toNatsHeaders(nats: typeof import('nats.ws'), init: NatsHeadersInit): NatsHeaders | undefined {\n if (!init) return undefined\n if (typeof (init as NatsHeaders).get === 'function') return init as NatsHeaders\n\n const h = nats.headers()\n for (const [k, v] of Object.entries(init as Record<string, string>)) {\n if (v !== undefined && v !== null) h.set(k, String(v))\n }\n return h\n}\n\n/** Returns a cryptographically random float in [0, 1). */\nfunction cryptoRandom(): number {\n const buf = new Uint32Array(1)\n crypto.getRandomValues(buf)\n return buf[0] / (0xffffffff + 1)\n}\n\ninterface ExponentialBackoffHandle {\n handler: () => number\n reset: () => void\n}\n\nfunction createExponentialBackoffHandler(opts: NonNullable<NatsClientOptions['exponentialBackoff']>): ExponentialBackoffHandle {\n const initialDelay = opts.initialDelayMs ?? 1000\n const maxDelay = opts.maxDelayMs ?? 30_000\n const multiplier = opts.multiplier ?? 2\n const jitter = opts.jitter ?? true\n\n let attempt = 0\n\n return {\n handler: (): number => {\n const delay = Math.min(initialDelay * multiplier ** attempt, maxDelay)\n attempt++\n return jitter ? delay * (0.5 + cryptoRandom() * 0.5) : delay\n },\n reset: () => {\n attempt = 0\n },\n }\n}\n\nfunction mapOptionsToConnectionOptions(\n opts: NatsClientOptions,\n backoff?: ExponentialBackoffHandle,\n): ConnectionOptions {\n return {\n servers: opts.servers,\n name: opts.name,\n token: opts.token,\n user: opts.user,\n pass: opts.pass,\n timeout: opts.connectTimeoutMs ?? 15000,\n reconnect: opts.reconnect ?? true,\n maxReconnectAttempts: opts.maxReconnectAttempts,\n reconnectTimeWait: opts.reconnectTimeWaitMs,\n reconnectDelayHandler: backoff?.handler,\n pingInterval: opts.pingIntervalMs,\n maxPingOut: opts.maxPingOut,\n inboxPrefix: opts.inboxPrefix,\n }\n}\n\nfunction mapNatsTypeToStatus(type: unknown): NatsStatus | null {\n const t = String(type).toLowerCase()\n if (t.includes('disconnect')) return 'disconnected'\n if (t === 'reconnecting') return 'reconnecting'\n if (t === 'reconnect' || t.includes('connect')) return 'connected'\n if (t.includes('error')) return 'error'\n if (t.includes('close')) return 'closed'\n return null\n}\n\nexport function createNatsClient(options: NatsClientOptions): NatsClient {\n let nc: NatsConnection | null = null\n let statusLoopAbort: AbortController | null = null\n let connectInFlight: Promise<void> | null = null\n\n const backoff = options.exponentialBackoff\n ? createExponentialBackoffHandler(options.exponentialBackoff)\n : undefined\n\n const statusListeners = new Set<(event: NatsStatusEvent) => void>()\n\n function emitStatus(event: NatsStatusEvent) {\n for (const listener of statusListeners) {\n try {\n listener(event)\n } catch {\n // ignore listener failures\n }\n }\n }\n\n async function connect(): Promise<void> {\n if (nc && !nc.isClosed()) return\n if (connectInFlight) return connectInFlight\n assertClientSide()\n\n connectInFlight = (async () => {\n try {\n emitStatus({ status: 'connecting' })\n\n const nats = await importNats()\n const conn = await nats.connect(mapOptionsToConnectionOptions(options, backoff))\n nc = conn\n\n emitStatus({ status: 'connected' })\n\n statusLoopAbort = new AbortController()\n const signal = statusLoopAbort.signal\n\n ;(async () => {\n try {\n for await (const s of conn.status()) {\n if (signal.aborted) return\n const mapped = mapNatsTypeToStatus((s as any)?.type)\n if (mapped) {\n if (mapped === 'connected' && backoff) {\n backoff.reset()\n }\n emitStatus({ status: mapped, data: (s as any)?.data })\n if (mapped === 'closed') {\n nc = null\n }\n }\n }\n } catch (e) {\n if (!signal.aborted) {\n emitStatus({ status: 'error', data: e })\n \n if (nc === conn && conn.isClosed()) {\n nc = null\n emitStatus({ status: 'closed' })\n }\n }\n }\n })().catch(() => {\n // ignore\n })\n } finally {\n connectInFlight = null\n }\n })()\n\n return connectInFlight\n }\n\n async function close(): Promise<void> {\n const conn = nc\n nc = null\n\n if (statusLoopAbort) {\n try {\n statusLoopAbort.abort()\n } catch {\n // ignore\n }\n statusLoopAbort = null\n }\n\n if (!conn) return\n try {\n await conn.drain()\n } finally {\n try {\n await conn.close()\n } finally {\n emitStatus({ status: 'closed' })\n }\n }\n }\n\n function requireConnection(): NatsConnection {\n if (!nc) throw new Error('NATS is not connected. Call client.connect() first.')\n return nc\n }\n\n function isConnected(): boolean {\n return Boolean(nc) && !nc!.isClosed()\n }\n\n function publishBytes(subject: string, payload: Uint8Array, opts?: NatsPublishOptions): void {\n const conn = requireConnection()\n ;(async () => {\n const nats = await importNats()\n conn.publish(subject, payload, { headers: toNatsHeaders(nats, opts?.headers) })\n })().catch((e) => emitStatus({ status: 'error', data: e }))\n }\n\n function publishString(subject: string, payload: string, opts?: NatsPublishOptions): void {\n ;(async () => {\n const nats = await importNats()\n const sc = nats.StringCodec()\n publishBytes(subject, sc.encode(payload), opts)\n })().catch((e) => emitStatus({ status: 'error', data: e }))\n }\n\n function publishJson<T>(subject: string, payload: T, opts?: NatsPublishOptions): void {\n ;(async () => {\n const nats = await importNats()\n const jc = nats.JSONCodec<T>()\n publishBytes(subject, jc.encode(payload), opts)\n })().catch((e) => emitStatus({ status: 'error', data: e }))\n }\n\n async function requestBytes(subject: string, payload: Uint8Array, opts?: NatsRequestOptions): Promise<Msg> {\n const conn = requireConnection()\n const nats = await importNats()\n const msg = await conn.request(subject, payload, {\n timeout: opts?.timeoutMs ?? 2000,\n headers: toNatsHeaders(nats, opts?.headers),\n })\n return msg\n }\n\n async function requestString(subject: string, payload: string, opts?: NatsRequestOptions): Promise<string> {\n const nats = await importNats()\n const sc = nats.StringCodec()\n const msg = await requestBytes(subject, sc.encode(payload), opts)\n return sc.decode(msg.data)\n }\n\n async function requestJson<TResponse, TRequest = unknown>(\n subject: string,\n payload: TRequest,\n opts?: NatsRequestOptions,\n ): Promise<TResponse> {\n const nats = await importNats()\n const reqCodec = nats.JSONCodec<TRequest>()\n const resCodec = nats.JSONCodec<TResponse>()\n const msg = await requestBytes(subject, reqCodec.encode(payload), opts)\n return resCodec.decode(msg.data)\n }\n\n function subscribeBytes(\n subject: string,\n onMessage: (msg: Msg) => void | Promise<void>,\n opts?: NatsSubscribeOptions,\n ): NatsSubscriptionHandle {\n const conn = requireConnection()\n const sub = conn.subscribe(subject, { queue: opts?.queue })\n if (typeof opts?.max === 'number') sub.unsubscribe(opts.max)\n\n const abortController = new AbortController()\n const signal = opts?.signal ?? abortController.signal\n\n ;(async () => {\n try {\n for await (const msg of sub) {\n if (signal.aborted) break\n await onMessage(msg)\n }\n } catch (e) {\n emitStatus({ status: 'error', data: e })\n } finally {\n try {\n sub.unsubscribe()\n } catch {\n // ignore\n }\n }\n })().catch((e) => emitStatus({ status: 'error', data: e }))\n\n return {\n subscription: sub,\n unsubscribe() {\n try {\n abortController.abort()\n } catch {\n // ignore\n }\n try {\n sub.unsubscribe()\n } catch {\n // ignore\n }\n },\n }\n }\n\n function subscribeString(\n subject: string,\n onMessage: (payload: string, msg: Msg) => void | Promise<void>,\n opts?: NatsSubscribeOptions,\n ): NatsSubscriptionHandle {\n return subscribeBytes(\n subject,\n async (msg) => {\n const nats = await importNats()\n const sc = nats.StringCodec()\n await onMessage(sc.decode(msg.data), msg)\n },\n opts,\n )\n }\n\n function subscribeJson<T>(\n subject: string,\n onMessage: (payload: T, msg: Msg) => void | Promise<void>,\n opts?: NatsSubscribeOptions,\n ): NatsSubscriptionHandle {\n return subscribeBytes(\n subject,\n async (msg) => {\n const nats = await importNats()\n const jc = nats.JSONCodec<T>()\n await onMessage(jc.decode(msg.data), msg)\n },\n opts,\n )\n }\n\n async function subscribeJetStreamOrdered(\n onMessage: (msg: JsMsg) => void | Promise<void>,\n opts: JetStreamOrderedSubscribeOptions,\n ): Promise<JetStreamSubscriptionHandle> {\n const conn = requireConnection()\n if (opts.signal?.aborted) {\n return { unsubscribe() {} }\n }\n\n const nats = await importNats()\n if (opts.signal?.aborted) {\n return { unsubscribe() {} }\n }\n\n const inactiveThresholdNs =\n (opts.inactiveThresholdMs ?? 5 * 60_000) * 1_000_000\n\n const js = conn.jetstream()\n const consumer: Consumer = await js.consumers.get(opts.streamName, {\n filterSubjects: opts.filterSubject,\n deliver_policy: nats.DeliverPolicy.StartSequence,\n opt_start_seq: opts.optStartSeq ?? 0,\n inactive_threshold: inactiveThresholdNs,\n })\n\n const iterRef: { current: ConsumerMessages | null } = { current: null }\n let closed = false\n\n const onAbort = () => {\n void teardown()\n }\n opts.signal?.addEventListener('abort', onAbort, { once: true })\n\n async function teardown(): Promise<void> {\n if (closed) return\n closed = true\n opts.signal?.removeEventListener('abort', onAbort)\n const iter = iterRef.current\n iterRef.current = null\n if (iter) {\n try {\n await iter.close()\n } catch {\n // ignore\n }\n }\n }\n\n if (opts.signal?.aborted) {\n void teardown()\n return { unsubscribe() {} }\n }\n\n ;(async () => {\n try {\n const iter = await consumer.consume()\n if (closed) {\n try {\n await iter.close()\n } catch {\n // ignore\n }\n return\n }\n iterRef.current = iter\n for await (const msg of iter) {\n if (closed) break\n try {\n await onMessage(msg)\n } catch (e) {\n emitStatus({ status: 'error', data: e })\n }\n }\n } catch (e) {\n if (!closed) emitStatus({ status: 'error', data: e })\n }\n })().catch((e) => emitStatus({ status: 'error', data: e }))\n\n return {\n unsubscribe() {\n void teardown()\n },\n }\n }\n\n function onStatus(listener: (event: NatsStatusEvent) => void): () => void {\n statusListeners.add(listener)\n return () => statusListeners.delete(listener)\n }\n\n return {\n connect,\n close,\n isConnected,\n publishBytes,\n publishString,\n publishJson,\n requestBytes,\n requestString,\n requestJson,\n subscribeBytes,\n subscribeString,\n subscribeJson,\n subscribeJetStreamOrdered,\n onStatus,\n }\n}\n","import { createNatsClient, type NatsClient, type NatsStatus, type NatsStatusEvent } from './nats'\n\nexport const NATS_DEFAULTS = {\n SHARED_CLOSE_DELAY_MS: 3000,\n CONNECT_TIMEOUT_MS: 10_000,\n PING_INTERVAL_MS: 30_000,\n MAX_PING_OUT: 3,\n RETRY_INITIAL_DELAY_MS: 1000,\n RETRY_MAX_DELAY_MS: 30_000,\n RETRY_MULTIPLIER: 2,\n} as const\n\nexport interface NatsReconnectionBackoff {\n /** Number of fast retries before exponential phase kicks in. Default: 0. */\n fastRetries?: number\n /** Delay used during the fast-retry phase. Default: RETRY_INITIAL_DELAY_MS. */\n fastRetryDelayMs?: number\n /** Base delay for the exponential phase. Default: RETRY_INITIAL_DELAY_MS. */\n initialDelayMs?: number\n /** Upper cap on any single retry delay. Default: RETRY_MAX_DELAY_MS. */\n maxDelayMs?: number\n /** Per-attempt multiplier during exponential phase. Default: RETRY_MULTIPLIER. */\n multiplier?: number\n}\n\nexport interface SharedConnection {\n wsUrl: string\n client: NatsClient\n connectPromise: Promise<void> | null\n refCount: number\n closeTimer: ReturnType<typeof setTimeout> | null\n retryTimer: ReturnType<typeof setTimeout> | null\n /**\n * Identity of the consumer driving reconnect. When set, other consumers\n * should observe status only and skip their own scheduleRetry — otherwise\n * each disconnect triggers multiple concurrent connect() calls racing over\n * connectPromise.\n */\n retryOwner: object | null\n}\n\nexport interface AcquireClientOptions {\n name?: string\n user?: string\n pass?: string\n connectTimeoutMs?: number\n pingIntervalMs?: number\n maxPingOut?: number\n}\n\nexport interface ReleaseClientOptions {\n delayMs?: number\n}\n\n// One shared connection PER URL. The previous single-slot implementation\n// force-closed whatever was connected the moment any consumer acquired a\n// DIFFERENT URL — even with live refs on it. With two chat surfaces on\n// distinct endpoints (`/ws/nats` client chat vs `/ws/nats-api` dashboard)\n// mounted at once, each acquire killed the other's socket, and the loser's\n// retry loop self-cancelled (connection identity mismatch) leaving a dead\n// subscription that silently received nothing.\nconst connections = new Map<string, SharedConnection>()\n\n/** Legacy accessor from the single-slot era: returns the first live shared\n * connection, or null. With MULTIPLE URLs connected (e.g. `/ws/nats` client\n * chat + `/ws/nats-api` dashboard mounted together) \"first\" is whichever\n * surface acquired first — an arbitrary, mount-order-dependent answer.\n * Prefer `getSharedConnectionFor(url)`; this stays only for external\n * registry-pinned consumers of the old single-connection API. */\nexport function getSharedConnection(): SharedConnection | null {\n const first = connections.values().next()\n return first.done ? null : first.value\n}\n\nexport function acquireClient(url: string, opts?: AcquireClientOptions): SharedConnection {\n let conn = connections.get(url)\n\n if (!conn) {\n const {\n name = 'openframe-frontend',\n user = 'machine',\n pass = '',\n connectTimeoutMs = NATS_DEFAULTS.CONNECT_TIMEOUT_MS,\n pingIntervalMs = NATS_DEFAULTS.PING_INTERVAL_MS,\n maxPingOut = NATS_DEFAULTS.MAX_PING_OUT,\n } = opts ?? {}\n\n const client = createNatsClient({\n servers: url,\n name,\n user,\n pass,\n connectTimeoutMs,\n reconnect: false,\n pingIntervalMs,\n maxPingOut,\n })\n\n conn = {\n wsUrl: url,\n client,\n connectPromise: null,\n refCount: 0,\n closeTimer: null,\n retryTimer: null,\n retryOwner: null,\n }\n connections.set(url, conn)\n }\n\n conn.refCount += 1\n if (conn.closeTimer) {\n clearTimeout(conn.closeTimer)\n conn.closeTimer = null\n }\n return conn\n}\n\nexport function releaseClient(url: string, opts?: ReleaseClientOptions): void {\n const conn = connections.get(url)\n if (!conn) return\n\n conn.refCount = Math.max(0, conn.refCount - 1)\n if (conn.refCount > 0) return\n\n const delay = opts?.delayMs ?? NATS_DEFAULTS.SHARED_CLOSE_DELAY_MS\n conn.closeTimer = setTimeout(() => {\n conn.closeTimer = null\n // A new acquire may have raced in during the grace period.\n if (conn.refCount > 0) return\n if (connections.get(url) === conn) {\n connections.delete(url)\n }\n if (conn.retryTimer) {\n clearTimeout(conn.retryTimer)\n conn.retryTimer = null\n }\n void conn.client.close().catch(() => {})\n }, delay)\n}\n\nexport function getSharedConnectionFor(url: string | null | undefined): SharedConnection | null {\n if (!url) return null\n return connections.get(url) ?? null\n}\n\n// ---------------------------------------------------------------------------\n// Connection lifecycle: retry + status loop, shared by NatsProvider and the\n// chat hooks. Each consumer that wants to drive reconnect creates an\n// ownerToken and calls startConnectionLifecycle(). The first caller to claim\n// retryOwner runs the actual retry loop; subsequent claimants observe status\n// only. When the owner unmounts and releases retryOwner, the next status\n// event lets a surviving consumer pick up ownership opportunistically.\n// ---------------------------------------------------------------------------\n\nexport interface ConnectionLifecycleOptions {\n conn: SharedConnection\n wsUrl: string\n onBeforeReconnect?: () => Promise<void> | void\n backoff?: NatsReconnectionBackoff\n getFreshUrl: () => string | null\n /** Called on every status change (after closed-guard). */\n onStatusChange?: (status: NatsStatus, evt: NatsStatusEvent) => void\n /**\n * Decide which statuses should trigger a retry attempt. Defaults to closed +\n * disconnected. Override to skip 'error' (JetStream protocol errors that\n * don't close the WS) or include it.\n */\n shouldRetryOn?: (status: NatsStatus) => boolean\n}\n\nexport interface ConnectionLifecycleHandle {\n /** Stop observing status, clear any pending retry, release ownership if held. */\n stop(): void\n}\n\nconst defaultShouldRetryOn = (status: NatsStatus) => status === 'closed' || status === 'disconnected'\n\nexport function startConnectionLifecycle(options: ConnectionLifecycleOptions): ConnectionLifecycleHandle {\n const { conn, wsUrl } = options\n // Each lifecycle gets its own identity for retry ownership. The first lifecycle to claim\n // an unowned connection drives reconnect; later attachers observe status only until the\n // owner releases (see opportunistic claim in scheduleRetry).\n const ownerToken = {}\n if (!conn.retryOwner) conn.retryOwner = ownerToken\n\n let closed = false\n let retryAttempt = 0\n\n function emitSynthetic(status: NatsStatus) {\n if (closed) return\n options.onStatusChange?.(status, { status })\n if (status === 'connected') {\n retryAttempt = 0\n }\n }\n\n function scheduleRetry() {\n if (closed) return\n if (getSharedConnectionFor(wsUrl) !== conn) return\n if (!conn.retryOwner) conn.retryOwner = ownerToken\n if (conn.retryOwner !== ownerToken) return\n\n if (conn.retryTimer) {\n clearTimeout(conn.retryTimer)\n conn.retryTimer = null\n }\n\n const cfg = options.backoff ?? {}\n const fastRetries = cfg.fastRetries ?? 0\n const fastDelay = cfg.fastRetryDelayMs ?? NATS_DEFAULTS.RETRY_INITIAL_DELAY_MS\n const baseDelay = cfg.initialDelayMs ?? NATS_DEFAULTS.RETRY_INITIAL_DELAY_MS\n const maxDelay = cfg.maxDelayMs ?? NATS_DEFAULTS.RETRY_MAX_DELAY_MS\n const multiplier = cfg.multiplier ?? NATS_DEFAULTS.RETRY_MULTIPLIER\n\n const delay =\n retryAttempt < fastRetries\n ? fastDelay\n : Math.min(baseDelay * multiplier ** (retryAttempt - fastRetries), maxDelay)\n const jitteredDelay = delay * (0.5 + Math.random() * 0.5)\n retryAttempt++\n\n conn.retryTimer = setTimeout(async () => {\n conn.retryTimer = null\n if (closed) return\n if (getSharedConnectionFor(wsUrl) !== conn) return\n\n try {\n await options.onBeforeReconnect?.()\n } catch {\n // continue regardless of token-refresh outcome\n }\n if (closed) return\n if (getSharedConnectionFor(wsUrl) !== conn) return\n\n const freshUrl = options.getFreshUrl()\n if (freshUrl !== wsUrl) return\n\n try {\n conn.connectPromise = null\n conn.connectPromise = conn.client.connect()\n await conn.connectPromise\n if (!closed && getSharedConnectionFor(wsUrl) === conn) {\n retryAttempt = 0\n }\n } catch {\n conn.connectPromise = null\n if (!closed && getSharedConnectionFor(wsUrl) === conn) {\n scheduleRetry()\n }\n }\n }, jitteredDelay)\n }\n\n const shouldRetryOn = options.shouldRetryOn ?? defaultShouldRetryOn\n\n const unsubStatus = conn.client.onStatus((evt) => {\n if (closed) return\n options.onStatusChange?.(evt.status, evt)\n if (evt.status === 'connected') {\n retryAttempt = 0\n }\n if (shouldRetryOn(evt.status)) {\n scheduleRetry()\n }\n })\n\n if (conn.client.isConnected()) {\n emitSynthetic('connected')\n }\n\n void (async () => {\n try {\n conn.connectPromise ||= conn.client.connect()\n await conn.connectPromise\n } catch {\n conn.connectPromise = null\n if (closed) return\n\n emitSynthetic('disconnected')\n scheduleRetry()\n }\n })()\n\n return {\n stop() {\n closed = true\n unsubStatus()\n if (conn.retryTimer) {\n clearTimeout(conn.retryTimer)\n conn.retryTimer = null\n }\n if (conn.retryOwner === ownerToken) {\n conn.retryOwner = null\n }\n },\n }\n}\n","'use client'\n\nimport * as React from 'react'\nimport type { NatsClient, NatsStatus } from './nats'\nimport {\n acquireClient,\n releaseClient,\n startConnectionLifecycle,\n type AcquireClientOptions,\n type NatsReconnectionBackoff,\n} from './shared-connection'\n\nexport type { NatsReconnectionBackoff } from './shared-connection'\n\nexport interface NatsProviderProps {\n children: React.ReactNode\n /** Return the current NATS WebSocket URL (or null when not yet available, e.g. unauthenticated). */\n getWsUrl: () => string | null\n /** Called before each reconnect attempt. */\n onBeforeReconnect?: () => Promise<void> | void\n clientConfig?: AcquireClientOptions\n reconnectionBackoff?: NatsReconnectionBackoff\n /**\n * Bump this to force re-evaluating `getWsUrl()` (e.g. when auth state flips).\n * Provider does not subscribe to external auth state by itself.\n */\n urlRevision?: unknown\n}\n\nexport interface NatsContextValue {\n client: NatsClient | null\n status: NatsStatus\n isReady: boolean\n reconnectionCount: number\n}\n\nconst NatsContext = React.createContext<NatsContextValue | null>(null)\n\nexport function NatsProvider({\n children,\n getWsUrl,\n onBeforeReconnect,\n clientConfig,\n reconnectionBackoff,\n urlRevision,\n}: NatsProviderProps) {\n const [client, setClient] = React.useState<NatsClient | null>(null)\n const [status, setStatus] = React.useState<NatsStatus>('closed')\n const [reconnectionCount, setReconnectionCount] = React.useState(0)\n\n const getWsUrlRef = React.useRef(getWsUrl)\n React.useEffect(() => {\n getWsUrlRef.current = getWsUrl\n }, [getWsUrl])\n\n const onBeforeReconnectRef = React.useRef(onBeforeReconnect)\n React.useEffect(() => {\n onBeforeReconnectRef.current = onBeforeReconnect\n }, [onBeforeReconnect])\n\n const reconnectionBackoffRef = React.useRef(reconnectionBackoff)\n React.useEffect(() => {\n reconnectionBackoffRef.current = reconnectionBackoff\n }, [reconnectionBackoff])\n\n const clientConfigRef = React.useRef(clientConfig)\n React.useEffect(() => {\n clientConfigRef.current = clientConfig\n }, [clientConfig])\n\n const heldUrlRef = React.useRef<string | null>(null)\n const hadConnectionBeforeRef = React.useRef(false)\n\n React.useEffect(() => {\n const wsUrl = getWsUrlRef.current()\n\n if (!wsUrl) {\n if (heldUrlRef.current) {\n releaseClient(heldUrlRef.current)\n heldUrlRef.current = null\n setClient(null)\n setStatus('closed')\n }\n return\n }\n\n if (heldUrlRef.current && heldUrlRef.current !== wsUrl) {\n releaseClient(heldUrlRef.current)\n heldUrlRef.current = null\n }\n\n const conn = acquireClient(wsUrl, clientConfigRef.current)\n heldUrlRef.current = wsUrl\n setClient(conn.client)\n setStatus(conn.client.isConnected() ? 'connected' : 'connecting')\n\n const lifecycle = startConnectionLifecycle({\n conn,\n wsUrl,\n onBeforeReconnect: () => onBeforeReconnectRef.current?.(),\n backoff: reconnectionBackoffRef.current,\n getFreshUrl: () => getWsUrlRef.current(),\n onStatusChange: (newStatus) => {\n if (newStatus === 'error') return\n setStatus(newStatus)\n if (newStatus === 'connected') {\n if (hadConnectionBeforeRef.current) {\n setReconnectionCount((c) => c + 1)\n }\n hadConnectionBeforeRef.current = true\n }\n },\n })\n\n return () => {\n lifecycle.stop()\n if (heldUrlRef.current) {\n releaseClient(heldUrlRef.current)\n heldUrlRef.current = null\n }\n setClient(null)\n setStatus('closed')\n }\n }, [urlRevision])\n\n const value = React.useMemo<NatsContextValue>(\n () => ({\n client,\n status,\n isReady: status === 'connected' && client !== null,\n reconnectionCount,\n }),\n [client, status, reconnectionCount],\n )\n\n return <NatsContext.Provider value={value}>{children}</NatsContext.Provider>\n}\n\nexport function useNats(): NatsContextValue {\n const ctx = React.useContext(NatsContext)\n if (!ctx) throw new Error('useNats must be used inside <NatsProvider>')\n return ctx\n}\n\nexport function useOptionalNats(): NatsContextValue | null {\n return React.useContext(NatsContext)\n}\n","'use client'\n\nimport * as React from 'react'\nimport type { JsMsg, Msg, NatsSubscribeOptions } from './nats'\nimport { useOptionalNats } from './nats-provider'\n\nexport interface UseNatsSubscriptionOptions extends NatsSubscribeOptions {\n enabled?: boolean\n}\n\nexport interface UseNatsSubscriptionReturn {\n isSubscribed: boolean\n isReady: boolean\n}\n\n/**\n * Subscribe to a NATS subject using the shared connection from <NatsProvider>.\n * Automatically (re)subscribes when the connection becomes ready, when the\n * subject changes, and after reconnections.\n */\nexport function useNatsSubscription(\n subject: string | null,\n onMessage: (msg: Msg) => void | Promise<void>,\n options?: UseNatsSubscriptionOptions,\n): UseNatsSubscriptionReturn {\n const nats = useOptionalNats()\n const handlerRef = React.useRef(onMessage)\n React.useEffect(() => {\n handlerRef.current = onMessage\n }, [onMessage])\n\n const [isSubscribed, setIsSubscribed] = React.useState(false)\n\n const enabled = options?.enabled !== false\n const queue = options?.queue\n const max = options?.max\n const reconnectionCount = nats?.reconnectionCount ?? 0\n const isReady = !!nats?.isReady\n const client = nats?.client ?? null\n\n React.useEffect(() => {\n if (!client || !isReady || !subject || !enabled) {\n setIsSubscribed(false)\n return\n }\n\n const sub = client.subscribeBytes(\n subject,\n (msg) => handlerRef.current(msg),\n { queue, max },\n )\n setIsSubscribed(true)\n\n return () => {\n setIsSubscribed(false)\n try {\n sub.unsubscribe()\n } catch {\n // ignore\n }\n }\n // reconnectionCount intentionally in deps: re-subscribe after reconnect\n }, [client, isReady, subject, enabled, queue, max, reconnectionCount])\n\n return { isSubscribed, isReady }\n}\n\nexport type UseNatsJsonSubscriptionOptions = UseNatsSubscriptionOptions\n\nexport function useNatsJsonSubscription<T = unknown>(\n subject: string | null,\n onPayload: (payload: T, msg: Msg) => void | Promise<void>,\n options?: UseNatsJsonSubscriptionOptions,\n): UseNatsSubscriptionReturn {\n const handlerRef = React.useRef(onPayload)\n React.useEffect(() => {\n handlerRef.current = onPayload\n }, [onPayload])\n\n const decoderRef = React.useRef<TextDecoder | null>(null)\n if (!decoderRef.current && typeof TextDecoder !== 'undefined') {\n decoderRef.current = new TextDecoder()\n }\n\n const wrapped = React.useCallback(async (msg: Msg) => {\n const decoder = decoderRef.current\n if (!decoder) return\n try {\n const parsed = JSON.parse(decoder.decode(msg.data)) as T\n await handlerRef.current(parsed, msg)\n } catch {\n // ignore malformed payloads\n }\n }, [])\n\n return useNatsSubscription(subject, wrapped, options)\n}\n\nexport type NatsJsMsg = JsMsg\n"],"mappings":"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","names":["React"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["/home/runner/work/openframe-oss-lib/openframe-oss-lib/openframe-frontend-core/dist/chunk-W24U7ZUV.cjs","../src/nats/nats.ts","../src/nats/shared-connection.ts","../src/nats/nats-provider.tsx","../src/nats/use-nats-subscription.ts"],"names":[],"mappings":"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","file":"/home/runner/work/openframe-oss-lib/openframe-oss-lib/openframe-frontend-core/dist/chunk-W24U7ZUV.cjs","sourcesContent":[null,"import type {\n ConnectionOptions,\n Consumer,\n ConsumerMessages,\n JsMsg,\n MsgHdrs as NatsHeaders,\n Msg,\n NatsConnection,\n Subscription,\n} from 'nats.ws'\n\nexport type { JsMsg, Msg, Subscription } from 'nats.ws'\n\nexport type JetStreamDeliverPolicy = 'new' | 'byStartSequence'\n\nexport interface JetStreamOrderedSubscribeOptions {\n streamName: string\n filterSubject: string\n deliverPolicy: JetStreamDeliverPolicy\n /** Required when deliverPolicy === 'byStartSequence'. */\n optStartSeq?: number\n /** Auto-cleanup the ephemeral consumer after this idle time. Default: 5 minutes. */\n inactiveThresholdMs?: number\n /** AbortSignal to tear down the consumer. */\n signal?: AbortSignal\n}\n\nexport interface JetStreamSubscriptionHandle {\n unsubscribe(): void\n}\n\nexport interface NatsClientOptions {\n /**\n * NATS server URL(s), for example:\n * - \"wss://nats.example.com:443\"\n * - [\"wss://nats-1.example.com:443\", \"wss://nats-2.example.com:443\"]\n */\n servers: string | string[]\n\n /**\n * Connection name (shows up in NATS monitoring).\n */\n name?: string\n\n /**\n * Auth options (pick one: token or user/pass).\n */\n token?: string\n user?: string\n pass?: string\n\n /**\n * Reconnect behavior.\n */\n reconnect?: boolean\n maxReconnectAttempts?: number\n reconnectTimeWaitMs?: number\n\n /**\n * Exponential backoff for reconnect delays.\n * When set, uses `reconnectDelayHandler` from nats.ws under the hood,\n * overriding `reconnectTimeWaitMs`.\n */\n exponentialBackoff?: {\n /** Initial delay in ms (default: 1000) */\n initialDelayMs?: number\n /** Maximum delay cap in ms (default: 30000) */\n maxDelayMs?: number\n /** Multiplier per attempt (default: 2) */\n multiplier?: number\n /** Add random jitter 0-50% of delay to prevent thundering herd (default: true) */\n jitter?: boolean\n }\n\n /**\n * Ping behavior (keep-alive).\n */\n pingIntervalMs?: number\n maxPingOut?: number\n\n /**\n * Optional inbox prefix (useful if you want to isolate request/reply inboxes).\n */\n inboxPrefix?: string\n\n /**\n * Connection timeout in milliseconds (maps to `nats.ws` connect option `timeout`).\n * If you see `NatsError: TIMEOUT` during connect, increase this.\n */\n connectTimeoutMs?: number\n}\n\nexport interface NatsSubscribeOptions {\n /**\n * Queue group for load-balancing messages across subscribers.\n */\n queue?: string\n\n /**\n * Auto-unsubscribe after receiving this many messages.\n */\n max?: number\n\n /**\n * Abort signal to stop message iteration and unsubscribe.\n */\n signal?: AbortSignal\n}\n\nexport type NatsHeadersInit = Record<string, string> | NatsHeaders | undefined\n\nexport interface NatsPublishOptions {\n headers?: NatsHeadersInit\n}\n\nexport interface NatsRequestOptions {\n timeoutMs?: number\n headers?: NatsHeadersInit\n}\n\nexport interface NatsSubscriptionHandle {\n readonly subscription: Subscription\n unsubscribe(): void\n}\n\nexport type NatsStatus =\n | 'connecting'\n | 'connected'\n | 'disconnected'\n | 'reconnecting'\n | 'closed'\n | 'error'\n\nexport interface NatsStatusEvent {\n status: NatsStatus\n data?: unknown\n}\n\nexport interface NatsClient {\n connect(): Promise<void>\n close(): Promise<void>\n\n isConnected(): boolean\n\n publishBytes(subject: string, payload: Uint8Array, options?: NatsPublishOptions): void\n publishString(subject: string, payload: string, options?: NatsPublishOptions): void\n publishJson<T>(subject: string, payload: T, options?: NatsPublishOptions): void\n\n requestBytes(subject: string, payload: Uint8Array, options?: NatsRequestOptions): Promise<Msg>\n requestString(subject: string, payload: string, options?: NatsRequestOptions): Promise<string>\n requestJson<TResponse, TRequest = unknown>(\n subject: string,\n payload: TRequest,\n options?: NatsRequestOptions,\n ): Promise<TResponse>\n\n subscribeBytes(\n subject: string,\n onMessage: (msg: Msg) => void | Promise<void>,\n options?: NatsSubscribeOptions,\n ): NatsSubscriptionHandle\n subscribeString(\n subject: string,\n onMessage: (payload: string, msg: Msg) => void | Promise<void>,\n options?: NatsSubscribeOptions,\n ): NatsSubscriptionHandle\n subscribeJson<T>(\n subject: string,\n onMessage: (payload: T, msg: Msg) => void | Promise<void>,\n options?: NatsSubscribeOptions,\n ): NatsSubscriptionHandle\n\n /**\n * Subscribe to a JetStream subject via an ephemeral OrderedConsumer (no acks).\n * Use `optStartSeq` with `deliverPolicy: 'byStartSequence'` to resume from a known offset,\n * or `deliverPolicy: 'new'` to live-tail.\n */\n subscribeJetStreamOrdered(\n onMessage: (msg: JsMsg) => void | Promise<void>,\n options: JetStreamOrderedSubscribeOptions,\n ): Promise<JetStreamSubscriptionHandle>\n\n onStatus(listener: (event: NatsStatusEvent) => void): () => void\n}\n\nfunction assertClientSide(): void {\n // This wrapper is meant for browser/Tauri usage via WebSockets.\n // Keep it safe to import from Next.js server bundles by throwing only when used.\n if (typeof window === 'undefined') {\n throw new Error('NATS client can only connect from the browser/runtime with WebSocket support (window is undefined).')\n }\n}\n\nasync function importNats(): Promise<typeof import('nats.ws')> {\n // Browser/Tauri only: always use the websocket client (no Node-only deps).\n return await import('nats.ws')\n}\n\nfunction toNatsHeaders(nats: typeof import('nats.ws'), init: NatsHeadersInit): NatsHeaders | undefined {\n if (!init) return undefined\n if (typeof (init as NatsHeaders).get === 'function') return init as NatsHeaders\n\n const h = nats.headers()\n for (const [k, v] of Object.entries(init as Record<string, string>)) {\n if (v !== undefined && v !== null) h.set(k, String(v))\n }\n return h\n}\n\n/** Returns a cryptographically random float in [0, 1). */\nfunction cryptoRandom(): number {\n const buf = new Uint32Array(1)\n crypto.getRandomValues(buf)\n return buf[0] / (0xffffffff + 1)\n}\n\ninterface ExponentialBackoffHandle {\n handler: () => number\n reset: () => void\n}\n\nfunction createExponentialBackoffHandler(opts: NonNullable<NatsClientOptions['exponentialBackoff']>): ExponentialBackoffHandle {\n const initialDelay = opts.initialDelayMs ?? 1000\n const maxDelay = opts.maxDelayMs ?? 30_000\n const multiplier = opts.multiplier ?? 2\n const jitter = opts.jitter ?? true\n\n let attempt = 0\n\n return {\n handler: (): number => {\n const delay = Math.min(initialDelay * multiplier ** attempt, maxDelay)\n attempt++\n return jitter ? delay * (0.5 + cryptoRandom() * 0.5) : delay\n },\n reset: () => {\n attempt = 0\n },\n }\n}\n\nfunction mapOptionsToConnectionOptions(\n opts: NatsClientOptions,\n backoff?: ExponentialBackoffHandle,\n): ConnectionOptions {\n return {\n servers: opts.servers,\n name: opts.name,\n token: opts.token,\n user: opts.user,\n pass: opts.pass,\n timeout: opts.connectTimeoutMs ?? 15000,\n reconnect: opts.reconnect ?? true,\n maxReconnectAttempts: opts.maxReconnectAttempts,\n reconnectTimeWait: opts.reconnectTimeWaitMs,\n reconnectDelayHandler: backoff?.handler,\n pingInterval: opts.pingIntervalMs,\n maxPingOut: opts.maxPingOut,\n inboxPrefix: opts.inboxPrefix,\n }\n}\n\nfunction mapNatsTypeToStatus(type: unknown): NatsStatus | null {\n const t = String(type).toLowerCase()\n if (t.includes('disconnect')) return 'disconnected'\n if (t === 'reconnecting') return 'reconnecting'\n if (t === 'reconnect' || t.includes('connect')) return 'connected'\n if (t.includes('error')) return 'error'\n if (t.includes('close')) return 'closed'\n return null\n}\n\nexport function createNatsClient(options: NatsClientOptions): NatsClient {\n let nc: NatsConnection | null = null\n let statusLoopAbort: AbortController | null = null\n let connectInFlight: Promise<void> | null = null\n\n const backoff = options.exponentialBackoff\n ? createExponentialBackoffHandler(options.exponentialBackoff)\n : undefined\n\n const statusListeners = new Set<(event: NatsStatusEvent) => void>()\n\n function emitStatus(event: NatsStatusEvent) {\n for (const listener of statusListeners) {\n try {\n listener(event)\n } catch {\n // ignore listener failures\n }\n }\n }\n\n async function connect(): Promise<void> {\n if (nc && !nc.isClosed()) return\n if (connectInFlight) return connectInFlight\n assertClientSide()\n\n connectInFlight = (async () => {\n try {\n emitStatus({ status: 'connecting' })\n\n const nats = await importNats()\n const conn = await nats.connect(mapOptionsToConnectionOptions(options, backoff))\n nc = conn\n\n emitStatus({ status: 'connected' })\n\n statusLoopAbort = new AbortController()\n const signal = statusLoopAbort.signal\n\n ;(async () => {\n try {\n for await (const s of conn.status()) {\n if (signal.aborted) return\n const mapped = mapNatsTypeToStatus((s as any)?.type)\n if (mapped) {\n if (mapped === 'connected' && backoff) {\n backoff.reset()\n }\n emitStatus({ status: mapped, data: (s as any)?.data })\n if (mapped === 'closed') {\n nc = null\n }\n }\n }\n } catch (e) {\n if (!signal.aborted) {\n emitStatus({ status: 'error', data: e })\n \n if (nc === conn && conn.isClosed()) {\n nc = null\n emitStatus({ status: 'closed' })\n }\n }\n }\n })().catch(() => {\n // ignore\n })\n } finally {\n connectInFlight = null\n }\n })()\n\n return connectInFlight\n }\n\n async function close(): Promise<void> {\n const conn = nc\n nc = null\n\n if (statusLoopAbort) {\n try {\n statusLoopAbort.abort()\n } catch {\n // ignore\n }\n statusLoopAbort = null\n }\n\n if (!conn) return\n try {\n await conn.drain()\n } finally {\n try {\n await conn.close()\n } finally {\n emitStatus({ status: 'closed' })\n }\n }\n }\n\n function requireConnection(): NatsConnection {\n if (!nc) throw new Error('NATS is not connected. Call client.connect() first.')\n return nc\n }\n\n function isConnected(): boolean {\n return Boolean(nc) && !nc!.isClosed()\n }\n\n function publishBytes(subject: string, payload: Uint8Array, opts?: NatsPublishOptions): void {\n const conn = requireConnection()\n ;(async () => {\n const nats = await importNats()\n conn.publish(subject, payload, { headers: toNatsHeaders(nats, opts?.headers) })\n })().catch((e) => emitStatus({ status: 'error', data: e }))\n }\n\n function publishString(subject: string, payload: string, opts?: NatsPublishOptions): void {\n ;(async () => {\n const nats = await importNats()\n const sc = nats.StringCodec()\n publishBytes(subject, sc.encode(payload), opts)\n })().catch((e) => emitStatus({ status: 'error', data: e }))\n }\n\n function publishJson<T>(subject: string, payload: T, opts?: NatsPublishOptions): void {\n ;(async () => {\n const nats = await importNats()\n const jc = nats.JSONCodec<T>()\n publishBytes(subject, jc.encode(payload), opts)\n })().catch((e) => emitStatus({ status: 'error', data: e }))\n }\n\n async function requestBytes(subject: string, payload: Uint8Array, opts?: NatsRequestOptions): Promise<Msg> {\n const conn = requireConnection()\n const nats = await importNats()\n const msg = await conn.request(subject, payload, {\n timeout: opts?.timeoutMs ?? 2000,\n headers: toNatsHeaders(nats, opts?.headers),\n })\n return msg\n }\n\n async function requestString(subject: string, payload: string, opts?: NatsRequestOptions): Promise<string> {\n const nats = await importNats()\n const sc = nats.StringCodec()\n const msg = await requestBytes(subject, sc.encode(payload), opts)\n return sc.decode(msg.data)\n }\n\n async function requestJson<TResponse, TRequest = unknown>(\n subject: string,\n payload: TRequest,\n opts?: NatsRequestOptions,\n ): Promise<TResponse> {\n const nats = await importNats()\n const reqCodec = nats.JSONCodec<TRequest>()\n const resCodec = nats.JSONCodec<TResponse>()\n const msg = await requestBytes(subject, reqCodec.encode(payload), opts)\n return resCodec.decode(msg.data)\n }\n\n function subscribeBytes(\n subject: string,\n onMessage: (msg: Msg) => void | Promise<void>,\n opts?: NatsSubscribeOptions,\n ): NatsSubscriptionHandle {\n const conn = requireConnection()\n const sub = conn.subscribe(subject, { queue: opts?.queue })\n if (typeof opts?.max === 'number') sub.unsubscribe(opts.max)\n\n const abortController = new AbortController()\n const signal = opts?.signal ?? abortController.signal\n\n ;(async () => {\n try {\n for await (const msg of sub) {\n if (signal.aborted) break\n await onMessage(msg)\n }\n } catch (e) {\n emitStatus({ status: 'error', data: e })\n } finally {\n try {\n sub.unsubscribe()\n } catch {\n // ignore\n }\n }\n })().catch((e) => emitStatus({ status: 'error', data: e }))\n\n return {\n subscription: sub,\n unsubscribe() {\n try {\n abortController.abort()\n } catch {\n // ignore\n }\n try {\n sub.unsubscribe()\n } catch {\n // ignore\n }\n },\n }\n }\n\n function subscribeString(\n subject: string,\n onMessage: (payload: string, msg: Msg) => void | Promise<void>,\n opts?: NatsSubscribeOptions,\n ): NatsSubscriptionHandle {\n return subscribeBytes(\n subject,\n async (msg) => {\n const nats = await importNats()\n const sc = nats.StringCodec()\n await onMessage(sc.decode(msg.data), msg)\n },\n opts,\n )\n }\n\n function subscribeJson<T>(\n subject: string,\n onMessage: (payload: T, msg: Msg) => void | Promise<void>,\n opts?: NatsSubscribeOptions,\n ): NatsSubscriptionHandle {\n return subscribeBytes(\n subject,\n async (msg) => {\n const nats = await importNats()\n const jc = nats.JSONCodec<T>()\n await onMessage(jc.decode(msg.data), msg)\n },\n opts,\n )\n }\n\n async function subscribeJetStreamOrdered(\n onMessage: (msg: JsMsg) => void | Promise<void>,\n opts: JetStreamOrderedSubscribeOptions,\n ): Promise<JetStreamSubscriptionHandle> {\n const conn = requireConnection()\n if (opts.signal?.aborted) {\n return { unsubscribe() {} }\n }\n\n const nats = await importNats()\n if (opts.signal?.aborted) {\n return { unsubscribe() {} }\n }\n\n const inactiveThresholdNs =\n (opts.inactiveThresholdMs ?? 5 * 60_000) * 1_000_000\n\n const js = conn.jetstream()\n const consumer: Consumer = await js.consumers.get(opts.streamName, {\n filterSubjects: opts.filterSubject,\n deliver_policy: nats.DeliverPolicy.StartSequence,\n opt_start_seq: opts.optStartSeq ?? 0,\n inactive_threshold: inactiveThresholdNs,\n })\n\n const iterRef: { current: ConsumerMessages | null } = { current: null }\n let closed = false\n\n const onAbort = () => {\n void teardown()\n }\n opts.signal?.addEventListener('abort', onAbort, { once: true })\n\n async function teardown(): Promise<void> {\n if (closed) return\n closed = true\n opts.signal?.removeEventListener('abort', onAbort)\n const iter = iterRef.current\n iterRef.current = null\n if (iter) {\n try {\n await iter.close()\n } catch {\n // ignore\n }\n }\n }\n\n if (opts.signal?.aborted) {\n void teardown()\n return { unsubscribe() {} }\n }\n\n ;(async () => {\n try {\n const iter = await consumer.consume()\n if (closed) {\n try {\n await iter.close()\n } catch {\n // ignore\n }\n return\n }\n iterRef.current = iter\n for await (const msg of iter) {\n if (closed) break\n try {\n await onMessage(msg)\n } catch (e) {\n emitStatus({ status: 'error', data: e })\n }\n }\n } catch (e) {\n if (!closed) emitStatus({ status: 'error', data: e })\n }\n })().catch((e) => emitStatus({ status: 'error', data: e }))\n\n return {\n unsubscribe() {\n void teardown()\n },\n }\n }\n\n function onStatus(listener: (event: NatsStatusEvent) => void): () => void {\n statusListeners.add(listener)\n return () => statusListeners.delete(listener)\n }\n\n return {\n connect,\n close,\n isConnected,\n publishBytes,\n publishString,\n publishJson,\n requestBytes,\n requestString,\n requestJson,\n subscribeBytes,\n subscribeString,\n subscribeJson,\n subscribeJetStreamOrdered,\n onStatus,\n }\n}\n","import { createNatsClient, type NatsClient, type NatsStatus, type NatsStatusEvent } from './nats'\n\nexport const NATS_DEFAULTS = {\n SHARED_CLOSE_DELAY_MS: 3000,\n CONNECT_TIMEOUT_MS: 10_000,\n PING_INTERVAL_MS: 30_000,\n MAX_PING_OUT: 3,\n RETRY_INITIAL_DELAY_MS: 1000,\n RETRY_MAX_DELAY_MS: 30_000,\n RETRY_MULTIPLIER: 2,\n} as const\n\nexport interface NatsReconnectionBackoff {\n /** Number of fast retries before exponential phase kicks in. Default: 0. */\n fastRetries?: number\n /** Delay used during the fast-retry phase. Default: RETRY_INITIAL_DELAY_MS. */\n fastRetryDelayMs?: number\n /** Base delay for the exponential phase. Default: RETRY_INITIAL_DELAY_MS. */\n initialDelayMs?: number\n /** Upper cap on any single retry delay. Default: RETRY_MAX_DELAY_MS. */\n maxDelayMs?: number\n /** Per-attempt multiplier during exponential phase. Default: RETRY_MULTIPLIER. */\n multiplier?: number\n}\n\nexport interface SharedConnection {\n wsUrl: string\n client: NatsClient\n connectPromise: Promise<void> | null\n refCount: number\n closeTimer: ReturnType<typeof setTimeout> | null\n retryTimer: ReturnType<typeof setTimeout> | null\n /**\n * Identity of the consumer driving reconnect. When set, other consumers\n * should observe status only and skip their own scheduleRetry — otherwise\n * each disconnect triggers multiple concurrent connect() calls racing over\n * connectPromise.\n */\n retryOwner: object | null\n}\n\nexport interface AcquireClientOptions {\n name?: string\n user?: string\n pass?: string\n connectTimeoutMs?: number\n pingIntervalMs?: number\n maxPingOut?: number\n}\n\nexport interface ReleaseClientOptions {\n delayMs?: number\n}\n\n// One shared connection PER URL. The previous single-slot implementation\n// force-closed whatever was connected the moment any consumer acquired a\n// DIFFERENT URL — even with live refs on it. With two chat surfaces on\n// distinct endpoints (`/ws/nats` client chat vs `/ws/nats-api` dashboard)\n// mounted at once, each acquire killed the other's socket, and the loser's\n// retry loop self-cancelled (connection identity mismatch) leaving a dead\n// subscription that silently received nothing.\nconst connections = new Map<string, SharedConnection>()\n\n/** Legacy accessor from the single-slot era: returns the first live shared\n * connection, or null. With MULTIPLE URLs connected (e.g. `/ws/nats` client\n * chat + `/ws/nats-api` dashboard mounted together) \"first\" is whichever\n * surface acquired first — an arbitrary, mount-order-dependent answer.\n * Prefer `getSharedConnectionFor(url)`; this stays only for external\n * registry-pinned consumers of the old single-connection API. */\nexport function getSharedConnection(): SharedConnection | null {\n const first = connections.values().next()\n return first.done ? null : first.value\n}\n\nexport function acquireClient(url: string, opts?: AcquireClientOptions): SharedConnection {\n let conn = connections.get(url)\n\n if (!conn) {\n const {\n name = 'openframe-frontend',\n user = 'machine',\n pass = '',\n connectTimeoutMs = NATS_DEFAULTS.CONNECT_TIMEOUT_MS,\n pingIntervalMs = NATS_DEFAULTS.PING_INTERVAL_MS,\n maxPingOut = NATS_DEFAULTS.MAX_PING_OUT,\n } = opts ?? {}\n\n const client = createNatsClient({\n servers: url,\n name,\n user,\n pass,\n connectTimeoutMs,\n reconnect: false,\n pingIntervalMs,\n maxPingOut,\n })\n\n conn = {\n wsUrl: url,\n client,\n connectPromise: null,\n refCount: 0,\n closeTimer: null,\n retryTimer: null,\n retryOwner: null,\n }\n connections.set(url, conn)\n }\n\n conn.refCount += 1\n if (conn.closeTimer) {\n clearTimeout(conn.closeTimer)\n conn.closeTimer = null\n }\n return conn\n}\n\nexport function releaseClient(url: string, opts?: ReleaseClientOptions): void {\n const conn = connections.get(url)\n if (!conn) return\n\n conn.refCount = Math.max(0, conn.refCount - 1)\n if (conn.refCount > 0) return\n\n const delay = opts?.delayMs ?? NATS_DEFAULTS.SHARED_CLOSE_DELAY_MS\n conn.closeTimer = setTimeout(() => {\n conn.closeTimer = null\n // A new acquire may have raced in during the grace period.\n if (conn.refCount > 0) return\n if (connections.get(url) === conn) {\n connections.delete(url)\n }\n if (conn.retryTimer) {\n clearTimeout(conn.retryTimer)\n conn.retryTimer = null\n }\n void conn.client.close().catch(() => {})\n }, delay)\n}\n\nexport function getSharedConnectionFor(url: string | null | undefined): SharedConnection | null {\n if (!url) return null\n return connections.get(url) ?? null\n}\n\n// ---------------------------------------------------------------------------\n// Connection lifecycle: retry + status loop, shared by NatsProvider and the\n// chat hooks. Each consumer that wants to drive reconnect creates an\n// ownerToken and calls startConnectionLifecycle(). The first caller to claim\n// retryOwner runs the actual retry loop; subsequent claimants observe status\n// only. When the owner unmounts and releases retryOwner, the next status\n// event lets a surviving consumer pick up ownership opportunistically.\n// ---------------------------------------------------------------------------\n\nexport interface ConnectionLifecycleOptions {\n conn: SharedConnection\n wsUrl: string\n onBeforeReconnect?: () => Promise<void> | void\n backoff?: NatsReconnectionBackoff\n getFreshUrl: () => string | null\n /** Called on every status change (after closed-guard). */\n onStatusChange?: (status: NatsStatus, evt: NatsStatusEvent) => void\n /**\n * Decide which statuses should trigger a retry attempt. Defaults to closed +\n * disconnected. Override to skip 'error' (JetStream protocol errors that\n * don't close the WS) or include it.\n */\n shouldRetryOn?: (status: NatsStatus) => boolean\n}\n\nexport interface ConnectionLifecycleHandle {\n /** Stop observing status, clear any pending retry, release ownership if held. */\n stop(): void\n}\n\nconst defaultShouldRetryOn = (status: NatsStatus) => status === 'closed' || status === 'disconnected'\n\nexport function startConnectionLifecycle(options: ConnectionLifecycleOptions): ConnectionLifecycleHandle {\n const { conn, wsUrl } = options\n // Each lifecycle gets its own identity for retry ownership. The first lifecycle to claim\n // an unowned connection drives reconnect; later attachers observe status only until the\n // owner releases (see opportunistic claim in scheduleRetry).\n const ownerToken = {}\n if (!conn.retryOwner) conn.retryOwner = ownerToken\n\n let closed = false\n let retryAttempt = 0\n\n function emitSynthetic(status: NatsStatus) {\n if (closed) return\n options.onStatusChange?.(status, { status })\n if (status === 'connected') {\n retryAttempt = 0\n }\n }\n\n function scheduleRetry() {\n if (closed) return\n if (getSharedConnectionFor(wsUrl) !== conn) return\n if (!conn.retryOwner) conn.retryOwner = ownerToken\n if (conn.retryOwner !== ownerToken) return\n\n if (conn.retryTimer) {\n clearTimeout(conn.retryTimer)\n conn.retryTimer = null\n }\n\n const cfg = options.backoff ?? {}\n const fastRetries = cfg.fastRetries ?? 0\n const fastDelay = cfg.fastRetryDelayMs ?? NATS_DEFAULTS.RETRY_INITIAL_DELAY_MS\n const baseDelay = cfg.initialDelayMs ?? NATS_DEFAULTS.RETRY_INITIAL_DELAY_MS\n const maxDelay = cfg.maxDelayMs ?? NATS_DEFAULTS.RETRY_MAX_DELAY_MS\n const multiplier = cfg.multiplier ?? NATS_DEFAULTS.RETRY_MULTIPLIER\n\n const delay =\n retryAttempt < fastRetries\n ? fastDelay\n : Math.min(baseDelay * multiplier ** (retryAttempt - fastRetries), maxDelay)\n const jitteredDelay = delay * (0.5 + Math.random() * 0.5)\n retryAttempt++\n\n conn.retryTimer = setTimeout(async () => {\n conn.retryTimer = null\n if (closed) return\n if (getSharedConnectionFor(wsUrl) !== conn) return\n\n try {\n await options.onBeforeReconnect?.()\n } catch {\n // continue regardless of token-refresh outcome\n }\n if (closed) return\n if (getSharedConnectionFor(wsUrl) !== conn) return\n\n const freshUrl = options.getFreshUrl()\n if (freshUrl !== wsUrl) return\n\n try {\n conn.connectPromise = null\n conn.connectPromise = conn.client.connect()\n await conn.connectPromise\n if (!closed && getSharedConnectionFor(wsUrl) === conn) {\n retryAttempt = 0\n }\n } catch {\n conn.connectPromise = null\n if (!closed && getSharedConnectionFor(wsUrl) === conn) {\n scheduleRetry()\n }\n }\n }, jitteredDelay)\n }\n\n const shouldRetryOn = options.shouldRetryOn ?? defaultShouldRetryOn\n\n const unsubStatus = conn.client.onStatus((evt) => {\n if (closed) return\n options.onStatusChange?.(evt.status, evt)\n if (evt.status === 'connected') {\n retryAttempt = 0\n }\n if (shouldRetryOn(evt.status)) {\n scheduleRetry()\n }\n })\n\n if (conn.client.isConnected()) {\n emitSynthetic('connected')\n }\n\n void (async () => {\n try {\n conn.connectPromise ||= conn.client.connect()\n await conn.connectPromise\n } catch {\n conn.connectPromise = null\n if (closed) return\n\n emitSynthetic('disconnected')\n scheduleRetry()\n }\n })()\n\n return {\n stop() {\n closed = true\n unsubStatus()\n if (conn.retryTimer) {\n clearTimeout(conn.retryTimer)\n conn.retryTimer = null\n }\n if (conn.retryOwner === ownerToken) {\n conn.retryOwner = null\n }\n },\n }\n}\n","'use client'\n\nimport * as React from 'react'\nimport type { NatsClient, NatsStatus } from './nats'\nimport {\n acquireClient,\n releaseClient,\n startConnectionLifecycle,\n type AcquireClientOptions,\n type NatsReconnectionBackoff,\n} from './shared-connection'\n\nexport type { NatsReconnectionBackoff } from './shared-connection'\n\nexport interface NatsProviderProps {\n children: React.ReactNode\n /** Return the current NATS WebSocket URL (or null when not yet available, e.g. unauthenticated). */\n getWsUrl: () => string | null\n /** Called before each reconnect attempt. */\n onBeforeReconnect?: () => Promise<void> | void\n clientConfig?: AcquireClientOptions\n reconnectionBackoff?: NatsReconnectionBackoff\n /**\n * Bump this to force re-evaluating `getWsUrl()` (e.g. when auth state flips).\n * Provider does not subscribe to external auth state by itself.\n */\n urlRevision?: unknown\n}\n\nexport interface NatsContextValue {\n client: NatsClient | null\n status: NatsStatus\n isReady: boolean\n reconnectionCount: number\n}\n\nconst NatsContext = React.createContext<NatsContextValue | null>(null)\n\nexport function NatsProvider({\n children,\n getWsUrl,\n onBeforeReconnect,\n clientConfig,\n reconnectionBackoff,\n urlRevision,\n}: NatsProviderProps) {\n const [client, setClient] = React.useState<NatsClient | null>(null)\n const [status, setStatus] = React.useState<NatsStatus>('closed')\n const [reconnectionCount, setReconnectionCount] = React.useState(0)\n\n const getWsUrlRef = React.useRef(getWsUrl)\n React.useEffect(() => {\n getWsUrlRef.current = getWsUrl\n }, [getWsUrl])\n\n const onBeforeReconnectRef = React.useRef(onBeforeReconnect)\n React.useEffect(() => {\n onBeforeReconnectRef.current = onBeforeReconnect\n }, [onBeforeReconnect])\n\n const reconnectionBackoffRef = React.useRef(reconnectionBackoff)\n React.useEffect(() => {\n reconnectionBackoffRef.current = reconnectionBackoff\n }, [reconnectionBackoff])\n\n const clientConfigRef = React.useRef(clientConfig)\n React.useEffect(() => {\n clientConfigRef.current = clientConfig\n }, [clientConfig])\n\n const heldUrlRef = React.useRef<string | null>(null)\n const hadConnectionBeforeRef = React.useRef(false)\n\n React.useEffect(() => {\n const wsUrl = getWsUrlRef.current()\n\n if (!wsUrl) {\n if (heldUrlRef.current) {\n releaseClient(heldUrlRef.current)\n heldUrlRef.current = null\n setClient(null)\n setStatus('closed')\n }\n return\n }\n\n if (heldUrlRef.current && heldUrlRef.current !== wsUrl) {\n releaseClient(heldUrlRef.current)\n heldUrlRef.current = null\n }\n\n const conn = acquireClient(wsUrl, clientConfigRef.current)\n heldUrlRef.current = wsUrl\n setClient(conn.client)\n setStatus(conn.client.isConnected() ? 'connected' : 'connecting')\n\n const lifecycle = startConnectionLifecycle({\n conn,\n wsUrl,\n onBeforeReconnect: () => onBeforeReconnectRef.current?.(),\n backoff: reconnectionBackoffRef.current,\n getFreshUrl: () => getWsUrlRef.current(),\n onStatusChange: (newStatus) => {\n if (newStatus === 'error') return\n setStatus(newStatus)\n if (newStatus === 'connected') {\n if (hadConnectionBeforeRef.current) {\n setReconnectionCount((c) => c + 1)\n }\n hadConnectionBeforeRef.current = true\n }\n },\n })\n\n return () => {\n lifecycle.stop()\n if (heldUrlRef.current) {\n releaseClient(heldUrlRef.current)\n heldUrlRef.current = null\n }\n setClient(null)\n setStatus('closed')\n }\n }, [urlRevision])\n\n const value = React.useMemo<NatsContextValue>(\n () => ({\n client,\n status,\n isReady: status === 'connected' && client !== null,\n reconnectionCount,\n }),\n [client, status, reconnectionCount],\n )\n\n return <NatsContext.Provider value={value}>{children}</NatsContext.Provider>\n}\n\nexport function useNats(): NatsContextValue {\n const ctx = React.useContext(NatsContext)\n if (!ctx) throw new Error('useNats must be used inside <NatsProvider>')\n return ctx\n}\n\nexport function useOptionalNats(): NatsContextValue | null {\n return React.useContext(NatsContext)\n}\n","'use client'\n\nimport * as React from 'react'\nimport type { JsMsg, Msg, NatsSubscribeOptions } from './nats'\nimport { useOptionalNats } from './nats-provider'\n\nexport interface UseNatsSubscriptionOptions extends NatsSubscribeOptions {\n enabled?: boolean\n}\n\nexport interface UseNatsSubscriptionReturn {\n isSubscribed: boolean\n isReady: boolean\n}\n\n/**\n * Subscribe to a NATS subject using the shared connection from <NatsProvider>.\n * Automatically (re)subscribes when the connection becomes ready, when the\n * subject changes, and after reconnections.\n */\nexport function useNatsSubscription(\n subject: string | null,\n onMessage: (msg: Msg) => void | Promise<void>,\n options?: UseNatsSubscriptionOptions,\n): UseNatsSubscriptionReturn {\n const nats = useOptionalNats()\n const handlerRef = React.useRef(onMessage)\n React.useEffect(() => {\n handlerRef.current = onMessage\n }, [onMessage])\n\n const [isSubscribed, setIsSubscribed] = React.useState(false)\n\n const enabled = options?.enabled !== false\n const queue = options?.queue\n const max = options?.max\n const reconnectionCount = nats?.reconnectionCount ?? 0\n const isReady = !!nats?.isReady\n const client = nats?.client ?? null\n\n React.useEffect(() => {\n if (!client || !isReady || !subject || !enabled) {\n setIsSubscribed(false)\n return\n }\n\n const sub = client.subscribeBytes(\n subject,\n (msg) => handlerRef.current(msg),\n { queue, max },\n )\n setIsSubscribed(true)\n\n return () => {\n setIsSubscribed(false)\n try {\n sub.unsubscribe()\n } catch {\n // ignore\n }\n }\n // reconnectionCount intentionally in deps: re-subscribe after reconnect\n }, [client, isReady, subject, enabled, queue, max, reconnectionCount])\n\n return { isSubscribed, isReady }\n}\n\nexport type UseNatsJsonSubscriptionOptions = UseNatsSubscriptionOptions\n\nexport function useNatsJsonSubscription<T = unknown>(\n subject: string | null,\n onPayload: (payload: T, msg: Msg) => void | Promise<void>,\n options?: UseNatsJsonSubscriptionOptions,\n): UseNatsSubscriptionReturn {\n const handlerRef = React.useRef(onPayload)\n React.useEffect(() => {\n handlerRef.current = onPayload\n }, [onPayload])\n\n const decoderRef = React.useRef<TextDecoder | null>(null)\n if (!decoderRef.current && typeof TextDecoder !== 'undefined') {\n decoderRef.current = new TextDecoder()\n }\n\n const wrapped = React.useCallback(async (msg: Msg) => {\n const decoder = decoderRef.current\n if (!decoder) return\n try {\n const parsed = JSON.parse(decoder.decode(msg.data)) as T\n await handlerRef.current(parsed, msg)\n } catch {\n // ignore malformed payloads\n }\n }, [])\n\n return useNatsSubscription(subject, wrapped, options)\n}\n\nexport type NatsJsMsg = JsMsg\n"]}