@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 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, SAMLProvider, SAMLLoginOptions, GraphQLRequestOptions, GraphQLError, GraphQLResponse, QueryBuilder, RealtimeCallback, RealtimePostgresChangesPayload, ListOptions, UploadOptions, UploadProgress, TransformOptions, SignedUrlOptions, AdminAuthResponse, ListUsersOptions, EnrichedUser, ClientKey, CreateClientKeyRequest, Webhook, CreateWebhookRequest, UpdateWebhookRequest, AppSettings, UpdateAppSettingsRequest, SystemSetting, UpdateSystemSettingRequest } from '@fluxbase/sdk';
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 - Function to build the query
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, SAMLProvider, SAMLLoginOptions, GraphQLRequestOptions, GraphQLError, GraphQLResponse, QueryBuilder, RealtimeCallback, RealtimePostgresChangesPayload, ListOptions, UploadOptions, UploadProgress, TransformOptions, SignedUrlOptions, AdminAuthResponse, ListUsersOptions, EnrichedUser, ClientKey, CreateClientKeyRequest, Webhook, CreateWebhookRequest, UpdateWebhookRequest, AppSettings, UpdateAppSettingsRequest, SystemSetting, UpdateSystemSettingRequest } from '@fluxbase/sdk';
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 - Function to build the query
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
- const queryKey = options?.queryKey || ["fluxbase", "query", buildQuery.toString()];
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
- queryKey: options?.queryKey || ["fluxbase", "table", table, buildQuery?.toString()]
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 (callback) {
631
- callback(payload);
647
+ if (callbackRef.current) {
648
+ callbackRef.current(payload);
632
649
  }
633
- if (autoInvalidate) {
650
+ if (autoInvalidateRef.current) {
634
651
  const tableName = channelName.replace(/^table:/, "");
635
- const key = invalidateKey || ["fluxbase", "table", tableName];
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
- staleTime: expiresIn ? expiresIn * 1e3 - 6e4 : 1e3 * 60 * 50
831
- // Refresh 1 minute before expiry
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
- staleTime: expiresIn ? expiresIn * 1e3 - 6e4 : 1e3 * 60 * 50
860
- // Refresh 1 minute before expiry
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) {