UNPKG

@rsweeten/dropbox-sync

Version:

Reusable Dropbox synchronization module with framework adapters

121 lines (120 loc) 4.5 kB
import { createDropboxSyncClient } from '../core/client'; import { cookies } from 'next/headers'; import { NextResponse } from 'next/server'; /** * Next.js-specific helper to create a Dropbox sync client * Can be used in both client and server components */ export function useNextDropboxSync(credentials) { return createDropboxSyncClient(credentials); } /** * Server-side helper to get credentials from Next.js cookies */ export async function getCredentialsFromCookies() { const cookieStore = await cookies(); return { clientId: process.env.DROPBOX_APP_KEY || '', clientSecret: process.env.DROPBOX_APP_SECRET, accessToken: cookieStore.get('dropbox_access_token')?.value, refreshToken: cookieStore.get('dropbox_refresh_token')?.value, }; } /** * Server action to handle Dropbox OAuth callback */ export async function handleOAuthCallback(request) { const url = new URL(request.url); const code = url.searchParams.get('code'); if (!code) { return NextResponse.redirect(new URL('/auth/error', request.url)); } const redirectUri = process.env.DROPBOX_REDIRECT_URI || `${process.env.NEXT_PUBLIC_APP_URL || 'http://localhost:3000'}/api/dropbox/auth/callback`; const dropboxSync = createDropboxSyncClient({ clientId: process.env.DROPBOX_APP_KEY || '', clientSecret: process.env.DROPBOX_APP_SECRET, }); try { const tokens = await dropboxSync.auth.exchangeCodeForToken(code, redirectUri); // Create response with redirect const response = NextResponse.redirect(new URL('/', request.url)); // Set cookies with the tokens response.cookies.set({ name: 'dropbox_access_token', value: tokens.accessToken, httpOnly: true, secure: process.env.NODE_ENV === 'production', maxAge: tokens.expiresAt ? (tokens.expiresAt - Date.now()) / 1000 : 14 * 24 * 60 * 60, // 14 days default sameSite: 'lax', path: '/', }); if (tokens.refreshToken) { response.cookies.set({ name: 'dropbox_refresh_token', value: tokens.refreshToken, httpOnly: true, secure: process.env.NODE_ENV === 'production', maxAge: 365 * 24 * 60 * 60, // 1 year sameSite: 'lax', path: '/', }); } // Set a non-httpOnly cookie to indicate connection status to the client response.cookies.set({ name: 'dropbox_connected', value: 'true', secure: process.env.NODE_ENV === 'production', maxAge: tokens.expiresAt ? (tokens.expiresAt - Date.now()) / 1000 : 14 * 24 * 60 * 60, sameSite: 'lax', path: '/', }); return response; } catch (error) { console.error('Error completing Dropbox OAuth flow:', error); return NextResponse.redirect(new URL('/auth/error', request.url)); } } /** * Create API route handlers for a Next.js app */ export function createNextDropboxApiHandlers() { return { /** * Handler for status check route */ async status() { const cookieStore = await cookies(); const isConnected = !!cookieStore.get('dropbox_access_token')?.value; return NextResponse.json({ connected: isConnected }); }, /** * Handler for OAuth start route */ async oauthStart() { const dropboxSync = createDropboxSyncClient({ clientId: process.env.DROPBOX_APP_KEY || '', }); const redirectUri = process.env.DROPBOX_REDIRECT_URI || `${process.env.NEXT_PUBLIC_APP_URL || 'http://localhost:3000'}/api/dropbox/auth/callback`; const authUrl = await dropboxSync.auth.getAuthUrl(redirectUri); return NextResponse.redirect(authUrl); }, /** * Handler for logout route */ async logout() { const response = NextResponse.json({ success: true }); // Clear all Dropbox-related cookies response.cookies.delete('dropbox_access_token'); response.cookies.delete('dropbox_refresh_token'); response.cookies.delete('dropbox_connected'); return response; }, }; }