codeplane-ai 31.0.1 → 31.0.2

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 +13 -13
  2. package/postinstall.mjs +80 -17
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "scripts": {
7
7
  "postinstall": "bun ./postinstall.mjs || node ./postinstall.mjs"
8
8
  },
9
- "version": "31.0.1",
9
+ "version": "31.0.2",
10
10
  "license": "MIT",
11
11
  "repository": {
12
12
  "type": "git",
@@ -17,17 +17,17 @@
17
17
  },
18
18
  "homepage": "https://github.com/devinoldenburg/codeplane",
19
19
  "optionalDependencies": {
20
- "codeplane-windows-x64-baseline": "31.0.1",
21
- "codeplane-linux-x64-baseline": "31.0.1",
22
- "codeplane-windows-arm64": "31.0.1",
23
- "codeplane-linux-x64": "31.0.1",
24
- "codeplane-darwin-arm64": "31.0.1",
25
- "codeplane-linux-x64-baseline-musl": "31.0.1",
26
- "codeplane-linux-arm64": "31.0.1",
27
- "codeplane-linux-x64-musl": "31.0.1",
28
- "codeplane-windows-x64": "31.0.1",
29
- "codeplane-darwin-x64": "31.0.1",
30
- "codeplane-linux-arm64-musl": "31.0.1",
31
- "codeplane-darwin-x64-baseline": "31.0.1"
20
+ "codeplane-windows-x64-baseline": "31.0.2",
21
+ "codeplane-linux-x64-baseline": "31.0.2",
22
+ "codeplane-windows-arm64": "31.0.2",
23
+ "codeplane-linux-x64": "31.0.2",
24
+ "codeplane-darwin-arm64": "31.0.2",
25
+ "codeplane-linux-x64-baseline-musl": "31.0.2",
26
+ "codeplane-linux-arm64": "31.0.2",
27
+ "codeplane-linux-x64-musl": "31.0.2",
28
+ "codeplane-windows-x64": "31.0.2",
29
+ "codeplane-darwin-x64": "31.0.2",
30
+ "codeplane-linux-arm64-musl": "31.0.2",
31
+ "codeplane-darwin-x64-baseline": "31.0.2"
32
32
  }
33
33
  }
package/postinstall.mjs CHANGED
@@ -172,30 +172,93 @@ async function tryFindBinaryWithRetry(attempts = 5, delayMs = 200) {
172
172
  throw lastError
173
173
  }
174
174
 
175
- async function main() {
176
- if (os.platform() === "win32") {
177
- // On Windows, the .exe is already included in the package and bin field points to it.
178
- // No postinstall setup needed.
179
- console.log("Windows detected: binary setup not needed (using packaged .exe)")
180
- return
175
+ function selfVersion() {
176
+ try {
177
+ const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, "package.json"), "utf8"))
178
+ return typeof pkg.version === "string" ? pkg.version : undefined
179
+ } catch {
180
+ return undefined
181
+ }
182
+ }
183
+
184
+ // Fetch a platform package's tarball straight from the npm registry and unpack
185
+ // it into our own node_modules. npm silently SKIPS optionalDependencies in
186
+ // several common cases — in-place `npm i -g` upgrades, a transient registry
187
+ // hiccup during install, --no-optional, or a lockfile generated on another OS —
188
+ // which otherwise strands the CLI with "failed to install the right version".
189
+ // Reconstructing the package here means the wrapper's findBinary() resolves it
190
+ // normally, with no shim changes. Fallback-only: never runs on the happy path.
191
+ async function downloadPackage(pkg, version, destDir) {
192
+ const tarball = `${pkg}-${version}.tgz`
193
+ const registry = (process.env.npm_config_registry || "https://registry.npmjs.org").replace(/\/+$/, "")
194
+ const url = `${registry}/${pkg}/-/${tarball}`
195
+ const response = await fetch(url)
196
+ if (!response || !response.ok) {
197
+ throw new Error(`download failed (${response ? response.status : "no response"}) for ${url}`)
198
+ }
199
+ const buffer = Buffer.from(await response.arrayBuffer())
200
+ const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "codeplane-pkg-"))
201
+ try {
202
+ const archive = path.join(tmp, tarball)
203
+ fs.writeFileSync(archive, buffer)
204
+ // npm tarballs unpack to a top-level "package/" directory.
205
+ require("child_process").execFileSync("tar", ["-xzf", archive, "-C", tmp], { stdio: "ignore" })
206
+ const unpacked = path.join(tmp, "package")
207
+ if (!fs.existsSync(unpacked)) throw new Error("tarball did not contain a package/ directory")
208
+ fs.mkdirSync(path.dirname(destDir), { recursive: true })
209
+ fs.rmSync(destDir, { recursive: true, force: true })
210
+ fs.cpSync(unpacked, destDir, { recursive: true })
211
+ } finally {
212
+ fs.rmSync(tmp, { recursive: true, force: true })
181
213
  }
214
+ }
182
215
 
216
+ async function healMissingBinary() {
217
+ const version = selfVersion()
218
+ if (!version) throw new Error("could not read codeplane-ai version")
219
+ const { platform, arch } = detectPlatformAndArch()
220
+ const binaryName = platform === "windows" ? "codeplane.exe" : "codeplane"
221
+ const nodeModules = path.join(__dirname, "node_modules")
222
+ let lastError
223
+ for (const pkg of packageNames(platform, arch)) {
224
+ try {
225
+ const destDir = path.join(nodeModules, pkg)
226
+ await downloadPackage(pkg, version, destDir)
227
+ const binaryPath = path.join(destDir, "bin", binaryName)
228
+ if (!fs.existsSync(binaryPath)) throw new Error(`${pkg} tarball missing bin/${binaryName}`)
229
+ if (platform !== "windows") fs.chmodSync(binaryPath, 0o755)
230
+ return { binaryPath, pkg }
231
+ } catch (error) {
232
+ lastError = error
233
+ }
234
+ }
235
+ throw lastError || new Error("no matching platform package could be installed")
236
+ }
237
+
238
+ async function main() {
183
239
  let binaryPath
184
240
  try {
185
241
  binaryPath = (await tryFindBinaryWithRetry()).binaryPath
186
- } catch (error) {
187
- // The wrapper script (bin/codeplane) does its own findBinary at runtime,
188
- // so a missing optional-dependency here only loses the .codeplane fast-
189
- // start cache — it does NOT prevent codeplane from running. Warn but
190
- // do not fail the install.
191
- console.warn(
192
- "[codeplane postinstall] Skipping fast-start cache: " +
193
- (error && error.message ? error.message : String(error)) +
194
- ". The CLI will still work; startup may be slightly slower on first run.",
195
- )
196
- return
242
+ } catch {
243
+ // optionalDependency missing self-heal by fetching the platform package
244
+ // so the CLI works instead of failing with "failed to install the right version".
245
+ try {
246
+ const healed = await healMissingBinary()
247
+ binaryPath = healed.binaryPath
248
+ console.log("[codeplane postinstall] Installed missing platform package " + healed.pkg + ".")
249
+ } catch (error) {
250
+ console.warn(
251
+ "[codeplane postinstall] Could not install the platform binary automatically: " +
252
+ (error && error.message ? error.message : String(error)) +
253
+ '. Re-run `npm install -g codeplane-ai`, or install the matching "codeplane-<platform>-<arch>" package manually.',
254
+ )
255
+ return
256
+ }
197
257
  }
198
258
 
259
+ // Windows runs the packaged .exe directly via the bin field; no fast-start cache.
260
+ if (os.platform() === "win32") return
261
+
199
262
  try {
200
263
  const target = path.join(__dirname, "bin", ".codeplane")
201
264
  if (fs.existsSync(target)) fs.unlinkSync(target)