@lunora/vue 1.0.0-alpha.7 → 1.0.0-alpha.71

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 (44) hide show
  1. package/LICENSE.md +6 -0
  2. package/README.md +2 -0
  3. package/dist/index.d.mts +825 -188
  4. package/dist/index.d.ts +825 -188
  5. package/dist/index.mjs +1 -11
  6. package/dist/packem_shared/AuthLoading-CST_mkXL.mjs +1 -0
  7. package/dist/packem_shared/LUNORA_INJECTION_KEY-CswQb5zb.mjs +1 -0
  8. package/dist/packem_shared/hydratePreloaded-C-yIiam2.mjs +1 -0
  9. package/dist/packem_shared/is-browser-BEdfLJHK.mjs +1 -0
  10. package/dist/packem_shared/scope-dispose-Dn0gQ2SS.mjs +1 -0
  11. package/dist/packem_shared/stable-key-BSG0zK_E.mjs +1 -0
  12. package/dist/packem_shared/subscribeToQuery-Sz46o9Xt.mjs +1 -0
  13. package/dist/packem_shared/useAgent-CeAYhGZA.mjs +1 -0
  14. package/dist/packem_shared/useAgentChat-B5mq0x66.mjs +1 -0
  15. package/dist/packem_shared/useAgentState-Cs1VcKQj.mjs +1 -0
  16. package/dist/packem_shared/useAgentToolEvents-BhjZrNSJ.mjs +1 -0
  17. package/dist/packem_shared/useAuth-DwDFjvto.mjs +1 -0
  18. package/dist/packem_shared/useConnectionStatus-1brbiHgc.mjs +1 -0
  19. package/dist/packem_shared/useFlag-Bxoq8mH9.mjs +1 -0
  20. package/dist/packem_shared/useInfiniteQuery-CD_dnvES.mjs +1 -0
  21. package/dist/packem_shared/useMutation-MdgW9pRE.mjs +1 -0
  22. package/dist/packem_shared/useMutator-DRVDOhcj.mjs +1 -0
  23. package/dist/packem_shared/usePresence-D2d4BqBJ.mjs +1 -0
  24. package/dist/packem_shared/useRateLimit-z8EUFuYJ.mjs +1 -0
  25. package/dist/packem_shared/useStream-CYkKEcDf.mjs +1 -0
  26. package/dist/packem_shared/useSubscription-3X8pNJ6P.mjs +1 -0
  27. package/dist/packem_shared/useVoiceAgent-1gtd9RU3.mjs +1 -0
  28. package/dist/server.mjs +1 -1
  29. package/dist/upload.d.mts +2 -0
  30. package/dist/upload.d.ts +2 -0
  31. package/dist/upload.mjs +1 -0
  32. package/dist/worker.mjs +1 -1
  33. package/package.json +10 -4
  34. package/dist/packem_shared/AuthLoading-_6-uOycE.mjs +0 -29
  35. package/dist/packem_shared/LUNORA_INJECTION_KEY-DtFXLDQ_.mjs +0 -22
  36. package/dist/packem_shared/hydratePreloaded-rVY68iFv.mjs +0 -14
  37. package/dist/packem_shared/subscribeToQuery-Cv5YL-SI.mjs +0 -51
  38. package/dist/packem_shared/useAuth-C2aEzXXH.mjs +0 -28
  39. package/dist/packem_shared/useConnectionStatus-CDgduQYe.mjs +0 -20
  40. package/dist/packem_shared/useInfiniteQuery-CEfbw7Nw.mjs +0 -199
  41. package/dist/packem_shared/useMutation-DWubV5pv.mjs +0 -29
  42. package/dist/packem_shared/usePresence-BeN5xaZM.mjs +0 -59
  43. package/dist/packem_shared/useRateLimit-DlPWjcX1.mjs +0 -67
  44. package/dist/packem_shared/useSubscription-Ol0AZFUv.mjs +0 -47
package/dist/index.mjs CHANGED
@@ -1,11 +1 @@
1
- export { AuthLoading, Authenticated, Unauthenticated } from './packem_shared/AuthLoading-_6-uOycE.mjs';
2
- export { hydratePreloaded } from './packem_shared/hydratePreloaded-rVY68iFv.mjs';
3
- export { LUNORA_INJECTION_KEY, createLunora, provideLunora, useLunora } from './packem_shared/LUNORA_INJECTION_KEY-DtFXLDQ_.mjs';
4
- export { useAuth } from './packem_shared/useAuth-C2aEzXXH.mjs';
5
- export { default as useConnectionStatus } from './packem_shared/useConnectionStatus-CDgduQYe.mjs';
6
- export { useMutation } from './packem_shared/useMutation-DWubV5pv.mjs';
7
- export { useInfiniteQuery, usePaginatedQuery } from './packem_shared/useInfiniteQuery-CEfbw7Nw.mjs';
8
- export { usePresence } from './packem_shared/usePresence-BeN5xaZM.mjs';
9
- export { subscribeToQuery, useQuery } from './packem_shared/subscribeToQuery-Cv5YL-SI.mjs';
10
- export { useRateLimit } from './packem_shared/useRateLimit-DlPWjcX1.mjs';
11
- export { useSubscription } from './packem_shared/useSubscription-Ol0AZFUv.mjs';
1
+ import{AuthLoading as o,Authenticated as t,Unauthenticated as u}from"./packem_shared/AuthLoading-CST_mkXL.mjs";import{hydratePreloaded as a}from"./packem_shared/hydratePreloaded-C-yIiam2.mjs";import{LUNORA_INJECTION_KEY as f,createLunora as m,provideLunora as p,useLunora as x}from"./packem_shared/LUNORA_INJECTION_KEY-CswQb5zb.mjs";import{useAgent as d}from"./packem_shared/useAgent-CeAYhGZA.mjs";import{useAgentChat as A}from"./packem_shared/useAgentChat-B5mq0x66.mjs";import{useAgentState as h}from"./packem_shared/useAgentState-Cs1VcKQj.mjs";import{useAgentToolEvents as l}from"./packem_shared/useAgentToolEvents-BhjZrNSJ.mjs";import{useAuth as Q}from"./packem_shared/useAuth-DwDFjvto.mjs";import{default as b}from"./packem_shared/useConnectionStatus-1brbiHgc.mjs";import{useFlag as E,useFlags as I}from"./packem_shared/useFlag-Bxoq8mH9.mjs";import{useMutation as P}from"./packem_shared/useMutation-MdgW9pRE.mjs";import{useMutator as v}from"./packem_shared/useMutator-DRVDOhcj.mjs";import{useInfiniteQuery as M,usePaginatedQuery as O}from"./packem_shared/useInfiniteQuery-CD_dnvES.mjs";import{usePresence as U}from"./packem_shared/usePresence-D2d4BqBJ.mjs";import{subscribeToQuery as J,useQuery as K}from"./packem_shared/subscribeToQuery-Sz46o9Xt.mjs";import{useRateLimit as Y}from"./packem_shared/useRateLimit-z8EUFuYJ.mjs";import{useStream as k}from"./packem_shared/useStream-CYkKEcDf.mjs";import{useSubscription as w}from"./packem_shared/useSubscription-3X8pNJ6P.mjs";import{useVoiceAgent as B}from"./packem_shared/useVoiceAgent-1gtd9RU3.mjs";export{o as AuthLoading,t as Authenticated,f as LUNORA_INJECTION_KEY,u as Unauthenticated,m as createLunora,a as hydratePreloaded,p as provideLunora,J as subscribeToQuery,d as useAgent,A as useAgentChat,h as useAgentState,l as useAgentToolEvents,Q as useAuth,b as useConnectionStatus,E as useFlag,I as useFlags,M as useInfiniteQuery,x as useLunora,P as useMutation,v as useMutator,O as usePaginatedQuery,U as usePresence,K as useQuery,Y as useRateLimit,k as useStream,w as useSubscription,B as useVoiceAgent};
@@ -0,0 +1 @@
1
+ import{defineComponent as l,computed as a}from"vue";import{useAuth as s}from"./useAuth-DwDFjvto.mjs";const i=l({name:"Authenticated",setup(o,{slots:t}){const{token:e,user:u}=s(),n=a(()=>e.value!==null&&u.value!==null);return()=>n.value?t.default?.():void 0}}),v=l({name:"Unauthenticated",setup(o,{slots:t}){const{token:e,user:u}=s(),n=a(()=>e.value!==null&&u.value===null);return()=>!n.value&&e.value===null?t.default?.():void 0}}),c=l({name:"AuthLoading",setup(o,{slots:t}){const{token:e,user:u}=s(),n=a(()=>e.value!==null&&u.value===null);return()=>n.value?t.default?.():void 0}});export{c as AuthLoading,i as Authenticated,v as Unauthenticated};
@@ -0,0 +1 @@
1
+ import{LunoraError as n}from"@lunora/errors";import{inject as t,provide as a}from"vue";const o=Symbol("lunora.client"),p=r=>({install(e){e.provide(o,r)}}),l=r=>{a(o,r)},L=()=>{const r=t(o,void 0);if(!r)throw new n("INTERNAL","useLunora(): no LunoraClient provided — call app.use(createLunora(client)) or provideLunora(client) in a parent setup().");return r};export{o as LUNORA_INJECTION_KEY,p as createLunora,l as provideLunora,L as useLunora};
@@ -0,0 +1 @@
1
+ import{useLunora as n}from"./LUNORA_INJECTION_KEY-CswQb5zb.mjs";import{subscribeToQuery as u}from"./subscribeToQuery-Sz46o9Xt.mjs";const f=r=>{const e=n(),{args:o,functionPath:t,shardKey:a,value:s}=r;return u(e,{__lunoraRef:t},o,{seed:s,shardKey:a})};export{f as hydratePreloaded};
@@ -0,0 +1 @@
1
+ const o=()=>globalThis.window!==void 0;export{o as i};
@@ -0,0 +1 @@
1
+ import{getCurrentScope as e,onScopeDispose as p}from"vue";const c=(o,r)=>{e()&&p(o)};export{c as e};
@@ -0,0 +1 @@
1
+ const y=(e,t)=>e<t?-1:e>t?1:0,s=e=>{if(e===void 0)return"null";if(typeof e=="bigint")throw new TypeError("stableStringify: cannot use a bigint in a stable JSON cache key — pass it as a string, or use stableWireKey");if(e===null||typeof e!="object")return JSON.stringify(e);if(Array.isArray(e))return`[${e.map(r=>s(r)).join(",")}]`;const t=Object.getPrototypeOf(e);if(t!==null&&t!==Object.prototype){const r=e.constructor?.name??"value";throw new TypeError(`stableStringify: cannot use a ${r} in a stable JSON cache key — only plain objects, arrays, and JSON primitives are supported (wire-typed values key via stableWireKey)`)}const n=e,a=Object.keys(n).toSorted(y),i=[];for(const r of a){const o=n[r];o!==void 0&&i.push(`${JSON.stringify(r)}:${s(o)}`)}return`{${i.join(",")}}`};export{s as e};
@@ -0,0 +1 @@
1
+ import{createQuerySubscription as f}from"@lunora/client/query";import{shallowRef as a,watch as p,toValue as y}from"vue";import{i as m}from"./is-browser-BEdfLJHK.mjs";import{useLunora as h}from"./LUNORA_INJECTION_KEY-CswQb5zb.mjs";import{e as l}from"./scope-dispose-Dn0gQ2SS.mjs";const R=(o,s,t,r={})=>{const e=a(r.seed);if(m()){const u=o.subscribe(s,t,i=>{e.value=i},{shardKey:r.shardKey});l(u)}return e},x=(o,s,t={})=>{const r=h(),e=a(void 0);return p(()=>y(s),(u,i,n)=>{if(!m())return;const c=f(r,o,u,{onData:d=>{e.value=d},onReset:()=>{e.value=void 0}},{shardKey:t.shardKey});n(c)},{immediate:!0}),e};export{R as subscribeToQuery,x as useQuery};
@@ -0,0 +1 @@
1
+ import{computed as s,toValue as n}from"vue";import{useMutation as i}from"./useMutation-MdgW9pRE.mjs";import{useSubscription as h}from"./useSubscription-3X8pNJ6P.mjs";const v={__lunoraRef:""},K=o=>{const{api:d,cancel:u,run:c,runArgs:p,threadKey:a}=o,r=i(c),m=i(u??v),{data:g}=h(d.agents.agentThread,()=>({key:n(a)})),e=s(()=>g.value),l=s(()=>e.value?.status),y=async(t,f)=>{await r.mutate({input:t,threadKey:n(a),...p,...f})};return{cancel:async()=>{const t=e.value?.instanceId;u===void 0||t===void 0||await m.mutate({instanceId:t,threadKey:n(a)})},pending:r.pending,run:y,status:l,thread:e}};export{v as NO_MUTATION_REF,K as useAgent};
@@ -0,0 +1 @@
1
+ import{reconcileOptimistic as y,maxSeq as I}from"@lunora/client";import{ref as N,computed as i,toValue as s}from"vue";import{NO_MUTATION_REF as R}from"./useAgent-CeAYhGZA.mjs";import{useMutation as m}from"./useMutation-MdgW9pRE.mjs";import{useStream as U}from"./useStream-CYkKEcDf.mjs";import{useSubscription as k}from"./useSubscription-3X8pNJ6P.mjs";const F={__lunoraRef:""},H=w=>{const{api:c,cancel:v,limit:p,send:A,sendArgs:x,stream:g,threadKey:n}=w,{data:S}=k(c.agents.agentMessages,()=>{const e=s(n);return p===void 0?{key:e}:{key:e,limit:p}}),{data:K}=k(c.agents.agentThread,()=>({key:s(n)})),O=g===void 0?"skip":()=>({key:s(n)}),{chunks:T}=U(g??F,O),_=m(A),C=m(v??R),M=m(c.agents.agentResolveApproval),o=N([]);let h=0;const l=i(()=>K.value),$=i(()=>l.value?.status),u=i(()=>S.value??[]),b=i(()=>{const e=u.value,a=y(o.value,e);if(a.length===0)return e;const t=I(e);return[...e,...a.map((r,d)=>({content:r.content,optimistic:!0,role:"user",seq:t+1+d}))]}),j=i(()=>{const e=s(n),a=u.value.filter(t=>t.role==="assistant").length;return T.value.filter(t=>t.kind!=="progress"&&t.threadKey===e&&t.turn>=a).map(t=>t.text).join("")}),q=async(e,a)=>{const t=h;h+=1;const r=I(u.value);o.value=[...y(o.value,u.value),{content:e,id:t,maxDurableSeqAtSend:r}];try{await _.mutate({input:e,threadKey:s(n),...x,...a})}catch(d){throw o.value=o.value.filter(E=>E.id!==t),d}},f=async(e,a,t)=>{const r=l.value?.instanceId;if(r===void 0)throw new Error(`useAgentChat: cannot ${e} — no in-flight run (thread has no instanceId)`);await M.mutate({decision:e,instanceId:r,threadKey:s(n),toolCallId:a,...t===void 0?{}:{note:t}})};return{approve:async(e,a)=>f("approve",e,a),cancel:async()=>{const e=l.value?.instanceId;v===void 0||e===void 0||await C.mutate({instanceId:e,threadKey:s(n)})},messages:b,reject:async(e,a)=>f("reject",e,a),send:q,status:$,streamingText:j}};export{H as useAgentChat};
@@ -0,0 +1 @@
1
+ import{computed as o,toValue as s}from"vue";import{useSubscription as n}from"./useSubscription-3X8pNJ6P.mjs";const p=t=>{const{data:e,error:r}=n(t.api.agents.agentState,()=>({key:s(t.threadKey)})),a=o(()=>e.value);return{error:r,state:a}};export{p as useAgentState};
@@ -0,0 +1 @@
1
+ import{computed as v,toValue as e}from"vue";import{useStream as c}from"./useStream-CYkKEcDf.mjs";import{useSubscription as C}from"./useSubscription-3X8pNJ6P.mjs";const f={__lunoraRef:""},g=[],y=t=>{if(t.role==="assistant"&&t.toolCalls)return t.toolCalls.map(a=>({input:a.input,seq:t.seq,toolCallId:a.id,toolName:a.name,type:"call"}));if(t.role==="tool")return t.status==="awaiting_approval"?[{seq:t.seq,type:"awaiting-approval",...t.toolCallId===void 0?{}:{toolCallId:t.toolCallId},...t.toolName===void 0?{}:{toolName:t.toolName}}]:[{output:t.content,seq:t.seq,type:"result",...t.status==="approved"||t.status==="rejected"?{status:t.status}:{},...t.toolCallId===void 0?{}:{toolCallId:t.toolCallId},...t.toolName===void 0?{}:{toolName:t.toolName}}]},q=t=>{const{api:a,limit:r,stream:i,threadKey:s}=t,u=()=>{const l=e(s);return r===void 0?{key:l}:{key:l,limit:r}},{data:d}=C(a.agents.agentMessages,u),n=i===void 0?"skip":()=>({key:e(s)}),{chunks:m}=c(i??f,n);return{events:v(()=>{const l=e(s),p=(d.value??g).flatMap(o=>y(o)??[]);for(const o of m.value)o.kind==="progress"&&o.threadKey===l&&p.push({data:o.data,toolCallId:o.toolCallId,type:"progress"});return p})}};export{q as useAgentToolEvents};
@@ -0,0 +1 @@
1
+ import{getIdentityStore as k}from"@lunora/client/auth";import{ref as n,onScopeDispose as m,readonly as s}from"vue";import{useLunora as p}from"./LUNORA_INJECTION_KEY-CswQb5zb.mjs";const f=()=>{const e=p(),t=k(e),o=n(e.getAuthToken()),r=n(t.getUser()),u=()=>{o.value=e.getAuthToken()},g=()=>{r.value=t.getUser()},i=e.onAuthTokenChange(u),a=t.subscribe(g);return m(()=>{i(),a()}),{setToken:h=>{e.setAuthToken(h)},token:s(o),user:s(r)}};export{f as useAuth};
@@ -0,0 +1 @@
1
+ import{shallowRef as r}from"vue";import{useLunora as a}from"./LUNORA_INJECTION_KEY-CswQb5zb.mjs";import{e as s}from"./scope-dispose-Dn0gQ2SS.mjs";const f=()=>{const o=a(),t=r(o.connectionStatus()),n=o.onConnectionStatus(e=>{t.value=e});return s(n),t};export{f as default};
@@ -0,0 +1 @@
1
+ import{shallowRef as b,watch as p,toValue as a}from"vue";import{e as v}from"./stable-key-BSG0zK_E.mjs";import{useLunora as _}from"./LUNORA_INJECTION_KEY-CswQb5zb.mjs";const g="__lunora_flags__:eval",y=t=>{const e=typeof t;return e==="boolean"||e==="number"||e==="string"?e:"object"},d={__lunoraRef:g},h=t=>t===void 0?"":v(t),k=(t,e,u)=>{const o=_(),n=y(e),c=b(e);return p(()=>`${a(t)}\0${h(a(u))}`,(x,m,f)=>{const l=a(t),r=a(u);c.value=e;let s;try{s=o.subscribe(d,{context:r,default:e,key:l,type:n},i=>{c.value=i})}catch{return}f(s)},{immediate:!0}),c},w=(t,e)=>{const u=_(),o=b(t),n=v(t);return p(()=>`${n}\0${h(a(e))}`,(c,x,m)=>{const f=a(e);o.value=t;const l=[];for(const[r,s]of Object.entries(t))try{l.push(u.subscribe(d,{context:f,default:s,key:r,type:y(s)},i=>{o.value={...o.value,[r]:i}}))}catch{}m(()=>{for(const r of l)r()})},{immediate:!0}),o};export{k as useFlag,w as useFlags};
@@ -0,0 +1 @@
1
+ import{shallowRef as N,watch as $,toValue as L,onScopeDispose as z,computed as K}from"vue";import{initialPages as U,derivePaginationStatus as E,applyLoadMore as Q,rebalance as q}from"@lunora/client/pagination";import{i as G}from"./is-browser-BEdfLJHK.mjs";import{e as H}from"./stable-key-BSG0zK_E.mjs";import{useLunora as J}from"./LUNORA_INJECTION_KEY-CswQb5zb.mjs";const k=e=>{let r="";for(let i=0;i<e.length;i+=32768)r+=String.fromCharCode(...e.subarray(i,i+32768));return btoa(r)},f="$lunora.wire$",F=64,W="__proto__",X=e=>{if(e===null||typeof e!="object")return!1;const r=Object.getPrototypeOf(e);return r===null||r===Object.prototype},h=(e,r=0)=>{if(r>F)throw new RangeError(`wire-codec: value nesting exceeds the ${F}-level limit`);if(e===void 0)return[f,"undefined"];if(e===null)return null;const i=typeof e;if(i==="bigint")return[f,"bigint",e.toString()];if(i==="number"){const t=e;return Number.isNaN(t)?[f,"nan"]:t===1/0?[f,"inf"]:t===-1/0?[f,"-inf"]:t}if(i!=="object")return e;if(e instanceof Date)return[f,"date",h(e.getTime(),r+1)];if(e instanceof Error){const t=e,o={};for(const b of Object.keys(t))t[b]!==void 0&&(o[b]=h(t[b],r+1));const a=[f,"error",t.name,t.message,o];return t.cause!==void 0&&a.push(h(t.cause,r+1)),a}if(e instanceof URL)return[f,"url",e.href];if(e instanceof Map)return[f,"map",[...e.entries()].map(([t,o])=>[h(t,r+1),h(o,r+1)])];if(e instanceof Set)return[f,"set",[...e].map(t=>h(t,r+1))];if(e instanceof ArrayBuffer)return[f,"bytes",k(new Uint8Array(e)),"ArrayBuffer"];if(ArrayBuffer.isView(e)){const t=e,o=t.constructor.name,a=new Uint8Array(t.buffer,t.byteOffset,t.byteLength);return o==="Uint8Array"?[f,"bytes",k(a)]:[f,"bytes",k(a),o]}if(Array.isArray(e)){const t=e.map(o=>h(o,r+1));return t.length>0&&t[0]===f?[f,"arr",t]:t}if(!X(e)){const t=e.constructor?.name??"value";throw new TypeError(`wire-codec: cannot encode a ${t} over the Lunora wire — only plain objects, arrays, and the supported built-ins (Date, Error, URL, Map, Set, ArrayBuffer/typed arrays, bigint) round-trip`)}const _=e,y={};for(const t of Object.keys(_)){const o=_[t];if(o===void 0)continue;const a=h(o,r+1);t===W?Object.defineProperty(y,t,{configurable:!0,enumerable:!0,value:a,writable:!0}):y[t]=a}return y},D=e=>H(h(e)),R=(e,r)=>`${e}::${D(r)}`,P=(e,r)=>({...r,paginationOpts:{cursor:e.lower,endCursor:e.upper,numItems:e.numItems}}),T=(e,r,i)=>{const _=J(),{initialNumItems:y,shardKey:t}=i,o=N(U(y)),a=N([]);let b;const p=new Map,d=new Map,m=new Set,S=(n,s)=>{a.value=n.map(v=>{const w=R(e.__lunoraRef,P(v,s));return d.get(w)})},V=(n,s,v)=>{const w=u=>R(e.__lunoraRef,P(u,v));for(const u of s){const l=w(u);if(d.has(l))continue;const g=n.find(c=>c.lower===u.lower);if(g){const c=d.get(w(g));c&&d.set(l,c)}}},x=(n,s)=>{const v=new Set;for(const u of n)v.add(R(e.__lunoraRef,P(u,s)));for(const[u,l]of p)v.has(l.currentKey)||(l.unsub(),p.delete(u),d.delete(l.currentKey),m.delete(l.currentKey));const w=new Set([...p.values()].map(u=>u.currentKey));for(const u of n){const l=P(u,s),g=R(e.__lunoraRef,l);if(w.has(g))continue;const c={currentKey:g,unsub:void 0};m.add(g);const M=_.subscribe(e,l,A=>{d.set(c.currentKey,A),m.delete(c.currentKey);const O=L(r);if(S(o.value,O),m.size===0){const I=o.value,j=q(I,a.value);j&&(V(I,j,O),o.value=j)}},{shardKey:t});c.unsub=M,p.set(g,c),w.add(g)}},C=()=>{for(const n of p.values())n.unsub();p.clear(),d.clear(),m.clear()};$(()=>D(L(r)),()=>{if(!G())return;const n=L(r);C(),o.value=U(y),a.value=[],b=void 0,n!=="skip"&&(x(o.value,n),S(o.value,n))},{immediate:!0}),$(()=>o.value,n=>{const s=L(r);s!=="skip"&&(x(n,s),S(n,s))}),z(C);const B=N("LoadingFirstPage");return $([()=>L(r),a],([n,s])=>{B.value=E(n==="skip",s).status},{immediate:!0}),{loadMore:n=>{const s=L(r);if(s==="skip")return;const{nextCursor:v,status:w}=E(!1,a.value);if(w!=="CanLoadMore"||v===b)return;const u=Q(o.value,v,n);if(!u)return;b=v;const l=o.value.at(-1),g=u.at(-2);if(l&&g){const c=R(e.__lunoraRef,P(l,s)),M=R(e.__lunoraRef,P(g,s)),A=p.get(c);if(A&&c!==M){A.currentKey=M,p.set(M,A),p.delete(c);const O=d.get(c);O&&(d.set(M,O),d.delete(c))}}o.value=u},pageResults:a,status:B}},oe=(e,r,i)=>{const{loadMore:_,pageResults:y,status:t}=T(e,r,i),o=K(()=>y.value.flatMap(a=>a?.page??[]));return{isLoading:K(()=>t.value==="LoadingFirstPage"||t.value==="LoadingMore"),loadMore:_,results:o,status:t}},ae=(e,r,i)=>{const{initialNumItems:_}=i,{loadMore:y,pageResults:t,status:o}=T(e,r,i),a=K(()=>t.value.flatMap(m=>m?[m.page]:[])),b=K(()=>o.value==="LoadingFirstPage"),p=K(()=>o.value==="CanLoadMore"),d=K(()=>o.value==="LoadingMore");return{fetchNextPage:m=>{y(m??_)},hasNextPage:p,isFetchingNextPage:d,isLoading:b,pages:a,status:o}};export{ae as useInfiniteQuery,oe as usePaginatedQuery};
@@ -0,0 +1 @@
1
+ import{createMutationRunner as v}from"@lunora/client";import{shallowRef as a,ref as l}from"vue";import{useLunora as d}from"./LUNORA_INJECTION_KEY-CswQb5zb.mjs";const c=u=>{const i=d(),t=a(void 0),r=a(void 0),o=l(!1),n=()=>{t.value=void 0,r.value=void 0},s=v(i,u,{setError:e=>{r.value=e},setPending:e=>{o.value=e},setResult:e=>{t.value=e,r.value=void 0}});return{data:t,error:r,mutate:s,pending:o,reset:n}};export{c as useMutation};
@@ -0,0 +1 @@
1
+ import{createMutatorRunner as i}from"@lunora/client";import{shallowRef as o,computed as m}from"vue";const p=u=>{const e=o(void 0),t=o(!1),a=m(()=>e.value!==void 0),{mutate:s,reset:n}=i(u,{setError:r=>{e.value=r},setPending:r=>{t.value=r}});return{error:e,isError:a,mutate:s,pending:t,reset:n}};export{p as useMutator};
@@ -0,0 +1 @@
1
+ import{shallowRef as I}from"vue";import{i as h}from"./is-browser-BEdfLJHK.mjs";import{useLunora as b}from"./LUNORA_INJECTION_KEY-CswQb5zb.mjs";import{e as g}from"./scope-dispose-Dn0gQ2SS.mjs";const $=(e="sess")=>{if(typeof crypto<"u"){if(typeof crypto.randomUUID=="function")return crypto.randomUUID();if(typeof crypto.getRandomValues=="function"){const t=crypto.getRandomValues(new Uint8Array(16));return`${e}-${Array.from(t,o=>o.toString(16).padStart(2,"0")).join("")}`}}return`${e}-${Date.now().toString(36)}`},w=1e4,S=(e,t)=>{const o=b(),{heartbeat:u,intervalMs:m=w,listPresent:y,shardKey:s}=t,i=t.sessionId??$(),c=I(void 0);let a=t.data;const n=()=>{const r={roomId:e,sessionId:i,...a===void 0?{}:{data:a}};o.mutation(u,r,{shardKey:s}).catch(()=>{})},f=r=>{a=r,n()};if(h()){n();const r=setInterval(n,m),d=()=>{typeof document<"u"&&document.visibilityState==="visible"&&n()};typeof document<"u"&&document.addEventListener("visibilitychange",d);const p=o.acquireConnectionContext({roomId:e,sessionId:i},{shardKey:s}),l=o.subscribe(y,{roomId:e},v=>{c.value=v},{shardKey:s});g(()=>{clearInterval(r),typeof document<"u"&&document.removeEventListener("visibilitychange",d),p(),l()})}return{present:c,sessionId:i,setData:f}};export{S as usePresence};
@@ -0,0 +1 @@
1
+ import{evaluate as u}from"@lunora/ratelimit";import{shallowRef as d,toValue as r,watchEffect as b,onScopeDispose as A,computed as f}from"vue";const L=(s,i={})=>{const a=i.now??Date.now,k=i.tickMs??1e3;let e;const w=d(0),l=()=>{w.value+=1},o=d(u(r(s),e,{consume:!1,count:1,now:a(),reserve:!1}).status),p=b(()=>{o.value=u(r(s),e,{consume:!1,count:1,now:a(),reserve:!1}).status},{flush:"sync"});let t;const n=()=>{t!==void 0&&(clearInterval(t),t=void 0)},m=()=>{o.value.ok||t!==void 0||(t=setInterval(()=>{l(),o.value.ok&&n()},k))};A(()=>{n(),p()}),m();const h=(c=1)=>{const v=u(r(s),e,{consume:!0,count:c,now:a(),reserve:!1});return v.value!==void 0&&(e=v.value),l(),m(),v.status},y=(c=1)=>u(r(s),e,{consume:!1,count:c,now:a(),reserve:!1}).status.ok,R=()=>{e=void 0,n(),l()};return{check:y,consume:h,disabled:f(()=>!o.value.ok),ok:f(()=>o.value.ok),reset:R,retryAfter:f(()=>o.value.retryAfter)}};export{L as useRateLimit};
@@ -0,0 +1 @@
1
+ import{ref as n,watch as h,toValue as y,onScopeDispose as w}from"vue";import{useLunora as x}from"./LUNORA_INJECTION_KEY-CswQb5zb.mjs";const B=(m,v,l={})=>{const d=x(),a=n([]),u=n(void 0),e=n("idle");let t;const c=()=>{t?.()};return h(()=>y(v),(i,S,p)=>{if(a.value=[],u.value=void 0,i==="skip"){e.value="idle";return}e.value="streaming";let o=!0;const f=d.stream(m,i,{maxBuffer:l.maxBuffer,shardKey:l.shardKey}),s=()=>{f.cancel()};t=s,(async()=>{try{for await(const r of f){if(!o)return;a.value=[...a.value,r]}o&&(e.value="complete")}catch(r){if(!o)return;u.value=r instanceof Error?r:new Error(String(r)),e.value="error"}})().catch(()=>{}),p(()=>{o=!1,s(),t===s&&(t=void 0)})},{immediate:!0}),w(()=>{c()}),{cancel:c,chunks:a,error:u,status:e}};export{B as useStream};
@@ -0,0 +1 @@
1
+ import{createQuerySubscription as n}from"@lunora/client/query";import{LunoraError as p}from"@lunora/errors";import{ref as a,watch as c,toValue as l,onScopeDispose as f}from"vue";import{i as w}from"./is-browser-BEdfLJHK.mjs";import{useLunora as h}from"./LUNORA_INJECTION_KEY-CswQb5zb.mjs";const K=(s,t,u={})=>{const v=h(),o=a(void 0),e=a(void 0);return c(()=>l(t),(i,y,d)=>{if(i==="skip"){o.value=void 0,e.value=void 0;return}if(!w())return;const m=n(v,s,i,{onData:r=>{o.value=r,e.value=void 0},onError:r=>{e.value=r.code===void 0?new Error(r.message):new p(r.code,r.message),o.value=void 0},onReset:()=>{o.value=void 0}},{shardKey:u.shardKey});d(m)},{immediate:!0}),f(()=>{o.value=void 0,e.value=void 0}),{data:o,error:e}};export{K as useSubscription};
@@ -0,0 +1 @@
1
+ import{ref as y,onScopeDispose as F,toValue as L}from"vue";import{useLunora as R}from"./LUNORA_INJECTION_KEY-CswQb5zb.mjs";const W=t=>{if(t.length===0)return 0;let s=0;for(const n of t)s+=n*n;return Math.sqrt(s/t.length)},B=(t,s)=>{const n=s/16e3,o=n>1?Math.floor(t.length/n):t.length,d=new ArrayBuffer(o*2),i=new DataView(d);for(let c=0;c<o;c+=1){const v=t[Math.floor(c*n)]??0,g=Math.max(-1,Math.min(1,v));i.setInt16(c*2,g<0?g*32768:g*32767,!0)}return new Uint8Array(d)},I=async t=>{const s=globalThis,n=s.navigator?.mediaDevices?.getUserMedia.bind(s.navigator.mediaDevices),o=s.AudioContext??s.webkitAudioContext;if(!n||!o)throw new Error("useVoiceAgent: microphone capture requires getUserMedia + AudioContext (no browser audio available)");const d=await n({audio:{channelCount:1,echoCancellation:!0,noiseSuppression:!0}}),i=new o,c=i.createMediaStreamSource(d),v=i.createScriptProcessor(4096,1,1);let g=!1,m=!1,f=0,a=0;return v.onaudioprocess=u=>{const p=u.inputBuffer.getChannelData(0),h=g?0:W(p);if(t.onLevel(h),g)return;if(t.onAudio(B(p,i.sampleRate)),t.isSpeaking()){a=h>=t.interruptThreshold?a+1:0,a>=t.interruptChunks&&(a=0,t.onInterrupt());return}a=0;const w=p.length/i.sampleRate*1e3;if(h>=t.silenceThreshold){m=!0,f=0;return}m&&(f+=w,f>=t.silenceDurationMs&&(m=!1,f=0,t.onSilence()))},c.connect(v),v.connect(i.destination),{setMuted:u=>{g=u},stop:()=>{v.disconnect(),c.disconnect();for(const u of d.getTracks())u.stop();i.close()}}},J=()=>{const t=globalThis,s=t.AudioContext??t.webkitAudioContext;if(!s)throw new Error("useVoiceAgent: audio playback requires AudioContext (no browser audio available)");const n=new s,o=new Set;let d=0,i=Promise.resolve(),c=0;const v=async(f,a)=>{if(a!==c)return;let u;try{u=await n.decodeAudioData(f.buffer)}catch{return}if(a!==c)return;const p=n.createBufferSource();p.buffer=u,p.connect(n.destination);const h=Math.max(n.currentTime,d);p.start(h),d=h+u.duration,o.add(p),p.onended=()=>{o.delete(p)}},g=f=>{const a=Uint8Array.from(f),u=c;i=i.then(()=>v(a,u))},m=()=>{c+=1;for(const f of o)try{f.stop()}catch{}o.clear(),d=n.currentTime};return{enqueue:g,interrupt:m,stop:()=>{m(),n.close()}}},D=1,K=.01,N=1200,P=.15,O=3,j=t=>t.startsWith("https://")?`wss://${t.slice(8)}`:t.startsWith("http://")?`ws://${t.slice(7)}`:t,G=t=>{const s=t.__lunoraRef,n=s.startsWith("agents:")?s.slice(7):s;return n.endsWith("Voice")?n.slice(0,-5):n},H=(t,s,n)=>{const o=j(t),d=o.endsWith("/")?o.slice(0,-1):o,i=new URLSearchParams({threadKey:n});return`${d}/_lunora/voice/${encodeURIComponent(s)}?${i.toString()}`},X=t=>{const{createMicrophone:s=I,createSpeaker:n=J,createSocket:o,interruptChunks:d=O,interruptThreshold:i=P,silenceDurationMs:c=N,silenceThreshold:v=K,threadKey:g,voice:m}=t,f=R(),a=y("idle"),u=y(!1),p=y(""),h=y(""),w=y(0),b=y(!1),A=y(void 0);let l,S=!1;const C=r=>{const e=l?.socket;return e?.readyState===D?(e.send(JSON.stringify(r)),!0):!1},M=()=>{const r=l;if(l=void 0,r){r.microphone?.stop(),r.speaker?.stop();try{r.socket.close()}catch{}}S=!1,u.value=!1,a.value="idle",w.value=0},U=M,V=r=>{const e=l;switch(r.type){case"assistant_delta":{e&&(e.speaking=!0),a.value="speaking",h.value+=r.text;break}case"assistant_done":{e&&(e.speaking=!1),h.value=r.text,a.value="listening";break}case"error":{e&&(e.speaking=!1),A.value=new Error(r.message),a.value="listening";break}case"interrupted":{e&&(e.speaking=!1,e.suppressAudio=!1),e?.speaker?.interrupt(),a.value="listening";break}case"ready":{e&&(e.audioFormat=r.audioFormat,e.suppressAudio=!1),u.value=!0,a.value="listening";break}case"user_transcript":{e&&(e.suppressAudio=!1),p.value=r.text,h.value="",a.value="thinking";break}}},$=r=>{const e=l;!e||e.suppressAudio||(e.speaker??=n({audioFormat:e.audioFormat}),e.speaking=!0,a.value="speaking",e.speaker.enqueue(r))},E=async()=>{if(!(l||S)){S=!0,A.value=void 0,p.value="",h.value="";try{const r=H(f.url,G(m),L(g)),e=(o??(k=>new globalThis.WebSocket(k)))(r);e.binaryType="arraybuffer";const x={audioFormat:"mp3",microphone:void 0,socket:e,speaker:void 0,speaking:!1,suppressAudio:!1};l=x,e.onmessage=k=>{if(typeof k.data=="string"){try{V(JSON.parse(k.data))}catch{}return}$(new Uint8Array(k.data))},e.onerror=()=>{A.value=new Error("useVoiceAgent: voice socket error")},e.onclose=()=>{l===x&&M()};const T=await s({interruptChunks:d,interruptThreshold:i,isSpeaking:()=>l?.speaking??!1,onAudio:k=>{e.readyState===D&&e.send(k)},onInterrupt:()=>{C({type:"interrupt"}),l?.speaker?.interrupt(),l&&(l.speaking=!1,l.suppressAudio=!0),a.value="listening"},onLevel:k=>{w.value=k},onSilence:()=>{C({type:"commit"}),a.value="thinking"},silenceDurationMs:c,silenceThreshold:v});l===x?(x.microphone=T,b.value=!1,a.value="listening"):T.stop()}catch(r){A.value=r instanceof Error?r:new Error(String(r)),M()}finally{S=!1}}},_=()=>{const r=!b.value;return l?.microphone?.setMuted(r),b.value=r,r},q=r=>{C({text:r,type:"text"})&&(a.value="thinking")};return F(M),{audioLevel:w,connected:u,endCall:U,error:A,interimTranscript:h,isMuted:b,sendText:q,startCall:E,status:a,toggleMute:_,transcript:p}};export{X as useVoiceAgent};
package/dist/server.mjs CHANGED
@@ -1 +1 @@
1
- export { createServerClient, deserializePreloaded, getServerSession, preloadQuery, preloadedQueryResult, serializePreloaded } from '@lunora/client/ssr';
1
+ import{createServerClient as d,deserializePreloaded as l,getServerSession as a,preloadQuery as o,preloadedQueryResult as i,serializePreloaded as s}from"@lunora/client/ssr";export{d as createServerClient,l as deserializePreloaded,a as getServerSession,o as preloadQuery,i as preloadedQueryResult,s as serializePreloaded};
@@ -0,0 +1,2 @@
1
+ export { RestrictionError, UploadControl, UploadError, type UploadMethod, type UploadRestrictions, type UploadResult } from '@visulima/storage-client';
2
+ export { type UseChunkedRestUploadOptions, type UseChunkedRestUploadReturn, type UseFileInputOptions, type UseFileInputReturn, type UseMultipartUploadOptions, type UseMultipartUploadReturn, type UsePasteUploadOptions, type UsePasteUploadReturn, type UseTusUploadOptions, type UseTusUploadReturn, type UseUploadOptions, type UseUploadReturn, useChunkedRestUpload, useFileInput, useMultipartUpload, usePasteUpload, useTusUpload, useUpload } from '@visulima/storage-client/vue';
@@ -0,0 +1,2 @@
1
+ export { RestrictionError, UploadControl, UploadError, type UploadMethod, type UploadRestrictions, type UploadResult } from '@visulima/storage-client';
2
+ export { type UseChunkedRestUploadOptions, type UseChunkedRestUploadReturn, type UseFileInputOptions, type UseFileInputReturn, type UseMultipartUploadOptions, type UseMultipartUploadReturn, type UsePasteUploadOptions, type UsePasteUploadReturn, type UseTusUploadOptions, type UseTusUploadReturn, type UseUploadOptions, type UseUploadReturn, useChunkedRestUpload, useFileInput, useMultipartUpload, usePasteUpload, useTusUpload, useUpload } from '@visulima/storage-client/vue';
@@ -0,0 +1 @@
1
+ import{RestrictionError as r,UploadControl as p,UploadError as l}from"@visulima/storage-client";import{useChunkedRestUpload as t,useFileInput as u,useMultipartUpload as a,usePasteUpload as d,useTusUpload as U,useUpload as i}from"@visulima/storage-client/vue";export{r as RestrictionError,p as UploadControl,l as UploadError,t as useChunkedRestUpload,u as useFileInput,a as useMultipartUpload,d as usePasteUpload,U as useTusUpload,i as useUpload};
package/dist/worker.mjs CHANGED
@@ -1 +1 @@
1
- export { withFrameworkWorker as withLunora } from '@lunora/runtime';
1
+ import{withFrameworkWorker as a}from"@lunora/runtime";export{a as withLunora};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/vue",
3
- "version": "1.0.0-alpha.7",
3
+ "version": "1.0.0-alpha.71",
4
4
  "description": "Vue adapter for Lunora — live composables, optimistic mutations, and reactive loaders",
5
5
  "keywords": [
6
6
  "cloudflare",
@@ -48,15 +48,21 @@
48
48
  "types": "./dist/worker.d.ts",
49
49
  "import": "./dist/worker.mjs"
50
50
  },
51
+ "./upload": {
52
+ "types": "./dist/upload.d.ts",
53
+ "import": "./dist/upload.mjs"
54
+ },
51
55
  "./package.json": "./package.json"
52
56
  },
53
57
  "publishConfig": {
54
58
  "access": "public"
55
59
  },
56
60
  "dependencies": {
57
- "@lunora/client": "1.0.0-alpha.3",
58
- "@lunora/ratelimit": "1.0.0-alpha.3",
59
- "@lunora/runtime": "1.0.0-alpha.5"
61
+ "@lunora/client": "1.0.0-alpha.43",
62
+ "@lunora/errors": "1.0.0-alpha.16",
63
+ "@lunora/ratelimit": "1.0.0-alpha.19",
64
+ "@lunora/runtime": "1.0.0-alpha.56",
65
+ "@visulima/storage-client": "1.0.0"
60
66
  },
61
67
  "peerDependencies": {
62
68
  "vue": "^3.5.0"
@@ -1,29 +0,0 @@
1
- import { defineComponent, computed } from 'vue';
2
- import { useAuth } from './useAuth-C2aEzXXH.mjs';
3
-
4
- const Authenticated = defineComponent({
5
- name: "Authenticated",
6
- setup(_props, { slots }) {
7
- const { token, user } = useAuth();
8
- const isAuthenticated = computed(() => token.value !== null && user.value !== null);
9
- return () => isAuthenticated.value ? slots.default?.() : void 0;
10
- }
11
- });
12
- const Unauthenticated = defineComponent({
13
- name: "Unauthenticated",
14
- setup(_props, { slots }) {
15
- const { token, user } = useAuth();
16
- const isLoading = computed(() => token.value !== null && user.value === null);
17
- return () => !isLoading.value && token.value === null ? slots.default?.() : void 0;
18
- }
19
- });
20
- const AuthLoading = defineComponent({
21
- name: "AuthLoading",
22
- setup(_props, { slots }) {
23
- const { token, user } = useAuth();
24
- const isLoading = computed(() => token.value !== null && user.value === null);
25
- return () => isLoading.value ? slots.default?.() : void 0;
26
- }
27
- });
28
-
29
- export { AuthLoading, Authenticated, Unauthenticated };
@@ -1,22 +0,0 @@
1
- import { inject, provide } from 'vue';
2
-
3
- const LUNORA_INJECTION_KEY = /* @__PURE__ */ Symbol("lunora.client");
4
- const createLunora = (client) => {
5
- return {
6
- install(app) {
7
- app.provide(LUNORA_INJECTION_KEY, client);
8
- }
9
- };
10
- };
11
- const provideLunora = (client) => {
12
- provide(LUNORA_INJECTION_KEY, client);
13
- };
14
- const useLunora = () => {
15
- const client = inject(LUNORA_INJECTION_KEY, void 0);
16
- if (!client) {
17
- throw new Error("useLunora(): no LunoraClient provided — call app.use(createLunora(client)) or provideLunora(client) in a parent setup().");
18
- }
19
- return client;
20
- };
21
-
22
- export { LUNORA_INJECTION_KEY, createLunora, provideLunora, useLunora };
@@ -1,14 +0,0 @@
1
- import { useLunora } from './LUNORA_INJECTION_KEY-DtFXLDQ_.mjs';
2
- import { subscribeToQuery } from './subscribeToQuery-Cv5YL-SI.mjs';
3
-
4
- const hydratePreloaded = (preloaded) => {
5
- const client = useLunora();
6
- const { args, functionPath, shardKey, value } = preloaded;
7
- const functionReference = { __lunoraRef: functionPath };
8
- return subscribeToQuery(client, functionReference, args, {
9
- seed: value,
10
- shardKey
11
- });
12
- };
13
-
14
- export { hydratePreloaded };
@@ -1,51 +0,0 @@
1
- import { createQuerySubscription } from '@lunora/client/query';
2
- import { shallowRef, getCurrentScope, onScopeDispose, watch, toValue } from 'vue';
3
- import { useLunora } from './LUNORA_INJECTION_KEY-DtFXLDQ_.mjs';
4
-
5
- const subscribeToQuery = (client, function_, args, options = {}) => {
6
- const data = shallowRef(options.seed);
7
- const unsubscribe = client.subscribe(
8
- function_,
9
- args,
10
- (value) => {
11
- data.value = value;
12
- },
13
- { shardKey: options.shardKey }
14
- );
15
- if (getCurrentScope()) {
16
- onScopeDispose(unsubscribe);
17
- } else {
18
- console.warn(
19
- "[@lunora/vue] subscribeToQuery called with no active effect scope — its subscription will not be cleaned up automatically. Call it inside setup()/an effect scope, or call the returned teardown yourself."
20
- );
21
- }
22
- return data;
23
- };
24
- const useQuery = (function_, args, options = {}) => {
25
- const client = useLunora();
26
- const data = shallowRef(void 0);
27
- watch(
28
- () => toValue(args),
29
- (current, _previous, onCleanup) => {
30
- const unsubscribe = createQuerySubscription(
31
- client,
32
- function_,
33
- current,
34
- {
35
- onData: (value) => {
36
- data.value = value;
37
- },
38
- onReset: () => {
39
- data.value = void 0;
40
- }
41
- },
42
- { shardKey: options.shardKey }
43
- );
44
- onCleanup(unsubscribe);
45
- },
46
- { immediate: true }
47
- );
48
- return data;
49
- };
50
-
51
- export { subscribeToQuery, useQuery };
@@ -1,28 +0,0 @@
1
- import { getIdentityStore } from '@lunora/client/auth';
2
- import { ref, onScopeDispose, readonly } from 'vue';
3
- import { useLunora } from './LUNORA_INJECTION_KEY-DtFXLDQ_.mjs';
4
-
5
- const useAuth = () => {
6
- const client = useLunora();
7
- const store = getIdentityStore(client);
8
- const tokenRef = ref(client.getAuthToken());
9
- const userRef = ref(store.getUser());
10
- const onTokenChange = () => {
11
- tokenRef.value = client.getAuthToken();
12
- };
13
- const onUserChange = () => {
14
- userRef.value = store.getUser();
15
- };
16
- const unsubToken = client.onAuthTokenChange(onTokenChange);
17
- const unsubUser = store.subscribe(onUserChange);
18
- onScopeDispose(() => {
19
- unsubToken();
20
- unsubUser();
21
- });
22
- const setToken = (next) => {
23
- client.setAuthToken(next);
24
- };
25
- return { setToken, token: readonly(tokenRef), user: readonly(userRef) };
26
- };
27
-
28
- export { useAuth };
@@ -1,20 +0,0 @@
1
- import { shallowRef, getCurrentScope, onScopeDispose } from 'vue';
2
- import { useLunora } from './LUNORA_INJECTION_KEY-DtFXLDQ_.mjs';
3
-
4
- const useConnectionStatus = () => {
5
- const client = useLunora();
6
- const status = shallowRef(client.connectionStatus());
7
- const unsubscribe = client.onConnectionStatus((next) => {
8
- status.value = next;
9
- });
10
- if (getCurrentScope()) {
11
- onScopeDispose(unsubscribe);
12
- } else {
13
- console.warn(
14
- "[@lunora/vue] useConnectionStatus called with no active effect scope — its listener will not be cleaned up automatically. Call it inside setup()/an effect scope."
15
- );
16
- }
17
- return status;
18
- };
19
-
20
- export { useConnectionStatus as default };
@@ -1,199 +0,0 @@
1
- import { shallowRef, watch, toValue, onScopeDispose, computed } from 'vue';
2
- import { initialPages, derivePaginationStatus, rebalance, applyLoadMore } from '@lunora/client/pagination';
3
- import { useLunora } from './LUNORA_INJECTION_KEY-DtFXLDQ_.mjs';
4
-
5
- const buildPageKey = (functionPath, pageArgs) => `${functionPath}::${JSON.stringify(pageArgs)}`;
6
- const buildPageArgs = (page, baseArgs) => {
7
- return {
8
- ...baseArgs,
9
- paginationOpts: { cursor: page.lower, endCursor: page.upper, numItems: page.numItems }
10
- };
11
- };
12
- const usePaginatedCore = (function_, args, options) => {
13
- const client = useLunora();
14
- const { initialNumItems, shardKey } = options;
15
- const pages = shallowRef(initialPages(initialNumItems));
16
- const pageResults = shallowRef([]);
17
- const activeSubs = /* @__PURE__ */ new Map();
18
- const resultsByKey = /* @__PURE__ */ new Map();
19
- const pendingPageKeys = /* @__PURE__ */ new Set();
20
- const rebuildPageResults = (currentPages, baseArgs) => {
21
- pageResults.value = currentPages.map((page) => {
22
- const key = buildPageKey(function_["__lunoraRef"], buildPageArgs(page, baseArgs));
23
- return resultsByKey.get(key);
24
- });
25
- };
26
- const migrateResultsForRebalance = (oldPages, newPages, baseArgs) => {
27
- const keyOf = (page) => buildPageKey(function_["__lunoraRef"], buildPageArgs(page, baseArgs));
28
- for (const newPage of newPages) {
29
- const newKey = keyOf(newPage);
30
- if (resultsByKey.has(newKey)) {
31
- continue;
32
- }
33
- const donor = oldPages.find((op) => op.lower === newPage.lower);
34
- if (donor) {
35
- const carried = resultsByKey.get(keyOf(donor));
36
- if (carried) {
37
- resultsByKey.set(newKey, carried);
38
- }
39
- }
40
- }
41
- };
42
- const syncSubscriptions = (currentPages, baseArgs) => {
43
- const wantedKeys = /* @__PURE__ */ new Set();
44
- for (const page of currentPages) {
45
- wantedKeys.add(buildPageKey(function_["__lunoraRef"], buildPageArgs(page, baseArgs)));
46
- }
47
- for (const [originalKey, entry] of activeSubs) {
48
- if (!wantedKeys.has(entry.currentKey)) {
49
- entry.unsub();
50
- activeSubs.delete(originalKey);
51
- resultsByKey.delete(entry.currentKey);
52
- }
53
- }
54
- const coveredKeys = new Set([...activeSubs.values()].map((subEntry) => subEntry.currentKey));
55
- for (const page of currentPages) {
56
- const pageArgs = buildPageArgs(page, baseArgs);
57
- const key = buildPageKey(function_["__lunoraRef"], pageArgs);
58
- if (coveredKeys.has(key)) {
59
- continue;
60
- }
61
- const entry = {
62
- currentKey: key,
63
- unsub: void 0
64
- };
65
- pendingPageKeys.add(key);
66
- const unsub = client.subscribe(
67
- function_,
68
- pageArgs,
69
- (value) => {
70
- resultsByKey.set(entry.currentKey, value);
71
- pendingPageKeys.delete(entry.currentKey);
72
- const currentBaseArgs = toValue(args);
73
- rebuildPageResults(pages.value, currentBaseArgs);
74
- if (pendingPageKeys.size === 0) {
75
- const latestPages = pages.value;
76
- const next = rebalance(latestPages, pageResults.value);
77
- if (next) {
78
- migrateResultsForRebalance(latestPages, next, currentBaseArgs);
79
- pages.value = next;
80
- }
81
- }
82
- },
83
- { shardKey }
84
- );
85
- entry.unsub = unsub;
86
- activeSubs.set(key, entry);
87
- coveredKeys.add(key);
88
- }
89
- };
90
- const teardownAll = () => {
91
- for (const entry of activeSubs.values()) {
92
- entry.unsub();
93
- }
94
- activeSubs.clear();
95
- resultsByKey.clear();
96
- };
97
- watch(
98
- () => toValue(args),
99
- (current) => {
100
- teardownAll();
101
- pages.value = initialPages(initialNumItems);
102
- pageResults.value = [];
103
- if (current !== "skip") {
104
- syncSubscriptions(pages.value, current);
105
- rebuildPageResults(pages.value, current);
106
- }
107
- },
108
- { immediate: true }
109
- );
110
- watch(
111
- () => pages.value,
112
- (currentPages) => {
113
- const current = toValue(args);
114
- if (current !== "skip") {
115
- syncSubscriptions(currentPages, current);
116
- rebuildPageResults(currentPages, current);
117
- }
118
- }
119
- );
120
- onScopeDispose(teardownAll);
121
- const status = shallowRef("LoadingFirstPage");
122
- watch(
123
- [() => toValue(args), pageResults],
124
- ([currentArgs, currentResults]) => {
125
- status.value = derivePaginationStatus(currentArgs === "skip", currentResults).status;
126
- },
127
- { immediate: true }
128
- );
129
- const loadMore = (numberItems) => {
130
- const currentArgs = toValue(args);
131
- if (currentArgs === "skip") {
132
- return;
133
- }
134
- const { nextCursor, status: currentStatus } = derivePaginationStatus(false, pageResults.value);
135
- if (currentStatus !== "CanLoadMore") {
136
- return;
137
- }
138
- const next = applyLoadMore(pages.value, nextCursor, numberItems);
139
- if (!next) {
140
- return;
141
- }
142
- const oldTail = pages.value.at(-1);
143
- const newPinnedPage = next.at(-2);
144
- if (oldTail && newPinnedPage) {
145
- const oldKey = buildPageKey(function_["__lunoraRef"], buildPageArgs(oldTail, currentArgs));
146
- const newKey = buildPageKey(function_["__lunoraRef"], buildPageArgs(newPinnedPage, currentArgs));
147
- const entry = activeSubs.get(oldKey);
148
- if (entry && oldKey !== newKey) {
149
- entry.currentKey = newKey;
150
- activeSubs.set(newKey, entry);
151
- activeSubs.delete(oldKey);
152
- const carried = resultsByKey.get(oldKey);
153
- if (carried) {
154
- resultsByKey.set(newKey, carried);
155
- resultsByKey.delete(oldKey);
156
- }
157
- }
158
- }
159
- pages.value = next;
160
- };
161
- return { loadMore, pageResults, status };
162
- };
163
-
164
- const usePaginatedQuery = (function_, args, options) => {
165
- const { loadMore, pageResults, status } = usePaginatedCore(function_, args, options);
166
- const results = computed(() => {
167
- const items = [];
168
- for (const result of pageResults.value) {
169
- if (result) {
170
- items.push(...result.page);
171
- }
172
- }
173
- return items;
174
- });
175
- const isLoading = computed(() => status.value === "LoadingFirstPage" || status.value === "LoadingMore");
176
- return { isLoading, loadMore, results, status };
177
- };
178
- const useInfiniteQuery = (function_, args, options) => {
179
- const { initialNumItems } = options;
180
- const { loadMore, pageResults, status } = usePaginatedCore(function_, args, options);
181
- const pages = computed(() => {
182
- const result = [];
183
- for (const page of pageResults.value) {
184
- if (page) {
185
- result.push(page.page);
186
- }
187
- }
188
- return result;
189
- });
190
- const isLoading = computed(() => status.value === "LoadingFirstPage");
191
- const hasNextPage = computed(() => status.value === "CanLoadMore");
192
- const isFetchingNextPage = computed(() => status.value === "LoadingMore");
193
- const fetchNextPage = (numberItems) => {
194
- loadMore(numberItems ?? initialNumItems);
195
- };
196
- return { fetchNextPage, hasNextPage, isFetchingNextPage, isLoading, pages, status };
197
- };
198
-
199
- export { useInfiniteQuery, usePaginatedQuery };
@@ -1,29 +0,0 @@
1
- import { createMutationRunner } from '@lunora/client';
2
- import { shallowRef, ref } from 'vue';
3
- import { useLunora } from './LUNORA_INJECTION_KEY-DtFXLDQ_.mjs';
4
-
5
- const useMutation = (function_) => {
6
- const client = useLunora();
7
- const data = shallowRef(void 0);
8
- const error = shallowRef(void 0);
9
- const pending = ref(false);
10
- const reset = () => {
11
- data.value = void 0;
12
- error.value = void 0;
13
- };
14
- const mutate = createMutationRunner(client, function_, {
15
- setError: (next) => {
16
- error.value = next;
17
- },
18
- setPending: (next) => {
19
- pending.value = next;
20
- },
21
- setResult: (result) => {
22
- data.value = result;
23
- error.value = void 0;
24
- }
25
- });
26
- return { data, error, mutate, pending, reset };
27
- };
28
-
29
- export { useMutation };