diff --git a/.archgate/adrs/ARCH-013-version-synchronization.md b/.archgate/adrs/ARCH-013-version-synchronization.md index 833b9000..0396d8f6 100644 --- a/.archgate/adrs/ARCH-013-version-synchronization.md +++ b/.archgate/adrs/ARCH-013-version-synchronization.md @@ -13,38 +13,33 @@ files: ["package.json", "docs/**"] The CLI version appears in multiple locations that must stay in sync: 1. `package.json` `version` — canonical source of truth -2. `package.json` `optionalDependencies` — platform-specific npm packages (`archgate-darwin-arm64`, `archgate-linux-x64`, `archgate-win32-x64`) must match the CLI version -3. `docs/astro.config.mjs` — `softwareVersion` in the JSON-LD structured data +2. `docs/astro.config.mjs` — `softwareVersion` in the JSON-LD structured data -When versions diverge, npm installs pull mismatched platform binaries and search engines display outdated version info. This was discovered during a consistency review where `package.json` was at `0.16.0` but `docs/astro.config.mjs` was still at `0.11.0`. +When versions diverge, search engines display outdated version info. This was discovered during a consistency review where `package.json` was at `0.16.0` but `docs/astro.config.mjs` was still at `0.11.0`. ## Decision `package.json` `version` is the single source of truth. All other version references MUST match it. -**Automated via release process:** The `.simple-release.js` bump hook already syncs `optionalDependencies` versions during the release workflow — it reads `package.json` after the version bump and updates all `optionalDependencies` entries to match. This is fully automated and requires no manual intervention. - -**Automated via release process:** The `.simple-release.js` bump hook also updates `softwareVersion` in `docs/astro.config.mjs` to match `package.json`. Both syncs are fully automated. +**Automated via release process:** The `.simple-release.js` bump hook updates `softwareVersion` in `docs/astro.config.mjs` to match `package.json`. This is fully automated and requires no manual intervention. ## Do's and Don'ts ### Do -- Rely on `.simple-release.js` for both `optionalDependencies` and `softwareVersion` sync (do not update manually) +- Rely on `.simple-release.js` for `softwareVersion` sync (do not update manually) - Use the companion rules to catch version drift in CI as a safety net ### Don't -- Don't manually edit `optionalDependencies` versions — the release hook handles this - Don't manually edit `softwareVersion` in `docs/astro.config.mjs` — the release hook handles this ## Consequences ### Positive -- Consistent version information across npm packages and user-facing surfaces +- Consistent version information across user-facing surfaces - CI catches version drift before it reaches production -- Platform-specific npm packages always match the CLI version ### Negative @@ -54,11 +49,10 @@ When versions diverge, npm installs pull mismatched platform binaries and search ### Automated Enforcement -- **Release hook** `.simple-release.js`: Syncs `optionalDependencies` versions and `docs/astro.config.mjs` `softwareVersion` during `bump()`. Fully automated. +- **Release hook** `.simple-release.js`: Syncs `docs/astro.config.mjs` `softwareVersion` during `bump()`. Fully automated. - **Archgate rule** `ARCH-013/docs-version-sync`: Checks that `softwareVersion` in `docs/astro.config.mjs` matches `package.json` version. Severity: `error`. -- **Archgate rule** `ARCH-013/optional-deps-version-sync`: Checks that all `optionalDependencies` versions match `package.json` version. Severity: `error`. ## References - [GEN-001 — Documentation Site](./GEN-001-documentation-site.md) — Docs site structure and configuration -- [`.simple-release.js`](../../.simple-release.js) — Release bump hook that syncs optionalDependencies +- [`.simple-release.js`](../../.simple-release.js) — Release bump hook that syncs softwareVersion diff --git a/.archgate/adrs/ARCH-013-version-synchronization.rules.ts b/.archgate/adrs/ARCH-013-version-synchronization.rules.ts index e9dfdc89..d734ea3b 100644 --- a/.archgate/adrs/ARCH-013-version-synchronization.rules.ts +++ b/.archgate/adrs/ARCH-013-version-synchronization.rules.ts @@ -31,26 +31,5 @@ export default { } }, }, - "optional-deps-version-sync": { - description: - "optionalDependencies versions must match package.json version", - severity: "error", - async check(ctx) { - const pkgJson = await ctx.readJSON("package.json"); - if (!pkgJson.version || !pkgJson.optionalDependencies) return; - - for (const [dep, depVersion] of Object.entries( - pkgJson.optionalDependencies - )) { - if (depVersion !== pkgJson.version) { - ctx.report.violation({ - message: `optionalDependencies "${dep}" version "${depVersion}" does not match package.json version "${pkgJson.version}"`, - file: "package.json", - fix: `Update ${dep} to "${pkgJson.version}" in optionalDependencies (normally handled by .simple-release.js during release)`, - }); - } - } - }, - }, }, } satisfies RuleSet; diff --git a/.claude/agent-memory/archgate-developer/MEMORY.md b/.claude/agent-memory/archgate-developer/MEMORY.md index 35a7105a..0d886e8a 100644 --- a/.claude/agent-memory/archgate-developer/MEMORY.md +++ b/.claude/agent-memory/archgate-developer/MEMORY.md @@ -53,11 +53,8 @@ Skipping steps 2 or 3 is a workflow violation. The user should NEVER have to inv ## Distribution / Packaging -- **npm binary distribution (Sentry pattern)** — Binaries are distributed as platform npm packages (`archgate-darwin-arm64`, `archgate-linux-x64`) listed as `optionalDependencies` of the main `archgate` package. Main package has a `bin` field pointing to `bin/archgate.cjs`. +- **npm shim + GitHub Releases** — The npm package is a thin shim (`bin/archgate.cjs` + `scripts/postinstall.cjs`). On first run, the shim downloads the platform binary from GitHub Releases and caches it to `~/.archgate/bin/`. No platform-specific npm packages. - **`.cjs` extension is mandatory** — Root `package.json` has `"type": "module"`. Any Node.js CJS wrapper script placed at the package root MUST use `.cjs`, not `.js`, or Node.js will attempt to parse it as ESM and fail. -- **Platform package version placeholder** — Platform `package.json` files start at version `0.0.0`. CI runs `npm version "$VERSION" --no-git-tag-version` inside the package directory before publishing. -- **Gitignore and prettierignore rules** — `packages/*/bin/archgate` is gitignored (binary injected by CI); `packages/*/bin/` is prettier-ignored (binary files must not be formatted). -- **npm OIDC publishing** — Uses `id-token: write` permission + `actions/setup-node@v4` with `registry-url: 'https://registry.npmjs.org'`. No `NODE_AUTH_TOKEN` secret needed for OIDC trusted publishing — matches the pattern in `release.yml`. ## Telemetry Strategy diff --git a/.github/workflows/release-binaries.yml b/.github/workflows/release-binaries.yml index ff1cb93d..45ff35cf 100644 --- a/.github/workflows/release-binaries.yml +++ b/.github/workflows/release-binaries.yml @@ -11,11 +11,10 @@ on: permissions: contents: write - id-token: write jobs: - build-and-publish: - name: Build and publish ${{ matrix.artifact }} + build: + name: Build ${{ matrix.artifact }} timeout-minutes: 15 strategy: fail-fast: false @@ -58,29 +57,6 @@ jobs: run: | bun build src/cli.ts --compile --bytecode --minify --target ${{ matrix.target }} --outfile dist/${{ matrix.artifact }} - - name: Copy binary into npm package (Unix) - if: runner.os != 'Windows' - run: | - TAG="${{ github.event.release.tag_name || inputs.tag }}" - VERSION="${TAG#v}" - cp dist/${{ matrix.artifact }} packages/${{ matrix.artifact }}/bin/${{ matrix.binary_name }} - chmod +x packages/${{ matrix.artifact }}/bin/${{ matrix.binary_name }} - cd packages/${{ matrix.artifact }} - npm version "$VERSION" --no-git-tag-version - - - name: Copy binary into npm package (Windows) - if: runner.os == 'Windows' - shell: pwsh - run: | - $tag = "${{ github.event.release.tag_name || inputs.tag }}" - $version = $tag -replace '^v', '' - Copy-Item "dist/${{ matrix.artifact }}.exe" "packages/${{ matrix.artifact }}/bin/${{ matrix.binary_name }}" - Set-Location "packages/${{ matrix.artifact }}" - npm version "$version" --no-git-tag-version - - - name: Publish platform package - run: npm publish ./packages/${{ matrix.artifact }} --access public --provenance - - name: Prepare release asset (Unix) if: runner.os != 'Windows' run: | diff --git a/.gitignore b/.gitignore index 8771b7a2..e60f2c37 100644 --- a/.gitignore +++ b/.gitignore @@ -34,9 +34,6 @@ coverage *.tgz .npm -# Platform package binaries (injected by CI) -packages/*/bin/archgate - # Docs site build artifacts docs/.astro/ diff --git a/.simple-release.js b/.simple-release.js index 76cf41f8..231fd1de 100644 --- a/.simple-release.js +++ b/.simple-release.js @@ -1,4 +1,3 @@ -import { execSync } from "node:child_process"; import { existsSync, readFileSync, writeFileSync } from "node:fs"; import { NpmProject } from "@simple-release/npm"; @@ -11,21 +10,6 @@ class ArchgateProject extends NpmProject { const pkgPath = "package.json"; const pkg = JSON.parse(readFileSync(pkgPath, "utf8")); const version = pkg.version; - let changed = false; - - // Sync optionalDependencies (platform-specific npm packages) - for (const dep of Object.keys(pkg.optionalDependencies || {})) { - if (pkg.optionalDependencies[dep] !== version) { - pkg.optionalDependencies[dep] = version; - changed = true; - } - } - - if (changed) { - writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n"); - execSync("bun install", { stdio: "inherit" }); - this.changedFiles.push("bun.lock"); - } // Sync docs/astro.config.mjs softwareVersion const astroConfigPath = "docs/astro.config.mjs"; diff --git a/CLAUDE.md b/CLAUDE.md index 2d6d0345..80740bb5 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -47,7 +47,7 @@ Zod schemas are the single source of truth. Types derived via `z.infer<>` — ne ## npm Distribution -The npm package is a **thin shim** — it contains only `bin/archgate.cjs` and `scripts/postinstall.cjs`. The postinstall script downloads the prebuilt platform binary. All runtime dependencies (commander, inquirer, zod) are bundled into the compiled binary via `bun build --compile`, so they belong in `devDependencies`, not `dependencies`. The `optionalDependencies` (archgate-darwin-arm64, etc.) are platform-specific binary packages synced to the CLI version by `.simple-release.js` during release. +The npm package is a **thin shim** — it contains only `bin/archgate.cjs` and `scripts/postinstall.cjs`. The shim downloads the platform binary from GitHub Releases on first run and caches it to `~/.archgate/bin/`. All runtime dependencies (commander, inquirer, zod) are bundled into the compiled binary via `bun build --compile`, so they belong in `devDependencies`, not `dependencies`. ## Conventions diff --git a/bin/archgate.cjs b/bin/archgate.cjs index b4110d01..a1c3f494 100755 --- a/bin/archgate.cjs +++ b/bin/archgate.cjs @@ -1,13 +1,14 @@ #!/usr/bin/env node "use strict"; -const { execFileSync } = require("child_process"); +const { execFileSync, execSync } = require("child_process"); const https = require("https"); const zlib = require("zlib"); const path = require("path"); const fs = require("fs"); +const os = require("os"); -function getPlatformPackageName() { +function getArtifactName() { const { platform, arch } = process; if (platform === "darwin" && arch === "arm64") return "archgate-darwin-arm64"; if (platform === "linux" && arch === "x64") return "archgate-linux-x64"; @@ -21,6 +22,10 @@ function getBinaryName() { return process.platform === "win32" ? "archgate.exe" : "archgate"; } +function getCacheDir() { + return path.join(os.homedir(), ".archgate", "bin"); +} + function getPackageVersion() { const pkg = JSON.parse( fs.readFileSync(path.join(__dirname, "..", "package.json"), "utf8") @@ -29,34 +34,20 @@ function getPackageVersion() { } function getBinaryPath() { - const pkgName = getPlatformPackageName(); const binaryName = getBinaryName(); - - // 1. Try the platform-specific optional dependency (normal path). - try { - const pkgDir = path.dirname(require.resolve(`${pkgName}/package.json`)); - const binaryPath = path.join(pkgDir, "bin", binaryName); - if (fs.existsSync(binaryPath)) return binaryPath; - } catch { - /* platform package not installed */ - } - - // 2. Fallback: binary downloaded into our own bin/ by postinstall or a - // previous on-demand download. - const fallbackPath = path.join(__dirname, binaryName); - if (fs.existsSync(fallbackPath)) return fallbackPath; - + const cachePath = path.join(getCacheDir(), binaryName); + if (fs.existsSync(cachePath)) return cachePath; return null; } // --------------------------------------------------------------------------- -// On-demand download from the npm registry +// On-demand download from GitHub Releases // --------------------------------------------------------------------------- function fetchWithRedirects(url) { return new Promise((resolve, reject) => { https - .get(url, (res) => { + .get(url, { headers: { "User-Agent": "archgate-cli" } }, (res) => { if ( res.statusCode >= 300 && res.statusCode < 400 && @@ -82,74 +73,106 @@ function stripNulls(str) { } /** - * Download the platform-specific npm package tarball and extract the binary. + * Download the platform binary from GitHub Releases and cache it. * Returns the path to the downloaded binary. */ async function downloadBinary() { - const pkgName = getPlatformPackageName(); + const artifactName = getArtifactName(); const version = getPackageVersion(); const binaryName = getBinaryName(); + const isWin = process.platform === "win32"; + const ext = isWin ? "zip" : "tar.gz"; - const url = `https://registry.npmjs.org/${pkgName}/-/${pkgName}-${version}.tgz`; - console.error( - `archgate: binary not found, downloading ${pkgName}@${version}...` - ); - - const res = await fetchWithRedirects(url); + const url = `https://github.com/archgate/cli/releases/download/v${version}/${artifactName}.${ext}`; + console.error(`archgate: binary not found, downloading v${version}...`); - const binDir = __dirname; - const destPath = path.join(binDir, binaryName); + const cacheDir = getCacheDir(); + fs.mkdirSync(cacheDir, { recursive: true }); + const destPath = path.join(cacheDir, binaryName); - return new Promise((resolve, reject) => { - const gunzip = zlib.createGunzip(); + if (isWin) { + // Download zip to temp file, extract with PowerShell + const res = await fetchWithRedirects(url); const chunks = []; - const expectedSuffix = `bin/${binaryName}`; - let found = false; - - res.pipe(gunzip); - gunzip.on("data", (chunk) => chunks.push(chunk)); - gunzip.on("end", () => { - const data = Buffer.concat(chunks); - let offset = 0; - - while (offset + 512 <= data.length) { - const header = data.subarray(offset, offset + 512); - offset += 512; - - // Empty header block signals end of archive - if (header.every((b) => b === 0)) break; - - let name = stripNulls(header.subarray(0, 100).toString("utf8")); - const prefix = stripNulls(header.subarray(345, 500).toString("utf8")); - if (prefix) name = `${prefix}/${name}`; - - const sizeStr = stripNulls( - header.subarray(124, 136).toString("utf8") - ).trim(); - const size = parseInt(sizeStr, 8) || 0; - const blocks = Math.ceil(size / 512); - const fileData = data.subarray(offset, offset + size); - offset += blocks * 512; - - if (name.endsWith(expectedSuffix)) { - fs.writeFileSync(destPath, fileData, { mode: 0o755 }); - found = true; - break; - } + await new Promise((resolve, reject) => { + res.on("data", (chunk) => chunks.push(chunk)); + res.on("end", resolve); + res.on("error", reject); + }); + const tmpZip = path.join(cacheDir, "archgate-download.zip"); + const tmpExtract = path.join(cacheDir, "archgate-extract"); + fs.writeFileSync(tmpZip, Buffer.concat(chunks)); + try { + fs.mkdirSync(tmpExtract, { recursive: true }); + execSync( + `powershell -NoProfile -Command "Expand-Archive -Path '${tmpZip}' -DestinationPath '${tmpExtract}' -Force"`, + { stdio: "pipe" } + ); + const extractedBinary = path.join(tmpExtract, binaryName); + if (!fs.existsSync(extractedBinary)) { + throw new Error(`Binary ${binaryName} not found in zip archive`); } + fs.copyFileSync(extractedBinary, destPath); + } finally { + try { fs.unlinkSync(tmpZip); } catch { /* cleanup */ } + try { fs.rmSync(tmpExtract, { recursive: true, force: true }); } catch { /* cleanup */ } + } + } else { + // Download tar.gz, extract binary using inline tar parser + const res = await fetchWithRedirects(url); + await new Promise((resolve, reject) => { + const gunzip = zlib.createGunzip(); + const chunks = []; + + res.pipe(gunzip); + gunzip.on("data", (chunk) => chunks.push(chunk)); + gunzip.on("end", () => { + const data = Buffer.concat(chunks); + let offset = 0; + let found = false; + + while (offset + 512 <= data.length) { + const header = data.subarray(offset, offset + 512); + offset += 512; + + if (header.every((b) => b === 0)) break; + + let name = stripNulls(header.subarray(0, 100).toString("utf8")); + const prefix = stripNulls( + header.subarray(345, 500).toString("utf8") + ); + if (prefix) name = `${prefix}/${name}`; + + const sizeStr = stripNulls( + header.subarray(124, 136).toString("utf8") + ).trim(); + const size = parseInt(sizeStr, 8) || 0; + const blocks = Math.ceil(size / 512); + const fileData = data.subarray(offset, offset + size); + offset += blocks * 512; + + if (name === binaryName || name.endsWith(`/${binaryName}`)) { + fs.writeFileSync(destPath, fileData, { mode: 0o755 }); + found = true; + break; + } + } - if (found) { - console.error(`archgate: binary downloaded successfully.`); - resolve(destPath); - } else { - reject( - new Error(`Could not find ${expectedSuffix} in tarball from ${url}`) - ); - } + if (found) { + resolve(); + } else { + reject( + new Error(`Could not find ${binaryName} in archive from ${url}`) + ); + } + }); + + gunzip.on("error", reject); }); + } - gunzip.on("error", reject); - }); + console.error(`archgate: binary downloaded successfully.`); + return destPath; } // --------------------------------------------------------------------------- @@ -159,15 +182,14 @@ async function downloadBinary() { async function main() { let binary = getBinaryPath(); - // If the binary is missing (optional dep skipped AND postinstall blocked), - // download it on-demand from the npm registry. + // If the binary is missing, download it on-demand from GitHub Releases. if (!binary) { try { binary = await downloadBinary(); } catch (err) { console.error( `archgate: failed to download binary: ${err.message}\n` + - `Try reinstalling: npm install archgate` + `Visit https://cli.archgate.dev/getting-started/installation/ for alternative install methods.` ); process.exit(2); } diff --git a/bun.lock b/bun.lock index ba6797e4..d63db033 100644 --- a/bun.lock +++ b/bun.lock @@ -21,11 +21,6 @@ "posthog-node": "5.28.5", "zod": "4.3.6", }, - "optionalDependencies": { - "archgate-darwin-arm64": "0.26.0", - "archgate-linux-x64": "0.26.0", - "archgate-win32-x64": "0.26.0", - }, "peerDependencies": { "typescript": "^5 || ^6.0.0", }, diff --git a/docs/public/llms-full.txt b/docs/public/llms-full.txt index 6c5ff751..aaa17db5 100644 --- a/docs/public/llms-full.txt +++ b/docs/public/llms-full.txt @@ -210,13 +210,13 @@ pnpm check:adrs Archgate ships pre-built binaries for the following platforms: -| Platform | Architecture | Package | +| Platform | Architecture | Artifact | | -------- | ------------ | ----------------------- | | macOS | arm64 | `archgate-darwin-arm64` | | Linux | x86_64 | `archgate-linux-x64` | | Windows | x86_64 | `archgate-win32-x64` | -The correct binary is installed automatically as an `optionalDependency` when you install `archgate`. +The correct binary is downloaded automatically from GitHub Releases on first run and cached to `~/.archgate/bin/`. ## Verify installation diff --git a/docs/src/content/docs/getting-started/installation.mdx b/docs/src/content/docs/getting-started/installation.mdx index 2a150388..8dacae1f 100644 --- a/docs/src/content/docs/getting-started/installation.mdx +++ b/docs/src/content/docs/getting-started/installation.mdx @@ -97,13 +97,13 @@ pnpm check:adrs Archgate ships pre-built binaries for the following platforms: -| Platform | Architecture | Package | +| Platform | Architecture | Artifact | | -------- | ------------ | ----------------------- | | macOS | arm64 | `archgate-darwin-arm64` | | Linux | x86_64 | `archgate-linux-x64` | | Windows | x86_64 | `archgate-win32-x64` | -The correct binary is installed automatically as an `optionalDependency` when you install `archgate`. +The correct binary is downloaded automatically from GitHub Releases on first run and cached to `~/.archgate/bin/`. ## Verify installation diff --git a/docs/src/content/docs/pt-br/getting-started/installation.mdx b/docs/src/content/docs/pt-br/getting-started/installation.mdx index adb2da62..cefe5d83 100644 --- a/docs/src/content/docs/pt-br/getting-started/installation.mdx +++ b/docs/src/content/docs/pt-br/getting-started/installation.mdx @@ -97,13 +97,13 @@ pnpm check:adrs O Archgate disponibiliza binários pré-compilados para as seguintes plataformas: -| Plataforma | Arquitetura | Pacote | +| Plataforma | Arquitetura | Artefato | | ---------- | ----------- | ----------------------- | | macOS | arm64 | `archgate-darwin-arm64` | | Linux | x86_64 | `archgate-linux-x64` | | Windows | x86_64 | `archgate-win32-x64` | -O binário correto é instalado automaticamente como `optionalDependency` quando você instala o `archgate`. +O binário correto é baixado automaticamente do GitHub Releases na primeira execução e armazenado em cache em `~/.archgate/bin/`. ## Verificar a instalação diff --git a/package.json b/package.json index c197b0e1..9f03c670 100644 --- a/package.json +++ b/package.json @@ -75,10 +75,5 @@ "peerDependencies": { "typescript": "^5 || ^6.0.0" }, - "optionalDependencies": { - "archgate-darwin-arm64": "0.26.0", - "archgate-linux-x64": "0.26.0", - "archgate-win32-x64": "0.26.0" - }, "readme": "README.md" } diff --git a/packages/archgate-darwin-arm64/bin/.gitkeep b/packages/archgate-darwin-arm64/bin/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/packages/archgate-darwin-arm64/package.json b/packages/archgate-darwin-arm64/package.json deleted file mode 100644 index d44a4fb8..00000000 --- a/packages/archgate-darwin-arm64/package.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "archgate-darwin-arm64", - "version": "0.0.0", - "description": "darwin arm64 binary for archgate", - "license": "Apache-2.0", - "repository": { - "type": "git", - "url": "git+https://github.com/archgate/cli.git" - }, - "files": [ - "bin/archgate" - ], - "os": [ - "darwin" - ], - "cpu": [ - "arm64" - ] -} diff --git a/packages/archgate-linux-x64/bin/.gitkeep b/packages/archgate-linux-x64/bin/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/packages/archgate-linux-x64/package.json b/packages/archgate-linux-x64/package.json deleted file mode 100644 index cb2ba141..00000000 --- a/packages/archgate-linux-x64/package.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "archgate-linux-x64", - "version": "0.0.0", - "description": "linux x64 binary for archgate", - "license": "Apache-2.0", - "repository": { - "type": "git", - "url": "git+https://github.com/archgate/cli.git" - }, - "files": [ - "bin/archgate" - ], - "os": [ - "linux" - ], - "cpu": [ - "x64" - ] -} diff --git a/packages/archgate-win32-x64/bin/.gitkeep b/packages/archgate-win32-x64/bin/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/packages/archgate-win32-x64/package.json b/packages/archgate-win32-x64/package.json deleted file mode 100644 index 8e21ef7a..00000000 --- a/packages/archgate-win32-x64/package.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "archgate-win32-x64", - "version": "0.0.0", - "description": "windows x64 binary for archgate", - "license": "Apache-2.0", - "repository": { - "type": "git", - "url": "git+https://github.com/archgate/cli.git" - }, - "files": [ - "bin/archgate.exe" - ], - "os": [ - "win32" - ], - "cpu": [ - "x64" - ] -} diff --git a/scripts/postinstall.cjs b/scripts/postinstall.cjs index ef375ee2..b561fc5e 100644 --- a/scripts/postinstall.cjs +++ b/scripts/postinstall.cjs @@ -8,32 +8,12 @@ const path = require("path"); const fs = require("fs"); - -const PACKAGE_NAME_MAP = { - "darwin-arm64": "archgate-darwin-arm64", - "linux-x64": "archgate-linux-x64", - "win32-x64": "archgate-win32-x64", -}; +const os = require("os"); function isBinaryPresent() { - const key = `${process.platform}-${process.arch}`; - const pkgName = PACKAGE_NAME_MAP[key]; - if (!pkgName) return true; // unsupported platform — skip silently - const binaryName = process.platform === "win32" ? "archgate.exe" : "archgate"; - - // Check optional dependency - try { - const pkgDir = path.dirname(require.resolve(`${pkgName}/package.json`)); - if (fs.existsSync(path.join(pkgDir, "bin", binaryName))) return true; - } catch { - /* not installed */ - } - - // Check local fallback - if (fs.existsSync(path.join(__dirname, "..", "bin", binaryName))) return true; - - return false; + const cachePath = path.join(os.homedir(), ".archgate", "bin", binaryName); + return fs.existsSync(cachePath); } if (!isBinaryPresent()) {