browser4-cli 0.1.10 → 0.1.11

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.
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "browser4-cli",
3
- "version": "0.1.10",
3
+ "version": "0.1.11",
4
4
  "description": "Browser automation CLI for AI agents",
5
5
  "type": "module",
6
6
  "files": [
@@ -21,31 +21,24 @@ const cargoToml = readFileSync(join(rootDir, 'browser4-cli/Cargo.toml'), 'utf-8'
21
21
  const cargoVersionMatch = cargoToml.match(/^version\s*=\s*"([^"]*)"/m);
22
22
 
23
23
  if (!cargoVersionMatch) {
24
- console.error('Could not find version in browser4-cli/Cargo.toml');
25
- process.exit(1);
24
+ console.error('Could not find version in browser4-cli/Cargo.toml');
25
+ process.exit(1);
26
26
  }
27
27
 
28
28
  const cargoVersion = cargoVersionMatch[1];
29
29
 
30
- // Read dashboard package.json version
31
- const dashboardPkg = JSON.parse(readFileSync(join(rootDir, 'packages/dashboard/package.json'), 'utf-8'));
32
- const dashboardVersion = dashboardPkg.version;
33
-
34
30
  const mismatches = [];
35
31
  if (packageVersion !== cargoVersion) {
36
- mismatches.push(` browser4-cli/Cargo.toml: ${cargoVersion}`);
37
- }
38
- if (packageVersion !== dashboardVersion) {
39
- mismatches.push(` packages/dashboard: ${dashboardVersion}`);
32
+ mismatches.push(` browser4-cli/Cargo.toml: ${cargoVersion}`);
40
33
  }
41
34
 
42
35
  if (mismatches.length > 0) {
43
- console.error('Version mismatch detected!');
44
- console.error(` package.json: ${packageVersion}`);
45
- for (const m of mismatches) console.error(m);
46
- console.error('');
47
- console.error("Run 'pnpm run version:sync' to fix this.");
48
- process.exit(1);
36
+ console.error('Version mismatch detected!');
37
+ console.error(` package.json: ${packageVersion}`);
38
+ for (const m of mismatches) console.error(m);
39
+ console.error('');
40
+ console.error("Run 'pnpm run version:sync' to fix this.");
41
+ process.exit(1);
49
42
  }
50
43
 
51
44
  console.log(`Versions are in sync: ${packageVersion}`);
@@ -1,69 +1,212 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  /**
4
- * Syncs the version from package.json to all other config files.
5
- * Run this script before building or releasing.
4
+ * Syncs the CLI version from cli/package.json to the Cargo manifest.
5
+ *
6
+ * cli/package.json is the single source of truth for the CLI version. This
7
+ * allows the backend Maven project and the CLI to be published separately with
8
+ * different versions. This script:
9
+ * - Reads the version from cli/package.json
10
+ * - Strips the Maven-style "-SNAPSHOT" suffix
11
+ * - Fetches the latest published version from npm and compares it
12
+ * against the local version, warning when the bump is neither a
13
+ * patch nor a minor increment.
14
+ * - Writes the clean semver to cli/browser4-cli/Cargo.toml
15
+ * - Updates Cargo.lock to match
16
+ *
17
+ * Usage:
18
+ * node cli/scripts/sync-version.js # sync all files
19
+ * node cli/scripts/sync-version.js --check # exit 1 if out of sync (CI lint)
6
20
  */
7
21
 
8
22
  import {execSync} from "child_process";
9
23
  import {readFileSync, writeFileSync} from "fs";
10
- import {dirname, join} from "path";
24
+ import {dirname, join, resolve} from "path";
11
25
  import {fileURLToPath} from "url";
12
26
 
13
27
  const __dirname = dirname(fileURLToPath(import.meta.url));
14
- const rootDir = join(__dirname, "..");
15
- const cliDir = join(rootDir, "browser4-cli");
28
+ const scriptsDir = __dirname; // cli/scripts
29
+ const cliDir = resolve(scriptsDir, ".."); // cli
30
+ const cargoDir = join(cliDir, "browser4-cli"); // cli/browser4-cli
16
31
 
17
- // Read version from package.json (single source of truth)
18
- const packageJson = JSON.parse(
19
- readFileSync(join(rootDir, "package.json"), "utf-8")
20
- );
21
- const version = packageJson.version;
32
+ // ---------------------------------------------------------------------------
33
+ // Helpers
34
+ // ---------------------------------------------------------------------------
22
35
 
23
- console.log(`Syncing version ${version} to all config files...`);
36
+ /** Strip the "-SNAPSHOT" suffix if present. */
37
+ function stripSnapshot(version) {
38
+ if (version.endsWith("-SNAPSHOT")) {
39
+ return version.slice(0, -"-SNAPSHOT".length);
40
+ }
41
+ return version;
42
+ }
43
+
44
+ /**
45
+ * Parse a semver string into { major, minor, patch } integers.
46
+ * Returns null for non-semver strings (e.g. snapshots, prereleases).
47
+ */
48
+ function parseSemver(version) {
49
+ const m = version.match(/^(\d+)\.(\d+)\.(\d+)$/);
50
+ if (!m) return null;
51
+ return { major: Number(m[1]), minor: Number(m[2]), patch: Number(m[3]) };
52
+ }
53
+
54
+ /**
55
+ * Fetch the latest published version of a package from the npm registry.
56
+ * Returns the version string, or null if the package hasn't been published
57
+ * yet or the registry is unreachable.
58
+ */
59
+ function getLatestPublishedVersion(packageName) {
60
+ try {
61
+ const raw = execSync(`npm view "${packageName}" version --json`, {
62
+ stdio: ["ignore", "pipe", "ignore"],
63
+ timeout: 10_000,
64
+ });
65
+ return JSON.parse(raw.toString().trim());
66
+ } catch {
67
+ // Package may not be published yet, or network is unavailable.
68
+ return null;
69
+ }
70
+ }
71
+
72
+ /**
73
+ * Check whether `local` is an expected bump from `published`:
74
+ * - same version (already published)
75
+ * - next patch
76
+ * - next minor
77
+ *
78
+ * Returns { ok: true } or { ok: false, reason: "..." }.
79
+ */
80
+ function checkVersionBump(published, local) {
81
+ const pub = parseSemver(published);
82
+ const loc = parseSemver(local);
83
+
84
+ if (!pub || !loc) {
85
+ // Can't compare — pre-release / snapshot versions are fine.
86
+ return { ok: true };
87
+ }
88
+
89
+ // Same version — already published.
90
+ if (loc.major === pub.major && loc.minor === pub.minor && loc.patch === pub.patch) {
91
+ return { ok: true, note: `version ${local} is already published` };
92
+ }
93
+
94
+ // Next patch: X.Y.Z → X.Y.(Z+1)
95
+ if (loc.major === pub.major && loc.minor === pub.minor && loc.patch === pub.patch + 1) {
96
+ return { ok: true };
97
+ }
98
+
99
+ // Next minor: X.Y.Z → X.(Y+1).0
100
+ if (loc.major === pub.major && loc.minor === pub.minor + 1 && loc.patch === 0) {
101
+ return { ok: true };
102
+ }
24
103
 
25
- // Update Cargo.toml
26
- const cargoTomlPath = join(cliDir, "Cargo.toml");
104
+ // Local is behind published.
105
+ if (
106
+ loc.major < pub.major ||
107
+ (loc.major === pub.major && loc.minor < pub.minor) ||
108
+ (loc.major === pub.major && loc.minor === pub.minor && loc.patch < pub.patch)
109
+ ) {
110
+ return {
111
+ ok: false,
112
+ reason: `local version ${local} is behind the published version ${published}`,
113
+ };
114
+ }
115
+
116
+ // Anything else — skipping versions, major bump, etc.
117
+ return {
118
+ ok: false,
119
+ reason: `version bump from ${published} to ${local} is neither a patch nor a minor increment`,
120
+ };
121
+ }
122
+
123
+ // ---------------------------------------------------------------------------
124
+ // Main
125
+ // ---------------------------------------------------------------------------
126
+
127
+ const checkOnly = process.argv.includes("--check");
128
+
129
+ // 1. Read the CLI version from cli/package.json (the source of truth)
130
+ const packageJsonPath = join(cliDir, "package.json");
131
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
132
+ const pkgName = packageJson.name;
133
+ const pkgVersion = packageJson.version;
134
+
135
+ if (!pkgVersion) {
136
+ console.error("ERROR: cli/package.json does not contain a version field.");
137
+ process.exit(1);
138
+ }
139
+
140
+ const version = stripSnapshot(pkgVersion);
141
+ if (checkOnly) console.log(`cli/package.json: ${version}`);
142
+
143
+ // 2. Compare against the latest published version on npm
144
+ const publishedVersion = getLatestPublishedVersion(pkgName);
145
+ if (publishedVersion) {
146
+ console.log(`Latest published: ${pkgName}@${publishedVersion}`);
147
+ const bump = checkVersionBump(publishedVersion, version);
148
+ if (!bump.ok) {
149
+ console.warn(`\x1b[33mWARNING: ${bump.reason}\x1b[0m`);
150
+ } else if (bump.note) {
151
+ console.log(` (${bump.note})`);
152
+ }
153
+ } else {
154
+ console.log(`Latest published: (not found — package may not be published yet)`);
155
+ }
156
+
157
+ // 3. Sync cli/browser4-cli/Cargo.toml
158
+ const cargoTomlPath = join(cargoDir, "Cargo.toml");
27
159
  let cargoToml = readFileSync(cargoTomlPath, "utf-8");
28
160
  const cargoVersionRegex = /^version\s*=\s*"[^"]*"/m;
29
- const newCargoVersion = `version = "${version}"`;
161
+ const cargoMatch = cargoToml.match(cargoVersionRegex);
30
162
 
31
- let cargoTomlUpdated = false;
32
- if (cargoVersionRegex.test(cargoToml)) {
33
- const oldMatch = cargoToml.match(cargoVersionRegex)?.[0];
34
- if (oldMatch !== newCargoVersion) {
35
- cargoToml = cargoToml.replace(cargoVersionRegex, newCargoVersion);
36
- writeFileSync(cargoTomlPath, cargoToml);
37
- console.log(` Updated browser4-cli/Cargo.toml: ${oldMatch} -> ${newCargoVersion}`);
38
- cargoTomlUpdated = true;
163
+ if (!cargoMatch) {
164
+ console.error("ERROR: Could not find version field in Cargo.toml");
165
+ process.exit(1);
166
+ }
167
+
168
+ const cargoVersion = cargoMatch[0].match(/"([^"]*)"/)[1];
169
+ if (cargoVersion !== version) {
170
+ if (checkOnly) {
171
+ console.error(`MISMATCH: ${cargoTomlPath} version is "${cargoVersion}", expected "${version}"`);
172
+ process.exitCode = 1;
39
173
  } else {
40
- console.log(` cli/Cargo.toml already up to date`);
174
+ cargoToml = cargoToml.replace(cargoVersionRegex, `version = "${version}"`);
175
+ writeFileSync(cargoTomlPath, cargoToml);
176
+ console.log(` Updated ${cargoTomlPath}: ${cargoVersion} -> ${version}`);
41
177
  }
42
178
  } else {
43
- console.error(" Could not find version field in browser4-cli/Cargo.toml");
44
- process.exit(1);
179
+ if (!checkOnly) console.log(` ${cargoTomlPath} already up to date`);
45
180
  }
46
181
 
47
- // Update Cargo.lock to match Cargo.toml
48
- if (cargoTomlUpdated) {
182
+ // 4. Update Cargo.lock (only in sync mode)
183
+ if (!checkOnly && cargoVersion !== version) {
49
184
  try {
50
185
  execSync("cargo update -p browser4-cli --offline", {
51
- cwd: cliDir,
186
+ cwd: cargoDir,
52
187
  stdio: "pipe",
53
188
  });
54
- console.log(` Updated cli/Cargo.lock`);
189
+ console.log(" Updated Cargo.lock");
55
190
  } catch {
56
- // --offline may fail if package not in cache, try without it
57
191
  try {
58
192
  execSync("cargo update -p browser4-cli", {
59
- cwd: cliDir,
193
+ cwd: cargoDir,
60
194
  stdio: "pipe",
61
195
  });
62
- console.log(` Updated cli/Cargo.lock`);
196
+ console.log(" Updated Cargo.lock");
63
197
  } catch (e) {
64
198
  console.error(` Warning: Could not update Cargo.lock: ${e.message}`);
65
199
  }
66
200
  }
67
201
  }
68
202
 
69
- console.log("Version sync complete.");
203
+ // 5. Report
204
+ if (checkOnly) {
205
+ if (process.exitCode === 1) {
206
+ console.error("\nVersion mismatch detected! Run 'node cli/scripts/sync-version.js' to fix.");
207
+ } else {
208
+ console.log(`\nAll versions in sync: ${version}`);
209
+ }
210
+ } else {
211
+ console.log(`\nVersion sync complete: ${pkgName}@${version}`);
212
+ }