@basictech/react 0.6.0 → 0.7.0-beta.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/changelog.md +12 -0
- package/dist/index.d.mts +14 -4
- package/dist/index.d.ts +14 -4
- package/dist/index.js +329 -76
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +329 -76
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/readme.md +127 -1
- package/src/AuthContext.tsx +424 -120
- package/src/index.ts +2 -2
package/dist/index.mjs
CHANGED
|
@@ -408,22 +408,33 @@ async function deleteRecord({ projectId, accountId, tableName, id, token }) {
|
|
|
408
408
|
import { validateSchema as validateSchema3, compareSchemas } from "@basictech/schema";
|
|
409
409
|
|
|
410
410
|
// package.json
|
|
411
|
-
var version = "0.6.0
|
|
411
|
+
var version = "0.6.0";
|
|
412
412
|
|
|
413
413
|
// src/AuthContext.tsx
|
|
414
414
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
415
|
+
var LocalStorageAdapter = class {
|
|
416
|
+
async get(key) {
|
|
417
|
+
return localStorage.getItem(key);
|
|
418
|
+
}
|
|
419
|
+
async set(key, value) {
|
|
420
|
+
localStorage.setItem(key, value);
|
|
421
|
+
}
|
|
422
|
+
async remove(key) {
|
|
423
|
+
localStorage.removeItem(key);
|
|
424
|
+
}
|
|
425
|
+
};
|
|
415
426
|
var BasicContext = createContext({
|
|
416
427
|
unicorn: "\u{1F984}",
|
|
417
428
|
isAuthReady: false,
|
|
418
429
|
isSignedIn: false,
|
|
419
430
|
user: null,
|
|
420
|
-
signout: () =>
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
},
|
|
431
|
+
signout: () => Promise.resolve(),
|
|
432
|
+
signin: () => Promise.resolve(),
|
|
433
|
+
signinWithCode: () => new Promise(() => {
|
|
434
|
+
}),
|
|
424
435
|
getToken: () => new Promise(() => {
|
|
425
436
|
}),
|
|
426
|
-
getSignInLink: () => "",
|
|
437
|
+
getSignInLink: () => Promise.resolve(""),
|
|
427
438
|
db: {},
|
|
428
439
|
dbStatus: "LOADING" /* LOADING */
|
|
429
440
|
});
|
|
@@ -540,7 +551,13 @@ run "npm install @basictech/react@${latestVersion}" to update`);
|
|
|
540
551
|
};
|
|
541
552
|
}
|
|
542
553
|
}
|
|
543
|
-
function BasicProvider({
|
|
554
|
+
function BasicProvider({
|
|
555
|
+
children,
|
|
556
|
+
project_id,
|
|
557
|
+
schema,
|
|
558
|
+
debug = false,
|
|
559
|
+
storage
|
|
560
|
+
}) {
|
|
544
561
|
const [isAuthReady, setIsAuthReady] = useState(false);
|
|
545
562
|
const [isSignedIn, setIsSignedIn] = useState(false);
|
|
546
563
|
const [token, setToken] = useState(null);
|
|
@@ -549,7 +566,56 @@ function BasicProvider({ children, project_id, schema, debug = false }) {
|
|
|
549
566
|
const [isReady, setIsReady] = useState(false);
|
|
550
567
|
const [dbStatus, setDbStatus] = useState("OFFLINE" /* OFFLINE */);
|
|
551
568
|
const [error, setError] = useState(null);
|
|
569
|
+
const [isOnline, setIsOnline] = useState(navigator.onLine);
|
|
570
|
+
const [pendingRefresh, setPendingRefresh] = useState(false);
|
|
552
571
|
const syncRef = useRef(null);
|
|
572
|
+
const storageAdapter = storage || new LocalStorageAdapter();
|
|
573
|
+
const STORAGE_KEYS = {
|
|
574
|
+
REFRESH_TOKEN: "basic_refresh_token",
|
|
575
|
+
USER_INFO: "basic_user_info",
|
|
576
|
+
AUTH_STATE: "basic_auth_state",
|
|
577
|
+
DEBUG: "basic_debug"
|
|
578
|
+
};
|
|
579
|
+
const isDevelopment = () => {
|
|
580
|
+
return window.location.hostname === "localhost" || window.location.hostname === "127.0.0.1" || window.location.hostname.includes("localhost") || window.location.hostname.includes("127.0.0.1") || window.location.hostname.includes(".local") || process.env.NODE_ENV === "development" || debug === true;
|
|
581
|
+
};
|
|
582
|
+
const cleanOAuthParamsFromUrl = () => {
|
|
583
|
+
if (window.location.search.includes("code") || window.location.search.includes("state")) {
|
|
584
|
+
const url = new URL(window.location.href);
|
|
585
|
+
url.searchParams.delete("code");
|
|
586
|
+
url.searchParams.delete("state");
|
|
587
|
+
window.history.pushState({}, document.title, url.pathname + url.search);
|
|
588
|
+
log("Cleaned OAuth parameters from URL");
|
|
589
|
+
}
|
|
590
|
+
};
|
|
591
|
+
useEffect(() => {
|
|
592
|
+
const handleOnline = () => {
|
|
593
|
+
log("Network came back online");
|
|
594
|
+
setIsOnline(true);
|
|
595
|
+
if (pendingRefresh) {
|
|
596
|
+
log("Retrying pending token refresh");
|
|
597
|
+
setPendingRefresh(false);
|
|
598
|
+
if (token) {
|
|
599
|
+
const refreshToken = token.refresh_token || localStorage.getItem("basic_refresh_token");
|
|
600
|
+
if (refreshToken) {
|
|
601
|
+
fetchToken(refreshToken).catch((error2) => {
|
|
602
|
+
log("Retry refresh failed:", error2);
|
|
603
|
+
});
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
};
|
|
608
|
+
const handleOffline = () => {
|
|
609
|
+
log("Network went offline");
|
|
610
|
+
setIsOnline(false);
|
|
611
|
+
};
|
|
612
|
+
window.addEventListener("online", handleOnline);
|
|
613
|
+
window.addEventListener("offline", handleOffline);
|
|
614
|
+
return () => {
|
|
615
|
+
window.removeEventListener("online", handleOnline);
|
|
616
|
+
window.removeEventListener("offline", handleOffline);
|
|
617
|
+
};
|
|
618
|
+
}, [pendingRefresh, token]);
|
|
553
619
|
useEffect(() => {
|
|
554
620
|
function initDb(options) {
|
|
555
621
|
if (!syncRef.current) {
|
|
@@ -615,32 +681,68 @@ function BasicProvider({ children, project_id, schema, debug = false }) {
|
|
|
615
681
|
connectToDb();
|
|
616
682
|
}
|
|
617
683
|
}, [isSignedIn, shouldConnect]);
|
|
684
|
+
const connectToDb = async () => {
|
|
685
|
+
const tok = await getToken();
|
|
686
|
+
if (!tok) {
|
|
687
|
+
log("no token found");
|
|
688
|
+
return;
|
|
689
|
+
}
|
|
690
|
+
log("connecting to db...");
|
|
691
|
+
syncRef.current.connect({ access_token: tok }).catch((e) => {
|
|
692
|
+
log("error connecting to db", e);
|
|
693
|
+
});
|
|
694
|
+
};
|
|
618
695
|
useEffect(() => {
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
if (cookie_token !== "") {
|
|
636
|
-
setToken(JSON.parse(cookie_token));
|
|
696
|
+
const initializeAuth = async () => {
|
|
697
|
+
await storageAdapter.set(STORAGE_KEYS.DEBUG, debug ? "true" : "false");
|
|
698
|
+
try {
|
|
699
|
+
if (window.location.search.includes("code")) {
|
|
700
|
+
let code = window.location?.search?.split("code=")[1].split("&")[0];
|
|
701
|
+
const state = await storageAdapter.get(STORAGE_KEYS.AUTH_STATE);
|
|
702
|
+
if (!state || state !== window.location.search.split("state=")[1].split("&")[0]) {
|
|
703
|
+
log("error: auth state does not match");
|
|
704
|
+
setIsAuthReady(true);
|
|
705
|
+
await storageAdapter.remove(STORAGE_KEYS.AUTH_STATE);
|
|
706
|
+
cleanOAuthParamsFromUrl();
|
|
707
|
+
return;
|
|
708
|
+
}
|
|
709
|
+
await storageAdapter.remove(STORAGE_KEYS.AUTH_STATE);
|
|
710
|
+
cleanOAuthParamsFromUrl();
|
|
711
|
+
fetchToken(code);
|
|
637
712
|
} else {
|
|
638
|
-
|
|
713
|
+
const refreshToken = await storageAdapter.get(STORAGE_KEYS.REFRESH_TOKEN);
|
|
714
|
+
if (refreshToken) {
|
|
715
|
+
log("Found refresh token in storage, attempting to refresh access token");
|
|
716
|
+
fetchToken(refreshToken);
|
|
717
|
+
} else {
|
|
718
|
+
let cookie_token = getCookie("basic_token");
|
|
719
|
+
if (cookie_token !== "") {
|
|
720
|
+
const tokenData = JSON.parse(cookie_token);
|
|
721
|
+
setToken(tokenData);
|
|
722
|
+
if (tokenData.refresh_token) {
|
|
723
|
+
await storageAdapter.set(STORAGE_KEYS.REFRESH_TOKEN, tokenData.refresh_token);
|
|
724
|
+
}
|
|
725
|
+
} else {
|
|
726
|
+
const cachedUserInfo = await storageAdapter.get(STORAGE_KEYS.USER_INFO);
|
|
727
|
+
if (cachedUserInfo) {
|
|
728
|
+
try {
|
|
729
|
+
const userData = JSON.parse(cachedUserInfo);
|
|
730
|
+
setUser(userData);
|
|
731
|
+
setIsSignedIn(true);
|
|
732
|
+
log("Loaded cached user info for offline mode");
|
|
733
|
+
} catch (error2) {
|
|
734
|
+
log("Error parsing cached user info:", error2);
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
setIsAuthReady(true);
|
|
738
|
+
}
|
|
739
|
+
}
|
|
639
740
|
}
|
|
741
|
+
} catch (e) {
|
|
742
|
+
log("error getting token", e);
|
|
640
743
|
}
|
|
641
|
-
}
|
|
642
|
-
|
|
643
|
-
}
|
|
744
|
+
};
|
|
745
|
+
initializeAuth();
|
|
644
746
|
}, []);
|
|
645
747
|
useEffect(() => {
|
|
646
748
|
async function fetchUser(acc_token) {
|
|
@@ -655,10 +757,13 @@ function BasicProvider({ children, project_id, schema, debug = false }) {
|
|
|
655
757
|
log("error fetching user", user2.error);
|
|
656
758
|
return;
|
|
657
759
|
} else {
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
window.history.pushState({}, document.title, "/");
|
|
760
|
+
if (token?.refresh_token) {
|
|
761
|
+
await storageAdapter.set(STORAGE_KEYS.REFRESH_TOKEN, token.refresh_token);
|
|
661
762
|
}
|
|
763
|
+
await storageAdapter.set(STORAGE_KEYS.USER_INFO, JSON.stringify(user2));
|
|
764
|
+
log("Cached user info in storage");
|
|
765
|
+
document.cookie = `basic_access_token=${token.access_token}; Secure; SameSite=Strict; HttpOnly=false`;
|
|
766
|
+
document.cookie = `basic_token=${JSON.stringify(token)}; Secure; SameSite=Strict`;
|
|
662
767
|
setUser(user2);
|
|
663
768
|
setIsSignedIn(true);
|
|
664
769
|
setIsAuthReady(true);
|
|
@@ -674,8 +779,18 @@ function BasicProvider({ children, project_id, schema, debug = false }) {
|
|
|
674
779
|
const isExpired = decoded.exp && decoded.exp < Date.now() / 1e3;
|
|
675
780
|
if (isExpired) {
|
|
676
781
|
log("token is expired - refreshing ...");
|
|
677
|
-
|
|
678
|
-
|
|
782
|
+
try {
|
|
783
|
+
const newToken = await fetchToken(token?.refresh_token);
|
|
784
|
+
fetchUser(newToken.access_token);
|
|
785
|
+
} catch (error2) {
|
|
786
|
+
log("Failed to refresh token in checkToken:", error2);
|
|
787
|
+
if (error2.message.includes("offline") || error2.message.includes("Network")) {
|
|
788
|
+
log("Network issue - continuing with expired token until online");
|
|
789
|
+
fetchUser(token.access_token);
|
|
790
|
+
} else {
|
|
791
|
+
setIsAuthReady(true);
|
|
792
|
+
}
|
|
793
|
+
}
|
|
679
794
|
} else {
|
|
680
795
|
fetchUser(token.access_token);
|
|
681
796
|
}
|
|
@@ -684,41 +799,97 @@ function BasicProvider({ children, project_id, schema, debug = false }) {
|
|
|
684
799
|
checkToken();
|
|
685
800
|
}
|
|
686
801
|
}, [token]);
|
|
687
|
-
const
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
802
|
+
const getSignInLink = async (redirectUri) => {
|
|
803
|
+
try {
|
|
804
|
+
log("getting sign in link...");
|
|
805
|
+
if (!project_id) {
|
|
806
|
+
throw new Error("Project ID is required to generate sign-in link");
|
|
807
|
+
}
|
|
808
|
+
const randomState = Math.random().toString(36).substring(6);
|
|
809
|
+
await storageAdapter.set(STORAGE_KEYS.AUTH_STATE, randomState);
|
|
810
|
+
const redirectUrl = redirectUri || window.location.href;
|
|
811
|
+
if (!redirectUrl || !redirectUrl.startsWith("http://") && !redirectUrl.startsWith("https://")) {
|
|
812
|
+
throw new Error("Invalid redirect URI provided");
|
|
813
|
+
}
|
|
814
|
+
let baseUrl2 = "https://api.basic.tech/auth/authorize";
|
|
815
|
+
baseUrl2 += `?client_id=${project_id}`;
|
|
816
|
+
baseUrl2 += `&redirect_uri=${encodeURIComponent(redirectUrl)}`;
|
|
817
|
+
baseUrl2 += `&response_type=code`;
|
|
818
|
+
baseUrl2 += `&scope=profile`;
|
|
819
|
+
baseUrl2 += `&state=${randomState}`;
|
|
820
|
+
log("Generated sign-in link successfully");
|
|
821
|
+
return baseUrl2;
|
|
822
|
+
} catch (error2) {
|
|
823
|
+
log("Error generating sign-in link:", error2);
|
|
824
|
+
throw error2;
|
|
692
825
|
}
|
|
693
|
-
log("connecting to db...");
|
|
694
|
-
syncRef.current.connect({ access_token: tok }).catch((e) => {
|
|
695
|
-
log("error connecting to db", e);
|
|
696
|
-
});
|
|
697
826
|
};
|
|
698
|
-
const
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
827
|
+
const signin = async () => {
|
|
828
|
+
try {
|
|
829
|
+
log("signing in...");
|
|
830
|
+
if (!project_id) {
|
|
831
|
+
log("Error: project_id is required for sign-in");
|
|
832
|
+
throw new Error("Project ID is required for authentication");
|
|
833
|
+
}
|
|
834
|
+
const signInLink = await getSignInLink();
|
|
835
|
+
log("Generated sign-in link:", signInLink);
|
|
836
|
+
if (!signInLink || !signInLink.startsWith("https://")) {
|
|
837
|
+
log("Error: Invalid sign-in link generated");
|
|
838
|
+
throw new Error("Failed to generate valid sign-in URL");
|
|
839
|
+
}
|
|
840
|
+
window.location.href = signInLink;
|
|
841
|
+
} catch (error2) {
|
|
842
|
+
log("Error during sign-in:", error2);
|
|
843
|
+
if (isDevelopment()) {
|
|
844
|
+
setError({
|
|
845
|
+
code: "signin_error",
|
|
846
|
+
title: "Sign-in Failed",
|
|
847
|
+
message: error2.message || "An error occurred during sign-in. Please try again."
|
|
848
|
+
});
|
|
849
|
+
}
|
|
850
|
+
throw error2;
|
|
851
|
+
}
|
|
709
852
|
};
|
|
710
|
-
const
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
853
|
+
const signinWithCode = async (code, state) => {
|
|
854
|
+
try {
|
|
855
|
+
log("signinWithCode called with code:", code);
|
|
856
|
+
if (!code || typeof code !== "string") {
|
|
857
|
+
return { success: false, error: "Invalid authorization code" };
|
|
858
|
+
}
|
|
859
|
+
if (state) {
|
|
860
|
+
const storedState = await storageAdapter.get(STORAGE_KEYS.AUTH_STATE);
|
|
861
|
+
if (storedState && storedState !== state) {
|
|
862
|
+
log("State parameter mismatch:", { provided: state, stored: storedState });
|
|
863
|
+
return { success: false, error: "State parameter mismatch" };
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
await storageAdapter.remove(STORAGE_KEYS.AUTH_STATE);
|
|
867
|
+
cleanOAuthParamsFromUrl();
|
|
868
|
+
const token2 = await fetchToken(code);
|
|
869
|
+
if (token2) {
|
|
870
|
+
log("signinWithCode successful");
|
|
871
|
+
return { success: true };
|
|
872
|
+
} else {
|
|
873
|
+
return { success: false, error: "Failed to exchange code for token" };
|
|
874
|
+
}
|
|
875
|
+
} catch (error2) {
|
|
876
|
+
log("signinWithCode error:", error2);
|
|
877
|
+
return {
|
|
878
|
+
success: false,
|
|
879
|
+
error: error2.message || "Authentication failed"
|
|
880
|
+
};
|
|
881
|
+
}
|
|
714
882
|
};
|
|
715
|
-
const signout = () => {
|
|
883
|
+
const signout = async () => {
|
|
716
884
|
log("signing out!");
|
|
717
885
|
setUser({});
|
|
718
886
|
setIsSignedIn(false);
|
|
719
887
|
setToken(null);
|
|
720
888
|
document.cookie = `basic_token=; Secure; SameSite=Strict`;
|
|
721
|
-
|
|
889
|
+
document.cookie = `basic_access_token=; Secure; SameSite=Strict`;
|
|
890
|
+
await storageAdapter.remove(STORAGE_KEYS.AUTH_STATE);
|
|
891
|
+
await storageAdapter.remove(STORAGE_KEYS.REFRESH_TOKEN);
|
|
892
|
+
await storageAdapter.remove(STORAGE_KEYS.USER_INFO);
|
|
722
893
|
if (syncRef.current) {
|
|
723
894
|
(async () => {
|
|
724
895
|
try {
|
|
@@ -735,6 +906,27 @@ function BasicProvider({ children, project_id, schema, debug = false }) {
|
|
|
735
906
|
const getToken = async () => {
|
|
736
907
|
log("getting token...");
|
|
737
908
|
if (!token) {
|
|
909
|
+
const refreshToken = await storageAdapter.get(STORAGE_KEYS.REFRESH_TOKEN);
|
|
910
|
+
if (refreshToken) {
|
|
911
|
+
log("No token in memory, attempting to refresh from storage");
|
|
912
|
+
try {
|
|
913
|
+
const newToken = await fetchToken(refreshToken);
|
|
914
|
+
if (newToken?.access_token) {
|
|
915
|
+
return newToken.access_token;
|
|
916
|
+
}
|
|
917
|
+
} catch (error2) {
|
|
918
|
+
log("Failed to refresh token from storage:", error2);
|
|
919
|
+
if (error2.message.includes("offline") || error2.message.includes("Network")) {
|
|
920
|
+
log("Network issue - continuing with potentially expired token");
|
|
921
|
+
const lastToken = localStorage.getItem("basic_access_token");
|
|
922
|
+
if (lastToken) {
|
|
923
|
+
return lastToken;
|
|
924
|
+
}
|
|
925
|
+
throw new Error("Network offline - authentication will be retried when online");
|
|
926
|
+
}
|
|
927
|
+
throw new Error("Authentication expired. Please sign in again.");
|
|
928
|
+
}
|
|
929
|
+
}
|
|
738
930
|
log("no token found");
|
|
739
931
|
throw new Error("no token found");
|
|
740
932
|
}
|
|
@@ -742,8 +934,22 @@ function BasicProvider({ children, project_id, schema, debug = false }) {
|
|
|
742
934
|
const isExpired = decoded.exp && decoded.exp < Date.now() / 1e3;
|
|
743
935
|
if (isExpired) {
|
|
744
936
|
log("token is expired - refreshing ...");
|
|
745
|
-
const
|
|
746
|
-
|
|
937
|
+
const refreshToken = token?.refresh_token || await storageAdapter.get(STORAGE_KEYS.REFRESH_TOKEN);
|
|
938
|
+
if (refreshToken) {
|
|
939
|
+
try {
|
|
940
|
+
const newToken = await fetchToken(refreshToken);
|
|
941
|
+
return newToken?.access_token || "";
|
|
942
|
+
} catch (error2) {
|
|
943
|
+
log("Failed to refresh expired token:", error2);
|
|
944
|
+
if (error2.message.includes("offline") || error2.message.includes("Network")) {
|
|
945
|
+
log("Network issue - using expired token until network is restored");
|
|
946
|
+
return token.access_token;
|
|
947
|
+
}
|
|
948
|
+
throw new Error("Authentication expired. Please sign in again.");
|
|
949
|
+
}
|
|
950
|
+
} else {
|
|
951
|
+
throw new Error("no refresh token available");
|
|
952
|
+
}
|
|
747
953
|
}
|
|
748
954
|
return token?.access_token || "";
|
|
749
955
|
};
|
|
@@ -762,20 +968,66 @@ function BasicProvider({ children, project_id, schema, debug = false }) {
|
|
|
762
968
|
return cookieValue;
|
|
763
969
|
}
|
|
764
970
|
const fetchToken = async (code) => {
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
971
|
+
try {
|
|
972
|
+
if (!isOnline) {
|
|
973
|
+
log("Network is offline, marking refresh as pending");
|
|
974
|
+
setPendingRefresh(true);
|
|
975
|
+
throw new Error("Network offline - refresh will be retried when online");
|
|
976
|
+
}
|
|
977
|
+
const token2 = await fetch("https://api.basic.tech/auth/token", {
|
|
978
|
+
method: "POST",
|
|
979
|
+
headers: {
|
|
980
|
+
"Content-Type": "application/json"
|
|
981
|
+
},
|
|
982
|
+
body: JSON.stringify({ code })
|
|
983
|
+
}).then((response) => response.json()).catch((error2) => {
|
|
984
|
+
log("Network error fetching token:", error2);
|
|
985
|
+
if (!isOnline) {
|
|
986
|
+
setPendingRefresh(true);
|
|
987
|
+
throw new Error("Network offline - refresh will be retried when online");
|
|
988
|
+
}
|
|
989
|
+
throw new Error("Network error during token refresh");
|
|
990
|
+
});
|
|
991
|
+
if (token2.error) {
|
|
992
|
+
log("error fetching token", token2.error);
|
|
993
|
+
if (token2.error.includes("network") || token2.error.includes("timeout")) {
|
|
994
|
+
setPendingRefresh(true);
|
|
995
|
+
throw new Error("Network issue - refresh will be retried when online");
|
|
996
|
+
}
|
|
997
|
+
await storageAdapter.remove(STORAGE_KEYS.REFRESH_TOKEN);
|
|
998
|
+
await storageAdapter.remove(STORAGE_KEYS.USER_INFO);
|
|
999
|
+
document.cookie = `basic_token=; Secure; SameSite=Strict`;
|
|
1000
|
+
document.cookie = `basic_access_token=; Secure; SameSite=Strict`;
|
|
1001
|
+
setUser({});
|
|
1002
|
+
setIsSignedIn(false);
|
|
1003
|
+
setToken(null);
|
|
1004
|
+
setIsAuthReady(true);
|
|
1005
|
+
throw new Error(`Token refresh failed: ${token2.error}`);
|
|
1006
|
+
} else {
|
|
1007
|
+
setToken(token2);
|
|
1008
|
+
setPendingRefresh(false);
|
|
1009
|
+
if (token2.refresh_token) {
|
|
1010
|
+
await storageAdapter.set(STORAGE_KEYS.REFRESH_TOKEN, token2.refresh_token);
|
|
1011
|
+
log("Updated refresh token in storage");
|
|
1012
|
+
}
|
|
1013
|
+
document.cookie = `basic_access_token=${token2.access_token}; Secure; SameSite=Strict; HttpOnly=false`;
|
|
1014
|
+
log("Updated access token in cookie");
|
|
1015
|
+
}
|
|
1016
|
+
return token2;
|
|
1017
|
+
} catch (error2) {
|
|
1018
|
+
log("Token refresh error:", error2);
|
|
1019
|
+
if (!error2.message.includes("offline") && !error2.message.includes("Network")) {
|
|
1020
|
+
await storageAdapter.remove(STORAGE_KEYS.REFRESH_TOKEN);
|
|
1021
|
+
await storageAdapter.remove(STORAGE_KEYS.USER_INFO);
|
|
1022
|
+
document.cookie = `basic_token=; Secure; SameSite=Strict`;
|
|
1023
|
+
document.cookie = `basic_access_token=; Secure; SameSite=Strict`;
|
|
1024
|
+
setUser({});
|
|
1025
|
+
setIsSignedIn(false);
|
|
1026
|
+
setToken(null);
|
|
1027
|
+
setIsAuthReady(true);
|
|
1028
|
+
}
|
|
1029
|
+
throw error2;
|
|
777
1030
|
}
|
|
778
|
-
return token2;
|
|
779
1031
|
};
|
|
780
1032
|
const db_ = (tableName) => {
|
|
781
1033
|
const checkSignIn = () => {
|
|
@@ -818,12 +1070,13 @@ function BasicProvider({ children, project_id, schema, debug = false }) {
|
|
|
818
1070
|
user,
|
|
819
1071
|
signout,
|
|
820
1072
|
signin,
|
|
1073
|
+
signinWithCode,
|
|
821
1074
|
getToken,
|
|
822
1075
|
getSignInLink,
|
|
823
1076
|
db: syncRef.current ? syncRef.current : noDb,
|
|
824
1077
|
dbStatus
|
|
825
1078
|
}, children: [
|
|
826
|
-
error && /* @__PURE__ */ jsx(ErrorDisplay, { error }),
|
|
1079
|
+
error && isDevelopment() && /* @__PURE__ */ jsx(ErrorDisplay, { error }),
|
|
827
1080
|
isReady && children
|
|
828
1081
|
] });
|
|
829
1082
|
}
|