@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.d.cts CHANGED
@@ -99,9 +99,17 @@ interface TwoFactorSetupResponse {
99
99
  totp: TOTPSetup;
100
100
  }
101
101
  /**
102
- * MFA verify/enable response (Supabase-compatible)
102
+ * MFA enable response - returned when activating 2FA after setup
103
103
  */
104
104
  interface TwoFactorEnableResponse {
105
+ success: boolean;
106
+ backup_codes: string[];
107
+ message: string;
108
+ }
109
+ /**
110
+ * MFA login response - returned when verifying 2FA during login
111
+ */
112
+ interface TwoFactorLoginResponse {
105
113
  access_token: string;
106
114
  refresh_token: string;
107
115
  user: User;
@@ -200,6 +208,8 @@ interface RealtimeMessage {
200
208
  config?: PostgresChangesConfig;
201
209
  presence?: any;
202
210
  broadcast?: any;
211
+ messageId?: string;
212
+ status?: string;
203
213
  }
204
214
  interface PostgresChangesConfig {
205
215
  event: 'INSERT' | 'UPDATE' | 'DELETE' | '*';
@@ -250,6 +260,7 @@ interface RealtimeChannelConfig {
250
260
  broadcast?: {
251
261
  self?: boolean;
252
262
  ack?: boolean;
263
+ ackTimeout?: number;
253
264
  };
254
265
  presence?: {
255
266
  key?: string;
@@ -406,6 +417,69 @@ interface OAuthUrlResponse {
406
417
  url: string;
407
418
  provider: string;
408
419
  }
420
+ type OTPType = 'signup' | 'invite' | 'magiclink' | 'recovery' | 'email_change' | 'sms' | 'phone_change' | 'email';
421
+ interface SignInWithOtpCredentials {
422
+ email?: string;
423
+ phone?: string;
424
+ options?: {
425
+ emailRedirectTo?: string;
426
+ shouldCreateUser?: boolean;
427
+ data?: Record<string, any>;
428
+ captchaToken?: string;
429
+ };
430
+ }
431
+ interface VerifyOtpParams {
432
+ email?: string;
433
+ phone?: string;
434
+ token: string;
435
+ type: OTPType;
436
+ options?: {
437
+ redirectTo?: string;
438
+ captchaToken?: string;
439
+ };
440
+ }
441
+ interface ResendOtpParams {
442
+ type: 'signup' | 'sms' | 'email';
443
+ email?: string;
444
+ phone?: string;
445
+ options?: {
446
+ emailRedirectTo?: string;
447
+ captchaToken?: string;
448
+ };
449
+ }
450
+ interface OTPResponse {
451
+ user: null;
452
+ session: null;
453
+ messageId?: string;
454
+ }
455
+ interface UserIdentity {
456
+ id: string;
457
+ user_id: string;
458
+ identity_data?: Record<string, any>;
459
+ provider: string;
460
+ created_at: string;
461
+ updated_at: string;
462
+ }
463
+ interface UserIdentitiesResponse {
464
+ identities: UserIdentity[];
465
+ }
466
+ interface LinkIdentityCredentials {
467
+ provider: string;
468
+ }
469
+ interface UnlinkIdentityParams {
470
+ identity: UserIdentity;
471
+ }
472
+ interface ReauthenticateResponse {
473
+ nonce: string;
474
+ }
475
+ interface SignInWithIdTokenCredentials {
476
+ provider: 'google' | 'apple';
477
+ token: string;
478
+ nonce?: string;
479
+ options?: {
480
+ captchaToken?: string;
481
+ };
482
+ }
409
483
  interface AdminSetupStatusResponse {
410
484
  needs_setup: boolean;
411
485
  has_admin: boolean;
@@ -1282,6 +1356,8 @@ declare class RealtimeChannel {
1282
1356
  private maxReconnectAttempts;
1283
1357
  private reconnectDelay;
1284
1358
  private heartbeatInterval;
1359
+ private pendingAcks;
1360
+ private messageIdCounter;
1285
1361
  constructor(url: string, channelName: string, token?: string | null, config?: RealtimeChannelConfig);
1286
1362
  /**
1287
1363
  * Listen to postgres_changes with optional row-level filtering
@@ -1645,6 +1721,15 @@ declare class FluxbaseAuth {
1645
1721
  user: User;
1646
1722
  session: AuthSession;
1647
1723
  }>>;
1724
+ /**
1725
+ * Refresh the session (Supabase-compatible alias)
1726
+ * Alias for refreshSession() to maintain compatibility with Supabase naming
1727
+ * Returns a new session with refreshed tokens
1728
+ */
1729
+ refreshToken(): Promise<FluxbaseResponse<{
1730
+ user: User;
1731
+ session: AuthSession;
1732
+ }>>;
1648
1733
  /**
1649
1734
  * Get the current user from the server
1650
1735
  */
@@ -1695,7 +1780,7 @@ declare class FluxbaseAuth {
1695
1780
  * @param request - User ID and TOTP code
1696
1781
  * @returns Promise with access_token, refresh_token, and user
1697
1782
  */
1698
- verify2FA(request: TwoFactorVerifyRequest): Promise<DataResponse<TwoFactorEnableResponse>>;
1783
+ verify2FA(request: TwoFactorVerifyRequest): Promise<DataResponse<TwoFactorLoginResponse>>;
1699
1784
  /**
1700
1785
  * Send password reset email (Supabase-compatible)
1701
1786
  * Sends a password reset link to the provided email address
@@ -1769,6 +1854,60 @@ declare class FluxbaseAuth {
1769
1854
  provider: string;
1770
1855
  url: string;
1771
1856
  }>>;
1857
+ /**
1858
+ * Sign in with OTP (One-Time Password) - Supabase-compatible
1859
+ * Sends a one-time password via email or SMS for passwordless authentication
1860
+ * @param credentials - Email or phone number and optional configuration
1861
+ * @returns Promise with OTP-style response
1862
+ */
1863
+ signInWithOtp(credentials: SignInWithOtpCredentials): Promise<DataResponse<OTPResponse>>;
1864
+ /**
1865
+ * Verify OTP (One-Time Password) - Supabase-compatible
1866
+ * Verify OTP tokens for various authentication flows
1867
+ * @param params - OTP verification parameters including token and type
1868
+ * @returns Promise with user and session if successful
1869
+ */
1870
+ verifyOtp(params: VerifyOtpParams): Promise<FluxbaseAuthResponse>;
1871
+ /**
1872
+ * Resend OTP (One-Time Password) - Supabase-compatible
1873
+ * Resend OTP code when user doesn't receive it
1874
+ * @param params - Resend parameters including type and email/phone
1875
+ * @returns Promise with OTP-style response
1876
+ */
1877
+ resendOtp(params: ResendOtpParams): Promise<DataResponse<OTPResponse>>;
1878
+ /**
1879
+ * Get user identities (linked OAuth providers) - Supabase-compatible
1880
+ * Lists all OAuth identities linked to the current user
1881
+ * @returns Promise with list of user identities
1882
+ */
1883
+ getUserIdentities(): Promise<DataResponse<UserIdentitiesResponse>>;
1884
+ /**
1885
+ * Link an OAuth identity to current user - Supabase-compatible
1886
+ * Links an additional OAuth provider to the existing account
1887
+ * @param credentials - Provider to link
1888
+ * @returns Promise with OAuth URL to complete linking
1889
+ */
1890
+ linkIdentity(credentials: LinkIdentityCredentials): Promise<DataResponse<OAuthUrlResponse>>;
1891
+ /**
1892
+ * Unlink an OAuth identity from current user - Supabase-compatible
1893
+ * Removes a linked OAuth provider from the account
1894
+ * @param params - Identity to unlink
1895
+ * @returns Promise with void response
1896
+ */
1897
+ unlinkIdentity(params: UnlinkIdentityParams): Promise<VoidResponse>;
1898
+ /**
1899
+ * Reauthenticate to get security nonce - Supabase-compatible
1900
+ * Get a security nonce for sensitive operations (password change, etc.)
1901
+ * @returns Promise with nonce for reauthentication
1902
+ */
1903
+ reauthenticate(): Promise<DataResponse<ReauthenticateResponse>>;
1904
+ /**
1905
+ * Sign in with ID token (for native mobile apps) - Supabase-compatible
1906
+ * Authenticate using native mobile app ID tokens (Google, Apple)
1907
+ * @param credentials - Provider, ID token, and optional nonce
1908
+ * @returns Promise with user and session
1909
+ */
1910
+ signInWithIdToken(credentials: SignInWithIdTokenCredentials): Promise<FluxbaseAuthResponse>;
1772
1911
  /**
1773
1912
  * Internal: Set the session and persist it
1774
1913
  */
package/dist/index.d.ts CHANGED
@@ -99,9 +99,17 @@ interface TwoFactorSetupResponse {
99
99
  totp: TOTPSetup;
100
100
  }
101
101
  /**
102
- * MFA verify/enable response (Supabase-compatible)
102
+ * MFA enable response - returned when activating 2FA after setup
103
103
  */
104
104
  interface TwoFactorEnableResponse {
105
+ success: boolean;
106
+ backup_codes: string[];
107
+ message: string;
108
+ }
109
+ /**
110
+ * MFA login response - returned when verifying 2FA during login
111
+ */
112
+ interface TwoFactorLoginResponse {
105
113
  access_token: string;
106
114
  refresh_token: string;
107
115
  user: User;
@@ -200,6 +208,8 @@ interface RealtimeMessage {
200
208
  config?: PostgresChangesConfig;
201
209
  presence?: any;
202
210
  broadcast?: any;
211
+ messageId?: string;
212
+ status?: string;
203
213
  }
204
214
  interface PostgresChangesConfig {
205
215
  event: 'INSERT' | 'UPDATE' | 'DELETE' | '*';
@@ -250,6 +260,7 @@ interface RealtimeChannelConfig {
250
260
  broadcast?: {
251
261
  self?: boolean;
252
262
  ack?: boolean;
263
+ ackTimeout?: number;
253
264
  };
254
265
  presence?: {
255
266
  key?: string;
@@ -406,6 +417,69 @@ interface OAuthUrlResponse {
406
417
  url: string;
407
418
  provider: string;
408
419
  }
420
+ type OTPType = 'signup' | 'invite' | 'magiclink' | 'recovery' | 'email_change' | 'sms' | 'phone_change' | 'email';
421
+ interface SignInWithOtpCredentials {
422
+ email?: string;
423
+ phone?: string;
424
+ options?: {
425
+ emailRedirectTo?: string;
426
+ shouldCreateUser?: boolean;
427
+ data?: Record<string, any>;
428
+ captchaToken?: string;
429
+ };
430
+ }
431
+ interface VerifyOtpParams {
432
+ email?: string;
433
+ phone?: string;
434
+ token: string;
435
+ type: OTPType;
436
+ options?: {
437
+ redirectTo?: string;
438
+ captchaToken?: string;
439
+ };
440
+ }
441
+ interface ResendOtpParams {
442
+ type: 'signup' | 'sms' | 'email';
443
+ email?: string;
444
+ phone?: string;
445
+ options?: {
446
+ emailRedirectTo?: string;
447
+ captchaToken?: string;
448
+ };
449
+ }
450
+ interface OTPResponse {
451
+ user: null;
452
+ session: null;
453
+ messageId?: string;
454
+ }
455
+ interface UserIdentity {
456
+ id: string;
457
+ user_id: string;
458
+ identity_data?: Record<string, any>;
459
+ provider: string;
460
+ created_at: string;
461
+ updated_at: string;
462
+ }
463
+ interface UserIdentitiesResponse {
464
+ identities: UserIdentity[];
465
+ }
466
+ interface LinkIdentityCredentials {
467
+ provider: string;
468
+ }
469
+ interface UnlinkIdentityParams {
470
+ identity: UserIdentity;
471
+ }
472
+ interface ReauthenticateResponse {
473
+ nonce: string;
474
+ }
475
+ interface SignInWithIdTokenCredentials {
476
+ provider: 'google' | 'apple';
477
+ token: string;
478
+ nonce?: string;
479
+ options?: {
480
+ captchaToken?: string;
481
+ };
482
+ }
409
483
  interface AdminSetupStatusResponse {
410
484
  needs_setup: boolean;
411
485
  has_admin: boolean;
@@ -1282,6 +1356,8 @@ declare class RealtimeChannel {
1282
1356
  private maxReconnectAttempts;
1283
1357
  private reconnectDelay;
1284
1358
  private heartbeatInterval;
1359
+ private pendingAcks;
1360
+ private messageIdCounter;
1285
1361
  constructor(url: string, channelName: string, token?: string | null, config?: RealtimeChannelConfig);
1286
1362
  /**
1287
1363
  * Listen to postgres_changes with optional row-level filtering
@@ -1645,6 +1721,15 @@ declare class FluxbaseAuth {
1645
1721
  user: User;
1646
1722
  session: AuthSession;
1647
1723
  }>>;
1724
+ /**
1725
+ * Refresh the session (Supabase-compatible alias)
1726
+ * Alias for refreshSession() to maintain compatibility with Supabase naming
1727
+ * Returns a new session with refreshed tokens
1728
+ */
1729
+ refreshToken(): Promise<FluxbaseResponse<{
1730
+ user: User;
1731
+ session: AuthSession;
1732
+ }>>;
1648
1733
  /**
1649
1734
  * Get the current user from the server
1650
1735
  */
@@ -1695,7 +1780,7 @@ declare class FluxbaseAuth {
1695
1780
  * @param request - User ID and TOTP code
1696
1781
  * @returns Promise with access_token, refresh_token, and user
1697
1782
  */
1698
- verify2FA(request: TwoFactorVerifyRequest): Promise<DataResponse<TwoFactorEnableResponse>>;
1783
+ verify2FA(request: TwoFactorVerifyRequest): Promise<DataResponse<TwoFactorLoginResponse>>;
1699
1784
  /**
1700
1785
  * Send password reset email (Supabase-compatible)
1701
1786
  * Sends a password reset link to the provided email address
@@ -1769,6 +1854,60 @@ declare class FluxbaseAuth {
1769
1854
  provider: string;
1770
1855
  url: string;
1771
1856
  }>>;
1857
+ /**
1858
+ * Sign in with OTP (One-Time Password) - Supabase-compatible
1859
+ * Sends a one-time password via email or SMS for passwordless authentication
1860
+ * @param credentials - Email or phone number and optional configuration
1861
+ * @returns Promise with OTP-style response
1862
+ */
1863
+ signInWithOtp(credentials: SignInWithOtpCredentials): Promise<DataResponse<OTPResponse>>;
1864
+ /**
1865
+ * Verify OTP (One-Time Password) - Supabase-compatible
1866
+ * Verify OTP tokens for various authentication flows
1867
+ * @param params - OTP verification parameters including token and type
1868
+ * @returns Promise with user and session if successful
1869
+ */
1870
+ verifyOtp(params: VerifyOtpParams): Promise<FluxbaseAuthResponse>;
1871
+ /**
1872
+ * Resend OTP (One-Time Password) - Supabase-compatible
1873
+ * Resend OTP code when user doesn't receive it
1874
+ * @param params - Resend parameters including type and email/phone
1875
+ * @returns Promise with OTP-style response
1876
+ */
1877
+ resendOtp(params: ResendOtpParams): Promise<DataResponse<OTPResponse>>;
1878
+ /**
1879
+ * Get user identities (linked OAuth providers) - Supabase-compatible
1880
+ * Lists all OAuth identities linked to the current user
1881
+ * @returns Promise with list of user identities
1882
+ */
1883
+ getUserIdentities(): Promise<DataResponse<UserIdentitiesResponse>>;
1884
+ /**
1885
+ * Link an OAuth identity to current user - Supabase-compatible
1886
+ * Links an additional OAuth provider to the existing account
1887
+ * @param credentials - Provider to link
1888
+ * @returns Promise with OAuth URL to complete linking
1889
+ */
1890
+ linkIdentity(credentials: LinkIdentityCredentials): Promise<DataResponse<OAuthUrlResponse>>;
1891
+ /**
1892
+ * Unlink an OAuth identity from current user - Supabase-compatible
1893
+ * Removes a linked OAuth provider from the account
1894
+ * @param params - Identity to unlink
1895
+ * @returns Promise with void response
1896
+ */
1897
+ unlinkIdentity(params: UnlinkIdentityParams): Promise<VoidResponse>;
1898
+ /**
1899
+ * Reauthenticate to get security nonce - Supabase-compatible
1900
+ * Get a security nonce for sensitive operations (password change, etc.)
1901
+ * @returns Promise with nonce for reauthentication
1902
+ */
1903
+ reauthenticate(): Promise<DataResponse<ReauthenticateResponse>>;
1904
+ /**
1905
+ * Sign in with ID token (for native mobile apps) - Supabase-compatible
1906
+ * Authenticate using native mobile app ID tokens (Google, Apple)
1907
+ * @param credentials - Provider, ID token, and optional nonce
1908
+ * @returns Promise with user and session
1909
+ */
1910
+ signInWithIdToken(credentials: SignInWithIdTokenCredentials): Promise<FluxbaseAuthResponse>;
1772
1911
  /**
1773
1912
  * Internal: Set the session and persist it
1774
1913
  */
package/dist/index.js CHANGED
@@ -291,6 +291,14 @@ var FluxbaseAuth = class {
291
291
  return { user: session.user, session };
292
292
  });
293
293
  }
294
+ /**
295
+ * Refresh the session (Supabase-compatible alias)
296
+ * Alias for refreshSession() to maintain compatibility with Supabase naming
297
+ * Returns a new session with refreshed tokens
298
+ */
299
+ async refreshToken() {
300
+ return this.refreshSession();
301
+ }
294
302
  /**
295
303
  * Get the current user from the server
296
304
  */
@@ -617,6 +625,136 @@ var FluxbaseAuth = class {
617
625
  return { provider, url };
618
626
  });
619
627
  }
628
+ /**
629
+ * Sign in with OTP (One-Time Password) - Supabase-compatible
630
+ * Sends a one-time password via email or SMS for passwordless authentication
631
+ * @param credentials - Email or phone number and optional configuration
632
+ * @returns Promise with OTP-style response
633
+ */
634
+ async signInWithOtp(credentials) {
635
+ return wrapAsync(async () => {
636
+ await this.fetch.post("/api/v1/auth/otp/signin", credentials);
637
+ return { user: null, session: null };
638
+ });
639
+ }
640
+ /**
641
+ * Verify OTP (One-Time Password) - Supabase-compatible
642
+ * Verify OTP tokens for various authentication flows
643
+ * @param params - OTP verification parameters including token and type
644
+ * @returns Promise with user and session if successful
645
+ */
646
+ async verifyOtp(params) {
647
+ return wrapAsync(async () => {
648
+ const response = await this.fetch.post(
649
+ "/api/v1/auth/otp/verify",
650
+ params
651
+ );
652
+ if (response.access_token && response.refresh_token) {
653
+ const session = {
654
+ ...response,
655
+ expires_at: Date.now() + response.expires_in * 1e3
656
+ };
657
+ this.setSessionInternal(session);
658
+ return { user: response.user, session };
659
+ }
660
+ return { user: response.user, session: null };
661
+ });
662
+ }
663
+ /**
664
+ * Resend OTP (One-Time Password) - Supabase-compatible
665
+ * Resend OTP code when user doesn't receive it
666
+ * @param params - Resend parameters including type and email/phone
667
+ * @returns Promise with OTP-style response
668
+ */
669
+ async resendOtp(params) {
670
+ return wrapAsync(async () => {
671
+ await this.fetch.post("/api/v1/auth/otp/resend", params);
672
+ return { user: null, session: null };
673
+ });
674
+ }
675
+ /**
676
+ * Get user identities (linked OAuth providers) - Supabase-compatible
677
+ * Lists all OAuth identities linked to the current user
678
+ * @returns Promise with list of user identities
679
+ */
680
+ async getUserIdentities() {
681
+ return wrapAsync(async () => {
682
+ if (!this.session) {
683
+ throw new Error("Not authenticated");
684
+ }
685
+ return await this.fetch.get(
686
+ "/api/v1/auth/user/identities"
687
+ );
688
+ });
689
+ }
690
+ /**
691
+ * Link an OAuth identity to current user - Supabase-compatible
692
+ * Links an additional OAuth provider to the existing account
693
+ * @param credentials - Provider to link
694
+ * @returns Promise with OAuth URL to complete linking
695
+ */
696
+ async linkIdentity(credentials) {
697
+ return wrapAsync(async () => {
698
+ if (!this.session) {
699
+ throw new Error("Not authenticated");
700
+ }
701
+ return await this.fetch.post(
702
+ "/api/v1/auth/user/identities",
703
+ credentials
704
+ );
705
+ });
706
+ }
707
+ /**
708
+ * Unlink an OAuth identity from current user - Supabase-compatible
709
+ * Removes a linked OAuth provider from the account
710
+ * @param params - Identity to unlink
711
+ * @returns Promise with void response
712
+ */
713
+ async unlinkIdentity(params) {
714
+ return wrapAsyncVoid(async () => {
715
+ if (!this.session) {
716
+ throw new Error("Not authenticated");
717
+ }
718
+ await this.fetch.delete(
719
+ `/api/v1/auth/user/identities/${params.identity.id}`
720
+ );
721
+ });
722
+ }
723
+ /**
724
+ * Reauthenticate to get security nonce - Supabase-compatible
725
+ * Get a security nonce for sensitive operations (password change, etc.)
726
+ * @returns Promise with nonce for reauthentication
727
+ */
728
+ async reauthenticate() {
729
+ return wrapAsync(async () => {
730
+ if (!this.session) {
731
+ throw new Error("Not authenticated");
732
+ }
733
+ return await this.fetch.post(
734
+ "/api/v1/auth/reauthenticate"
735
+ );
736
+ });
737
+ }
738
+ /**
739
+ * Sign in with ID token (for native mobile apps) - Supabase-compatible
740
+ * Authenticate using native mobile app ID tokens (Google, Apple)
741
+ * @param credentials - Provider, ID token, and optional nonce
742
+ * @returns Promise with user and session
743
+ */
744
+ async signInWithIdToken(credentials) {
745
+ return wrapAsync(async () => {
746
+ const response = await this.fetch.post(
747
+ "/api/v1/auth/signin/idtoken",
748
+ credentials
749
+ );
750
+ const session = {
751
+ ...response,
752
+ expires_at: Date.now() + response.expires_in * 1e3
753
+ };
754
+ this.setSessionInternal(session);
755
+ return { user: session.user, session };
756
+ });
757
+ }
620
758
  /**
621
759
  * Internal: Set the session and persist it
622
760
  */
@@ -700,6 +838,8 @@ var RealtimeChannel = class {
700
838
  this.maxReconnectAttempts = 10;
701
839
  this.reconnectDelay = 1e3;
702
840
  this.heartbeatInterval = null;
841
+ this.pendingAcks = /* @__PURE__ */ new Map();
842
+ this.messageIdCounter = 0;
703
843
  this.url = url;
704
844
  this.channelName = channelName;
705
845
  this.token = token;
@@ -822,16 +962,40 @@ var RealtimeChannel = class {
822
962
  return "error";
823
963
  }
824
964
  try {
965
+ const messageId = this.config.broadcast?.ack ? `msg_${Date.now()}_${++this.messageIdCounter}` : void 0;
825
966
  this.ws.send(
826
967
  JSON.stringify({
827
968
  type: "broadcast",
828
969
  channel: this.channelName,
829
970
  event: message.event,
830
- payload: message.payload
971
+ payload: message.payload,
972
+ ...messageId && { messageId }
831
973
  })
832
974
  );
833
- if (this.config.broadcast?.ack) {
834
- return "ok";
975
+ if (this.config.broadcast?.ack && messageId) {
976
+ const ackTimeout = this.config.broadcast.ackTimeout || 5e3;
977
+ return await new Promise((resolve, reject) => {
978
+ const timeout = setTimeout(() => {
979
+ this.pendingAcks.delete(messageId);
980
+ reject(new Error("Acknowledgment timeout"));
981
+ }, ackTimeout);
982
+ this.pendingAcks.set(messageId, {
983
+ resolve: (value) => {
984
+ clearTimeout(timeout);
985
+ this.pendingAcks.delete(messageId);
986
+ resolve(value);
987
+ },
988
+ reject: (reason) => {
989
+ clearTimeout(timeout);
990
+ this.pendingAcks.delete(messageId);
991
+ reject(reason);
992
+ },
993
+ timeout
994
+ });
995
+ }).catch((error) => {
996
+ console.error("[Fluxbase Realtime] Acknowledgment error:", error);
997
+ return "error";
998
+ });
835
999
  }
836
1000
  return "ok";
837
1001
  } catch (error) {
@@ -1010,7 +1174,14 @@ var RealtimeChannel = class {
1010
1174
  }
1011
1175
  break;
1012
1176
  case "ack":
1013
- console.log("[Fluxbase Realtime] Subscription acknowledged");
1177
+ if (message.messageId && this.pendingAcks.has(message.messageId)) {
1178
+ const ackHandler = this.pendingAcks.get(message.messageId);
1179
+ if (ackHandler) {
1180
+ ackHandler.resolve(message.status || "ok");
1181
+ }
1182
+ } else {
1183
+ console.log("[Fluxbase Realtime] Acknowledged:", message);
1184
+ }
1014
1185
  break;
1015
1186
  case "error":
1016
1187
  console.error("[Fluxbase Realtime] Error:", message.error);