@hasna/connectors 0.5.0 → 0.5.2
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/bin/index.js +147 -6
- package/bin/mcp.js +92 -1
- package/bin/serve.js +91 -0
- package/connectors/connect-ably/.env.example +11 -0
- package/connectors/connect-ably/CLAUDE.md +111 -0
- package/connectors/connect-ably/README.md +193 -0
- package/connectors/connect-ably/package.json +54 -0
- package/connectors/connect-ably/scripts/release.ts +179 -0
- package/connectors/connect-ably/src/api/channels.ts +33 -0
- package/connectors/connect-ably/src/api/client.ts +203 -0
- package/connectors/connect-ably/src/api/index.ts +59 -0
- package/connectors/connect-ably/src/api/messages.ts +48 -0
- package/connectors/connect-ably/src/api/presence.ts +39 -0
- package/connectors/connect-ably/src/api/stats.ts +29 -0
- package/connectors/connect-ably/src/cli/index.ts +397 -0
- package/connectors/connect-ably/src/index.ts +102 -0
- package/connectors/connect-ably/src/types/index.ts +294 -0
- package/connectors/connect-ably/src/utils/auth.ts +274 -0
- package/connectors/connect-ably/src/utils/bulk.ts +212 -0
- package/connectors/connect-ably/src/utils/config.ts +323 -0
- package/connectors/connect-ably/src/utils/output.ts +175 -0
- package/connectors/connect-ably/src/utils/settings.ts +114 -0
- package/connectors/connect-ably/src/utils/storage.ts +198 -0
- package/connectors/connect-ably/tsconfig.json +16 -0
- package/connectors/connect-box/.env.example +11 -0
- package/connectors/connect-box/CLAUDE.md +272 -0
- package/connectors/connect-box/README.md +193 -0
- package/connectors/connect-box/package.json +51 -0
- package/connectors/connect-box/scripts/release.ts +179 -0
- package/connectors/connect-box/src/api/client.ts +213 -0
- package/connectors/connect-box/src/api/example.ts +48 -0
- package/connectors/connect-box/src/api/index.ts +51 -0
- package/connectors/connect-box/src/cli/index.ts +254 -0
- package/connectors/connect-box/src/index.ts +103 -0
- package/connectors/connect-box/src/types/index.ts +237 -0
- package/connectors/connect-box/src/utils/auth.ts +274 -0
- package/connectors/connect-box/src/utils/bulk.ts +212 -0
- package/connectors/connect-box/src/utils/config.ts +326 -0
- package/connectors/connect-box/src/utils/output.ts +175 -0
- package/connectors/connect-box/src/utils/settings.ts +114 -0
- package/connectors/connect-box/src/utils/storage.ts +198 -0
- package/connectors/connect-box/tsconfig.json +16 -0
- package/connectors/connect-clearbit/.env.example +11 -0
- package/connectors/connect-clearbit/CLAUDE.md +272 -0
- package/connectors/connect-clearbit/README.md +193 -0
- package/connectors/connect-clearbit/package.json +51 -0
- package/connectors/connect-clearbit/scripts/release.ts +179 -0
- package/connectors/connect-clearbit/src/api/client.ts +213 -0
- package/connectors/connect-clearbit/src/api/example.ts +48 -0
- package/connectors/connect-clearbit/src/api/index.ts +51 -0
- package/connectors/connect-clearbit/src/cli/index.ts +254 -0
- package/connectors/connect-clearbit/src/index.ts +103 -0
- package/connectors/connect-clearbit/src/types/index.ts +237 -0
- package/connectors/connect-clearbit/src/utils/auth.ts +274 -0
- package/connectors/connect-clearbit/src/utils/bulk.ts +212 -0
- package/connectors/connect-clearbit/src/utils/config.ts +326 -0
- package/connectors/connect-clearbit/src/utils/output.ts +175 -0
- package/connectors/connect-clearbit/src/utils/settings.ts +114 -0
- package/connectors/connect-clearbit/src/utils/storage.ts +198 -0
- package/connectors/connect-clearbit/tsconfig.json +16 -0
- package/connectors/connect-coda/.env.example +11 -0
- package/connectors/connect-coda/CLAUDE.md +272 -0
- package/connectors/connect-coda/README.md +193 -0
- package/connectors/connect-coda/package.json +51 -0
- package/connectors/connect-coda/scripts/release.ts +179 -0
- package/connectors/connect-coda/src/api/client.ts +213 -0
- package/connectors/connect-coda/src/api/example.ts +48 -0
- package/connectors/connect-coda/src/api/index.ts +51 -0
- package/connectors/connect-coda/src/cli/index.ts +254 -0
- package/connectors/connect-coda/src/index.ts +103 -0
- package/connectors/connect-coda/src/types/index.ts +237 -0
- package/connectors/connect-coda/src/utils/auth.ts +274 -0
- package/connectors/connect-coda/src/utils/bulk.ts +212 -0
- package/connectors/connect-coda/src/utils/config.ts +326 -0
- package/connectors/connect-coda/src/utils/output.ts +175 -0
- package/connectors/connect-coda/src/utils/settings.ts +114 -0
- package/connectors/connect-coda/src/utils/storage.ts +198 -0
- package/connectors/connect-coda/tsconfig.json +16 -0
- package/connectors/connect-dropbox/.env.example +11 -0
- package/connectors/connect-dropbox/CLAUDE.md +119 -0
- package/connectors/connect-dropbox/README.md +193 -0
- package/connectors/connect-dropbox/package.json +51 -0
- package/connectors/connect-dropbox/src/api/client.ts +222 -0
- package/connectors/connect-dropbox/src/api/index.ts +395 -0
- package/connectors/connect-dropbox/src/cli/index.ts +627 -0
- package/connectors/connect-dropbox/src/index.ts +20 -0
- package/connectors/connect-dropbox/src/types/index.ts +516 -0
- package/connectors/connect-dropbox/src/utils/config.ts +197 -0
- package/connectors/connect-dropbox/tsconfig.json +16 -0
- package/connectors/connect-linode/.env.example +11 -0
- package/connectors/connect-linode/CLAUDE.md +272 -0
- package/connectors/connect-linode/README.md +193 -0
- package/connectors/connect-linode/package.json +51 -0
- package/connectors/connect-linode/scripts/release.ts +179 -0
- package/connectors/connect-linode/src/api/client.ts +213 -0
- package/connectors/connect-linode/src/api/example.ts +48 -0
- package/connectors/connect-linode/src/api/index.ts +51 -0
- package/connectors/connect-linode/src/cli/index.ts +254 -0
- package/connectors/connect-linode/src/index.ts +103 -0
- package/connectors/connect-linode/src/types/index.ts +237 -0
- package/connectors/connect-linode/src/utils/auth.ts +274 -0
- package/connectors/connect-linode/src/utils/bulk.ts +212 -0
- package/connectors/connect-linode/src/utils/config.ts +326 -0
- package/connectors/connect-linode/src/utils/output.ts +175 -0
- package/connectors/connect-linode/src/utils/settings.ts +114 -0
- package/connectors/connect-linode/src/utils/storage.ts +198 -0
- package/connectors/connect-linode/tsconfig.json +16 -0
- package/connectors/connect-mailgun/.env.example +11 -0
- package/connectors/connect-mailgun/CLAUDE.md +272 -0
- package/connectors/connect-mailgun/README.md +193 -0
- package/connectors/connect-mailgun/package.json +51 -0
- package/connectors/connect-mailgun/scripts/release.ts +179 -0
- package/connectors/connect-mailgun/src/api/client.ts +213 -0
- package/connectors/connect-mailgun/src/api/example.ts +48 -0
- package/connectors/connect-mailgun/src/api/index.ts +51 -0
- package/connectors/connect-mailgun/src/cli/index.ts +254 -0
- package/connectors/connect-mailgun/src/index.ts +103 -0
- package/connectors/connect-mailgun/src/types/index.ts +237 -0
- package/connectors/connect-mailgun/src/utils/auth.ts +274 -0
- package/connectors/connect-mailgun/src/utils/bulk.ts +212 -0
- package/connectors/connect-mailgun/src/utils/config.ts +326 -0
- package/connectors/connect-mailgun/src/utils/output.ts +175 -0
- package/connectors/connect-mailgun/src/utils/settings.ts +114 -0
- package/connectors/connect-mailgun/src/utils/storage.ts +198 -0
- package/connectors/connect-mailgun/tsconfig.json +16 -0
- package/connectors/connect-messagebird/.env.example +11 -0
- package/connectors/connect-messagebird/CLAUDE.md +272 -0
- package/connectors/connect-messagebird/README.md +193 -0
- package/connectors/connect-messagebird/package.json +51 -0
- package/connectors/connect-messagebird/scripts/release.ts +179 -0
- package/connectors/connect-messagebird/src/api/client.ts +213 -0
- package/connectors/connect-messagebird/src/api/example.ts +48 -0
- package/connectors/connect-messagebird/src/api/index.ts +51 -0
- package/connectors/connect-messagebird/src/cli/index.ts +254 -0
- package/connectors/connect-messagebird/src/index.ts +103 -0
- package/connectors/connect-messagebird/src/types/index.ts +237 -0
- package/connectors/connect-messagebird/src/utils/auth.ts +274 -0
- package/connectors/connect-messagebird/src/utils/bulk.ts +212 -0
- package/connectors/connect-messagebird/src/utils/config.ts +326 -0
- package/connectors/connect-messagebird/src/utils/output.ts +175 -0
- package/connectors/connect-messagebird/src/utils/settings.ts +114 -0
- package/connectors/connect-messagebird/src/utils/storage.ts +198 -0
- package/connectors/connect-messagebird/tsconfig.json +16 -0
- package/connectors/connect-miro/.env.example +11 -0
- package/connectors/connect-miro/CLAUDE.md +272 -0
- package/connectors/connect-miro/README.md +193 -0
- package/connectors/connect-miro/package.json +51 -0
- package/connectors/connect-miro/scripts/release.ts +179 -0
- package/connectors/connect-miro/src/api/client.ts +213 -0
- package/connectors/connect-miro/src/api/example.ts +48 -0
- package/connectors/connect-miro/src/api/index.ts +51 -0
- package/connectors/connect-miro/src/cli/index.ts +254 -0
- package/connectors/connect-miro/src/index.ts +103 -0
- package/connectors/connect-miro/src/types/index.ts +237 -0
- package/connectors/connect-miro/src/utils/auth.ts +274 -0
- package/connectors/connect-miro/src/utils/bulk.ts +212 -0
- package/connectors/connect-miro/src/utils/config.ts +326 -0
- package/connectors/connect-miro/src/utils/output.ts +175 -0
- package/connectors/connect-miro/src/utils/settings.ts +114 -0
- package/connectors/connect-miro/src/utils/storage.ts +198 -0
- package/connectors/connect-miro/tsconfig.json +16 -0
- package/connectors/connect-monday/.env.example +11 -0
- package/connectors/connect-monday/CLAUDE.md +128 -0
- package/connectors/connect-monday/README.md +193 -0
- package/connectors/connect-monday/package.json +52 -0
- package/connectors/connect-monday/src/api/client.ts +59 -0
- package/connectors/connect-monday/src/api/index.ts +539 -0
- package/connectors/connect-monday/src/cli/index.ts +479 -0
- package/connectors/connect-monday/src/index.ts +19 -0
- package/connectors/connect-monday/src/types/index.ts +274 -0
- package/connectors/connect-monday/src/utils/config.ts +197 -0
- package/connectors/connect-monday/src/utils/output.ts +119 -0
- package/connectors/connect-monday/tsconfig.json +16 -0
- package/connectors/connect-pipedrive/.env.example +11 -0
- package/connectors/connect-pipedrive/CLAUDE.md +128 -0
- package/connectors/connect-pipedrive/README.md +193 -0
- package/connectors/connect-pipedrive/package.json +52 -0
- package/connectors/connect-pipedrive/src/api/client.ts +121 -0
- package/connectors/connect-pipedrive/src/api/index.ts +306 -0
- package/connectors/connect-pipedrive/src/cli/index.ts +824 -0
- package/connectors/connect-pipedrive/src/index.ts +19 -0
- package/connectors/connect-pipedrive/src/types/index.ts +335 -0
- package/connectors/connect-pipedrive/src/utils/config.ts +171 -0
- package/connectors/connect-pipedrive/src/utils/output.ts +119 -0
- package/connectors/connect-pipedrive/tsconfig.json +16 -0
- package/connectors/connect-pusher/.env.example +11 -0
- package/connectors/connect-pusher/CLAUDE.md +272 -0
- package/connectors/connect-pusher/README.md +193 -0
- package/connectors/connect-pusher/package.json +51 -0
- package/connectors/connect-pusher/scripts/release.ts +179 -0
- package/connectors/connect-pusher/src/api/client.ts +213 -0
- package/connectors/connect-pusher/src/api/example.ts +48 -0
- package/connectors/connect-pusher/src/api/index.ts +51 -0
- package/connectors/connect-pusher/src/cli/index.ts +254 -0
- package/connectors/connect-pusher/src/index.ts +103 -0
- package/connectors/connect-pusher/src/types/index.ts +237 -0
- package/connectors/connect-pusher/src/utils/auth.ts +274 -0
- package/connectors/connect-pusher/src/utils/bulk.ts +212 -0
- package/connectors/connect-pusher/src/utils/config.ts +326 -0
- package/connectors/connect-pusher/src/utils/output.ts +175 -0
- package/connectors/connect-pusher/src/utils/settings.ts +114 -0
- package/connectors/connect-pusher/src/utils/storage.ts +198 -0
- package/connectors/connect-pusher/tsconfig.json +16 -0
- package/connectors/connect-vonage/.env.example +11 -0
- package/connectors/connect-vonage/CLAUDE.md +272 -0
- package/connectors/connect-vonage/README.md +193 -0
- package/connectors/connect-vonage/package.json +51 -0
- package/connectors/connect-vonage/scripts/release.ts +179 -0
- package/connectors/connect-vonage/src/api/client.ts +213 -0
- package/connectors/connect-vonage/src/api/example.ts +48 -0
- package/connectors/connect-vonage/src/api/index.ts +51 -0
- package/connectors/connect-vonage/src/cli/index.ts +254 -0
- package/connectors/connect-vonage/src/index.ts +103 -0
- package/connectors/connect-vonage/src/types/index.ts +237 -0
- package/connectors/connect-vonage/src/utils/auth.ts +274 -0
- package/connectors/connect-vonage/src/utils/bulk.ts +212 -0
- package/connectors/connect-vonage/src/utils/config.ts +326 -0
- package/connectors/connect-vonage/src/utils/output.ts +175 -0
- package/connectors/connect-vonage/src/utils/settings.ts +114 -0
- package/connectors/connect-vonage/src/utils/storage.ts +198 -0
- package/connectors/connect-vonage/tsconfig.json +16 -0
- package/dist/index.js +91 -0
- package/package.json +1 -1
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import type { DropboxConfig, OutputFormat, DropboxErrorResponse } from '../types';
|
|
2
|
+
import { DropboxApiError } from '../types';
|
|
3
|
+
|
|
4
|
+
// Dropbox API endpoints
|
|
5
|
+
const API_BASE_URL = 'https://api.dropboxapi.com/2';
|
|
6
|
+
const CONTENT_BASE_URL = 'https://content.dropboxapi.com/2';
|
|
7
|
+
|
|
8
|
+
export interface RequestOptions {
|
|
9
|
+
method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
|
|
10
|
+
body?: Record<string, unknown> | unknown[] | string;
|
|
11
|
+
headers?: Record<string, string>;
|
|
12
|
+
format?: OutputFormat;
|
|
13
|
+
endpoint?: 'api' | 'content'; // api for metadata, content for uploads/downloads
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export class DropboxClient {
|
|
17
|
+
private readonly accessToken: string;
|
|
18
|
+
|
|
19
|
+
constructor(config: DropboxConfig) {
|
|
20
|
+
if (!config.accessToken) {
|
|
21
|
+
throw new Error('Access token is required');
|
|
22
|
+
}
|
|
23
|
+
this.accessToken = config.accessToken;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
private getBaseUrl(endpoint: 'api' | 'content' = 'api'): string {
|
|
27
|
+
return endpoint === 'content' ? CONTENT_BASE_URL : API_BASE_URL;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Make an authenticated request to Dropbox API
|
|
32
|
+
* Uses Bearer token authentication
|
|
33
|
+
*/
|
|
34
|
+
async request<T>(path: string, options: RequestOptions = {}): Promise<T> {
|
|
35
|
+
const { method = 'POST', body, headers = {}, endpoint = 'api' } = options;
|
|
36
|
+
|
|
37
|
+
const url = `${this.getBaseUrl(endpoint)}${path}`;
|
|
38
|
+
|
|
39
|
+
const requestHeaders: Record<string, string> = {
|
|
40
|
+
'Authorization': `Bearer ${this.accessToken}`,
|
|
41
|
+
...headers,
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
// Dropbox API uses JSON in the body for regular API calls
|
|
45
|
+
if (endpoint === 'api' && body) {
|
|
46
|
+
requestHeaders['Content-Type'] = 'application/json';
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const fetchOptions: RequestInit = {
|
|
50
|
+
method,
|
|
51
|
+
headers: requestHeaders,
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
if (body && endpoint === 'api') {
|
|
55
|
+
fetchOptions.body = typeof body === 'string' ? body : JSON.stringify(body);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const response = await fetch(url, fetchOptions);
|
|
59
|
+
|
|
60
|
+
// Handle 204 No Content
|
|
61
|
+
if (response.status === 204) {
|
|
62
|
+
return {} as T;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Parse response
|
|
66
|
+
let data: unknown;
|
|
67
|
+
const contentType = response.headers.get('content-type') || '';
|
|
68
|
+
|
|
69
|
+
if (contentType.includes('application/json')) {
|
|
70
|
+
const text = await response.text();
|
|
71
|
+
if (text) {
|
|
72
|
+
try {
|
|
73
|
+
data = JSON.parse(text);
|
|
74
|
+
} catch {
|
|
75
|
+
data = text;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
} else {
|
|
79
|
+
data = await response.text();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Handle errors
|
|
83
|
+
if (!response.ok) {
|
|
84
|
+
let errorMessage: string;
|
|
85
|
+
let errorTag: string | undefined;
|
|
86
|
+
let userMessage: string | undefined;
|
|
87
|
+
|
|
88
|
+
if (typeof data === 'object' && data !== null) {
|
|
89
|
+
const errorData = data as DropboxErrorResponse;
|
|
90
|
+
errorMessage = errorData.error_summary || JSON.stringify(data);
|
|
91
|
+
errorTag = errorData.error?.['.tag'];
|
|
92
|
+
userMessage = errorData.user_message?.text;
|
|
93
|
+
} else {
|
|
94
|
+
errorMessage = String(data || response.statusText);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
throw new DropboxApiError(errorMessage, response.status, errorTag, userMessage);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return data as T;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Make a content upload request (for file uploads)
|
|
105
|
+
*/
|
|
106
|
+
async uploadRequest<T>(path: string, content: Uint8Array | string, arg: Record<string, unknown>): Promise<T> {
|
|
107
|
+
const url = `${CONTENT_BASE_URL}${path}`;
|
|
108
|
+
|
|
109
|
+
const requestHeaders: Record<string, string> = {
|
|
110
|
+
'Authorization': `Bearer ${this.accessToken}`,
|
|
111
|
+
'Content-Type': 'application/octet-stream',
|
|
112
|
+
'Dropbox-API-Arg': JSON.stringify(arg),
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const response = await fetch(url, {
|
|
116
|
+
method: 'POST',
|
|
117
|
+
headers: requestHeaders,
|
|
118
|
+
body: content,
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
// Parse response
|
|
122
|
+
let data: unknown;
|
|
123
|
+
const contentType = response.headers.get('content-type') || '';
|
|
124
|
+
|
|
125
|
+
if (contentType.includes('application/json')) {
|
|
126
|
+
const text = await response.text();
|
|
127
|
+
if (text) {
|
|
128
|
+
try {
|
|
129
|
+
data = JSON.parse(text);
|
|
130
|
+
} catch {
|
|
131
|
+
data = text;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
} else {
|
|
135
|
+
data = await response.text();
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Handle errors
|
|
139
|
+
if (!response.ok) {
|
|
140
|
+
let errorMessage: string;
|
|
141
|
+
let errorTag: string | undefined;
|
|
142
|
+
|
|
143
|
+
if (typeof data === 'object' && data !== null) {
|
|
144
|
+
const errorData = data as DropboxErrorResponse;
|
|
145
|
+
errorMessage = errorData.error_summary || JSON.stringify(data);
|
|
146
|
+
errorTag = errorData.error?.['.tag'];
|
|
147
|
+
} else {
|
|
148
|
+
errorMessage = String(data || response.statusText);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
throw new DropboxApiError(errorMessage, response.status, errorTag);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return data as T;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Make a content download request (for file downloads)
|
|
159
|
+
* Returns the file content and metadata
|
|
160
|
+
*/
|
|
161
|
+
async downloadRequest(path: string, arg: Record<string, unknown>): Promise<{ content: ArrayBuffer; metadata: unknown }> {
|
|
162
|
+
const url = `${CONTENT_BASE_URL}${path}`;
|
|
163
|
+
|
|
164
|
+
const requestHeaders: Record<string, string> = {
|
|
165
|
+
'Authorization': `Bearer ${this.accessToken}`,
|
|
166
|
+
'Dropbox-API-Arg': JSON.stringify(arg),
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
const response = await fetch(url, {
|
|
170
|
+
method: 'POST',
|
|
171
|
+
headers: requestHeaders,
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
// Handle errors
|
|
175
|
+
if (!response.ok) {
|
|
176
|
+
const text = await response.text();
|
|
177
|
+
let errorMessage: string;
|
|
178
|
+
let errorTag: string | undefined;
|
|
179
|
+
|
|
180
|
+
try {
|
|
181
|
+
const errorData = JSON.parse(text) as DropboxErrorResponse;
|
|
182
|
+
errorMessage = errorData.error_summary || text;
|
|
183
|
+
errorTag = errorData.error?.['.tag'];
|
|
184
|
+
} catch {
|
|
185
|
+
errorMessage = text || response.statusText;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
throw new DropboxApiError(errorMessage, response.status, errorTag);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Get metadata from header
|
|
192
|
+
const metadataHeader = response.headers.get('Dropbox-API-Result');
|
|
193
|
+
let metadata: unknown = {};
|
|
194
|
+
if (metadataHeader) {
|
|
195
|
+
try {
|
|
196
|
+
metadata = JSON.parse(metadataHeader);
|
|
197
|
+
} catch {
|
|
198
|
+
// Ignore parse errors
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const content = await response.arrayBuffer();
|
|
203
|
+
return { content, metadata };
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Shorthand for POST requests (most Dropbox API calls use POST)
|
|
208
|
+
*/
|
|
209
|
+
async post<T>(path: string, body?: Record<string, unknown> | object): Promise<T> {
|
|
210
|
+
return this.request<T>(path, { method: 'POST', body: body as Record<string, unknown> });
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Get a preview of the access token (for display/debugging)
|
|
215
|
+
*/
|
|
216
|
+
getAccessTokenPreview(): string {
|
|
217
|
+
if (this.accessToken.length > 10) {
|
|
218
|
+
return `${this.accessToken.substring(0, 6)}...${this.accessToken.substring(this.accessToken.length - 4)}`;
|
|
219
|
+
}
|
|
220
|
+
return '***';
|
|
221
|
+
}
|
|
222
|
+
}
|
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
DropboxConfig,
|
|
3
|
+
FileMetadata,
|
|
4
|
+
FolderMetadata,
|
|
5
|
+
Metadata,
|
|
6
|
+
ListFolderResult,
|
|
7
|
+
SearchV2Result,
|
|
8
|
+
SharedLinkMetadata,
|
|
9
|
+
SharedFolderMetadata,
|
|
10
|
+
ListSharedLinksResult,
|
|
11
|
+
ListFolderMembersResult,
|
|
12
|
+
Account,
|
|
13
|
+
SpaceUsage,
|
|
14
|
+
RelocationResult,
|
|
15
|
+
DeleteResult,
|
|
16
|
+
} from '../types';
|
|
17
|
+
import { DropboxClient } from './client';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Dropbox API wrapper
|
|
21
|
+
*/
|
|
22
|
+
export class Dropbox {
|
|
23
|
+
private readonly client: DropboxClient;
|
|
24
|
+
|
|
25
|
+
constructor(config: DropboxConfig) {
|
|
26
|
+
this.client = new DropboxClient(config);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Create a client from environment variables
|
|
31
|
+
*/
|
|
32
|
+
static fromEnv(): Dropbox {
|
|
33
|
+
const accessToken = process.env.DROPBOX_ACCESS_TOKEN || process.env.DROPBOX_TOKEN;
|
|
34
|
+
|
|
35
|
+
if (!accessToken) {
|
|
36
|
+
throw new Error('DROPBOX_ACCESS_TOKEN or DROPBOX_TOKEN environment variable is required');
|
|
37
|
+
}
|
|
38
|
+
return new Dropbox({ accessToken });
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Get a preview of the access token (for debugging)
|
|
43
|
+
*/
|
|
44
|
+
getAccessTokenPreview(): string {
|
|
45
|
+
return this.client.getAccessTokenPreview();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Get the underlying client for direct API access
|
|
50
|
+
*/
|
|
51
|
+
getClient(): DropboxClient {
|
|
52
|
+
return this.client;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// ============================================
|
|
56
|
+
// Files API
|
|
57
|
+
// ============================================
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Get metadata for a file or folder
|
|
61
|
+
*/
|
|
62
|
+
async getMetadata(path: string, params?: {
|
|
63
|
+
include_media_info?: boolean;
|
|
64
|
+
include_deleted?: boolean;
|
|
65
|
+
include_has_explicit_shared_members?: boolean;
|
|
66
|
+
include_property_groups?: 'property_template_ids';
|
|
67
|
+
}): Promise<Metadata> {
|
|
68
|
+
return this.client.post<Metadata>('/files/get_metadata', {
|
|
69
|
+
path,
|
|
70
|
+
...params,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* List folder contents
|
|
76
|
+
*/
|
|
77
|
+
async listFolder(path: string, params?: {
|
|
78
|
+
recursive?: boolean;
|
|
79
|
+
include_media_info?: boolean;
|
|
80
|
+
include_deleted?: boolean;
|
|
81
|
+
include_has_explicit_shared_members?: boolean;
|
|
82
|
+
include_mounted_folders?: boolean;
|
|
83
|
+
include_non_downloadable_files?: boolean;
|
|
84
|
+
limit?: number;
|
|
85
|
+
}): Promise<ListFolderResult> {
|
|
86
|
+
return this.client.post<ListFolderResult>('/files/list_folder', {
|
|
87
|
+
path,
|
|
88
|
+
...params,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Continue listing folder contents
|
|
94
|
+
*/
|
|
95
|
+
async listFolderContinue(cursor: string): Promise<ListFolderResult> {
|
|
96
|
+
return this.client.post<ListFolderResult>('/files/list_folder/continue', { cursor });
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Create a folder
|
|
101
|
+
*/
|
|
102
|
+
async createFolder(path: string, autorename?: boolean): Promise<FolderMetadata> {
|
|
103
|
+
const result = await this.client.post<{ metadata: FolderMetadata }>('/files/create_folder_v2', {
|
|
104
|
+
path,
|
|
105
|
+
autorename: autorename ?? false,
|
|
106
|
+
});
|
|
107
|
+
return result.metadata;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Delete a file or folder
|
|
112
|
+
*/
|
|
113
|
+
async delete(path: string): Promise<DeleteResult> {
|
|
114
|
+
return this.client.post<DeleteResult>('/files/delete_v2', { path });
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Permanently delete a file or folder
|
|
119
|
+
*/
|
|
120
|
+
async permanentlyDelete(path: string): Promise<void> {
|
|
121
|
+
await this.client.post('/files/permanently_delete', { path });
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Copy a file or folder
|
|
126
|
+
*/
|
|
127
|
+
async copy(fromPath: string, toPath: string, params?: {
|
|
128
|
+
autorename?: boolean;
|
|
129
|
+
allow_shared_folder?: boolean;
|
|
130
|
+
allow_ownership_transfer?: boolean;
|
|
131
|
+
}): Promise<RelocationResult> {
|
|
132
|
+
return this.client.post<RelocationResult>('/files/copy_v2', {
|
|
133
|
+
from_path: fromPath,
|
|
134
|
+
to_path: toPath,
|
|
135
|
+
...params,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Move a file or folder
|
|
141
|
+
*/
|
|
142
|
+
async move(fromPath: string, toPath: string, params?: {
|
|
143
|
+
autorename?: boolean;
|
|
144
|
+
allow_shared_folder?: boolean;
|
|
145
|
+
allow_ownership_transfer?: boolean;
|
|
146
|
+
}): Promise<RelocationResult> {
|
|
147
|
+
return this.client.post<RelocationResult>('/files/move_v2', {
|
|
148
|
+
from_path: fromPath,
|
|
149
|
+
to_path: toPath,
|
|
150
|
+
...params,
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Search for files and folders
|
|
156
|
+
*/
|
|
157
|
+
async search(query: string, params?: {
|
|
158
|
+
path?: string;
|
|
159
|
+
max_results?: number;
|
|
160
|
+
file_status?: 'active' | 'deleted';
|
|
161
|
+
filename_only?: boolean;
|
|
162
|
+
file_extensions?: string[];
|
|
163
|
+
file_categories?: Array<'image' | 'document' | 'pdf' | 'spreadsheet' | 'presentation' | 'audio' | 'video' | 'folder' | 'paper' | 'others'>;
|
|
164
|
+
}): Promise<SearchV2Result> {
|
|
165
|
+
return this.client.post<SearchV2Result>('/files/search_v2', {
|
|
166
|
+
query,
|
|
167
|
+
options: params ? {
|
|
168
|
+
path: params.path,
|
|
169
|
+
max_results: params.max_results,
|
|
170
|
+
file_status: params.file_status ? { '.tag': params.file_status } : undefined,
|
|
171
|
+
filename_only: params.filename_only,
|
|
172
|
+
file_extensions: params.file_extensions,
|
|
173
|
+
file_categories: params.file_categories?.map(c => ({ '.tag': c })),
|
|
174
|
+
} : undefined,
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Continue search
|
|
180
|
+
*/
|
|
181
|
+
async searchContinue(cursor: string): Promise<SearchV2Result> {
|
|
182
|
+
return this.client.post<SearchV2Result>('/files/search/continue_v2', { cursor });
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Upload a file (up to 150MB)
|
|
187
|
+
*/
|
|
188
|
+
async upload(path: string, content: Uint8Array | string, params?: {
|
|
189
|
+
mode?: 'add' | 'overwrite' | 'update';
|
|
190
|
+
autorename?: boolean;
|
|
191
|
+
mute?: boolean;
|
|
192
|
+
strict_conflict?: boolean;
|
|
193
|
+
}): Promise<FileMetadata> {
|
|
194
|
+
return this.client.uploadRequest<FileMetadata>('/files/upload', content, {
|
|
195
|
+
path,
|
|
196
|
+
mode: params?.mode ? { '.tag': params.mode } : { '.tag': 'add' },
|
|
197
|
+
autorename: params?.autorename ?? false,
|
|
198
|
+
mute: params?.mute ?? false,
|
|
199
|
+
strict_conflict: params?.strict_conflict ?? false,
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Download a file
|
|
205
|
+
*/
|
|
206
|
+
async download(path: string): Promise<{ content: ArrayBuffer; metadata: FileMetadata }> {
|
|
207
|
+
const result = await this.client.downloadRequest('/files/download', { path });
|
|
208
|
+
return {
|
|
209
|
+
content: result.content,
|
|
210
|
+
metadata: result.metadata as FileMetadata,
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Get a temporary link to download a file
|
|
216
|
+
*/
|
|
217
|
+
async getTemporaryLink(path: string): Promise<{ link: string; metadata: FileMetadata }> {
|
|
218
|
+
return this.client.post<{ link: string; metadata: FileMetadata }>('/files/get_temporary_link', { path });
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Get a preview of a file (PDF, images)
|
|
223
|
+
*/
|
|
224
|
+
async getPreview(path: string): Promise<{ content: ArrayBuffer; metadata: FileMetadata }> {
|
|
225
|
+
const result = await this.client.downloadRequest('/files/get_preview', { path });
|
|
226
|
+
return {
|
|
227
|
+
content: result.content,
|
|
228
|
+
metadata: result.metadata as FileMetadata,
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Get a thumbnail for an image
|
|
234
|
+
*/
|
|
235
|
+
async getThumbnail(path: string, params?: {
|
|
236
|
+
format?: 'jpeg' | 'png';
|
|
237
|
+
size?: 'w32h32' | 'w64h64' | 'w128h128' | 'w256h256' | 'w480h320' | 'w640h480' | 'w960h640' | 'w1024h768' | 'w2048h1536';
|
|
238
|
+
mode?: 'strict' | 'bestfit' | 'fitone_bestfit';
|
|
239
|
+
}): Promise<{ content: ArrayBuffer; metadata: FileMetadata }> {
|
|
240
|
+
const result = await this.client.downloadRequest('/files/get_thumbnail_v2', {
|
|
241
|
+
resource: { '.tag': 'path', path },
|
|
242
|
+
format: params?.format ? { '.tag': params.format } : { '.tag': 'jpeg' },
|
|
243
|
+
size: params?.size ? { '.tag': params.size } : { '.tag': 'w64h64' },
|
|
244
|
+
mode: params?.mode ? { '.tag': params.mode } : { '.tag': 'strict' },
|
|
245
|
+
});
|
|
246
|
+
return {
|
|
247
|
+
content: result.content,
|
|
248
|
+
metadata: result.metadata as FileMetadata,
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// ============================================
|
|
253
|
+
// Sharing API
|
|
254
|
+
// ============================================
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Create a shared link
|
|
258
|
+
*/
|
|
259
|
+
async createSharedLink(path: string, params?: {
|
|
260
|
+
short_url?: boolean;
|
|
261
|
+
pending_upload?: 'file' | 'folder';
|
|
262
|
+
}): Promise<SharedLinkMetadata> {
|
|
263
|
+
return this.client.post<SharedLinkMetadata>('/sharing/create_shared_link_with_settings', {
|
|
264
|
+
path,
|
|
265
|
+
settings: params,
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* List shared links
|
|
271
|
+
*/
|
|
272
|
+
async listSharedLinks(params?: {
|
|
273
|
+
path?: string;
|
|
274
|
+
cursor?: string;
|
|
275
|
+
direct_only?: boolean;
|
|
276
|
+
}): Promise<ListSharedLinksResult> {
|
|
277
|
+
return this.client.post<ListSharedLinksResult>('/sharing/list_shared_links', params || {});
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Get shared link metadata
|
|
282
|
+
*/
|
|
283
|
+
async getSharedLinkMetadata(url: string, params?: {
|
|
284
|
+
path?: string;
|
|
285
|
+
link_password?: string;
|
|
286
|
+
}): Promise<SharedLinkMetadata> {
|
|
287
|
+
return this.client.post<SharedLinkMetadata>('/sharing/get_shared_link_metadata', {
|
|
288
|
+
url,
|
|
289
|
+
...params,
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Revoke a shared link
|
|
295
|
+
*/
|
|
296
|
+
async revokeSharedLink(url: string): Promise<void> {
|
|
297
|
+
await this.client.post('/sharing/revoke_shared_link', { url });
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Share a folder
|
|
302
|
+
*/
|
|
303
|
+
async shareFolder(path: string, params?: {
|
|
304
|
+
force_async?: boolean;
|
|
305
|
+
acl_update_policy?: 'owner' | 'editors';
|
|
306
|
+
member_policy?: 'team' | 'anyone';
|
|
307
|
+
shared_link_policy?: 'anyone' | 'team' | 'members';
|
|
308
|
+
viewer_info_policy?: 'enabled' | 'disabled';
|
|
309
|
+
}): Promise<SharedFolderMetadata | { '.tag': 'async_job_id'; async_job_id: string }> {
|
|
310
|
+
const result = await this.client.post<SharedFolderMetadata | { '.tag': 'async_job_id'; async_job_id: string } | { '.tag': 'complete'; complete: SharedFolderMetadata }>('/sharing/share_folder', {
|
|
311
|
+
path,
|
|
312
|
+
...params,
|
|
313
|
+
});
|
|
314
|
+
if ((result as { '.tag': string })['?tag'] === 'complete') {
|
|
315
|
+
return (result as { '.tag': 'complete'; complete: SharedFolderMetadata }).complete;
|
|
316
|
+
}
|
|
317
|
+
return result as SharedFolderMetadata;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* List shared folders
|
|
322
|
+
*/
|
|
323
|
+
async listSharedFolders(params?: {
|
|
324
|
+
limit?: number;
|
|
325
|
+
actions?: Array<'change_options' | 'disable_viewer_info' | 'edit_contents' | 'enable_viewer_info' | 'invite_editor' | 'invite_viewer' | 'invite_viewer_no_comment' | 'relinquish_membership' | 'unmount' | 'unshare' | 'leave_a_copy' | 'share_link' | 'create_link' | 'set_access_inheritance'>;
|
|
326
|
+
}): Promise<{ entries: SharedFolderMetadata[]; cursor?: string }> {
|
|
327
|
+
return this.client.post('/sharing/list_folders', params || {});
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Get shared folder metadata
|
|
332
|
+
*/
|
|
333
|
+
async getSharedFolderMetadata(sharedFolderId: string): Promise<SharedFolderMetadata> {
|
|
334
|
+
return this.client.post<SharedFolderMetadata>('/sharing/get_folder_metadata', {
|
|
335
|
+
shared_folder_id: sharedFolderId,
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* List shared folder members
|
|
341
|
+
*/
|
|
342
|
+
async listSharedFolderMembers(sharedFolderId: string, params?: {
|
|
343
|
+
actions?: string[];
|
|
344
|
+
limit?: number;
|
|
345
|
+
}): Promise<ListFolderMembersResult> {
|
|
346
|
+
return this.client.post<ListFolderMembersResult>('/sharing/list_folder_members', {
|
|
347
|
+
shared_folder_id: sharedFolderId,
|
|
348
|
+
...params,
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Unshare a folder
|
|
354
|
+
*/
|
|
355
|
+
async unshareFolder(sharedFolderId: string, leaveACopy?: boolean): Promise<{ '.tag': 'complete' } | { '.tag': 'async_job_id'; async_job_id: string }> {
|
|
356
|
+
return this.client.post('/sharing/unshare_folder', {
|
|
357
|
+
shared_folder_id: sharedFolderId,
|
|
358
|
+
leave_a_copy: leaveACopy ?? false,
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// ============================================
|
|
363
|
+
// Users API
|
|
364
|
+
// ============================================
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Get current account
|
|
368
|
+
*/
|
|
369
|
+
async getCurrentAccount(): Promise<Account> {
|
|
370
|
+
return this.client.post<Account>('/users/get_current_account', null);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* Get space usage
|
|
375
|
+
*/
|
|
376
|
+
async getSpaceUsage(): Promise<SpaceUsage> {
|
|
377
|
+
return this.client.post<SpaceUsage>('/users/get_space_usage', null);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* Get account by account ID
|
|
382
|
+
*/
|
|
383
|
+
async getAccount(accountId: string): Promise<Account> {
|
|
384
|
+
return this.client.post<Account>('/users/get_account', { account_id: accountId });
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* Get multiple accounts
|
|
389
|
+
*/
|
|
390
|
+
async getAccountBatch(accountIds: string[]): Promise<Account[]> {
|
|
391
|
+
return this.client.post<Account[]>('/users/get_account_batch', { account_ids: accountIds });
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
export { DropboxClient } from './client';
|