@rsweeten/dropbox-sync 0.1.1 → 0.1.3
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/.github/workflows/test-pr.yml +30 -0
- package/README.md +521 -315
- package/__mocks__/nuxt/app.js +20 -0
- package/dist/adapters/__tests__/angular.spec.d.ts +1 -0
- package/dist/adapters/__tests__/angular.spec.js +237 -0
- package/dist/adapters/__tests__/next.spec.d.ts +1 -0
- package/dist/adapters/__tests__/next.spec.js +179 -0
- package/dist/adapters/__tests__/nuxt.spec.d.ts +1 -0
- package/dist/adapters/__tests__/nuxt.spec.js +145 -0
- package/dist/adapters/__tests__/svelte.spec.d.ts +1 -0
- package/dist/adapters/__tests__/svelte.spec.js +149 -0
- package/dist/core/__tests__/auth.spec.d.ts +1 -0
- package/dist/core/__tests__/auth.spec.js +83 -0
- package/dist/core/__tests__/client.spec.d.ts +1 -0
- package/dist/core/__tests__/client.spec.js +102 -0
- package/dist/core/__tests__/socket.spec.d.ts +1 -0
- package/dist/core/__tests__/socket.spec.js +122 -0
- package/dist/core/__tests__/sync.spec.d.ts +1 -0
- package/dist/core/__tests__/sync.spec.js +375 -0
- package/dist/core/sync.js +30 -11
- package/jest.config.js +24 -0
- package/jest.setup.js +38 -0
- package/package.json +77 -74
- package/src/adapters/__tests__/angular.spec.ts +338 -0
- package/src/adapters/__tests__/next.spec.ts +240 -0
- package/src/adapters/__tests__/nuxt.spec.ts +185 -0
- package/src/adapters/__tests__/svelte.spec.ts +194 -0
- package/src/core/__tests__/auth.spec.ts +142 -0
- package/src/core/__tests__/client.spec.ts +128 -0
- package/src/core/__tests__/socket.spec.ts +153 -0
- package/src/core/__tests__/sync.spec.ts +508 -0
- package/src/core/sync.ts +503 -476
package/README.md
CHANGED
|
@@ -1,315 +1,521 @@
|
|
|
1
|
-
# Dropbox Sync Module
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
```
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
1
|
+
# Dropbox Sync Module
|
|
2
|
+
|
|
3
|
+
[](https://github.com/sweetenr/dropbox-sync-service/actions/workflows/test-pr.yml)
|
|
4
|
+
|
|
5
|
+
A reusable TypeScript module for syncing files between your application and Dropbox. Features framework-specific adapters for Next.js, SvelteKit, Nuxt, and Angular.
|
|
6
|
+
|
|
7
|
+
> N.B. This NPM package is neither tested nor supported
|
|
8
|
+
|
|
9
|
+
## Table of Contents
|
|
10
|
+
|
|
11
|
+
- [Features](#features)
|
|
12
|
+
- [Installation](#installation)
|
|
13
|
+
- [Quick Start](#quick-start)
|
|
14
|
+
- [Core Usage](#core-usage)
|
|
15
|
+
- [Development Setup](#development-setup)
|
|
16
|
+
- [Architecture](#architecture)
|
|
17
|
+
- [Data Flow](#data-flow)
|
|
18
|
+
- [Testing](#testing)
|
|
19
|
+
- [Test Structure](#test-structure)
|
|
20
|
+
- [Running Tests](#running-tests)
|
|
21
|
+
- [Testing Approach](#testing-approach)
|
|
22
|
+
- [Mock Strategy](#mock-strategy)
|
|
23
|
+
- [Test Coverage](#test-coverage)
|
|
24
|
+
- [Framework-Specific Usage](#framework-specific-usage)
|
|
25
|
+
- [Next.js](#nextjs)
|
|
26
|
+
- [Nuxt.js](#nuxtjs)
|
|
27
|
+
- [SvelteKit](#sveltekit)
|
|
28
|
+
- [Angular](#angular)
|
|
29
|
+
- [API Reference](#api-reference)
|
|
30
|
+
- [Core Client](#core-client)
|
|
31
|
+
- [Auth Methods](#auth-methods)
|
|
32
|
+
- [Sync Methods](#sync-methods)
|
|
33
|
+
- [Socket Methods](#socket-methods)
|
|
34
|
+
- [Socket Events](#socket-events)
|
|
35
|
+
- [Configuration Options](#configuration-options)
|
|
36
|
+
- [License](#license)
|
|
37
|
+
|
|
38
|
+
## Features
|
|
39
|
+
|
|
40
|
+
- **File Synchronization**: Upload local files to Dropbox and download Dropbox files to your local filesystem
|
|
41
|
+
- **Real-time Progress**: Integrated Socket.IO support for real-time sync progress updates
|
|
42
|
+
- **Path Normalization**: Robust path handling to ensure consistent comparison between local and remote paths
|
|
43
|
+
- **OAuth Authentication**: Built-in OAuth flow handling for Dropbox API authentication
|
|
44
|
+
- **Framework Adapters**: Ready-to-use integrations for Next.js, SvelteKit, and Angular
|
|
45
|
+
- **TypeScript Support**: Fully typed API for improved developer experience
|
|
46
|
+
|
|
47
|
+
## Installation
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
# Install the package in your project
|
|
51
|
+
npm install dropbox-sync
|
|
52
|
+
# or
|
|
53
|
+
yarn add dropbox-sync
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
You may also need to install peer dependencies:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
npm install socket.io socket.io-client
|
|
60
|
+
# or
|
|
61
|
+
yarn add socket.io socket.io-client
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Quick Start
|
|
65
|
+
|
|
66
|
+
### Core Usage
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
import createDropboxSyncClient from 'dropbox-sync'
|
|
70
|
+
|
|
71
|
+
// Create a Dropbox sync client
|
|
72
|
+
const dropboxSync = createDropboxSyncClient({
|
|
73
|
+
clientId: 'YOUR_DROPBOX_APP_KEY',
|
|
74
|
+
clientSecret: 'YOUR_DROPBOX_APP_SECRET',
|
|
75
|
+
accessToken: 'OPTIONAL_EXISTING_TOKEN',
|
|
76
|
+
refreshToken: 'OPTIONAL_REFRESH_TOKEN',
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
// Start OAuth flow
|
|
80
|
+
const authUrl = await dropboxSync.auth.getAuthUrl(
|
|
81
|
+
'http://localhost:3000/callback'
|
|
82
|
+
)
|
|
83
|
+
// Redirect the user to authUrl
|
|
84
|
+
|
|
85
|
+
// Exchange authorization code for tokens
|
|
86
|
+
const tokens = await dropboxSync.auth.exchangeCodeForToken(code, redirectUri)
|
|
87
|
+
// Save tokens.accessToken and tokens.refreshToken
|
|
88
|
+
|
|
89
|
+
// Sync files
|
|
90
|
+
const syncResult = await dropboxSync.sync.syncFiles({
|
|
91
|
+
localDir: './public/img',
|
|
92
|
+
dropboxDir: '/app-images',
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
console.log(`Uploaded ${syncResult.uploaded.length} files`)
|
|
96
|
+
console.log(`Downloaded ${syncResult.downloaded.length} files`)
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Development Setup
|
|
100
|
+
|
|
101
|
+
To set up this project for local development:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
# Clone the repository
|
|
105
|
+
git clone https://github.com/yourusername/dropbox-sync-service.git
|
|
106
|
+
cd dropbox-sync-service
|
|
107
|
+
|
|
108
|
+
# Install dependencies
|
|
109
|
+
npm install
|
|
110
|
+
|
|
111
|
+
# Run tests
|
|
112
|
+
npm test
|
|
113
|
+
|
|
114
|
+
# Build the package
|
|
115
|
+
npm run build
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Architecture
|
|
119
|
+
|
|
120
|
+
The Dropbox Sync Module architecture is designed with modularity, extensibility, and framework-agnosticism in mind.
|
|
121
|
+
|
|
122
|
+
```mermaid
|
|
123
|
+
graph TD
|
|
124
|
+
A[Application] --> B[Framework Adapter]
|
|
125
|
+
B --> C[Core Client]
|
|
126
|
+
C --> D[Auth Module]
|
|
127
|
+
C --> E[Sync Module]
|
|
128
|
+
C --> F[Socket Module]
|
|
129
|
+
D --> G[Dropbox API]
|
|
130
|
+
E --> G
|
|
131
|
+
F --> H[Socket.IO]
|
|
132
|
+
H --> E
|
|
133
|
+
H --> A
|
|
134
|
+
|
|
135
|
+
%% File Flow
|
|
136
|
+
I[Local Files] --> E
|
|
137
|
+
E --> I
|
|
138
|
+
G --> E
|
|
139
|
+
E --> G
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Data Flow
|
|
143
|
+
|
|
144
|
+
1. **Authentication Flow:**
|
|
145
|
+
|
|
146
|
+
```mermaid
|
|
147
|
+
sequenceDiagram
|
|
148
|
+
participant User
|
|
149
|
+
participant App
|
|
150
|
+
participant DropboxSync
|
|
151
|
+
participant Dropbox
|
|
152
|
+
|
|
153
|
+
User->>App: Initiate auth
|
|
154
|
+
App->>DropboxSync: getAuthUrl()
|
|
155
|
+
DropboxSync->>Dropbox: Request auth URL
|
|
156
|
+
Dropbox-->>DropboxSync: Auth URL
|
|
157
|
+
DropboxSync-->>App: Auth URL
|
|
158
|
+
App-->>User: Redirect to auth URL
|
|
159
|
+
User->>Dropbox: Authorize app
|
|
160
|
+
Dropbox-->>App: Auth code (via redirect)
|
|
161
|
+
App->>DropboxSync: exchangeCodeForToken(code)
|
|
162
|
+
DropboxSync->>Dropbox: Exchange code for token
|
|
163
|
+
Dropbox-->>DropboxSync: Access & refresh tokens
|
|
164
|
+
DropboxSync-->>App: Tokens
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
2. **Sync Flow:**
|
|
168
|
+
|
|
169
|
+
```mermaid
|
|
170
|
+
sequenceDiagram
|
|
171
|
+
participant App
|
|
172
|
+
participant DropboxSync
|
|
173
|
+
participant Socket
|
|
174
|
+
participant Dropbox
|
|
175
|
+
participant LocalFS
|
|
176
|
+
|
|
177
|
+
App->>DropboxSync: syncFiles(options)
|
|
178
|
+
DropboxSync->>LocalFS: Scan local files
|
|
179
|
+
LocalFS-->>DropboxSync: Local file list
|
|
180
|
+
DropboxSync->>Dropbox: List files
|
|
181
|
+
Dropbox-->>DropboxSync: Dropbox file list
|
|
182
|
+
DropboxSync->>DropboxSync: Create sync queue
|
|
183
|
+
|
|
184
|
+
loop For each file to upload
|
|
185
|
+
DropboxSync->>Dropbox: Upload file
|
|
186
|
+
DropboxSync->>Socket: Emit progress
|
|
187
|
+
Socket-->>App: Progress update
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
loop For each file to download
|
|
191
|
+
DropboxSync->>Dropbox: Download file
|
|
192
|
+
DropboxSync->>LocalFS: Write file
|
|
193
|
+
DropboxSync->>Socket: Emit progress
|
|
194
|
+
Socket-->>App: Progress update
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
DropboxSync-->>App: Sync results
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## Testing
|
|
201
|
+
|
|
202
|
+
The Dropbox Sync Module uses Jest for unit testing. Tests are organized to match the structure of the source code.
|
|
203
|
+
|
|
204
|
+
### Test Structure
|
|
205
|
+
|
|
206
|
+
```
|
|
207
|
+
__tests__/ # Test utilities and mocks
|
|
208
|
+
src/
|
|
209
|
+
core/
|
|
210
|
+
__tests__/ # Core module tests
|
|
211
|
+
auth.spec.ts # Authentication tests
|
|
212
|
+
client.spec.ts # Client tests
|
|
213
|
+
socket.spec.ts # Socket tests
|
|
214
|
+
sync.spec.ts # Sync tests
|
|
215
|
+
adapters/
|
|
216
|
+
__tests__/ # Framework adapter tests
|
|
217
|
+
angular.spec.ts # Angular adapter tests
|
|
218
|
+
next.spec.ts # Next.js adapter tests
|
|
219
|
+
nuxt.spec.ts # Nuxt adapter tests
|
|
220
|
+
svelte.spec.ts # SvelteKit adapter tests
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### Running Tests
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
# Run all tests
|
|
227
|
+
npm test
|
|
228
|
+
|
|
229
|
+
# Run tests with coverage
|
|
230
|
+
npm test -- --coverage
|
|
231
|
+
|
|
232
|
+
# Run specific test file
|
|
233
|
+
npm test -- src/core/__tests__/auth.spec.ts
|
|
234
|
+
|
|
235
|
+
# Run tests in watch mode during development
|
|
236
|
+
npm test -- --watch
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
### Testing Approach
|
|
240
|
+
|
|
241
|
+
1. **Unit Tests**: Each module is tested in isolation with mocked dependencies
|
|
242
|
+
2. **Integration Tests**: Tests for interactions between modules
|
|
243
|
+
3. **Adapter Tests**: Tests for framework-specific adapters
|
|
244
|
+
|
|
245
|
+
### Mock Strategy
|
|
246
|
+
|
|
247
|
+
- Dropbox API calls are mocked using Jest mock functions
|
|
248
|
+
- File system operations are mocked to avoid touching real files
|
|
249
|
+
- Socket.IO is mocked to test event emission and handling
|
|
250
|
+
|
|
251
|
+
### Test Coverage
|
|
252
|
+
|
|
253
|
+
We aim for high test coverage, especially for the core functionality:
|
|
254
|
+
|
|
255
|
+
| Module | Coverage |
|
|
256
|
+
| -------- | -------- |
|
|
257
|
+
| Core | >90% |
|
|
258
|
+
| Auth | >95% |
|
|
259
|
+
| Sync | >90% |
|
|
260
|
+
| Socket | >90% |
|
|
261
|
+
| Adapters | >85% |
|
|
262
|
+
|
|
263
|
+
## Framework-Specific Usage
|
|
264
|
+
|
|
265
|
+
### Next.js
|
|
266
|
+
|
|
267
|
+
```typescript
|
|
268
|
+
// In your component
|
|
269
|
+
import { useNextDropboxSync } from 'dropbox-sync'
|
|
270
|
+
|
|
271
|
+
export function DropboxComponent() {
|
|
272
|
+
// Initialize client
|
|
273
|
+
const dropboxSync = useNextDropboxSync({
|
|
274
|
+
clientId: process.env.NEXT_PUBLIC_DROPBOX_APP_KEY,
|
|
275
|
+
})
|
|
276
|
+
|
|
277
|
+
// Connect to socket for real-time updates
|
|
278
|
+
useEffect(() => {
|
|
279
|
+
dropboxSync.socket.connect()
|
|
280
|
+
dropboxSync.socket.on('sync:progress', handleProgress)
|
|
281
|
+
|
|
282
|
+
return () => {
|
|
283
|
+
dropboxSync.socket.disconnect()
|
|
284
|
+
}
|
|
285
|
+
}, [])
|
|
286
|
+
|
|
287
|
+
// Start sync
|
|
288
|
+
const handleSync = () => {
|
|
289
|
+
// This will trigger the server-side sync through Socket.IO
|
|
290
|
+
dropboxSync.socket.emit('dropbox:sync')
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
return <button onClick={handleSync}>Sync with Dropbox</button>
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// In your API route
|
|
297
|
+
import { createNextDropboxApiHandlers } from 'dropbox-sync'
|
|
298
|
+
|
|
299
|
+
const handlers = createNextDropboxApiHandlers()
|
|
300
|
+
|
|
301
|
+
export async function GET(request) {
|
|
302
|
+
return handlers.status()
|
|
303
|
+
}
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
### Nuxt.js
|
|
307
|
+
|
|
308
|
+
The Nuxt adapter leverages Nuxt's runtime config system for app settings and uses H3 (Nitro's HTTP server) utilities for handling requests and cookies. It's designed to work seamlessly with Nuxt 3's composition API and server routes.
|
|
309
|
+
|
|
310
|
+
To use this adapter in a Nuxt project, developers would:
|
|
311
|
+
|
|
312
|
+
1. Add runtime config in their nuxt.config.ts:
|
|
313
|
+
|
|
314
|
+
```typescript
|
|
315
|
+
export default defineNuxtConfig({
|
|
316
|
+
runtimeConfig: {
|
|
317
|
+
// Private keys
|
|
318
|
+
dropboxAppSecret: process.env.DROPBOX_APP_SECRET,
|
|
319
|
+
dropboxRedirectUri: process.env.DROPBOX_REDIRECT_URI,
|
|
320
|
+
|
|
321
|
+
// Public keys
|
|
322
|
+
public: {
|
|
323
|
+
dropboxAppKey: process.env.DROPBOX_APP_KEY,
|
|
324
|
+
appUrl: process.env.APP_URL || 'http://localhost:3000',
|
|
325
|
+
},
|
|
326
|
+
},
|
|
327
|
+
})
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
2. Create a plugin using the example provided
|
|
331
|
+
3. Set up API routes using the handlers from `createNuxtApiHandlers()`
|
|
332
|
+
|
|
333
|
+
```typescript
|
|
334
|
+
// In your plugins/dropbox.ts
|
|
335
|
+
import { useNuxtDropboxSync } from 'dropbox-sync'
|
|
336
|
+
import { defineNuxtPlugin } from 'nuxt/app'
|
|
337
|
+
|
|
338
|
+
export default defineNuxtPlugin((nuxtApp) => {
|
|
339
|
+
// Create the Dropbox client
|
|
340
|
+
const dropboxSync = useNuxtDropboxSync()
|
|
341
|
+
|
|
342
|
+
// Provide the client to the app
|
|
343
|
+
return {
|
|
344
|
+
provide: {
|
|
345
|
+
dropbox: dropboxSync
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
})
|
|
349
|
+
|
|
350
|
+
// In your Vue component
|
|
351
|
+
<script setup>
|
|
352
|
+
import { ref, onMounted, onBeforeUnmount } from 'vue'
|
|
353
|
+
|
|
354
|
+
const { $dropbox } = useNuxtApp()
|
|
355
|
+
const syncProgress = ref(0)
|
|
356
|
+
|
|
357
|
+
// Handle progress updates
|
|
358
|
+
const handleProgress = (data) => {
|
|
359
|
+
syncProgress.value = data.progress
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// Connect to socket
|
|
363
|
+
onMounted(() => {
|
|
364
|
+
$dropbox.socket.connect()
|
|
365
|
+
$dropbox.socket.on('sync:progress', handleProgress)
|
|
366
|
+
})
|
|
367
|
+
|
|
368
|
+
// Clean up on unmount
|
|
369
|
+
onBeforeUnmount(() => {
|
|
370
|
+
$dropbox.socket.disconnect()
|
|
371
|
+
})
|
|
372
|
+
|
|
373
|
+
// Start sync
|
|
374
|
+
const startSync = () => {
|
|
375
|
+
$dropbox.socket.emit('dropbox:sync')
|
|
376
|
+
}
|
|
377
|
+
</script>
|
|
378
|
+
|
|
379
|
+
<template>
|
|
380
|
+
<div>
|
|
381
|
+
<button @click="startSync">Sync with Dropbox</button>
|
|
382
|
+
<progress :value="syncProgress" max="100"></progress>
|
|
383
|
+
</div>
|
|
384
|
+
</template>
|
|
385
|
+
|
|
386
|
+
// In your server/api/dropbox/[...].ts
|
|
387
|
+
import { createNuxtApiHandlers } from 'dropbox-sync'
|
|
388
|
+
import { defineEventHandler } from 'h3'
|
|
389
|
+
|
|
390
|
+
// Create handlers
|
|
391
|
+
const handlers = createNuxtApiHandlers()
|
|
392
|
+
|
|
393
|
+
export default defineEventHandler(async (event) => {
|
|
394
|
+
// Handle different endpoints
|
|
395
|
+
const path = event.path || ''
|
|
396
|
+
|
|
397
|
+
if (path.endsWith('/status')) {
|
|
398
|
+
return await handlers.status(event)
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
if (path.endsWith('/auth')) {
|
|
402
|
+
return await handlers.oauthStart(event)
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
if (path.endsWith('/auth/callback')) {
|
|
406
|
+
return await handlers.oauthCallback(event)
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
if (path.endsWith('/logout')) {
|
|
410
|
+
return await handlers.logout(event)
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
return { error: 'Not found' }
|
|
414
|
+
})
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
### SvelteKit
|
|
418
|
+
|
|
419
|
+
```typescript
|
|
420
|
+
// In your store
|
|
421
|
+
import { useSvelteDropboxSync } from 'dropbox-sync'
|
|
422
|
+
import { writable } from 'svelte/store'
|
|
423
|
+
|
|
424
|
+
// Create store
|
|
425
|
+
export function createDropboxStore() {
|
|
426
|
+
const dropboxSync = useSvelteDropboxSync({
|
|
427
|
+
clientId: import.meta.env.VITE_DROPBOX_APP_KEY,
|
|
428
|
+
})
|
|
429
|
+
|
|
430
|
+
const progress = writable(0)
|
|
431
|
+
|
|
432
|
+
// Set up socket listeners
|
|
433
|
+
dropboxSync.socket.connect()
|
|
434
|
+
dropboxSync.socket.on('sync:progress', (data) => {
|
|
435
|
+
progress.set(data.progress)
|
|
436
|
+
})
|
|
437
|
+
|
|
438
|
+
return {
|
|
439
|
+
progress: { subscribe: progress.subscribe },
|
|
440
|
+
startSync: () => {
|
|
441
|
+
dropboxSync.socket.emit('dropbox:sync')
|
|
442
|
+
},
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
### Angular
|
|
448
|
+
|
|
449
|
+
```typescript
|
|
450
|
+
// In your service
|
|
451
|
+
import { DropboxSyncService, getCredentialsFromEnvironment } from 'dropbox-sync'
|
|
452
|
+
import { environment } from '../environments/environment'
|
|
453
|
+
|
|
454
|
+
@Injectable({ providedIn: 'root' })
|
|
455
|
+
export class DropboxService {
|
|
456
|
+
constructor(private dropboxSyncService: DropboxSyncService) {
|
|
457
|
+
// Initialize the service
|
|
458
|
+
this.dropboxSyncService.initialize(
|
|
459
|
+
getCredentialsFromEnvironment(environment)
|
|
460
|
+
)
|
|
461
|
+
|
|
462
|
+
// Listen for socket events
|
|
463
|
+
const socketEvents = this.dropboxSyncService.setupSocketListeners()
|
|
464
|
+
socketEvents.subscribe((event) => console.log(event))
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
startSync() {
|
|
468
|
+
return this.dropboxSyncService.startSync()
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
## API Reference
|
|
474
|
+
|
|
475
|
+
### Core Client
|
|
476
|
+
|
|
477
|
+
- `createDropboxSyncClient(credentials)` - Creates a new client instance
|
|
478
|
+
|
|
479
|
+
### Auth Methods
|
|
480
|
+
|
|
481
|
+
- `getAuthUrl(redirectUri, state?)` - Generate an OAuth authentication URL
|
|
482
|
+
- `exchangeCodeForToken(code, redirectUri)` - Exchange authorization code for access token
|
|
483
|
+
- `refreshAccessToken()` - Refresh an expired access token
|
|
484
|
+
|
|
485
|
+
### Sync Methods
|
|
486
|
+
|
|
487
|
+
- `scanLocalFiles(dir?)` - Scan local directory for files
|
|
488
|
+
- `scanDropboxFiles(dir?)` - Scan Dropbox folder for files
|
|
489
|
+
- `createSyncQueue(options?)` - Create upload/download queues
|
|
490
|
+
- `syncFiles(options?)` - Synchronize files between local and Dropbox
|
|
491
|
+
- `cancelSync()` - Cancel an ongoing synchronization
|
|
492
|
+
|
|
493
|
+
### Socket Methods
|
|
494
|
+
|
|
495
|
+
- `connect()` - Connect to Socket.IO
|
|
496
|
+
- `disconnect()` - Disconnect from Socket.IO
|
|
497
|
+
- `on(event, handler)` - Listen for an event
|
|
498
|
+
- `off(event)` - Remove event listener
|
|
499
|
+
- `emit(event, ...args)` - Emit an event
|
|
500
|
+
|
|
501
|
+
## Socket Events
|
|
502
|
+
|
|
503
|
+
- `sync:progress` - Emitted during sync with progress information
|
|
504
|
+
- `sync:queue` - Emitted at the start of sync with queue information
|
|
505
|
+
- `sync:complete` - Emitted when sync is complete
|
|
506
|
+
- `sync:error` - Emitted when an error occurs during sync
|
|
507
|
+
|
|
508
|
+
## Configuration Options
|
|
509
|
+
|
|
510
|
+
```typescript
|
|
511
|
+
interface SyncOptions {
|
|
512
|
+
localDir: string // Local directory path
|
|
513
|
+
dropboxDir?: string // Dropbox folder path
|
|
514
|
+
fileTypes?: RegExp // File types to sync (default: images and JSON)
|
|
515
|
+
progressCallback?: (progress: SyncProgress) => void
|
|
516
|
+
}
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
## License
|
|
520
|
+
|
|
521
|
+
MIT
|