UNPKG

@rsweeten/dropbox-sync

Version:

Reusable Dropbox synchronization module with framework adapters

191 lines (190 loc) 7.38 kB
import { createDropboxSyncClient } from '../core/client'; import { useCookie, useRuntimeConfig } from 'nuxt/app'; /** * Helper to safely access runtime config properties */ function getConfigValue(obj, path, defaultValue) { const parts = path.split('.'); let current = obj; for (const part of parts) { if (current === undefined || current === null) { return defaultValue; } current = current[part]; } return current || defaultValue; } /** * Nuxt-specific helper for creating a Dropbox sync client * Can be used in both client and server components */ export function useNuxtDropboxSync(credentials) { // Get Nuxt runtime config (for client ID and secret) const config = useRuntimeConfig(); // Create base credentials with defaults from runtime config const baseCredentials = { clientId: getConfigValue(config, 'public.dropboxAppKey', ''), clientSecret: getConfigValue(config, 'dropboxAppSecret', ''), ...credentials, }; // On client-side, attempt to get tokens from cookies if (process.client) { const accessToken = useCookie('dropbox_access_token'); const refreshToken = useCookie('dropbox_refresh_token'); if (accessToken.value && !baseCredentials.accessToken) { baseCredentials.accessToken = accessToken.value; } if (refreshToken.value && !baseCredentials.refreshToken) { baseCredentials.refreshToken = refreshToken.value; } } return createDropboxSyncClient(baseCredentials); } /** * Server-side helper to get credentials from Nuxt server event */ export function getCredentialsFromCookies(event) { const config = useRuntimeConfig(); // Get cookies from Nuxt server event const accessToken = getCookie(event, 'dropbox_access_token'); const refreshToken = getCookie(event, 'dropbox_refresh_token'); return { clientId: getConfigValue(config, 'public.dropboxAppKey', ''), clientSecret: getConfigValue(config, 'dropboxAppSecret', ''), accessToken, refreshToken, }; } /** * Create API event handlers for a Nuxt app */ export function createNuxtApiHandlers() { return { /** * Handler for status check endpoint */ async status(event) { const accessToken = getCookie(event, 'dropbox_access_token'); const isConnected = !!accessToken; return { connected: isConnected }; }, /** * Handler for OAuth start endpoint */ async oauthStart(event) { const config = useRuntimeConfig(); const dropboxSync = createDropboxSyncClient({ clientId: getConfigValue(config, 'public.dropboxAppKey', ''), }); const redirectUri = getConfigValue(config, 'dropboxRedirectUri', '') || `${getConfigValue(config, 'public.appUrl', 'http://localhost:3000')}/api/dropbox/auth/callback`; const authUrl = await dropboxSync.auth.getAuthUrl(redirectUri); return sendRedirect(event, authUrl); }, /** * Handler for OAuth callback endpoint */ async oauthCallback(event) { const config = useRuntimeConfig(); // Get the authorization code from query parameters const query = getQuery(event); const code = query.code; if (!code) { return sendRedirect(event, '/auth/error'); } const redirectUri = getConfigValue(config, 'dropboxRedirectUri', '') || `${getConfigValue(config, 'public.appUrl', 'http://localhost:3000')}/api/dropbox/auth/callback`; const dropboxSync = createDropboxSyncClient({ clientId: getConfigValue(config, 'public.dropboxAppKey', ''), clientSecret: getConfigValue(config, 'dropboxAppSecret', ''), }); try { const tokens = await dropboxSync.auth.exchangeCodeForToken(code, redirectUri); // Set cookies with the tokens setCookie(event, 'dropbox_access_token', tokens.accessToken, { httpOnly: true, secure: process.env.NODE_ENV === 'production', maxAge: tokens.expiresAt ? Math.floor((tokens.expiresAt - Date.now()) / 1000) : 14 * 24 * 60 * 60, // 14 days default sameSite: 'lax', path: '/', }); if (tokens.refreshToken) { setCookie(event, 'dropbox_refresh_token', 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 setCookie(event, 'dropbox_connected', 'true', { secure: process.env.NODE_ENV === 'production', maxAge: tokens.expiresAt ? Math.floor((tokens.expiresAt - Date.now()) / 1000) : 14 * 24 * 60 * 60, sameSite: 'lax', path: '/', }); return sendRedirect(event, '/'); } catch (error) { console.error('Error completing Dropbox OAuth flow:', error); return sendRedirect(event, '/auth/error'); } }, /** * Handler for logout endpoint */ async logout(event) { // Clear all Dropbox-related cookies deleteCookie(event, 'dropbox_access_token'); deleteCookie(event, 'dropbox_refresh_token'); deleteCookie(event, 'dropbox_connected'); return { success: true }; }, }; } /** * Helper functions to work with Nuxt's H3Event * These import statements need to be added to avoid reference errors */ const { getCookie, setCookie, deleteCookie } = useNuxtCookies(); const { getQuery, sendRedirect } = useNuxtServer(); /** * Helper to access h3 cookie methods */ function useNuxtCookies() { return { getCookie: (event, name) => { // Import inside function to avoid module loading issues const { getCookie } = require('h3'); return getCookie(event, name); }, setCookie: (event, name, value, options) => { const { setCookie } = require('h3'); return setCookie(event, name, value, options); }, deleteCookie: (event, name, options) => { const { deleteCookie } = require('h3'); return deleteCookie(event, name, { ...options, path: '/' }); }, }; } /** * Helper to access h3 server methods */ function useNuxtServer() { return { getQuery: (event) => { const { getQuery } = require('h3'); return getQuery(event); }, sendRedirect: (event, location) => { const { sendRedirect } = require('h3'); return sendRedirect(event, location); }, }; }