cfpan-cli 0.1.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 (74) hide show
  1. package/README.md +69 -0
  2. package/dist/api/auth.d.ts +15 -0
  3. package/dist/api/auth.d.ts.map +1 -0
  4. package/dist/api/auth.js +20 -0
  5. package/dist/api/auth.js.map +1 -0
  6. package/dist/api/client.d.ts +20 -0
  7. package/dist/api/client.d.ts.map +1 -0
  8. package/dist/api/client.js +81 -0
  9. package/dist/api/client.js.map +1 -0
  10. package/dist/api/download.d.ts +3 -0
  11. package/dist/api/download.d.ts.map +1 -0
  12. package/dist/api/download.js +50 -0
  13. package/dist/api/download.js.map +1 -0
  14. package/dist/api/files.d.ts +50 -0
  15. package/dist/api/files.d.ts.map +1 -0
  16. package/dist/api/files.js +56 -0
  17. package/dist/api/files.js.map +1 -0
  18. package/dist/api/share.d.ts +15 -0
  19. package/dist/api/share.d.ts.map +1 -0
  20. package/dist/api/share.js +21 -0
  21. package/dist/api/share.js.map +1 -0
  22. package/dist/api/upload.d.ts +35 -0
  23. package/dist/api/upload.d.ts.map +1 -0
  24. package/dist/api/upload.js +65 -0
  25. package/dist/api/upload.js.map +1 -0
  26. package/dist/commands/download.d.ts +3 -0
  27. package/dist/commands/download.d.ts.map +1 -0
  28. package/dist/commands/download.js +33 -0
  29. package/dist/commands/download.js.map +1 -0
  30. package/dist/commands/login.d.ts +3 -0
  31. package/dist/commands/login.d.ts.map +1 -0
  32. package/dist/commands/login.js +35 -0
  33. package/dist/commands/login.js.map +1 -0
  34. package/dist/commands/logout.d.ts +3 -0
  35. package/dist/commands/logout.d.ts.map +1 -0
  36. package/dist/commands/logout.js +16 -0
  37. package/dist/commands/logout.js.map +1 -0
  38. package/dist/commands/ls.d.ts +3 -0
  39. package/dist/commands/ls.d.ts.map +1 -0
  40. package/dist/commands/ls.js +92 -0
  41. package/dist/commands/ls.js.map +1 -0
  42. package/dist/commands/mkdir.d.ts +3 -0
  43. package/dist/commands/mkdir.d.ts.map +1 -0
  44. package/dist/commands/mkdir.js +29 -0
  45. package/dist/commands/mkdir.js.map +1 -0
  46. package/dist/commands/rm.d.ts +4 -0
  47. package/dist/commands/rm.d.ts.map +1 -0
  48. package/dist/commands/rm.js +69 -0
  49. package/dist/commands/rm.js.map +1 -0
  50. package/dist/commands/share.d.ts +3 -0
  51. package/dist/commands/share.d.ts.map +1 -0
  52. package/dist/commands/share.js +64 -0
  53. package/dist/commands/share.js.map +1 -0
  54. package/dist/commands/upload.d.ts +3 -0
  55. package/dist/commands/upload.d.ts.map +1 -0
  56. package/dist/commands/upload.js +44 -0
  57. package/dist/commands/upload.js.map +1 -0
  58. package/dist/config.d.ts +15 -0
  59. package/dist/config.d.ts.map +1 -0
  60. package/dist/config.js +52 -0
  61. package/dist/config.js.map +1 -0
  62. package/dist/index.d.ts +3 -0
  63. package/dist/index.d.ts.map +1 -0
  64. package/dist/index.js +27 -0
  65. package/dist/index.js.map +1 -0
  66. package/dist/utils/format.d.ts +10 -0
  67. package/dist/utils/format.d.ts.map +1 -0
  68. package/dist/utils/format.js +66 -0
  69. package/dist/utils/format.js.map +1 -0
  70. package/dist/utils/progress.d.ts +8 -0
  71. package/dist/utils/progress.d.ts.map +1 -0
  72. package/dist/utils/progress.js +40 -0
  73. package/dist/utils/progress.js.map +1 -0
  74. package/package.json +40 -0
package/README.md ADDED
@@ -0,0 +1,69 @@
1
+ # @cfpan/cli
2
+
3
+ CLI tool for CFpan - self-hosted netdisk on Cloudflare Workers.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install -g @cfpan/cli
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```bash
14
+ # Login to your CFpan instance
15
+ cfpan login https://your-cfpan-domain.com
16
+
17
+ # List files
18
+ cfpan ls
19
+
20
+ # Upload a file
21
+ cfpan upload ./local-file.txt /remote/path/
22
+
23
+ # Download a file
24
+ cfpan download /remote/file.txt ./local/
25
+
26
+ # Create a share link
27
+ cfpan share /path/to/file
28
+ ```
29
+
30
+ ## Commands
31
+
32
+ ### Authentication
33
+ - `cfpan login <endpoint>` - Login to CFpan instance
34
+ - `cfpan logout` - Logout from current session
35
+
36
+ ### File Operations
37
+ - `cfpan ls [path]` - List files and folders
38
+ - `cfpan upload <local> <remote>` - Upload file(s)
39
+ - `cfpan download <remote> <local>` - Download file(s)
40
+ - `cfpan mkdir <path>` - Create folder
41
+ - `cfpan rm <path>` - Delete file/folder (move to trash)
42
+ - `cfpan mv <source> <dest>` - Move/rename file/folder
43
+
44
+ ### Sharing
45
+ - `cfpan share <path>` - Create share link
46
+ - `cfpan share <path> --code <6-digit>` - Create share with access code
47
+
48
+ ### Storage
49
+ - `cfpan quota` - Show storage quota
50
+
51
+ ## Configuration
52
+
53
+ Configuration is stored in `~/.cfpan/config.json`:
54
+
55
+ ```json
56
+ {
57
+ "profiles": {
58
+ "default": {
59
+ "endpoint": "https://your-cfpan.com",
60
+ "token": "cfpan_xxxxx"
61
+ }
62
+ },
63
+ "activeProfile": "default"
64
+ }
65
+ ```
66
+
67
+ ## License
68
+
69
+ MIT
@@ -0,0 +1,15 @@
1
+ import type { ApiClient } from './client.js';
2
+ export interface LoginResponse {
3
+ token: string;
4
+ expiresAt: string;
5
+ }
6
+ export interface TokenInfo {
7
+ id: string;
8
+ name: string;
9
+ createdAt: string;
10
+ lastUsedAt: string | null;
11
+ }
12
+ export declare function login(endpoint: string, username: string, password: string): Promise<LoginResponse>;
13
+ export declare function listTokens(client: ApiClient): Promise<TokenInfo[]>;
14
+ export declare function revokeToken(client: ApiClient, tokenId: string): Promise<void>;
15
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/api/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,wBAAsB,KAAK,CACzB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,aAAa,CAAC,CAiBxB;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAExE;AAED,wBAAsB,WAAW,CAC/B,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CAEf"}
@@ -0,0 +1,20 @@
1
+ export async function login(endpoint, username, password) {
2
+ const url = `${endpoint.replace(/\/$/, '')}/api/admin/auth/token`;
3
+ const response = await fetch(url, {
4
+ method: 'POST',
5
+ headers: { 'Content-Type': 'application/json' },
6
+ body: JSON.stringify({ username, password, name: 'CLI' }),
7
+ });
8
+ if (!response.ok) {
9
+ const body = (await response.json().catch(() => ({})));
10
+ throw new Error(body.message ?? `Login failed: ${response.status}`);
11
+ }
12
+ return (await response.json());
13
+ }
14
+ export async function listTokens(client) {
15
+ return client.get('/api/admin/auth/tokens');
16
+ }
17
+ export async function revokeToken(client, tokenId) {
18
+ await client.delete(`/api/admin/auth/tokens/${tokenId}`);
19
+ }
20
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/api/auth.ts"],"names":[],"mappings":"AAcA,MAAM,CAAC,KAAK,UAAU,KAAK,CACzB,QAAgB,EAChB,QAAgB,EAChB,QAAgB;IAEhB,MAAM,GAAG,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,uBAAuB,CAAC;IAClE,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAChC,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;KAC1D,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAGpD,CAAC;QACF,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,IAAI,iBAAiB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IACtE,CAAC;IAED,OAAO,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAkB,CAAC;AAClD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,MAAiB;IAChD,OAAO,MAAM,CAAC,GAAG,CAAc,wBAAwB,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,MAAiB,EACjB,OAAe;IAEf,MAAM,MAAM,CAAC,MAAM,CAAC,0BAA0B,OAAO,EAAE,CAAC,CAAC;AAC3D,CAAC"}
@@ -0,0 +1,20 @@
1
+ import { type RequestInit, type Response } from 'node-fetch';
2
+ import type { ProfileConfig } from '../config.js';
3
+ export declare class ApiError extends Error {
4
+ readonly status: number;
5
+ readonly code: string;
6
+ readonly retryAfter?: number | undefined;
7
+ constructor(status: number, code: string, message: string, retryAfter?: number | undefined);
8
+ }
9
+ export declare class ApiClient {
10
+ private endpoint;
11
+ private token;
12
+ constructor(profile: ProfileConfig);
13
+ private request;
14
+ get<T>(path: string): Promise<T>;
15
+ post<T>(path: string, body?: unknown): Promise<T>;
16
+ patch<T>(path: string, body: unknown): Promise<T>;
17
+ delete<T>(path: string, body?: unknown): Promise<T>;
18
+ fetch(path: string, init?: RequestInit): Promise<Response>;
19
+ }
20
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAAA,OAAc,EAAE,KAAK,WAAW,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,CAAC;AACpE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD,qBAAa,QAAS,SAAQ,KAAK;aAEf,MAAM,EAAE,MAAM;aACd,IAAI,EAAE,MAAM;aAEZ,UAAU,CAAC,EAAE,MAAM;gBAHnB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EAC5B,OAAO,EAAE,MAAM,EACC,UAAU,CAAC,EAAE,MAAM,YAAA;CAKtC;AAED,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,KAAK,CAAS;gBAEV,OAAO,EAAE,aAAa;YAKpB,OAAO;IAiCf,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAIhC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC;IAOjD,KAAK,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC;IAOjD,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC;IAQnD,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC;CAwBjE"}
@@ -0,0 +1,81 @@
1
+ import fetch from 'node-fetch';
2
+ export class ApiError extends Error {
3
+ status;
4
+ code;
5
+ retryAfter;
6
+ constructor(status, code, message, retryAfter) {
7
+ super(message);
8
+ this.status = status;
9
+ this.code = code;
10
+ this.retryAfter = retryAfter;
11
+ this.name = 'ApiError';
12
+ }
13
+ }
14
+ export class ApiClient {
15
+ endpoint;
16
+ token;
17
+ constructor(profile) {
18
+ this.endpoint = profile.endpoint.replace(/\/$/, '');
19
+ this.token = profile.token;
20
+ }
21
+ async request(path, init) {
22
+ const url = `${this.endpoint}${path}`;
23
+ let response;
24
+ try {
25
+ response = await fetch(url, {
26
+ ...init,
27
+ headers: {
28
+ Authorization: `Bearer ${this.token}`,
29
+ ...(init?.body ? { 'Content-Type': 'application/json' } : {}),
30
+ ...init?.headers,
31
+ },
32
+ });
33
+ }
34
+ catch (error) {
35
+ throw new ApiError(0, 'network_error', `Network error: ${error}`);
36
+ }
37
+ if (!response.ok) {
38
+ const body = (await response.json().catch(() => ({})));
39
+ throw new ApiError(response.status, body.error ?? 'request_failed', body.message ?? `Request failed with status ${response.status}`, Number(response.headers.get('Retry-After')) || undefined);
40
+ }
41
+ return (await response.json());
42
+ }
43
+ async get(path) {
44
+ return this.request(path, { method: 'GET' });
45
+ }
46
+ async post(path, body) {
47
+ return this.request(path, {
48
+ method: 'POST',
49
+ body: body ? JSON.stringify(body) : undefined,
50
+ });
51
+ }
52
+ async patch(path, body) {
53
+ return this.request(path, {
54
+ method: 'PATCH',
55
+ body: JSON.stringify(body),
56
+ });
57
+ }
58
+ async delete(path, body) {
59
+ return this.request(path, {
60
+ method: 'DELETE',
61
+ body: body ? JSON.stringify(body) : undefined,
62
+ });
63
+ }
64
+ // Raw fetch for binary data (downloads)
65
+ async fetch(path, init) {
66
+ const url = `${this.endpoint}${path}`;
67
+ const response = await fetch(url, {
68
+ ...init,
69
+ headers: {
70
+ Authorization: `Bearer ${this.token}`,
71
+ ...init?.headers,
72
+ },
73
+ });
74
+ if (!response.ok) {
75
+ const body = (await response.json().catch(() => ({})));
76
+ throw new ApiError(response.status, body.error ?? 'request_failed', body.message ?? `Request failed with status ${response.status}`);
77
+ }
78
+ return response;
79
+ }
80
+ }
81
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { ApiClient } from './client.js';
2
+ export declare function downloadFile(client: ApiClient, fileId: string, localPath: string, onProgress?: (downloaded: number, total: number) => void): Promise<void>;
3
+ //# sourceMappingURL=download.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"download.d.ts","sourceRoot":"","sources":["../../src/api/download.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAK7C,wBAAsB,YAAY,CAChC,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,UAAU,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,GACvD,OAAO,CAAC,IAAI,CAAC,CA0Df"}
@@ -0,0 +1,50 @@
1
+ import { createWriteStream } from 'node:fs';
2
+ import { pipeline } from 'node:stream/promises';
3
+ import { Readable } from 'node:stream';
4
+ export async function downloadFile(client, fileId, localPath, onProgress) {
5
+ const downloadUrl = `/api/admin/files/${encodeURIComponent(fileId)}/download`;
6
+ const response = await client.fetch(downloadUrl);
7
+ if (response.status === 302) {
8
+ // Follow redirect to presigned URL
9
+ const redirectUrl = response.headers.get('location');
10
+ if (!redirectUrl) {
11
+ throw new Error('No redirect URL in response');
12
+ }
13
+ const actualResponse = await fetch(redirectUrl);
14
+ if (!actualResponse.ok) {
15
+ throw new Error(`Download failed: ${actualResponse.status}`);
16
+ }
17
+ const contentLength = Number(actualResponse.headers.get('content-length')) || 0;
18
+ const writeStream = createWriteStream(localPath);
19
+ if (onProgress && contentLength > 0 && actualResponse.body) {
20
+ let downloaded = 0;
21
+ const nodeStream = Readable.fromWeb(actualResponse.body);
22
+ nodeStream.on('data', (chunk) => {
23
+ downloaded += chunk.length;
24
+ onProgress(downloaded, contentLength);
25
+ });
26
+ await pipeline(nodeStream, writeStream);
27
+ }
28
+ else if (actualResponse.body) {
29
+ await pipeline(Readable.fromWeb(actualResponse.body), writeStream);
30
+ }
31
+ }
32
+ else {
33
+ // Direct download
34
+ const contentLength = Number(response.headers.get('content-length')) || 0;
35
+ const writeStream = createWriteStream(localPath);
36
+ if (onProgress && contentLength > 0 && response.body) {
37
+ let downloaded = 0;
38
+ const nodeStream = Readable.fromWeb(response.body);
39
+ nodeStream.on('data', (chunk) => {
40
+ downloaded += chunk.length;
41
+ onProgress(downloaded, contentLength);
42
+ });
43
+ await pipeline(nodeStream, writeStream);
44
+ }
45
+ else if (response.body) {
46
+ await pipeline(Readable.fromWeb(response.body), writeStream);
47
+ }
48
+ }
49
+ }
50
+ //# sourceMappingURL=download.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"download.js","sourceRoot":"","sources":["../../src/api/download.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ import type { ApiClient } from './client.js';
2
+ export interface FileEntry {
3
+ id: string;
4
+ name: string;
5
+ type: 'file' | 'folder';
6
+ size: number;
7
+ createdAt: string;
8
+ favorite: boolean;
9
+ shared: boolean;
10
+ }
11
+ export interface AdminFileListResponse {
12
+ files: FileEntry[];
13
+ folders: FileEntry[];
14
+ breadcrumbs: Array<{
15
+ id: string;
16
+ name: string;
17
+ }>;
18
+ hasMore: boolean;
19
+ total: number;
20
+ used: number;
21
+ capacity: number;
22
+ }
23
+ export interface FileListOptions {
24
+ folderId?: string | null;
25
+ limit?: number;
26
+ offset?: number;
27
+ reverse?: boolean;
28
+ scope?: 'all' | 'current';
29
+ search?: string;
30
+ sort?: 'created' | 'name' | 'size' | 'type';
31
+ view?: 'files' | 'recent' | 'favorites' | 'shared' | 'trash';
32
+ }
33
+ export declare function listFiles(client: ApiClient, options?: FileListOptions): Promise<AdminFileListResponse>;
34
+ export interface FolderCreateRequest {
35
+ name: string;
36
+ parentId?: string | null;
37
+ }
38
+ export declare function createFolder(client: ApiClient, request: FolderCreateRequest): Promise<FileEntry>;
39
+ export declare function deleteFile(client: ApiClient, fileId: string): Promise<{
40
+ status: 'deleted' | 'deleting';
41
+ }>;
42
+ export declare function deleteFolder(client: ApiClient, folderId: string): Promise<{
43
+ status: 'deleted';
44
+ }>;
45
+ export declare function restoreFile(client: ApiClient, fileId: string): Promise<FileEntry>;
46
+ export declare function restoreFolder(client: ApiClient, folderId: string): Promise<FileEntry>;
47
+ export declare function moveFile(client: ApiClient, fileId: string, targetFolderId: string | null): Promise<FileEntry>;
48
+ export declare function renameFile(client: ApiClient, fileId: string, newName: string): Promise<FileEntry>;
49
+ export declare function renameFolder(client: ApiClient, folderId: string, newName: string): Promise<FileEntry>;
50
+ //# sourceMappingURL=files.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../../src/api/files.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,OAAO,EAAE,SAAS,EAAE,CAAC;IACrB,WAAW,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACjD,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,KAAK,GAAG,SAAS,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;IAC5C,IAAI,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,WAAW,GAAG,QAAQ,GAAG,OAAO,CAAC;CAC9D;AAED,wBAAsB,SAAS,CAC7B,MAAM,EAAE,SAAS,EACjB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,qBAAqB,CAAC,CAuBhC;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,wBAAsB,YAAY,CAChC,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,SAAS,CAAC,CAEpB;AAED,wBAAsB,UAAU,CAC9B,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC;IAAE,MAAM,EAAE,SAAS,GAAG,UAAU,CAAA;CAAE,CAAC,CAE7C;AAED,wBAAsB,YAAY,CAChC,MAAM,EAAE,SAAS,EACjB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;IAAE,MAAM,EAAE,SAAS,CAAA;CAAE,CAAC,CAEhC;AAED,wBAAsB,WAAW,CAC/B,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,SAAS,CAAC,CAEpB;AAED,wBAAsB,aAAa,CACjC,MAAM,EAAE,SAAS,EACjB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,SAAS,CAAC,CAEpB;AAED,wBAAsB,QAAQ,CAC5B,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,MAAM,GAAG,IAAI,GAC5B,OAAO,CAAC,SAAS,CAAC,CAIpB;AAED,wBAAsB,UAAU,CAC9B,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,SAAS,CAAC,CAIpB;AAED,wBAAsB,YAAY,CAChC,MAAM,EAAE,SAAS,EACjB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,SAAS,CAAC,CAIpB"}
@@ -0,0 +1,56 @@
1
+ export async function listFiles(client, options = {}) {
2
+ const params = new URLSearchParams();
3
+ if (options.view && options.view !== 'files') {
4
+ params.set('view', options.view);
5
+ }
6
+ if (options.folderId && (options.view ?? 'files') === 'files') {
7
+ params.set('folderId', options.folderId);
8
+ }
9
+ if (options.search)
10
+ params.set('search', options.search);
11
+ if (options.search && options.scope === 'current') {
12
+ params.set('scope', 'current');
13
+ }
14
+ if (options.sort && options.sort !== 'created') {
15
+ params.set('sort', options.sort);
16
+ }
17
+ if (options.reverse)
18
+ params.set('reverse', '1');
19
+ if (options.limit)
20
+ params.set('limit', String(options.limit));
21
+ if (options.offset)
22
+ params.set('offset', String(options.offset));
23
+ const path = params.size === 0 ? '/api/admin/files' : `/api/admin/files?${params}`;
24
+ return client.get(path);
25
+ }
26
+ export async function createFolder(client, request) {
27
+ return client.post('/api/admin/folders', request);
28
+ }
29
+ export async function deleteFile(client, fileId) {
30
+ return client.delete(`/api/admin/files/${fileId}`, { confirm: true });
31
+ }
32
+ export async function deleteFolder(client, folderId) {
33
+ return client.delete(`/api/admin/folders/${folderId}`, { confirm: true });
34
+ }
35
+ export async function restoreFile(client, fileId) {
36
+ return client.post(`/api/admin/files/${fileId}/restore`, {});
37
+ }
38
+ export async function restoreFolder(client, folderId) {
39
+ return client.post(`/api/admin/folders/${folderId}/restore`, {});
40
+ }
41
+ export async function moveFile(client, fileId, targetFolderId) {
42
+ return client.patch(`/api/admin/files/${fileId}`, {
43
+ folderId: targetFolderId,
44
+ });
45
+ }
46
+ export async function renameFile(client, fileId, newName) {
47
+ return client.patch(`/api/admin/files/${fileId}`, {
48
+ name: newName,
49
+ });
50
+ }
51
+ export async function renameFolder(client, folderId, newName) {
52
+ return client.patch(`/api/admin/folders/${folderId}`, {
53
+ name: newName,
54
+ });
55
+ }
56
+ //# sourceMappingURL=files.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"files.js","sourceRoot":"","sources":["../../src/api/files.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { ApiClient } from './client.js';
2
+ export interface ShareUpdateRequest {
3
+ accessCode?: 'random' | string | null;
4
+ cancel?: true;
5
+ expiry?: '1h' | '5h' | '24h' | '3d' | '7d' | 'permanent';
6
+ }
7
+ export interface ShareResponse {
8
+ shareUrl: string;
9
+ accessCode?: string;
10
+ expiresAt?: string;
11
+ }
12
+ export declare function createFileShare(client: ApiClient, fileId: string, options?: ShareUpdateRequest): Promise<ShareResponse>;
13
+ export declare function createFolderShare(client: ApiClient, folderId: string, options?: ShareUpdateRequest): Promise<ShareResponse>;
14
+ export declare function cancelShare(client: ApiClient, fileId: string, isFolder?: boolean): Promise<void>;
15
+ //# sourceMappingURL=share.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"share.d.ts","sourceRoot":"","sources":["../../src/api/share.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,WAAW,kBAAkB;IACjC,UAAU,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,IAAI,CAAC;IACtC,MAAM,CAAC,EAAE,IAAI,CAAC;IACd,MAAM,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,KAAK,GAAG,IAAI,GAAG,IAAI,GAAG,WAAW,CAAC;CAC1D;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAsB,eAAe,CACnC,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,aAAa,CAAC,CASxB;AAED,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,SAAS,EACjB,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,aAAa,CAAC,CASxB;AAED,wBAAsB,WAAW,CAC/B,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,MAAM,EACd,QAAQ,GAAE,OAAe,GACxB,OAAO,CAAC,IAAI,CAAC,CAKf"}
@@ -0,0 +1,21 @@
1
+ export async function createFileShare(client, fileId, options = {}) {
2
+ const response = await client.patch(`/api/admin/files/${fileId}/share`, options);
3
+ if (!response.share) {
4
+ throw new Error('Failed to create share');
5
+ }
6
+ return response.share;
7
+ }
8
+ export async function createFolderShare(client, folderId, options = {}) {
9
+ const response = await client.patch(`/api/admin/folders/${folderId}/share`, options);
10
+ if (!response.share) {
11
+ throw new Error('Failed to create share');
12
+ }
13
+ return response.share;
14
+ }
15
+ export async function cancelShare(client, fileId, isFolder = false) {
16
+ const path = isFolder
17
+ ? `/api/admin/folders/${fileId}/share`
18
+ : `/api/admin/files/${fileId}/share`;
19
+ await client.patch(path, { cancel: true });
20
+ }
21
+ //# sourceMappingURL=share.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"share.js","sourceRoot":"","sources":["../../src/api/share.ts"],"names":[],"mappings":"AAcA,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,MAAiB,EACjB,MAAc,EACd,UAA8B,EAAE;IAEhC,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,KAAK,CACjC,oBAAoB,MAAM,QAAQ,EAClC,OAAO,CACR,CAAC;IACF,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;IAC5C,CAAC;IACD,OAAO,QAAQ,CAAC,KAAK,CAAC;AACxB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,MAAiB,EACjB,QAAgB,EAChB,UAA8B,EAAE;IAEhC,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,KAAK,CACjC,sBAAsB,QAAQ,QAAQ,EACtC,OAAO,CACR,CAAC;IACF,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;IAC5C,CAAC;IACD,OAAO,QAAQ,CAAC,KAAK,CAAC;AACxB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,MAAiB,EACjB,MAAc,EACd,WAAoB,KAAK;IAEzB,MAAM,IAAI,GAAG,QAAQ;QACnB,CAAC,CAAC,sBAAsB,MAAM,QAAQ;QACtC,CAAC,CAAC,oBAAoB,MAAM,QAAQ,CAAC;IACvC,MAAM,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;AAC7C,CAAC"}
@@ -0,0 +1,35 @@
1
+ import type { ApiClient } from './client.js';
2
+ export interface UploadInitRequest {
3
+ bucketId?: string;
4
+ contentType: string;
5
+ folderId?: string | null;
6
+ name: string;
7
+ nameConflict?: 'reject' | 'overwrite' | 'rename';
8
+ size: number;
9
+ }
10
+ export interface UploadInitResponse {
11
+ uploadId: string;
12
+ fileId: string;
13
+ objectUploadId: string;
14
+ totalParts: number;
15
+ partSize: number;
16
+ originalName?: string;
17
+ }
18
+ export interface UploadSignPartsResponse {
19
+ parts: Array<{
20
+ partNumber: number;
21
+ url: string;
22
+ }>;
23
+ }
24
+ export interface UploadCompleteRequest {
25
+ parts: Array<{
26
+ partNumber: number;
27
+ etag: string;
28
+ }>;
29
+ }
30
+ export interface UploadCompleteResponse {
31
+ fileId: string;
32
+ status: 'completed';
33
+ }
34
+ export declare function uploadFile(client: ApiClient, localPath: string, remotePath: string, folderId: string | null, onProgress?: (uploaded: number, total: number) => void): Promise<void>;
35
+ //# sourceMappingURL=upload.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../../src/api/upload.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAO7C,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,QAAQ,GAAG,WAAW,GAAG,QAAQ,CAAC;IACjD,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,KAAK,CAAC;QACX,UAAU,EAAE,MAAM,CAAC;QACnB,GAAG,EAAE,MAAM,CAAC;KACb,CAAC,CAAC;CACJ;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,KAAK,CAAC;QACX,UAAU,EAAE,MAAM,CAAC;QACnB,IAAI,EAAE,MAAM,CAAC;KACd,CAAC,CAAC;CACJ;AAED,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,WAAW,CAAC;CACrB;AAED,wBAAsB,UAAU,CAC9B,MAAM,EAAE,SAAS,EACjB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,GACrD,OAAO,CAAC,IAAI,CAAC,CAmFf"}
@@ -0,0 +1,65 @@
1
+ import { createReadStream, statSync } from 'node:fs';
2
+ import { basename } from 'node:path';
3
+ import fetch from 'node-fetch';
4
+ const PART_SIZE = 10 * 1024 * 1024; // 10MB per part
5
+ export async function uploadFile(client, localPath, remotePath, folderId, onProgress) {
6
+ const stats = statSync(localPath);
7
+ const fileName = remotePath || basename(localPath);
8
+ // 1. Initialize upload
9
+ const initRequest = {
10
+ name: fileName,
11
+ size: stats.size,
12
+ contentType: 'application/octet-stream',
13
+ folderId,
14
+ nameConflict: 'reject',
15
+ };
16
+ const initResponse = await client.post('/api/admin/uploads/init', initRequest);
17
+ const { uploadId, totalParts } = initResponse;
18
+ try {
19
+ // 2. Upload parts
20
+ const parts = [];
21
+ for (let i = 0; i < totalParts; i++) {
22
+ const partNumber = i + 1;
23
+ // Get signed URL
24
+ const signResponse = await client.post(`/api/admin/uploads/${uploadId}/sign-parts`, { partNumbers: [partNumber] });
25
+ const signedUrl = signResponse.parts[0]?.url;
26
+ if (!signedUrl) {
27
+ throw new Error(`Failed to get signed URL for part ${partNumber}`);
28
+ }
29
+ // Read part data
30
+ const start = i * PART_SIZE;
31
+ const end = Math.min(start + PART_SIZE, stats.size);
32
+ const stream = createReadStream(localPath, { start, end: end - 1 });
33
+ // Upload to S3
34
+ const uploadResponse = await fetch(signedUrl, {
35
+ method: 'PUT',
36
+ body: stream,
37
+ headers: {
38
+ 'Content-Length': String(end - start),
39
+ },
40
+ });
41
+ if (!uploadResponse.ok) {
42
+ throw new Error(`Failed to upload part ${partNumber}: ${uploadResponse.status}`);
43
+ }
44
+ const etag = uploadResponse.headers.get('etag');
45
+ if (!etag) {
46
+ throw new Error(`No ETag returned for part ${partNumber}`);
47
+ }
48
+ parts.push({ partNumber, etag: etag.replace(/"/g, '') });
49
+ if (onProgress) {
50
+ onProgress(end, stats.size);
51
+ }
52
+ }
53
+ // 3. Complete upload
54
+ const completeRequest = { parts };
55
+ await client.post(`/api/admin/uploads/${uploadId}/complete`, completeRequest);
56
+ }
57
+ catch (error) {
58
+ // Abort upload on error
59
+ await client
60
+ .post(`/api/admin/uploads/${uploadId}/abort`, {})
61
+ .catch(() => { });
62
+ throw error;
63
+ }
64
+ }
65
+ //# sourceMappingURL=upload.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upload.js","sourceRoot":"","sources":["../../src/api/upload.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const downloadCommand: Command;
3
+ //# sourceMappingURL=download.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"download.d.ts","sourceRoot":"","sources":["../../src/commands/download.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC,eAAO,MAAM,eAAe,SA4BxB,CAAC"}
@@ -0,0 +1,33 @@
1
+ import { Command } from 'commander';
2
+ import { ApiClient } from '../api/client.js';
3
+ import { getActiveProfile } from '../config.js';
4
+ import { downloadFile } from '../api/download.js';
5
+ import { error, success } from '../utils/format.js';
6
+ import { createFileProgressBar } from '../utils/progress.js';
7
+ import { basename } from 'node:path';
8
+ export const downloadCommand = new Command('download')
9
+ .description('Download file from CFpan')
10
+ .argument('<file-id>', 'Remote file ID')
11
+ .argument('<local>', 'Local file path')
12
+ .action(async (fileId, local) => {
13
+ try {
14
+ const profile = await getActiveProfile();
15
+ if (!profile) {
16
+ error('Not logged in. Run: cfpan login <endpoint>');
17
+ process.exit(1);
18
+ }
19
+ const client = new ApiClient(profile);
20
+ const fileName = basename(local);
21
+ const progress = createFileProgressBar(fileName);
22
+ await downloadFile(client, fileId, local, (downloaded, total) => {
23
+ progress.update(downloaded, total);
24
+ });
25
+ progress.finish();
26
+ success(`Downloaded: ${local}`);
27
+ }
28
+ catch (err) {
29
+ error(`Download failed: ${err instanceof Error ? err.message : String(err)}`);
30
+ process.exit(1);
31
+ }
32
+ });
33
+ //# sourceMappingURL=download.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"download.js","sourceRoot":"","sources":["../../src/commands/download.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAErC,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,OAAO,CAAC,UAAU,CAAC;KACnD,WAAW,CAAC,0BAA0B,CAAC;KACvC,QAAQ,CAAC,WAAW,EAAE,gBAAgB,CAAC;KACvC,QAAQ,CAAC,SAAS,EAAE,iBAAiB,CAAC;KACtC,MAAM,CAAC,KAAK,EAAE,MAAc,EAAE,KAAa,EAAE,EAAE;IAC9C,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,gBAAgB,EAAE,CAAC;QACzC,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,KAAK,CAAC,4CAA4C,CAAC,CAAC;YACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,OAAO,CAAC,CAAC;QACtC,MAAM,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;QACjC,MAAM,QAAQ,GAAG,qBAAqB,CAAC,QAAQ,CAAC,CAAC;QAEjD,MAAM,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,UAAU,EAAE,KAAK,EAAE,EAAE;YAC9D,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;QACrC,CAAC,CAAC,CAAC;QAEH,QAAQ,CAAC,MAAM,EAAE,CAAC;QAClB,OAAO,CAAC,eAAe,KAAK,EAAE,CAAC,CAAC;IAClC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,KAAK,CACH,oBAAoB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CACvE,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const loginCommand: Command;
3
+ //# sourceMappingURL=login.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC,eAAO,MAAM,YAAY,SA4CtB,CAAC"}