@reverbia/sdk 1.0.0-next.20251218225706 → 1.0.0-next.20251219092050
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/react/index.cjs +855 -114
- package/dist/react/index.d.mts +697 -31
- package/dist/react/index.d.ts +697 -31
- package/dist/react/index.mjs +856 -111
- package/package.json +1 -1
package/dist/react/index.cjs
CHANGED
|
@@ -38,18 +38,24 @@ var __decorateClass = (decorators, target, key, kind) => {
|
|
|
38
38
|
// src/react/index.ts
|
|
39
39
|
var index_exports = {};
|
|
40
40
|
__export(index_exports, {
|
|
41
|
+
BACKUP_DRIVE_CONVERSATIONS_FOLDER: () => DEFAULT_CONVERSATIONS_FOLDER,
|
|
42
|
+
BACKUP_DRIVE_ROOT_FOLDER: () => DEFAULT_ROOT_FOLDER,
|
|
43
|
+
BackupAuthProvider: () => BackupAuthProvider,
|
|
41
44
|
ChatConversation: () => Conversation,
|
|
42
45
|
ChatMessage: () => Message,
|
|
43
46
|
DEFAULT_BACKUP_FOLDER: () => DEFAULT_BACKUP_FOLDER,
|
|
44
47
|
DEFAULT_DRIVE_CONVERSATIONS_FOLDER: () => DEFAULT_CONVERSATIONS_FOLDER,
|
|
45
48
|
DEFAULT_DRIVE_ROOT_FOLDER: () => DEFAULT_ROOT_FOLDER,
|
|
49
|
+
DEFAULT_DROPBOX_FOLDER: () => DEFAULT_BACKUP_FOLDER,
|
|
46
50
|
DEFAULT_TOOL_SELECTOR_MODEL: () => DEFAULT_TOOL_SELECTOR_MODEL,
|
|
47
51
|
DropboxAuthProvider: () => DropboxAuthProvider,
|
|
52
|
+
GoogleDriveAuthProvider: () => GoogleDriveAuthProvider,
|
|
48
53
|
StoredMemoryModel: () => Memory,
|
|
49
54
|
StoredModelPreferenceModel: () => ModelPreference,
|
|
50
55
|
chatStorageMigrations: () => chatStorageMigrations,
|
|
51
56
|
chatStorageSchema: () => chatStorageSchema,
|
|
52
57
|
clearDropboxToken: () => clearToken,
|
|
58
|
+
clearGoogleDriveToken: () => clearGoogleDriveToken,
|
|
53
59
|
createMemoryContextSystemMessage: () => createMemoryContextSystemMessage,
|
|
54
60
|
decryptData: () => decryptData,
|
|
55
61
|
decryptDataBytes: () => decryptDataBytes,
|
|
@@ -60,8 +66,10 @@ __export(index_exports, {
|
|
|
60
66
|
generateCompositeKey: () => generateCompositeKey,
|
|
61
67
|
generateConversationId: () => generateConversationId,
|
|
62
68
|
generateUniqueKey: () => generateUniqueKey,
|
|
63
|
-
|
|
69
|
+
getGoogleDriveStoredToken: () => getGoogleDriveStoredToken,
|
|
70
|
+
hasDropboxCredentials: () => hasDropboxCredentials,
|
|
64
71
|
hasEncryptionKey: () => hasEncryptionKey,
|
|
72
|
+
hasGoogleDriveCredentials: () => hasGoogleDriveCredentials,
|
|
65
73
|
memoryStorageSchema: () => memoryStorageSchema,
|
|
66
74
|
requestEncryptionKey: () => requestEncryptionKey,
|
|
67
75
|
sdkMigrations: () => sdkMigrations,
|
|
@@ -69,12 +77,14 @@ __export(index_exports, {
|
|
|
69
77
|
sdkSchema: () => sdkSchema,
|
|
70
78
|
selectTool: () => selectTool,
|
|
71
79
|
settingsStorageSchema: () => settingsStorageSchema,
|
|
72
|
-
|
|
80
|
+
useBackup: () => useBackup,
|
|
81
|
+
useBackupAuth: () => useBackupAuth,
|
|
73
82
|
useChat: () => useChat,
|
|
74
83
|
useChatStorage: () => useChatStorage,
|
|
75
84
|
useDropboxAuth: () => useDropboxAuth,
|
|
76
85
|
useDropboxBackup: () => useDropboxBackup,
|
|
77
86
|
useEncryption: () => useEncryption,
|
|
87
|
+
useGoogleDriveAuth: () => useGoogleDriveAuth,
|
|
78
88
|
useGoogleDriveBackup: () => useGoogleDriveBackup,
|
|
79
89
|
useImageGeneration: () => useImageGeneration,
|
|
80
90
|
useMemoryStorage: () => useMemoryStorage,
|
|
@@ -3065,6 +3075,36 @@ var postApiV1Search = (options) => {
|
|
|
3065
3075
|
}
|
|
3066
3076
|
});
|
|
3067
3077
|
};
|
|
3078
|
+
var postAuthOauthByProviderExchange = (options) => {
|
|
3079
|
+
return (options.client ?? client).post({
|
|
3080
|
+
url: "/auth/oauth/{provider}/exchange",
|
|
3081
|
+
...options,
|
|
3082
|
+
headers: {
|
|
3083
|
+
"Content-Type": "application/json",
|
|
3084
|
+
...options.headers
|
|
3085
|
+
}
|
|
3086
|
+
});
|
|
3087
|
+
};
|
|
3088
|
+
var postAuthOauthByProviderRefresh = (options) => {
|
|
3089
|
+
return (options.client ?? client).post({
|
|
3090
|
+
url: "/auth/oauth/{provider}/refresh",
|
|
3091
|
+
...options,
|
|
3092
|
+
headers: {
|
|
3093
|
+
"Content-Type": "application/json",
|
|
3094
|
+
...options.headers
|
|
3095
|
+
}
|
|
3096
|
+
});
|
|
3097
|
+
};
|
|
3098
|
+
var postAuthOauthByProviderRevoke = (options) => {
|
|
3099
|
+
return (options.client ?? client).post({
|
|
3100
|
+
url: "/auth/oauth/{provider}/revoke",
|
|
3101
|
+
...options,
|
|
3102
|
+
headers: {
|
|
3103
|
+
"Content-Type": "application/json",
|
|
3104
|
+
...options.headers
|
|
3105
|
+
}
|
|
3106
|
+
});
|
|
3107
|
+
};
|
|
3068
3108
|
|
|
3069
3109
|
// src/lib/memory/constants.ts
|
|
3070
3110
|
var DEFAULT_LOCAL_EMBEDDING_MODEL = "Snowflake/snowflake-arctic-embed-xs";
|
|
@@ -4608,116 +4648,196 @@ async function performDropboxImport(userAddress, token, deps, onProgress, backup
|
|
|
4608
4648
|
// src/react/useDropboxAuth.ts
|
|
4609
4649
|
var import_react10 = require("react");
|
|
4610
4650
|
|
|
4611
|
-
// src/lib/backup/
|
|
4612
|
-
var
|
|
4613
|
-
|
|
4614
|
-
|
|
4615
|
-
var VERIFIER_STORAGE_KEY = "dropbox_code_verifier";
|
|
4616
|
-
function generateCodeVerifier() {
|
|
4617
|
-
const array = new Uint8Array(32);
|
|
4618
|
-
crypto.getRandomValues(array);
|
|
4619
|
-
return Array.from(array, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
4651
|
+
// src/lib/backup/oauth/storage.ts
|
|
4652
|
+
var STORAGE_KEY_PREFIX = "oauth_token_";
|
|
4653
|
+
function getStorageKey2(provider) {
|
|
4654
|
+
return `${STORAGE_KEY_PREFIX}${provider}`;
|
|
4620
4655
|
}
|
|
4621
|
-
|
|
4622
|
-
const encoder = new TextEncoder();
|
|
4623
|
-
const data = encoder.encode(verifier);
|
|
4624
|
-
const hash = await crypto.subtle.digest("SHA-256", data);
|
|
4625
|
-
const base64 = btoa(String.fromCharCode(...new Uint8Array(hash)));
|
|
4626
|
-
return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
4627
|
-
}
|
|
4628
|
-
function getStoredToken() {
|
|
4656
|
+
function getStoredTokenData(provider) {
|
|
4629
4657
|
if (typeof window === "undefined") return null;
|
|
4630
|
-
|
|
4658
|
+
try {
|
|
4659
|
+
const stored = localStorage.getItem(getStorageKey2(provider));
|
|
4660
|
+
if (!stored) return null;
|
|
4661
|
+
const data = JSON.parse(stored);
|
|
4662
|
+
if (!data.accessToken) return null;
|
|
4663
|
+
return data;
|
|
4664
|
+
} catch {
|
|
4665
|
+
return null;
|
|
4666
|
+
}
|
|
4631
4667
|
}
|
|
4632
|
-
function
|
|
4668
|
+
function storeTokenData(provider, data) {
|
|
4633
4669
|
if (typeof window === "undefined") return;
|
|
4634
|
-
|
|
4670
|
+
localStorage.setItem(getStorageKey2(provider), JSON.stringify(data));
|
|
4635
4671
|
}
|
|
4636
|
-
function
|
|
4672
|
+
function clearTokenData(provider) {
|
|
4637
4673
|
if (typeof window === "undefined") return;
|
|
4638
|
-
|
|
4674
|
+
localStorage.removeItem(getStorageKey2(provider));
|
|
4639
4675
|
}
|
|
4640
|
-
function
|
|
4641
|
-
if (
|
|
4642
|
-
|
|
4676
|
+
function isTokenExpired(data, bufferSeconds = 60) {
|
|
4677
|
+
if (!data) return true;
|
|
4678
|
+
if (!data.expiresAt) return false;
|
|
4679
|
+
const now = Date.now();
|
|
4680
|
+
const bufferMs = bufferSeconds * 1e3;
|
|
4681
|
+
return data.expiresAt - bufferMs <= now;
|
|
4643
4682
|
}
|
|
4644
|
-
function
|
|
4645
|
-
|
|
4646
|
-
|
|
4683
|
+
function getValidAccessToken(provider) {
|
|
4684
|
+
const data = getStoredTokenData(provider);
|
|
4685
|
+
if (!data) return null;
|
|
4686
|
+
if (data.expiresAt && isTokenExpired(data)) {
|
|
4687
|
+
return null;
|
|
4688
|
+
}
|
|
4689
|
+
return data.accessToken;
|
|
4647
4690
|
}
|
|
4648
|
-
function
|
|
4649
|
-
|
|
4650
|
-
|
|
4691
|
+
function getRefreshToken(provider) {
|
|
4692
|
+
const data = getStoredTokenData(provider);
|
|
4693
|
+
return data?.refreshToken ?? null;
|
|
4694
|
+
}
|
|
4695
|
+
function tokenResponseToStoredData(accessToken, expiresIn, refreshToken, scope) {
|
|
4696
|
+
const data = {
|
|
4697
|
+
accessToken,
|
|
4698
|
+
refreshToken,
|
|
4699
|
+
scope
|
|
4700
|
+
};
|
|
4701
|
+
if (expiresIn) {
|
|
4702
|
+
data.expiresAt = Date.now() + expiresIn * 1e3;
|
|
4703
|
+
}
|
|
4704
|
+
return data;
|
|
4651
4705
|
}
|
|
4706
|
+
|
|
4707
|
+
// src/lib/backup/dropbox/auth.ts
|
|
4708
|
+
var PROVIDER = "dropbox";
|
|
4709
|
+
var STATE_STORAGE_KEY = "dropbox_oauth_state";
|
|
4710
|
+
var DROPBOX_AUTH_URL = "https://www.dropbox.com/oauth2/authorize";
|
|
4652
4711
|
function getRedirectUri(callbackPath) {
|
|
4653
4712
|
if (typeof window === "undefined") return "";
|
|
4654
4713
|
return `${window.location.origin}${callbackPath}`;
|
|
4655
4714
|
}
|
|
4656
|
-
|
|
4715
|
+
function generateState() {
|
|
4716
|
+
const array = new Uint8Array(16);
|
|
4717
|
+
crypto.getRandomValues(array);
|
|
4718
|
+
return Array.from(array, (byte) => byte.toString(16).padStart(2, "0")).join(
|
|
4719
|
+
""
|
|
4720
|
+
);
|
|
4721
|
+
}
|
|
4722
|
+
function storeOAuthState(state) {
|
|
4723
|
+
if (typeof window === "undefined") return;
|
|
4724
|
+
sessionStorage.setItem(STATE_STORAGE_KEY, state);
|
|
4725
|
+
}
|
|
4726
|
+
function getAndClearOAuthState() {
|
|
4727
|
+
if (typeof window === "undefined") return null;
|
|
4728
|
+
const state = sessionStorage.getItem(STATE_STORAGE_KEY);
|
|
4729
|
+
sessionStorage.removeItem(STATE_STORAGE_KEY);
|
|
4730
|
+
return state;
|
|
4731
|
+
}
|
|
4732
|
+
function isDropboxCallback() {
|
|
4733
|
+
if (typeof window === "undefined") return false;
|
|
4734
|
+
const url = new URL(window.location.href);
|
|
4735
|
+
const code = url.searchParams.get("code");
|
|
4736
|
+
const state = url.searchParams.get("state");
|
|
4737
|
+
const storedState = sessionStorage.getItem(STATE_STORAGE_KEY);
|
|
4738
|
+
return !!code && !!state && state === storedState;
|
|
4739
|
+
}
|
|
4740
|
+
async function handleDropboxCallback(callbackPath, apiClient) {
|
|
4657
4741
|
if (typeof window === "undefined") return null;
|
|
4658
4742
|
const url = new URL(window.location.href);
|
|
4659
4743
|
const code = url.searchParams.get("code");
|
|
4660
4744
|
const state = url.searchParams.get("state");
|
|
4661
|
-
|
|
4662
|
-
|
|
4663
|
-
|
|
4745
|
+
const storedState = getAndClearOAuthState();
|
|
4746
|
+
if (!code || !state || state !== storedState) {
|
|
4747
|
+
return null;
|
|
4748
|
+
}
|
|
4664
4749
|
try {
|
|
4665
|
-
const response = await
|
|
4666
|
-
|
|
4667
|
-
|
|
4668
|
-
|
|
4669
|
-
},
|
|
4670
|
-
body: new URLSearchParams({
|
|
4750
|
+
const response = await postAuthOauthByProviderExchange({
|
|
4751
|
+
client: apiClient,
|
|
4752
|
+
path: { provider: PROVIDER },
|
|
4753
|
+
body: {
|
|
4671
4754
|
code,
|
|
4672
|
-
|
|
4673
|
-
|
|
4674
|
-
redirect_uri: getRedirectUri(callbackPath),
|
|
4675
|
-
code_verifier: verifier
|
|
4676
|
-
})
|
|
4755
|
+
redirect_uri: getRedirectUri(callbackPath)
|
|
4756
|
+
}
|
|
4677
4757
|
});
|
|
4678
|
-
if (!response.
|
|
4679
|
-
throw new Error("
|
|
4680
|
-
}
|
|
4681
|
-
const data = await response.json();
|
|
4682
|
-
const token = data.access_token;
|
|
4683
|
-
if (typeof token !== "string" || token.trim() === "") {
|
|
4684
|
-
throw new Error("Invalid token response: access_token is missing or empty");
|
|
4758
|
+
if (!response.data?.access_token) {
|
|
4759
|
+
throw new Error("No access token in response");
|
|
4685
4760
|
}
|
|
4686
|
-
|
|
4687
|
-
|
|
4761
|
+
const tokenData = tokenResponseToStoredData(
|
|
4762
|
+
response.data.access_token,
|
|
4763
|
+
response.data.expires_in,
|
|
4764
|
+
response.data.refresh_token,
|
|
4765
|
+
response.data.scope
|
|
4766
|
+
);
|
|
4767
|
+
storeTokenData(PROVIDER, tokenData);
|
|
4688
4768
|
window.history.replaceState({}, "", window.location.pathname);
|
|
4689
|
-
return
|
|
4769
|
+
return response.data.access_token;
|
|
4690
4770
|
} catch {
|
|
4691
|
-
clearVerifier();
|
|
4692
4771
|
return null;
|
|
4693
4772
|
}
|
|
4694
4773
|
}
|
|
4774
|
+
async function refreshDropboxToken(apiClient) {
|
|
4775
|
+
const refreshToken = getRefreshToken(PROVIDER);
|
|
4776
|
+
if (!refreshToken) return null;
|
|
4777
|
+
try {
|
|
4778
|
+
const response = await postAuthOauthByProviderRefresh({
|
|
4779
|
+
client: apiClient,
|
|
4780
|
+
path: { provider: PROVIDER },
|
|
4781
|
+
body: { refresh_token: refreshToken }
|
|
4782
|
+
});
|
|
4783
|
+
if (!response.data?.access_token) {
|
|
4784
|
+
throw new Error("No access token in refresh response");
|
|
4785
|
+
}
|
|
4786
|
+
const currentData = getStoredTokenData(PROVIDER);
|
|
4787
|
+
const tokenData = tokenResponseToStoredData(
|
|
4788
|
+
response.data.access_token,
|
|
4789
|
+
response.data.expires_in,
|
|
4790
|
+
response.data.refresh_token ?? currentData?.refreshToken,
|
|
4791
|
+
response.data.scope ?? currentData?.scope
|
|
4792
|
+
);
|
|
4793
|
+
storeTokenData(PROVIDER, tokenData);
|
|
4794
|
+
return response.data.access_token;
|
|
4795
|
+
} catch {
|
|
4796
|
+
clearTokenData(PROVIDER);
|
|
4797
|
+
return null;
|
|
4798
|
+
}
|
|
4799
|
+
}
|
|
4800
|
+
async function revokeDropboxToken(apiClient) {
|
|
4801
|
+
const tokenData = getStoredTokenData(PROVIDER);
|
|
4802
|
+
if (!tokenData) return;
|
|
4803
|
+
try {
|
|
4804
|
+
const tokenToRevoke = tokenData.refreshToken ?? tokenData.accessToken;
|
|
4805
|
+
await postAuthOauthByProviderRevoke({
|
|
4806
|
+
client: apiClient,
|
|
4807
|
+
path: { provider: PROVIDER },
|
|
4808
|
+
body: { token: tokenToRevoke }
|
|
4809
|
+
});
|
|
4810
|
+
} catch {
|
|
4811
|
+
} finally {
|
|
4812
|
+
clearTokenData(PROVIDER);
|
|
4813
|
+
}
|
|
4814
|
+
}
|
|
4815
|
+
async function getDropboxAccessToken(apiClient) {
|
|
4816
|
+
const validToken = getValidAccessToken(PROVIDER);
|
|
4817
|
+
if (validToken) return validToken;
|
|
4818
|
+
return refreshDropboxToken(apiClient);
|
|
4819
|
+
}
|
|
4695
4820
|
async function startDropboxAuth(appKey, callbackPath) {
|
|
4696
|
-
const
|
|
4697
|
-
|
|
4698
|
-
storeVerifier(verifier);
|
|
4821
|
+
const state = generateState();
|
|
4822
|
+
storeOAuthState(state);
|
|
4699
4823
|
const params = new URLSearchParams({
|
|
4700
4824
|
client_id: appKey,
|
|
4701
4825
|
redirect_uri: getRedirectUri(callbackPath),
|
|
4702
4826
|
response_type: "code",
|
|
4703
|
-
|
|
4704
|
-
code_challenge_method: "S256",
|
|
4705
|
-
state: "dropbox_auth",
|
|
4827
|
+
state,
|
|
4706
4828
|
token_access_type: "offline"
|
|
4829
|
+
// Request refresh token
|
|
4707
4830
|
});
|
|
4708
4831
|
window.location.href = `${DROPBOX_AUTH_URL}?${params.toString()}`;
|
|
4709
4832
|
return new Promise(() => {
|
|
4710
4833
|
});
|
|
4711
4834
|
}
|
|
4712
|
-
|
|
4713
|
-
|
|
4714
|
-
|
|
4715
|
-
|
|
4716
|
-
const
|
|
4717
|
-
|
|
4718
|
-
return storedToken;
|
|
4719
|
-
}
|
|
4720
|
-
return startDropboxAuth(appKey, callbackPath);
|
|
4835
|
+
function clearToken() {
|
|
4836
|
+
clearTokenData(PROVIDER);
|
|
4837
|
+
}
|
|
4838
|
+
function hasDropboxCredentials() {
|
|
4839
|
+
const data = getStoredTokenData(PROVIDER);
|
|
4840
|
+
return !!(data?.accessToken || data?.refreshToken);
|
|
4721
4841
|
}
|
|
4722
4842
|
|
|
4723
4843
|
// src/react/useDropboxAuth.ts
|
|
@@ -4725,26 +4845,41 @@ var DropboxAuthContext = (0, import_react10.createContext)(null);
|
|
|
4725
4845
|
function DropboxAuthProvider({
|
|
4726
4846
|
appKey,
|
|
4727
4847
|
callbackPath = "/auth/dropbox/callback",
|
|
4848
|
+
apiClient,
|
|
4728
4849
|
children
|
|
4729
4850
|
}) {
|
|
4730
4851
|
const [accessToken, setAccessToken] = (0, import_react10.useState)(null);
|
|
4731
4852
|
const isConfigured = !!appKey;
|
|
4732
4853
|
(0, import_react10.useEffect)(() => {
|
|
4733
|
-
const
|
|
4734
|
-
|
|
4735
|
-
|
|
4736
|
-
|
|
4737
|
-
|
|
4854
|
+
const checkStoredToken = async () => {
|
|
4855
|
+
if (hasDropboxCredentials()) {
|
|
4856
|
+
const token = await getDropboxAccessToken(apiClient);
|
|
4857
|
+
if (token) {
|
|
4858
|
+
setAccessToken(token);
|
|
4859
|
+
}
|
|
4860
|
+
}
|
|
4861
|
+
};
|
|
4862
|
+
checkStoredToken();
|
|
4863
|
+
}, [apiClient]);
|
|
4738
4864
|
(0, import_react10.useEffect)(() => {
|
|
4739
|
-
if (!isConfigured
|
|
4865
|
+
if (!isConfigured) return;
|
|
4740
4866
|
const handleCallback = async () => {
|
|
4741
|
-
|
|
4742
|
-
|
|
4743
|
-
|
|
4867
|
+
if (isDropboxCallback()) {
|
|
4868
|
+
const token = await handleDropboxCallback(callbackPath, apiClient);
|
|
4869
|
+
if (token) {
|
|
4870
|
+
setAccessToken(token);
|
|
4871
|
+
}
|
|
4744
4872
|
}
|
|
4745
4873
|
};
|
|
4746
4874
|
handleCallback();
|
|
4747
|
-
}, [
|
|
4875
|
+
}, [callbackPath, isConfigured, apiClient]);
|
|
4876
|
+
const refreshTokenFn = (0, import_react10.useCallback)(async () => {
|
|
4877
|
+
const token = await getDropboxAccessToken(apiClient);
|
|
4878
|
+
if (token) {
|
|
4879
|
+
setAccessToken(token);
|
|
4880
|
+
}
|
|
4881
|
+
return token;
|
|
4882
|
+
}, [apiClient]);
|
|
4748
4883
|
const requestAccess = (0, import_react10.useCallback)(async () => {
|
|
4749
4884
|
if (!isConfigured || !appKey) {
|
|
4750
4885
|
throw new Error("Dropbox is not configured");
|
|
@@ -4752,17 +4887,17 @@ function DropboxAuthProvider({
|
|
|
4752
4887
|
if (accessToken) {
|
|
4753
4888
|
return accessToken;
|
|
4754
4889
|
}
|
|
4755
|
-
const storedToken =
|
|
4890
|
+
const storedToken = await getDropboxAccessToken(apiClient);
|
|
4756
4891
|
if (storedToken) {
|
|
4757
4892
|
setAccessToken(storedToken);
|
|
4758
4893
|
return storedToken;
|
|
4759
4894
|
}
|
|
4760
|
-
return
|
|
4761
|
-
}, [accessToken, appKey, callbackPath, isConfigured]);
|
|
4762
|
-
const logout = (0, import_react10.useCallback)(() => {
|
|
4763
|
-
|
|
4895
|
+
return startDropboxAuth(appKey, callbackPath);
|
|
4896
|
+
}, [accessToken, appKey, callbackPath, isConfigured, apiClient]);
|
|
4897
|
+
const logout = (0, import_react10.useCallback)(async () => {
|
|
4898
|
+
await revokeDropboxToken(apiClient);
|
|
4764
4899
|
setAccessToken(null);
|
|
4765
|
-
}, []);
|
|
4900
|
+
}, [apiClient]);
|
|
4766
4901
|
return (0, import_react10.createElement)(
|
|
4767
4902
|
DropboxAuthContext.Provider,
|
|
4768
4903
|
{
|
|
@@ -4771,7 +4906,8 @@ function DropboxAuthProvider({
|
|
|
4771
4906
|
isAuthenticated: !!accessToken,
|
|
4772
4907
|
isConfigured,
|
|
4773
4908
|
requestAccess,
|
|
4774
|
-
logout
|
|
4909
|
+
logout,
|
|
4910
|
+
refreshToken: refreshTokenFn
|
|
4775
4911
|
}
|
|
4776
4912
|
},
|
|
4777
4913
|
children
|
|
@@ -4798,25 +4934,25 @@ function useDropboxBackup(options) {
|
|
|
4798
4934
|
const {
|
|
4799
4935
|
accessToken: dropboxToken,
|
|
4800
4936
|
isConfigured: isDropboxConfigured,
|
|
4801
|
-
requestAccess:
|
|
4937
|
+
requestAccess: requestDropboxAccess
|
|
4802
4938
|
} = useDropboxAuth();
|
|
4803
4939
|
const deps = (0, import_react11.useMemo)(
|
|
4804
4940
|
() => ({
|
|
4805
|
-
requestDropboxAccess
|
|
4941
|
+
requestDropboxAccess,
|
|
4806
4942
|
requestEncryptionKey: requestEncryptionKey2,
|
|
4807
4943
|
exportConversation,
|
|
4808
4944
|
importConversation
|
|
4809
4945
|
}),
|
|
4810
|
-
[
|
|
4946
|
+
[requestDropboxAccess, requestEncryptionKey2, exportConversation, importConversation]
|
|
4811
4947
|
);
|
|
4812
4948
|
const ensureToken = (0, import_react11.useCallback)(async () => {
|
|
4813
4949
|
if (dropboxToken) return dropboxToken;
|
|
4814
4950
|
try {
|
|
4815
|
-
return await
|
|
4951
|
+
return await requestDropboxAccess();
|
|
4816
4952
|
} catch {
|
|
4817
4953
|
return null;
|
|
4818
4954
|
}
|
|
4819
|
-
}, [dropboxToken,
|
|
4955
|
+
}, [dropboxToken, requestDropboxAccess]);
|
|
4820
4956
|
const backup = (0, import_react11.useCallback)(
|
|
4821
4957
|
async (backupOptions) => {
|
|
4822
4958
|
if (!userAddress) {
|
|
@@ -4876,9 +5012,241 @@ function useDropboxBackup(options) {
|
|
|
4876
5012
|
};
|
|
4877
5013
|
}
|
|
4878
5014
|
|
|
4879
|
-
// src/react/
|
|
5015
|
+
// src/react/useGoogleDriveAuth.ts
|
|
4880
5016
|
var import_react12 = require("react");
|
|
4881
5017
|
|
|
5018
|
+
// src/lib/backup/google/auth.ts
|
|
5019
|
+
var PROVIDER2 = "google-drive";
|
|
5020
|
+
var CODE_STORAGE_KEY = "google_oauth_state";
|
|
5021
|
+
var GOOGLE_AUTH_URL = "https://accounts.google.com/o/oauth2/v2/auth";
|
|
5022
|
+
var DRIVE_SCOPES = [
|
|
5023
|
+
"https://www.googleapis.com/auth/drive.file"
|
|
5024
|
+
// Access to files created by the app
|
|
5025
|
+
].join(" ");
|
|
5026
|
+
function getRedirectUri2(callbackPath) {
|
|
5027
|
+
if (typeof window === "undefined") return "";
|
|
5028
|
+
return `${window.location.origin}${callbackPath}`;
|
|
5029
|
+
}
|
|
5030
|
+
function generateState2() {
|
|
5031
|
+
const array = new Uint8Array(16);
|
|
5032
|
+
crypto.getRandomValues(array);
|
|
5033
|
+
return Array.from(array, (byte) => byte.toString(16).padStart(2, "0")).join(
|
|
5034
|
+
""
|
|
5035
|
+
);
|
|
5036
|
+
}
|
|
5037
|
+
function storeOAuthState2(state) {
|
|
5038
|
+
if (typeof window === "undefined") return;
|
|
5039
|
+
sessionStorage.setItem(CODE_STORAGE_KEY, state);
|
|
5040
|
+
}
|
|
5041
|
+
function getAndClearOAuthState2() {
|
|
5042
|
+
if (typeof window === "undefined") return null;
|
|
5043
|
+
const state = sessionStorage.getItem(CODE_STORAGE_KEY);
|
|
5044
|
+
sessionStorage.removeItem(CODE_STORAGE_KEY);
|
|
5045
|
+
return state;
|
|
5046
|
+
}
|
|
5047
|
+
function isGoogleDriveCallback() {
|
|
5048
|
+
if (typeof window === "undefined") return false;
|
|
5049
|
+
const url = new URL(window.location.href);
|
|
5050
|
+
const code = url.searchParams.get("code");
|
|
5051
|
+
const state = url.searchParams.get("state");
|
|
5052
|
+
const storedState = sessionStorage.getItem(CODE_STORAGE_KEY);
|
|
5053
|
+
return !!code && !!state && state === storedState;
|
|
5054
|
+
}
|
|
5055
|
+
async function handleGoogleDriveCallback(callbackPath, apiClient) {
|
|
5056
|
+
if (typeof window === "undefined") return null;
|
|
5057
|
+
const url = new URL(window.location.href);
|
|
5058
|
+
const code = url.searchParams.get("code");
|
|
5059
|
+
const state = url.searchParams.get("state");
|
|
5060
|
+
const storedState = getAndClearOAuthState2();
|
|
5061
|
+
if (!code || !state || state !== storedState) {
|
|
5062
|
+
return null;
|
|
5063
|
+
}
|
|
5064
|
+
try {
|
|
5065
|
+
const response = await postAuthOauthByProviderExchange({
|
|
5066
|
+
client: apiClient,
|
|
5067
|
+
path: { provider: PROVIDER2 },
|
|
5068
|
+
body: {
|
|
5069
|
+
code,
|
|
5070
|
+
redirect_uri: getRedirectUri2(callbackPath)
|
|
5071
|
+
}
|
|
5072
|
+
});
|
|
5073
|
+
if (!response.data?.access_token) {
|
|
5074
|
+
throw new Error("No access token in response");
|
|
5075
|
+
}
|
|
5076
|
+
const tokenData = tokenResponseToStoredData(
|
|
5077
|
+
response.data.access_token,
|
|
5078
|
+
response.data.expires_in,
|
|
5079
|
+
response.data.refresh_token,
|
|
5080
|
+
response.data.scope
|
|
5081
|
+
);
|
|
5082
|
+
storeTokenData(PROVIDER2, tokenData);
|
|
5083
|
+
window.history.replaceState({}, "", window.location.pathname);
|
|
5084
|
+
return response.data.access_token;
|
|
5085
|
+
} catch {
|
|
5086
|
+
return null;
|
|
5087
|
+
}
|
|
5088
|
+
}
|
|
5089
|
+
async function refreshGoogleDriveToken(apiClient) {
|
|
5090
|
+
const refreshToken = getRefreshToken(PROVIDER2);
|
|
5091
|
+
if (!refreshToken) return null;
|
|
5092
|
+
try {
|
|
5093
|
+
const response = await postAuthOauthByProviderRefresh({
|
|
5094
|
+
client: apiClient,
|
|
5095
|
+
path: { provider: PROVIDER2 },
|
|
5096
|
+
body: { refresh_token: refreshToken }
|
|
5097
|
+
});
|
|
5098
|
+
if (!response.data?.access_token) {
|
|
5099
|
+
throw new Error("No access token in refresh response");
|
|
5100
|
+
}
|
|
5101
|
+
const currentData = getStoredTokenData(PROVIDER2);
|
|
5102
|
+
const tokenData = tokenResponseToStoredData(
|
|
5103
|
+
response.data.access_token,
|
|
5104
|
+
response.data.expires_in,
|
|
5105
|
+
response.data.refresh_token ?? currentData?.refreshToken,
|
|
5106
|
+
response.data.scope ?? currentData?.scope
|
|
5107
|
+
);
|
|
5108
|
+
storeTokenData(PROVIDER2, tokenData);
|
|
5109
|
+
return response.data.access_token;
|
|
5110
|
+
} catch {
|
|
5111
|
+
clearTokenData(PROVIDER2);
|
|
5112
|
+
return null;
|
|
5113
|
+
}
|
|
5114
|
+
}
|
|
5115
|
+
async function revokeGoogleDriveToken(apiClient) {
|
|
5116
|
+
const tokenData = getStoredTokenData(PROVIDER2);
|
|
5117
|
+
if (!tokenData) return;
|
|
5118
|
+
try {
|
|
5119
|
+
const tokenToRevoke = tokenData.refreshToken ?? tokenData.accessToken;
|
|
5120
|
+
await postAuthOauthByProviderRevoke({
|
|
5121
|
+
client: apiClient,
|
|
5122
|
+
path: { provider: PROVIDER2 },
|
|
5123
|
+
body: { token: tokenToRevoke }
|
|
5124
|
+
});
|
|
5125
|
+
} catch {
|
|
5126
|
+
} finally {
|
|
5127
|
+
clearTokenData(PROVIDER2);
|
|
5128
|
+
}
|
|
5129
|
+
}
|
|
5130
|
+
async function getGoogleDriveAccessToken(apiClient) {
|
|
5131
|
+
const validToken = getValidAccessToken(PROVIDER2);
|
|
5132
|
+
if (validToken) return validToken;
|
|
5133
|
+
return refreshGoogleDriveToken(apiClient);
|
|
5134
|
+
}
|
|
5135
|
+
async function startGoogleDriveAuth(clientId, callbackPath) {
|
|
5136
|
+
const state = generateState2();
|
|
5137
|
+
storeOAuthState2(state);
|
|
5138
|
+
const params = new URLSearchParams({
|
|
5139
|
+
client_id: clientId,
|
|
5140
|
+
redirect_uri: getRedirectUri2(callbackPath),
|
|
5141
|
+
response_type: "code",
|
|
5142
|
+
scope: DRIVE_SCOPES,
|
|
5143
|
+
state,
|
|
5144
|
+
access_type: "offline",
|
|
5145
|
+
// Request refresh token
|
|
5146
|
+
prompt: "consent"
|
|
5147
|
+
// Force consent to always get refresh token
|
|
5148
|
+
});
|
|
5149
|
+
window.location.href = `${GOOGLE_AUTH_URL}?${params.toString()}`;
|
|
5150
|
+
return new Promise(() => {
|
|
5151
|
+
});
|
|
5152
|
+
}
|
|
5153
|
+
function getGoogleDriveStoredToken() {
|
|
5154
|
+
return getValidAccessToken(PROVIDER2);
|
|
5155
|
+
}
|
|
5156
|
+
function clearGoogleDriveToken() {
|
|
5157
|
+
clearTokenData(PROVIDER2);
|
|
5158
|
+
}
|
|
5159
|
+
function hasGoogleDriveCredentials() {
|
|
5160
|
+
const data = getStoredTokenData(PROVIDER2);
|
|
5161
|
+
return !!(data?.accessToken || data?.refreshToken);
|
|
5162
|
+
}
|
|
5163
|
+
|
|
5164
|
+
// src/react/useGoogleDriveAuth.ts
|
|
5165
|
+
var GoogleDriveAuthContext = (0, import_react12.createContext)(null);
|
|
5166
|
+
function GoogleDriveAuthProvider({
|
|
5167
|
+
clientId,
|
|
5168
|
+
callbackPath = "/auth/google/callback",
|
|
5169
|
+
apiClient,
|
|
5170
|
+
children
|
|
5171
|
+
}) {
|
|
5172
|
+
const [accessToken, setAccessToken] = (0, import_react12.useState)(null);
|
|
5173
|
+
const isConfigured = !!clientId;
|
|
5174
|
+
(0, import_react12.useEffect)(() => {
|
|
5175
|
+
const checkStoredToken = async () => {
|
|
5176
|
+
if (hasGoogleDriveCredentials()) {
|
|
5177
|
+
const token = await getGoogleDriveAccessToken(apiClient);
|
|
5178
|
+
if (token) {
|
|
5179
|
+
setAccessToken(token);
|
|
5180
|
+
}
|
|
5181
|
+
}
|
|
5182
|
+
};
|
|
5183
|
+
checkStoredToken();
|
|
5184
|
+
}, [apiClient]);
|
|
5185
|
+
(0, import_react12.useEffect)(() => {
|
|
5186
|
+
if (!isConfigured) return;
|
|
5187
|
+
const handleCallback = async () => {
|
|
5188
|
+
if (isGoogleDriveCallback()) {
|
|
5189
|
+
const token = await handleGoogleDriveCallback(callbackPath, apiClient);
|
|
5190
|
+
if (token) {
|
|
5191
|
+
setAccessToken(token);
|
|
5192
|
+
}
|
|
5193
|
+
}
|
|
5194
|
+
};
|
|
5195
|
+
handleCallback();
|
|
5196
|
+
}, [callbackPath, isConfigured, apiClient]);
|
|
5197
|
+
const refreshTokenFn = (0, import_react12.useCallback)(async () => {
|
|
5198
|
+
const token = await getGoogleDriveAccessToken(apiClient);
|
|
5199
|
+
if (token) {
|
|
5200
|
+
setAccessToken(token);
|
|
5201
|
+
}
|
|
5202
|
+
return token;
|
|
5203
|
+
}, [apiClient]);
|
|
5204
|
+
const requestAccess = (0, import_react12.useCallback)(async () => {
|
|
5205
|
+
if (!isConfigured || !clientId) {
|
|
5206
|
+
throw new Error("Google Drive is not configured");
|
|
5207
|
+
}
|
|
5208
|
+
if (accessToken) {
|
|
5209
|
+
return accessToken;
|
|
5210
|
+
}
|
|
5211
|
+
const storedToken = await getGoogleDriveAccessToken(apiClient);
|
|
5212
|
+
if (storedToken) {
|
|
5213
|
+
setAccessToken(storedToken);
|
|
5214
|
+
return storedToken;
|
|
5215
|
+
}
|
|
5216
|
+
return startGoogleDriveAuth(clientId, callbackPath);
|
|
5217
|
+
}, [accessToken, clientId, callbackPath, isConfigured, apiClient]);
|
|
5218
|
+
const logout = (0, import_react12.useCallback)(async () => {
|
|
5219
|
+
await revokeGoogleDriveToken(apiClient);
|
|
5220
|
+
setAccessToken(null);
|
|
5221
|
+
}, [apiClient]);
|
|
5222
|
+
return (0, import_react12.createElement)(
|
|
5223
|
+
GoogleDriveAuthContext.Provider,
|
|
5224
|
+
{
|
|
5225
|
+
value: {
|
|
5226
|
+
accessToken,
|
|
5227
|
+
isAuthenticated: !!accessToken,
|
|
5228
|
+
isConfigured,
|
|
5229
|
+
requestAccess,
|
|
5230
|
+
logout,
|
|
5231
|
+
refreshToken: refreshTokenFn
|
|
5232
|
+
}
|
|
5233
|
+
},
|
|
5234
|
+
children
|
|
5235
|
+
);
|
|
5236
|
+
}
|
|
5237
|
+
function useGoogleDriveAuth() {
|
|
5238
|
+
const context = (0, import_react12.useContext)(GoogleDriveAuthContext);
|
|
5239
|
+
if (!context) {
|
|
5240
|
+
throw new Error(
|
|
5241
|
+
"useGoogleDriveAuth must be used within GoogleDriveAuthProvider"
|
|
5242
|
+
);
|
|
5243
|
+
}
|
|
5244
|
+
return context;
|
|
5245
|
+
}
|
|
5246
|
+
|
|
5247
|
+
// src/react/useGoogleDriveBackup.ts
|
|
5248
|
+
var import_react13 = require("react");
|
|
5249
|
+
|
|
4882
5250
|
// src/lib/backup/google/api.ts
|
|
4883
5251
|
var DRIVE_API_URL = "https://www.googleapis.com/drive/v3";
|
|
4884
5252
|
var DRIVE_UPLOAD_URL = "https://www.googleapis.com/upload/drive/v3";
|
|
@@ -5184,37 +5552,35 @@ function useGoogleDriveBackup(options) {
|
|
|
5184
5552
|
const {
|
|
5185
5553
|
database,
|
|
5186
5554
|
userAddress,
|
|
5187
|
-
accessToken,
|
|
5188
|
-
requestDriveAccess,
|
|
5189
5555
|
requestEncryptionKey: requestEncryptionKey2,
|
|
5190
5556
|
exportConversation,
|
|
5191
5557
|
importConversation,
|
|
5192
5558
|
rootFolder = DEFAULT_ROOT_FOLDER,
|
|
5193
5559
|
conversationsFolder = DEFAULT_CONVERSATIONS_FOLDER
|
|
5194
5560
|
} = options;
|
|
5195
|
-
const
|
|
5561
|
+
const {
|
|
5562
|
+
accessToken: driveToken,
|
|
5563
|
+
isConfigured: isDriveConfigured,
|
|
5564
|
+
requestAccess: requestDriveAccess
|
|
5565
|
+
} = useGoogleDriveAuth();
|
|
5566
|
+
const deps = (0, import_react13.useMemo)(
|
|
5196
5567
|
() => ({
|
|
5197
5568
|
requestDriveAccess,
|
|
5198
5569
|
requestEncryptionKey: requestEncryptionKey2,
|
|
5199
5570
|
exportConversation,
|
|
5200
5571
|
importConversation
|
|
5201
5572
|
}),
|
|
5202
|
-
[
|
|
5203
|
-
requestDriveAccess,
|
|
5204
|
-
requestEncryptionKey2,
|
|
5205
|
-
exportConversation,
|
|
5206
|
-
importConversation
|
|
5207
|
-
]
|
|
5573
|
+
[requestDriveAccess, requestEncryptionKey2, exportConversation, importConversation]
|
|
5208
5574
|
);
|
|
5209
|
-
const ensureToken = (0,
|
|
5210
|
-
if (
|
|
5575
|
+
const ensureToken = (0, import_react13.useCallback)(async () => {
|
|
5576
|
+
if (driveToken) return driveToken;
|
|
5211
5577
|
try {
|
|
5212
5578
|
return await requestDriveAccess();
|
|
5213
5579
|
} catch {
|
|
5214
5580
|
return null;
|
|
5215
5581
|
}
|
|
5216
|
-
}, [
|
|
5217
|
-
const backup = (0,
|
|
5582
|
+
}, [driveToken, requestDriveAccess]);
|
|
5583
|
+
const backup = (0, import_react13.useCallback)(
|
|
5218
5584
|
async (backupOptions) => {
|
|
5219
5585
|
if (!userAddress) {
|
|
5220
5586
|
return { error: "Please sign in to backup to Google Drive" };
|
|
@@ -5241,7 +5607,7 @@ function useGoogleDriveBackup(options) {
|
|
|
5241
5607
|
},
|
|
5242
5608
|
[database, userAddress, ensureToken, deps, rootFolder, conversationsFolder]
|
|
5243
5609
|
);
|
|
5244
|
-
const restore = (0,
|
|
5610
|
+
const restore = (0, import_react13.useCallback)(
|
|
5245
5611
|
async (restoreOptions) => {
|
|
5246
5612
|
if (!userAddress) {
|
|
5247
5613
|
return { error: "Please sign in to restore from Google Drive" };
|
|
@@ -5270,23 +5636,394 @@ function useGoogleDriveBackup(options) {
|
|
|
5270
5636
|
return {
|
|
5271
5637
|
backup,
|
|
5272
5638
|
restore,
|
|
5273
|
-
|
|
5639
|
+
isConfigured: isDriveConfigured,
|
|
5640
|
+
isAuthenticated: !!driveToken
|
|
5641
|
+
};
|
|
5642
|
+
}
|
|
5643
|
+
|
|
5644
|
+
// src/react/useBackupAuth.ts
|
|
5645
|
+
var import_react14 = require("react");
|
|
5646
|
+
var BackupAuthContext = (0, import_react14.createContext)(null);
|
|
5647
|
+
function BackupAuthProvider({
|
|
5648
|
+
dropboxAppKey,
|
|
5649
|
+
dropboxCallbackPath = "/auth/dropbox/callback",
|
|
5650
|
+
googleClientId,
|
|
5651
|
+
googleCallbackPath = "/auth/google/callback",
|
|
5652
|
+
apiClient,
|
|
5653
|
+
children
|
|
5654
|
+
}) {
|
|
5655
|
+
const [dropboxToken, setDropboxToken] = (0, import_react14.useState)(null);
|
|
5656
|
+
const isDropboxConfigured = !!dropboxAppKey;
|
|
5657
|
+
const [googleToken, setGoogleToken] = (0, import_react14.useState)(null);
|
|
5658
|
+
const isGoogleConfigured = !!googleClientId;
|
|
5659
|
+
(0, import_react14.useEffect)(() => {
|
|
5660
|
+
const checkStoredTokens = async () => {
|
|
5661
|
+
if (hasDropboxCredentials()) {
|
|
5662
|
+
const token = await getDropboxAccessToken(apiClient);
|
|
5663
|
+
if (token) {
|
|
5664
|
+
setDropboxToken(token);
|
|
5665
|
+
}
|
|
5666
|
+
}
|
|
5667
|
+
if (hasGoogleDriveCredentials()) {
|
|
5668
|
+
const token = await getGoogleDriveAccessToken(apiClient);
|
|
5669
|
+
if (token) {
|
|
5670
|
+
setGoogleToken(token);
|
|
5671
|
+
}
|
|
5672
|
+
}
|
|
5673
|
+
};
|
|
5674
|
+
checkStoredTokens();
|
|
5675
|
+
}, [apiClient]);
|
|
5676
|
+
(0, import_react14.useEffect)(() => {
|
|
5677
|
+
if (!isDropboxConfigured) return;
|
|
5678
|
+
const handleCallback = async () => {
|
|
5679
|
+
if (isDropboxCallback()) {
|
|
5680
|
+
const token = await handleDropboxCallback(
|
|
5681
|
+
dropboxCallbackPath,
|
|
5682
|
+
apiClient
|
|
5683
|
+
);
|
|
5684
|
+
if (token) {
|
|
5685
|
+
setDropboxToken(token);
|
|
5686
|
+
}
|
|
5687
|
+
}
|
|
5688
|
+
};
|
|
5689
|
+
handleCallback();
|
|
5690
|
+
}, [dropboxCallbackPath, isDropboxConfigured, apiClient]);
|
|
5691
|
+
(0, import_react14.useEffect)(() => {
|
|
5692
|
+
if (!isGoogleConfigured) return;
|
|
5693
|
+
const handleCallback = async () => {
|
|
5694
|
+
if (isGoogleDriveCallback()) {
|
|
5695
|
+
const token = await handleGoogleDriveCallback(
|
|
5696
|
+
googleCallbackPath,
|
|
5697
|
+
apiClient
|
|
5698
|
+
);
|
|
5699
|
+
if (token) {
|
|
5700
|
+
setGoogleToken(token);
|
|
5701
|
+
}
|
|
5702
|
+
}
|
|
5703
|
+
};
|
|
5704
|
+
handleCallback();
|
|
5705
|
+
}, [googleCallbackPath, isGoogleConfigured, apiClient]);
|
|
5706
|
+
const refreshDropboxTokenFn = (0, import_react14.useCallback)(async () => {
|
|
5707
|
+
const token = await getDropboxAccessToken(apiClient);
|
|
5708
|
+
if (token) {
|
|
5709
|
+
setDropboxToken(token);
|
|
5710
|
+
}
|
|
5711
|
+
return token;
|
|
5712
|
+
}, [apiClient]);
|
|
5713
|
+
const requestDropboxAccess = (0, import_react14.useCallback)(async () => {
|
|
5714
|
+
if (!isDropboxConfigured || !dropboxAppKey) {
|
|
5715
|
+
throw new Error("Dropbox is not configured");
|
|
5716
|
+
}
|
|
5717
|
+
if (dropboxToken) {
|
|
5718
|
+
return dropboxToken;
|
|
5719
|
+
}
|
|
5720
|
+
const storedToken = await getDropboxAccessToken(apiClient);
|
|
5721
|
+
if (storedToken) {
|
|
5722
|
+
setDropboxToken(storedToken);
|
|
5723
|
+
return storedToken;
|
|
5724
|
+
}
|
|
5725
|
+
return startDropboxAuth(dropboxAppKey, dropboxCallbackPath);
|
|
5726
|
+
}, [
|
|
5727
|
+
dropboxToken,
|
|
5728
|
+
dropboxAppKey,
|
|
5729
|
+
dropboxCallbackPath,
|
|
5730
|
+
isDropboxConfigured,
|
|
5731
|
+
apiClient
|
|
5732
|
+
]);
|
|
5733
|
+
const logoutDropbox = (0, import_react14.useCallback)(async () => {
|
|
5734
|
+
await revokeDropboxToken(apiClient);
|
|
5735
|
+
setDropboxToken(null);
|
|
5736
|
+
}, [apiClient]);
|
|
5737
|
+
const refreshGoogleTokenFn = (0, import_react14.useCallback)(async () => {
|
|
5738
|
+
const token = await getGoogleDriveAccessToken(apiClient);
|
|
5739
|
+
if (token) {
|
|
5740
|
+
setGoogleToken(token);
|
|
5741
|
+
}
|
|
5742
|
+
return token;
|
|
5743
|
+
}, [apiClient]);
|
|
5744
|
+
const requestGoogleAccess = (0, import_react14.useCallback)(async () => {
|
|
5745
|
+
if (!isGoogleConfigured || !googleClientId) {
|
|
5746
|
+
throw new Error("Google Drive is not configured");
|
|
5747
|
+
}
|
|
5748
|
+
if (googleToken) {
|
|
5749
|
+
return googleToken;
|
|
5750
|
+
}
|
|
5751
|
+
const storedToken = await getGoogleDriveAccessToken(apiClient);
|
|
5752
|
+
if (storedToken) {
|
|
5753
|
+
setGoogleToken(storedToken);
|
|
5754
|
+
return storedToken;
|
|
5755
|
+
}
|
|
5756
|
+
return startGoogleDriveAuth(googleClientId, googleCallbackPath);
|
|
5757
|
+
}, [
|
|
5758
|
+
googleToken,
|
|
5759
|
+
googleClientId,
|
|
5760
|
+
googleCallbackPath,
|
|
5761
|
+
isGoogleConfigured,
|
|
5762
|
+
apiClient
|
|
5763
|
+
]);
|
|
5764
|
+
const logoutGoogle = (0, import_react14.useCallback)(async () => {
|
|
5765
|
+
await revokeGoogleDriveToken(apiClient);
|
|
5766
|
+
setGoogleToken(null);
|
|
5767
|
+
}, [apiClient]);
|
|
5768
|
+
const logoutAll = (0, import_react14.useCallback)(async () => {
|
|
5769
|
+
await Promise.all([
|
|
5770
|
+
isDropboxConfigured ? logoutDropbox() : Promise.resolve(),
|
|
5771
|
+
isGoogleConfigured ? logoutGoogle() : Promise.resolve()
|
|
5772
|
+
]);
|
|
5773
|
+
}, [isDropboxConfigured, isGoogleConfigured, logoutDropbox, logoutGoogle]);
|
|
5774
|
+
const dropboxState = {
|
|
5775
|
+
accessToken: dropboxToken,
|
|
5776
|
+
isAuthenticated: !!dropboxToken,
|
|
5777
|
+
isConfigured: isDropboxConfigured,
|
|
5778
|
+
requestAccess: requestDropboxAccess,
|
|
5779
|
+
logout: logoutDropbox,
|
|
5780
|
+
refreshToken: refreshDropboxTokenFn
|
|
5781
|
+
};
|
|
5782
|
+
const googleDriveState = {
|
|
5783
|
+
accessToken: googleToken,
|
|
5784
|
+
isAuthenticated: !!googleToken,
|
|
5785
|
+
isConfigured: isGoogleConfigured,
|
|
5786
|
+
requestAccess: requestGoogleAccess,
|
|
5787
|
+
logout: logoutGoogle,
|
|
5788
|
+
refreshToken: refreshGoogleTokenFn
|
|
5789
|
+
};
|
|
5790
|
+
return (0, import_react14.createElement)(
|
|
5791
|
+
BackupAuthContext.Provider,
|
|
5792
|
+
{
|
|
5793
|
+
value: {
|
|
5794
|
+
dropbox: dropboxState,
|
|
5795
|
+
googleDrive: googleDriveState,
|
|
5796
|
+
hasAnyProvider: isDropboxConfigured || isGoogleConfigured,
|
|
5797
|
+
hasAnyAuthentication: !!dropboxToken || !!googleToken,
|
|
5798
|
+
logoutAll
|
|
5799
|
+
}
|
|
5800
|
+
},
|
|
5801
|
+
children
|
|
5802
|
+
);
|
|
5803
|
+
}
|
|
5804
|
+
function useBackupAuth() {
|
|
5805
|
+
const context = (0, import_react14.useContext)(BackupAuthContext);
|
|
5806
|
+
if (!context) {
|
|
5807
|
+
throw new Error("useBackupAuth must be used within BackupAuthProvider");
|
|
5808
|
+
}
|
|
5809
|
+
return context;
|
|
5810
|
+
}
|
|
5811
|
+
|
|
5812
|
+
// src/react/useBackup.ts
|
|
5813
|
+
var import_react15 = require("react");
|
|
5814
|
+
function useBackup(options) {
|
|
5815
|
+
const {
|
|
5816
|
+
database,
|
|
5817
|
+
userAddress,
|
|
5818
|
+
requestEncryptionKey: requestEncryptionKey2,
|
|
5819
|
+
exportConversation,
|
|
5820
|
+
importConversation,
|
|
5821
|
+
dropboxFolder = DEFAULT_BACKUP_FOLDER,
|
|
5822
|
+
googleRootFolder = DEFAULT_ROOT_FOLDER,
|
|
5823
|
+
googleConversationsFolder = DEFAULT_CONVERSATIONS_FOLDER
|
|
5824
|
+
} = options;
|
|
5825
|
+
const {
|
|
5826
|
+
dropbox: dropboxAuth,
|
|
5827
|
+
googleDrive: googleDriveAuth,
|
|
5828
|
+
hasAnyProvider,
|
|
5829
|
+
hasAnyAuthentication,
|
|
5830
|
+
logoutAll
|
|
5831
|
+
} = useBackupAuth();
|
|
5832
|
+
const dropboxDeps = (0, import_react15.useMemo)(
|
|
5833
|
+
() => ({
|
|
5834
|
+
requestDropboxAccess: dropboxAuth.requestAccess,
|
|
5835
|
+
requestEncryptionKey: requestEncryptionKey2,
|
|
5836
|
+
exportConversation,
|
|
5837
|
+
importConversation
|
|
5838
|
+
}),
|
|
5839
|
+
[dropboxAuth.requestAccess, requestEncryptionKey2, exportConversation, importConversation]
|
|
5840
|
+
);
|
|
5841
|
+
const googleDriveDeps = (0, import_react15.useMemo)(
|
|
5842
|
+
() => ({
|
|
5843
|
+
requestDriveAccess: googleDriveAuth.requestAccess,
|
|
5844
|
+
requestEncryptionKey: requestEncryptionKey2,
|
|
5845
|
+
exportConversation,
|
|
5846
|
+
importConversation
|
|
5847
|
+
}),
|
|
5848
|
+
[googleDriveAuth.requestAccess, requestEncryptionKey2, exportConversation, importConversation]
|
|
5849
|
+
);
|
|
5850
|
+
const dropboxBackup = (0, import_react15.useCallback)(
|
|
5851
|
+
async (backupOptions) => {
|
|
5852
|
+
if (!userAddress) {
|
|
5853
|
+
return { error: "Please sign in to backup to Dropbox" };
|
|
5854
|
+
}
|
|
5855
|
+
let token = dropboxAuth.accessToken;
|
|
5856
|
+
if (!token) {
|
|
5857
|
+
try {
|
|
5858
|
+
token = await dropboxAuth.requestAccess();
|
|
5859
|
+
} catch {
|
|
5860
|
+
return { error: "Dropbox access denied" };
|
|
5861
|
+
}
|
|
5862
|
+
}
|
|
5863
|
+
try {
|
|
5864
|
+
return await performDropboxExport(
|
|
5865
|
+
database,
|
|
5866
|
+
userAddress,
|
|
5867
|
+
token,
|
|
5868
|
+
dropboxDeps,
|
|
5869
|
+
backupOptions?.onProgress,
|
|
5870
|
+
dropboxFolder
|
|
5871
|
+
);
|
|
5872
|
+
} catch (err) {
|
|
5873
|
+
return {
|
|
5874
|
+
error: err instanceof Error ? err.message : "Failed to backup to Dropbox"
|
|
5875
|
+
};
|
|
5876
|
+
}
|
|
5877
|
+
},
|
|
5878
|
+
[database, userAddress, dropboxAuth, dropboxDeps, dropboxFolder]
|
|
5879
|
+
);
|
|
5880
|
+
const dropboxRestore = (0, import_react15.useCallback)(
|
|
5881
|
+
async (restoreOptions) => {
|
|
5882
|
+
if (!userAddress) {
|
|
5883
|
+
return { error: "Please sign in to restore from Dropbox" };
|
|
5884
|
+
}
|
|
5885
|
+
let token = dropboxAuth.accessToken;
|
|
5886
|
+
if (!token) {
|
|
5887
|
+
try {
|
|
5888
|
+
token = await dropboxAuth.requestAccess();
|
|
5889
|
+
} catch {
|
|
5890
|
+
return { error: "Dropbox access denied" };
|
|
5891
|
+
}
|
|
5892
|
+
}
|
|
5893
|
+
try {
|
|
5894
|
+
return await performDropboxImport(
|
|
5895
|
+
userAddress,
|
|
5896
|
+
token,
|
|
5897
|
+
dropboxDeps,
|
|
5898
|
+
restoreOptions?.onProgress,
|
|
5899
|
+
dropboxFolder
|
|
5900
|
+
);
|
|
5901
|
+
} catch (err) {
|
|
5902
|
+
return {
|
|
5903
|
+
error: err instanceof Error ? err.message : "Failed to restore from Dropbox"
|
|
5904
|
+
};
|
|
5905
|
+
}
|
|
5906
|
+
},
|
|
5907
|
+
[userAddress, dropboxAuth, dropboxDeps, dropboxFolder]
|
|
5908
|
+
);
|
|
5909
|
+
const googleDriveBackup = (0, import_react15.useCallback)(
|
|
5910
|
+
async (backupOptions) => {
|
|
5911
|
+
if (!userAddress) {
|
|
5912
|
+
return { error: "Please sign in to backup to Google Drive" };
|
|
5913
|
+
}
|
|
5914
|
+
let token = googleDriveAuth.accessToken;
|
|
5915
|
+
if (!token) {
|
|
5916
|
+
try {
|
|
5917
|
+
token = await googleDriveAuth.requestAccess();
|
|
5918
|
+
} catch {
|
|
5919
|
+
return { error: "Google Drive access denied" };
|
|
5920
|
+
}
|
|
5921
|
+
}
|
|
5922
|
+
try {
|
|
5923
|
+
return await performGoogleDriveExport(
|
|
5924
|
+
database,
|
|
5925
|
+
userAddress,
|
|
5926
|
+
token,
|
|
5927
|
+
googleDriveDeps,
|
|
5928
|
+
backupOptions?.onProgress,
|
|
5929
|
+
googleRootFolder,
|
|
5930
|
+
googleConversationsFolder
|
|
5931
|
+
);
|
|
5932
|
+
} catch (err) {
|
|
5933
|
+
return {
|
|
5934
|
+
error: err instanceof Error ? err.message : "Failed to backup to Google Drive"
|
|
5935
|
+
};
|
|
5936
|
+
}
|
|
5937
|
+
},
|
|
5938
|
+
[
|
|
5939
|
+
database,
|
|
5940
|
+
userAddress,
|
|
5941
|
+
googleDriveAuth,
|
|
5942
|
+
googleDriveDeps,
|
|
5943
|
+
googleRootFolder,
|
|
5944
|
+
googleConversationsFolder
|
|
5945
|
+
]
|
|
5946
|
+
);
|
|
5947
|
+
const googleDriveRestore = (0, import_react15.useCallback)(
|
|
5948
|
+
async (restoreOptions) => {
|
|
5949
|
+
if (!userAddress) {
|
|
5950
|
+
return { error: "Please sign in to restore from Google Drive" };
|
|
5951
|
+
}
|
|
5952
|
+
let token = googleDriveAuth.accessToken;
|
|
5953
|
+
if (!token) {
|
|
5954
|
+
try {
|
|
5955
|
+
token = await googleDriveAuth.requestAccess();
|
|
5956
|
+
} catch {
|
|
5957
|
+
return { error: "Google Drive access denied" };
|
|
5958
|
+
}
|
|
5959
|
+
}
|
|
5960
|
+
try {
|
|
5961
|
+
return await performGoogleDriveImport(
|
|
5962
|
+
userAddress,
|
|
5963
|
+
token,
|
|
5964
|
+
googleDriveDeps,
|
|
5965
|
+
restoreOptions?.onProgress,
|
|
5966
|
+
googleRootFolder,
|
|
5967
|
+
googleConversationsFolder
|
|
5968
|
+
);
|
|
5969
|
+
} catch (err) {
|
|
5970
|
+
return {
|
|
5971
|
+
error: err instanceof Error ? err.message : "Failed to restore from Google Drive"
|
|
5972
|
+
};
|
|
5973
|
+
}
|
|
5974
|
+
},
|
|
5975
|
+
[
|
|
5976
|
+
userAddress,
|
|
5977
|
+
googleDriveAuth,
|
|
5978
|
+
googleDriveDeps,
|
|
5979
|
+
googleRootFolder,
|
|
5980
|
+
googleConversationsFolder
|
|
5981
|
+
]
|
|
5982
|
+
);
|
|
5983
|
+
const dropboxState = {
|
|
5984
|
+
isConfigured: dropboxAuth.isConfigured,
|
|
5985
|
+
isAuthenticated: dropboxAuth.isAuthenticated,
|
|
5986
|
+
backup: dropboxBackup,
|
|
5987
|
+
restore: dropboxRestore,
|
|
5988
|
+
connect: dropboxAuth.requestAccess,
|
|
5989
|
+
disconnect: dropboxAuth.logout
|
|
5990
|
+
};
|
|
5991
|
+
const googleDriveState = {
|
|
5992
|
+
isConfigured: googleDriveAuth.isConfigured,
|
|
5993
|
+
isAuthenticated: googleDriveAuth.isAuthenticated,
|
|
5994
|
+
backup: googleDriveBackup,
|
|
5995
|
+
restore: googleDriveRestore,
|
|
5996
|
+
connect: googleDriveAuth.requestAccess,
|
|
5997
|
+
disconnect: googleDriveAuth.logout
|
|
5998
|
+
};
|
|
5999
|
+
return {
|
|
6000
|
+
dropbox: dropboxState,
|
|
6001
|
+
googleDrive: googleDriveState,
|
|
6002
|
+
hasAnyProvider,
|
|
6003
|
+
hasAnyAuthentication,
|
|
6004
|
+
disconnectAll: logoutAll
|
|
5274
6005
|
};
|
|
5275
6006
|
}
|
|
5276
6007
|
// Annotate the CommonJS export names for ESM import in node:
|
|
5277
6008
|
0 && (module.exports = {
|
|
6009
|
+
BACKUP_DRIVE_CONVERSATIONS_FOLDER,
|
|
6010
|
+
BACKUP_DRIVE_ROOT_FOLDER,
|
|
6011
|
+
BackupAuthProvider,
|
|
5278
6012
|
ChatConversation,
|
|
5279
6013
|
ChatMessage,
|
|
5280
6014
|
DEFAULT_BACKUP_FOLDER,
|
|
5281
6015
|
DEFAULT_DRIVE_CONVERSATIONS_FOLDER,
|
|
5282
6016
|
DEFAULT_DRIVE_ROOT_FOLDER,
|
|
6017
|
+
DEFAULT_DROPBOX_FOLDER,
|
|
5283
6018
|
DEFAULT_TOOL_SELECTOR_MODEL,
|
|
5284
6019
|
DropboxAuthProvider,
|
|
6020
|
+
GoogleDriveAuthProvider,
|
|
5285
6021
|
StoredMemoryModel,
|
|
5286
6022
|
StoredModelPreferenceModel,
|
|
5287
6023
|
chatStorageMigrations,
|
|
5288
6024
|
chatStorageSchema,
|
|
5289
6025
|
clearDropboxToken,
|
|
6026
|
+
clearGoogleDriveToken,
|
|
5290
6027
|
createMemoryContextSystemMessage,
|
|
5291
6028
|
decryptData,
|
|
5292
6029
|
decryptDataBytes,
|
|
@@ -5297,8 +6034,10 @@ function useGoogleDriveBackup(options) {
|
|
|
5297
6034
|
generateCompositeKey,
|
|
5298
6035
|
generateConversationId,
|
|
5299
6036
|
generateUniqueKey,
|
|
5300
|
-
|
|
6037
|
+
getGoogleDriveStoredToken,
|
|
6038
|
+
hasDropboxCredentials,
|
|
5301
6039
|
hasEncryptionKey,
|
|
6040
|
+
hasGoogleDriveCredentials,
|
|
5302
6041
|
memoryStorageSchema,
|
|
5303
6042
|
requestEncryptionKey,
|
|
5304
6043
|
sdkMigrations,
|
|
@@ -5306,12 +6045,14 @@ function useGoogleDriveBackup(options) {
|
|
|
5306
6045
|
sdkSchema,
|
|
5307
6046
|
selectTool,
|
|
5308
6047
|
settingsStorageSchema,
|
|
5309
|
-
|
|
6048
|
+
useBackup,
|
|
6049
|
+
useBackupAuth,
|
|
5310
6050
|
useChat,
|
|
5311
6051
|
useChatStorage,
|
|
5312
6052
|
useDropboxAuth,
|
|
5313
6053
|
useDropboxBackup,
|
|
5314
6054
|
useEncryption,
|
|
6055
|
+
useGoogleDriveAuth,
|
|
5315
6056
|
useGoogleDriveBackup,
|
|
5316
6057
|
useImageGeneration,
|
|
5317
6058
|
useMemoryStorage,
|