@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,627 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import { Dropbox } from '../api';
|
|
5
|
+
import {
|
|
6
|
+
getAccessToken,
|
|
7
|
+
setAccessToken,
|
|
8
|
+
clearConfig,
|
|
9
|
+
getCurrentProfile,
|
|
10
|
+
setCurrentProfile,
|
|
11
|
+
listProfiles,
|
|
12
|
+
createProfile,
|
|
13
|
+
deleteProfile,
|
|
14
|
+
setProfileOverride,
|
|
15
|
+
getConfigDir,
|
|
16
|
+
} from '../utils/config';
|
|
17
|
+
import type { Metadata, FileMetadata, FolderMetadata } from '../types';
|
|
18
|
+
|
|
19
|
+
const program = new Command();
|
|
20
|
+
|
|
21
|
+
// Helper to get authenticated client
|
|
22
|
+
function getClient(): Dropbox {
|
|
23
|
+
const accessToken = getAccessToken();
|
|
24
|
+
if (!accessToken) {
|
|
25
|
+
console.error(chalk.red('Error: Not authenticated. Run "connect-dropbox auth set <token>" first or set DROPBOX_ACCESS_TOKEN.'));
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
return new Dropbox({ accessToken });
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Format file size
|
|
32
|
+
function formatSize(bytes: number): string {
|
|
33
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
34
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
35
|
+
if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
36
|
+
return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Format metadata for display
|
|
40
|
+
function formatMetadata(item: Metadata): string {
|
|
41
|
+
if (item['.tag'] === 'file') {
|
|
42
|
+
const file = item as FileMetadata;
|
|
43
|
+
return `${chalk.white(file.name)} ${chalk.gray(`(${formatSize(file.size)})`)}`;
|
|
44
|
+
} else if (item['.tag'] === 'folder') {
|
|
45
|
+
return chalk.blue(item.name + '/');
|
|
46
|
+
} else {
|
|
47
|
+
return chalk.gray(`[deleted] ${item.name}`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
program
|
|
52
|
+
.name('connect-dropbox')
|
|
53
|
+
.description('Dropbox connector - Manage files, folders, sharing, and team administration')
|
|
54
|
+
.version('0.0.1')
|
|
55
|
+
.option('--profile <name>', 'Use a specific profile')
|
|
56
|
+
.hook('preAction', (thisCommand) => {
|
|
57
|
+
const opts = thisCommand.opts();
|
|
58
|
+
if (opts.profile) {
|
|
59
|
+
setProfileOverride(opts.profile);
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// ============================================
|
|
64
|
+
// Auth Commands
|
|
65
|
+
// ============================================
|
|
66
|
+
|
|
67
|
+
const authCmd = program.command('auth').description('Authentication management');
|
|
68
|
+
|
|
69
|
+
authCmd
|
|
70
|
+
.command('set')
|
|
71
|
+
.description('Set access token for the current profile')
|
|
72
|
+
.argument('<token>', 'Dropbox access token')
|
|
73
|
+
.action((token: string) => {
|
|
74
|
+
setAccessToken(token);
|
|
75
|
+
console.log(chalk.green(`Access token saved to profile "${getCurrentProfile()}"`));
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
authCmd
|
|
79
|
+
.command('status')
|
|
80
|
+
.description('Check authentication status')
|
|
81
|
+
.action(async () => {
|
|
82
|
+
const token = getAccessToken();
|
|
83
|
+
if (!token) {
|
|
84
|
+
console.log(chalk.yellow('Not authenticated'));
|
|
85
|
+
console.log(chalk.gray('Run "connect-dropbox auth set <token>" to authenticate'));
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
try {
|
|
90
|
+
const client = getClient();
|
|
91
|
+
const account = await client.getCurrentAccount();
|
|
92
|
+
console.log(chalk.green('Authenticated'));
|
|
93
|
+
console.log(` Profile: ${chalk.cyan(getCurrentProfile())}`);
|
|
94
|
+
console.log(` User: ${chalk.white(account.name.display_name)}`);
|
|
95
|
+
console.log(` Email: ${chalk.white(account.email)}`);
|
|
96
|
+
console.log(` Account Type: ${chalk.white(account.account_type['.tag'])}`);
|
|
97
|
+
} catch (error) {
|
|
98
|
+
console.log(chalk.red('Authentication failed'));
|
|
99
|
+
console.error(chalk.gray(error instanceof Error ? error.message : String(error)));
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
authCmd
|
|
104
|
+
.command('clear')
|
|
105
|
+
.description('Clear stored credentials')
|
|
106
|
+
.action(() => {
|
|
107
|
+
clearConfig();
|
|
108
|
+
console.log(chalk.green('Credentials cleared'));
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
// ============================================
|
|
112
|
+
// Profile Commands
|
|
113
|
+
// ============================================
|
|
114
|
+
|
|
115
|
+
const profileCmd = program.command('profile').description('Profile management');
|
|
116
|
+
|
|
117
|
+
profileCmd
|
|
118
|
+
.command('list')
|
|
119
|
+
.description('List all profiles')
|
|
120
|
+
.action(() => {
|
|
121
|
+
const profiles = listProfiles();
|
|
122
|
+
const current = getCurrentProfile();
|
|
123
|
+
|
|
124
|
+
if (profiles.length === 0) {
|
|
125
|
+
console.log(chalk.gray('No profiles configured'));
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
console.log(chalk.bold('Profiles:'));
|
|
130
|
+
for (const profile of profiles) {
|
|
131
|
+
const marker = profile === current ? chalk.green(' (active)') : '';
|
|
132
|
+
console.log(` ${profile}${marker}`);
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
profileCmd
|
|
137
|
+
.command('use')
|
|
138
|
+
.description('Switch to a profile')
|
|
139
|
+
.argument('<name>', 'Profile name')
|
|
140
|
+
.action((name: string) => {
|
|
141
|
+
try {
|
|
142
|
+
setCurrentProfile(name);
|
|
143
|
+
console.log(chalk.green(`Switched to profile "${name}"`));
|
|
144
|
+
} catch (error) {
|
|
145
|
+
console.error(chalk.red(error instanceof Error ? error.message : String(error)));
|
|
146
|
+
process.exit(1);
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
profileCmd
|
|
151
|
+
.command('create')
|
|
152
|
+
.description('Create a new profile')
|
|
153
|
+
.argument('<name>', 'Profile name')
|
|
154
|
+
.action((name: string) => {
|
|
155
|
+
try {
|
|
156
|
+
if (createProfile(name)) {
|
|
157
|
+
console.log(chalk.green(`Profile "${name}" created`));
|
|
158
|
+
} else {
|
|
159
|
+
console.log(chalk.yellow(`Profile "${name}" already exists`));
|
|
160
|
+
}
|
|
161
|
+
} catch (error) {
|
|
162
|
+
console.error(chalk.red(error instanceof Error ? error.message : String(error)));
|
|
163
|
+
process.exit(1);
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
profileCmd
|
|
168
|
+
.command('delete')
|
|
169
|
+
.description('Delete a profile')
|
|
170
|
+
.argument('<name>', 'Profile name')
|
|
171
|
+
.action((name: string) => {
|
|
172
|
+
if (deleteProfile(name)) {
|
|
173
|
+
console.log(chalk.green(`Profile "${name}" deleted`));
|
|
174
|
+
} else {
|
|
175
|
+
console.log(chalk.yellow(`Cannot delete profile "${name}" (doesn't exist or is default)`));
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
profileCmd
|
|
180
|
+
.command('show')
|
|
181
|
+
.description('Show current profile')
|
|
182
|
+
.action(() => {
|
|
183
|
+
console.log(`Current profile: ${chalk.cyan(getCurrentProfile())}`);
|
|
184
|
+
console.log(`Config directory: ${chalk.gray(getConfigDir())}`);
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
// ============================================
|
|
188
|
+
// Files Commands
|
|
189
|
+
// ============================================
|
|
190
|
+
|
|
191
|
+
const filesCmd = program.command('files').description('File operations');
|
|
192
|
+
|
|
193
|
+
filesCmd
|
|
194
|
+
.command('list')
|
|
195
|
+
.description('List folder contents')
|
|
196
|
+
.argument('[path]', 'Folder path', '')
|
|
197
|
+
.option('-r, --recursive', 'List recursively')
|
|
198
|
+
.option('-l, --long', 'Show detailed information')
|
|
199
|
+
.option('--limit <n>', 'Limit number of results', '100')
|
|
200
|
+
.action(async (path: string, options) => {
|
|
201
|
+
try {
|
|
202
|
+
const client = getClient();
|
|
203
|
+
const result = await client.listFolder(path, {
|
|
204
|
+
recursive: options.recursive,
|
|
205
|
+
limit: parseInt(options.limit),
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
if (result.entries.length === 0) {
|
|
209
|
+
console.log(chalk.gray('Empty folder'));
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
for (const entry of result.entries) {
|
|
214
|
+
if (options.long) {
|
|
215
|
+
const type = entry['.tag'] === 'folder' ? 'd' : '-';
|
|
216
|
+
const size = entry['.tag'] === 'file' ? formatSize((entry as FileMetadata).size) : '-';
|
|
217
|
+
const modified = entry['.tag'] === 'file' ? (entry as FileMetadata).server_modified : '';
|
|
218
|
+
console.log(`${type} ${size.padStart(10)} ${modified.padStart(20)} ${formatMetadata(entry)}`);
|
|
219
|
+
} else {
|
|
220
|
+
console.log(formatMetadata(entry));
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if (result.has_more) {
|
|
225
|
+
console.log(chalk.gray(`\n... and more (use --limit to see more)`));
|
|
226
|
+
}
|
|
227
|
+
} catch (error) {
|
|
228
|
+
console.error(chalk.red('Error:'), error instanceof Error ? error.message : String(error));
|
|
229
|
+
process.exit(1);
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
filesCmd
|
|
234
|
+
.command('info')
|
|
235
|
+
.description('Get file or folder metadata')
|
|
236
|
+
.argument('<path>', 'File or folder path')
|
|
237
|
+
.action(async (path: string) => {
|
|
238
|
+
try {
|
|
239
|
+
const client = getClient();
|
|
240
|
+
const metadata = await client.getMetadata(path, {
|
|
241
|
+
include_media_info: true,
|
|
242
|
+
include_has_explicit_shared_members: true,
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
console.log(chalk.bold('Metadata:'));
|
|
246
|
+
console.log(` Type: ${chalk.cyan(metadata['.tag'])}`);
|
|
247
|
+
console.log(` Name: ${metadata.name}`);
|
|
248
|
+
console.log(` Path: ${metadata.path_display || metadata.path_lower}`);
|
|
249
|
+
console.log(` ID: ${chalk.gray(metadata.id)}`);
|
|
250
|
+
|
|
251
|
+
if (metadata['.tag'] === 'file') {
|
|
252
|
+
const file = metadata as FileMetadata;
|
|
253
|
+
console.log(` Size: ${formatSize(file.size)}`);
|
|
254
|
+
console.log(` Modified: ${file.server_modified}`);
|
|
255
|
+
console.log(` Rev: ${chalk.gray(file.rev)}`);
|
|
256
|
+
if (file.content_hash) {
|
|
257
|
+
console.log(` Content Hash: ${chalk.gray(file.content_hash)}`);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
} catch (error) {
|
|
261
|
+
console.error(chalk.red('Error:'), error instanceof Error ? error.message : String(error));
|
|
262
|
+
process.exit(1);
|
|
263
|
+
}
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
filesCmd
|
|
267
|
+
.command('search')
|
|
268
|
+
.description('Search for files and folders')
|
|
269
|
+
.argument('<query>', 'Search query')
|
|
270
|
+
.option('-p, --path <path>', 'Search within path')
|
|
271
|
+
.option('--filename-only', 'Search only filenames')
|
|
272
|
+
.option('--limit <n>', 'Maximum results', '20')
|
|
273
|
+
.action(async (query: string, options) => {
|
|
274
|
+
try {
|
|
275
|
+
const client = getClient();
|
|
276
|
+
const result = await client.search(query, {
|
|
277
|
+
path: options.path,
|
|
278
|
+
filename_only: options.filenameOnly,
|
|
279
|
+
max_results: parseInt(options.limit),
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
if (result.matches.length === 0) {
|
|
283
|
+
console.log(chalk.gray('No matches found'));
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
console.log(chalk.bold(`Found ${result.matches.length} matches:`));
|
|
288
|
+
for (const match of result.matches) {
|
|
289
|
+
const metadata = match.metadata.metadata;
|
|
290
|
+
console.log(` ${formatMetadata(metadata)}`);
|
|
291
|
+
console.log(chalk.gray(` ${metadata.path_display || metadata.path_lower}`));
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
if (result.has_more) {
|
|
295
|
+
console.log(chalk.gray(`\n... and more results`));
|
|
296
|
+
}
|
|
297
|
+
} catch (error) {
|
|
298
|
+
console.error(chalk.red('Error:'), error instanceof Error ? error.message : String(error));
|
|
299
|
+
process.exit(1);
|
|
300
|
+
}
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
filesCmd
|
|
304
|
+
.command('mkdir')
|
|
305
|
+
.description('Create a folder')
|
|
306
|
+
.argument('<path>', 'Folder path')
|
|
307
|
+
.option('--autorename', 'Autorename if exists')
|
|
308
|
+
.action(async (path: string, options) => {
|
|
309
|
+
try {
|
|
310
|
+
const client = getClient();
|
|
311
|
+
const folder = await client.createFolder(path, options.autorename);
|
|
312
|
+
console.log(chalk.green(`Created folder: ${folder.path_display || folder.name}`));
|
|
313
|
+
} catch (error) {
|
|
314
|
+
console.error(chalk.red('Error:'), error instanceof Error ? error.message : String(error));
|
|
315
|
+
process.exit(1);
|
|
316
|
+
}
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
filesCmd
|
|
320
|
+
.command('delete')
|
|
321
|
+
.description('Delete a file or folder')
|
|
322
|
+
.argument('<path>', 'File or folder path')
|
|
323
|
+
.option('--permanent', 'Permanently delete (cannot be recovered)')
|
|
324
|
+
.action(async (path: string, options) => {
|
|
325
|
+
try {
|
|
326
|
+
const client = getClient();
|
|
327
|
+
if (options.permanent) {
|
|
328
|
+
await client.permanentlyDelete(path);
|
|
329
|
+
console.log(chalk.green(`Permanently deleted: ${path}`));
|
|
330
|
+
} else {
|
|
331
|
+
const result = await client.delete(path);
|
|
332
|
+
console.log(chalk.green(`Deleted: ${result.metadata.path_display || result.metadata.name}`));
|
|
333
|
+
}
|
|
334
|
+
} catch (error) {
|
|
335
|
+
console.error(chalk.red('Error:'), error instanceof Error ? error.message : String(error));
|
|
336
|
+
process.exit(1);
|
|
337
|
+
}
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
filesCmd
|
|
341
|
+
.command('copy')
|
|
342
|
+
.description('Copy a file or folder')
|
|
343
|
+
.argument('<from>', 'Source path')
|
|
344
|
+
.argument('<to>', 'Destination path')
|
|
345
|
+
.option('--autorename', 'Autorename if destination exists')
|
|
346
|
+
.action(async (from: string, to: string, options) => {
|
|
347
|
+
try {
|
|
348
|
+
const client = getClient();
|
|
349
|
+
const result = await client.copy(from, to, { autorename: options.autorename });
|
|
350
|
+
console.log(chalk.green(`Copied to: ${result.metadata.path_display || result.metadata.name}`));
|
|
351
|
+
} catch (error) {
|
|
352
|
+
console.error(chalk.red('Error:'), error instanceof Error ? error.message : String(error));
|
|
353
|
+
process.exit(1);
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
filesCmd
|
|
358
|
+
.command('move')
|
|
359
|
+
.description('Move a file or folder')
|
|
360
|
+
.argument('<from>', 'Source path')
|
|
361
|
+
.argument('<to>', 'Destination path')
|
|
362
|
+
.option('--autorename', 'Autorename if destination exists')
|
|
363
|
+
.action(async (from: string, to: string, options) => {
|
|
364
|
+
try {
|
|
365
|
+
const client = getClient();
|
|
366
|
+
const result = await client.move(from, to, { autorename: options.autorename });
|
|
367
|
+
console.log(chalk.green(`Moved to: ${result.metadata.path_display || result.metadata.name}`));
|
|
368
|
+
} catch (error) {
|
|
369
|
+
console.error(chalk.red('Error:'), error instanceof Error ? error.message : String(error));
|
|
370
|
+
process.exit(1);
|
|
371
|
+
}
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
filesCmd
|
|
375
|
+
.command('upload')
|
|
376
|
+
.description('Upload a file')
|
|
377
|
+
.argument('<local>', 'Local file path')
|
|
378
|
+
.argument('<remote>', 'Remote Dropbox path')
|
|
379
|
+
.option('--overwrite', 'Overwrite if exists')
|
|
380
|
+
.option('--autorename', 'Autorename if exists')
|
|
381
|
+
.action(async (local: string, remote: string, options) => {
|
|
382
|
+
try {
|
|
383
|
+
const content = await Bun.file(local).arrayBuffer();
|
|
384
|
+
const client = getClient();
|
|
385
|
+
|
|
386
|
+
let mode: 'add' | 'overwrite' = 'add';
|
|
387
|
+
if (options.overwrite) mode = 'overwrite';
|
|
388
|
+
|
|
389
|
+
const result = await client.upload(remote, new Uint8Array(content), {
|
|
390
|
+
mode,
|
|
391
|
+
autorename: options.autorename,
|
|
392
|
+
});
|
|
393
|
+
console.log(chalk.green(`Uploaded: ${result.path_display || result.name}`));
|
|
394
|
+
console.log(` Size: ${formatSize(result.size)}`);
|
|
395
|
+
} catch (error) {
|
|
396
|
+
console.error(chalk.red('Error:'), error instanceof Error ? error.message : String(error));
|
|
397
|
+
process.exit(1);
|
|
398
|
+
}
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
filesCmd
|
|
402
|
+
.command('download')
|
|
403
|
+
.description('Download a file')
|
|
404
|
+
.argument('<remote>', 'Remote Dropbox path')
|
|
405
|
+
.argument('[local]', 'Local file path (defaults to filename)')
|
|
406
|
+
.action(async (remote: string, local?: string) => {
|
|
407
|
+
try {
|
|
408
|
+
const client = getClient();
|
|
409
|
+
const result = await client.download(remote);
|
|
410
|
+
|
|
411
|
+
const localPath = local || result.metadata.name;
|
|
412
|
+
await Bun.write(localPath, result.content);
|
|
413
|
+
|
|
414
|
+
console.log(chalk.green(`Downloaded: ${localPath}`));
|
|
415
|
+
console.log(` Size: ${formatSize(result.metadata.size)}`);
|
|
416
|
+
} catch (error) {
|
|
417
|
+
console.error(chalk.red('Error:'), error instanceof Error ? error.message : String(error));
|
|
418
|
+
process.exit(1);
|
|
419
|
+
}
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
filesCmd
|
|
423
|
+
.command('link')
|
|
424
|
+
.description('Get a temporary download link')
|
|
425
|
+
.argument('<path>', 'File path')
|
|
426
|
+
.action(async (path: string) => {
|
|
427
|
+
try {
|
|
428
|
+
const client = getClient();
|
|
429
|
+
const result = await client.getTemporaryLink(path);
|
|
430
|
+
console.log(chalk.bold('Temporary Link:'));
|
|
431
|
+
console.log(result.link);
|
|
432
|
+
console.log(chalk.gray('\nThis link expires after 4 hours.'));
|
|
433
|
+
} catch (error) {
|
|
434
|
+
console.error(chalk.red('Error:'), error instanceof Error ? error.message : String(error));
|
|
435
|
+
process.exit(1);
|
|
436
|
+
}
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
// ============================================
|
|
440
|
+
// Sharing Commands
|
|
441
|
+
// ============================================
|
|
442
|
+
|
|
443
|
+
const shareCmd = program.command('share').description('Sharing operations');
|
|
444
|
+
|
|
445
|
+
shareCmd
|
|
446
|
+
.command('create')
|
|
447
|
+
.description('Create a shared link')
|
|
448
|
+
.argument('<path>', 'File or folder path')
|
|
449
|
+
.action(async (path: string) => {
|
|
450
|
+
try {
|
|
451
|
+
const client = getClient();
|
|
452
|
+
const link = await client.createSharedLink(path);
|
|
453
|
+
console.log(chalk.green('Shared link created:'));
|
|
454
|
+
console.log(link.url);
|
|
455
|
+
} catch (error) {
|
|
456
|
+
console.error(chalk.red('Error:'), error instanceof Error ? error.message : String(error));
|
|
457
|
+
process.exit(1);
|
|
458
|
+
}
|
|
459
|
+
});
|
|
460
|
+
|
|
461
|
+
shareCmd
|
|
462
|
+
.command('list')
|
|
463
|
+
.description('List shared links')
|
|
464
|
+
.option('-p, --path <path>', 'List links for specific path')
|
|
465
|
+
.action(async (options) => {
|
|
466
|
+
try {
|
|
467
|
+
const client = getClient();
|
|
468
|
+
const result = await client.listSharedLinks({ path: options.path });
|
|
469
|
+
|
|
470
|
+
if (result.links.length === 0) {
|
|
471
|
+
console.log(chalk.gray('No shared links'));
|
|
472
|
+
return;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
console.log(chalk.bold(`Shared Links (${result.links.length}):`));
|
|
476
|
+
for (const link of result.links) {
|
|
477
|
+
console.log(`\n ${chalk.white(link.name)}`);
|
|
478
|
+
console.log(` URL: ${chalk.cyan(link.url)}`);
|
|
479
|
+
console.log(` Path: ${chalk.gray(link.path_lower || '-')}`);
|
|
480
|
+
console.log(` Visibility: ${link.link_permissions.resolved_visibility['.tag']}`);
|
|
481
|
+
if (link.expires) {
|
|
482
|
+
console.log(` Expires: ${link.expires}`);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
} catch (error) {
|
|
486
|
+
console.error(chalk.red('Error:'), error instanceof Error ? error.message : String(error));
|
|
487
|
+
process.exit(1);
|
|
488
|
+
}
|
|
489
|
+
});
|
|
490
|
+
|
|
491
|
+
shareCmd
|
|
492
|
+
.command('revoke')
|
|
493
|
+
.description('Revoke a shared link')
|
|
494
|
+
.argument('<url>', 'Shared link URL')
|
|
495
|
+
.action(async (url: string) => {
|
|
496
|
+
try {
|
|
497
|
+
const client = getClient();
|
|
498
|
+
await client.revokeSharedLink(url);
|
|
499
|
+
console.log(chalk.green('Shared link revoked'));
|
|
500
|
+
} catch (error) {
|
|
501
|
+
console.error(chalk.red('Error:'), error instanceof Error ? error.message : String(error));
|
|
502
|
+
process.exit(1);
|
|
503
|
+
}
|
|
504
|
+
});
|
|
505
|
+
|
|
506
|
+
shareCmd
|
|
507
|
+
.command('folders')
|
|
508
|
+
.description('List shared folders')
|
|
509
|
+
.action(async () => {
|
|
510
|
+
try {
|
|
511
|
+
const client = getClient();
|
|
512
|
+
const result = await client.listSharedFolders();
|
|
513
|
+
|
|
514
|
+
if (result.entries.length === 0) {
|
|
515
|
+
console.log(chalk.gray('No shared folders'));
|
|
516
|
+
return;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
console.log(chalk.bold(`Shared Folders (${result.entries.length}):`));
|
|
520
|
+
for (const folder of result.entries) {
|
|
521
|
+
console.log(`\n ${chalk.blue(folder.name + '/')}`);
|
|
522
|
+
console.log(` ID: ${chalk.gray(folder.shared_folder_id)}`);
|
|
523
|
+
console.log(` Access: ${folder.access_type['.tag']}`);
|
|
524
|
+
console.log(` Team Folder: ${folder.is_team_folder ? 'Yes' : 'No'}`);
|
|
525
|
+
if (folder.path_lower) {
|
|
526
|
+
console.log(` Path: ${folder.path_lower}`);
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
} catch (error) {
|
|
530
|
+
console.error(chalk.red('Error:'), error instanceof Error ? error.message : String(error));
|
|
531
|
+
process.exit(1);
|
|
532
|
+
}
|
|
533
|
+
});
|
|
534
|
+
|
|
535
|
+
shareCmd
|
|
536
|
+
.command('folder-members')
|
|
537
|
+
.description('List members of a shared folder')
|
|
538
|
+
.argument('<folder-id>', 'Shared folder ID')
|
|
539
|
+
.action(async (folderId: string) => {
|
|
540
|
+
try {
|
|
541
|
+
const client = getClient();
|
|
542
|
+
const result = await client.listSharedFolderMembers(folderId);
|
|
543
|
+
|
|
544
|
+
console.log(chalk.bold('Members:'));
|
|
545
|
+
for (const member of result.users) {
|
|
546
|
+
console.log(`\n ${chalk.white(member.user.display_name)}`);
|
|
547
|
+
console.log(` Email: ${member.user.email}`);
|
|
548
|
+
console.log(` Access: ${member.access_type['.tag']}`);
|
|
549
|
+
console.log(` Same Team: ${member.user.same_team ? 'Yes' : 'No'}`);
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
if (result.groups && result.groups.length > 0) {
|
|
553
|
+
console.log(chalk.bold('\nGroups:'));
|
|
554
|
+
for (const group of result.groups) {
|
|
555
|
+
console.log(`\n ${chalk.white(group.group.group_name)}`);
|
|
556
|
+
console.log(` Access: ${group.access_type['.tag']}`);
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
} catch (error) {
|
|
560
|
+
console.error(chalk.red('Error:'), error instanceof Error ? error.message : String(error));
|
|
561
|
+
process.exit(1);
|
|
562
|
+
}
|
|
563
|
+
});
|
|
564
|
+
|
|
565
|
+
// ============================================
|
|
566
|
+
// Account Commands
|
|
567
|
+
// ============================================
|
|
568
|
+
|
|
569
|
+
const accountCmd = program.command('account').description('Account information');
|
|
570
|
+
|
|
571
|
+
accountCmd
|
|
572
|
+
.command('info')
|
|
573
|
+
.description('Get account information')
|
|
574
|
+
.action(async () => {
|
|
575
|
+
try {
|
|
576
|
+
const client = getClient();
|
|
577
|
+
const account = await client.getCurrentAccount();
|
|
578
|
+
|
|
579
|
+
console.log(chalk.bold('Account Information:'));
|
|
580
|
+
console.log(` Name: ${account.name.display_name}`);
|
|
581
|
+
console.log(` Email: ${account.email} ${account.email_verified ? chalk.green('(verified)') : chalk.yellow('(unverified)')}`);
|
|
582
|
+
console.log(` Account Type: ${account.account_type['.tag']}`);
|
|
583
|
+
console.log(` Locale: ${account.locale}`);
|
|
584
|
+
console.log(` Referral Link: ${account.referral_link}`);
|
|
585
|
+
|
|
586
|
+
if (account.team) {
|
|
587
|
+
console.log(`\n Team: ${account.team.name}`);
|
|
588
|
+
console.log(` Team ID: ${chalk.gray(account.team.id)}`);
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
console.log(`\n Account ID: ${chalk.gray(account.account_id)}`);
|
|
592
|
+
console.log(` Root Namespace ID: ${chalk.gray(account.root_info.root_namespace_id)}`);
|
|
593
|
+
} catch (error) {
|
|
594
|
+
console.error(chalk.red('Error:'), error instanceof Error ? error.message : String(error));
|
|
595
|
+
process.exit(1);
|
|
596
|
+
}
|
|
597
|
+
});
|
|
598
|
+
|
|
599
|
+
accountCmd
|
|
600
|
+
.command('usage')
|
|
601
|
+
.description('Get space usage')
|
|
602
|
+
.action(async () => {
|
|
603
|
+
try {
|
|
604
|
+
const client = getClient();
|
|
605
|
+
const usage = await client.getSpaceUsage();
|
|
606
|
+
|
|
607
|
+
const usedPercent = (usage.used / usage.allocation.allocated * 100).toFixed(1);
|
|
608
|
+
|
|
609
|
+
console.log(chalk.bold('Space Usage:'));
|
|
610
|
+
console.log(` Used: ${formatSize(usage.used)}`);
|
|
611
|
+
console.log(` Allocated: ${formatSize(usage.allocation.allocated)}`);
|
|
612
|
+
console.log(` Usage: ${usedPercent}%`);
|
|
613
|
+
console.log(` Type: ${usage.allocation['.tag']}`);
|
|
614
|
+
|
|
615
|
+
// Progress bar
|
|
616
|
+
const barWidth = 30;
|
|
617
|
+
const filled = Math.round(parseFloat(usedPercent) / 100 * barWidth);
|
|
618
|
+
const bar = chalk.green('█'.repeat(filled)) + chalk.gray('░'.repeat(barWidth - filled));
|
|
619
|
+
console.log(`\n [${bar}] ${usedPercent}%`);
|
|
620
|
+
} catch (error) {
|
|
621
|
+
console.error(chalk.red('Error:'), error instanceof Error ? error.message : String(error));
|
|
622
|
+
process.exit(1);
|
|
623
|
+
}
|
|
624
|
+
});
|
|
625
|
+
|
|
626
|
+
// Parse and execute
|
|
627
|
+
program.parse();
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// Dropbox Connector
|
|
2
|
+
// A TypeScript wrapper for the Dropbox API
|
|
3
|
+
|
|
4
|
+
export { Dropbox } from './api';
|
|
5
|
+
export { DropboxClient } from './api/client';
|
|
6
|
+
export * from './types';
|
|
7
|
+
|
|
8
|
+
// Export config utilities
|
|
9
|
+
export {
|
|
10
|
+
getAccessToken,
|
|
11
|
+
setAccessToken,
|
|
12
|
+
getCurrentProfile,
|
|
13
|
+
setCurrentProfile,
|
|
14
|
+
listProfiles,
|
|
15
|
+
createProfile,
|
|
16
|
+
deleteProfile,
|
|
17
|
+
loadProfile,
|
|
18
|
+
saveProfile,
|
|
19
|
+
clearConfig,
|
|
20
|
+
} from './utils/config';
|