@rsweeten/dropbox-sync
Version:
Reusable Dropbox synchronization module with framework adapters
175 lines (149 loc) • 5.51 kB
text/typescript
// SvelteKit store for Dropbox sync
import { writable, derived } from 'svelte/store'
// For a private module, you would import from your private registry or local path
// import { useSvelteDropboxSync } from '@yourcompany/dropbox-sync';
import { useSvelteDropboxSync } from 'dropbox-sync'
import { browser } from '$app/environment'
import { goto } from '$app/navigation'
// Create a persistent store
export function createDropboxStore() {
const credentials = {
clientId: browser
? import.meta.env.VITE_DROPBOX_APP_KEY
: process.env.DROPBOX_APP_KEY,
// The access token will be added from cookies on the server side
}
// Initialize the Dropbox client
const dropboxSync = useSvelteDropboxSync(credentials)
// Create stores for state management
const connected = writable(false)
const syncing = writable(false)
const progress = writable(0)
const message = writable('')
const error = writable<string | null>(null)
const syncStats = writable({
total: 0,
uploads: 0,
downloads: 0,
completed: 0,
})
// Check connection status on initialization
async function checkConnection() {
if (!browser) return
try {
const response = await fetch('/api/dropbox/status')
const data = await response.json()
connected.set(data.connected)
} catch (err) {
console.error('Error checking Dropbox connection:', err)
connected.set(false)
}
}
if (browser) {
checkConnection()
// Set up socket connection for real-time updates
dropboxSync.socket.connect()
// Listen for progress updates
dropboxSync.socket.on('sync:progress', (data) => {
progress.set(data.progress)
message.set(data.message)
})
// Listen for queue information
dropboxSync.socket.on('sync:queue', (data) => {
syncStats.set({
total: data.total,
uploads: data.totalUploads,
downloads: data.totalDownloads,
completed: 0,
})
})
// Listen for completion
dropboxSync.socket.on('sync:complete', (data) => {
progress.set(100)
message.set(data.message)
syncing.set(false)
if (data.stats) {
syncStats.update((stats) => ({
...stats,
completed: stats.total,
}))
}
})
// Listen for errors
dropboxSync.socket.on('sync:error', (data) => {
error.set(data.message)
syncing.set(false)
})
}
return {
connected: { subscribe: connected.subscribe },
syncing: { subscribe: syncing.subscribe },
progress: { subscribe: progress.subscribe },
message: { subscribe: message.subscribe },
error: { subscribe: error.subscribe },
syncStats: { subscribe: syncStats.subscribe },
// Connect to Dropbox
connect() {
if (!browser) return
goto('/api/dropbox/auth/start')
},
// Disconnect from Dropbox
async disconnect() {
if (!browser) return
try {
await fetch('/api/dropbox/logout', { method: 'POST' })
connected.set(false)
} catch (err) {
console.error('Error disconnecting from Dropbox:', err)
}
},
// Start synchronization
async startSync() {
if (!browser) return
try {
syncing.set(true)
progress.set(0)
message.set('Initializing Dropbox sync...')
error.set(null)
// Trigger sync via socket
dropboxSync.socket.emit('dropbox:sync')
} catch (err: any) {
console.error('Error starting Dropbox sync:', err)
error.set(
err.message || 'An error occurred while starting sync'
)
syncing.set(false)
}
},
// Cancel synchronization
cancelSync() {
if (!browser) return
dropboxSync.sync.cancelSync()
syncing.set(false)
message.set('Sync cancelled')
},
// Check files that need syncing without starting the sync
async checkSyncNeeded(options?: {
localDir?: string
dropboxDir?: string
}) {
if (!browser) return { upload: 0, download: 0 }
try {
const { uploadQueue, downloadQueue } =
await dropboxSync.sync.createSyncQueue({
localDir: options?.localDir,
dropboxDir: options?.dropboxDir,
})
return {
upload: uploadQueue.length,
download: downloadQueue.length,
}
} catch (err) {
console.error('Error checking sync status:', err)
return { upload: 0, download: 0 }
}
},
}
}
// Export singleton instance
export const dropbox = createDropboxStore()