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

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
  */
@@ -1666,9 +1751,10 @@ declare class FluxbaseAuth {
1666
1751
  /**
1667
1752
  * Setup 2FA for the current user (Supabase-compatible)
1668
1753
  * Enrolls a new MFA factor and returns TOTP details
1754
+ * @param issuer - Optional custom issuer name for the QR code (e.g., "MyApp"). If not provided, uses server default.
1669
1755
  * @returns Promise with factor id, type, and TOTP setup details
1670
1756
  */
1671
- setup2FA(): Promise<DataResponse<TwoFactorSetupResponse>>;
1757
+ setup2FA(issuer?: string): Promise<DataResponse<TwoFactorSetupResponse>>;
1672
1758
  /**
1673
1759
  * Enable 2FA after verifying the TOTP code (Supabase-compatible)
1674
1760
  * Verifies the TOTP code and returns new tokens with MFA session
@@ -1695,7 +1781,7 @@ declare class FluxbaseAuth {
1695
1781
  * @param request - User ID and TOTP code
1696
1782
  * @returns Promise with access_token, refresh_token, and user
1697
1783
  */
1698
- verify2FA(request: TwoFactorVerifyRequest): Promise<DataResponse<TwoFactorEnableResponse>>;
1784
+ verify2FA(request: TwoFactorVerifyRequest): Promise<DataResponse<TwoFactorLoginResponse>>;
1699
1785
  /**
1700
1786
  * Send password reset email (Supabase-compatible)
1701
1787
  * Sends a password reset link to the provided email address
@@ -1769,6 +1855,60 @@ declare class FluxbaseAuth {
1769
1855
  provider: string;
1770
1856
  url: string;
1771
1857
  }>>;
1858
+ /**
1859
+ * Sign in with OTP (One-Time Password) - Supabase-compatible
1860
+ * Sends a one-time password via email or SMS for passwordless authentication
1861
+ * @param credentials - Email or phone number and optional configuration
1862
+ * @returns Promise with OTP-style response
1863
+ */
1864
+ signInWithOtp(credentials: SignInWithOtpCredentials): Promise<DataResponse<OTPResponse>>;
1865
+ /**
1866
+ * Verify OTP (One-Time Password) - Supabase-compatible
1867
+ * Verify OTP tokens for various authentication flows
1868
+ * @param params - OTP verification parameters including token and type
1869
+ * @returns Promise with user and session if successful
1870
+ */
1871
+ verifyOtp(params: VerifyOtpParams): Promise<FluxbaseAuthResponse>;
1872
+ /**
1873
+ * Resend OTP (One-Time Password) - Supabase-compatible
1874
+ * Resend OTP code when user doesn't receive it
1875
+ * @param params - Resend parameters including type and email/phone
1876
+ * @returns Promise with OTP-style response
1877
+ */
1878
+ resendOtp(params: ResendOtpParams): Promise<DataResponse<OTPResponse>>;
1879
+ /**
1880
+ * Get user identities (linked OAuth providers) - Supabase-compatible
1881
+ * Lists all OAuth identities linked to the current user
1882
+ * @returns Promise with list of user identities
1883
+ */
1884
+ getUserIdentities(): Promise<DataResponse<UserIdentitiesResponse>>;
1885
+ /**
1886
+ * Link an OAuth identity to current user - Supabase-compatible
1887
+ * Links an additional OAuth provider to the existing account
1888
+ * @param credentials - Provider to link
1889
+ * @returns Promise with OAuth URL to complete linking
1890
+ */
1891
+ linkIdentity(credentials: LinkIdentityCredentials): Promise<DataResponse<OAuthUrlResponse>>;
1892
+ /**
1893
+ * Unlink an OAuth identity from current user - Supabase-compatible
1894
+ * Removes a linked OAuth provider from the account
1895
+ * @param params - Identity to unlink
1896
+ * @returns Promise with void response
1897
+ */
1898
+ unlinkIdentity(params: UnlinkIdentityParams): Promise<VoidResponse>;
1899
+ /**
1900
+ * Reauthenticate to get security nonce - Supabase-compatible
1901
+ * Get a security nonce for sensitive operations (password change, etc.)
1902
+ * @returns Promise with nonce for reauthentication
1903
+ */
1904
+ reauthenticate(): Promise<DataResponse<ReauthenticateResponse>>;
1905
+ /**
1906
+ * Sign in with ID token (for native mobile apps) - Supabase-compatible
1907
+ * Authenticate using native mobile app ID tokens (Google, Apple)
1908
+ * @param credentials - Provider, ID token, and optional nonce
1909
+ * @returns Promise with user and session
1910
+ */
1911
+ signInWithIdToken(credentials: SignInWithIdTokenCredentials): Promise<FluxbaseAuthResponse>;
1772
1912
  /**
1773
1913
  * Internal: Set the session and persist it
1774
1914
  */
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
  */
@@ -1666,9 +1751,10 @@ declare class FluxbaseAuth {
1666
1751
  /**
1667
1752
  * Setup 2FA for the current user (Supabase-compatible)
1668
1753
  * Enrolls a new MFA factor and returns TOTP details
1754
+ * @param issuer - Optional custom issuer name for the QR code (e.g., "MyApp"). If not provided, uses server default.
1669
1755
  * @returns Promise with factor id, type, and TOTP setup details
1670
1756
  */
1671
- setup2FA(): Promise<DataResponse<TwoFactorSetupResponse>>;
1757
+ setup2FA(issuer?: string): Promise<DataResponse<TwoFactorSetupResponse>>;
1672
1758
  /**
1673
1759
  * Enable 2FA after verifying the TOTP code (Supabase-compatible)
1674
1760
  * Verifies the TOTP code and returns new tokens with MFA session
@@ -1695,7 +1781,7 @@ declare class FluxbaseAuth {
1695
1781
  * @param request - User ID and TOTP code
1696
1782
  * @returns Promise with access_token, refresh_token, and user
1697
1783
  */
1698
- verify2FA(request: TwoFactorVerifyRequest): Promise<DataResponse<TwoFactorEnableResponse>>;
1784
+ verify2FA(request: TwoFactorVerifyRequest): Promise<DataResponse<TwoFactorLoginResponse>>;
1699
1785
  /**
1700
1786
  * Send password reset email (Supabase-compatible)
1701
1787
  * Sends a password reset link to the provided email address
@@ -1769,6 +1855,60 @@ declare class FluxbaseAuth {
1769
1855
  provider: string;
1770
1856
  url: string;
1771
1857
  }>>;
1858
+ /**
1859
+ * Sign in with OTP (One-Time Password) - Supabase-compatible
1860
+ * Sends a one-time password via email or SMS for passwordless authentication
1861
+ * @param credentials - Email or phone number and optional configuration
1862
+ * @returns Promise with OTP-style response
1863
+ */
1864
+ signInWithOtp(credentials: SignInWithOtpCredentials): Promise<DataResponse<OTPResponse>>;
1865
+ /**
1866
+ * Verify OTP (One-Time Password) - Supabase-compatible
1867
+ * Verify OTP tokens for various authentication flows
1868
+ * @param params - OTP verification parameters including token and type
1869
+ * @returns Promise with user and session if successful
1870
+ */
1871
+ verifyOtp(params: VerifyOtpParams): Promise<FluxbaseAuthResponse>;
1872
+ /**
1873
+ * Resend OTP (One-Time Password) - Supabase-compatible
1874
+ * Resend OTP code when user doesn't receive it
1875
+ * @param params - Resend parameters including type and email/phone
1876
+ * @returns Promise with OTP-style response
1877
+ */
1878
+ resendOtp(params: ResendOtpParams): Promise<DataResponse<OTPResponse>>;
1879
+ /**
1880
+ * Get user identities (linked OAuth providers) - Supabase-compatible
1881
+ * Lists all OAuth identities linked to the current user
1882
+ * @returns Promise with list of user identities
1883
+ */
1884
+ getUserIdentities(): Promise<DataResponse<UserIdentitiesResponse>>;
1885
+ /**
1886
+ * Link an OAuth identity to current user - Supabase-compatible
1887
+ * Links an additional OAuth provider to the existing account
1888
+ * @param credentials - Provider to link
1889
+ * @returns Promise with OAuth URL to complete linking
1890
+ */
1891
+ linkIdentity(credentials: LinkIdentityCredentials): Promise<DataResponse<OAuthUrlResponse>>;
1892
+ /**
1893
+ * Unlink an OAuth identity from current user - Supabase-compatible
1894
+ * Removes a linked OAuth provider from the account
1895
+ * @param params - Identity to unlink
1896
+ * @returns Promise with void response
1897
+ */
1898
+ unlinkIdentity(params: UnlinkIdentityParams): Promise<VoidResponse>;
1899
+ /**
1900
+ * Reauthenticate to get security nonce - Supabase-compatible
1901
+ * Get a security nonce for sensitive operations (password change, etc.)
1902
+ * @returns Promise with nonce for reauthentication
1903
+ */
1904
+ reauthenticate(): Promise<DataResponse<ReauthenticateResponse>>;
1905
+ /**
1906
+ * Sign in with ID token (for native mobile apps) - Supabase-compatible
1907
+ * Authenticate using native mobile app ID tokens (Google, Apple)
1908
+ * @param credentials - Provider, ID token, and optional nonce
1909
+ * @returns Promise with user and session
1910
+ */
1911
+ signInWithIdToken(credentials: SignInWithIdTokenCredentials): Promise<FluxbaseAuthResponse>;
1772
1912
  /**
1773
1913
  * Internal: Set the session and persist it
1774
1914
  */
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
  */
@@ -347,15 +355,17 @@ var FluxbaseAuth = class {
347
355
  /**
348
356
  * Setup 2FA for the current user (Supabase-compatible)
349
357
  * Enrolls a new MFA factor and returns TOTP details
358
+ * @param issuer - Optional custom issuer name for the QR code (e.g., "MyApp"). If not provided, uses server default.
350
359
  * @returns Promise with factor id, type, and TOTP setup details
351
360
  */
352
- async setup2FA() {
361
+ async setup2FA(issuer) {
353
362
  return wrapAsync(async () => {
354
363
  if (!this.session) {
355
364
  throw new Error("Not authenticated");
356
365
  }
357
366
  return await this.fetch.post(
358
- "/api/v1/auth/2fa/setup"
367
+ "/api/v1/auth/2fa/setup",
368
+ issuer ? { issuer } : void 0
359
369
  );
360
370
  });
361
371
  }
@@ -617,6 +627,136 @@ var FluxbaseAuth = class {
617
627
  return { provider, url };
618
628
  });
619
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
+ }
620
760
  /**
621
761
  * Internal: Set the session and persist it
622
762
  */
@@ -700,6 +840,8 @@ var RealtimeChannel = class {
700
840
  this.maxReconnectAttempts = 10;
701
841
  this.reconnectDelay = 1e3;
702
842
  this.heartbeatInterval = null;
843
+ this.pendingAcks = /* @__PURE__ */ new Map();
844
+ this.messageIdCounter = 0;
703
845
  this.url = url;
704
846
  this.channelName = channelName;
705
847
  this.token = token;
@@ -822,16 +964,40 @@ var RealtimeChannel = class {
822
964
  return "error";
823
965
  }
824
966
  try {
967
+ const messageId = this.config.broadcast?.ack ? `msg_${Date.now()}_${++this.messageIdCounter}` : void 0;
825
968
  this.ws.send(
826
969
  JSON.stringify({
827
970
  type: "broadcast",
828
971
  channel: this.channelName,
829
972
  event: message.event,
830
- payload: message.payload
973
+ payload: message.payload,
974
+ ...messageId && { messageId }
831
975
  })
832
976
  );
833
- if (this.config.broadcast?.ack) {
834
- 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
+ });
835
1001
  }
836
1002
  return "ok";
837
1003
  } catch (error) {
@@ -1010,7 +1176,14 @@ var RealtimeChannel = class {
1010
1176
  }
1011
1177
  break;
1012
1178
  case "ack":
1013
- 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
+ }
1014
1187
  break;
1015
1188
  case "error":
1016
1189
  console.error("[Fluxbase Realtime] Error:", message.error);