veryfront 0.0.56 → 0.0.58
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/ai/index.js +104 -13
- package/dist/ai/index.js.map +3 -3
- package/dist/ai/workflow.js +1 -1
- package/dist/ai/workflow.js.map +1 -1
- package/dist/cli.js +183 -26
- package/dist/components.js +1 -1
- package/dist/components.js.map +1 -1
- package/dist/config.js +1 -1
- package/dist/config.js.map +1 -1
- package/dist/data.js +1 -1
- package/dist/data.js.map +1 -1
- package/dist/index.js +2 -4
- package/dist/index.js.map +2 -2
- package/dist/integrations/_base/files/app/api/integrations/status/route.ts +1 -1
- package/dist/integrations/_base/files/app/api/integrations/token-storage/route.ts +7 -3
- package/dist/integrations/_base/files/app/setup/page.tsx +81 -23
- package/dist/integrations/_base/files/lib/token-store-examples.ts +1 -1
- package/dist/integrations/_base/files/lib/token-store.ts +35 -9
- package/dist/integrations/airtable/files/app/api/auth/airtable/callback/route.ts +23 -3
- package/dist/integrations/asana/files/app/api/auth/asana/callback/route.ts +23 -3
- package/dist/integrations/bitbucket/files/app/api/auth/bitbucket/callback/route.ts +23 -3
- package/dist/integrations/box/files/app/api/auth/box/callback/route.ts +23 -3
- package/dist/integrations/calendar/files/app/api/auth/calendar/callback/route.ts +23 -3
- package/dist/integrations/clickup/files/app/api/auth/clickup/callback/route.ts +23 -3
- package/dist/integrations/confluence/files/app/api/auth/confluence/callback/route.ts +23 -3
- package/dist/integrations/discord/files/app/api/auth/discord/callback/route.ts +23 -3
- package/dist/integrations/docs-google/files/app/api/auth/docs-google/callback/route.ts +24 -4
- package/dist/integrations/drive/files/app/api/auth/drive/callback/route.ts +24 -4
- package/dist/integrations/dropbox/files/app/api/auth/dropbox/callback/route.ts +23 -3
- package/dist/integrations/figma/files/app/api/auth/figma/callback/route.ts +23 -3
- package/dist/integrations/freshdesk/files/app/api/auth/freshdesk/callback/route.ts +24 -4
- package/dist/integrations/github/files/app/api/auth/github/callback/route.ts +23 -3
- package/dist/integrations/gitlab/files/app/api/auth/gitlab/callback/route.ts +23 -3
- package/dist/integrations/gmail/files/app/api/auth/gmail/callback/route.ts +1 -1
- package/dist/integrations/gmail/files/lib/gmail-client.ts +21 -3
- package/dist/integrations/hubspot/files/app/api/auth/hubspot/callback/route.ts +23 -3
- package/dist/integrations/intercom/files/app/api/auth/intercom/callback/route.ts +24 -4
- package/dist/integrations/jira/files/app/api/auth/jira/callback/route.ts +23 -3
- package/dist/integrations/linear/files/app/api/auth/linear/callback/route.ts +23 -3
- package/dist/integrations/mailchimp/files/app/api/auth/mailchimp/callback/route.ts +23 -3
- package/dist/integrations/monday/files/app/api/auth/monday/callback/route.ts +24 -4
- package/dist/integrations/neon/files/app/api/auth/neon/route.ts +1 -1
- package/dist/integrations/notion/files/app/api/auth/notion/callback/route.ts +23 -3
- package/dist/integrations/onedrive/files/app/api/auth/onedrive/callback/route.ts +23 -3
- package/dist/integrations/outlook/files/app/api/auth/outlook/callback/route.ts +23 -3
- package/dist/integrations/pipedrive/files/app/api/auth/pipedrive/callback/route.ts +24 -4
- package/dist/integrations/quickbooks/files/app/api/auth/quickbooks/callback/route.ts +24 -4
- package/dist/integrations/salesforce/files/app/api/auth/salesforce/callback/route.ts +23 -3
- package/dist/integrations/sharepoint/files/app/api/auth/sharepoint/callback/route.ts +23 -3
- package/dist/integrations/sheets/files/app/api/auth/sheets/callback/route.ts +23 -3
- package/dist/integrations/shopify/files/app/api/auth/shopify/callback/route.ts +24 -4
- package/dist/integrations/slack/files/app/api/auth/slack/callback/route.ts +23 -3
- package/dist/integrations/teams/files/app/api/auth/teams/callback/route.ts +23 -3
- package/dist/integrations/trello/files/app/api/auth/trello/callback/route.ts +24 -4
- package/dist/integrations/twitter/files/app/api/auth/twitter/callback/route.ts +23 -3
- package/dist/integrations/webex/files/app/api/auth/webex/callback/route.ts +23 -3
- package/dist/integrations/xero/files/app/api/auth/xero/callback/route.ts +24 -4
- package/dist/integrations/zoom/files/app/api/auth/zoom/callback/route.ts +24 -4
- package/package.json +1 -1
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Used by the setup guide to show which services are connected.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import { tokenStore } from "../../../../lib/token-store";
|
|
8
|
+
import { tokenStore } from "../../../../lib/token-store.ts";
|
|
9
9
|
|
|
10
10
|
// Define available integrations - will be populated based on project config
|
|
11
11
|
const INTEGRATIONS = [
|
|
@@ -18,9 +18,13 @@ export async function GET() {
|
|
|
18
18
|
mode = "redis";
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
// Check if encryption is
|
|
21
|
+
// Check if encryption key is explicitly set
|
|
22
22
|
const encryptionKey = env.TOKEN_ENCRYPTION_KEY;
|
|
23
|
-
const
|
|
23
|
+
const hasExplicitKey = typeof encryptionKey === "string" && encryptionKey.length === 64;
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
// Encryption is always enabled (auto-generated in dev if not set)
|
|
26
|
+
const encrypted = true;
|
|
27
|
+
const autoGenerated = !hasExplicitKey;
|
|
28
|
+
|
|
29
|
+
return Response.json({ mode, encrypted, autoGenerated });
|
|
26
30
|
}
|
|
@@ -30,6 +30,7 @@ interface SetupGuide {
|
|
|
30
30
|
interface TokenStorageStatus {
|
|
31
31
|
mode: "memory" | "database" | "kv" | "redis" | "custom";
|
|
32
32
|
encrypted: boolean;
|
|
33
|
+
autoGenerated?: boolean;
|
|
33
34
|
}
|
|
34
35
|
|
|
35
36
|
// Categories for organizing integrations
|
|
@@ -871,34 +872,91 @@ export default function SetupPage() {
|
|
|
871
872
|
: "text-green-700 dark:text-green-300"
|
|
872
873
|
}`}>
|
|
873
874
|
{tokenStorage.mode === "memory" ? (
|
|
874
|
-
<>Tokens are stored in memory and will be lost on restart
|
|
875
|
+
<>Tokens are stored in memory and will be lost on restart.</>
|
|
875
876
|
) : (
|
|
876
877
|
<>Tokens are persisted to {tokenStorage.mode} storage.</>
|
|
877
878
|
)}
|
|
878
879
|
</p>
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
<>
|
|
887
|
-
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
888
|
-
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" />
|
|
889
|
-
</svg>
|
|
890
|
-
Encryption enabled
|
|
891
|
-
</>
|
|
892
|
-
) : (
|
|
893
|
-
<>
|
|
894
|
-
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
895
|
-
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 11V7a4 4 0 118 0m-4 8v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2z" />
|
|
896
|
-
</svg>
|
|
897
|
-
Set <code className="px-1 py-0.5 bg-amber-100 dark:bg-amber-900 rounded text-xs">TOKEN_ENCRYPTION_KEY</code> for encryption
|
|
898
|
-
</>
|
|
899
|
-
)}
|
|
900
|
-
</span>
|
|
880
|
+
|
|
881
|
+
{/* Encryption Status */}
|
|
882
|
+
<div className="mt-2 flex items-center gap-1.5 text-sm text-green-600 dark:text-green-400">
|
|
883
|
+
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
884
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" />
|
|
885
|
+
</svg>
|
|
886
|
+
<span>Encryption enabled {tokenStorage.autoGenerated && "(auto-generated key)"}</span>
|
|
901
887
|
</div>
|
|
888
|
+
|
|
889
|
+
{/* Production Storage Options */}
|
|
890
|
+
{tokenStorage.mode === "memory" && (
|
|
891
|
+
<div className="mt-4 pt-4 border-t border-amber-200 dark:border-amber-800">
|
|
892
|
+
<p className="text-sm font-medium text-amber-800 dark:text-amber-200 mb-3">
|
|
893
|
+
For production, add one of these to your <code className="px-1 py-0.5 bg-amber-100 dark:bg-amber-900 rounded text-xs">.env</code>:
|
|
894
|
+
</p>
|
|
895
|
+
<div className="grid gap-2">
|
|
896
|
+
<a
|
|
897
|
+
href="https://upstash.com/docs/redis/overall/getstarted"
|
|
898
|
+
target="_blank"
|
|
899
|
+
rel="noopener noreferrer"
|
|
900
|
+
className="flex items-center justify-between p-3 bg-white dark:bg-neutral-800 rounded-lg border border-green-200 dark:border-green-700 hover:border-green-400 dark:hover:border-green-500 transition-colors group"
|
|
901
|
+
>
|
|
902
|
+
<div>
|
|
903
|
+
<span className="font-medium text-neutral-900 dark:text-white">Upstash</span>
|
|
904
|
+
<span className="text-green-600 dark:text-green-400 text-xs ml-2 font-medium">Recommended</span>
|
|
905
|
+
<span className="text-neutral-500 dark:text-neutral-400 text-sm ml-2">Serverless Redis, scales horizontally</span>
|
|
906
|
+
</div>
|
|
907
|
+
<code className="text-xs bg-neutral-100 dark:bg-neutral-700 px-2 py-1 rounded text-neutral-600 dark:text-neutral-300">REDIS_URL</code>
|
|
908
|
+
</a>
|
|
909
|
+
<a
|
|
910
|
+
href="https://docs.turso.tech/quickstart"
|
|
911
|
+
target="_blank"
|
|
912
|
+
rel="noopener noreferrer"
|
|
913
|
+
className="flex items-center justify-between p-3 bg-white dark:bg-neutral-800 rounded-lg border border-amber-200 dark:border-amber-700 hover:border-amber-400 dark:hover:border-amber-500 transition-colors group"
|
|
914
|
+
>
|
|
915
|
+
<div>
|
|
916
|
+
<span className="font-medium text-neutral-900 dark:text-white">Turso / libSQL</span>
|
|
917
|
+
<span className="text-neutral-500 dark:text-neutral-400 text-sm ml-2">Edge SQLite, fast reads globally</span>
|
|
918
|
+
</div>
|
|
919
|
+
<code className="text-xs bg-neutral-100 dark:bg-neutral-700 px-2 py-1 rounded text-neutral-600 dark:text-neutral-300">DATABASE_URL</code>
|
|
920
|
+
</a>
|
|
921
|
+
<a
|
|
922
|
+
href="https://vercel.com/docs/storage/vercel-kv/quickstart"
|
|
923
|
+
target="_blank"
|
|
924
|
+
rel="noopener noreferrer"
|
|
925
|
+
className="flex items-center justify-between p-3 bg-white dark:bg-neutral-800 rounded-lg border border-amber-200 dark:border-amber-700 hover:border-amber-400 dark:hover:border-amber-500 transition-colors group"
|
|
926
|
+
>
|
|
927
|
+
<div>
|
|
928
|
+
<span className="font-medium text-neutral-900 dark:text-white">Vercel KV</span>
|
|
929
|
+
<span className="text-neutral-500 dark:text-neutral-400 text-sm ml-2">Built-in if using Vercel</span>
|
|
930
|
+
</div>
|
|
931
|
+
<code className="text-xs bg-neutral-100 dark:bg-neutral-700 px-2 py-1 rounded text-neutral-600 dark:text-neutral-300">KV_REST_API_URL</code>
|
|
932
|
+
</a>
|
|
933
|
+
<a
|
|
934
|
+
href="https://neon.tech/docs/get-started-with-neon/connect-neon"
|
|
935
|
+
target="_blank"
|
|
936
|
+
rel="noopener noreferrer"
|
|
937
|
+
className="flex items-center justify-between p-3 bg-white dark:bg-neutral-800 rounded-lg border border-amber-200 dark:border-amber-700 hover:border-amber-400 dark:hover:border-amber-500 transition-colors group"
|
|
938
|
+
>
|
|
939
|
+
<div>
|
|
940
|
+
<span className="font-medium text-neutral-900 dark:text-white">Neon</span>
|
|
941
|
+
<span className="text-neutral-500 dark:text-neutral-400 text-sm ml-2">Serverless Postgres</span>
|
|
942
|
+
</div>
|
|
943
|
+
<code className="text-xs bg-neutral-100 dark:bg-neutral-700 px-2 py-1 rounded text-neutral-600 dark:text-neutral-300">DATABASE_URL</code>
|
|
944
|
+
</a>
|
|
945
|
+
<a
|
|
946
|
+
href="https://www.sqlite.org/index.html"
|
|
947
|
+
target="_blank"
|
|
948
|
+
rel="noopener noreferrer"
|
|
949
|
+
className="flex items-center justify-between p-3 bg-white dark:bg-neutral-800 rounded-lg border border-amber-200 dark:border-amber-700 hover:border-amber-400 dark:hover:border-amber-500 transition-colors group"
|
|
950
|
+
>
|
|
951
|
+
<div>
|
|
952
|
+
<span className="font-medium text-neutral-900 dark:text-white">SQLite</span>
|
|
953
|
+
<span className="text-neutral-500 dark:text-neutral-400 text-sm ml-2">Local file, single instance only</span>
|
|
954
|
+
</div>
|
|
955
|
+
<code className="text-xs bg-neutral-100 dark:bg-neutral-700 px-2 py-1 rounded text-neutral-600 dark:text-neutral-300">DATABASE_URL=file:./data.db</code>
|
|
956
|
+
</a>
|
|
957
|
+
</div>
|
|
958
|
+
</div>
|
|
959
|
+
)}
|
|
902
960
|
</div>
|
|
903
961
|
</div>
|
|
904
962
|
</div>
|
|
@@ -172,24 +172,52 @@ export async function decryptToken(encrypted: string): Promise<OAuthToken | null
|
|
|
172
172
|
}
|
|
173
173
|
}
|
|
174
174
|
|
|
175
|
-
|
|
175
|
+
// Auto-generated encryption key storage (persists for the session)
|
|
176
|
+
const AUTO_KEY_STORAGE = "__veryfront_auto_encryption_key__";
|
|
177
|
+
// deno-lint-ignore no-explicit-any
|
|
178
|
+
const globalStore = globalThis as any;
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Generate a cryptographically secure encryption key
|
|
182
|
+
* Returns a 64-character hex string (32 bytes)
|
|
183
|
+
*/
|
|
184
|
+
export function generateEncryptionKey(): string {
|
|
185
|
+
const bytes = crypto.getRandomValues(new Uint8Array(32));
|
|
186
|
+
return Array.from(bytes).map(b => b.toString(16).padStart(2, '0')).join('');
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/** Get encryption key from environment or auto-generate for development */
|
|
176
190
|
function getEncryptionKey(): Uint8Array | null {
|
|
177
191
|
const keyHex = typeof process !== "undefined"
|
|
178
192
|
? process.env?.TOKEN_ENCRYPTION_KEY
|
|
179
193
|
// deno-lint-ignore no-explicit-any
|
|
180
194
|
: (globalThis as any).Deno?.env?.get("TOKEN_ENCRYPTION_KEY");
|
|
181
195
|
|
|
182
|
-
if (
|
|
196
|
+
if (keyHex) {
|
|
197
|
+
// Convert hex string to Uint8Array (32 bytes = 64 hex chars)
|
|
198
|
+
if (keyHex.length !== 64) {
|
|
199
|
+
console.error("[Token Store] TOKEN_ENCRYPTION_KEY must be 64 hex characters (32 bytes)");
|
|
200
|
+
return null;
|
|
201
|
+
}
|
|
183
202
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
203
|
+
const key = new Uint8Array(32);
|
|
204
|
+
for (let i = 0; i < 32; i++) {
|
|
205
|
+
key[i] = parseInt(keyHex.slice(i * 2, i * 2 + 2), 16);
|
|
206
|
+
}
|
|
207
|
+
return key;
|
|
188
208
|
}
|
|
189
209
|
|
|
210
|
+
// Auto-generate key for development (persists in memory for the session)
|
|
211
|
+
// This ensures tokens remain encrypted even in dev mode
|
|
212
|
+
if (!globalStore[AUTO_KEY_STORAGE]) {
|
|
213
|
+
globalStore[AUTO_KEY_STORAGE] = generateEncryptionKey();
|
|
214
|
+
console.log("[Token Store] Auto-generated encryption key for this session");
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const autoKey = globalStore[AUTO_KEY_STORAGE] as string;
|
|
190
218
|
const key = new Uint8Array(32);
|
|
191
219
|
for (let i = 0; i < 32; i++) {
|
|
192
|
-
key[i] = parseInt(
|
|
220
|
+
key[i] = parseInt(autoKey.slice(i * 2, i * 2 + 2), 16);
|
|
193
221
|
}
|
|
194
222
|
return key;
|
|
195
223
|
}
|
|
@@ -225,8 +253,6 @@ export function isEncryptionEnabled(): boolean {
|
|
|
225
253
|
|
|
226
254
|
// Use globalThis to share across esbuild bundles (each API route is bundled separately)
|
|
227
255
|
const TOKENS_KEY = "__veryfront_oauth_tokens__";
|
|
228
|
-
// deno-lint-ignore no-explicit-any
|
|
229
|
-
const globalStore = globalThis as any;
|
|
230
256
|
const tokens: Map<string, OAuthToken> = globalStore[TOKENS_KEY] ||= new Map<string, OAuthToken>();
|
|
231
257
|
|
|
232
258
|
function getKey(userId: string, service: string): string {
|
|
@@ -1,11 +1,31 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Airtable OAuth Callback
|
|
3
|
+
*
|
|
4
|
+
* Handles the OAuth callback from Airtable and stores the tokens.
|
|
3
5
|
*/
|
|
4
6
|
|
|
5
7
|
import { airtableConfig, createOAuthCallbackHandler, memoryTokenStore } from "veryfront/oauth";
|
|
8
|
+
import { tokenStore } from "../../../../../lib/token-store.ts";
|
|
9
|
+
|
|
10
|
+
// Hybrid adapter: uses framework's memoryTokenStore for state (PKCE),
|
|
11
|
+
// but user's tokenStore for actual token storage
|
|
12
|
+
const hybridTokenStore = {
|
|
13
|
+
// Token methods - delegate to user's tokenStore
|
|
14
|
+
async getTokens(serviceId: string) {
|
|
15
|
+
return tokenStore.getToken("current-user", serviceId);
|
|
16
|
+
},
|
|
17
|
+
async setTokens(serviceId: string, tokens: { accessToken: string; refreshToken?: string; expiresAt?: number }) {
|
|
18
|
+
await tokenStore.setToken("current-user", serviceId, tokens);
|
|
19
|
+
},
|
|
20
|
+
async clearTokens(serviceId: string) {
|
|
21
|
+
await tokenStore.revokeToken("current-user", serviceId);
|
|
22
|
+
},
|
|
23
|
+
// State methods - delegate to framework's memoryTokenStore (shared with init route)
|
|
24
|
+
getState: (state: string) => memoryTokenStore.getState(state),
|
|
25
|
+
setState: (state: { state: string; codeVerifier?: string; createdAt: number }) => memoryTokenStore.setState(state),
|
|
26
|
+
clearState: (state: string) => memoryTokenStore.clearState(state),
|
|
27
|
+
};
|
|
6
28
|
|
|
7
29
|
export const GET = createOAuthCallbackHandler(airtableConfig, {
|
|
8
|
-
tokenStore:
|
|
9
|
-
onSuccess: () => "/",
|
|
10
|
-
onError: () => "/",
|
|
30
|
+
tokenStore: hybridTokenStore,
|
|
11
31
|
});
|
|
@@ -1,11 +1,31 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Asana OAuth Callback
|
|
3
|
+
*
|
|
4
|
+
* Handles the OAuth callback from Asana and stores the tokens.
|
|
3
5
|
*/
|
|
4
6
|
|
|
5
7
|
import { asanaConfig, createOAuthCallbackHandler, memoryTokenStore } from "veryfront/oauth";
|
|
8
|
+
import { tokenStore } from "../../../../../lib/token-store.ts";
|
|
9
|
+
|
|
10
|
+
// Hybrid adapter: uses framework's memoryTokenStore for state (PKCE),
|
|
11
|
+
// but user's tokenStore for actual token storage
|
|
12
|
+
const hybridTokenStore = {
|
|
13
|
+
// Token methods - delegate to user's tokenStore
|
|
14
|
+
async getTokens(serviceId: string) {
|
|
15
|
+
return tokenStore.getToken("current-user", serviceId);
|
|
16
|
+
},
|
|
17
|
+
async setTokens(serviceId: string, tokens: { accessToken: string; refreshToken?: string; expiresAt?: number }) {
|
|
18
|
+
await tokenStore.setToken("current-user", serviceId, tokens);
|
|
19
|
+
},
|
|
20
|
+
async clearTokens(serviceId: string) {
|
|
21
|
+
await tokenStore.revokeToken("current-user", serviceId);
|
|
22
|
+
},
|
|
23
|
+
// State methods - delegate to framework's memoryTokenStore (shared with init route)
|
|
24
|
+
getState: (state: string) => memoryTokenStore.getState(state),
|
|
25
|
+
setState: (state: { state: string; codeVerifier?: string; createdAt: number }) => memoryTokenStore.setState(state),
|
|
26
|
+
clearState: (state: string) => memoryTokenStore.clearState(state),
|
|
27
|
+
};
|
|
6
28
|
|
|
7
29
|
export const GET = createOAuthCallbackHandler(asanaConfig, {
|
|
8
|
-
tokenStore:
|
|
9
|
-
onSuccess: () => "/",
|
|
10
|
-
onError: () => "/",
|
|
30
|
+
tokenStore: hybridTokenStore,
|
|
11
31
|
});
|
|
@@ -1,11 +1,31 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Bitbucket OAuth Callback
|
|
3
|
+
*
|
|
4
|
+
* Handles the OAuth callback from Atlassian and stores the tokens.
|
|
3
5
|
*/
|
|
4
6
|
|
|
5
7
|
import { bitbucketConfig, createOAuthCallbackHandler, memoryTokenStore } from "veryfront/oauth";
|
|
8
|
+
import { tokenStore } from "../../../../../lib/token-store.ts";
|
|
9
|
+
|
|
10
|
+
// Hybrid adapter: uses framework's memoryTokenStore for state (PKCE),
|
|
11
|
+
// but user's tokenStore for actual token storage
|
|
12
|
+
const hybridTokenStore = {
|
|
13
|
+
// Token methods - delegate to user's tokenStore
|
|
14
|
+
async getTokens(serviceId: string) {
|
|
15
|
+
return tokenStore.getToken("current-user", serviceId);
|
|
16
|
+
},
|
|
17
|
+
async setTokens(serviceId: string, tokens: { accessToken: string; refreshToken?: string; expiresAt?: number }) {
|
|
18
|
+
await tokenStore.setToken("current-user", serviceId, tokens);
|
|
19
|
+
},
|
|
20
|
+
async clearTokens(serviceId: string) {
|
|
21
|
+
await tokenStore.revokeToken("current-user", serviceId);
|
|
22
|
+
},
|
|
23
|
+
// State methods - delegate to framework's memoryTokenStore (shared with init route)
|
|
24
|
+
getState: (state: string) => memoryTokenStore.getState(state),
|
|
25
|
+
setState: (state: { state: string; codeVerifier?: string; createdAt: number }) => memoryTokenStore.setState(state),
|
|
26
|
+
clearState: (state: string) => memoryTokenStore.clearState(state),
|
|
27
|
+
};
|
|
6
28
|
|
|
7
29
|
export const GET = createOAuthCallbackHandler(bitbucketConfig, {
|
|
8
|
-
tokenStore:
|
|
9
|
-
onSuccess: () => "/",
|
|
10
|
-
onError: () => "/",
|
|
30
|
+
tokenStore: hybridTokenStore,
|
|
11
31
|
});
|
|
@@ -1,11 +1,31 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Box OAuth Callback
|
|
3
|
+
*
|
|
4
|
+
* Handles the OAuth callback from Box and stores the tokens.
|
|
3
5
|
*/
|
|
4
6
|
|
|
5
7
|
import { boxConfig, createOAuthCallbackHandler, memoryTokenStore } from "veryfront/oauth";
|
|
8
|
+
import { tokenStore } from "../../../../../lib/token-store.ts";
|
|
9
|
+
|
|
10
|
+
// Hybrid adapter: uses framework's memoryTokenStore for state (PKCE),
|
|
11
|
+
// but user's tokenStore for actual token storage
|
|
12
|
+
const hybridTokenStore = {
|
|
13
|
+
// Token methods - delegate to user's tokenStore
|
|
14
|
+
async getTokens(serviceId: string) {
|
|
15
|
+
return tokenStore.getToken("current-user", serviceId);
|
|
16
|
+
},
|
|
17
|
+
async setTokens(serviceId: string, tokens: { accessToken: string; refreshToken?: string; expiresAt?: number }) {
|
|
18
|
+
await tokenStore.setToken("current-user", serviceId, tokens);
|
|
19
|
+
},
|
|
20
|
+
async clearTokens(serviceId: string) {
|
|
21
|
+
await tokenStore.revokeToken("current-user", serviceId);
|
|
22
|
+
},
|
|
23
|
+
// State methods - delegate to framework's memoryTokenStore (shared with init route)
|
|
24
|
+
getState: (state: string) => memoryTokenStore.getState(state),
|
|
25
|
+
setState: (state: { state: string; codeVerifier?: string; createdAt: number }) => memoryTokenStore.setState(state),
|
|
26
|
+
clearState: (state: string) => memoryTokenStore.clearState(state),
|
|
27
|
+
};
|
|
6
28
|
|
|
7
29
|
export const GET = createOAuthCallbackHandler(boxConfig, {
|
|
8
|
-
tokenStore:
|
|
9
|
-
onSuccess: () => "/",
|
|
10
|
-
onError: () => "/",
|
|
30
|
+
tokenStore: hybridTokenStore,
|
|
11
31
|
});
|
|
@@ -1,11 +1,31 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Calendar OAuth Callback
|
|
3
|
+
*
|
|
4
|
+
* Handles the OAuth callback from Google and stores the tokens.
|
|
3
5
|
*/
|
|
4
6
|
|
|
5
7
|
import { calendarConfig, createOAuthCallbackHandler, memoryTokenStore } from "veryfront/oauth";
|
|
8
|
+
import { tokenStore } from "../../../../../lib/token-store.ts";
|
|
9
|
+
|
|
10
|
+
// Hybrid adapter: uses framework's memoryTokenStore for state (PKCE),
|
|
11
|
+
// but user's tokenStore for actual token storage
|
|
12
|
+
const hybridTokenStore = {
|
|
13
|
+
// Token methods - delegate to user's tokenStore
|
|
14
|
+
async getTokens(serviceId: string) {
|
|
15
|
+
return tokenStore.getToken("current-user", serviceId);
|
|
16
|
+
},
|
|
17
|
+
async setTokens(serviceId: string, tokens: { accessToken: string; refreshToken?: string; expiresAt?: number }) {
|
|
18
|
+
await tokenStore.setToken("current-user", serviceId, tokens);
|
|
19
|
+
},
|
|
20
|
+
async clearTokens(serviceId: string) {
|
|
21
|
+
await tokenStore.revokeToken("current-user", serviceId);
|
|
22
|
+
},
|
|
23
|
+
// State methods - delegate to framework's memoryTokenStore (shared with init route)
|
|
24
|
+
getState: (state: string) => memoryTokenStore.getState(state),
|
|
25
|
+
setState: (state: { state: string; codeVerifier?: string; createdAt: number }) => memoryTokenStore.setState(state),
|
|
26
|
+
clearState: (state: string) => memoryTokenStore.clearState(state),
|
|
27
|
+
};
|
|
6
28
|
|
|
7
29
|
export const GET = createOAuthCallbackHandler(calendarConfig, {
|
|
8
|
-
tokenStore:
|
|
9
|
-
onSuccess: () => "/",
|
|
10
|
-
onError: () => "/",
|
|
30
|
+
tokenStore: hybridTokenStore,
|
|
11
31
|
});
|
|
@@ -1,11 +1,31 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* ClickUp OAuth Callback
|
|
3
|
+
*
|
|
4
|
+
* Handles the OAuth callback from ClickUp and stores the tokens.
|
|
3
5
|
*/
|
|
4
6
|
|
|
5
7
|
import { clickupConfig, createOAuthCallbackHandler, memoryTokenStore } from "veryfront/oauth";
|
|
8
|
+
import { tokenStore } from "../../../../../lib/token-store.ts";
|
|
9
|
+
|
|
10
|
+
// Hybrid adapter: uses framework's memoryTokenStore for state (PKCE),
|
|
11
|
+
// but user's tokenStore for actual token storage
|
|
12
|
+
const hybridTokenStore = {
|
|
13
|
+
// Token methods - delegate to user's tokenStore
|
|
14
|
+
async getTokens(serviceId: string) {
|
|
15
|
+
return tokenStore.getToken("current-user", serviceId);
|
|
16
|
+
},
|
|
17
|
+
async setTokens(serviceId: string, tokens: { accessToken: string; refreshToken?: string; expiresAt?: number }) {
|
|
18
|
+
await tokenStore.setToken("current-user", serviceId, tokens);
|
|
19
|
+
},
|
|
20
|
+
async clearTokens(serviceId: string) {
|
|
21
|
+
await tokenStore.revokeToken("current-user", serviceId);
|
|
22
|
+
},
|
|
23
|
+
// State methods - delegate to framework's memoryTokenStore (shared with init route)
|
|
24
|
+
getState: (state: string) => memoryTokenStore.getState(state),
|
|
25
|
+
setState: (state: { state: string; codeVerifier?: string; createdAt: number }) => memoryTokenStore.setState(state),
|
|
26
|
+
clearState: (state: string) => memoryTokenStore.clearState(state),
|
|
27
|
+
};
|
|
6
28
|
|
|
7
29
|
export const GET = createOAuthCallbackHandler(clickupConfig, {
|
|
8
|
-
tokenStore:
|
|
9
|
-
onSuccess: () => "/",
|
|
10
|
-
onError: () => "/",
|
|
30
|
+
tokenStore: hybridTokenStore,
|
|
11
31
|
});
|
|
@@ -1,11 +1,31 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Confluence OAuth Callback
|
|
3
|
+
*
|
|
4
|
+
* Handles the OAuth callback from Atlassian and stores the tokens.
|
|
3
5
|
*/
|
|
4
6
|
|
|
5
7
|
import { confluenceConfig, createOAuthCallbackHandler, memoryTokenStore } from "veryfront/oauth";
|
|
8
|
+
import { tokenStore } from "../../../../../lib/token-store.ts";
|
|
9
|
+
|
|
10
|
+
// Hybrid adapter: uses framework's memoryTokenStore for state (PKCE),
|
|
11
|
+
// but user's tokenStore for actual token storage
|
|
12
|
+
const hybridTokenStore = {
|
|
13
|
+
// Token methods - delegate to user's tokenStore
|
|
14
|
+
async getTokens(serviceId: string) {
|
|
15
|
+
return tokenStore.getToken("current-user", serviceId);
|
|
16
|
+
},
|
|
17
|
+
async setTokens(serviceId: string, tokens: { accessToken: string; refreshToken?: string; expiresAt?: number }) {
|
|
18
|
+
await tokenStore.setToken("current-user", serviceId, tokens);
|
|
19
|
+
},
|
|
20
|
+
async clearTokens(serviceId: string) {
|
|
21
|
+
await tokenStore.revokeToken("current-user", serviceId);
|
|
22
|
+
},
|
|
23
|
+
// State methods - delegate to framework's memoryTokenStore (shared with init route)
|
|
24
|
+
getState: (state: string) => memoryTokenStore.getState(state),
|
|
25
|
+
setState: (state: { state: string; codeVerifier?: string; createdAt: number }) => memoryTokenStore.setState(state),
|
|
26
|
+
clearState: (state: string) => memoryTokenStore.clearState(state),
|
|
27
|
+
};
|
|
6
28
|
|
|
7
29
|
export const GET = createOAuthCallbackHandler(confluenceConfig, {
|
|
8
|
-
tokenStore:
|
|
9
|
-
onSuccess: () => "/",
|
|
10
|
-
onError: () => "/",
|
|
30
|
+
tokenStore: hybridTokenStore,
|
|
11
31
|
});
|
|
@@ -1,11 +1,31 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Discord OAuth Callback
|
|
3
|
+
*
|
|
4
|
+
* Handles the OAuth callback from Discord and stores the tokens.
|
|
3
5
|
*/
|
|
4
6
|
|
|
5
7
|
import { createOAuthCallbackHandler, discordConfig, memoryTokenStore } from "veryfront/oauth";
|
|
8
|
+
import { tokenStore } from "../../../../../lib/token-store.ts";
|
|
9
|
+
|
|
10
|
+
// Hybrid adapter: uses framework's memoryTokenStore for state (PKCE),
|
|
11
|
+
// but user's tokenStore for actual token storage
|
|
12
|
+
const hybridTokenStore = {
|
|
13
|
+
// Token methods - delegate to user's tokenStore
|
|
14
|
+
async getTokens(serviceId: string) {
|
|
15
|
+
return tokenStore.getToken("current-user", serviceId);
|
|
16
|
+
},
|
|
17
|
+
async setTokens(serviceId: string, tokens: { accessToken: string; refreshToken?: string; expiresAt?: number }) {
|
|
18
|
+
await tokenStore.setToken("current-user", serviceId, tokens);
|
|
19
|
+
},
|
|
20
|
+
async clearTokens(serviceId: string) {
|
|
21
|
+
await tokenStore.revokeToken("current-user", serviceId);
|
|
22
|
+
},
|
|
23
|
+
// State methods - delegate to framework's memoryTokenStore (shared with init route)
|
|
24
|
+
getState: (state: string) => memoryTokenStore.getState(state),
|
|
25
|
+
setState: (state: { state: string; codeVerifier?: string; createdAt: number }) => memoryTokenStore.setState(state),
|
|
26
|
+
clearState: (state: string) => memoryTokenStore.clearState(state),
|
|
27
|
+
};
|
|
6
28
|
|
|
7
29
|
export const GET = createOAuthCallbackHandler(discordConfig, {
|
|
8
|
-
tokenStore:
|
|
9
|
-
onSuccess: () => "/",
|
|
10
|
-
onError: () => "/",
|
|
30
|
+
tokenStore: hybridTokenStore,
|
|
11
31
|
});
|
|
@@ -1,11 +1,31 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Google Docs OAuth Callback
|
|
3
|
+
*
|
|
4
|
+
* Handles the OAuth callback from Google and stores the tokens.
|
|
3
5
|
*/
|
|
4
6
|
|
|
5
|
-
import { createOAuthCallbackHandler,
|
|
7
|
+
import { createOAuthCallbackHandler, docsGoogleConfig, memoryTokenStore } from "veryfront/oauth";
|
|
8
|
+
import { tokenStore } from "../../../../../lib/token-store.ts";
|
|
9
|
+
|
|
10
|
+
// Hybrid adapter: uses framework's memoryTokenStore for state (PKCE),
|
|
11
|
+
// but user's tokenStore for actual token storage
|
|
12
|
+
const hybridTokenStore = {
|
|
13
|
+
// Token methods - delegate to user's tokenStore
|
|
14
|
+
async getTokens(serviceId: string) {
|
|
15
|
+
return tokenStore.getToken("current-user", serviceId);
|
|
16
|
+
},
|
|
17
|
+
async setTokens(serviceId: string, tokens: { accessToken: string; refreshToken?: string; expiresAt?: number }) {
|
|
18
|
+
await tokenStore.setToken("current-user", serviceId, tokens);
|
|
19
|
+
},
|
|
20
|
+
async clearTokens(serviceId: string) {
|
|
21
|
+
await tokenStore.revokeToken("current-user", serviceId);
|
|
22
|
+
},
|
|
23
|
+
// State methods - delegate to framework's memoryTokenStore (shared with init route)
|
|
24
|
+
getState: (state: string) => memoryTokenStore.getState(state),
|
|
25
|
+
setState: (state: { state: string; codeVerifier?: string; createdAt: number }) => memoryTokenStore.setState(state),
|
|
26
|
+
clearState: (state: string) => memoryTokenStore.clearState(state),
|
|
27
|
+
};
|
|
6
28
|
|
|
7
29
|
export const GET = createOAuthCallbackHandler(docsGoogleConfig, {
|
|
8
|
-
tokenStore:
|
|
9
|
-
onSuccess: () => "/",
|
|
10
|
-
onError: () => "/",
|
|
30
|
+
tokenStore: hybridTokenStore,
|
|
11
31
|
});
|
|
@@ -1,11 +1,31 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Google Drive OAuth Callback
|
|
3
|
+
*
|
|
4
|
+
* Handles the OAuth callback from Google and stores the tokens.
|
|
3
5
|
*/
|
|
4
6
|
|
|
5
|
-
import { createOAuthCallbackHandler,
|
|
7
|
+
import { createOAuthCallbackHandler, driveConfig, memoryTokenStore } from "veryfront/oauth";
|
|
8
|
+
import { tokenStore } from "../../../../../lib/token-store.ts";
|
|
9
|
+
|
|
10
|
+
// Hybrid adapter: uses framework's memoryTokenStore for state (PKCE),
|
|
11
|
+
// but user's tokenStore for actual token storage
|
|
12
|
+
const hybridTokenStore = {
|
|
13
|
+
// Token methods - delegate to user's tokenStore
|
|
14
|
+
async getTokens(serviceId: string) {
|
|
15
|
+
return tokenStore.getToken("current-user", serviceId);
|
|
16
|
+
},
|
|
17
|
+
async setTokens(serviceId: string, tokens: { accessToken: string; refreshToken?: string; expiresAt?: number }) {
|
|
18
|
+
await tokenStore.setToken("current-user", serviceId, tokens);
|
|
19
|
+
},
|
|
20
|
+
async clearTokens(serviceId: string) {
|
|
21
|
+
await tokenStore.revokeToken("current-user", serviceId);
|
|
22
|
+
},
|
|
23
|
+
// State methods - delegate to framework's memoryTokenStore (shared with init route)
|
|
24
|
+
getState: (state: string) => memoryTokenStore.getState(state),
|
|
25
|
+
setState: (state: { state: string; codeVerifier?: string; createdAt: number }) => memoryTokenStore.setState(state),
|
|
26
|
+
clearState: (state: string) => memoryTokenStore.clearState(state),
|
|
27
|
+
};
|
|
6
28
|
|
|
7
29
|
export const GET = createOAuthCallbackHandler(driveConfig, {
|
|
8
|
-
tokenStore:
|
|
9
|
-
onSuccess: () => "/",
|
|
10
|
-
onError: () => "/",
|
|
30
|
+
tokenStore: hybridTokenStore,
|
|
11
31
|
});
|
|
@@ -1,11 +1,31 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Dropbox OAuth Callback
|
|
3
|
+
*
|
|
4
|
+
* Handles the OAuth callback from Dropbox and stores the tokens.
|
|
3
5
|
*/
|
|
4
6
|
|
|
5
7
|
import { createOAuthCallbackHandler, dropboxConfig, memoryTokenStore } from "veryfront/oauth";
|
|
8
|
+
import { tokenStore } from "../../../../../lib/token-store.ts";
|
|
9
|
+
|
|
10
|
+
// Hybrid adapter: uses framework's memoryTokenStore for state (PKCE),
|
|
11
|
+
// but user's tokenStore for actual token storage
|
|
12
|
+
const hybridTokenStore = {
|
|
13
|
+
// Token methods - delegate to user's tokenStore
|
|
14
|
+
async getTokens(serviceId: string) {
|
|
15
|
+
return tokenStore.getToken("current-user", serviceId);
|
|
16
|
+
},
|
|
17
|
+
async setTokens(serviceId: string, tokens: { accessToken: string; refreshToken?: string; expiresAt?: number }) {
|
|
18
|
+
await tokenStore.setToken("current-user", serviceId, tokens);
|
|
19
|
+
},
|
|
20
|
+
async clearTokens(serviceId: string) {
|
|
21
|
+
await tokenStore.revokeToken("current-user", serviceId);
|
|
22
|
+
},
|
|
23
|
+
// State methods - delegate to framework's memoryTokenStore (shared with init route)
|
|
24
|
+
getState: (state: string) => memoryTokenStore.getState(state),
|
|
25
|
+
setState: (state: { state: string; codeVerifier?: string; createdAt: number }) => memoryTokenStore.setState(state),
|
|
26
|
+
clearState: (state: string) => memoryTokenStore.clearState(state),
|
|
27
|
+
};
|
|
6
28
|
|
|
7
29
|
export const GET = createOAuthCallbackHandler(dropboxConfig, {
|
|
8
|
-
tokenStore:
|
|
9
|
-
onSuccess: () => "/",
|
|
10
|
-
onError: () => "/",
|
|
30
|
+
tokenStore: hybridTokenStore,
|
|
11
31
|
});
|