@zuzjs/flare 0.2.21 → 0.2.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/react.cjs CHANGED
@@ -1,2 +1,2 @@
1
1
  'use strict';require('./chunk-DGCKTOF5.cjs');var react=require('react');/* ZuzFlare Client */
2
- var q=E=>{let{query:i,options:l,onData:m,forceReadyOnFirstEmission:d=true}=E,y=react.useRef(null),f=react.useRef(null),p=react.useRef(""),h=react.useRef(0),S=react.useRef(false),b=react.useRef(m),o=react.useRef(i??null),n=react.useRef(l),C=react.useRef(d),s=(...g)=>{};react.useEffect(()=>{b.current=m;},[m]),react.useEffect(()=>{o.current=i??null;},[i]),react.useEffect(()=>{n.current=l;},[l]),react.useEffect(()=>{C.current=d;},[d]);let a=react.useCallback(()=>{f.current?.(),y.current?.close(),f.current=null,S.current=false,p.current="";},[]),Q=react.useCallback(g=>{a(),h.current+=1,g&&(o.current=g),o.current&&(y.current=o.current.stream({flushMs:n.current?.flushMs??20,maxBatchSize:n.current?.maxBatchSize??20,insertAt:n.current?.insertAt??"end",maxDocs:n.current?.maxDocs??50}),f.current=y.current.subscribe((e,t)=>{let $=e.map(c=>`${c?.id??""}:${c?.updatedAt??c?.updated_at??c?.mtime??""}`).join(","),D=`${h.current}:${t?.ready?1:0}:${$}`;if(D===p.current){s("[Sidebar] Skipping duplicate boards stream payload",{size:e.length,meta:t.ready});return}if(p.current=D,!S.current){S.current=true,b.current(e,{ready:C.current?true:!!t?.ready}),s("Stream first payload",{size:e.length,meta:t});return}s("[Sidebar] Boards stream update",{size:e.length,meta:t.ready}),b.current(e,{ready:!!t?.ready});}));},[a]);return react.useEffect(()=>()=>{a();},[a]),{buildStream:Q,closeStream:a}};exports.useLiveQuery=q;
2
+ var se=x=>{let{query:L,options:M,onData:D,forceReadyOnFirstEmission:Q=true,firstReadyEmptyRetryCount:f=1,firstReadyEmptyRetryDelayMs:z=120,stalledFirstEmissionRetryCount:g=2,stalledFirstEmissionTimeoutMs:A=500,debugTrace:I=false,debugLabel:U="useLiveQuery",emptyReadyGraceMs:Z=0}=x,G=react.useRef(null),$=react.useRef(null),v=react.useRef(""),V=react.useRef(0),o=react.useRef(false),m=react.useRef(false),R=react.useRef(D),b=react.useRef(L??null),p=react.useRef(M),H=react.useRef(Q),J=react.useRef(f),K=react.useRef(z),y=react.useRef(f),P=react.useRef(g),W=react.useRef(A),i=react.useRef(g),d=react.useRef(null),X=react.useRef(I),Y=react.useRef(U),h=react.useRef(Z),a=react.useRef(null),T=react.useRef(null),q=react.useRef(0),ee=()=>{let l=globalThis,O=l?.__ZUZ_LIVE_QUERY_TRACE,r=false,s=null;try{typeof window<"u"&&window.localStorage&&(r=window.localStorage.getItem("__ZUZ_LIVE_QUERY_TRACE")==="1",s=window.localStorage.getItem("__ZUZ_LIVE_QUERY_TRACE_FILTER"));}catch{}if(!O&&!r)return false;let S=l?.__ZUZ_LIVE_QUERY_TRACE_FILTER??s;return S?String(Y.current).toLowerCase().includes(String(S).toLowerCase()):true},u=(...l)=>{(X.current||ee())&&console.log(`[${Y.current}]`,...l);};react.useEffect(()=>{R.current=D;},[D]),react.useEffect(()=>{b.current=L??null;},[L]),react.useEffect(()=>{p.current=M;},[M]),react.useEffect(()=>{H.current=Q;},[Q]),react.useEffect(()=>{J.current=f,y.current=f;},[f]),react.useEffect(()=>{K.current=z;},[z]),react.useEffect(()=>{P.current=g,i.current=g;},[g]),react.useEffect(()=>{W.current=A;},[A]),react.useEffect(()=>{X.current=I;},[I]),react.useEffect(()=>{Y.current=U;},[U]),react.useEffect(()=>{h.current=Z;},[Z]);let _=react.useCallback(()=>{a.current!==null&&(clearTimeout(a.current),a.current=null),T.current=null;},[]),B=react.useCallback(()=>{d.current!==null&&(clearTimeout(d.current),d.current=null);},[]),E=react.useCallback(()=>{_(),B(),$.current?.(),G.current?.close(),$.current=null,o.current=false,m.current=false,q.current=0,v.current="";},[_,B]),N=react.useCallback((l,O=false)=>{E(),V.current+=1,O||(y.current=J.current,i.current=P.current),l&&(b.current=l),b.current&&(G.current=b.current.stream({flushMs:p.current?.flushMs??20,maxBatchSize:p.current?.maxBatchSize??20,insertAt:p.current?.insertAt??"end",maxDocs:p.current?.maxDocs??50}),$.current=G.current.subscribe((r,s)=>{d.current!==null&&B();let S=r.map(t=>`${t?.id??""}:${t?.updatedAt??t?.updated_at??t?.mtime??""}`).join(","),w=`${V.current}:${s?.ready?1:0}:${S}`;q.current+=1;let c=q.current;if(u("emission",{emissionNo:c,generation:V.current,ready:!!s?.ready,size:r.length,firstRetryRemaining:y.current,hasNonEmpty:m.current}),w===v.current){u("skip duplicate",{emissionNo:c,size:r.length,metaReady:!!s?.ready});return}v.current=w;let k=!o.current,re=k&&H.current&&r.length>0,C=k&&re?true:!!s?.ready,j=!!s?.ready;if(k&&!j&&r.length===0&&i.current>0){let t=Math.max(0,W.current),te=i.current-1;d.current=setTimeout(()=>{d.current=null,i.current=Math.max(0,i.current-1),u("stalled first emission timeout hit \u2014 rebuilding stream",{stallTimeout:t,retriesLeft:i.current}),N(void 0,true);},t),u("schedule stalled-first-emission retry",{emissionNo:c,stallTimeout:t,retriesLeft:te});return}if(j&&r.length===0&&!m.current&&y.current>0){y.current-=1;let t=Math.max(0,K.current);u("schedule first-ready-empty retry",{emissionNo:c,retryDelay:t,retriesLeft:y.current}),setTimeout(()=>{N(void 0,true);},t);return}if(a.current!==null&&r.length>0){_(),o.current=true,m.current=true,u("emit non-empty after grace wait",{emissionNo:c,ready:C,size:r.length}),R.current(r,{ready:C});return}if(j&&r.length===0&&h.current>0&&a.current===null){T.current={rows:r},o.current=true,a.current=setTimeout(()=>{a.current=null;let t=T.current;T.current=null,t&&(u("emit deferred empty after grace timeout",{size:t.rows.length}),R.current(t.rows,{ready:true}));},h.current),u("start empty-ready grace timer",{emissionNo:c,graceMs:h.current});return}if(!o.current){o.current=true,r.length>0&&(m.current=true),u("emit first payload",{emissionNo:c,ready:C,size:r.length}),R.current(r,{ready:C});return}u("emit update",{emissionNo:c,size:r.length,metaReady:!!s?.ready}),r.length>0&&(m.current=true),R.current(r,{ready:!!s?.ready});}));},[E]);return react.useEffect(()=>()=>{u("[Sidebar] Cleaning up boards stream"),E();},[E]),{buildStream:N,closeStream:E,cancelGraceTimer:_}};exports.useLiveQuery=se;
package/dist/react.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { a as CollectionQuery } from './index-mMCJajDN.cjs';
2
- import './index-DlQgWDy-.cjs';
1
+ import { a as CollectionQuery } from './index-DOaU2Hxo.cjs';
2
+ import './index-18tMqAtM.cjs';
3
3
  import '@zuzjs/auth';
4
4
 
5
5
  declare const useLiveQuery: (data: {
@@ -14,9 +14,47 @@ declare const useLiveQuery: (data: {
14
14
  maxDocs: number;
15
15
  };
16
16
  forceReadyOnFirstEmission?: boolean;
17
+ /**
18
+ * Retry the stream when the very first emission is ready=true with zero rows.
19
+ * Helps recover from transient first-load races on higher-latency networks.
20
+ * Default 1.
21
+ */
22
+ firstReadyEmptyRetryCount?: number;
23
+ /**
24
+ * Delay in ms before retrying a first ready+empty emission.
25
+ * Default 120.
26
+ */
27
+ firstReadyEmptyRetryDelayMs?: number;
28
+ /**
29
+ * Retry count when the first emission is ready=false with zero rows and
30
+ * no follow-up emissions arrive within stalledFirstEmissionTimeoutMs.
31
+ * Default 2.
32
+ */
33
+ stalledFirstEmissionRetryCount?: number;
34
+ /**
35
+ * Timeout in ms to consider the stream stalled after first ready=false empty emission.
36
+ * Default 500.
37
+ */
38
+ stalledFirstEmissionTimeoutMs?: number;
39
+ /**
40
+ * Enable detailed stream trace logs for debugging race conditions.
41
+ */
42
+ debugTrace?: boolean;
43
+ /**
44
+ * Prefix used in debug logs to identify the caller.
45
+ */
46
+ debugLabel?: string;
47
+ /**
48
+ * When the stream emits ready=true with zero rows, wait this many ms before
49
+ * forwarding the empty result. If a non-empty emission arrives within the window
50
+ * the grace timer is cancelled and data is forwarded immediately.
51
+ * Default 0 (no grace period — backwards-compatible).
52
+ */
53
+ emptyReadyGraceMs?: number;
17
54
  }) => {
18
- buildStream: (queryOverride?: CollectionQuery<any, {}>) => void;
55
+ buildStream: (queryOverride?: CollectionQuery<any, {}>, isInternalRetry?: boolean) => void;
19
56
  closeStream: () => void;
57
+ cancelGraceTimer: () => void;
20
58
  };
21
59
 
22
60
  export { useLiveQuery };
package/dist/react.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { a as CollectionQuery } from './index-TRU0q-av.js';
2
- import './index-DlQgWDy-.js';
1
+ import { a as CollectionQuery } from './index-CRByt4Qw.js';
2
+ import './index-18tMqAtM.js';
3
3
  import '@zuzjs/auth';
4
4
 
5
5
  declare const useLiveQuery: (data: {
@@ -14,9 +14,47 @@ declare const useLiveQuery: (data: {
14
14
  maxDocs: number;
15
15
  };
16
16
  forceReadyOnFirstEmission?: boolean;
17
+ /**
18
+ * Retry the stream when the very first emission is ready=true with zero rows.
19
+ * Helps recover from transient first-load races on higher-latency networks.
20
+ * Default 1.
21
+ */
22
+ firstReadyEmptyRetryCount?: number;
23
+ /**
24
+ * Delay in ms before retrying a first ready+empty emission.
25
+ * Default 120.
26
+ */
27
+ firstReadyEmptyRetryDelayMs?: number;
28
+ /**
29
+ * Retry count when the first emission is ready=false with zero rows and
30
+ * no follow-up emissions arrive within stalledFirstEmissionTimeoutMs.
31
+ * Default 2.
32
+ */
33
+ stalledFirstEmissionRetryCount?: number;
34
+ /**
35
+ * Timeout in ms to consider the stream stalled after first ready=false empty emission.
36
+ * Default 500.
37
+ */
38
+ stalledFirstEmissionTimeoutMs?: number;
39
+ /**
40
+ * Enable detailed stream trace logs for debugging race conditions.
41
+ */
42
+ debugTrace?: boolean;
43
+ /**
44
+ * Prefix used in debug logs to identify the caller.
45
+ */
46
+ debugLabel?: string;
47
+ /**
48
+ * When the stream emits ready=true with zero rows, wait this many ms before
49
+ * forwarding the empty result. If a non-empty emission arrives within the window
50
+ * the grace timer is cancelled and data is forwarded immediately.
51
+ * Default 0 (no grace period — backwards-compatible).
52
+ */
53
+ emptyReadyGraceMs?: number;
17
54
  }) => {
18
- buildStream: (queryOverride?: CollectionQuery<any, {}>) => void;
55
+ buildStream: (queryOverride?: CollectionQuery<any, {}>, isInternalRetry?: boolean) => void;
19
56
  closeStream: () => void;
57
+ cancelGraceTimer: () => void;
20
58
  };
21
59
 
22
60
  export { useLiveQuery };
package/dist/react.js CHANGED
@@ -1 +1 @@
1
- import {useRef,useEffect,useCallback}from'react';var F=E=>{let{query:i,options:l,onData:m,forceReadyOnFirstEmission:d=true}=E,y=useRef(null),f=useRef(null),p=useRef(""),h=useRef(0),S=useRef(false),b=useRef(m),o=useRef(i??null),n=useRef(l),C=useRef(d),s=(...g)=>{};useEffect(()=>{b.current=m;},[m]),useEffect(()=>{o.current=i??null;},[i]),useEffect(()=>{n.current=l;},[l]),useEffect(()=>{C.current=d;},[d]);let a=useCallback(()=>{f.current?.(),y.current?.close(),f.current=null,S.current=false,p.current="";},[]),Q=useCallback(g=>{a(),h.current+=1,g&&(o.current=g),o.current&&(y.current=o.current.stream({flushMs:n.current?.flushMs??20,maxBatchSize:n.current?.maxBatchSize??20,insertAt:n.current?.insertAt??"end",maxDocs:n.current?.maxDocs??50}),f.current=y.current.subscribe((e,t)=>{let $=e.map(c=>`${c?.id??""}:${c?.updatedAt??c?.updated_at??c?.mtime??""}`).join(","),D=`${h.current}:${t?.ready?1:0}:${$}`;if(D===p.current){s("[Sidebar] Skipping duplicate boards stream payload",{size:e.length,meta:t.ready});return}if(p.current=D,!S.current){S.current=true,b.current(e,{ready:C.current?true:!!t?.ready}),s("Stream first payload",{size:e.length,meta:t});return}s("[Sidebar] Boards stream update",{size:e.length,meta:t.ready}),b.current(e,{ready:!!t?.ready});}));},[a]);return useEffect(()=>()=>{a();},[a]),{buildStream:Q,closeStream:a}};export{F as useLiveQuery};
1
+ import {useRef,useEffect,useCallback}from'react';var ce=x=>{let{query:L,options:M,onData:D,forceReadyOnFirstEmission:Q=true,firstReadyEmptyRetryCount:f=1,firstReadyEmptyRetryDelayMs:z=120,stalledFirstEmissionRetryCount:g=2,stalledFirstEmissionTimeoutMs:A=500,debugTrace:I=false,debugLabel:U="useLiveQuery",emptyReadyGraceMs:Z=0}=x,G=useRef(null),$=useRef(null),v=useRef(""),V=useRef(0),o=useRef(false),m=useRef(false),R=useRef(D),b=useRef(L??null),p=useRef(M),H=useRef(Q),J=useRef(f),K=useRef(z),y=useRef(f),P=useRef(g),W=useRef(A),i=useRef(g),d=useRef(null),X=useRef(I),Y=useRef(U),h=useRef(Z),a=useRef(null),T=useRef(null),q=useRef(0),ee=()=>{let l=globalThis,O=l?.__ZUZ_LIVE_QUERY_TRACE,r=false,s=null;try{typeof window<"u"&&window.localStorage&&(r=window.localStorage.getItem("__ZUZ_LIVE_QUERY_TRACE")==="1",s=window.localStorage.getItem("__ZUZ_LIVE_QUERY_TRACE_FILTER"));}catch{}if(!O&&!r)return false;let S=l?.__ZUZ_LIVE_QUERY_TRACE_FILTER??s;return S?String(Y.current).toLowerCase().includes(String(S).toLowerCase()):true},u=(...l)=>{(X.current||ee())&&console.log(`[${Y.current}]`,...l);};useEffect(()=>{R.current=D;},[D]),useEffect(()=>{b.current=L??null;},[L]),useEffect(()=>{p.current=M;},[M]),useEffect(()=>{H.current=Q;},[Q]),useEffect(()=>{J.current=f,y.current=f;},[f]),useEffect(()=>{K.current=z;},[z]),useEffect(()=>{P.current=g,i.current=g;},[g]),useEffect(()=>{W.current=A;},[A]),useEffect(()=>{X.current=I;},[I]),useEffect(()=>{Y.current=U;},[U]),useEffect(()=>{h.current=Z;},[Z]);let _=useCallback(()=>{a.current!==null&&(clearTimeout(a.current),a.current=null),T.current=null;},[]),B=useCallback(()=>{d.current!==null&&(clearTimeout(d.current),d.current=null);},[]),E=useCallback(()=>{_(),B(),$.current?.(),G.current?.close(),$.current=null,o.current=false,m.current=false,q.current=0,v.current="";},[_,B]),N=useCallback((l,O=false)=>{E(),V.current+=1,O||(y.current=J.current,i.current=P.current),l&&(b.current=l),b.current&&(G.current=b.current.stream({flushMs:p.current?.flushMs??20,maxBatchSize:p.current?.maxBatchSize??20,insertAt:p.current?.insertAt??"end",maxDocs:p.current?.maxDocs??50}),$.current=G.current.subscribe((r,s)=>{d.current!==null&&B();let S=r.map(t=>`${t?.id??""}:${t?.updatedAt??t?.updated_at??t?.mtime??""}`).join(","),w=`${V.current}:${s?.ready?1:0}:${S}`;q.current+=1;let c=q.current;if(u("emission",{emissionNo:c,generation:V.current,ready:!!s?.ready,size:r.length,firstRetryRemaining:y.current,hasNonEmpty:m.current}),w===v.current){u("skip duplicate",{emissionNo:c,size:r.length,metaReady:!!s?.ready});return}v.current=w;let k=!o.current,re=k&&H.current&&r.length>0,C=k&&re?true:!!s?.ready,j=!!s?.ready;if(k&&!j&&r.length===0&&i.current>0){let t=Math.max(0,W.current),te=i.current-1;d.current=setTimeout(()=>{d.current=null,i.current=Math.max(0,i.current-1),u("stalled first emission timeout hit \u2014 rebuilding stream",{stallTimeout:t,retriesLeft:i.current}),N(void 0,true);},t),u("schedule stalled-first-emission retry",{emissionNo:c,stallTimeout:t,retriesLeft:te});return}if(j&&r.length===0&&!m.current&&y.current>0){y.current-=1;let t=Math.max(0,K.current);u("schedule first-ready-empty retry",{emissionNo:c,retryDelay:t,retriesLeft:y.current}),setTimeout(()=>{N(void 0,true);},t);return}if(a.current!==null&&r.length>0){_(),o.current=true,m.current=true,u("emit non-empty after grace wait",{emissionNo:c,ready:C,size:r.length}),R.current(r,{ready:C});return}if(j&&r.length===0&&h.current>0&&a.current===null){T.current={rows:r},o.current=true,a.current=setTimeout(()=>{a.current=null;let t=T.current;T.current=null,t&&(u("emit deferred empty after grace timeout",{size:t.rows.length}),R.current(t.rows,{ready:true}));},h.current),u("start empty-ready grace timer",{emissionNo:c,graceMs:h.current});return}if(!o.current){o.current=true,r.length>0&&(m.current=true),u("emit first payload",{emissionNo:c,ready:C,size:r.length}),R.current(r,{ready:C});return}u("emit update",{emissionNo:c,size:r.length,metaReady:!!s?.ready}),r.length>0&&(m.current=true),R.current(r,{ready:!!s?.ready});}));},[E]);return useEffect(()=>()=>{u("[Sidebar] Cleaning up boards stream"),E();},[E]),{buildStream:N,closeStream:E,cancelGraceTimer:_}};export{ce as useLiveQuery};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zuzjs/flare",
3
- "version": "0.2.21",
3
+ "version": "0.2.22",
4
4
  "keywords": [
5
5
  "core",
6
6
  "zuz",