@lunora/react 1.0.0-alpha.2 → 1.0.0-alpha.21
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/LICENSE.md +6 -0
- package/README.md +2 -0
- package/__assets__/package-og.svg +1 -1
- package/dist/index.d.mts +60 -3
- package/dist/index.d.ts +60 -3
- package/dist/index.mjs +18 -15
- package/dist/packem_shared/{Authenticated-DtKgZT2Z.mjs → AuthLoading-DezUWNB2.mjs} +1 -1
- package/dist/packem_shared/{CheckoutButton-CVSry8U1.mjs → CheckoutButton-DUite8jJ.mjs} +8 -4
- package/dist/packem_shared/{LunoraProvider-D38Xp16l.mjs → LunoraProvider-BsuiW4Lk.mjs} +3 -2
- package/dist/packem_shared/{cache-CItk3fgN.mjs → cache-BFlsXmup.mjs} +1 -1
- package/dist/packem_shared/{hydratePreloaded-BlFL9FGq.mjs → hydratePreloaded-Dsf9YuII.mjs} +22 -14
- package/dist/packem_shared/{lunoraQueryOptions-CsuWzjg1.mjs → lunoraQueryOptions-C3uwOTMW.mjs} +1 -1
- package/dist/packem_shared/query-key-BmCbgidV.mjs +13 -0
- package/dist/packem_shared/stable-key-CGp4e2Ux.mjs +38 -0
- package/dist/packem_shared/{use-paginated-core-CoOfcc-p.mjs → use-paginated-core-CWSzk1J1.mjs} +36 -17
- package/dist/packem_shared/{useAuth-CNUKtOOp.mjs → useAuth-BSutjJaa.mjs} +1 -1
- package/dist/packem_shared/{useAuthState-BiGhtSCs.mjs → useAuthState-CyF35qZR.mjs} +1 -1
- package/dist/packem_shared/{useConnectionStatus-DRSY9ldm.mjs → useConnectionStatus-PJ7vyCHy.mjs} +1 -1
- package/dist/packem_shared/useFlag-hhoN_xYA.mjs +224 -0
- package/dist/packem_shared/{useInfiniteQuery-MH0x4l8h.mjs → useInfiniteQuery-Dy42_srs.mjs} +1 -1
- package/dist/packem_shared/{useMutation-CrvMXRsk.mjs → useMutation-BeqeIjTr.mjs} +1 -1
- package/dist/packem_shared/useMutator-IIrLtDiM.mjs +47 -0
- package/dist/packem_shared/{usePaginatedQuery-D3PTDRGS.mjs → usePaginatedQuery-Tx-B3mAP.mjs} +1 -1
- package/dist/packem_shared/{usePresence-D7jLuxj0.mjs → usePresence-DC8VIyLB.mjs} +1 -1
- package/dist/packem_shared/useQuery-_fTR6DCQ.mjs +54 -0
- package/dist/packem_shared/{useStream-BRY9nemd.mjs → useStream-DFuryaIC.mjs} +2 -2
- package/dist/packem_shared/{useSubscription-CHMCjyQg.mjs → useSubscription-D38Jdyr8.mjs} +2 -2
- package/dist/server.mjs +2 -2
- package/package.json +5 -4
- package/dist/packem_shared/query-key-C5rufkEE.mjs +0 -21
- package/dist/packem_shared/useQuery-C5S0W-7K.mjs +0 -41
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ReactNode, ReactElement } from 'react';
|
|
2
|
-
import { LunoraClient, OptimisticUpdate, User, ConnectionStatus, ReturnOf, ArgsOf, FunctionReference, Preloaded } from '@lunora/client';
|
|
3
|
-
export type
|
|
2
|
+
import { LunoraClient, OptimisticUpdate, User, ConnectionStatus, ReturnOf, ArgsOf, FunctionReference, MutatorHandle, Preloaded } from '@lunora/client';
|
|
3
|
+
export { type ArgsOf, type FunctionReference, type LunoraClient, type LunoraErrorCode, type MutatorHandle, type MutatorTransaction, type OptimisticLocalStore, type OptimisticUpdate, type Preloaded, type ReturnOf, type User, 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-D4okOpO8.mjs";
|
|
6
6
|
import { PaginationStatus } from '@lunora/client/pagination';
|
|
@@ -233,6 +233,38 @@ declare const useAuth: () => UseAuthResult;
|
|
|
233
233
|
* operator can tell a healthy live channel from a silently-dropped socket.
|
|
234
234
|
*/
|
|
235
235
|
declare const useConnectionStatus: () => ConnectionStatus;
|
|
236
|
+
/** A targeting context merged on top of the app's default (`defineFlags({ identify })`). */
|
|
237
|
+
type FlagContext = Record<string, unknown>;
|
|
238
|
+
/** The value kinds a flag resolves to — OpenFeature's boolean / number / string / structured (JSON) flags. */
|
|
239
|
+
type FlagValue = boolean | number | string | {
|
|
240
|
+
[key: string]: unknown;
|
|
241
|
+
} | unknown[] | null;
|
|
242
|
+
/**
|
|
243
|
+
* Subscribe to a single feature flag, live over Lunora's WebSocket.
|
|
244
|
+
*
|
|
245
|
+
* Returns `defaultValue` until the first evaluation lands, then the server's
|
|
246
|
+
* resolved value — re-pushed whenever the provider re-evaluates (e.g. a flag is
|
|
247
|
+
* toggled in Cloudflare Flagship). The flag's kind is inferred from
|
|
248
|
+
* `defaultValue`'s runtime type, so `useFlag("dark", false)` reads a boolean and
|
|
249
|
+
* `useFlag("hero", "control")` a string. `context` supplies a per-call targeting
|
|
250
|
+
* context merged on top of the app's default `identify` targeting key.
|
|
251
|
+
*
|
|
252
|
+
* Evaluation runs through whatever OpenFeature provider the app wired in
|
|
253
|
+
* `lunora/flags.ts`; the read never throws — a provider error resolves the
|
|
254
|
+
* default (the same fail-open contract as server-side `ctx.flags`).
|
|
255
|
+
*/
|
|
256
|
+
declare const useFlag: <T extends FlagValue>(key: string, defaultValue: T, context?: FlagContext) => T;
|
|
257
|
+
/**
|
|
258
|
+
* Subscribe to several feature flags at once, live over Lunora's WebSocket.
|
|
259
|
+
*
|
|
260
|
+
* Pass a record of `key → defaultValue`; each flag's kind is inferred from its
|
|
261
|
+
* default, and the result is the same-shaped record with resolved values (the
|
|
262
|
+
* defaults until each evaluation lands). A single `context` applies to every
|
|
263
|
+
* flag. This is the batched form of {@link useFlag} — one effect manages one
|
|
264
|
+
* subscription per key, so it stays rules-of-hooks-safe even as the flag set
|
|
265
|
+
* changes between renders.
|
|
266
|
+
*/
|
|
267
|
+
declare const useFlags: <T extends Record<string, FlagValue>>(flags: T, context?: FlagContext) => T;
|
|
236
268
|
/** The args a paginated query exposes minus the framework-supplied page cursor. */
|
|
237
269
|
type PaginatedArgs<F> = Omit<ArgsOf<F>, "paginationOpts">;
|
|
238
270
|
/** The element type of the `page` array a paginated query returns. */
|
|
@@ -322,6 +354,31 @@ interface MutationHook<F extends FunctionReference> {
|
|
|
322
354
|
* through TanStack's `onMutate`.
|
|
323
355
|
*/
|
|
324
356
|
declare const useMutation: <F extends FunctionReference>(function_: F) => MutationHook<F>;
|
|
357
|
+
interface MutatorHook<TArgs> {
|
|
358
|
+
/** The latest invocation's error, or `undefined`. */
|
|
359
|
+
error: Error | undefined;
|
|
360
|
+
/** `true` when the latest invocation rejected. */
|
|
361
|
+
isError: boolean;
|
|
362
|
+
/** Run the mutator; resolves once the write is persisted, rejects on failure. */
|
|
363
|
+
mutate: (args: TArgs) => Promise<void>;
|
|
364
|
+
/** `true` while ANY invocation from this hook is in flight (ref-counted, so overlapping calls compose). */
|
|
365
|
+
pending: boolean;
|
|
366
|
+
/** Clear the latest `error` back to idle. */
|
|
367
|
+
reset: () => void;
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* Ergonomic `{ mutate, pending, error, isError, reset }` wrapper over a bound
|
|
371
|
+
* custom-mutator handle from `@lunora/db`'s `bindMutators`. The optimistic
|
|
372
|
+
* overlay and server-authoritative push are owned by the bound handle (and
|
|
373
|
+
* TanStack DB's optimistic-transaction layer rebases pending overlays on every
|
|
374
|
+
* sync tick) — this hook only surfaces React state for the in-flight/error
|
|
375
|
+
* lifecycle. Reads stay on the existing `useLiveQuery`; no new query hook is
|
|
376
|
+
* needed.
|
|
377
|
+
*
|
|
378
|
+
* `pending` is ref-counted across overlapping invocations of THIS hook instance,
|
|
379
|
+
* so it clears only once every concurrent call has settled.
|
|
380
|
+
*/
|
|
381
|
+
declare const useMutator: <TArgs = Record<string, unknown>>(handle: MutatorHandle<TArgs>) => MutatorHook<TArgs>;
|
|
325
382
|
/**
|
|
326
383
|
* Hydrate a query from a {@link Preloaded} token produced by `preloadQuery`
|
|
327
384
|
* during SSR, then keep it live.
|
|
@@ -496,4 +553,4 @@ declare const useStream: <F extends FunctionReference<"stream">>(function_: F, a
|
|
|
496
553
|
* the server pushes over the WS.
|
|
497
554
|
*/
|
|
498
555
|
declare const useSubscription: <F extends FunctionReference>(function_: F, args: ArgsOf<F> | "skip", options?: UseQueryOptions) => UseSubscriptionResult<ReturnOf<F>>;
|
|
499
|
-
export { AuthLoading, type AuthState, Authenticated, CheckoutButton, type CheckoutButtonProps, CustomerPortalButton, type CustomerPortalButtonProps, type HeartbeatReference, type ListPresentReference, LunoraProvider, type LunoraProviderProps, type MutationHook, type PageItemOf, type PaginatedArgs, type RedirectTarget, type RedirectTrigger, type Subscription, Unauthenticated, type UseAuthResult, type UseCheckoutResult, type UseInfiniteQueryOptions, type UseInfiniteQueryResult, type UseMutationCallOptions, type UsePaginatedQueryOptions, type UsePaginatedQueryResult, type UsePresenceOptions, type UsePresenceResult, type UseQueryOptions, type UseRateLimitOptions, type UseRateLimitResult, type UseStreamOptions, type UseStreamResult, type UseStreamStatus, type UseSubscriptionResult, hydratePreloaded, useAuth, useAuthState, useCheckout, useConnectionStatus, useInfiniteQuery, useLunora, useMutation, usePaginatedQuery, usePreloadedQuery, usePresence, useQuery, useRateLimit, useStream, useSubscription };
|
|
556
|
+
export { AuthLoading, type AuthState, Authenticated, CheckoutButton, type CheckoutButtonProps, CustomerPortalButton, type CustomerPortalButtonProps, type FlagContext, type FlagValue, type HeartbeatReference, type ListPresentReference, LunoraProvider, type LunoraProviderProps, type MutationHook, type MutatorHook, type PageItemOf, type PaginatedArgs, type RedirectTarget, type RedirectTrigger, type Subscription, Unauthenticated, type UseAuthResult, type UseCheckoutResult, type UseInfiniteQueryOptions, type UseInfiniteQueryResult, type UseMutationCallOptions, type UsePaginatedQueryOptions, type UsePaginatedQueryResult, type UsePresenceOptions, type UsePresenceResult, type UseQueryOptions, type UseRateLimitOptions, type UseRateLimitResult, type UseStreamOptions, type UseStreamResult, type UseStreamStatus, type UseSubscriptionResult, hydratePreloaded, useAuth, useAuthState, useCheckout, useConnectionStatus, useFlag, useFlags, useInfiniteQuery, useLunora, useMutation, useMutator, usePaginatedQuery, usePreloadedQuery, usePresence, useQuery, useRateLimit, useStream, useSubscription };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ReactNode, ReactElement } from 'react';
|
|
2
|
-
import { LunoraClient, OptimisticUpdate, User, ConnectionStatus, ReturnOf, ArgsOf, FunctionReference, Preloaded } from '@lunora/client';
|
|
3
|
-
export type
|
|
2
|
+
import { LunoraClient, OptimisticUpdate, User, ConnectionStatus, ReturnOf, ArgsOf, FunctionReference, MutatorHandle, Preloaded } from '@lunora/client';
|
|
3
|
+
export { type ArgsOf, type FunctionReference, type LunoraClient, type LunoraErrorCode, type MutatorHandle, type MutatorTransaction, type OptimisticLocalStore, type OptimisticUpdate, type Preloaded, type ReturnOf, type User, 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-D4okOpO8.js";
|
|
6
6
|
import { PaginationStatus } from '@lunora/client/pagination';
|
|
@@ -233,6 +233,38 @@ declare const useAuth: () => UseAuthResult;
|
|
|
233
233
|
* operator can tell a healthy live channel from a silently-dropped socket.
|
|
234
234
|
*/
|
|
235
235
|
declare const useConnectionStatus: () => ConnectionStatus;
|
|
236
|
+
/** A targeting context merged on top of the app's default (`defineFlags({ identify })`). */
|
|
237
|
+
type FlagContext = Record<string, unknown>;
|
|
238
|
+
/** The value kinds a flag resolves to — OpenFeature's boolean / number / string / structured (JSON) flags. */
|
|
239
|
+
type FlagValue = boolean | number | string | {
|
|
240
|
+
[key: string]: unknown;
|
|
241
|
+
} | unknown[] | null;
|
|
242
|
+
/**
|
|
243
|
+
* Subscribe to a single feature flag, live over Lunora's WebSocket.
|
|
244
|
+
*
|
|
245
|
+
* Returns `defaultValue` until the first evaluation lands, then the server's
|
|
246
|
+
* resolved value — re-pushed whenever the provider re-evaluates (e.g. a flag is
|
|
247
|
+
* toggled in Cloudflare Flagship). The flag's kind is inferred from
|
|
248
|
+
* `defaultValue`'s runtime type, so `useFlag("dark", false)` reads a boolean and
|
|
249
|
+
* `useFlag("hero", "control")` a string. `context` supplies a per-call targeting
|
|
250
|
+
* context merged on top of the app's default `identify` targeting key.
|
|
251
|
+
*
|
|
252
|
+
* Evaluation runs through whatever OpenFeature provider the app wired in
|
|
253
|
+
* `lunora/flags.ts`; the read never throws — a provider error resolves the
|
|
254
|
+
* default (the same fail-open contract as server-side `ctx.flags`).
|
|
255
|
+
*/
|
|
256
|
+
declare const useFlag: <T extends FlagValue>(key: string, defaultValue: T, context?: FlagContext) => T;
|
|
257
|
+
/**
|
|
258
|
+
* Subscribe to several feature flags at once, live over Lunora's WebSocket.
|
|
259
|
+
*
|
|
260
|
+
* Pass a record of `key → defaultValue`; each flag's kind is inferred from its
|
|
261
|
+
* default, and the result is the same-shaped record with resolved values (the
|
|
262
|
+
* defaults until each evaluation lands). A single `context` applies to every
|
|
263
|
+
* flag. This is the batched form of {@link useFlag} — one effect manages one
|
|
264
|
+
* subscription per key, so it stays rules-of-hooks-safe even as the flag set
|
|
265
|
+
* changes between renders.
|
|
266
|
+
*/
|
|
267
|
+
declare const useFlags: <T extends Record<string, FlagValue>>(flags: T, context?: FlagContext) => T;
|
|
236
268
|
/** The args a paginated query exposes minus the framework-supplied page cursor. */
|
|
237
269
|
type PaginatedArgs<F> = Omit<ArgsOf<F>, "paginationOpts">;
|
|
238
270
|
/** The element type of the `page` array a paginated query returns. */
|
|
@@ -322,6 +354,31 @@ interface MutationHook<F extends FunctionReference> {
|
|
|
322
354
|
* through TanStack's `onMutate`.
|
|
323
355
|
*/
|
|
324
356
|
declare const useMutation: <F extends FunctionReference>(function_: F) => MutationHook<F>;
|
|
357
|
+
interface MutatorHook<TArgs> {
|
|
358
|
+
/** The latest invocation's error, or `undefined`. */
|
|
359
|
+
error: Error | undefined;
|
|
360
|
+
/** `true` when the latest invocation rejected. */
|
|
361
|
+
isError: boolean;
|
|
362
|
+
/** Run the mutator; resolves once the write is persisted, rejects on failure. */
|
|
363
|
+
mutate: (args: TArgs) => Promise<void>;
|
|
364
|
+
/** `true` while ANY invocation from this hook is in flight (ref-counted, so overlapping calls compose). */
|
|
365
|
+
pending: boolean;
|
|
366
|
+
/** Clear the latest `error` back to idle. */
|
|
367
|
+
reset: () => void;
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* Ergonomic `{ mutate, pending, error, isError, reset }` wrapper over a bound
|
|
371
|
+
* custom-mutator handle from `@lunora/db`'s `bindMutators`. The optimistic
|
|
372
|
+
* overlay and server-authoritative push are owned by the bound handle (and
|
|
373
|
+
* TanStack DB's optimistic-transaction layer rebases pending overlays on every
|
|
374
|
+
* sync tick) — this hook only surfaces React state for the in-flight/error
|
|
375
|
+
* lifecycle. Reads stay on the existing `useLiveQuery`; no new query hook is
|
|
376
|
+
* needed.
|
|
377
|
+
*
|
|
378
|
+
* `pending` is ref-counted across overlapping invocations of THIS hook instance,
|
|
379
|
+
* so it clears only once every concurrent call has settled.
|
|
380
|
+
*/
|
|
381
|
+
declare const useMutator: <TArgs = Record<string, unknown>>(handle: MutatorHandle<TArgs>) => MutatorHook<TArgs>;
|
|
325
382
|
/**
|
|
326
383
|
* Hydrate a query from a {@link Preloaded} token produced by `preloadQuery`
|
|
327
384
|
* during SSR, then keep it live.
|
|
@@ -496,4 +553,4 @@ declare const useStream: <F extends FunctionReference<"stream">>(function_: F, a
|
|
|
496
553
|
* the server pushes over the WS.
|
|
497
554
|
*/
|
|
498
555
|
declare const useSubscription: <F extends FunctionReference>(function_: F, args: ArgsOf<F> | "skip", options?: UseQueryOptions) => UseSubscriptionResult<ReturnOf<F>>;
|
|
499
|
-
export { AuthLoading, type AuthState, Authenticated, CheckoutButton, type CheckoutButtonProps, CustomerPortalButton, type CustomerPortalButtonProps, type HeartbeatReference, type ListPresentReference, LunoraProvider, type LunoraProviderProps, type MutationHook, type PageItemOf, type PaginatedArgs, type RedirectTarget, type RedirectTrigger, type Subscription, Unauthenticated, type UseAuthResult, type UseCheckoutResult, type UseInfiniteQueryOptions, type UseInfiniteQueryResult, type UseMutationCallOptions, type UsePaginatedQueryOptions, type UsePaginatedQueryResult, type UsePresenceOptions, type UsePresenceResult, type UseQueryOptions, type UseRateLimitOptions, type UseRateLimitResult, type UseStreamOptions, type UseStreamResult, type UseStreamStatus, type UseSubscriptionResult, hydratePreloaded, useAuth, useAuthState, useCheckout, useConnectionStatus, useInfiniteQuery, useLunora, useMutation, usePaginatedQuery, usePreloadedQuery, usePresence, useQuery, useRateLimit, useStream, useSubscription };
|
|
556
|
+
export { AuthLoading, type AuthState, Authenticated, CheckoutButton, type CheckoutButtonProps, CustomerPortalButton, type CustomerPortalButtonProps, type FlagContext, type FlagValue, type HeartbeatReference, type ListPresentReference, LunoraProvider, type LunoraProviderProps, type MutationHook, type MutatorHook, type PageItemOf, type PaginatedArgs, type RedirectTarget, type RedirectTrigger, type Subscription, Unauthenticated, type UseAuthResult, type UseCheckoutResult, type UseInfiniteQueryOptions, type UseInfiniteQueryResult, type UseMutationCallOptions, type UsePaginatedQueryOptions, type UsePaginatedQueryResult, type UsePresenceOptions, type UsePresenceResult, type UseQueryOptions, type UseRateLimitOptions, type UseRateLimitResult, type UseStreamOptions, type UseStreamResult, type UseStreamStatus, type UseSubscriptionResult, hydratePreloaded, useAuth, useAuthState, useCheckout, useConnectionStatus, useFlag, useFlags, useInfiniteQuery, useLunora, useMutation, useMutator, usePaginatedQuery, usePreloadedQuery, usePresence, useQuery, useRateLimit, useStream, useSubscription };
|
package/dist/index.mjs
CHANGED
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
export { AuthLoading, Authenticated, Unauthenticated } from './packem_shared/
|
|
3
|
-
export { useAuthState } from './packem_shared/useAuthState-
|
|
4
|
-
export { LunoraProvider, useLunora } from './packem_shared/LunoraProvider-
|
|
5
|
-
export { CheckoutButton, CustomerPortalButton, useCheckout } from './packem_shared/CheckoutButton-
|
|
6
|
-
export { lunoraQueryOptions } from './packem_shared/lunoraQueryOptions-
|
|
7
|
-
export { default as useAuth } from './packem_shared/useAuth-
|
|
8
|
-
export { default as useConnectionStatus } from './packem_shared/useConnectionStatus-
|
|
9
|
-
export {
|
|
10
|
-
export {
|
|
11
|
-
export {
|
|
12
|
-
export {
|
|
13
|
-
export {
|
|
14
|
-
export { default as
|
|
2
|
+
export { AuthLoading, Authenticated, Unauthenticated } from './packem_shared/AuthLoading-DezUWNB2.mjs';
|
|
3
|
+
export { useAuthState } from './packem_shared/useAuthState-CyF35qZR.mjs';
|
|
4
|
+
export { LunoraProvider, useLunora } from './packem_shared/LunoraProvider-BsuiW4Lk.mjs';
|
|
5
|
+
export { CheckoutButton, CustomerPortalButton, useCheckout } from './packem_shared/CheckoutButton-DUite8jJ.mjs';
|
|
6
|
+
export { lunoraQueryOptions } from './packem_shared/lunoraQueryOptions-C3uwOTMW.mjs';
|
|
7
|
+
export { default as useAuth } from './packem_shared/useAuth-BSutjJaa.mjs';
|
|
8
|
+
export { default as useConnectionStatus } from './packem_shared/useConnectionStatus-PJ7vyCHy.mjs';
|
|
9
|
+
export { useFlag, useFlags } from './packem_shared/useFlag-hhoN_xYA.mjs';
|
|
10
|
+
export { default as useInfiniteQuery } from './packem_shared/useInfiniteQuery-Dy42_srs.mjs';
|
|
11
|
+
export { useMutation } from './packem_shared/useMutation-BeqeIjTr.mjs';
|
|
12
|
+
export { useMutator } from './packem_shared/useMutator-IIrLtDiM.mjs';
|
|
13
|
+
export { usePaginatedQuery } from './packem_shared/usePaginatedQuery-Tx-B3mAP.mjs';
|
|
14
|
+
export { hydratePreloaded, default as usePreloadedQuery } from './packem_shared/hydratePreloaded-Dsf9YuII.mjs';
|
|
15
|
+
export { usePresence } from './packem_shared/usePresence-DC8VIyLB.mjs';
|
|
16
|
+
export { default as useQuery } from './packem_shared/useQuery-_fTR6DCQ.mjs';
|
|
15
17
|
export { useRateLimit } from './packem_shared/useRateLimit-DTEffQEi.mjs';
|
|
16
|
-
export { useStream } from './packem_shared/useStream-
|
|
17
|
-
export { default as useSubscription } from './packem_shared/useSubscription-
|
|
18
|
+
export { useStream } from './packem_shared/useStream-DFuryaIC.mjs';
|
|
19
|
+
export { default as useSubscription } from './packem_shared/useSubscription-D38Jdyr8.mjs';
|
|
20
|
+
export { getErrorCode, getRetryAfterMs, isConflictError, isForbiddenError, isRateLimitedError, isUnauthorizedError } from '@lunora/client';
|
|
@@ -3,6 +3,13 @@ import { c } from 'react/compiler-runtime';
|
|
|
3
3
|
import { useState, useCallback } from 'react';
|
|
4
4
|
import { jsxDEV } from 'react/jsx-dev-runtime';
|
|
5
5
|
|
|
6
|
+
const safeRedirectHref = (url) => {
|
|
7
|
+
const parsed = new URL(url, globalThis.location.href);
|
|
8
|
+
if (parsed.protocol !== "https:" && parsed.protocol !== "http:") {
|
|
9
|
+
throw new Error(`refusing to redirect to a non-http(s) URL: ${parsed.protocol}`);
|
|
10
|
+
}
|
|
11
|
+
return parsed.href;
|
|
12
|
+
};
|
|
6
13
|
const useCheckout = (trigger) => {
|
|
7
14
|
const [pending, setPending] = useState(false);
|
|
8
15
|
const [error, setError] = useState(void 0);
|
|
@@ -11,10 +18,7 @@ const useCheckout = (trigger) => {
|
|
|
11
18
|
setError(void 0);
|
|
12
19
|
try {
|
|
13
20
|
const target = await trigger();
|
|
14
|
-
|
|
15
|
-
url
|
|
16
|
-
} = target;
|
|
17
|
-
globalThis.location.assign(url);
|
|
21
|
+
globalThis.location.assign(safeRedirectHref(target.url));
|
|
18
22
|
} catch (error_) {
|
|
19
23
|
const normalized = error_ instanceof Error ? error_ : new Error(String(error_));
|
|
20
24
|
setError(normalized);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { c } from 'react/compiler-runtime';
|
|
3
|
+
import { LunoraError } from '@lunora/errors';
|
|
3
4
|
import { QueryClientContext, QueryClientProvider, QueryClient } from '@tanstack/react-query';
|
|
4
5
|
import { use, useState, createContext } from 'react';
|
|
5
6
|
import { jsxDEV } from 'react/jsx-dev-runtime';
|
|
@@ -37,7 +38,7 @@ const LunoraProvider = (t0) => {
|
|
|
37
38
|
const [internalClient] = useState(t1);
|
|
38
39
|
const effectiveClient = queryClient ?? parentQueryClient ?? internalClient;
|
|
39
40
|
if (!effectiveClient) {
|
|
40
|
-
throw new
|
|
41
|
+
throw new LunoraError("INTERNAL", "LunoraProvider: failed to resolve a QueryClient");
|
|
41
42
|
}
|
|
42
43
|
let t2;
|
|
43
44
|
if ($[3] !== children || $[4] !== client) {
|
|
@@ -72,7 +73,7 @@ const LunoraProvider = (t0) => {
|
|
|
72
73
|
const useLunora = () => {
|
|
73
74
|
const client = use(LunoraContext);
|
|
74
75
|
if (!client) {
|
|
75
|
-
throw new
|
|
76
|
+
throw new LunoraError("INTERNAL", "useLunora must be used inside <LunoraProvider />");
|
|
76
77
|
}
|
|
77
78
|
return client;
|
|
78
79
|
};
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
'use client';
|
|
2
|
+
import { c } from 'react/compiler-runtime';
|
|
2
3
|
import { useQueryClient, useQuery } from '@tanstack/react-query';
|
|
3
|
-
import {
|
|
4
|
-
import { g as getSubscriptionRegistry } from './cache-
|
|
5
|
-
import { useLunora } from './LunoraProvider-
|
|
6
|
-
import {
|
|
4
|
+
import { useEffect } from 'react';
|
|
5
|
+
import { g as getSubscriptionRegistry } from './cache-BFlsXmup.mjs';
|
|
6
|
+
import { useLunora } from './LunoraProvider-BsuiW4Lk.mjs';
|
|
7
|
+
import { s as serializeQueryKey, l as lunoraQueryKey } from './query-key-BmCbgidV.mjs';
|
|
7
8
|
|
|
8
9
|
const usePreloadedQuery = function(preloaded) {
|
|
10
|
+
const $ = c(4);
|
|
9
11
|
const client = useLunora();
|
|
10
12
|
const queryClient = useQueryClient();
|
|
11
13
|
const {
|
|
@@ -14,18 +16,13 @@ const usePreloadedQuery = function(preloaded) {
|
|
|
14
16
|
shardKey,
|
|
15
17
|
value
|
|
16
18
|
} = preloaded;
|
|
17
|
-
const functionRef =
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}, [functionPath]);
|
|
22
|
-
const queryKey = useMemo(() => lunoraQueryKey(functionRef, args, shardKey), [functionRef.__lunoraRef, JSON.stringify(args), shardKey]);
|
|
19
|
+
const functionRef = {
|
|
20
|
+
__lunoraRef: functionPath
|
|
21
|
+
};
|
|
22
|
+
const queryKey = lunoraQueryKey(functionRef, args, shardKey);
|
|
23
23
|
const {
|
|
24
24
|
data
|
|
25
25
|
} = useQuery({
|
|
26
|
-
// Seed the cache with the server value so the first paint doesn't
|
|
27
|
-
// re-fetch. TanStack treats `initialData` as fresh — the WS push from
|
|
28
|
-
// the registry is what supplies subsequent updates.
|
|
29
26
|
initialData: value,
|
|
30
27
|
queryFn: () => client.query(functionRef, args, {
|
|
31
28
|
shardKey
|
|
@@ -33,10 +30,21 @@ const usePreloadedQuery = function(preloaded) {
|
|
|
33
30
|
queryKey,
|
|
34
31
|
staleTime: Number.POSITIVE_INFINITY
|
|
35
32
|
});
|
|
33
|
+
const t0 = serializeQueryKey(queryKey);
|
|
34
|
+
let t1;
|
|
35
|
+
if ($[0] !== client || $[1] !== queryClient || $[2] !== t0) {
|
|
36
|
+
t1 = [client, queryClient, t0];
|
|
37
|
+
$[0] = client;
|
|
38
|
+
$[1] = queryClient;
|
|
39
|
+
$[2] = t0;
|
|
40
|
+
$[3] = t1;
|
|
41
|
+
} else {
|
|
42
|
+
t1 = $[3];
|
|
43
|
+
}
|
|
36
44
|
useEffect(() => {
|
|
37
45
|
const registry = getSubscriptionRegistry(client);
|
|
38
46
|
return registry.attach(queryClient, queryKey, functionRef, args, shardKey);
|
|
39
|
-
},
|
|
47
|
+
}, t1);
|
|
40
48
|
return data ?? value;
|
|
41
49
|
};
|
|
42
50
|
const hydratePreloaded = function(preloaded) {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { s as stableStringify } from './stable-key-CGp4e2Ux.mjs';
|
|
2
|
+
|
|
3
|
+
const keyHash = (queryKey) => stableStringify(queryKey);
|
|
4
|
+
const lunoraQueryKey = (function_, args, shardKey) => [
|
|
5
|
+
"lunora",
|
|
6
|
+
function_.__lunoraRef,
|
|
7
|
+
args,
|
|
8
|
+
// eslint-disable-next-line unicorn/no-null -- this literal is part of the JSON-serialized query key TanStack hashes for dedup; `null` keeps a stable, distinct slot from an absent shardKey across renders.
|
|
9
|
+
shardKey ?? null
|
|
10
|
+
];
|
|
11
|
+
const serializeQueryKey = (queryKey) => keyHash(queryKey);
|
|
12
|
+
|
|
13
|
+
export { keyHash as k, lunoraQueryKey as l, serializeQueryKey as s };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
const compareKeys = (a, b) => {
|
|
2
|
+
if (a < b) {
|
|
3
|
+
return -1;
|
|
4
|
+
}
|
|
5
|
+
return a > b ? 1 : 0;
|
|
6
|
+
};
|
|
7
|
+
const stableStringify = (value) => {
|
|
8
|
+
if (value === void 0) {
|
|
9
|
+
return "null";
|
|
10
|
+
}
|
|
11
|
+
if (typeof value === "bigint") {
|
|
12
|
+
throw new TypeError("stableStringify: cannot use a bigint in a cache key (query/subscription/shape args) — pass it as a string");
|
|
13
|
+
}
|
|
14
|
+
if (value === null || typeof value !== "object") {
|
|
15
|
+
return JSON.stringify(value);
|
|
16
|
+
}
|
|
17
|
+
if (Array.isArray(value)) {
|
|
18
|
+
return `[${value.map((item) => stableStringify(item)).join(",")}]`;
|
|
19
|
+
}
|
|
20
|
+
const proto = Object.getPrototypeOf(value);
|
|
21
|
+
if (proto !== null && proto !== Object.prototype) {
|
|
22
|
+
const name = value.constructor?.name ?? "value";
|
|
23
|
+
throw new TypeError(`stableStringify: cannot use a ${name} in a cache key (query/subscription/shape args) — only plain objects, arrays, and JSON primitives are supported`);
|
|
24
|
+
}
|
|
25
|
+
const record = value;
|
|
26
|
+
const keys = Object.keys(record).toSorted(compareKeys);
|
|
27
|
+
const parts = [];
|
|
28
|
+
for (const key of keys) {
|
|
29
|
+
const raw = record[key];
|
|
30
|
+
if (raw === void 0) {
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
parts.push(`${JSON.stringify(key)}:${stableStringify(raw)}`);
|
|
34
|
+
}
|
|
35
|
+
return `{${parts.join(",")}}`;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export { stableStringify as s };
|
package/dist/packem_shared/{use-paginated-core-CoOfcc-p.mjs → use-paginated-core-CWSzk1J1.mjs}
RENAMED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
import { initialPages, rebalance, derivePaginationStatus, applyLoadMore } from '@lunora/client/pagination';
|
|
3
3
|
import { useQueryClient } from '@tanstack/react-query';
|
|
4
4
|
import { useRef, useReducer, useState, useEffect, useCallback } from 'react';
|
|
5
|
-
import { g as getSubscriptionRegistry } from './cache-
|
|
6
|
-
import { useLunora } from './LunoraProvider-
|
|
7
|
-
import { s as serializeQueryKey, l as lunoraQueryKey } from './query-key-
|
|
5
|
+
import { g as getSubscriptionRegistry } from './cache-BFlsXmup.mjs';
|
|
6
|
+
import { useLunora } from './LunoraProvider-BsuiW4Lk.mjs';
|
|
7
|
+
import { s as serializeQueryKey, l as lunoraQueryKey } from './query-key-BmCbgidV.mjs';
|
|
8
8
|
|
|
9
9
|
const useLazyRef = function(create) {
|
|
10
10
|
const reference = useRef(void 0);
|
|
@@ -49,12 +49,14 @@ const usePaginatedCore = function(function_, args, options) {
|
|
|
49
49
|
key: key_0
|
|
50
50
|
}) => serializeQueryKey(key_0)).join("|");
|
|
51
51
|
const desiredRef = useRef({
|
|
52
|
+
baseArgs,
|
|
52
53
|
entries: [],
|
|
53
54
|
fn: function_,
|
|
54
55
|
shardKey
|
|
55
56
|
});
|
|
56
57
|
useEffect(() => {
|
|
57
58
|
desiredRef.current = {
|
|
59
|
+
baseArgs,
|
|
58
60
|
entries: pageEntries,
|
|
59
61
|
fn: function_,
|
|
60
62
|
shardKey
|
|
@@ -106,12 +108,16 @@ const usePaginatedCore = function(function_, args, options) {
|
|
|
106
108
|
detaches.set(hash_0, registry.attach(queryClient, entry.key, desired.fn, entry.args, desired.shardKey));
|
|
107
109
|
}
|
|
108
110
|
}, [client, queryClient, pageKeysHash, skipped]);
|
|
109
|
-
useEffect(
|
|
110
|
-
|
|
111
|
-
detach_2()
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
111
|
+
useEffect(
|
|
112
|
+
() => () => {
|
|
113
|
+
for (const detach_2 of detachesRef.current.values()) {
|
|
114
|
+
detach_2();
|
|
115
|
+
}
|
|
116
|
+
detachesRef.current.clear();
|
|
117
|
+
},
|
|
118
|
+
// react-doctor-disable-next-line react-doctor/exhaustive-deps -- intentional: unmount-only cleanup. `detachesRef` is a stable ref, so the empty dep array is correct — the teardown must run once on unmount, not every render.
|
|
119
|
+
[]
|
|
120
|
+
);
|
|
115
121
|
useEffect(() => {
|
|
116
122
|
const cache = queryClient.getQueryCache();
|
|
117
123
|
const unsubscribe = cache.subscribe((event) => {
|
|
@@ -140,17 +146,30 @@ const usePaginatedCore = function(function_, args, options) {
|
|
|
140
146
|
}
|
|
141
147
|
});
|
|
142
148
|
const {
|
|
143
|
-
nextCursor,
|
|
144
149
|
status
|
|
145
150
|
} = derivePaginationStatus(skipped, pageResults);
|
|
146
|
-
const nextCursorRef = useRef(void 0);
|
|
147
|
-
useEffect(() => {
|
|
148
|
-
nextCursorRef.current = status === "CanLoadMore" ? nextCursor : void 0;
|
|
149
|
-
});
|
|
150
151
|
const loadMore = useCallback((numberItems) => {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
152
|
+
setPages((current) => {
|
|
153
|
+
const desired_0 = desiredRef.current;
|
|
154
|
+
const results = current.map((page_0) => {
|
|
155
|
+
const pageArgs_0 = {
|
|
156
|
+
...desired_0.baseArgs,
|
|
157
|
+
paginationOpts: {
|
|
158
|
+
cursor: page_0.lower,
|
|
159
|
+
endCursor: page_0.upper,
|
|
160
|
+
numItems: page_0.numItems
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
return queryClient.getQueryData(lunoraQueryKey(desired_0.fn, pageArgs_0, desired_0.shardKey));
|
|
164
|
+
});
|
|
165
|
+
const {
|
|
166
|
+
nextCursor,
|
|
167
|
+
status: liveStatus
|
|
168
|
+
} = derivePaginationStatus(false, results);
|
|
169
|
+
const cursor = liveStatus === "CanLoadMore" ? nextCursor : void 0;
|
|
170
|
+
return applyLoadMore(current, cursor, numberItems) ?? current;
|
|
171
|
+
});
|
|
172
|
+
}, [queryClient]);
|
|
154
173
|
return {
|
|
155
174
|
loadMore,
|
|
156
175
|
pageResults,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { c } from 'react/compiler-runtime';
|
|
3
3
|
import { useSyncExternalStore } from 'react';
|
|
4
|
-
import { useLunora } from './LunoraProvider-
|
|
4
|
+
import { useLunora } from './LunoraProvider-BsuiW4Lk.mjs';
|
|
5
5
|
|
|
6
6
|
const stores = /* @__PURE__ */ new WeakMap();
|
|
7
7
|
const createStore = (client) => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { c } from 'react/compiler-runtime';
|
|
3
3
|
import { useSyncExternalStore } from 'react';
|
|
4
|
-
import useAuth from './useAuth-
|
|
4
|
+
import useAuth from './useAuth-BSutjJaa.mjs';
|
|
5
5
|
|
|
6
6
|
const subscribe = () => () => void 0;
|
|
7
7
|
const useAuthState = () => {
|
package/dist/packem_shared/{useConnectionStatus-DRSY9ldm.mjs → useConnectionStatus-PJ7vyCHy.mjs}
RENAMED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { c } from 'react/compiler-runtime';
|
|
3
3
|
import { useSyncExternalStore } from 'react';
|
|
4
|
-
import { useLunora } from './LunoraProvider-
|
|
4
|
+
import { useLunora } from './LunoraProvider-BsuiW4Lk.mjs';
|
|
5
5
|
|
|
6
6
|
const useConnectionStatus = () => {
|
|
7
7
|
const $ = c(4);
|