@tuskydp/cli 0.2.0 → 0.3.0

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.
Files changed (104) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/src/commands/decrypt.d.ts.map +1 -1
  3. package/dist/src/commands/decrypt.js +53 -21
  4. package/dist/src/commands/decrypt.js.map +1 -1
  5. package/dist/src/commands/download.d.ts +1 -0
  6. package/dist/src/commands/download.d.ts.map +1 -1
  7. package/dist/src/commands/download.js +81 -11
  8. package/dist/src/commands/download.js.map +1 -1
  9. package/dist/src/commands/export.d.ts +6 -0
  10. package/dist/src/commands/export.d.ts.map +1 -1
  11. package/dist/src/commands/export.js +29 -17
  12. package/dist/src/commands/export.js.map +1 -1
  13. package/dist/src/commands/files.d.ts.map +1 -1
  14. package/dist/src/commands/files.js +89 -10
  15. package/dist/src/commands/files.js.map +1 -1
  16. package/dist/src/commands/folder.d.ts +3 -0
  17. package/dist/src/commands/folder.d.ts.map +1 -0
  18. package/dist/src/commands/folder.js +151 -0
  19. package/dist/src/commands/folder.js.map +1 -0
  20. package/dist/src/commands/rehydrate.d.ts +1 -0
  21. package/dist/src/commands/rehydrate.d.ts.map +1 -1
  22. package/dist/src/commands/rehydrate.js +15 -7
  23. package/dist/src/commands/rehydrate.js.map +1 -1
  24. package/dist/src/commands/trash.d.ts +3 -0
  25. package/dist/src/commands/trash.d.ts.map +1 -0
  26. package/dist/src/commands/trash.js +109 -0
  27. package/dist/src/commands/trash.js.map +1 -0
  28. package/dist/src/commands/upload.d.ts +4 -0
  29. package/dist/src/commands/upload.d.ts.map +1 -1
  30. package/dist/src/commands/upload.js +104 -3
  31. package/dist/src/commands/upload.js.map +1 -1
  32. package/dist/src/commands/wallet.d.ts +3 -0
  33. package/dist/src/commands/wallet.d.ts.map +1 -0
  34. package/dist/src/commands/wallet.js +126 -0
  35. package/dist/src/commands/wallet.js.map +1 -0
  36. package/dist/src/commands/webhook.d.ts +3 -0
  37. package/dist/src/commands/webhook.d.ts.map +1 -0
  38. package/dist/src/commands/webhook.js +172 -0
  39. package/dist/src/commands/webhook.js.map +1 -0
  40. package/dist/src/crypto.d.ts +16 -0
  41. package/dist/src/crypto.d.ts.map +1 -1
  42. package/dist/src/crypto.js +26 -0
  43. package/dist/src/crypto.js.map +1 -1
  44. package/dist/src/index.js +17 -3
  45. package/dist/src/index.js.map +1 -1
  46. package/dist/src/mcp/server.d.ts.map +1 -1
  47. package/dist/src/mcp/server.js +2 -1
  48. package/dist/src/mcp/server.js.map +1 -1
  49. package/dist/src/mcp/tools/files.d.ts.map +1 -1
  50. package/dist/src/mcp/tools/files.js +40 -5
  51. package/dist/src/mcp/tools/files.js.map +1 -1
  52. package/dist/src/seal.d.ts +16 -0
  53. package/dist/src/seal.d.ts.map +1 -1
  54. package/dist/src/seal.js +23 -0
  55. package/dist/src/seal.js.map +1 -1
  56. package/dist/src/tui/files-panel.d.ts +31 -1
  57. package/dist/src/tui/files-panel.d.ts.map +1 -1
  58. package/dist/src/tui/files-panel.js +118 -11
  59. package/dist/src/tui/files-panel.js.map +1 -1
  60. package/dist/src/tui/index.d.ts.map +1 -1
  61. package/dist/src/tui/index.js +272 -33
  62. package/dist/src/tui/index.js.map +1 -1
  63. package/dist/src/tui/overview.d.ts.map +1 -1
  64. package/dist/src/tui/overview.js +24 -8
  65. package/dist/src/tui/overview.js.map +1 -1
  66. package/dist/src/tui/trash-screen.d.ts +4 -0
  67. package/dist/src/tui/trash-screen.d.ts.map +1 -0
  68. package/dist/src/tui/trash-screen.js +190 -0
  69. package/dist/src/tui/trash-screen.js.map +1 -0
  70. package/dist/src/tui/vaults-panel.d.ts +8 -0
  71. package/dist/src/tui/vaults-panel.d.ts.map +1 -1
  72. package/dist/src/tui/vaults-panel.js +45 -6
  73. package/dist/src/tui/vaults-panel.js.map +1 -1
  74. package/dist/src/version.d.ts +2 -0
  75. package/dist/src/version.d.ts.map +1 -0
  76. package/dist/src/version.js +21 -0
  77. package/dist/src/version.js.map +1 -0
  78. package/package.json +3 -3
  79. package/src/commands/decrypt.ts +56 -23
  80. package/src/commands/download.ts +82 -11
  81. package/src/commands/export.ts +35 -19
  82. package/src/commands/files.ts +93 -9
  83. package/src/commands/folder.ts +169 -0
  84. package/src/commands/rehydrate.ts +15 -8
  85. package/src/commands/trash.ts +121 -0
  86. package/src/commands/upload.ts +126 -3
  87. package/src/commands/wallet.ts +183 -0
  88. package/src/commands/webhook.ts +193 -0
  89. package/src/crypto.ts +35 -0
  90. package/src/index.ts +17 -4
  91. package/src/mcp/server.ts +2 -1
  92. package/src/mcp/tools/files.ts +43 -5
  93. package/src/seal.ts +34 -1
  94. package/src/tui/files-panel.ts +139 -11
  95. package/src/tui/index.ts +289 -33
  96. package/src/tui/overview.ts +22 -8
  97. package/src/tui/trash-screen.ts +203 -0
  98. package/src/tui/vaults-panel.ts +55 -6
  99. package/src/version.ts +21 -0
  100. package/vitest.config.ts +1 -0
  101. package/dist/src/client.d.ts +0 -120
  102. package/dist/src/client.d.ts.map +0 -1
  103. package/dist/src/client.js +0 -152
  104. package/dist/src/client.js.map +0 -1
@@ -0,0 +1,203 @@
1
+ import blessed from 'blessed';
2
+ import type { TuskyClient } from '@tuskydp/sdk';
3
+ import { formatBytes, formatDate, showError, showMessage } from './helpers.js';
4
+
5
+ export async function showTrashScreen(
6
+ screen: blessed.Widgets.Screen,
7
+ sdk: TuskyClient,
8
+ ): Promise<void> {
9
+ return new Promise((resolve) => {
10
+ const container = blessed.box({
11
+ parent: screen,
12
+ top: 0,
13
+ left: 0,
14
+ width: '100%',
15
+ height: '100%',
16
+ tags: true,
17
+ border: { type: 'line' },
18
+ style: {
19
+ border: { fg: 'yellow' },
20
+ fg: 'white',
21
+ },
22
+ label: ' Trash ',
23
+ });
24
+
25
+ const list = blessed.list({
26
+ parent: container,
27
+ top: 0,
28
+ left: 0,
29
+ width: '100%',
30
+ height: '100%-3',
31
+ style: {
32
+ fg: 'white',
33
+ selected: { bg: 'yellow', fg: 'black' },
34
+ },
35
+ keys: true,
36
+ vi: true,
37
+ interactive: true,
38
+ scrollable: true,
39
+ alwaysScroll: true,
40
+ scrollbar: { style: { bg: 'yellow' } },
41
+ tags: true,
42
+ padding: { left: 1, right: 1 },
43
+ });
44
+
45
+ const hint = blessed.box({
46
+ parent: container,
47
+ bottom: 0,
48
+ left: 0,
49
+ width: '100%',
50
+ height: 1,
51
+ tags: true,
52
+ style: { fg: 'gray' },
53
+ content: ' {bold}r{/bold} restore {bold}d{/bold} permanent delete {bold}e{/bold} empty all {bold}Esc{/bold} back',
54
+ });
55
+
56
+ type TrashEntry = { id: string; type: 'file' | 'vault'; name: string; size: number; deletedAt: string };
57
+ let items: TrashEntry[] = [];
58
+
59
+ async function loadTrash() {
60
+ list.setItems(['Loading trash...'] as any);
61
+ screen.render();
62
+
63
+ try {
64
+ const trashed = await sdk.trash.list();
65
+ items = [];
66
+
67
+ for (const v of trashed.vaults) {
68
+ items.push({
69
+ id: v.id,
70
+ type: 'vault',
71
+ name: v.name,
72
+ size: v.totalSizeBytes,
73
+ deletedAt: v.deletedAt || '',
74
+ });
75
+ }
76
+ for (const f of trashed.files) {
77
+ items.push({
78
+ id: f.id,
79
+ type: 'file',
80
+ name: f.name,
81
+ size: f.plaintextSizeBytes || f.sizeBytes,
82
+ deletedAt: f.deletedAt || '',
83
+ });
84
+ }
85
+
86
+ if (items.length === 0) {
87
+ list.setItems(['{gray-fg}Trash is empty.{/gray-fg}'] as any);
88
+ } else {
89
+ const listItems = items.map((item) => {
90
+ const typeTag = item.type === 'vault'
91
+ ? '{yellow-fg}[vault]{/yellow-fg}'
92
+ : '{cyan-fg}[file]{/cyan-fg} ';
93
+ const deleted = item.deletedAt ? formatDate(item.deletedAt) : 'N/A';
94
+ return ` ${typeTag} ${item.name} ${formatBytes(item.size)} deleted ${deleted}`;
95
+ });
96
+ list.setItems(listItems as any);
97
+ }
98
+ list.select(0);
99
+ screen.render();
100
+ } catch (err: any) {
101
+ list.setItems([`{red-fg}Error: ${err.message}{/red-fg}`] as any);
102
+ screen.render();
103
+ }
104
+ }
105
+
106
+ function close() {
107
+ container.destroy();
108
+ screen.render();
109
+ resolve();
110
+ }
111
+
112
+ // Restore
113
+ list.key(['r'], async () => {
114
+ const idx = (list as any).selected as number;
115
+ const entry = items[idx];
116
+ if (!entry) return;
117
+
118
+ try {
119
+ await sdk.trash.restore(entry.id);
120
+ showMessage(screen, `Restored: ${entry.name}`, ' Trash ');
121
+ await loadTrash();
122
+ } catch (err: any) {
123
+ showError(screen, err.message);
124
+ }
125
+ });
126
+
127
+ // Permanent delete
128
+ list.key(['d'], async () => {
129
+ const idx = (list as any).selected as number;
130
+ const entry = items[idx];
131
+ if (!entry) return;
132
+
133
+ // Inline confirm via question
134
+ const dialog = blessed.question({
135
+ parent: screen,
136
+ top: 'center',
137
+ left: 'center',
138
+ width: '50%',
139
+ height: 'shrink',
140
+ border: { type: 'line' },
141
+ style: { border: { fg: 'red' }, fg: 'white' },
142
+ label: ' Confirm ',
143
+ tags: true,
144
+ keys: true,
145
+ vi: true,
146
+ });
147
+ dialog.ask(`Permanently delete "${entry.name}"? (cannot be undone)`, async (err, value) => {
148
+ dialog.destroy();
149
+ screen.render();
150
+ if (!err && value) {
151
+ try {
152
+ await sdk.trash.delete(entry.id);
153
+ showMessage(screen, `Permanently deleted: ${entry.name}`, ' Trash ');
154
+ await loadTrash();
155
+ } catch (e: any) {
156
+ showError(screen, e.message);
157
+ }
158
+ }
159
+ list.focus();
160
+ });
161
+ });
162
+
163
+ // Empty all trash
164
+ list.key(['e'], async () => {
165
+ if (items.length === 0) return;
166
+
167
+ const dialog = blessed.question({
168
+ parent: screen,
169
+ top: 'center',
170
+ left: 'center',
171
+ width: '50%',
172
+ height: 'shrink',
173
+ border: { type: 'line' },
174
+ style: { border: { fg: 'red' }, fg: 'white' },
175
+ label: ' Confirm ',
176
+ tags: true,
177
+ keys: true,
178
+ vi: true,
179
+ });
180
+ dialog.ask('Permanently delete ALL trashed items? (cannot be undone)', async (err, value) => {
181
+ dialog.destroy();
182
+ screen.render();
183
+ if (!err && value) {
184
+ try {
185
+ await sdk.trash.empty();
186
+ showMessage(screen, 'Trash emptied', ' Trash ');
187
+ await loadTrash();
188
+ } catch (e: any) {
189
+ showError(screen, e.message);
190
+ }
191
+ }
192
+ list.focus();
193
+ });
194
+ });
195
+
196
+ container.key(['escape', 'q'], close);
197
+ list.key(['escape'], close);
198
+
199
+ loadTrash();
200
+ list.focus();
201
+ screen.render();
202
+ });
203
+ }
@@ -9,6 +9,16 @@ export interface VaultItem {
9
9
  visibility: string;
10
10
  fileCount: number;
11
11
  totalSizeBytes: number;
12
+ description: string | null;
13
+ // SEAL shared vault fields
14
+ sealAllowlistObjectId?: string | null;
15
+ sealPackageId?: string | null;
16
+ sealKeyServerIds?: string[] | null;
17
+ sealThreshold?: number | null;
18
+ createdAt: string;
19
+ // For shared vault memberships
20
+ isSharedMembership?: boolean;
21
+ memberRole?: string;
12
22
  }
13
23
 
14
24
  export class VaultsPanel {
@@ -74,32 +84,71 @@ export class VaultsPanel {
74
84
  this.screen.render();
75
85
 
76
86
  try {
77
- const vaults = await this.sdk.vaults.list();
78
- this.vaults = vaults.map((v) => ({
87
+ // Fetch owned vaults + shared vault memberships in parallel
88
+ const [ownedVaults, sharedResult] = await Promise.all([
89
+ this.sdk.vaults.list(),
90
+ this.sdk.sharedVaults.list().catch(() => ({ vaults: [] })),
91
+ ]);
92
+
93
+ this.vaults = ownedVaults.map((v) => ({
79
94
  id: v.id,
80
95
  name: v.name,
81
96
  slug: v.slug,
82
97
  visibility: v.visibility,
83
98
  fileCount: v.fileCount || 0,
84
99
  totalSizeBytes: v.totalSizeBytes || 0,
100
+ description: v.description,
101
+ sealAllowlistObjectId: v.sealAllowlistObjectId,
102
+ sealPackageId: v.sealPackageId,
103
+ sealKeyServerIds: v.sealKeyServerIds,
104
+ sealThreshold: v.sealThreshold,
105
+ createdAt: v.createdAt,
85
106
  }));
86
107
 
108
+ // Append shared vault memberships (vaults user doesn't own but has access to)
109
+ for (const entry of sharedResult.vaults) {
110
+ this.vaults.push({
111
+ id: entry.vault.id,
112
+ name: entry.vault.name,
113
+ slug: entry.vault.slug,
114
+ visibility: 'shared',
115
+ fileCount: entry.vault.fileCount || 0,
116
+ totalSizeBytes: entry.vault.totalSizeBytes || 0,
117
+ description: entry.vault.description,
118
+ createdAt: entry.grantedAt,
119
+ isSharedMembership: true,
120
+ memberRole: entry.role,
121
+ });
122
+ }
123
+
87
124
  if (this.vaults.length === 0) {
88
125
  this.list.setItems(['(no vaults — press n to create)'] as any);
89
126
  } else {
90
127
  // Calculate available width (subtract border + padding)
91
128
  const totalW = (this.list.width as number) - 4;
92
129
  const filesW = 7; // "999 files" max ~9
93
- const visW = 7; // "private"
130
+ const visW = 8; // "shared" + tag
94
131
  const sizeW = 9; // "999.9 GB"
95
132
  const nameW = Math.max(8, totalW - filesW - visW - sizeW - 3);
96
133
 
97
134
  const items = this.vaults.map((v) => {
98
- const vis = v.visibility === 'private' ? 'private' : 'public';
99
- const visTagged = v.visibility === 'private' ? '{yellow-fg}private{/yellow-fg}' : '{green-fg}public{/green-fg}';
135
+ let vis: string;
136
+ let visTagged: string;
137
+ if (v.visibility === 'private') {
138
+ vis = 'private';
139
+ visTagged = '{yellow-fg}private{/yellow-fg}';
140
+ } else if (v.visibility === 'shared') {
141
+ vis = v.isSharedMembership ? 'member' : 'shared';
142
+ visTagged = v.isSharedMembership
143
+ ? '{magenta-fg}member{/magenta-fg}'
144
+ : '{magenta-fg}shared{/magenta-fg}';
145
+ } else {
146
+ vis = 'public';
147
+ visTagged = '{green-fg}public{/green-fg}';
148
+ }
100
149
  const size = formatBytes(v.totalSizeBytes);
101
150
  const files = `${v.fileCount}`;
102
- const name = v.name.length > nameW ? v.name.slice(0, nameW - 1) + '' : v.name;
151
+ const name = v.name.length > nameW ? v.name.slice(0, nameW - 1) + '...' : v.name;
103
152
  return formatRow([
104
153
  { text: name, width: nameW },
105
154
  { text: vis, tagged: visTagged, width: visW },
package/src/version.ts ADDED
@@ -0,0 +1,21 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { resolve, dirname } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+
5
+ const __dirname = dirname(fileURLToPath(import.meta.url));
6
+
7
+ function loadVersion(): string {
8
+ // Walk up from current dir until we find package.json with our package name
9
+ let dir = __dirname;
10
+ for (let i = 0; i < 5; i++) {
11
+ try {
12
+ const pkgPath = resolve(dir, 'package.json');
13
+ const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
14
+ if (pkg.name === '@tuskydp/cli') return pkg.version;
15
+ } catch { /* keep walking */ }
16
+ dir = resolve(dir, '..');
17
+ }
18
+ return '0.0.0';
19
+ }
20
+
21
+ export const CLI_VERSION: string = loadVersion();
package/vitest.config.ts CHANGED
@@ -3,5 +3,6 @@ import { defineConfig } from 'vitest/config';
3
3
  export default defineConfig({
4
4
  test: {
5
5
  include: ['src/**/*.test.ts'],
6
+ testTimeout: 30000,
6
7
  },
7
8
  });
@@ -1,120 +0,0 @@
1
- export declare class TuskyDPApiError extends Error {
2
- statusCode: number;
3
- constructor(statusCode: number, message: string);
4
- }
5
- export declare class TuskyDPClient {
6
- private apiUrl;
7
- private apiKey;
8
- constructor(apiUrl: string, apiKey: string);
9
- private request;
10
- createVault(name: string, description?: string, visibility?: 'public' | 'private'): Promise<{
11
- vault: any;
12
- }>;
13
- listVaults(): Promise<{
14
- vaults: any[];
15
- }>;
16
- getVault(vaultId: string): Promise<{
17
- vault: any;
18
- }>;
19
- updateVault(vaultId: string, updates: {
20
- name?: string;
21
- description?: string;
22
- }): Promise<{
23
- vault: any;
24
- }>;
25
- deleteVault(vaultId: string, force?: boolean): Promise<{
26
- success: boolean;
27
- }>;
28
- requestUpload(params: {
29
- name: string;
30
- mimeType: string;
31
- sizeBytes: number;
32
- vaultId: string;
33
- wrappedKey?: string;
34
- encryptionIv?: string;
35
- plaintextSizeBytes?: number;
36
- plaintextChecksumSha256?: string;
37
- }): Promise<{
38
- fileId: string;
39
- uploadUrl: string;
40
- spacesKey: string;
41
- }>;
42
- confirmUpload(fileId: string): Promise<{
43
- file: any;
44
- }>;
45
- getDownloadUrl(fileId: string): Promise<{
46
- downloadUrl: string | null;
47
- status: string;
48
- encryption: any;
49
- message?: string;
50
- pollUrl?: string;
51
- }>;
52
- listFiles(params?: {
53
- vaultId?: string;
54
- limit?: number;
55
- sortBy?: string;
56
- order?: string;
57
- }): Promise<{
58
- files: any[];
59
- nextCursor: string | null;
60
- }>;
61
- getFileInfo(fileId: string): Promise<any>;
62
- deleteFile(fileId: string): Promise<{
63
- success: boolean;
64
- }>;
65
- retryFile(fileId: string): Promise<{
66
- file: any;
67
- message: string;
68
- }>;
69
- retryAllFiles(): Promise<{
70
- retriedCount: number;
71
- message: string;
72
- }>;
73
- getEncryptionParams(): Promise<{
74
- setupComplete: boolean;
75
- salt?: string;
76
- verifier?: string;
77
- encryptedMasterKey?: string;
78
- }>;
79
- setupEncryption(salt: string, verifier: string, encryptedMasterKey: string, wrappedMasterKeyBackup: string): Promise<{
80
- success: boolean;
81
- }>;
82
- getRecoveryData(): Promise<{
83
- wrappedMasterKeyBackup: string;
84
- }>;
85
- resetEncryption(salt: string, verifier: string, encryptedMasterKey: string, wrappedMasterKeyBackup: string): Promise<{
86
- success: boolean;
87
- }>;
88
- register(email: string, password: string, displayName?: string): Promise<{
89
- user: any;
90
- accessToken: string;
91
- refreshToken: string;
92
- }>;
93
- login(email: string, password: string): Promise<{
94
- user: any;
95
- accessToken: string;
96
- refreshToken: string;
97
- }>;
98
- createApiKeyWithJwt(accessToken: string, name: string): Promise<{
99
- apiKey: string;
100
- name: string;
101
- keyPrefix: string;
102
- }>;
103
- getAccount(): Promise<any>;
104
- getPlans(): Promise<{
105
- plans: any[];
106
- }>;
107
- createApiKey(params: {
108
- name: string;
109
- scopes?: string[];
110
- vaultIds?: string[];
111
- expiresInDays?: number;
112
- }): Promise<any>;
113
- listApiKeys(): Promise<{
114
- apiKeys: any[];
115
- }>;
116
- revokeApiKey(keyId: string): Promise<{
117
- success: boolean;
118
- }>;
119
- }
120
- //# sourceMappingURL=client.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"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"}
@@ -1,152 +0,0 @@
1
- const VERSION = '0.1.0';
2
- export class TuskyDPApiError extends Error {
3
- statusCode;
4
- constructor(statusCode, message) {
5
- super(message);
6
- this.statusCode = statusCode;
7
- this.name = 'TuskyDPApiError';
8
- }
9
- }
10
- export class TuskyDPClient {
11
- apiUrl;
12
- apiKey;
13
- constructor(apiUrl, apiKey) {
14
- this.apiUrl = apiUrl.replace(/\/$/, '');
15
- this.apiKey = apiKey;
16
- }
17
- async request(method, path, body) {
18
- const headers = {
19
- 'Authorization': `Bearer ${this.apiKey}`,
20
- 'User-Agent': `tusky-cli/${VERSION}`,
21
- };
22
- if (body) {
23
- headers['Content-Type'] = 'application/json';
24
- }
25
- const response = await fetch(`${this.apiUrl}${path}`, {
26
- method,
27
- headers,
28
- body: body ? JSON.stringify(body) : undefined,
29
- });
30
- if (!response.ok) {
31
- const error = await response.json().catch(() => ({ error: response.statusText }));
32
- throw new TuskyDPApiError(response.status, error.error || 'Unknown error');
33
- }
34
- return response.json();
35
- }
36
- // Vaults
37
- async createVault(name, description, visibility) {
38
- return this.request('POST', '/api/vaults', { name, description, visibility: visibility || 'private' });
39
- }
40
- async listVaults() {
41
- return this.request('GET', '/api/vaults');
42
- }
43
- async getVault(vaultId) {
44
- return this.request('GET', `/api/vaults/${vaultId}`);
45
- }
46
- async updateVault(vaultId, updates) {
47
- return this.request('PATCH', `/api/vaults/${vaultId}`, updates);
48
- }
49
- async deleteVault(vaultId, force = false) {
50
- return this.request('DELETE', `/api/vaults/${vaultId}?force=${force}`);
51
- }
52
- // Files
53
- async requestUpload(params) {
54
- return this.request('POST', '/api/files/upload', params);
55
- }
56
- async confirmUpload(fileId) {
57
- return this.request('POST', `/api/files/${fileId}/confirm`);
58
- }
59
- async getDownloadUrl(fileId) {
60
- return this.request('GET', `/api/files/${fileId}/download`);
61
- }
62
- async listFiles(params) {
63
- const qs = params ? new URLSearchParams(Object.fromEntries(Object.entries(params).filter(([, v]) => v !== undefined).map(([k, v]) => [k, String(v)]))).toString() : '';
64
- return this.request('GET', `/api/files${qs ? `?${qs}` : ''}`);
65
- }
66
- async getFileInfo(fileId) {
67
- return this.request('GET', `/api/files/${fileId}/status`);
68
- }
69
- async deleteFile(fileId) {
70
- return this.request('DELETE', `/api/files/${fileId}`);
71
- }
72
- async retryFile(fileId) {
73
- return this.request('POST', `/api/files/${fileId}/retry`);
74
- }
75
- async retryAllFiles() {
76
- return this.request('POST', '/api/files/retry-all');
77
- }
78
- // Encryption
79
- async getEncryptionParams() {
80
- return this.request('GET', '/api/account/encryption/params');
81
- }
82
- async setupEncryption(salt, verifier, encryptedMasterKey, wrappedMasterKeyBackup) {
83
- return this.request('POST', '/api/account/encryption/setup', { salt, verifier, encryptedMasterKey, wrappedMasterKeyBackup });
84
- }
85
- async getRecoveryData() {
86
- return this.request('GET', '/api/account/encryption/recovery');
87
- }
88
- async resetEncryption(salt, verifier, encryptedMasterKey, wrappedMasterKeyBackup) {
89
- return this.request('POST', '/api/account/encryption/reset', { salt, verifier, encryptedMasterKey, wrappedMasterKeyBackup });
90
- }
91
- // Auth (no stored API key needed)
92
- async register(email, password, displayName) {
93
- const response = await fetch(`${this.apiUrl}/api/auth/register`, {
94
- method: 'POST',
95
- headers: { 'Content-Type': 'application/json', 'User-Agent': `tusky-cli/${VERSION}` },
96
- body: JSON.stringify({ email, password, displayName }),
97
- });
98
- if (!response.ok) {
99
- const error = await response.json().catch(() => ({ error: response.statusText }));
100
- throw new TuskyDPApiError(response.status, error.error || 'Unknown error');
101
- }
102
- return response.json();
103
- }
104
- async login(email, password) {
105
- const response = await fetch(`${this.apiUrl}/api/auth/login`, {
106
- method: 'POST',
107
- headers: { 'Content-Type': 'application/json', 'User-Agent': `tusky-cli/${VERSION}` },
108
- body: JSON.stringify({ email, password }),
109
- });
110
- if (!response.ok) {
111
- const error = await response.json().catch(() => ({ error: response.statusText }));
112
- throw new TuskyDPApiError(response.status, error.error || 'Unknown error');
113
- }
114
- return response.json();
115
- }
116
- async createApiKeyWithJwt(accessToken, name) {
117
- const response = await fetch(`${this.apiUrl}/api/auth/api-keys`, {
118
- method: 'POST',
119
- headers: {
120
- 'Content-Type': 'application/json',
121
- 'Authorization': `Bearer ${accessToken}`,
122
- 'User-Agent': `tusky-cli/${VERSION}`,
123
- },
124
- body: JSON.stringify({ name, scopes: ['files:read', 'files:write', 'vaults:read', 'vaults:write'] }),
125
- });
126
- if (!response.ok) {
127
- const error = await response.json().catch(() => ({ error: response.statusText }));
128
- throw new TuskyDPApiError(response.status, error.error || 'Unknown error');
129
- }
130
- return response.json();
131
- }
132
- // Account
133
- async getAccount() {
134
- return this.request('GET', '/api/account');
135
- }
136
- // Plans
137
- async getPlans() {
138
- // Public endpoint — no auth needed but request() adds it harmlessly
139
- return this.request('GET', '/api/plans');
140
- }
141
- // API Keys
142
- async createApiKey(params) {
143
- return this.request('POST', '/api/auth/api-keys', params);
144
- }
145
- async listApiKeys() {
146
- return this.request('GET', '/api/auth/api-keys');
147
- }
148
- async revokeApiKey(keyId) {
149
- return this.request('DELETE', `/api/auth/api-keys/${keyId}`);
150
- }
151
- }
152
- //# sourceMappingURL=client.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"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"}