@lunora/react 1.0.0-alpha.106 → 1.0.0-alpha.108

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/README.md CHANGED
@@ -108,7 +108,7 @@ function MessageList({ room }: { room: string }) {
108
108
  | `useStream(fn, args, options?)` | `{ chunks, status, error, cancel }` | Consumes a streamed action response chunk by chunk. |
109
109
  | `useRateLimit(config, options?)` | `{ ok, disabled, retryAfter, check, consume, reset }` | Client-side mirror of a `@lunora/ratelimit` budget for instant UX. |
110
110
  | `useConnectionStatus()` | `ConnectionStatus` | `idle` / `connecting` / `connected` / `offline`. |
111
- | `useAuth()` | `{ user, token, setToken }` | Call `setToken(jwt)` after sign-in; RPC then carries the token. |
111
+ | `useAuth()` | `{ user, token, status, setToken }` | Call `setToken(jwt)` after sign-in; RPC then carries the token. |
112
112
  | `useAuthState()` | `{ isAuthenticated, isLoading }` | Hydration-safe three-state gate. |
113
113
  | `useAgentToolEvents({ api, threadKey, … })` | `{ events }` | One agent thread's tool lifecycle: call / result / awaiting-approval / progress. |
114
114
  | `useVoiceAgent({ voice, threadKey, … })` | `{ status, transcript, startCall, endCall, … }` | Full-duplex voice call: mic capture, playback, live transcripts, barge-in. |
package/dist/index.d.mts CHANGED
@@ -3,6 +3,7 @@ import { LunoraClient, OptimisticUpdate, User, SubscriptionErrorCallback, Subscr
3
3
  export { type ArgsOf, type AuthImpersonation, type AuthPage, type AuthSession, type AuthUser, type ClientQueryRef, type FunctionReference, type HttpStreamArgsOf, type HttpStreamChunkOf, type HttpStreamRef, type LunoraClient, type LunoraErrorCode, type MutatorHandle, type MutatorTransaction, type OptimisticLocalStore, type OptimisticUpdate, type Preloaded, type ReturnOf, type SubscriptionError, type SubscriptionErrorCallback, type User, createClientQuery, getErrorCode, getRetryAfterMs, isConflictError, isForbiddenError, isRateLimitedError, isUnauthorizedError } from '@lunora/client';
4
4
  import { QueryClient } from '@tanstack/react-query';
5
5
  export { type L as LunoraQueryOptions, l as lunoraQueryOptions } from "./packem_shared/query-options.d-CdgGQ9s4.mjs";
6
+ import { AuthStatus } from '@lunora/client/auth';
6
7
  import { PaginationStatus } from '@lunora/client/pagination';
7
8
  export type { PaginationResult, PaginationStatus } from '@lunora/client/pagination';
8
9
  import { RateLimitStatus, RateLimitConfig } from '@lunora/ratelimit';
@@ -11,29 +12,36 @@ export { type UploadMethod, type UploadResult, type UseChunkedRestUploadOptions,
11
12
  interface AuthGateProps {
12
13
  children: ReactNode;
13
14
  }
14
- /** Renders `children` only once a token is set on the client (after hydration). */
15
+ /**
16
+ * Renders `children` once authentication has settled in the caller's favour — a
17
+ * credential is held and nothing has contradicted it. Follows the shared
18
+ * `AuthStatus` contract in `@lunora/client/auth`, so an unreachable identity
19
+ * endpoint keeps the gate open (with `useAuth().user` still `null`).
20
+ */
15
21
  declare const Authenticated: ({ children }: AuthGateProps) => ReactNode;
16
- /** Renders `children` only when auth has settled and no token is set. */
22
+ /** Renders `children` only when auth has settled and there is no session. */
17
23
  declare const Unauthenticated: ({ children }: AuthGateProps) => ReactNode;
18
- /** Renders `children` while auth is still settling (before hydration completes). */
24
+ /** Renders `children` while auth is still settling — before hydration, or while the first identity resolve is in flight. */
19
25
  declare const AuthLoading: ({ children }: AuthGateProps) => ReactNode;
20
26
  /**
21
- * Resolved auth-gate state. `isLoading` covers the window before the client has
22
- * hydrated — the server render and the first hydration render both report
23
- * loading, so the markup agrees and no signed-out UI flashes in.
27
+ * Resolved auth-gate state, derived from the shared `AuthStatus` contract in
28
+ * `@lunora/client/auth` — the same mapping Vue, Solid, Svelte and Angular use.
24
29
  */
25
30
  interface AuthState {
26
31
  isAuthenticated: boolean;
27
32
  isLoading: boolean;
28
33
  }
29
34
  /**
30
- * Three-state auth status for gating UI. Reports `isLoading` until the client
31
- * has hydrated, then `isAuthenticated` tracks whether a token is set on the
32
- * shared client.
35
+ * Three-state auth status for gating UI.
36
+ *
37
+ * `isLoading` covers the server render and the first hydration render (the
38
+ * identity store's server snapshot is `"loading"`, so the markup agrees and no
39
+ * signed-out UI flashes in) as well as the window where a credential is held and
40
+ * its first identity resolve is still in flight.
33
41
  *
34
- * Lunora auth is token-based and resolves synchronously once the token is
35
- * known, so the loading window is hydration rather than a server round-trip —
36
- * use it (via {@link AuthState}) to render a fallback while it settles.
42
+ * `isAuthenticated` follows the credential, not the identity record: an
43
+ * unreachable identity endpoint keeps the gate open with `user === null`. A UI
44
+ * that needs to tell that apart reads `useAuth().status`.
37
45
  */
38
46
  declare const useAuthState: () => AuthState;
39
47
  interface LunoraProviderProps {
@@ -142,6 +150,12 @@ interface UseInfiniteQueryResult<T> {
142
150
  }
143
151
  interface UseAuthResult {
144
152
  setToken: (token: string | null) => void;
153
+ /**
154
+ * The resolved auth state. Branch on this, not on `user === null` — see the
155
+ * contract in `@lunora/client/auth`; `user` is `null` both when signed out
156
+ * and when a held credential's identity could not be resolved.
157
+ */
158
+ status: AuthStatus;
145
159
  token: string | null;
146
160
  user: User | null;
147
161
  }
@@ -760,14 +774,18 @@ declare const useAgentToolEvents: (options: UseAgentToolEventsOptions) => UseAge
760
774
  /**
761
775
  * Token + identity plumbing. The token lives on the shared `LunoraClient`;
762
776
  * `setToken(jwt)` after a sign-in makes subsequent RPC calls carry the
763
- * `Authorization` header. `user` is resolved from better-auth's `get-session`
764
- * endpoint via `client.getCurrentUser()` — fetched on mount and refetched
765
- * whenever the token changes (`onAuthTokenChange`), and `null` when signed out.
777
+ * `Authorization` header. `user` and `status` come from the framework-agnostic
778
+ * per-client identity store in `@lunora/client/auth` — the same store Vue,
779
+ * Solid, Svelte and Angular read, so all five agree on what "authenticated"
780
+ * means rather than each keeping a private copy of the resolve logic.
781
+ *
782
+ * `status` is the value to branch on: `user` is `null` both when signed out and
783
+ * when a held credential's identity endpoint could not be reached. See the
784
+ * contract documented on `AuthStatus`.
766
785
  *
767
- * Multiple `useAuth` instances stay in sync: both `token` and `user` are read
768
- * through `useSyncExternalStore` over the shared client (and a per-client
769
- * identity store), so a `setToken` from one component re-renders every mounted
770
- * hook with the freshly-resolved user.
786
+ * Multiple `useAuth` instances stay in sync: token, user and status are all read
787
+ * through `useSyncExternalStore` over the shared client and its identity store,
788
+ * so a `setToken` from one component re-renders every mounted hook.
771
789
  */
772
790
  declare const useAuth: () => UseAuthResult;
773
791
  type Setter<T> = (value: T) => void;
package/dist/index.d.ts CHANGED
@@ -3,6 +3,7 @@ import { LunoraClient, OptimisticUpdate, User, SubscriptionErrorCallback, Subscr
3
3
  export { type ArgsOf, type AuthImpersonation, type AuthPage, type AuthSession, type AuthUser, type ClientQueryRef, type FunctionReference, type HttpStreamArgsOf, type HttpStreamChunkOf, type HttpStreamRef, type LunoraClient, type LunoraErrorCode, type MutatorHandle, type MutatorTransaction, type OptimisticLocalStore, type OptimisticUpdate, type Preloaded, type ReturnOf, type SubscriptionError, type SubscriptionErrorCallback, type User, createClientQuery, getErrorCode, getRetryAfterMs, isConflictError, isForbiddenError, isRateLimitedError, isUnauthorizedError } from '@lunora/client';
4
4
  import { QueryClient } from '@tanstack/react-query';
5
5
  export { type L as LunoraQueryOptions, l as lunoraQueryOptions } from "./packem_shared/query-options.d-CdgGQ9s4.js";
6
+ import { AuthStatus } from '@lunora/client/auth';
6
7
  import { PaginationStatus } from '@lunora/client/pagination';
7
8
  export type { PaginationResult, PaginationStatus } from '@lunora/client/pagination';
8
9
  import { RateLimitStatus, RateLimitConfig } from '@lunora/ratelimit';
@@ -11,29 +12,36 @@ export { type UploadMethod, type UploadResult, type UseChunkedRestUploadOptions,
11
12
  interface AuthGateProps {
12
13
  children: ReactNode;
13
14
  }
14
- /** Renders `children` only once a token is set on the client (after hydration). */
15
+ /**
16
+ * Renders `children` once authentication has settled in the caller's favour — a
17
+ * credential is held and nothing has contradicted it. Follows the shared
18
+ * `AuthStatus` contract in `@lunora/client/auth`, so an unreachable identity
19
+ * endpoint keeps the gate open (with `useAuth().user` still `null`).
20
+ */
15
21
  declare const Authenticated: ({ children }: AuthGateProps) => ReactNode;
16
- /** Renders `children` only when auth has settled and no token is set. */
22
+ /** Renders `children` only when auth has settled and there is no session. */
17
23
  declare const Unauthenticated: ({ children }: AuthGateProps) => ReactNode;
18
- /** Renders `children` while auth is still settling (before hydration completes). */
24
+ /** Renders `children` while auth is still settling — before hydration, or while the first identity resolve is in flight. */
19
25
  declare const AuthLoading: ({ children }: AuthGateProps) => ReactNode;
20
26
  /**
21
- * Resolved auth-gate state. `isLoading` covers the window before the client has
22
- * hydrated — the server render and the first hydration render both report
23
- * loading, so the markup agrees and no signed-out UI flashes in.
27
+ * Resolved auth-gate state, derived from the shared `AuthStatus` contract in
28
+ * `@lunora/client/auth` — the same mapping Vue, Solid, Svelte and Angular use.
24
29
  */
25
30
  interface AuthState {
26
31
  isAuthenticated: boolean;
27
32
  isLoading: boolean;
28
33
  }
29
34
  /**
30
- * Three-state auth status for gating UI. Reports `isLoading` until the client
31
- * has hydrated, then `isAuthenticated` tracks whether a token is set on the
32
- * shared client.
35
+ * Three-state auth status for gating UI.
36
+ *
37
+ * `isLoading` covers the server render and the first hydration render (the
38
+ * identity store's server snapshot is `"loading"`, so the markup agrees and no
39
+ * signed-out UI flashes in) as well as the window where a credential is held and
40
+ * its first identity resolve is still in flight.
33
41
  *
34
- * Lunora auth is token-based and resolves synchronously once the token is
35
- * known, so the loading window is hydration rather than a server round-trip —
36
- * use it (via {@link AuthState}) to render a fallback while it settles.
42
+ * `isAuthenticated` follows the credential, not the identity record: an
43
+ * unreachable identity endpoint keeps the gate open with `user === null`. A UI
44
+ * that needs to tell that apart reads `useAuth().status`.
37
45
  */
38
46
  declare const useAuthState: () => AuthState;
39
47
  interface LunoraProviderProps {
@@ -142,6 +150,12 @@ interface UseInfiniteQueryResult<T> {
142
150
  }
143
151
  interface UseAuthResult {
144
152
  setToken: (token: string | null) => void;
153
+ /**
154
+ * The resolved auth state. Branch on this, not on `user === null` — see the
155
+ * contract in `@lunora/client/auth`; `user` is `null` both when signed out
156
+ * and when a held credential's identity could not be resolved.
157
+ */
158
+ status: AuthStatus;
145
159
  token: string | null;
146
160
  user: User | null;
147
161
  }
@@ -760,14 +774,18 @@ declare const useAgentToolEvents: (options: UseAgentToolEventsOptions) => UseAge
760
774
  /**
761
775
  * Token + identity plumbing. The token lives on the shared `LunoraClient`;
762
776
  * `setToken(jwt)` after a sign-in makes subsequent RPC calls carry the
763
- * `Authorization` header. `user` is resolved from better-auth's `get-session`
764
- * endpoint via `client.getCurrentUser()` — fetched on mount and refetched
765
- * whenever the token changes (`onAuthTokenChange`), and `null` when signed out.
777
+ * `Authorization` header. `user` and `status` come from the framework-agnostic
778
+ * per-client identity store in `@lunora/client/auth` — the same store Vue,
779
+ * Solid, Svelte and Angular read, so all five agree on what "authenticated"
780
+ * means rather than each keeping a private copy of the resolve logic.
781
+ *
782
+ * `status` is the value to branch on: `user` is `null` both when signed out and
783
+ * when a held credential's identity endpoint could not be reached. See the
784
+ * contract documented on `AuthStatus`.
766
785
  *
767
- * Multiple `useAuth` instances stay in sync: both `token` and `user` are read
768
- * through `useSyncExternalStore` over the shared client (and a per-client
769
- * identity store), so a `setToken` from one component re-renders every mounted
770
- * hook with the freshly-resolved user.
786
+ * Multiple `useAuth` instances stay in sync: token, user and status are all read
787
+ * through `useSyncExternalStore` over the shared client and its identity store,
788
+ * so a `setToken` from one component re-renders every mounted hook.
771
789
  */
772
790
  declare const useAuth: () => UseAuthResult;
773
791
  type Setter<T> = (value: T) => void;
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
1
  'use client';
2
- import{AuthLoading as o,Authenticated as t,Unauthenticated as u}from"./packem_shared/AuthLoading-dC08yqew.mjs";import{useAuthState as a}from"./packem_shared/useAuthState-CoOG9XdT.mjs";import{LunoraProvider as n,useLunora as f}from"./packem_shared/LunoraProvider-DC06S-p1.mjs";import{lunoraQueryOptions as m}from"./packem_shared/lunoraQueryOptions-BVgQsR9d.mjs";import{useAction as x}from"./packem_shared/useAction-CUSJu4yq.mjs";import{useAuthSessions as g,useAuthUsers as A,useImpersonate as h,useOrganizations as U,useSignUpInvitations as c}from"./packem_shared/useAuthSessions-gBDeNFnd.mjs";import{useAgent as C}from"./packem_shared/useAgent-DtQfMu4S.mjs";import{useAgentChat as S}from"./packem_shared/useAgentChat-g4ZNMq1B.mjs";import{useAgentState as P}from"./packem_shared/useAgentState-BuMYPWb2.mjs";import{useAgentToolEvents as R}from"./packem_shared/useAgentToolEvents-B1ItKmZi.mjs";import{default as I}from"./packem_shared/useAuth-x4boOoAR.mjs";import{default as v}from"./packem_shared/useClientQuery-DFs7trEf.mjs";import{default as z}from"./packem_shared/useConnectionStatus-XYsYGiT6.mjs";import{useFlag as T,useFlags as k}from"./packem_shared/useFlag-BDM923ke.mjs";import{useHttpStream as V}from"./packem_shared/useHttpStream-DWtB9sAr.mjs";import{default as q}from"./packem_shared/useInfiniteQuery-BnekI8ek.mjs";import{useMutation as B}from"./packem_shared/useMutation-BnKec7bE.mjs";import{useMutator as G}from"./packem_shared/useMutator-BtUd-xEA.mjs";import{usePaginatedQuery as K}from"./packem_shared/usePaginatedQuery-DhjOm3E5.mjs";import{hydratePreloaded as W,default as X}from"./packem_shared/hydratePreloaded-CB9ns38y.mjs";import{usePresence as Z}from"./packem_shared/usePresence-BVjZyltT.mjs";import{default as $}from"./packem_shared/useQuery-Dl68EkYb.mjs";import{useRateLimit as re}from"./packem_shared/useRateLimit-Cckxi8m9.mjs";import{useStream as te}from"./packem_shared/useStream-Cor62Cu-.mjs";import{default as se}from"./packem_shared/useSubscription-egFPCaGE.mjs";import{useVoiceAgent as pe}from"./packem_shared/useVoiceAgent-DHdUlo0G.mjs";import{createClientQuery as fe,getErrorCode as ie,getRetryAfterMs as me,isConflictError as de,isForbiddenError as xe,isRateLimitedError as le,isUnauthorizedError as ge}from"@lunora/client";import{RestrictionError as he,UploadControl as Ue,UploadError as ce}from"@visulima/storage-client";import{useChunkedRestUpload as Ce,useFileInput as Ee,useMultipartUpload as Se,usePasteUpload as Qe,useTusUpload as Pe,useUpload as Le}from"@visulima/storage-client/react";export{o as AuthLoading,t as Authenticated,n as LunoraProvider,he as RestrictionError,u as Unauthenticated,Ue as UploadControl,ce as UploadError,fe as createClientQuery,ie as getErrorCode,me as getRetryAfterMs,W as hydratePreloaded,de as isConflictError,xe as isForbiddenError,le as isRateLimitedError,ge as isUnauthorizedError,m as lunoraQueryOptions,x as useAction,C as useAgent,S as useAgentChat,P as useAgentState,R as useAgentToolEvents,I as useAuth,g as useAuthSessions,a as useAuthState,A as useAuthUsers,Ce as useChunkedRestUpload,v as useClientQuery,z as useConnectionStatus,Ee as useFileInput,T as useFlag,k as useFlags,V as useHttpStream,h as useImpersonate,q as useInfiniteQuery,f as useLunora,Se as useMultipartUpload,B as useMutation,G as useMutator,U as useOrganizations,K as usePaginatedQuery,Qe as usePasteUpload,X as usePreloadedQuery,Z as usePresence,$ as useQuery,re as useRateLimit,c as useSignUpInvitations,te as useStream,se as useSubscription,Pe as useTusUpload,Le as useUpload,pe as useVoiceAgent};
2
+ import{AuthLoading as o,Authenticated as t,Unauthenticated as u}from"./packem_shared/AuthLoading-ueuPtzle.mjs";import{useAuthState as a}from"./packem_shared/useAuthState-A5yrsHUw.mjs";import{LunoraProvider as n,useLunora as f}from"./packem_shared/LunoraProvider-DC06S-p1.mjs";import{lunoraQueryOptions as m}from"./packem_shared/lunoraQueryOptions-BVgQsR9d.mjs";import{useAction as x}from"./packem_shared/useAction-CUSJu4yq.mjs";import{useAuthSessions as g,useAuthUsers as A,useImpersonate as h,useOrganizations as U,useSignUpInvitations as c}from"./packem_shared/useAuthSessions-gBDeNFnd.mjs";import{useAgent as C}from"./packem_shared/useAgent-DtQfMu4S.mjs";import{useAgentChat as S}from"./packem_shared/useAgentChat-g4ZNMq1B.mjs";import{useAgentState as P}from"./packem_shared/useAgentState-BuMYPWb2.mjs";import{useAgentToolEvents as R}from"./packem_shared/useAgentToolEvents-B1ItKmZi.mjs";import{default as I}from"./packem_shared/useAuth-BuH3kbVK.mjs";import{default as v}from"./packem_shared/useClientQuery-DFs7trEf.mjs";import{default as z}from"./packem_shared/useConnectionStatus-XYsYGiT6.mjs";import{useFlag as T,useFlags as k}from"./packem_shared/useFlag-BDM923ke.mjs";import{useHttpStream as V}from"./packem_shared/useHttpStream-DWtB9sAr.mjs";import{default as q}from"./packem_shared/useInfiniteQuery-BnekI8ek.mjs";import{useMutation as B}from"./packem_shared/useMutation-BnKec7bE.mjs";import{useMutator as G}from"./packem_shared/useMutator-BtUd-xEA.mjs";import{usePaginatedQuery as K}from"./packem_shared/usePaginatedQuery-DhjOm3E5.mjs";import{hydratePreloaded as W,default as X}from"./packem_shared/hydratePreloaded-CB9ns38y.mjs";import{usePresence as Z}from"./packem_shared/usePresence-BVjZyltT.mjs";import{default as $}from"./packem_shared/useQuery-Dl68EkYb.mjs";import{useRateLimit as re}from"./packem_shared/useRateLimit-Cckxi8m9.mjs";import{useStream as te}from"./packem_shared/useStream-Cor62Cu-.mjs";import{default as se}from"./packem_shared/useSubscription-egFPCaGE.mjs";import{useVoiceAgent as pe}from"./packem_shared/useVoiceAgent-DHdUlo0G.mjs";import{createClientQuery as fe,getErrorCode as ie,getRetryAfterMs as me,isConflictError as de,isForbiddenError as xe,isRateLimitedError as le,isUnauthorizedError as ge}from"@lunora/client";import{RestrictionError as he,UploadControl as Ue,UploadError as ce}from"@visulima/storage-client";import{useChunkedRestUpload as Ce,useFileInput as Ee,useMultipartUpload as Se,usePasteUpload as Qe,useTusUpload as Pe,useUpload as Le}from"@visulima/storage-client/react";export{o as AuthLoading,t as Authenticated,n as LunoraProvider,he as RestrictionError,u as Unauthenticated,Ue as UploadControl,ce as UploadError,fe as createClientQuery,ie as getErrorCode,me as getRetryAfterMs,W as hydratePreloaded,de as isConflictError,xe as isForbiddenError,le as isRateLimitedError,ge as isUnauthorizedError,m as lunoraQueryOptions,x as useAction,C as useAgent,S as useAgentChat,P as useAgentState,R as useAgentToolEvents,I as useAuth,g as useAuthSessions,a as useAuthState,A as useAuthUsers,Ce as useChunkedRestUpload,v as useClientQuery,z as useConnectionStatus,Ee as useFileInput,T as useFlag,k as useFlags,V as useHttpStream,h as useImpersonate,q as useInfiniteQuery,f as useLunora,Se as useMultipartUpload,B as useMutation,G as useMutator,U as useOrganizations,K as usePaginatedQuery,Qe as usePasteUpload,X as usePreloadedQuery,Z as usePresence,$ as useQuery,re as useRateLimit,c as useSignUpInvitations,te as useStream,se as useSubscription,Pe as useTusUpload,Le as useUpload,pe as useVoiceAgent};
@@ -1,2 +1,2 @@
1
1
  'use client';
2
- import{useAuthState as o}from"./useAuthState-CoOG9XdT.mjs";const s=t=>{const{children:n}=t,{isAuthenticated:i}=o();return i?n:void 0},d=t=>{const{children:n}=t,{isAuthenticated:i,isLoading:e}=o();return!e&&!i?n:void 0},r=t=>{const{children:n}=t,{isLoading:i}=o();return i?n:void 0};export{r as AuthLoading,s as Authenticated,d as Unauthenticated};
2
+ import{useAuthState as o}from"./useAuthState-A5yrsHUw.mjs";const s=t=>{const{children:n}=t,{isAuthenticated:i}=o();return i?n:void 0},d=t=>{const{children:n}=t,{isAuthenticated:i,isLoading:e}=o();return!e&&!i?n:void 0},r=t=>{const{children:n}=t,{isLoading:i}=o();return i?n:void 0};export{r as AuthLoading,s as Authenticated,d as Unauthenticated};
@@ -0,0 +1,2 @@
1
+ 'use client';
2
+ import{c as h}from"react/compiler-runtime";import{getIdentityStore as k}from"@lunora/client/auth";import{useSyncExternalStore as p}from"react";import{useLunora as A}from"./LunoraProvider-DC06S-p1.mjs";const _=()=>{const t=h(13),e=A();let o;t[0]!==e?(o=k(e),t[0]=e,t[1]=o):o=t[1];const n=o;let s,r,u;t[2]!==e?(s=g=>e.onAuthTokenChange(g),r=()=>e.getAuthToken(),u=()=>e.getAuthToken(),t[2]=e,t[3]=s,t[4]=r,t[5]=u):(s=t[3],r=t[4],u=t[5]);const i=p(s,r,u),f=p(n.subscribe,n.getUser,T),m=p(n.subscribe,n.getStatus,b);let l;t[6]!==e?(l=g=>{e.setAuthToken(g)},t[6]=e,t[7]=l):l=t[7];const a=l;let c;return t[8]!==a||t[9]!==m||t[10]!==i||t[11]!==f?(c={setToken:a,status:m,token:i,user:f},t[8]=a,t[9]=m,t[10]=i,t[11]=f,t[12]=c):c=t[12],c};function T(){return null}function b(){return"loading"}export{_ as default};
@@ -0,0 +1,2 @@
1
+ 'use client';
2
+ import{c as u}from"react/compiler-runtime";import{isAuthenticatedStatus as r,isLoadingStatus as a}from"@lunora/client/auth";import n from"./useAuth-BuH3kbVK.mjs";const m=()=>{const t=u(7),{status:e}=n();let s;t[0]!==e?(s=r(e),t[0]=e,t[1]=s):s=t[1];let i;t[2]!==e?(i=a(e),t[2]=e,t[3]=i):i=t[3];let o;return t[4]!==s||t[5]!==i?(o={isAuthenticated:s,isLoading:i},t[4]=s,t[5]=i,t[6]=o):o=t[6],o};export{m as useAuthState};
@@ -20,6 +20,16 @@ interface Subscription {
20
20
  readonly currentPeriodStart?: number;
21
21
  readonly id: string;
22
22
  readonly priceId: string;
23
+ /**
24
+ * EVERY price/product id the subscription bills, not just the primary one. A Stripe
25
+ * subscription can carry an add-on or a metered price alongside the base plan, and a
26
+ * customer paying for one is entitled to it — so entitlements test membership here.
27
+ *
28
+ * Optional because the webhook path and any pre-existing stored row carry only
29
+ * `priceId`; absent reads as `[priceId]`, which is exactly right for the single-item
30
+ * case every other provider has.
31
+ */
32
+ readonly priceIds?: ReadonlyArray<string>;
23
33
  readonly provider: ProviderId;
24
34
  readonly quantity: number;
25
35
  readonly referenceId: string;
package/dist/payment.d.ts CHANGED
@@ -20,6 +20,16 @@ interface Subscription {
20
20
  readonly currentPeriodStart?: number;
21
21
  readonly id: string;
22
22
  readonly priceId: string;
23
+ /**
24
+ * EVERY price/product id the subscription bills, not just the primary one. A Stripe
25
+ * subscription can carry an add-on or a metered price alongside the base plan, and a
26
+ * customer paying for one is entitled to it — so entitlements test membership here.
27
+ *
28
+ * Optional because the webhook path and any pre-existing stored row carry only
29
+ * `priceId`; absent reads as `[priceId]`, which is exactly right for the single-item
30
+ * case every other provider has.
31
+ */
32
+ readonly priceIds?: ReadonlyArray<string>;
23
33
  readonly provider: ProviderId;
24
34
  readonly quantity: number;
25
35
  readonly referenceId: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/react",
3
- "version": "1.0.0-alpha.106",
3
+ "version": "1.0.0-alpha.108",
4
4
  "description": "React hooks for Lunora: useQuery, useMutation, useSubscription, and useAuth",
5
5
  "keywords": [
6
6
  "cloudflare",
@@ -57,7 +57,7 @@
57
57
  "access": "public"
58
58
  },
59
59
  "dependencies": {
60
- "@lunora/client": "1.0.0-alpha.101",
60
+ "@lunora/client": "1.0.0-alpha.102",
61
61
  "@lunora/errors": "1.0.0-alpha.36",
62
62
  "@lunora/ratelimit": "1.0.0-alpha.57",
63
63
  "@visulima/storage-client": "1.0.3"
@@ -1,2 +0,0 @@
1
- 'use client';
2
- import{c as b}from"react/compiler-runtime";import{useSyncExternalStore as g}from"react";import{useLunora as p}from"./LunoraProvider-DC06S-p1.mjs";const k=new WeakMap,S=e=>{const t=new Set;let o=null;const i=()=>{for(const n of t)n()};let s=0;const r=n=>{o!==n&&(o=n,i())},l=()=>{s+=1;const n=s;if(e.getAuthToken()===null){r(null);return}e.getCurrentUser().then(u=>{n===s&&r(u)}).catch(()=>{n===s&&r(null)})};let c;return{getSnapshot:()=>o,subscribe:n=>{const u=t.size===0;return t.add(n),u&&(c=e.onAuthTokenChange(l),l()),()=>{t.delete(n),t.size===0&&(c?.(),c=void 0)}}}},T=e=>{let t=k.get(e);return t||(t=S(e),k.set(e,t)),t},w=()=>{const e=b(12),t=p();let o;e[0]!==t?(o=T(t),e[0]=t,e[1]=o):o=e[1];const i=o;let s,r,l;e[2]!==t?(s=h=>t.onAuthTokenChange(h),r=()=>t.getAuthToken(),l=()=>t.getAuthToken(),e[2]=t,e[3]=s,e[4]=r,e[5]=l):(s=e[3],r=e[4],l=e[5]);const c=g(s,r,l),n=g(i.subscribe,i.getSnapshot,m);let u;e[6]!==t?(u=h=>{t.setAuthToken(h)},e[6]=t,e[7]=u):u=e[7];const a=u;let f;return e[8]!==a||e[9]!==c||e[10]!==n?(f={setToken:a,token:c,user:n},e[8]=a,e[9]=c,e[10]=n,e[11]=f):f=e[11],f};function m(){return null}export{w as default};
@@ -1,2 +0,0 @@
1
- 'use client';
2
- import{c as u}from"react/compiler-runtime";import{useSyncExternalStore as c}from"react";import i from"./useAuth-x4boOoAR.mjs";const m=()=>()=>{},h=()=>{const t=u(3),{token:s}=i(),r=c(m,f,a),n=r&&s!==null,o=!r;let e;return t[0]!==n||t[1]!==o?(e={isAuthenticated:n,isLoading:o},t[0]=n,t[1]=o,t[2]=e):e=t[2],e};function f(){return!0}function a(){return!1}export{h as useAuthState};