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