@involvex/syncstuff-cli 0.0.3 → 0.0.5
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/dist/cli.js +128 -22
- package/package.json +1 -1
- package/src/cli/commands/debug.ts +3 -3
- package/src/cli/commands/devices.ts +71 -4
- package/src/cli/commands/version.ts +13 -1
- package/src/cli/index.ts +5 -1
- package/src/core.ts +2 -2
- package/src/utils/ui.ts +1 -1
- package/src/utils/update-checker.ts +86 -0
package/dist/cli.js
CHANGED
|
@@ -9641,7 +9641,7 @@ function createTable(data, headers) {
|
|
|
9641
9641
|
});
|
|
9642
9642
|
}
|
|
9643
9643
|
function printHeader() {
|
|
9644
|
-
const packagePath = join(__dirname, "
|
|
9644
|
+
const packagePath = join(__dirname, "../../package.json");
|
|
9645
9645
|
const packageJson = JSON.parse(readFileSync(packagePath, "utf-8"));
|
|
9646
9646
|
const version = packageJson.version;
|
|
9647
9647
|
const header = source_default.cyan.bold(`
|
|
@@ -20411,7 +20411,7 @@ var init_RemoveFileError = __esm(() => {
|
|
|
20411
20411
|
|
|
20412
20412
|
// ../../node_modules/.bun/@inquirer+external-editor@2.0.2+cda980ff03d0f389/node_modules/@inquirer/external-editor/dist/index.js
|
|
20413
20413
|
import { spawn, spawnSync } from "child_process";
|
|
20414
|
-
import { readFileSync as
|
|
20414
|
+
import { readFileSync as readFileSync3, unlinkSync, writeFileSync } from "fs";
|
|
20415
20415
|
import path from "node:path";
|
|
20416
20416
|
import os2 from "node:os";
|
|
20417
20417
|
import { randomUUID } from "node:crypto";
|
|
@@ -20527,7 +20527,7 @@ class ExternalEditor {
|
|
|
20527
20527
|
}
|
|
20528
20528
|
readTemporaryFile() {
|
|
20529
20529
|
try {
|
|
20530
|
-
const tempFileBuffer =
|
|
20530
|
+
const tempFileBuffer = readFileSync3(this.tempFile);
|
|
20531
20531
|
if (tempFileBuffer.length === 0) {
|
|
20532
20532
|
this.text = "";
|
|
20533
20533
|
} else {
|
|
@@ -30801,9 +30801,9 @@ var init_dist16 = __esm(() => {
|
|
|
30801
30801
|
});
|
|
30802
30802
|
|
|
30803
30803
|
// src/utils/config.ts
|
|
30804
|
-
import { mkdirSync, readFileSync as
|
|
30804
|
+
import { mkdirSync, readFileSync as readFileSync4, writeFileSync as writeFileSync2 } from "fs";
|
|
30805
30805
|
import { homedir } from "os";
|
|
30806
|
-
import { join as
|
|
30806
|
+
import { join as join3 } from "path";
|
|
30807
30807
|
function ensureConfigDir() {
|
|
30808
30808
|
try {
|
|
30809
30809
|
mkdirSync(CONFIG_DIR, { recursive: true });
|
|
@@ -30812,7 +30812,7 @@ function ensureConfigDir() {
|
|
|
30812
30812
|
function readConfig() {
|
|
30813
30813
|
ensureConfigDir();
|
|
30814
30814
|
try {
|
|
30815
|
-
const content =
|
|
30815
|
+
const content = readFileSync4(CONFIG_FILE, "utf-8");
|
|
30816
30816
|
return JSON.parse(content);
|
|
30817
30817
|
} catch {
|
|
30818
30818
|
return {};
|
|
@@ -30824,8 +30824,8 @@ function writeConfig(config) {
|
|
|
30824
30824
|
}
|
|
30825
30825
|
var CONFIG_DIR, CONFIG_FILE;
|
|
30826
30826
|
var init_config = __esm(() => {
|
|
30827
|
-
CONFIG_DIR =
|
|
30828
|
-
CONFIG_FILE =
|
|
30827
|
+
CONFIG_DIR = join3(homedir(), ".syncstuff");
|
|
30828
|
+
CONFIG_FILE = join3(CONFIG_DIR, "config.json");
|
|
30829
30829
|
});
|
|
30830
30830
|
|
|
30831
30831
|
// src/utils/api-client.ts
|
|
@@ -31079,8 +31079,17 @@ var exports_devices = {};
|
|
|
31079
31079
|
__export(exports_devices, {
|
|
31080
31080
|
listDevices: () => listDevices
|
|
31081
31081
|
});
|
|
31082
|
-
async function listDevices(ctx) {
|
|
31083
|
-
|
|
31082
|
+
async function listDevices(args, ctx) {
|
|
31083
|
+
const isLoop = args.includes("--loop") || args.includes("-l");
|
|
31084
|
+
debugLog(ctx, "Devices command", { loop: isLoop });
|
|
31085
|
+
if (isLoop) {
|
|
31086
|
+
await loopDevices(ctx);
|
|
31087
|
+
} else {
|
|
31088
|
+
printHeader();
|
|
31089
|
+
await fetchAndDisplayDevices(ctx);
|
|
31090
|
+
}
|
|
31091
|
+
}
|
|
31092
|
+
async function fetchAndDisplayDevices(ctx) {
|
|
31084
31093
|
debugLog(ctx, "Fetching devices list");
|
|
31085
31094
|
if (!apiClient.isAuthenticated()) {
|
|
31086
31095
|
error2("You are not logged in. Please run 'syncstuff login' first.");
|
|
@@ -31096,7 +31105,7 @@ async function listDevices(ctx) {
|
|
|
31096
31105
|
if (response.data.length === 0) {
|
|
31097
31106
|
info2("No devices found. Connect a device to get started.");
|
|
31098
31107
|
printSeparator();
|
|
31099
|
-
return;
|
|
31108
|
+
return true;
|
|
31100
31109
|
}
|
|
31101
31110
|
const tableData = response.data.map((device) => [
|
|
31102
31111
|
device.id.substring(0, 8) + "...",
|
|
@@ -31118,6 +31127,7 @@ async function listDevices(ctx) {
|
|
|
31118
31127
|
printSeparator();
|
|
31119
31128
|
success2(`Found ${response.data.length} device(s)`);
|
|
31120
31129
|
printSeparator();
|
|
31130
|
+
return true;
|
|
31121
31131
|
} else {
|
|
31122
31132
|
spinner.fail("Failed to fetch devices");
|
|
31123
31133
|
if (response.error?.includes("404") || response.error?.includes("Not found")) {
|
|
@@ -31126,13 +31136,39 @@ async function listDevices(ctx) {
|
|
|
31126
31136
|
} else {
|
|
31127
31137
|
error2(response.error || "Unknown error");
|
|
31128
31138
|
}
|
|
31139
|
+
return false;
|
|
31129
31140
|
}
|
|
31130
31141
|
} catch (err) {
|
|
31131
31142
|
spinner.fail("Error fetching devices");
|
|
31132
31143
|
error2(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
31133
|
-
|
|
31144
|
+
return false;
|
|
31134
31145
|
}
|
|
31135
31146
|
}
|
|
31147
|
+
async function loopDevices(ctx) {
|
|
31148
|
+
const REFRESH_INTERVAL = 5000;
|
|
31149
|
+
console.clear();
|
|
31150
|
+
printHeader();
|
|
31151
|
+
console.log(source_default.cyan("Loop mode enabled. Press Ctrl+C to exit."));
|
|
31152
|
+
console.log(source_default.gray(`Refreshing every ${REFRESH_INTERVAL / 1000} seconds...
|
|
31153
|
+
`));
|
|
31154
|
+
process.on("SIGINT", () => {
|
|
31155
|
+
console.log(`
|
|
31156
|
+
`);
|
|
31157
|
+
info2("Loop stopped by user");
|
|
31158
|
+
process.exit(0);
|
|
31159
|
+
});
|
|
31160
|
+
await fetchAndDisplayDevices(ctx);
|
|
31161
|
+
const interval = setInterval(async () => {
|
|
31162
|
+
console.clear();
|
|
31163
|
+
printHeader();
|
|
31164
|
+
console.log(source_default.cyan("Loop mode enabled. Press Ctrl+C to exit."));
|
|
31165
|
+
console.log(source_default.gray(`Last refresh: ${new Date().toLocaleTimeString()}
|
|
31166
|
+
`));
|
|
31167
|
+
await fetchAndDisplayDevices(ctx);
|
|
31168
|
+
}, REFRESH_INTERVAL);
|
|
31169
|
+
await new Promise(() => {});
|
|
31170
|
+
clearInterval(interval);
|
|
31171
|
+
}
|
|
31136
31172
|
var init_devices = __esm(() => {
|
|
31137
31173
|
init_source();
|
|
31138
31174
|
init_api_client();
|
|
@@ -31460,20 +31496,33 @@ var init_transfer = __esm(() => {
|
|
|
31460
31496
|
init_ui();
|
|
31461
31497
|
});
|
|
31462
31498
|
|
|
31499
|
+
// src/core.ts
|
|
31500
|
+
var DebugMode;
|
|
31501
|
+
var init_core = __esm(() => {
|
|
31502
|
+
DebugMode = {
|
|
31503
|
+
enabled: false
|
|
31504
|
+
};
|
|
31505
|
+
});
|
|
31506
|
+
|
|
31463
31507
|
// src/cli/commands/version.ts
|
|
31464
31508
|
var exports_version = {};
|
|
31465
31509
|
__export(exports_version, {
|
|
31466
31510
|
showversion: () => showversion
|
|
31467
31511
|
});
|
|
31468
|
-
import { readFileSync as
|
|
31469
|
-
import { dirname, join as
|
|
31470
|
-
import { fileURLToPath } from "url";
|
|
31512
|
+
import { readFileSync as readFileSync5 } from "fs";
|
|
31513
|
+
import { dirname as dirname2, join as join4 } from "path";
|
|
31514
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
31471
31515
|
function showversion() {
|
|
31472
31516
|
printHeader();
|
|
31473
31517
|
try {
|
|
31474
|
-
const packagePath =
|
|
31475
|
-
const packageJson = JSON.parse(
|
|
31518
|
+
const packagePath = join4(__dirname3, "../../../package.json");
|
|
31519
|
+
const packageJson = JSON.parse(readFileSync5(packagePath, "utf-8"));
|
|
31476
31520
|
const version = packageJson.version;
|
|
31521
|
+
if (DebugMode.enabled === true) {
|
|
31522
|
+
console.log(source_default.yellow("Debug mode enabled"));
|
|
31523
|
+
console.log("Package path: " + packagePath);
|
|
31524
|
+
console.log("Version: " + version);
|
|
31525
|
+
}
|
|
31477
31526
|
const versionBox = createBox(source_default.cyan.bold(`Syncstuff CLI
|
|
31478
31527
|
|
|
31479
31528
|
`) + source_default.bold("Version:") + ` ${source_default.green(version)}
|
|
@@ -31484,23 +31533,80 @@ function showversion() {
|
|
|
31484
31533
|
console.log(versionBox);
|
|
31485
31534
|
printSeparator();
|
|
31486
31535
|
} catch {
|
|
31487
|
-
|
|
31536
|
+
if (DebugMode.enabled === true) {
|
|
31537
|
+
const packagePath = join4(__dirname3, "../../../package.json");
|
|
31538
|
+
console.log(source_default.yellow("Debug mode enabled"));
|
|
31539
|
+
console.log("Packagepath: " + packagePath);
|
|
31540
|
+
console.log(source_default.yellow("Version: 0.0.1 (unable to read package.json)"));
|
|
31541
|
+
}
|
|
31488
31542
|
}
|
|
31489
31543
|
}
|
|
31490
|
-
var
|
|
31544
|
+
var __filename3, __dirname3;
|
|
31491
31545
|
var init_version = __esm(() => {
|
|
31492
31546
|
init_source();
|
|
31547
|
+
init_core();
|
|
31493
31548
|
init_ui();
|
|
31494
|
-
|
|
31495
|
-
|
|
31549
|
+
__filename3 = fileURLToPath2(import.meta.url);
|
|
31550
|
+
__dirname3 = dirname2(__filename3);
|
|
31496
31551
|
});
|
|
31497
31552
|
|
|
31498
31553
|
// src/cli/index.ts
|
|
31499
31554
|
init_ui();
|
|
31555
|
+
|
|
31556
|
+
// src/utils/update-checker.ts
|
|
31557
|
+
init_source();
|
|
31558
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
31559
|
+
import { dirname, join as join2 } from "path";
|
|
31560
|
+
import { fileURLToPath } from "url";
|
|
31561
|
+
var __filename2 = fileURLToPath(import.meta.url);
|
|
31562
|
+
var __dirname2 = dirname(__filename2);
|
|
31563
|
+
async function checkForUpdates() {
|
|
31564
|
+
try {
|
|
31565
|
+
const packagePath = join2(__dirname2, "../../package.json");
|
|
31566
|
+
const packageJson = JSON.parse(readFileSync2(packagePath, "utf-8"));
|
|
31567
|
+
const currentVersion = packageJson.version;
|
|
31568
|
+
const packageName = packageJson.name;
|
|
31569
|
+
const response = await fetch(`https://registry.npmjs.org/${packageName}/latest`, {
|
|
31570
|
+
headers: { Accept: "application/json" },
|
|
31571
|
+
signal: AbortSignal.timeout(3000)
|
|
31572
|
+
});
|
|
31573
|
+
if (!response.ok) {
|
|
31574
|
+
return;
|
|
31575
|
+
}
|
|
31576
|
+
const data = await response.json();
|
|
31577
|
+
const latestVersion = data.version;
|
|
31578
|
+
if (latestVersion && latestVersion !== currentVersion) {
|
|
31579
|
+
const isNewer = compareVersions(latestVersion, currentVersion) > 0;
|
|
31580
|
+
if (isNewer) {
|
|
31581
|
+
console.log("");
|
|
31582
|
+
console.log(source_default.yellow.bold("╭─────────────────────────────────────────╮"));
|
|
31583
|
+
console.log(source_default.yellow.bold("│") + source_default.yellow(" Update available! ") + source_default.gray(`${currentVersion}`) + source_default.yellow(" → ") + source_default.green.bold(`${latestVersion}`) + source_default.yellow.bold(" │"));
|
|
31584
|
+
console.log(source_default.yellow.bold("│") + source_default.cyan(` Run: npm i -g ${packageName}`) + " ".repeat(7) + source_default.yellow.bold("│"));
|
|
31585
|
+
console.log(source_default.yellow.bold("╰─────────────────────────────────────────╯"));
|
|
31586
|
+
console.log("");
|
|
31587
|
+
}
|
|
31588
|
+
}
|
|
31589
|
+
} catch {}
|
|
31590
|
+
}
|
|
31591
|
+
function compareVersions(a, b) {
|
|
31592
|
+
const partsA = a.split(".").map(Number);
|
|
31593
|
+
const partsB = b.split(".").map(Number);
|
|
31594
|
+
for (let i = 0;i < 3; i++) {
|
|
31595
|
+
const partA = partsA[i] || 0;
|
|
31596
|
+
const partB = partsB[i] || 0;
|
|
31597
|
+
if (partA !== partB) {
|
|
31598
|
+
return partA - partB;
|
|
31599
|
+
}
|
|
31600
|
+
}
|
|
31601
|
+
return 0;
|
|
31602
|
+
}
|
|
31603
|
+
|
|
31604
|
+
// src/cli/index.ts
|
|
31500
31605
|
async function run() {
|
|
31501
31606
|
const args = process.argv.slice(2);
|
|
31502
31607
|
const { command, flags, commandArgs } = parseArgs(args);
|
|
31503
31608
|
const ctx = { debug: flags.debug };
|
|
31609
|
+
checkForUpdates();
|
|
31504
31610
|
debugLog(ctx, "Parsed arguments:", { command, flags, commandArgs });
|
|
31505
31611
|
if (flags.help) {
|
|
31506
31612
|
const { showHelp: showHelp2 } = await Promise.resolve().then(() => (init_help(), exports_help));
|
|
@@ -31534,7 +31640,7 @@ async function run() {
|
|
|
31534
31640
|
case "devices":
|
|
31535
31641
|
{
|
|
31536
31642
|
const { listDevices: listDevices2 } = await Promise.resolve().then(() => (init_devices(), exports_devices));
|
|
31537
|
-
await listDevices2(ctx);
|
|
31643
|
+
await listDevices2(commandArgs, ctx);
|
|
31538
31644
|
}
|
|
31539
31645
|
break;
|
|
31540
31646
|
case "device":
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { DebugMode } from "../../core";
|
|
2
2
|
|
|
3
|
-
export const showDebug = (
|
|
4
|
-
if (!
|
|
3
|
+
export const showDebug = () => {
|
|
4
|
+
if (!DebugMode.enabled) {
|
|
5
5
|
return;
|
|
6
6
|
} else {
|
|
7
7
|
console.log("Debug mode enabled");
|
|
@@ -11,8 +11,31 @@ import {
|
|
|
11
11
|
success,
|
|
12
12
|
} from "../../utils/ui.js";
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
/**
|
|
15
|
+
* List devices command
|
|
16
|
+
* Options:
|
|
17
|
+
* --loop Continuously refresh devices until Ctrl+C
|
|
18
|
+
*/
|
|
19
|
+
export async function listDevices(
|
|
20
|
+
args: string[],
|
|
21
|
+
ctx: CommandContext,
|
|
22
|
+
): Promise<void> {
|
|
23
|
+
const isLoop = args.includes("--loop") || args.includes("-l");
|
|
24
|
+
|
|
25
|
+
debugLog(ctx, "Devices command", { loop: isLoop });
|
|
26
|
+
|
|
27
|
+
if (isLoop) {
|
|
28
|
+
await loopDevices(ctx);
|
|
29
|
+
} else {
|
|
30
|
+
printHeader();
|
|
31
|
+
await fetchAndDisplayDevices(ctx);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Fetch and display devices once
|
|
37
|
+
*/
|
|
38
|
+
async function fetchAndDisplayDevices(ctx: CommandContext): Promise<boolean> {
|
|
16
39
|
debugLog(ctx, "Fetching devices list");
|
|
17
40
|
|
|
18
41
|
if (!apiClient.isAuthenticated()) {
|
|
@@ -33,7 +56,7 @@ export async function listDevices(ctx: CommandContext): Promise<void> {
|
|
|
33
56
|
if (response.data.length === 0) {
|
|
34
57
|
info("No devices found. Connect a device to get started.");
|
|
35
58
|
printSeparator();
|
|
36
|
-
return;
|
|
59
|
+
return true;
|
|
37
60
|
}
|
|
38
61
|
|
|
39
62
|
const tableData = response.data.map(device => [
|
|
@@ -58,6 +81,7 @@ export async function listDevices(ctx: CommandContext): Promise<void> {
|
|
|
58
81
|
printSeparator();
|
|
59
82
|
success(`Found ${response.data.length} device(s)`);
|
|
60
83
|
printSeparator();
|
|
84
|
+
return true;
|
|
61
85
|
} else {
|
|
62
86
|
spinner.fail("Failed to fetch devices");
|
|
63
87
|
if (
|
|
@@ -69,10 +93,53 @@ export async function listDevices(ctx: CommandContext): Promise<void> {
|
|
|
69
93
|
} else {
|
|
70
94
|
error(response.error || "Unknown error");
|
|
71
95
|
}
|
|
96
|
+
return false;
|
|
72
97
|
}
|
|
73
98
|
} catch (err) {
|
|
74
99
|
spinner.fail("Error fetching devices");
|
|
75
100
|
error(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
76
|
-
|
|
101
|
+
return false;
|
|
77
102
|
}
|
|
78
103
|
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Loop mode: continuously refresh devices
|
|
107
|
+
*/
|
|
108
|
+
async function loopDevices(ctx: CommandContext): Promise<void> {
|
|
109
|
+
const REFRESH_INTERVAL = 5000; // 5 seconds
|
|
110
|
+
|
|
111
|
+
console.clear();
|
|
112
|
+
printHeader();
|
|
113
|
+
console.log(chalk.cyan("Loop mode enabled. Press Ctrl+C to exit."));
|
|
114
|
+
console.log(
|
|
115
|
+
chalk.gray(`Refreshing every ${REFRESH_INTERVAL / 1000} seconds...\n`),
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
// Handle Ctrl+C gracefully
|
|
119
|
+
process.on("SIGINT", () => {
|
|
120
|
+
console.log("\n");
|
|
121
|
+
info("Loop stopped by user");
|
|
122
|
+
process.exit(0);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
// Initial fetch
|
|
126
|
+
await fetchAndDisplayDevices(ctx);
|
|
127
|
+
|
|
128
|
+
// Set up refresh loop
|
|
129
|
+
const interval = setInterval(async () => {
|
|
130
|
+
console.clear();
|
|
131
|
+
printHeader();
|
|
132
|
+
console.log(chalk.cyan("Loop mode enabled. Press Ctrl+C to exit."));
|
|
133
|
+
console.log(
|
|
134
|
+
chalk.gray(`Last refresh: ${new Date().toLocaleTimeString()}\n`),
|
|
135
|
+
);
|
|
136
|
+
await fetchAndDisplayDevices(ctx);
|
|
137
|
+
}, REFRESH_INTERVAL);
|
|
138
|
+
|
|
139
|
+
// Keep the process running
|
|
140
|
+
await new Promise(() => {
|
|
141
|
+
// This promise never resolves - we wait for SIGINT
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
clearInterval(interval);
|
|
145
|
+
}
|
|
@@ -2,6 +2,7 @@ import chalk from "chalk";
|
|
|
2
2
|
import { readFileSync } from "fs";
|
|
3
3
|
import { dirname, join } from "path";
|
|
4
4
|
import { fileURLToPath } from "url";
|
|
5
|
+
import { DebugMode } from "../../core.js";
|
|
5
6
|
import { createBox, printHeader, printSeparator } from "../../utils/ui.js";
|
|
6
7
|
|
|
7
8
|
const __filename = fileURLToPath(import.meta.url);
|
|
@@ -15,6 +16,12 @@ export function showversion() {
|
|
|
15
16
|
const packageJson = JSON.parse(readFileSync(packagePath, "utf-8"));
|
|
16
17
|
const version = packageJson.version;
|
|
17
18
|
|
|
19
|
+
if (DebugMode.enabled === true) {
|
|
20
|
+
console.log(chalk.yellow("Debug mode enabled"));
|
|
21
|
+
console.log("Package path: " + packagePath);
|
|
22
|
+
console.log("Version: " + version);
|
|
23
|
+
}
|
|
24
|
+
|
|
18
25
|
const versionBox = createBox(
|
|
19
26
|
chalk.cyan.bold("Syncstuff CLI\n\n") +
|
|
20
27
|
chalk.bold("Version:") +
|
|
@@ -30,6 +37,11 @@ export function showversion() {
|
|
|
30
37
|
console.log(versionBox);
|
|
31
38
|
printSeparator();
|
|
32
39
|
} catch {
|
|
33
|
-
|
|
40
|
+
if (DebugMode.enabled === true) {
|
|
41
|
+
const packagePath = join(__dirname, "../../../package.json");
|
|
42
|
+
console.log(chalk.yellow("Debug mode enabled"));
|
|
43
|
+
console.log("Packagepath: " + packagePath);
|
|
44
|
+
console.log(chalk.yellow("Version: 0.0.1 (unable to read package.json)"));
|
|
45
|
+
}
|
|
34
46
|
}
|
|
35
47
|
}
|
package/src/cli/index.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { debugLog, parseArgs, type CommandContext } from "../utils/context.js";
|
|
3
3
|
import { printHeader } from "../utils/ui.js";
|
|
4
|
+
import { checkForUpdates } from "../utils/update-checker.js";
|
|
4
5
|
|
|
5
6
|
export async function run() {
|
|
6
7
|
const args = process.argv.slice(2);
|
|
@@ -8,6 +9,9 @@ export async function run() {
|
|
|
8
9
|
|
|
9
10
|
const ctx: CommandContext = { debug: flags.debug };
|
|
10
11
|
|
|
12
|
+
// Check for updates (non-blocking)
|
|
13
|
+
checkForUpdates();
|
|
14
|
+
|
|
11
15
|
// Debug mode: log parsed arguments
|
|
12
16
|
debugLog(ctx, "Parsed arguments:", { command, flags, commandArgs });
|
|
13
17
|
|
|
@@ -47,7 +51,7 @@ export async function run() {
|
|
|
47
51
|
case "devices":
|
|
48
52
|
{
|
|
49
53
|
const { listDevices } = await import("./commands/devices.js");
|
|
50
|
-
await listDevices(ctx);
|
|
54
|
+
await listDevices(commandArgs, ctx);
|
|
51
55
|
}
|
|
52
56
|
break;
|
|
53
57
|
case "device":
|
package/src/core.ts
CHANGED
package/src/utils/ui.ts
CHANGED
|
@@ -71,7 +71,7 @@ export function animateText(text: string, delay: number = 50): Promise<void> {
|
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
export function printHeader(): void {
|
|
74
|
-
const packagePath = join(__dirname, "
|
|
74
|
+
const packagePath = join(__dirname, "../../package.json");
|
|
75
75
|
const packageJson = JSON.parse(readFileSync(packagePath, "utf-8"));
|
|
76
76
|
const version = packageJson.version;
|
|
77
77
|
const header = chalk.cyan.bold(`
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { readFileSync } from "fs";
|
|
3
|
+
import { dirname, join } from "path";
|
|
4
|
+
import { fileURLToPath } from "url";
|
|
5
|
+
|
|
6
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
+
const __dirname = dirname(__filename);
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Check if a newer version of the CLI is available on npm
|
|
11
|
+
*/
|
|
12
|
+
export async function checkForUpdates(): Promise<void> {
|
|
13
|
+
try {
|
|
14
|
+
// Get current version from package.json
|
|
15
|
+
const packagePath = join(__dirname, "../../package.json");
|
|
16
|
+
const packageJson = JSON.parse(readFileSync(packagePath, "utf-8"));
|
|
17
|
+
const currentVersion = packageJson.version;
|
|
18
|
+
const packageName = packageJson.name;
|
|
19
|
+
|
|
20
|
+
// Fetch latest version from npm registry
|
|
21
|
+
const response = await fetch(
|
|
22
|
+
`https://registry.npmjs.org/${packageName}/latest`,
|
|
23
|
+
{
|
|
24
|
+
headers: { Accept: "application/json" },
|
|
25
|
+
signal: AbortSignal.timeout(3000), // 3 second timeout
|
|
26
|
+
},
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
if (!response.ok) {
|
|
30
|
+
return; // Silently fail if npm check fails
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const data = (await response.json()) as { version: string };
|
|
34
|
+
const latestVersion = data.version;
|
|
35
|
+
|
|
36
|
+
// Compare versions
|
|
37
|
+
if (latestVersion && latestVersion !== currentVersion) {
|
|
38
|
+
const isNewer = compareVersions(latestVersion, currentVersion) > 0;
|
|
39
|
+
|
|
40
|
+
if (isNewer) {
|
|
41
|
+
console.log("");
|
|
42
|
+
console.log(
|
|
43
|
+
chalk.yellow.bold("╭─────────────────────────────────────────╮"),
|
|
44
|
+
);
|
|
45
|
+
console.log(
|
|
46
|
+
chalk.yellow.bold("│") +
|
|
47
|
+
chalk.yellow(" Update available! ") +
|
|
48
|
+
chalk.gray(`${currentVersion}`) +
|
|
49
|
+
chalk.yellow(" → ") +
|
|
50
|
+
chalk.green.bold(`${latestVersion}`) +
|
|
51
|
+
chalk.yellow.bold(" │"),
|
|
52
|
+
);
|
|
53
|
+
console.log(
|
|
54
|
+
chalk.yellow.bold("│") +
|
|
55
|
+
chalk.cyan(` Run: npm i -g ${packageName}`) +
|
|
56
|
+
" ".repeat(7) +
|
|
57
|
+
chalk.yellow.bold("│"),
|
|
58
|
+
);
|
|
59
|
+
console.log(
|
|
60
|
+
chalk.yellow.bold("╰─────────────────────────────────────────╯"),
|
|
61
|
+
);
|
|
62
|
+
console.log("");
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
} catch {
|
|
66
|
+
// Silently fail - update check is not critical
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Compare two semantic versions
|
|
72
|
+
* Returns: positive if a > b, negative if a < b, 0 if equal
|
|
73
|
+
*/
|
|
74
|
+
function compareVersions(a: string, b: string): number {
|
|
75
|
+
const partsA = a.split(".").map(Number);
|
|
76
|
+
const partsB = b.split(".").map(Number);
|
|
77
|
+
|
|
78
|
+
for (let i = 0; i < 3; i++) {
|
|
79
|
+
const partA = partsA[i] || 0;
|
|
80
|
+
const partB = partsB[i] || 0;
|
|
81
|
+
if (partA !== partB) {
|
|
82
|
+
return partA - partB;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return 0;
|
|
86
|
+
}
|