@involvex/syncstuff-cli 0.0.1 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@involvex/syncstuff-cli",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "type": "module",
5
5
  "homepage": "https://syncstuff-web.involvex.workers.dev/",
6
6
  "sponsor": {
@@ -10,7 +10,7 @@
10
10
  "name": "involvex"
11
11
  },
12
12
  "bin": {
13
- "syncstuff": "src/cli/index.ts"
13
+ "syncstuff": "dist/cli.js"
14
14
  },
15
15
  "scripts": {
16
16
  "dev": "bun run src/cli/index.ts",
@@ -1,7 +1,7 @@
1
1
  import chalk from "chalk";
2
2
  import { existsSync, statSync } from "fs";
3
3
  import inquirer from "inquirer";
4
- import { resolve } from "path";
4
+ import { basename, resolve } from "path";
5
5
  import { apiClient } from "../../utils/api-client.js";
6
6
  import { debugLog, type CommandContext } from "../../utils/context.js";
7
7
  import {
@@ -11,8 +11,20 @@ import {
11
11
  printHeader,
12
12
  printSeparator,
13
13
  success,
14
+ warning,
14
15
  } from "../../utils/ui.js";
15
16
 
17
+ /**
18
+ * Format file size for display
19
+ */
20
+ function formatFileSize(bytes: number): string {
21
+ if (bytes < 1024) return `${bytes} B`;
22
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(2)} KB`;
23
+ if (bytes < 1024 * 1024 * 1024)
24
+ return `${(bytes / 1024 / 1024).toFixed(2)} MB`;
25
+ return `${(bytes / 1024 / 1024 / 1024).toFixed(2)} GB`;
26
+ }
27
+
16
28
  export async function transferFile(
17
29
  filePath: string | undefined,
18
30
  ctx: CommandContext,
@@ -24,11 +36,13 @@ export async function transferFile(
24
36
  error("You are not logged in. Please run 'syncstuff login' first.");
25
37
  process.exit(1);
26
38
  }
39
+ debugLog(ctx, "Authentication verified");
27
40
 
28
41
  let targetFile = filePath;
29
42
 
30
43
  // If no file path provided, prompt for it
31
44
  if (!targetFile) {
45
+ debugLog(ctx, "No file path provided, prompting user");
32
46
  const answers = await inquirer.prompt([
33
47
  {
34
48
  type: "input",
@@ -58,6 +72,7 @@ export async function transferFile(
58
72
  }
59
73
 
60
74
  const resolvedPath = resolve(targetFile);
75
+ debugLog(ctx, "Resolved file path", { resolvedPath });
61
76
 
62
77
  if (!existsSync(resolvedPath)) {
63
78
  error(`File not found: ${resolvedPath}`);
@@ -71,16 +86,31 @@ export async function transferFile(
71
86
 
72
87
  // Get file info
73
88
  const stats = statSync(resolvedPath);
74
- const fileSize = (stats.size / 1024 / 1024).toFixed(2);
75
-
76
- info(`File: ${resolvedPath}`);
77
- info(`Size: ${fileSize} MB`);
89
+ const fileName = basename(resolvedPath);
90
+ const fileSize = formatFileSize(stats.size);
91
+
92
+ debugLog(ctx, "File info", {
93
+ name: fileName,
94
+ size: stats.size,
95
+ formattedSize: fileSize,
96
+ modified: stats.mtime,
97
+ });
98
+
99
+ printSeparator();
100
+ console.log(chalk.cyan("File Details:"));
101
+ console.log(` Name: ${chalk.bold(fileName)}`);
102
+ console.log(` Path: ${resolvedPath}`);
103
+ console.log(` Size: ${chalk.yellow(fileSize)}`);
104
+ printSeparator();
78
105
 
79
106
  // Get device list
80
- const devicesSpinner = createSpinner("Fetching devices...");
107
+ const devicesSpinner = createSpinner("Fetching available devices...");
81
108
  devicesSpinner.start();
82
109
 
110
+ debugLog(ctx, "Fetching devices from API");
83
111
  const devicesResponse = await apiClient.getDevices();
112
+ debugLog(ctx, "Devices response", devicesResponse);
113
+
84
114
  devicesSpinner.stop();
85
115
 
86
116
  if (
@@ -88,15 +118,32 @@ export async function transferFile(
88
118
  !devicesResponse.data ||
89
119
  devicesResponse.data.length === 0
90
120
  ) {
91
- error(
92
- "No devices available. Please ensure at least one device is connected.",
93
- );
121
+ if (devicesResponse.error) {
122
+ debugLog(ctx, "Devices API error", { error: devicesResponse.error });
123
+ error(`Failed to fetch devices: ${devicesResponse.error}`);
124
+ } else {
125
+ warning("No devices available.");
126
+ info("Make sure you have at least one device connected to your account.");
127
+ info("Run 'syncstuff devices' to see your registered devices.");
128
+ }
129
+ process.exit(1);
130
+ }
131
+
132
+ const onlineDevices = devicesResponse.data.filter(d => d.is_online);
133
+ debugLog(ctx, "Device counts", {
134
+ total: devicesResponse.data.length,
135
+ online: onlineDevices.length,
136
+ });
137
+
138
+ if (onlineDevices.length === 0) {
139
+ warning("All devices are offline.");
140
+ info("Start Syncstuff on your target device to receive files.");
94
141
  process.exit(1);
95
142
  }
96
143
 
97
144
  // Prompt for device selection
98
145
  const deviceChoices = devicesResponse.data.map(device => ({
99
- name: `${device.name} (${device.platform}) - ${device.is_online ? "Online" : "Offline"}`,
146
+ name: `${device.name} (${device.platform}) - ${device.is_online ? chalk.green("Online") : chalk.red("Offline")}`,
100
147
  value: device.id,
101
148
  disabled: !device.is_online ? "Offline" : false,
102
149
  }));
@@ -110,22 +157,38 @@ export async function transferFile(
110
157
  },
111
158
  ]);
112
159
 
160
+ const selectedDevice = devicesResponse.data.find(
161
+ d => d.id === deviceAnswer.deviceId,
162
+ );
163
+ debugLog(ctx, "Selected device", selectedDevice);
164
+
113
165
  // Transfer file
166
+ printSeparator();
114
167
  const transferSpinner = createSpinner(
115
- `Transferring ${chalk.cyan(resolvedPath)} to device...`,
168
+ `Transferring ${chalk.cyan(fileName)} to ${chalk.yellow(selectedDevice?.name || "device")}...`,
116
169
  );
117
170
  transferSpinner.start();
118
171
 
119
172
  try {
173
+ debugLog(ctx, "Initiating transfer API call", {
174
+ deviceId: deviceAnswer.deviceId,
175
+ filePath: resolvedPath,
176
+ });
177
+
120
178
  const transferResponse = await apiClient.transferFile(
121
179
  deviceAnswer.deviceId,
122
180
  resolvedPath,
123
181
  );
124
182
 
183
+ debugLog(ctx, "Transfer response", transferResponse);
184
+
125
185
  if (transferResponse.success) {
126
186
  transferSpinner.succeed("File transfer initiated!");
127
187
  printSeparator();
128
188
  success(`Transfer ID: ${transferResponse.data?.transferId || "N/A"}`);
189
+ info(`File: ${fileName}`);
190
+ info(`Size: ${fileSize}`);
191
+ info(`Target: ${selectedDevice?.name || deviceAnswer.deviceId}`);
129
192
  info("File is being synced to the target device");
130
193
  printSeparator();
131
194
  } else {
@@ -134,15 +197,19 @@ export async function transferFile(
134
197
  transferResponse.error?.includes("404") ||
135
198
  transferResponse.error?.includes("Not found")
136
199
  ) {
137
- info("File transfer endpoint not yet implemented in API");
200
+ warning("File transfer endpoint not yet implemented in API");
138
201
  info("This feature will be available soon!");
202
+ debugLog(ctx, "API endpoint not implemented");
139
203
  } else {
140
- error(transferResponse.error || "Unknown error");
204
+ error(transferResponse.error || "Unknown error occurred");
205
+ debugLog(ctx, "Transfer error", { error: transferResponse.error });
141
206
  }
142
207
  }
143
208
  } catch (err) {
144
209
  transferSpinner.fail("Transfer error");
145
- error(`Error: ${err instanceof Error ? err.message : String(err)}`);
210
+ const errorMessage = err instanceof Error ? err.message : String(err);
211
+ error(`Error: ${errorMessage}`);
212
+ debugLog(ctx, "Exception during transfer", { error: err });
146
213
  process.exit(1);
147
214
  }
148
215
  }
@@ -13,7 +13,7 @@ export function showversion() {
13
13
  try {
14
14
  const packagePath = join(__dirname, "../../../package.json");
15
15
  const packageJson = JSON.parse(readFileSync(packagePath, "utf-8"));
16
- const version = packageJson.version || "0.0.1";
16
+ const version = packageJson.version;
17
17
 
18
18
  const versionBox = createBox(
19
19
  chalk.cyan.bold("Syncstuff CLI\n\n") +
package/src/utils/ui.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  import boxen from "boxen";
2
2
  import chalk from "chalk";
3
+ import { readFileSync } from "fs";
3
4
  import ora from "ora";
5
+ import { join } from "path";
4
6
  import Table from "table";
5
7
 
6
8
  export function success(message: string): void {
@@ -69,9 +71,12 @@ export function animateText(text: string, delay: number = 50): Promise<void> {
69
71
  }
70
72
 
71
73
  export function printHeader(): void {
74
+ const packagePath = join(__dirname, "../../../../package.json");
75
+ const packageJson = JSON.parse(readFileSync(packagePath, "utf-8"));
76
+ const version = packageJson.version;
72
77
  const header = chalk.cyan.bold(`
73
78
  ╔═══════════════════════════════════════╗
74
- ║ Syncstuff CLI v0.0.1
79
+ ║ Syncstuff CLI v${version}
75
80
  ║ Seamless Sync Across Devices ║
76
81
  ╚═══════════════════════════════════════╝
77
82
  `);