@fluxbase/sdk-react 2026.1.22 → 2026.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +33 -2
- package/dist/index.d.ts +33 -2
- package/dist/index.js +33 -21
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +33 -21
- package/dist/index.mjs.map +1 -1
- package/package.json +20 -10
- package/src/context.test.tsx +147 -0
- package/src/index.test.ts +255 -0
- package/src/test-setup.ts +22 -0
- package/src/test-utils.tsx +215 -0
- package/src/use-admin-auth.test.ts +175 -0
- package/src/use-admin-auth.ts +10 -2
- package/src/use-admin-hooks.test.ts +457 -0
- package/src/use-auth-config.test.ts +145 -0
- package/src/use-auth.test.ts +313 -0
- package/src/use-auth.ts +2 -1
- package/src/use-captcha.test.ts +273 -0
- package/src/use-client-keys.test.ts +286 -0
- package/src/use-graphql.test.ts +424 -0
- package/src/use-query.test.ts +348 -0
- package/src/use-query.ts +50 -4
- package/src/use-realtime.test.ts +359 -0
- package/src/use-realtime.ts +20 -15
- package/src/use-saml.test.ts +269 -0
- package/src/use-storage.test.ts +549 -0
- package/src/use-storage.ts +10 -2
- package/src/use-users.test.ts +264 -0
- package/vitest.config.ts +22 -0
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
3
|
import * as _fluxbase_sdk from '@fluxbase/sdk';
|
|
4
|
-
import { FluxbaseClient, User, AuthSession, SignInCredentials, SignUpCredentials, CaptchaConfig, CaptchaProvider, AuthConfig,
|
|
4
|
+
import { FluxbaseClient, User, AuthSession, SignInCredentials, SignUpCredentials, CaptchaConfig, CaptchaProvider, AuthConfig, SAMLLoginOptions, SAMLProvider, GraphQLRequestOptions, GraphQLError, GraphQLResponse, QueryBuilder, RealtimeCallback, RealtimePostgresChangesPayload, ListOptions, SignedUrlOptions, TransformOptions, UploadOptions, UploadProgress, AdminAuthResponse, ListUsersOptions, EnrichedUser, ClientKey, CreateClientKeyRequest, AppSettings, UpdateAppSettingsRequest, SystemSetting, UpdateSystemSettingRequest, Webhook, CreateWebhookRequest, UpdateWebhookRequest } from '@fluxbase/sdk';
|
|
5
5
|
export { APIKey, AdminUser, AppSettings, AuthSession, CaptchaConfig, CaptchaProvider, ClientKey, EnrichedUser, FluxbaseClient, GraphQLError, GraphQLErrorLocation, GraphQLRequestOptions, GraphQLResponse, ImageFitMode, ImageFormat, PostgrestResponse, RealtimeChangePayload, SAMLLoginOptions, SAMLLoginResponse, SAMLProvider, SAMLProvidersResponse, SAMLSession, SignInCredentials, SignUpCredentials, SignedUrlOptions, StorageObject, SystemSetting, TransformOptions, User, Webhook } from '@fluxbase/sdk';
|
|
6
6
|
import * as _tanstack_react_query from '@tanstack/react-query';
|
|
7
7
|
import { UseQueryOptions } from '@tanstack/react-query';
|
|
@@ -634,12 +634,40 @@ interface UseFluxbaseQueryOptions<T> extends Omit<UseQueryOptions<T[], Error>, '
|
|
|
634
634
|
* Hook to execute a database query
|
|
635
635
|
* @param buildQuery - Function that builds and returns the query
|
|
636
636
|
* @param options - React Query options
|
|
637
|
+
*
|
|
638
|
+
* IMPORTANT: You must provide a stable `queryKey` in options for proper caching.
|
|
639
|
+
* Without a custom queryKey, each render may create a new cache entry.
|
|
640
|
+
*
|
|
641
|
+
* @example
|
|
642
|
+
* ```tsx
|
|
643
|
+
* // Always provide a queryKey for stable caching
|
|
644
|
+
* useFluxbaseQuery(
|
|
645
|
+
* (client) => client.from('users').select('*'),
|
|
646
|
+
* { queryKey: ['users', 'all'] }
|
|
647
|
+
* )
|
|
648
|
+
* ```
|
|
637
649
|
*/
|
|
638
650
|
declare function useFluxbaseQuery<T = any>(buildQuery: (client: ReturnType<typeof useFluxbaseClient>) => QueryBuilder<T>, options?: UseFluxbaseQueryOptions<T>): _tanstack_react_query.UseQueryResult<T[], Error>;
|
|
639
651
|
/**
|
|
640
652
|
* Hook for table queries with a simpler API
|
|
641
653
|
* @param table - Table name
|
|
642
|
-
* @param buildQuery -
|
|
654
|
+
* @param buildQuery - Optional function to build the query (e.g., add filters)
|
|
655
|
+
* @param options - Query options including a stable queryKey
|
|
656
|
+
*
|
|
657
|
+
* NOTE: When using buildQuery with filters, provide a custom queryKey that includes
|
|
658
|
+
* the filter values to ensure proper caching.
|
|
659
|
+
*
|
|
660
|
+
* @example
|
|
661
|
+
* ```tsx
|
|
662
|
+
* // Simple query - queryKey is auto-generated from table name
|
|
663
|
+
* useTable('users')
|
|
664
|
+
*
|
|
665
|
+
* // With filters - provide queryKey including filter values
|
|
666
|
+
* useTable('users',
|
|
667
|
+
* (q) => q.eq('status', 'active'),
|
|
668
|
+
* { queryKey: ['users', 'active'] }
|
|
669
|
+
* )
|
|
670
|
+
* ```
|
|
643
671
|
*/
|
|
644
672
|
declare function useTable<T = any>(table: string, buildQuery?: (query: QueryBuilder<T>) => QueryBuilder<T>, options?: UseFluxbaseQueryOptions<T>): _tanstack_react_query.UseQueryResult<T[], Error>;
|
|
645
673
|
/**
|
|
@@ -693,6 +721,9 @@ interface UseRealtimeOptions {
|
|
|
693
721
|
}
|
|
694
722
|
/**
|
|
695
723
|
* Hook to subscribe to realtime changes for a channel
|
|
724
|
+
*
|
|
725
|
+
* NOTE: The callback and invalidateKey are stored in refs to prevent
|
|
726
|
+
* subscription recreation on every render when inline functions/arrays are used.
|
|
696
727
|
*/
|
|
697
728
|
declare function useRealtime(options: UseRealtimeOptions): {
|
|
698
729
|
channel: _fluxbase_sdk.RealtimeChannel | null;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
3
|
import * as _fluxbase_sdk from '@fluxbase/sdk';
|
|
4
|
-
import { FluxbaseClient, User, AuthSession, SignInCredentials, SignUpCredentials, CaptchaConfig, CaptchaProvider, AuthConfig,
|
|
4
|
+
import { FluxbaseClient, User, AuthSession, SignInCredentials, SignUpCredentials, CaptchaConfig, CaptchaProvider, AuthConfig, SAMLLoginOptions, SAMLProvider, GraphQLRequestOptions, GraphQLError, GraphQLResponse, QueryBuilder, RealtimeCallback, RealtimePostgresChangesPayload, ListOptions, SignedUrlOptions, TransformOptions, UploadOptions, UploadProgress, AdminAuthResponse, ListUsersOptions, EnrichedUser, ClientKey, CreateClientKeyRequest, AppSettings, UpdateAppSettingsRequest, SystemSetting, UpdateSystemSettingRequest, Webhook, CreateWebhookRequest, UpdateWebhookRequest } from '@fluxbase/sdk';
|
|
5
5
|
export { APIKey, AdminUser, AppSettings, AuthSession, CaptchaConfig, CaptchaProvider, ClientKey, EnrichedUser, FluxbaseClient, GraphQLError, GraphQLErrorLocation, GraphQLRequestOptions, GraphQLResponse, ImageFitMode, ImageFormat, PostgrestResponse, RealtimeChangePayload, SAMLLoginOptions, SAMLLoginResponse, SAMLProvider, SAMLProvidersResponse, SAMLSession, SignInCredentials, SignUpCredentials, SignedUrlOptions, StorageObject, SystemSetting, TransformOptions, User, Webhook } from '@fluxbase/sdk';
|
|
6
6
|
import * as _tanstack_react_query from '@tanstack/react-query';
|
|
7
7
|
import { UseQueryOptions } from '@tanstack/react-query';
|
|
@@ -634,12 +634,40 @@ interface UseFluxbaseQueryOptions<T> extends Omit<UseQueryOptions<T[], Error>, '
|
|
|
634
634
|
* Hook to execute a database query
|
|
635
635
|
* @param buildQuery - Function that builds and returns the query
|
|
636
636
|
* @param options - React Query options
|
|
637
|
+
*
|
|
638
|
+
* IMPORTANT: You must provide a stable `queryKey` in options for proper caching.
|
|
639
|
+
* Without a custom queryKey, each render may create a new cache entry.
|
|
640
|
+
*
|
|
641
|
+
* @example
|
|
642
|
+
* ```tsx
|
|
643
|
+
* // Always provide a queryKey for stable caching
|
|
644
|
+
* useFluxbaseQuery(
|
|
645
|
+
* (client) => client.from('users').select('*'),
|
|
646
|
+
* { queryKey: ['users', 'all'] }
|
|
647
|
+
* )
|
|
648
|
+
* ```
|
|
637
649
|
*/
|
|
638
650
|
declare function useFluxbaseQuery<T = any>(buildQuery: (client: ReturnType<typeof useFluxbaseClient>) => QueryBuilder<T>, options?: UseFluxbaseQueryOptions<T>): _tanstack_react_query.UseQueryResult<T[], Error>;
|
|
639
651
|
/**
|
|
640
652
|
* Hook for table queries with a simpler API
|
|
641
653
|
* @param table - Table name
|
|
642
|
-
* @param buildQuery -
|
|
654
|
+
* @param buildQuery - Optional function to build the query (e.g., add filters)
|
|
655
|
+
* @param options - Query options including a stable queryKey
|
|
656
|
+
*
|
|
657
|
+
* NOTE: When using buildQuery with filters, provide a custom queryKey that includes
|
|
658
|
+
* the filter values to ensure proper caching.
|
|
659
|
+
*
|
|
660
|
+
* @example
|
|
661
|
+
* ```tsx
|
|
662
|
+
* // Simple query - queryKey is auto-generated from table name
|
|
663
|
+
* useTable('users')
|
|
664
|
+
*
|
|
665
|
+
* // With filters - provide queryKey including filter values
|
|
666
|
+
* useTable('users',
|
|
667
|
+
* (q) => q.eq('status', 'active'),
|
|
668
|
+
* { queryKey: ['users', 'active'] }
|
|
669
|
+
* )
|
|
670
|
+
* ```
|
|
643
671
|
*/
|
|
644
672
|
declare function useTable<T = any>(table: string, buildQuery?: (query: QueryBuilder<T>) => QueryBuilder<T>, options?: UseFluxbaseQueryOptions<T>): _tanstack_react_query.UseQueryResult<T[], Error>;
|
|
645
673
|
/**
|
|
@@ -693,6 +721,9 @@ interface UseRealtimeOptions {
|
|
|
693
721
|
}
|
|
694
722
|
/**
|
|
695
723
|
* Hook to subscribe to realtime changes for a channel
|
|
724
|
+
*
|
|
725
|
+
* NOTE: The callback and invalidateKey are stored in refs to prevent
|
|
726
|
+
* subscription recreation on every render when inline functions/arrays are used.
|
|
696
727
|
*/
|
|
697
728
|
declare function useRealtime(options: UseRealtimeOptions): {
|
|
698
729
|
channel: _fluxbase_sdk.RealtimeChannel | null;
|
package/dist/index.js
CHANGED
|
@@ -135,7 +135,7 @@ function useSignIn() {
|
|
|
135
135
|
},
|
|
136
136
|
onSuccess: (session) => {
|
|
137
137
|
queryClient.setQueryData(["fluxbase", "auth", "session"], session);
|
|
138
|
-
if ("user" in session) {
|
|
138
|
+
if (session && "user" in session && session.user) {
|
|
139
139
|
queryClient.setQueryData(["fluxbase", "auth", "user"], session.user);
|
|
140
140
|
}
|
|
141
141
|
}
|
|
@@ -506,7 +506,12 @@ function useGraphQL() {
|
|
|
506
506
|
var import_react_query6 = require("@tanstack/react-query");
|
|
507
507
|
function useFluxbaseQuery(buildQuery, options) {
|
|
508
508
|
const client = useFluxbaseClient();
|
|
509
|
-
|
|
509
|
+
if (!options?.queryKey) {
|
|
510
|
+
console.warn(
|
|
511
|
+
"[useFluxbaseQuery] No queryKey provided. This may cause cache misses. Please provide a stable queryKey in options."
|
|
512
|
+
);
|
|
513
|
+
}
|
|
514
|
+
const queryKey = options?.queryKey || ["fluxbase", "query", "unstable"];
|
|
510
515
|
return (0, import_react_query6.useQuery)({
|
|
511
516
|
queryKey,
|
|
512
517
|
queryFn: async () => {
|
|
@@ -522,6 +527,11 @@ function useFluxbaseQuery(buildQuery, options) {
|
|
|
522
527
|
}
|
|
523
528
|
function useTable(table, buildQuery, options) {
|
|
524
529
|
const client = useFluxbaseClient();
|
|
530
|
+
if (buildQuery && !options?.queryKey) {
|
|
531
|
+
console.warn(
|
|
532
|
+
`[useTable] Using buildQuery without a custom queryKey for table "${table}". This may cause cache misses. Provide a queryKey that includes your filter values.`
|
|
533
|
+
);
|
|
534
|
+
}
|
|
525
535
|
return useFluxbaseQuery(
|
|
526
536
|
(client2) => {
|
|
527
537
|
const query = client2.from(table);
|
|
@@ -529,7 +539,8 @@ function useTable(table, buildQuery, options) {
|
|
|
529
539
|
},
|
|
530
540
|
{
|
|
531
541
|
...options,
|
|
532
|
-
|
|
542
|
+
// Use table name as base key, or custom key if provided
|
|
543
|
+
queryKey: options?.queryKey || ["fluxbase", "table", table]
|
|
533
544
|
}
|
|
534
545
|
);
|
|
535
546
|
}
|
|
@@ -620,6 +631,12 @@ function useRealtime(options) {
|
|
|
620
631
|
invalidateKey,
|
|
621
632
|
enabled = true
|
|
622
633
|
} = options;
|
|
634
|
+
const callbackRef = (0, import_react3.useRef)(callback);
|
|
635
|
+
const invalidateKeyRef = (0, import_react3.useRef)(invalidateKey);
|
|
636
|
+
const autoInvalidateRef = (0, import_react3.useRef)(autoInvalidate);
|
|
637
|
+
callbackRef.current = callback;
|
|
638
|
+
invalidateKeyRef.current = invalidateKey;
|
|
639
|
+
autoInvalidateRef.current = autoInvalidate;
|
|
623
640
|
(0, import_react3.useEffect)(() => {
|
|
624
641
|
if (!enabled) {
|
|
625
642
|
return;
|
|
@@ -627,12 +644,12 @@ function useRealtime(options) {
|
|
|
627
644
|
const channel = client.realtime.channel(channelName);
|
|
628
645
|
channelRef.current = channel;
|
|
629
646
|
const handleChange = (payload) => {
|
|
630
|
-
if (
|
|
631
|
-
|
|
647
|
+
if (callbackRef.current) {
|
|
648
|
+
callbackRef.current(payload);
|
|
632
649
|
}
|
|
633
|
-
if (
|
|
650
|
+
if (autoInvalidateRef.current) {
|
|
634
651
|
const tableName = channelName.replace(/^table:/, "");
|
|
635
|
-
const key =
|
|
652
|
+
const key = invalidateKeyRef.current || ["fluxbase", "table", tableName];
|
|
636
653
|
queryClient.invalidateQueries({ queryKey: key });
|
|
637
654
|
}
|
|
638
655
|
};
|
|
@@ -641,16 +658,7 @@ function useRealtime(options) {
|
|
|
641
658
|
channel.unsubscribe();
|
|
642
659
|
channelRef.current = null;
|
|
643
660
|
};
|
|
644
|
-
}, [
|
|
645
|
-
client,
|
|
646
|
-
channelName,
|
|
647
|
-
event,
|
|
648
|
-
callback,
|
|
649
|
-
autoInvalidate,
|
|
650
|
-
invalidateKey,
|
|
651
|
-
queryClient,
|
|
652
|
-
enabled
|
|
653
|
-
]);
|
|
661
|
+
}, [client, channelName, event, queryClient, enabled]);
|
|
654
662
|
return {
|
|
655
663
|
channel: channelRef.current
|
|
656
664
|
};
|
|
@@ -827,8 +835,10 @@ function useStorageSignedUrl(bucket, path, expiresIn) {
|
|
|
827
835
|
return data?.signedUrl || null;
|
|
828
836
|
},
|
|
829
837
|
enabled: !!path,
|
|
830
|
-
|
|
831
|
-
//
|
|
838
|
+
// Refresh 1 minute before expiry, but ensure staleTime is never negative
|
|
839
|
+
// For very short expirations (<60s), use half the expiration time
|
|
840
|
+
staleTime: expiresIn ? Math.max(expiresIn * 500, expiresIn * 1e3 - 6e4) : 1e3 * 60 * 50
|
|
841
|
+
// 50 minutes default
|
|
832
842
|
});
|
|
833
843
|
}
|
|
834
844
|
function useStorageSignedUrlWithOptions(bucket, path, options) {
|
|
@@ -856,8 +866,10 @@ function useStorageSignedUrlWithOptions(bucket, path, options) {
|
|
|
856
866
|
return data?.signedUrl || null;
|
|
857
867
|
},
|
|
858
868
|
enabled: !!path,
|
|
859
|
-
|
|
860
|
-
//
|
|
869
|
+
// Refresh 1 minute before expiry, but ensure staleTime is never negative
|
|
870
|
+
// For very short expirations (<60s), use half the expiration time
|
|
871
|
+
staleTime: expiresIn ? Math.max(expiresIn * 500, expiresIn * 1e3 - 6e4) : 1e3 * 60 * 50
|
|
872
|
+
// 50 minutes default
|
|
861
873
|
});
|
|
862
874
|
}
|
|
863
875
|
function useStorageMove(bucket) {
|