22 * @fileoverview Socket-btm release download utilities.
33 *
44 * Provides utilities for downloading binaries and assets from the
5- * SocketDev/socket-btm GitHub repository. This includes build tools (binject,
6- * binflate, binpress), Node.js binaries (node-smol), and WASM assets
7- * (yoga-layout).
5+ * SocketDev/socket-btm GitHub repository. This includes build tools,
6+ * Node.js binaries, and WASM assets.
87 *
98 * Features:
109 * - Generic function for any socket-btm release asset or binary
2019 * ├── {binaryName}
2120 * └── .version
2221 * ```
23- *
24- * @example
25- * ```ts
26- * import { downloadSocketBtmRelease } from '@socketsecurity/lib/releases/socket-btm'
27- *
28- * // Download node-smol binary (like: brew install nodejs → /usr/local/bin/node)
29- * const nodePath = await downloadSocketBtmRelease({
30- * tool: 'node-smol',
31- * bin: 'node' // Presence of 'bin' = binary download
32- * })
33- *
34- * // Download binject binary (like: cargo install binject → binject)
35- * const binjectPath = await downloadSocketBtmRelease({
36- * tool: 'binject' // No 'bin' or 'asset' = binary with bin=tool
37- * })
38- *
39- * // Cross-platform binary (like: cargo install --target)
40- * const nodePathLinux = await downloadSocketBtmRelease({
41- * tool: 'node-smol',
42- * bin: 'node',
43- * targetPlatform: 'linux',
44- * targetArch: 'x64',
45- * libc: 'musl'
46- * })
47- *
48- * // Download WASM asset (like: gh release download --pattern)
49- * const yogaPath = await downloadSocketBtmRelease({
50- * tool: 'yoga-layout',
51- * asset: 'yoga-sync.mjs' // Presence of 'asset' = asset download
52- * })
53- * ```
5422 */
5523
56- import os from 'node:os'
24+ import { existsSync } from 'fs'
25+ import os from 'os'
5726
5827import {
5928 downloadGitHubRelease ,
@@ -128,7 +97,7 @@ export interface SocketBtmBinaryConfig {
12897 targetArch ?: Arch
12998 /**
13099 * Linux libc variant (musl or glibc).
131- * Defaults to musl for Linux for broader compatibility .
100+ * Auto-detected from the Node.js binary if not specified .
132101 * Ignored for non-Linux platforms.
133102 */
134103 libc ?: Libc
@@ -241,6 +210,46 @@ const ARCH_MAP: Record<string, string> = {
241210 x64 : 'x64' ,
242211}
243212
213+ /**
214+ * Detect the libc variant (musl or glibc) on Linux systems.
215+ * Returns undefined for non-Linux platforms.
216+ *
217+ * Detection method: Check for musl-specific files in the filesystem.
218+ * This is more reliable than checking the Node.js binary, especially for
219+ * statically-linked binaries that may contain references to both libc variants.
220+ *
221+ * @returns 'musl', 'glibc', or undefined (for non-Linux)
222+ */
223+ function detectLibc ( ) : Libc | undefined {
224+ const platform = os . platform ( )
225+ if ( platform !== 'linux' ) {
226+ return undefined
227+ }
228+
229+ try {
230+ // Check for musl-specific dynamic linker
231+ // These files only exist on musl systems
232+ const muslPaths = [
233+ '/lib/ld-musl-x86_64.so.1' ,
234+ '/lib/ld-musl-aarch64.so.1' ,
235+ '/usr/lib/ld-musl-x86_64.so.1' ,
236+ '/usr/lib/ld-musl-aarch64.so.1' ,
237+ ]
238+
239+ for ( const path of muslPaths ) {
240+ if ( existsSync ( path ) ) {
241+ return 'musl'
242+ }
243+ }
244+
245+ // If no musl files found, assume glibc
246+ return 'glibc'
247+ } catch {
248+ // If detection fails, default to glibc (most common)
249+ return 'glibc'
250+ }
251+ }
252+
244253/**
245254 * Get asset name for a socket-btm binary.
246255 *
@@ -259,7 +268,7 @@ function getBinaryAssetName(
259268 binaryBaseName : string ,
260269 platform : Platform ,
261270 arch : Arch ,
262- libc ?: Libc ,
271+ libc ?: Libc | undefined ,
263272) : string {
264273 const mappedArch = ARCH_MAP [ arch ]
265274 if ( ! mappedArch ) {
@@ -431,12 +440,12 @@ export async function downloadSocketBtmRelease(
431440 // Default bin to tool if not provided (like brew/cargo)
432441 const baseName = bin || tool
433442
434- // Resolve platform and arch
443+ // Resolve platform and arch based on host if not specified
435444 const platform = ( targetPlatform || os . platform ( ) ) as Platform
436445 const arch = ( targetArch || os . arch ( ) ) as Arch
437446
438- // Default to musl for Linux for broader compatibility (works on both musl and glibc systems)
439- const libcType = libc || ( platform === 'linux' ? 'musl' : undefined )
447+ // Auto-detect libc variant on Linux if not specified
448+ const libcType = libc || detectLibc ( )
440449
441450 // Build asset name and platform-arch identifier
442451 const assetName = getBinaryAssetName ( baseName , platform , arch , libcType )
0 commit comments