reallink-cli 0.1.7 → 0.1.10

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/README.md CHANGED
@@ -8,8 +8,10 @@ Rust-based CLI for Reallink authentication, token workflows, and workspace file
8
8
  npm install -g reallink-cli
9
9
  ```
10
10
 
11
- `npm install` performs a one-time Rust release build during postinstall. After that, `reallink` runs the compiled binary directly (no per-command cargo compile step).
12
- CLI checks for updates in the background (cached daily) and prints a hint when a newer version is available.
11
+ On supported published platforms, npm installs a bundled prebuilt binary so install/update is fast.
12
+ If a prebuilt binary is not available for your OS/arch, npm falls back to a one-time Rust release build during postinstall.
13
+ After install, `reallink` runs the compiled binary directly (no per-command cargo compile step).
14
+ CLI caches update metadata daily. To keep command startup fast, network update checks run during `reallink login` (or explicitly via `reallink self-update --check`) rather than every command.
13
15
 
14
16
  ## Commands
15
17
 
package/bin/reallink.cjs CHANGED
@@ -7,7 +7,25 @@ const packageRoot = path.resolve(__dirname, "..");
7
7
  const manifestPath = path.join(packageRoot, "rust", "Cargo.toml");
8
8
  const args = process.argv.slice(2);
9
9
  const binaryName = process.platform === "win32" ? "reallink-cli.exe" : "reallink-cli";
10
- const releaseBinaryPath = path.join(packageRoot, "rust", "target", "release", binaryName);
10
+ const prebuiltBinaryPath = path.join(
11
+ packageRoot,
12
+ "prebuilt",
13
+ `${process.platform}-${process.arch}`,
14
+ binaryName
15
+ );
16
+ const releaseBinaryCandidates = [
17
+ path.resolve(packageRoot, "..", "..", "target", "release", binaryName),
18
+ path.join(packageRoot, "rust", "target", "release", binaryName)
19
+ ];
20
+
21
+ function resolveExistingReleaseBinary() {
22
+ for (const candidate of releaseBinaryCandidates) {
23
+ if (fs.existsSync(candidate)) {
24
+ return candidate;
25
+ }
26
+ }
27
+ return null;
28
+ }
11
29
 
12
30
  function runBinary(binaryPath) {
13
31
  return spawnSync(binaryPath, args, {
@@ -17,7 +35,7 @@ function runBinary(binaryPath) {
17
35
  }
18
36
 
19
37
  function ensureBinary() {
20
- if (fs.existsSync(releaseBinaryPath)) {
38
+ if (resolveExistingReleaseBinary() || fs.existsSync(prebuiltBinaryPath)) {
21
39
  return true;
22
40
  }
23
41
 
@@ -38,14 +56,15 @@ function ensureBinary() {
38
56
  return false;
39
57
  }
40
58
 
41
- return build.status === 0 && fs.existsSync(releaseBinaryPath);
59
+ return build.status === 0 && !!resolveExistingReleaseBinary();
42
60
  }
43
61
 
44
62
  if (!ensureBinary()) {
45
63
  process.exit(1);
46
64
  }
47
65
 
48
- const result = runBinary(releaseBinaryPath);
66
+ const binaryPath = resolveExistingReleaseBinary() || prebuiltBinaryPath;
67
+ const result = runBinary(binaryPath);
49
68
  if (result.error) {
50
69
  console.error(`Failed to run reallink binary: ${result.error.message}`);
51
70
  process.exit(1);
package/package.json CHANGED
@@ -1,19 +1,22 @@
1
1
  {
2
2
  "name": "reallink-cli",
3
- "version": "0.1.7",
3
+ "version": "0.1.10",
4
4
  "description": "Rust-based CLI for Reallink auth and API operations",
5
5
  "bin": {
6
6
  "reallink": "bin/reallink.cjs"
7
7
  },
8
8
  "files": [
9
9
  "bin/reallink.cjs",
10
+ "prebuilt",
10
11
  "scripts/postinstall.cjs",
12
+ "scripts/prepare-prebuilt.cjs",
11
13
  "rust/Cargo.toml",
12
14
  "rust/Cargo.lock",
13
15
  "rust/src",
14
16
  "README.md"
15
17
  ],
16
18
  "scripts": {
19
+ "prepack": "node ./scripts/prepare-prebuilt.cjs",
17
20
  "postinstall": "node ./scripts/postinstall.cjs",
18
21
  "build": "cargo build --manifest-path ./rust/Cargo.toml --release",
19
22
  "dev": "node ./bin/reallink.cjs --help",
package/rust/Cargo.lock CHANGED
@@ -910,7 +910,7 @@ dependencies = [
910
910
 
911
911
  [[package]]
912
912
  name = "reallink-cli"
913
- version = "0.1.7"
913
+ version = "0.1.10"
914
914
  dependencies = [
915
915
  "anyhow",
916
916
  "clap",
package/rust/Cargo.toml CHANGED
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "reallink-cli"
3
- version = "0.1.7"
3
+ version = "0.1.10"
4
4
  edition = "2021"
5
5
  description = "CLI for Reallink auth and token workflows"
6
6
  license = "MIT"
package/rust/src/main.rs CHANGED
@@ -15,9 +15,10 @@ const SESSION_DIR_NAME: &str = "reallink";
15
15
  const SESSION_FILE_NAME: &str = "session.json";
16
16
  const UPDATE_CACHE_FILE_NAME: &str = "update-check.json";
17
17
  const VERSION_CHECK_INTERVAL_MS: u128 = 24 * 60 * 60 * 1000;
18
+ const DEFAULT_VERSION_FETCH_TIMEOUT_MS: u64 = 800;
18
19
 
19
20
  #[derive(Parser)]
20
- #[command(name = "reallink", version, about = "Reallink CLI")]
21
+ #[command(name = "reallink", bin_name = "reallink", version, about = "Reallink CLI")]
21
22
  struct Cli {
22
23
  #[command(subcommand)]
23
24
  command: Commands,
@@ -733,8 +734,13 @@ fn is_newer_version(current: &str, latest: &str) -> bool {
733
734
  }
734
735
 
735
736
  async fn fetch_latest_cli_version(client: &reqwest::Client) -> Option<String> {
737
+ let timeout_ms = std::env::var("REALLINK_UPDATE_CHECK_TIMEOUT_MS")
738
+ .ok()
739
+ .and_then(|value| value.parse::<u64>().ok())
740
+ .filter(|value| *value > 0)
741
+ .unwrap_or(DEFAULT_VERSION_FETCH_TIMEOUT_MS);
736
742
  let response = with_cli_headers(client.get("https://registry.npmjs.org/reallink-cli/latest"))
737
- .timeout(Duration::from_secs(2))
743
+ .timeout(Duration::from_millis(timeout_ms))
738
744
  .send()
739
745
  .await
740
746
  .ok()?;
@@ -749,7 +755,7 @@ async fn fetch_latest_cli_version(client: &reqwest::Client) -> Option<String> {
749
755
  .filter(|value| !value.is_empty())
750
756
  }
751
757
 
752
- async fn maybe_notify_update(client: &reqwest::Client, force_refresh: bool) {
758
+ async fn maybe_notify_update(client: &reqwest::Client, force_refresh: bool, allow_network_fetch: bool) {
753
759
  if std::env::var("REALLINK_DISABLE_AUTO_UPDATE_CHECK")
754
760
  .map(|value| value == "1")
755
761
  .unwrap_or(false)
@@ -772,7 +778,7 @@ async fn maybe_notify_update(client: &reqwest::Client, force_refresh: bool) {
772
778
  None
773
779
  };
774
780
 
775
- if latest_version.is_none() {
781
+ if latest_version.is_none() && allow_network_fetch {
776
782
  latest_version = fetch_latest_cli_version(client).await;
777
783
  let _ = save_update_cache(&UpdateCheckCache {
778
784
  last_checked_epoch_ms: now,
@@ -1922,7 +1928,8 @@ async fn main() -> Result<()> {
1922
1928
  .build()?;
1923
1929
 
1924
1930
  if !matches!(&cli.command, Commands::SelfUpdate(_)) {
1925
- maybe_notify_update(&client, false).await;
1931
+ let allow_update_fetch = matches!(&cli.command, Commands::Login(_));
1932
+ maybe_notify_update(&client, false, allow_update_fetch).await;
1926
1933
  }
1927
1934
 
1928
1935
  match cli.command {
@@ -6,13 +6,26 @@ const path = require("node:path");
6
6
  const packageRoot = path.resolve(__dirname, "..");
7
7
  const manifestPath = path.join(packageRoot, "rust", "Cargo.toml");
8
8
  const binaryName = process.platform === "win32" ? "reallink-cli.exe" : "reallink-cli";
9
- const releaseBinaryPath = path.join(packageRoot, "rust", "target", "release", binaryName);
9
+ const prebuiltBinaryPath = path.join(
10
+ packageRoot,
11
+ "prebuilt",
12
+ `${process.platform}-${process.arch}`,
13
+ binaryName
14
+ );
15
+ const releaseBinaryCandidates = [
16
+ path.resolve(packageRoot, "..", "..", "target", "release", binaryName),
17
+ path.join(packageRoot, "rust", "target", "release", binaryName)
18
+ ];
19
+
20
+ function hasReleaseBinary() {
21
+ return releaseBinaryCandidates.some((candidate) => fs.existsSync(candidate));
22
+ }
10
23
 
11
24
  if (process.env.REALLINK_SKIP_BUILD === "1") {
12
25
  process.exit(0);
13
26
  }
14
27
 
15
- if (fs.existsSync(releaseBinaryPath)) {
28
+ if (hasReleaseBinary() || fs.existsSync(prebuiltBinaryPath)) {
16
29
  process.exit(0);
17
30
  }
18
31
 
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env node
2
+ const { spawnSync } = require("node:child_process");
3
+ const fs = require("node:fs");
4
+ const path = require("node:path");
5
+
6
+ const packageRoot = path.resolve(__dirname, "..");
7
+ const manifestPath = path.join(packageRoot, "rust", "Cargo.toml");
8
+ const binaryName = process.platform === "win32" ? "reallink-cli.exe" : "reallink-cli";
9
+ const releaseBinaryCandidates = [
10
+ path.resolve(packageRoot, "..", "..", "target", "release", binaryName),
11
+ path.join(packageRoot, "rust", "target", "release", binaryName)
12
+ ];
13
+ const prebuiltDir = path.join(packageRoot, "prebuilt", `${process.platform}-${process.arch}`);
14
+ const prebuiltBinaryPath = path.join(prebuiltDir, binaryName);
15
+
16
+ function resolveNewestReleaseBinary() {
17
+ const existing = releaseBinaryCandidates
18
+ .filter((candidate) => fs.existsSync(candidate))
19
+ .map((candidate) => ({
20
+ candidate,
21
+ mtimeMs: fs.statSync(candidate).mtimeMs
22
+ }))
23
+ .sort((a, b) => b.mtimeMs - a.mtimeMs);
24
+ return existing.length > 0 ? existing[0].candidate : null;
25
+ }
26
+
27
+ const build = spawnSync(
28
+ "cargo",
29
+ ["build", "--release", "--manifest-path", manifestPath],
30
+ {
31
+ stdio: "inherit",
32
+ shell: process.platform === "win32"
33
+ }
34
+ );
35
+
36
+ if (build.error) {
37
+ console.error(`prepare-prebuilt failed: ${build.error.message}`);
38
+ process.exit(1);
39
+ }
40
+
41
+ const releaseBinaryPath = resolveNewestReleaseBinary();
42
+ if (build.status !== 0 || !releaseBinaryPath) {
43
+ console.error("prepare-prebuilt failed: release binary was not produced");
44
+ process.exit(build.status ?? 1);
45
+ }
46
+
47
+ fs.mkdirSync(prebuiltDir, { recursive: true });
48
+ fs.copyFileSync(releaseBinaryPath, prebuiltBinaryPath);
49
+ console.log(`Prepared prebuilt binary: ${prebuiltBinaryPath}`);