@fluxbase/sdk 0.0.1-rc.32 → 0.0.1-rc.33

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.cjs CHANGED
@@ -293,6 +293,14 @@ var FluxbaseAuth = class {
293
293
  return { user: session.user, session };
294
294
  });
295
295
  }
296
+ /**
297
+ * Refresh the session (Supabase-compatible alias)
298
+ * Alias for refreshSession() to maintain compatibility with Supabase naming
299
+ * Returns a new session with refreshed tokens
300
+ */
301
+ async refreshToken() {
302
+ return this.refreshSession();
303
+ }
296
304
  /**
297
305
  * Get the current user from the server
298
306
  */
@@ -619,6 +627,136 @@ var FluxbaseAuth = class {
619
627
  return { provider, url };
620
628
  });
621
629
  }
630
+ /**
631
+ * Sign in with OTP (One-Time Password) - Supabase-compatible
632
+ * Sends a one-time password via email or SMS for passwordless authentication
633
+ * @param credentials - Email or phone number and optional configuration
634
+ * @returns Promise with OTP-style response
635
+ */
636
+ async signInWithOtp(credentials) {
637
+ return wrapAsync(async () => {
638
+ await this.fetch.post("/api/v1/auth/otp/signin", credentials);
639
+ return { user: null, session: null };
640
+ });
641
+ }
642
+ /**
643
+ * Verify OTP (One-Time Password) - Supabase-compatible
644
+ * Verify OTP tokens for various authentication flows
645
+ * @param params - OTP verification parameters including token and type
646
+ * @returns Promise with user and session if successful
647
+ */
648
+ async verifyOtp(params) {
649
+ return wrapAsync(async () => {
650
+ const response = await this.fetch.post(
651
+ "/api/v1/auth/otp/verify",
652
+ params
653
+ );
654
+ if (response.access_token && response.refresh_token) {
655
+ const session = {
656
+ ...response,
657
+ expires_at: Date.now() + response.expires_in * 1e3
658
+ };
659
+ this.setSessionInternal(session);
660
+ return { user: response.user, session };
661
+ }
662
+ return { user: response.user, session: null };
663
+ });
664
+ }
665
+ /**
666
+ * Resend OTP (One-Time Password) - Supabase-compatible
667
+ * Resend OTP code when user doesn't receive it
668
+ * @param params - Resend parameters including type and email/phone
669
+ * @returns Promise with OTP-style response
670
+ */
671
+ async resendOtp(params) {
672
+ return wrapAsync(async () => {
673
+ await this.fetch.post("/api/v1/auth/otp/resend", params);
674
+ return { user: null, session: null };
675
+ });
676
+ }
677
+ /**
678
+ * Get user identities (linked OAuth providers) - Supabase-compatible
679
+ * Lists all OAuth identities linked to the current user
680
+ * @returns Promise with list of user identities
681
+ */
682
+ async getUserIdentities() {
683
+ return wrapAsync(async () => {
684
+ if (!this.session) {
685
+ throw new Error("Not authenticated");
686
+ }
687
+ return await this.fetch.get(
688
+ "/api/v1/auth/user/identities"
689
+ );
690
+ });
691
+ }
692
+ /**
693
+ * Link an OAuth identity to current user - Supabase-compatible
694
+ * Links an additional OAuth provider to the existing account
695
+ * @param credentials - Provider to link
696
+ * @returns Promise with OAuth URL to complete linking
697
+ */
698
+ async linkIdentity(credentials) {
699
+ return wrapAsync(async () => {
700
+ if (!this.session) {
701
+ throw new Error("Not authenticated");
702
+ }
703
+ return await this.fetch.post(
704
+ "/api/v1/auth/user/identities",
705
+ credentials
706
+ );
707
+ });
708
+ }
709
+ /**
710
+ * Unlink an OAuth identity from current user - Supabase-compatible
711
+ * Removes a linked OAuth provider from the account
712
+ * @param params - Identity to unlink
713
+ * @returns Promise with void response
714
+ */
715
+ async unlinkIdentity(params) {
716
+ return wrapAsyncVoid(async () => {
717
+ if (!this.session) {
718
+ throw new Error("Not authenticated");
719
+ }
720
+ await this.fetch.delete(
721
+ `/api/v1/auth/user/identities/${params.identity.id}`
722
+ );
723
+ });
724
+ }
725
+ /**
726
+ * Reauthenticate to get security nonce - Supabase-compatible
727
+ * Get a security nonce for sensitive operations (password change, etc.)
728
+ * @returns Promise with nonce for reauthentication
729
+ */
730
+ async reauthenticate() {
731
+ return wrapAsync(async () => {
732
+ if (!this.session) {
733
+ throw new Error("Not authenticated");
734
+ }
735
+ return await this.fetch.post(
736
+ "/api/v1/auth/reauthenticate"
737
+ );
738
+ });
739
+ }
740
+ /**
741
+ * Sign in with ID token (for native mobile apps) - Supabase-compatible
742
+ * Authenticate using native mobile app ID tokens (Google, Apple)
743
+ * @param credentials - Provider, ID token, and optional nonce
744
+ * @returns Promise with user and session
745
+ */
746
+ async signInWithIdToken(credentials) {
747
+ return wrapAsync(async () => {
748
+ const response = await this.fetch.post(
749
+ "/api/v1/auth/signin/idtoken",
750
+ credentials
751
+ );
752
+ const session = {
753
+ ...response,
754
+ expires_at: Date.now() + response.expires_in * 1e3
755
+ };
756
+ this.setSessionInternal(session);
757
+ return { user: session.user, session };
758
+ });
759
+ }
622
760
  /**
623
761
  * Internal: Set the session and persist it
624
762
  */
@@ -702,6 +840,8 @@ var RealtimeChannel = class {
702
840
  this.maxReconnectAttempts = 10;
703
841
  this.reconnectDelay = 1e3;
704
842
  this.heartbeatInterval = null;
843
+ this.pendingAcks = /* @__PURE__ */ new Map();
844
+ this.messageIdCounter = 0;
705
845
  this.url = url;
706
846
  this.channelName = channelName;
707
847
  this.token = token;
@@ -824,16 +964,40 @@ var RealtimeChannel = class {
824
964
  return "error";
825
965
  }
826
966
  try {
967
+ const messageId = this.config.broadcast?.ack ? `msg_${Date.now()}_${++this.messageIdCounter}` : void 0;
827
968
  this.ws.send(
828
969
  JSON.stringify({
829
970
  type: "broadcast",
830
971
  channel: this.channelName,
831
972
  event: message.event,
832
- payload: message.payload
973
+ payload: message.payload,
974
+ ...messageId && { messageId }
833
975
  })
834
976
  );
835
- if (this.config.broadcast?.ack) {
836
- return "ok";
977
+ if (this.config.broadcast?.ack && messageId) {
978
+ const ackTimeout = this.config.broadcast.ackTimeout || 5e3;
979
+ return await new Promise((resolve, reject) => {
980
+ const timeout = setTimeout(() => {
981
+ this.pendingAcks.delete(messageId);
982
+ reject(new Error("Acknowledgment timeout"));
983
+ }, ackTimeout);
984
+ this.pendingAcks.set(messageId, {
985
+ resolve: (value) => {
986
+ clearTimeout(timeout);
987
+ this.pendingAcks.delete(messageId);
988
+ resolve(value);
989
+ },
990
+ reject: (reason) => {
991
+ clearTimeout(timeout);
992
+ this.pendingAcks.delete(messageId);
993
+ reject(reason);
994
+ },
995
+ timeout
996
+ });
997
+ }).catch((error) => {
998
+ console.error("[Fluxbase Realtime] Acknowledgment error:", error);
999
+ return "error";
1000
+ });
837
1001
  }
838
1002
  return "ok";
839
1003
  } catch (error) {
@@ -1012,7 +1176,14 @@ var RealtimeChannel = class {
1012
1176
  }
1013
1177
  break;
1014
1178
  case "ack":
1015
- console.log("[Fluxbase Realtime] Subscription acknowledged");
1179
+ if (message.messageId && this.pendingAcks.has(message.messageId)) {
1180
+ const ackHandler = this.pendingAcks.get(message.messageId);
1181
+ if (ackHandler) {
1182
+ ackHandler.resolve(message.status || "ok");
1183
+ }
1184
+ } else {
1185
+ console.log("[Fluxbase Realtime] Acknowledged:", message);
1186
+ }
1016
1187
  break;
1017
1188
  case "error":
1018
1189
  console.error("[Fluxbase Realtime] Error:", message.error);