@aptove/bridge 0.1.12 → 0.1.15

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.
Files changed (2) hide show
  1. package/package.json +6 -6
  2. package/postinstall.js +114 -74
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aptove/bridge",
3
- "version": "0.1.12",
3
+ "version": "0.1.15",
4
4
  "description": "ACP bridge — connects ACP agents to mobile and desktop clients over WebSocket",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -33,10 +33,10 @@
33
33
  "node": ">=16"
34
34
  },
35
35
  "optionalDependencies": {
36
- "@aptove/bridge-darwin-arm64": "0.1.12",
37
- "@aptove/bridge-darwin-x64": "0.1.12",
38
- "@aptove/bridge-linux-arm64": "0.1.12",
39
- "@aptove/bridge-linux-x64": "0.1.12",
40
- "@aptove/bridge-win32-x64": "0.1.12"
36
+ "@aptove/bridge-darwin-arm64": "0.1.15",
37
+ "@aptove/bridge-darwin-x64": "0.1.15",
38
+ "@aptove/bridge-linux-arm64": "0.1.15",
39
+ "@aptove/bridge-linux-x64": "0.1.15",
40
+ "@aptove/bridge-win32-x64": "0.1.15"
41
41
  }
42
42
  }
package/postinstall.js CHANGED
@@ -19,37 +19,34 @@ const PLATFORM_PACKAGES = {
19
19
  'win32-x64': '@aptove/bridge-win32-x64',
20
20
  };
21
21
 
22
- const platformKey = `${process.platform}-${process.arch}`;
23
- const packageName = PLATFORM_PACKAGES[platformKey];
24
-
25
- if (!packageName) {
26
- console.warn(`⚠️ bridge: unsupported platform ${platformKey}`);
27
- process.exit(0);
22
+ function isBinaryPresent(binaryPath) {
23
+ return fs.existsSync(binaryPath);
28
24
  }
29
25
 
30
- const binaryName = process.platform === 'win32' ? 'bridge.exe' : 'bridge';
31
- const shortName = packageName.split('/')[1]; // e.g. "bridge-darwin-arm64"
32
-
33
- // postinstall.js lives at @aptove/bridge/postinstall.js
34
- // platform binary lives at @aptove/bridge-darwin-arm64/bin/bridge (sibling package)
35
- const siblingBinaryPath = path.join(__dirname, '..', shortName, 'bin', binaryName);
36
-
37
- function isBinaryPresent() {
38
- return fs.existsSync(siblingBinaryPath);
26
+ // Ensures the binary has executable permissions (no-op on Windows).
27
+ function ensureExecutable(binaryPath) {
28
+ if (process.platform === 'win32') return;
29
+ try {
30
+ fs.chmodSync(binaryPath, 0o755);
31
+ } catch (e) {
32
+ // best-effort
33
+ }
39
34
  }
40
35
 
41
- // Returns the version string from `bridge --version` (e.g. "0.1.11"), or null on failure.
42
- function getBinaryVersion() {
43
- const result = spawnSync(siblingBinaryPath, ['--version'], { stdio: 'pipe' });
36
+ // Returns the version string from `bridge --version` (e.g. "0.1.12"), or null on failure.
37
+ function getBinaryVersion(binaryPath) {
38
+ const result = spawnSync(binaryPath, ['--version'], { stdio: 'pipe' });
44
39
  if (result.error || result.status !== 0) return null;
45
- const output = (result.stdout || '').toString().trim(); // e.g. "bridge 0.1.11"
40
+ const output = (result.stdout || '').toString().trim(); // e.g. "bridge 0.1.12"
46
41
  const parts = output.split(' ');
47
42
  return parts.length >= 2 ? parts[1] : output;
48
43
  }
49
44
 
50
- function getExpectedVersion() {
45
+ // Reads the expected platform package version from the main package's optionalDependencies.
46
+ function getExpectedVersion(packageJsonPath) {
51
47
  try {
52
- const pkg = require('./package.json');
48
+ delete require.cache[require.resolve(packageJsonPath)];
49
+ const pkg = require(packageJsonPath);
53
50
  // optionalDependencies values are updated by the release workflow to match the published version
54
51
  const deps = pkg.optionalDependencies || {};
55
52
  const versions = Object.values(deps).filter(v => v !== '*');
@@ -59,70 +56,113 @@ function getExpectedVersion() {
59
56
  }
60
57
  }
61
58
 
62
- function installPlatformPackage(version) {
63
- // During `npm install -g`, npm_config_prefix points to the global prefix.
64
- // Installing with --prefix ensures the package lands in the same global node_modules tree.
65
- const prefix = process.env.npm_config_prefix;
66
- const prefixFlag = prefix ? `--prefix "${prefix}"` : '';
67
- console.log(` Installing ${packageName}@${version}...`);
68
- execSync(
69
- `npm install ${prefixFlag} --no-save --no-audit --no-fund "${packageName}@${version}"`,
70
- { stdio: 'inherit' }
71
- );
72
- }
59
+ /**
60
+ * Main postinstall logic.
61
+ *
62
+ * All I/O is injectable for testing:
63
+ * baseDir — replaces __dirname for computing the sibling binary path
64
+ * packageJsonPath— path to the main package's package.json
65
+ * platformKey — override platform detection (default: process.platform-process.arch)
66
+ * npmPrefix — override npm_config_prefix
67
+ * installFn — (packageName, version) => void; throws on failure
68
+ * defaults to running `npm install` via execSync
69
+ * log / warn — console.log / console.warn replacements
70
+ * exitFn — process.exit replacement
71
+ */
72
+ function main({
73
+ baseDir = __dirname,
74
+ packageJsonPath = path.join(__dirname, 'package.json'),
75
+ platformKey = `${process.platform}-${process.arch}`,
76
+ npmPrefix = process.env.npm_config_prefix,
77
+ installFn = null,
78
+ log = (...a) => console.log(...a),
79
+ warn = (...a) => console.warn(...a),
80
+ exitFn = process.exit,
81
+ } = {}) {
82
+ const packageName = PLATFORM_PACKAGES[platformKey];
73
83
 
74
- function tryInstall(version) {
75
- try {
76
- installPlatformPackage(version);
77
- return true;
78
- } catch (e) {
79
- return false;
84
+ if (!packageName) {
85
+ warn(`⚠️ bridge: unsupported platform ${platformKey}`);
86
+ exitFn(0); return;
80
87
  }
81
- }
82
88
 
83
- // --- Main ---
89
+ const binaryName = process.platform === 'win32' ? 'bridge.exe' : 'bridge';
90
+ const shortName = packageName.split('/')[1]; // e.g. "bridge-darwin-arm64"
84
91
 
85
- const expectedVersion = getExpectedVersion();
92
+ // postinstall.js lives at @aptove/bridge/postinstall.js
93
+ // platform binary lives at @aptove/bridge-darwin-arm64/bin/bridge (sibling package)
94
+ const siblingBinaryPath = path.join(baseDir, '..', shortName, 'bin', binaryName);
86
95
 
87
- // Check if binary is present and at the correct version.
88
- if (isBinaryPresent()) {
89
- const installedVersion = getBinaryVersion();
90
- if (installedVersion && expectedVersion && installedVersion !== expectedVersion) {
91
- console.log(`⬆ bridge: updating platform binary ${installedVersion} ${expectedVersion}...`);
92
- if (!tryInstall(expectedVersion)) {
93
- console.warn(`⚠️ bridge: update failed — run: npm install -g ${packageName}@${expectedVersion}`);
94
- process.exit(0);
96
+ function tryInstall(version) {
97
+ const fn = installFn || ((pkg, ver) => {
98
+ const prefixFlag = npmPrefix ? `--prefix "${npmPrefix}"` : '';
99
+ execSync(
100
+ `npm install ${prefixFlag} --no-save --no-audit --no-fund "${pkg}@${ver}"`,
101
+ { stdio: 'inherit' }
102
+ );
103
+ });
104
+ try {
105
+ log(` Installing ${packageName}@${version}...`);
106
+ fn(packageName, version);
107
+ // GitHub artifact uploads strip execute permissions; restore them.
108
+ if (isBinaryPresent(siblingBinaryPath)) ensureExecutable(siblingBinaryPath);
109
+ return true;
110
+ } catch (e) {
111
+ return false;
95
112
  }
96
- } else {
97
- const version = installedVersion || getBinaryVersion();
98
- console.log(`✓ bridge ${version || installedVersion} installed successfully for ${platformKey}`);
99
- process.exit(0);
100
113
  }
101
- } else {
102
- // Optional dependency was not installed (common with `npm install -g`).
103
- console.log(`\n⬇ bridge: platform binary not found, installing ${packageName}...`);
104
- if (!tryInstall(expectedVersion || 'latest')) {
105
- console.warn(`\n⚠️ bridge: failed to install ${packageName}`);
106
- console.warn(` Run manually: npm install -g ${packageName}${expectedVersion ? '@' + expectedVersion : ''}`);
107
- process.exit(0);
114
+
115
+ const expectedVersion = getExpectedVersion(packageJsonPath);
116
+
117
+ if (isBinaryPresent(siblingBinaryPath)) {
118
+ // Fix permissions in case the binary was published without the execute bit
119
+ // (GitHub Actions artifacts do not preserve file permissions).
120
+ ensureExecutable(siblingBinaryPath);
121
+ const installedVersion = getBinaryVersion(siblingBinaryPath);
122
+ if (installedVersion && expectedVersion && installedVersion !== expectedVersion) {
123
+ log(`⬆ bridge: updating platform binary ${installedVersion} → ${expectedVersion}...`);
124
+ if (!tryInstall(expectedVersion)) {
125
+ warn(`⚠️ bridge: update failed — run: npm install -g ${packageName}@${expectedVersion}`);
126
+ exitFn(0); return;
127
+ }
128
+ } else {
129
+ log(`✓ bridge ${installedVersion || '(unknown)'} installed successfully for ${platformKey}`);
130
+ exitFn(0); return;
131
+ }
132
+ } else {
133
+ log(`\n⬇ bridge: platform binary not found, installing ${packageName}...`);
134
+ if (!tryInstall(expectedVersion || 'latest')) {
135
+ warn(`\n⚠️ bridge: failed to install ${packageName}`);
136
+ warn(` Run manually: npm install -g ${packageName}${expectedVersion ? '@' + expectedVersion : ''}`);
137
+ exitFn(0); return;
138
+ }
108
139
  }
109
- }
110
140
 
111
- // Validate after install using sibling path directly.
112
- // (require.resolve cannot be used here — Node.js caches negative module
113
- // resolution results within the same process.)
114
- if (isBinaryPresent()) {
115
- const installedVersion = getBinaryVersion();
116
- if (installedVersion) {
117
- if (expectedVersion && installedVersion !== expectedVersion) {
118
- console.warn(`⚠️ bridge: installed ${installedVersion} but expected ${expectedVersion} (may not be published yet)`);
141
+ // Validate after install using sibling path directly.
142
+ // (require.resolve cannot be used here — Node.js caches negative module
143
+ // resolution results within the same process.)
144
+ if (isBinaryPresent(siblingBinaryPath)) {
145
+ ensureExecutable(siblingBinaryPath);
146
+ const installedVersion = getBinaryVersion(siblingBinaryPath);
147
+ if (installedVersion) {
148
+ if (expectedVersion && installedVersion !== expectedVersion) {
149
+ warn(`⚠️ bridge: installed ${installedVersion} but expected ${expectedVersion} (may not be published yet)`);
150
+ } else {
151
+ log(`✓ bridge ${installedVersion} installed successfully for ${platformKey}`);
152
+ }
119
153
  } else {
120
- console.log(`✓ bridge ${installedVersion} installed successfully for ${platformKey}`);
154
+ warn(`⚠️ bridge: binary present but failed to run — try: ${siblingBinaryPath} --version`);
121
155
  }
122
156
  } else {
123
- console.warn(`⚠️ bridge: binary present but failed to run — try: ${siblingBinaryPath} --version`);
157
+ warn(`\n⚠️ bridge: binary not found after installation`);
158
+ warn(` Run manually: npm install -g ${packageName}${expectedVersion ? '@' + expectedVersion : ''}`);
124
159
  }
125
- } else {
126
- console.warn(`\n⚠️ bridge: binary not found after installation`);
127
- console.warn(` Run manually: npm install -g ${packageName}${expectedVersion ? '@' + expectedVersion : ''}`);
160
+
161
+ exitFn(0);
162
+ }
163
+
164
+ module.exports = { main, PLATFORM_PACKAGES, isBinaryPresent, ensureExecutable, getBinaryVersion, getExpectedVersion };
165
+
166
+ if (require.main === module) {
167
+ main();
128
168
  }