@testspectra/cli 1.0.69 → 1.0.70

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.
@@ -0,0 +1,3 @@
1
+ export declare function updateCommand(options?: {
2
+ check?: boolean;
3
+ }): Promise<void>;
@@ -0,0 +1,113 @@
1
+ import { execSync, execFileSync } from "child_process";
2
+ import fs from "fs";
3
+ import path from "path";
4
+ import { fileURLToPath } from "url";
5
+ const __filename = fileURLToPath(import.meta.url);
6
+ const __dirname = path.dirname(__filename);
7
+ const PACKAGES = ["@testspectra/cli", "@testspectra/matchers"];
8
+ function getLatestVersion(pkg) {
9
+ try {
10
+ const out = execFileSync("npm", ["view", pkg, "version", "--json"], {
11
+ stdio: ["ignore", "pipe", "ignore"],
12
+ timeout: 10000,
13
+ })
14
+ .toString()
15
+ .trim()
16
+ .replace(/"/g, "");
17
+ return out || null;
18
+ }
19
+ catch {
20
+ return null;
21
+ }
22
+ }
23
+ function getCurrentVersion(pkg, cwd) {
24
+ // Walk up to find the installed version
25
+ let cur = path.resolve(cwd);
26
+ while (cur && cur !== path.dirname(cur)) {
27
+ const pkgJson = path.join(cur, "node_modules", pkg, "package.json");
28
+ if (fs.existsSync(pkgJson)) {
29
+ try {
30
+ const p = JSON.parse(fs.readFileSync(pkgJson, "utf-8"));
31
+ return p.version ?? null;
32
+ }
33
+ catch { }
34
+ }
35
+ cur = path.dirname(cur);
36
+ }
37
+ return null;
38
+ }
39
+ function detectPackageManager(cwd) {
40
+ if (fs.existsSync(path.join(cwd, "pnpm-lock.yaml")))
41
+ return "pnpm";
42
+ if (fs.existsSync(path.join(cwd, "bun.lockb")) || fs.existsSync(path.join(cwd, "bun.lock")))
43
+ return "bun";
44
+ return "npm";
45
+ }
46
+ function buildInstallCmd(pm, pkgSpecs) {
47
+ const list = pkgSpecs.join(" ");
48
+ switch (pm) {
49
+ case "pnpm":
50
+ return `pnpm add -D ${list}`;
51
+ case "bun":
52
+ return `bun add -d ${list}`;
53
+ case "npm":
54
+ default:
55
+ return `npm install -D ${list}`;
56
+ }
57
+ }
58
+ export async function updateCommand(options = {}) {
59
+ const cwd = process.cwd();
60
+ const pm = detectPackageManager(cwd);
61
+ console.log("\x1b[36m┌ 🔄 TestSpectra Self-Update\x1b[0m");
62
+ console.log("\x1b[36m│\x1b[0m");
63
+ console.log(`\x1b[36m│\x1b[0m Package Manager: \x1b[33m${pm}\x1b[0m`);
64
+ console.log("\x1b[36m│\x1b[0m");
65
+ console.log("\x1b[36m│\x1b[0m Fetching latest versions from npm registry...");
66
+ const updates = [];
67
+ for (const pkg of PACKAGES) {
68
+ const current = getCurrentVersion(pkg, cwd);
69
+ const latest = getLatestVersion(pkg);
70
+ const needsUpdate = !!latest && latest !== current;
71
+ updates.push({ pkg, current, latest, needsUpdate });
72
+ const currentStr = current ? `\x1b[33mv${current}\x1b[0m` : "\x1b[90m(not installed)\x1b[0m";
73
+ const latestStr = latest ? `\x1b[32mv${latest}\x1b[0m` : "\x1b[31m(unavailable)\x1b[0m";
74
+ const arrow = needsUpdate ? ` → ${latestStr}` : "";
75
+ const status = !latest
76
+ ? "\x1b[31m✗\x1b[0m"
77
+ : needsUpdate
78
+ ? "\x1b[33m↑\x1b[0m"
79
+ : "\x1b[32m✓\x1b[0m";
80
+ console.log(`\x1b[36m│\x1b[0m ${status} ${pkg.padEnd(28)} ${currentStr}${arrow}`);
81
+ }
82
+ const toUpdate = updates.filter((u) => u.needsUpdate && u.latest);
83
+ console.log("\x1b[36m│\x1b[0m");
84
+ if (toUpdate.length === 0) {
85
+ console.log("\x1b[36m└──────────────────────────────────────────────────────────\x1b[0m");
86
+ console.log("\x1b[32m✓ All TestSpectra packages are already up-to-date!\x1b[0m\n");
87
+ return;
88
+ }
89
+ if (options.check) {
90
+ console.log(`\x1b[36m│\x1b[0m \x1b[33m${toUpdate.length} update(s) available. Run \x1b[36mspectra update\x1b[33m to install.\x1b[0m`);
91
+ console.log("\x1b[36m└──────────────────────────────────────────────────────────\x1b[0m\n");
92
+ return;
93
+ }
94
+ const pkgSpecs = toUpdate.map((u) => `${u.pkg}@${u.latest}`);
95
+ const installCmd = buildInstallCmd(pm, pkgSpecs);
96
+ console.log(`\x1b[36m│\x1b[0m Running: \x1b[90m${installCmd}\x1b[0m`);
97
+ console.log("\x1b[36m│\x1b[0m");
98
+ try {
99
+ execSync(installCmd, { cwd, stdio: "inherit" });
100
+ console.log("\x1b[36m│\x1b[0m");
101
+ console.log("\x1b[36m└──────────────────────────────────────────────────────────\x1b[0m");
102
+ console.log("\x1b[32m🎉 TestSpectra updated successfully!\x1b[0m");
103
+ for (const u of toUpdate) {
104
+ console.log(` \x1b[32m✓\x1b[0m ${u.pkg}: v${u.current ?? "?"} → v${u.latest}`);
105
+ }
106
+ console.log("");
107
+ }
108
+ catch (err) {
109
+ console.log("\x1b[36m└──────────────────────────────────────────────────────────\x1b[0m");
110
+ console.error(`\x1b[31m✗ Update failed: ${err.message}\x1b[0m\n`);
111
+ process.exit(1);
112
+ }
113
+ }
package/dist/index.js CHANGED
@@ -5,6 +5,7 @@ import { devicesCommand } from "./commands/devices.js";
5
5
  import { doctorCommand } from "./commands/doctor.js";
6
6
  import { initCommand } from "./commands/init.js";
7
7
  import { runCommand } from "./commands/run.js";
8
+ import { updateCommand } from "./commands/update.js";
8
9
  import { watchCommand } from "./commands/watch.js";
9
10
  export * from "./config/schema.js";
10
11
  export * from "./config/loader.js";
@@ -44,6 +45,11 @@ export function createCliProgram() {
44
45
  .option("--fix", "Attempt automatic fix / download of missing tools")
45
46
  .option("--json", "Output diagnostic results as JSON")
46
47
  .action(doctorCommand);
48
+ program
49
+ .command("update")
50
+ .description("Update @testspectra/cli and @testspectra/matchers to the latest version from npm")
51
+ .option("--check", "Only check for available updates without installing")
52
+ .action(updateCommand);
47
53
  program
48
54
  .command("devices")
49
55
  .description("List connected Android/iOS devices and local browsers")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@testspectra/cli",
3
- "version": "1.0.69",
3
+ "version": "1.0.70",
4
4
  "description": "TestSpectra Zero-Config Cross-Platform Test Runner CLI",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -30,7 +30,7 @@
30
30
  ],
31
31
  "dependencies": {
32
32
  "@clack/prompts": "^1.7.0",
33
- "@testspectra/matchers": "^1.0.69",
33
+ "@testspectra/matchers": "^1.0.70",
34
34
  "chalk": "^5.3.0",
35
35
  "commander": "^12.1.0",
36
36
  "dotenv": "^16.4.5",
@@ -8,8 +8,8 @@
8
8
  "type-check": "tsc -b"
9
9
  },
10
10
  "devDependencies": {
11
- "@testspectra/cli": "^1.0.69",
12
- "@testspectra/matchers": "^1.0.69",
11
+ "@testspectra/cli": "^1.0.70",
12
+ "@testspectra/matchers": "^1.0.70",
13
13
  "@types/node": "^20.14.0",
14
14
  "@wdio/cli": "^9.2.8",
15
15
  "@wdio/local-runner": "^9.2.8",
@@ -10,8 +10,8 @@
10
10
  "build": "nx run-many -t build"
11
11
  },
12
12
  "devDependencies": {
13
- "@testspectra/cli": "^1.0.69",
14
- "@testspectra/matchers": "^1.0.69",
13
+ "@testspectra/cli": "^1.0.70",
14
+ "@testspectra/matchers": "^1.0.70",
15
15
  "@types/node": "^20.14.0",
16
16
  "@wdio/cli": "^9.2.8",
17
17
  "@wdio/local-runner": "^9.2.8",