@socketsecurity/lib 2.0.0 → 2.1.0
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/CHANGELOG.md +8 -0
- package/dist/dlx-package.d.ts +51 -0
- package/dist/dlx-package.js +1 -1
- package/dist/dlx-package.js.map +3 -3
- package/dist/dlx.d.ts +15 -0
- package/dist/dlx.js +1 -1
- package/dist/dlx.js.map +3 -3
- package/dist/env/package-manager.d.ts +58 -0
- package/dist/env/package-manager.js +3 -0
- package/dist/env/package-manager.js.map +7 -0
- package/package.json +5 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [2.1.0](https://github.com/SocketDev/socket-lib/releases/tag/v2.1.0) - 2025-10-28
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Package manager detection utilities (`detectPackageManager()`, `getPackageManagerInfo()`, `getPackageManagerUserAgent()`)
|
|
13
|
+
- `isInSocketDlx()` utility to check if file path is within `~/.socket/_dlx/`
|
|
14
|
+
- `downloadPackage()` and `executePackage()` functions for separate download and execution of packages
|
|
15
|
+
|
|
8
16
|
## [2.0.0](https://github.com/SocketDev/socket-lib/releases/tag/v2.0.0) - 2025-10-27
|
|
9
17
|
|
|
10
18
|
### Breaking Changes
|
package/dist/dlx-package.d.ts
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import type { SpawnExtra, SpawnOptions } from './spawn';
|
|
2
2
|
import { spawn } from './spawn';
|
|
3
|
+
export interface DownloadPackageResult {
|
|
4
|
+
/** Path to the installed package directory. */
|
|
5
|
+
packageDir: string;
|
|
6
|
+
/** Path to the binary. */
|
|
7
|
+
binaryPath: string;
|
|
8
|
+
/** Whether the package was newly installed. */
|
|
9
|
+
installed: boolean;
|
|
10
|
+
}
|
|
3
11
|
export interface DlxPackageOptions {
|
|
4
12
|
/**
|
|
5
13
|
* Package to install (e.g., '@cyclonedx/cdxgen@10.0.0').
|
|
@@ -31,5 +39,48 @@ export interface DlxPackageResult {
|
|
|
31
39
|
* our own cache directory (~/.socket/_dlx) and installation logic.
|
|
32
40
|
*
|
|
33
41
|
* Auto-forces reinstall for version ranges to get latest within range.
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```typescript
|
|
45
|
+
* // Download and execute cdxgen
|
|
46
|
+
* const result = await dlxPackage(
|
|
47
|
+
* ['--version'],
|
|
48
|
+
* { package: '@cyclonedx/cdxgen@10.0.0' }
|
|
49
|
+
* )
|
|
50
|
+
* await result.spawnPromise
|
|
51
|
+
* ```
|
|
34
52
|
*/
|
|
35
53
|
export declare function dlxPackage(args: readonly string[] | string[], options?: DlxPackageOptions | undefined, spawnExtra?: SpawnExtra | undefined): Promise<DlxPackageResult>;
|
|
54
|
+
/**
|
|
55
|
+
* Download and install a package without executing it.
|
|
56
|
+
* This is useful for self-update or when you need the package files
|
|
57
|
+
* but don't want to run the binary immediately.
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```typescript
|
|
61
|
+
* // Install @socketsecurity/cli without running it
|
|
62
|
+
* const result = await downloadPackage({
|
|
63
|
+
* package: '@socketsecurity/cli@1.2.0',
|
|
64
|
+
* force: true
|
|
65
|
+
* })
|
|
66
|
+
* console.log('Installed to:', result.packageDir)
|
|
67
|
+
* console.log('Binary at:', result.binaryPath)
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
export declare function downloadPackage(options: DlxPackageOptions): Promise<DownloadPackageResult>;
|
|
71
|
+
/**
|
|
72
|
+
* Execute a package's binary.
|
|
73
|
+
* The package must already be installed (use downloadPackage first).
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* ```typescript
|
|
77
|
+
* // Execute an already-installed package
|
|
78
|
+
* const downloaded = await downloadPackage({ package: 'cowsay@1.5.0' })
|
|
79
|
+
* const result = await executePackage(
|
|
80
|
+
* downloaded.binaryPath,
|
|
81
|
+
* ['Hello World'],
|
|
82
|
+
* { stdio: 'inherit' }
|
|
83
|
+
* )
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
export declare function executePackage(binaryPath: string, args: readonly string[] | string[], spawnOptions?: SpawnOptions | undefined, spawnExtra?: SpawnExtra | undefined): ReturnType<typeof spawn>;
|
package/dist/dlx-package.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
/* Socket Lib - Built with esbuild */
|
|
2
|
-
var
|
|
2
|
+
var j=Object.create;var l=Object.defineProperty;var v=Object.getOwnPropertyDescriptor;var _=Object.getOwnPropertyNames;var E=Object.getPrototypeOf,J=Object.prototype.hasOwnProperty;var $=(n,e)=>{for(var t in e)l(n,t,{get:e[t],enumerable:!0})},m=(n,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let a of _(e))!J.call(n,a)&&a!==t&&l(n,a,{get:()=>e[a],enumerable:!(r=v(e,a))||r.enumerable});return n};var k=(n,e,t)=>(t=n!=null?j(E(n)):{},m(e||!n||!n.__esModule?l(t,"default",{value:n,enumerable:!0}):t,n)),I=n=>m(l({},"__esModule",{value:!0}),n);var W={};$(W,{dlxPackage:()=>V,downloadPackage:()=>S,executePackage:()=>O});module.exports=I(W);var P=require("node:crypto"),p=require("node:fs"),s=k(require("node:path")),h=k(require("./external/pacote")),w=require("./constants/platform"),x=require("./constants/packages"),y=require("./fs"),g=require("./path"),D=require("./paths"),b=require("./spawn");const N=/[~^><=xX* ]|\|\|/;function C(n){return(0,P.createHash)("sha256").update(n).digest("hex").slice(0,16)}function A(n){if(n.startsWith("@")){const t=n.split("@");return t.length===3?{name:t[1],version:t[2]}:t.length===2?{name:`@${t[1]}`,version:void 0}:{name:`@${t[1]}`,version:t[2]}}const e=n.lastIndexOf("@");return e===-1?{name:n,version:void 0}:{name:n.slice(0,e),version:n.slice(e+1)}}async function K(n,e,t){const r=C(n),a=(0,g.normalizePath)(s.default.join((0,D.getSocketDlxDir)(),r)),c=(0,g.normalizePath)(s.default.join(a,"node_modules",e));if(!t&&(0,p.existsSync)(c)){const i=s.default.join(c,"package.json");if((0,p.existsSync)(i))return{installed:!1,packageDir:a}}await p.promises.mkdir(a,{recursive:!0});const o=(0,x.getPacoteCachePath)();return await h.default.extract(n,c,{cache:o||s.default.join(a,".cache")}),{installed:!0,packageDir:a}}function T(n,e,t){const r=(0,g.normalizePath)(s.default.join(n,"node_modules",e)),a=s.default.join(r,"package.json"),o=(0,y.readJsonSync)(a).bin;let i;if(typeof o=="string")i=o;else if(typeof o=="object"&&o!==null){const d=t||e.split("/").pop();i=o[d]}if(!i)throw new Error(`No binary found for package "${e}"`);return(0,g.normalizePath)(s.default.join(r,i))}async function V(n,e,t){const r=await S(e),a=O(r.binaryPath,n,e?.spawnOptions,t);return{...r,spawnPromise:a}}async function S(n){const{force:e,package:t}={__proto__:null,...n},{name:r,version:a}=A(t),c=a!==void 0&&N.test(a),o=e!==void 0?e:c,i=a?`${r}@${a}`:r,{installed:d,packageDir:u}=await K(i,r,o),f=T(u,r);if(!w.WIN32&&(0,p.existsSync)(f)){const{chmodSync:R}=require("node:fs");try{R(f,493)}catch{}}return{binaryPath:f,installed:d,packageDir:u}}function O(n,e,t,r){return(0,b.spawn)(n,e,t,r)}0&&(module.exports={dlxPackage,downloadPackage,executePackage});
|
|
3
3
|
//# sourceMappingURL=dlx-package.js.map
|
package/dist/dlx-package.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/dlx-package.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * @fileoverview DLX package execution - Install and execute npm packages.\n *\n * This module provides functionality to install and execute npm packages\n * in the ~/.socket/_dlx directory, similar to npx but with Socket's own cache.\n *\n * Uses content-addressed storage like npm's _npx:\n * - Hash is generated from package spec (name@version)\n * - Each unique spec gets its own directory: ~/.socket/_dlx/<hash>/\n * - Allows caching multiple versions of the same package\n *\n * Version range handling:\n * - Exact versions (1.0.0) use cache if available\n * - Range versions (^1.0.0, ~1.0.0) auto-force to get latest within range\n * - User can override with explicit force: false\n *\n * Key difference from dlx-binary.ts:\n * - dlx-binary.ts: Downloads standalone binaries from URLs\n * - dlx-package.ts: Installs npm packages from registries\n */\n\nimport { createHash } from 'node:crypto'\nimport { existsSync } from 'node:fs'\nimport path from 'node:path'\n\nimport { WIN32 } from './constants/platform'\nimport { readJsonSync } from './fs'\nimport { normalizePath } from './path'\nimport { getSocketDlxDir } from './paths'\nimport type { SpawnExtra, SpawnOptions } from './spawn'\nimport { spawn } from './spawn'\n\n/**\n * Regex to check if a version string contains range operators.\n * Matches any version with range operators: ~, ^, >, <, =, x, X, *, spaces, or ||.\n */\nconst rangeOperatorsRegExp = /[~^><=xX* ]|\\|\\|/\n\nexport interface DlxPackageOptions {\n /**\n * Package to install (e.g., '@cyclonedx/cdxgen@10.0.0').\n */\n package: string\n /**\n * Force reinstallation even if package exists.\n */\n force?: boolean | undefined\n /**\n * Additional spawn options for the execution.\n */\n spawnOptions?: SpawnOptions | undefined\n}\n\nexport interface DlxPackageResult {\n /** Path to the installed package directory. */\n packageDir: string\n /** Path to the binary that was executed. */\n binaryPath: string\n /** Whether the package was newly installed. */\n installed: boolean\n /** The spawn promise for the running process. */\n spawnPromise: ReturnType<typeof spawn>\n}\n\n/**\n * Generate a cache key from package spec, similar to npm's _npx.\n * Uses first 16 hex characters of SHA256 hash.\n */\nfunction generatePackageCacheKey(packageSpec: string): string {\n return createHash('sha256').update(packageSpec).digest('hex').slice(0, 16)\n}\n\n/**\n * Parse package spec into name and version.\n * Examples:\n * - 'lodash@4.17.21' \u2192 { name: 'lodash', version: '4.17.21' }\n * - '@scope/pkg@1.0.0' \u2192 { name: '@scope/pkg', version: '1.0.0' }\n * - 'lodash' \u2192 { name: 'lodash', version: undefined }\n */\nfunction parsePackageSpec(spec: string): {\n name: string\n version: string | undefined\n} {\n // Handle scoped packages (@scope/name@version).\n if (spec.startsWith('@')) {\n const parts = spec.split('@')\n if (parts.length === 3) {\n // @scope@version -> Invalid, but handle gracefully.\n return { name: parts[1], version: parts[2] }\n }\n if (parts.length === 2) {\n // @scope/name with no version.\n return { name: `@${parts[1]}`, version: undefined }\n }\n // @scope/name@version.\n const scopeAndName = `@${parts[1]}`\n return { name: scopeAndName, version: parts[2] }\n }\n\n // Handle unscoped packages (name@version).\n const atIndex = spec.lastIndexOf('@')\n if (atIndex === -1) {\n return { name: spec, version: undefined }\n }\n\n return {\n name: spec.slice(0, atIndex),\n version: spec.slice(atIndex + 1),\n }\n}\n\n/**\n * Install package to ~/.socket/_dlx/<hash>/ if not already installed.\n */\nasync function ensurePackageInstalled(\n packageSpec: string,\n packageName: string,\n force: boolean,\n): Promise<{ installed: boolean; packageDir: string }> {\n const cacheKey = generatePackageCacheKey(packageSpec)\n const packageDir = normalizePath(path.join(getSocketDlxDir(), cacheKey))\n const installedDir = normalizePath(\n path.join(packageDir, 'node_modules', packageName),\n )\n\n // Check if already installed (unless force).\n if (!force && existsSync(installedDir)) {\n // Verify package.json exists.\n const pkgJsonPath = path.join(installedDir, 'package.json')\n if (existsSync(pkgJsonPath)) {\n return { installed: false, packageDir }\n }\n }\n\n // Use npm install --prefix to install to specific directory.\n await spawn(\n 'npm',\n [\n 'install',\n '--prefix',\n packageDir,\n '--no-save',\n '--no-package-lock',\n '--no-audit',\n '--no-fund',\n packageSpec,\n ],\n {\n stdio: 'pipe',\n },\n )\n\n return { installed: true, packageDir }\n}\n\n/**\n * Find the binary path for an installed package.\n */\nfunction findBinaryPath(\n packageDir: string,\n packageName: string,\n binaryName?: string,\n): string {\n const installedDir = normalizePath(\n path.join(packageDir, 'node_modules', packageName),\n )\n const pkgJsonPath = path.join(installedDir, 'package.json')\n\n // Read package.json to find bin entry.\n const pkgJson = readJsonSync(pkgJsonPath) as Record<string, unknown>\n const bin = pkgJson['bin']\n\n let binPath: string | undefined\n\n if (typeof bin === 'string') {\n // Single binary.\n binPath = bin\n } else if (typeof bin === 'object' && bin !== null) {\n // Multiple binaries - use binaryName or package name.\n const binName = binaryName || packageName.split('/').pop()\n binPath = (bin as Record<string, string>)[binName!]\n }\n\n if (!binPath) {\n throw new Error(`No binary found for package \"${packageName}\"`)\n }\n\n return normalizePath(path.join(installedDir, binPath))\n}\n\n/**\n * Execute a package via DLX - install if needed and run its binary.\n *\n * This is the Socket equivalent of npx/pnpm dlx/yarn dlx, but using\n * our own cache directory (~/.socket/_dlx) and installation logic.\n *\n * Auto-forces reinstall for version ranges to get latest within range.\n */\nexport async function dlxPackage(\n args: readonly string[] | string[],\n options?: DlxPackageOptions | undefined,\n spawnExtra?: SpawnExtra | undefined,\n): Promise<DlxPackageResult> {\n const {\n force: userForce,\n package: packageSpec,\n spawnOptions,\n } = { __proto__: null, ...options } as DlxPackageOptions\n\n // Parse package spec.\n const { name: packageName, version: packageVersion } =\n parsePackageSpec(packageSpec)\n\n // Auto-force for version ranges to get latest within range.\n // User can still override with explicit force: false if they want cache.\n const isVersionRange =\n packageVersion !== undefined && rangeOperatorsRegExp.test(packageVersion)\n const force = userForce !== undefined ? userForce : isVersionRange\n\n // Build full package spec for installation.\n const fullPackageSpec = packageVersion\n ? `${packageName}@${packageVersion}`\n : packageName\n\n // Ensure package is installed.\n const { installed, packageDir } = await ensurePackageInstalled(\n fullPackageSpec,\n packageName,\n force,\n )\n\n // Find binary path.\n const binaryPath = findBinaryPath(packageDir, packageName)\n\n // Make binary executable on Unix systems.\n if (!WIN32 && existsSync(binaryPath)) {\n const { chmodSync } = require('node:fs')\n try {\n chmodSync(binaryPath, 0o755)\n } catch {\n // Ignore chmod errors.\n }\n }\n\n // Execute binary.\n const spawnPromise = spawn(binaryPath, args, spawnOptions, spawnExtra)\n\n return {\n binaryPath,\n installed,\n packageDir,\n spawnPromise,\n }\n}\n"],
|
|
5
|
-
"mappings": ";6iBAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,gBAAAE,IAAA,eAAAC,
|
|
6
|
-
"names": ["dlx_package_exports", "__export", "dlxPackage", "__toCommonJS", "import_node_crypto", "import_node_fs", "import_node_path", "import_platform", "import_fs", "import_path", "import_paths", "import_spawn", "rangeOperatorsRegExp", "generatePackageCacheKey", "packageSpec", "parsePackageSpec", "spec", "parts", "atIndex", "ensurePackageInstalled", "packageName", "force", "cacheKey", "packageDir", "path", "installedDir", "pkgJsonPath", "findBinaryPath", "binaryName", "bin", "binPath", "binName", "args", "options", "spawnExtra", "
|
|
4
|
+
"sourcesContent": ["/**\n * @fileoverview DLX package execution - Install and execute npm packages.\n *\n * This module provides functionality to install and execute npm packages\n * in the ~/.socket/_dlx directory, similar to npx but with Socket's own cache.\n *\n * Uses content-addressed storage like npm's _npx:\n * - Hash is generated from package spec (name@version)\n * - Each unique spec gets its own directory: ~/.socket/_dlx/<hash>/\n * - Allows caching multiple versions of the same package\n *\n * Version range handling:\n * - Exact versions (1.0.0) use cache if available\n * - Range versions (^1.0.0, ~1.0.0) auto-force to get latest within range\n * - User can override with explicit force: false\n *\n * Key difference from dlx-binary.ts:\n * - dlx-binary.ts: Downloads standalone binaries from URLs\n * - dlx-package.ts: Installs npm packages from registries\n *\n * Implementation:\n * - Uses pacote for package installation (no npm CLI required)\n * - Split into downloadPackage() and executePackage() for flexibility\n * - dlxPackage() combines both for convenience\n */\n\nimport { createHash } from 'node:crypto'\nimport { existsSync, promises as fs } from 'node:fs'\nimport path from 'node:path'\n\nimport pacote from './external/pacote'\nimport { WIN32 } from './constants/platform'\nimport { getPacoteCachePath } from './constants/packages'\nimport { readJsonSync } from './fs'\nimport { normalizePath } from './path'\nimport { getSocketDlxDir } from './paths'\nimport type { SpawnExtra, SpawnOptions } from './spawn'\nimport { spawn } from './spawn'\n\n/**\n * Regex to check if a version string contains range operators.\n * Matches any version with range operators: ~, ^, >, <, =, x, X, *, spaces, or ||.\n */\nconst rangeOperatorsRegExp = /[~^><=xX* ]|\\|\\|/\n\nexport interface DownloadPackageResult {\n /** Path to the installed package directory. */\n packageDir: string\n /** Path to the binary. */\n binaryPath: string\n /** Whether the package was newly installed. */\n installed: boolean\n}\n\nexport interface DlxPackageOptions {\n /**\n * Package to install (e.g., '@cyclonedx/cdxgen@10.0.0').\n */\n package: string\n /**\n * Force reinstallation even if package exists.\n */\n force?: boolean | undefined\n /**\n * Additional spawn options for the execution.\n */\n spawnOptions?: SpawnOptions | undefined\n}\n\nexport interface DlxPackageResult {\n /** Path to the installed package directory. */\n packageDir: string\n /** Path to the binary that was executed. */\n binaryPath: string\n /** Whether the package was newly installed. */\n installed: boolean\n /** The spawn promise for the running process. */\n spawnPromise: ReturnType<typeof spawn>\n}\n\n/**\n * Generate a cache key from package spec, similar to npm's _npx.\n * Uses first 16 hex characters of SHA256 hash.\n */\nfunction generatePackageCacheKey(packageSpec: string): string {\n return createHash('sha256').update(packageSpec).digest('hex').slice(0, 16)\n}\n\n/**\n * Parse package spec into name and version.\n * Examples:\n * - 'lodash@4.17.21' \u2192 { name: 'lodash', version: '4.17.21' }\n * - '@scope/pkg@1.0.0' \u2192 { name: '@scope/pkg', version: '1.0.0' }\n * - 'lodash' \u2192 { name: 'lodash', version: undefined }\n */\nfunction parsePackageSpec(spec: string): {\n name: string\n version: string | undefined\n} {\n // Handle scoped packages (@scope/name@version).\n if (spec.startsWith('@')) {\n const parts = spec.split('@')\n if (parts.length === 3) {\n // @scope@version -> Invalid, but handle gracefully.\n return { name: parts[1], version: parts[2] }\n }\n if (parts.length === 2) {\n // @scope/name with no version.\n return { name: `@${parts[1]}`, version: undefined }\n }\n // @scope/name@version.\n const scopeAndName = `@${parts[1]}`\n return { name: scopeAndName, version: parts[2] }\n }\n\n // Handle unscoped packages (name@version).\n const atIndex = spec.lastIndexOf('@')\n if (atIndex === -1) {\n return { name: spec, version: undefined }\n }\n\n return {\n name: spec.slice(0, atIndex),\n version: spec.slice(atIndex + 1),\n }\n}\n\n/**\n * Install package to ~/.socket/_dlx/<hash>/ if not already installed.\n * Uses pacote for installation (no npm CLI required).\n */\nasync function ensurePackageInstalled(\n packageSpec: string,\n packageName: string,\n force: boolean,\n): Promise<{ installed: boolean; packageDir: string }> {\n const cacheKey = generatePackageCacheKey(packageSpec)\n const packageDir = normalizePath(path.join(getSocketDlxDir(), cacheKey))\n const installedDir = normalizePath(\n path.join(packageDir, 'node_modules', packageName),\n )\n\n // Check if already installed (unless force).\n if (!force && existsSync(installedDir)) {\n // Verify package.json exists.\n const pkgJsonPath = path.join(installedDir, 'package.json')\n if (existsSync(pkgJsonPath)) {\n return { installed: false, packageDir }\n }\n }\n\n // Ensure package directory exists.\n await fs.mkdir(packageDir, { recursive: true })\n\n // Use pacote to extract the package.\n // Pacote leverages npm cache when available but doesn't require npm CLI.\n const pacoteCachePath = getPacoteCachePath()\n await pacote.extract(packageSpec, installedDir, {\n // Use consistent pacote cache path (respects npm cache locations when available).\n cache: pacoteCachePath || path.join(packageDir, '.cache'),\n })\n\n return { installed: true, packageDir }\n}\n\n/**\n * Find the binary path for an installed package.\n */\nfunction findBinaryPath(\n packageDir: string,\n packageName: string,\n binaryName?: string,\n): string {\n const installedDir = normalizePath(\n path.join(packageDir, 'node_modules', packageName),\n )\n const pkgJsonPath = path.join(installedDir, 'package.json')\n\n // Read package.json to find bin entry.\n const pkgJson = readJsonSync(pkgJsonPath) as Record<string, unknown>\n const bin = pkgJson['bin']\n\n let binPath: string | undefined\n\n if (typeof bin === 'string') {\n // Single binary.\n binPath = bin\n } else if (typeof bin === 'object' && bin !== null) {\n // Multiple binaries - use binaryName or package name.\n const binName = binaryName || packageName.split('/').pop()\n binPath = (bin as Record<string, string>)[binName!]\n }\n\n if (!binPath) {\n throw new Error(`No binary found for package \"${packageName}\"`)\n }\n\n return normalizePath(path.join(installedDir, binPath))\n}\n\n/**\n * Execute a package via DLX - install if needed and run its binary.\n *\n * This is the Socket equivalent of npx/pnpm dlx/yarn dlx, but using\n * our own cache directory (~/.socket/_dlx) and installation logic.\n *\n * Auto-forces reinstall for version ranges to get latest within range.\n *\n * @example\n * ```typescript\n * // Download and execute cdxgen\n * const result = await dlxPackage(\n * ['--version'],\n * { package: '@cyclonedx/cdxgen@10.0.0' }\n * )\n * await result.spawnPromise\n * ```\n */\nexport async function dlxPackage(\n args: readonly string[] | string[],\n options?: DlxPackageOptions | undefined,\n spawnExtra?: SpawnExtra | undefined,\n): Promise<DlxPackageResult> {\n // Download the package.\n const downloadResult = await downloadPackage(options!)\n\n // Execute the binary.\n const spawnPromise = executePackage(\n downloadResult.binaryPath,\n args,\n options?.spawnOptions,\n spawnExtra,\n )\n\n return {\n ...downloadResult,\n spawnPromise,\n }\n}\n\n/**\n * Download and install a package without executing it.\n * This is useful for self-update or when you need the package files\n * but don't want to run the binary immediately.\n *\n * @example\n * ```typescript\n * // Install @socketsecurity/cli without running it\n * const result = await downloadPackage({\n * package: '@socketsecurity/cli@1.2.0',\n * force: true\n * })\n * console.log('Installed to:', result.packageDir)\n * console.log('Binary at:', result.binaryPath)\n * ```\n */\nexport async function downloadPackage(\n options: DlxPackageOptions,\n): Promise<DownloadPackageResult> {\n const { force: userForce, package: packageSpec } = {\n __proto__: null,\n ...options,\n } as DlxPackageOptions\n\n // Parse package spec.\n const { name: packageName, version: packageVersion } =\n parsePackageSpec(packageSpec)\n\n // Auto-force for version ranges to get latest within range.\n // User can still override with explicit force: false if they want cache.\n const isVersionRange =\n packageVersion !== undefined && rangeOperatorsRegExp.test(packageVersion)\n const force = userForce !== undefined ? userForce : isVersionRange\n\n // Build full package spec for installation.\n const fullPackageSpec = packageVersion\n ? `${packageName}@${packageVersion}`\n : packageName\n\n // Ensure package is installed.\n const { installed, packageDir } = await ensurePackageInstalled(\n fullPackageSpec,\n packageName,\n force,\n )\n\n // Find binary path.\n const binaryPath = findBinaryPath(packageDir, packageName)\n\n // Make binary executable on Unix systems.\n if (!WIN32 && existsSync(binaryPath)) {\n const { chmodSync } = require('node:fs')\n try {\n chmodSync(binaryPath, 0o755)\n } catch {\n // Ignore chmod errors.\n }\n }\n\n return {\n binaryPath,\n installed,\n packageDir,\n }\n}\n\n/**\n * Execute a package's binary.\n * The package must already be installed (use downloadPackage first).\n *\n * @example\n * ```typescript\n * // Execute an already-installed package\n * const downloaded = await downloadPackage({ package: 'cowsay@1.5.0' })\n * const result = await executePackage(\n * downloaded.binaryPath,\n * ['Hello World'],\n * { stdio: 'inherit' }\n * )\n * ```\n */\nexport function executePackage(\n binaryPath: string,\n args: readonly string[] | string[],\n spawnOptions?: SpawnOptions | undefined,\n spawnExtra?: SpawnExtra | undefined,\n): ReturnType<typeof spawn> {\n return spawn(binaryPath, args, spawnOptions, spawnExtra)\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["dlx_package_exports", "__export", "dlxPackage", "downloadPackage", "executePackage", "__toCommonJS", "import_node_crypto", "import_node_fs", "import_node_path", "import_pacote", "import_platform", "import_packages", "import_fs", "import_path", "import_paths", "import_spawn", "rangeOperatorsRegExp", "generatePackageCacheKey", "packageSpec", "parsePackageSpec", "spec", "parts", "atIndex", "ensurePackageInstalled", "packageName", "force", "cacheKey", "packageDir", "path", "installedDir", "pkgJsonPath", "fs", "pacoteCachePath", "pacote", "findBinaryPath", "binaryName", "bin", "binPath", "binName", "args", "options", "spawnExtra", "downloadResult", "spawnPromise", "userForce", "packageVersion", "isVersionRange", "fullPackageSpec", "installed", "binaryPath", "chmodSync", "spawnOptions"]
|
|
7
7
|
}
|
package/dist/dlx.d.ts
CHANGED
|
@@ -38,6 +38,21 @@ export declare function getDlxPackageJsonPath(packageName: string): string;
|
|
|
38
38
|
* Get the node_modules directory for a DLX package installation.
|
|
39
39
|
*/
|
|
40
40
|
export declare function getDlxPackageNodeModulesDir(packageName: string): string;
|
|
41
|
+
/**
|
|
42
|
+
* Check if a file path is within the Socket DLX directory.
|
|
43
|
+
* This is useful for determining if a binary or file is managed by Socket's DLX system.
|
|
44
|
+
*
|
|
45
|
+
* @param filePath - Absolute or relative path to check
|
|
46
|
+
* @returns true if the path is within ~/.socket/_dlx/, false otherwise
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```typescript
|
|
50
|
+
* isInSocketDlx('/home/user/.socket/_dlx/abc123/bin/socket') // true
|
|
51
|
+
* isInSocketDlx('/usr/local/bin/socket') // false
|
|
52
|
+
* isInSocketDlx(process.argv[0]) // Check if current binary is in DLX
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
export declare function isInSocketDlx(filePath: string): boolean;
|
|
41
56
|
/**
|
|
42
57
|
* Check if a package is installed in DLX.
|
|
43
58
|
*/
|
package/dist/dlx.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
/* Socket Lib - Built with esbuild */
|
|
2
|
-
var x=Object.defineProperty;var P=Object.getOwnPropertyDescriptor;var k=Object.getOwnPropertyNames;var v=Object.prototype.hasOwnProperty;var w=(r
|
|
2
|
+
var x=Object.defineProperty;var P=Object.getOwnPropertyDescriptor;var k=Object.getOwnPropertyNames;var v=Object.prototype.hasOwnProperty;var w=(t,r)=>{for(var e in r)x(t,e,{get:r[e],enumerable:!0})},S=(t,r,e,i)=>{if(r&&typeof r=="object"||typeof r=="function")for(let s of k(r))!v.call(t,s)&&s!==e&&x(t,s,{get:()=>r[s],enumerable:!(i=P(r,s))||i.enumerable});return t};var b=t=>S(x({},"__esModule",{value:!0}),t);var z={};w(z,{clearDlx:()=>j,clearDlxSync:()=>E,dlxDirExists:()=>I,dlxDirExistsAsync:()=>q,ensureDlxDir:()=>A,ensureDlxDirSync:()=>F,getDlxInstalledPackageDir:()=>l,getDlxPackageDir:()=>p,getDlxPackageJsonPath:()=>L,getDlxPackageNodeModulesDir:()=>D,isDlxPackageInstalled:()=>_,isDlxPackageInstalledAsync:()=>$,isInSocketDlx:()=>X,listDlxPackages:()=>d,listDlxPackagesAsync:()=>m,removeDlxPackage:()=>h,removeDlxPackageSync:()=>y});module.exports=b(z);var o=require("node:fs"),u=require("./fs"),a=require("./path"),n=require("./paths"),g=require("./promises");let f;function c(){return f===void 0&&(f=require("node:path")),f}async function j(){const t=await m();await(0,g.pEach)(t,r=>h(r))}function E(){const t=d();for(const r of t)y(r)}function I(){return(0,o.existsSync)((0,n.getSocketDlxDir)())}async function q(){try{return await o.promises.access((0,n.getSocketDlxDir)()),!0}catch{return!1}}async function A(){await o.promises.mkdir((0,n.getSocketDlxDir)(),{recursive:!0})}function F(){const{mkdirSync:t}=require("node:fs");t((0,n.getSocketDlxDir)(),{recursive:!0})}function l(t){return(0,a.normalizePath)(c().join(D(t),t))}function p(t){return(0,a.normalizePath)(c().join((0,n.getSocketDlxDir)(),t))}function L(t){return(0,a.normalizePath)(c().join(l(t),"package.json"))}function D(t){return(0,a.normalizePath)(c().join(p(t),"node_modules"))}function X(t){if(!t)return!1;const r=c(),e=(0,n.getSocketDlxDir)();return r.resolve(t).startsWith(e+r.sep)}function _(t){return(0,o.existsSync)(l(t))}async function $(t){try{return await o.promises.access(l(t)),!0}catch{return!1}}function d(){try{return(0,u.readDirNamesSync)((0,n.getSocketDlxDir)(),{sort:!0})}catch{return[]}}async function m(){try{return(await o.promises.readdir((0,n.getSocketDlxDir)(),{withFileTypes:!0})).filter(r=>r.isDirectory()).map(r=>r.name).sort()}catch{return[]}}async function h(t){const r=p(t);try{await(0,u.safeDelete)(r,{recursive:!0,force:!0})}catch(e){throw new Error(`Failed to remove DLX package "${t}"`,{cause:e})}}function y(t){const{rmSync:r}=require("node:fs"),e=p(t);try{r(e,{recursive:!0,force:!0})}catch(i){throw new Error(`Failed to remove DLX package "${t}"`,{cause:i})}}0&&(module.exports={clearDlx,clearDlxSync,dlxDirExists,dlxDirExistsAsync,ensureDlxDir,ensureDlxDirSync,getDlxInstalledPackageDir,getDlxPackageDir,getDlxPackageJsonPath,getDlxPackageNodeModulesDir,isDlxPackageInstalled,isDlxPackageInstalledAsync,isInSocketDlx,listDlxPackages,listDlxPackagesAsync,removeDlxPackage,removeDlxPackageSync});
|
|
3
3
|
//# sourceMappingURL=dlx.js.map
|
package/dist/dlx.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/dlx.ts"],
|
|
4
|
-
"sourcesContent": ["/** @fileoverview DLX (execute package) utilities for Socket ecosystem shared installations. */\n\nimport { existsSync, promises as fs } from 'node:fs'\n\nimport { readDirNamesSync, safeDelete } from './fs'\nimport { normalizePath } from './path'\nimport { getSocketDlxDir } from './paths'\nimport { pEach } from './promises'\n\nlet _path: typeof import('path') | undefined\n/**\n * Lazily load the path module to avoid Webpack errors.\n * @private\n */\n/*@__NO_SIDE_EFFECTS__*/\nfunction getPath() {\n if (_path === undefined) {\n // Use non-'node:' prefixed require to avoid Webpack errors.\n\n _path = /*@__PURE__*/ require('node:path')\n }\n return _path!\n}\n\n/**\n * Clear all DLX package installations.\n */\nexport async function clearDlx(): Promise<void> {\n const packages = await listDlxPackagesAsync()\n await pEach(packages, pkg => removeDlxPackage(pkg))\n}\n\n/**\n * Clear all DLX package installations synchronously.\n */\nexport function clearDlxSync(): void {\n const packages = listDlxPackages()\n for (const pkg of packages) {\n removeDlxPackageSync(pkg)\n }\n}\n\n/**\n * Check if the DLX directory exists.\n */\nexport function dlxDirExists(): boolean {\n return existsSync(getSocketDlxDir())\n}\n\n/**\n * Check if the DLX directory exists asynchronously.\n */\nexport async function dlxDirExistsAsync(): Promise<boolean> {\n try {\n await fs.access(getSocketDlxDir())\n return true\n } catch {\n return false\n }\n}\n\n/**\n * Ensure the DLX directory exists, creating it if necessary.\n */\nexport async function ensureDlxDir(): Promise<void> {\n await fs.mkdir(getSocketDlxDir(), { recursive: true })\n}\n\n/**\n * Ensure the DLX directory exists synchronously, creating it if necessary.\n */\nexport function ensureDlxDirSync(): void {\n const { mkdirSync } = require('node:fs')\n mkdirSync(getSocketDlxDir(), { recursive: true })\n}\n\n/**\n * Get the installed package directory within DLX node_modules.\n */\nexport function getDlxInstalledPackageDir(packageName: string): string {\n const path = getPath()\n return normalizePath(\n path.join(getDlxPackageNodeModulesDir(packageName), packageName),\n )\n}\n\n/**\n * Get the DLX installation directory for a specific package.\n */\nexport function getDlxPackageDir(packageName: string): string {\n const path = getPath()\n return normalizePath(path.join(getSocketDlxDir(), packageName))\n}\n\n/**\n * Get the package.json path for a DLX installed package.\n */\nexport function getDlxPackageJsonPath(packageName: string): string {\n const path = getPath()\n return normalizePath(\n path.join(getDlxInstalledPackageDir(packageName), 'package.json'),\n )\n}\n\n/**\n * Get the node_modules directory for a DLX package installation.\n */\nexport function getDlxPackageNodeModulesDir(packageName: string): string {\n const path = getPath()\n return normalizePath(path.join(getDlxPackageDir(packageName), 'node_modules'))\n}\n\n/**\n * Check if a package is installed in DLX.\n */\nexport function isDlxPackageInstalled(packageName: string): boolean {\n return existsSync(getDlxInstalledPackageDir(packageName))\n}\n\n/**\n * Check if a package is installed in DLX asynchronously.\n */\nexport async function isDlxPackageInstalledAsync(\n packageName: string,\n): Promise<boolean> {\n try {\n await fs.access(getDlxInstalledPackageDir(packageName))\n return true\n } catch {\n return false\n }\n}\n\n/**\n * List all packages installed in DLX.\n */\nexport function listDlxPackages(): string[] {\n try {\n return readDirNamesSync(getSocketDlxDir(), { sort: true })\n } catch {\n return []\n }\n}\n\n/**\n * List all packages installed in DLX asynchronously.\n */\nexport async function listDlxPackagesAsync(): Promise<string[]> {\n try {\n const entries = await fs.readdir(getSocketDlxDir(), {\n withFileTypes: true,\n })\n return entries\n .filter(e => e.isDirectory())\n .map(e => e.name)\n .sort()\n } catch {\n return []\n }\n}\n\n/**\n * Remove a DLX package installation.\n */\nexport async function removeDlxPackage(packageName: string): Promise<void> {\n const packageDir = getDlxPackageDir(packageName)\n try {\n await safeDelete(packageDir, { recursive: true, force: true })\n } catch (e) {\n throw new Error(`Failed to remove DLX package \"${packageName}\"`, {\n cause: e,\n })\n }\n}\n\n/**\n * Remove a DLX package installation synchronously.\n */\nexport function removeDlxPackageSync(packageName: string): void {\n const { rmSync } = require('node:fs')\n const packageDir = getDlxPackageDir(packageName)\n try {\n rmSync(packageDir, { recursive: true, force: true })\n } catch (e) {\n throw new Error(`Failed to remove DLX package \"${packageName}\"`, {\n cause: e,\n })\n }\n}\n"],
|
|
5
|
-
"mappings": ";4ZAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,cAAAE,EAAA,iBAAAC,EAAA,iBAAAC,EAAA,sBAAAC,EAAA,iBAAAC,EAAA,qBAAAC,EAAA,8BAAAC,EAAA,qBAAAC,EAAA,0BAAAC,EAAA,gCAAAC,EAAA,0BAAAC,EAAA,+BAAAC,EAAA,oBAAAC,EAAA,yBAAAC,EAAA,qBAAAC,EAAA,yBAAAC,IAAA,eAAAC,
|
|
6
|
-
"names": ["dlx_exports", "__export", "clearDlx", "clearDlxSync", "dlxDirExists", "dlxDirExistsAsync", "ensureDlxDir", "ensureDlxDirSync", "getDlxInstalledPackageDir", "getDlxPackageDir", "getDlxPackageJsonPath", "getDlxPackageNodeModulesDir", "isDlxPackageInstalled", "isDlxPackageInstalledAsync", "listDlxPackages", "listDlxPackagesAsync", "removeDlxPackage", "removeDlxPackageSync", "__toCommonJS", "import_node_fs", "import_fs", "import_path", "import_paths", "import_promises", "_path", "getPath", "packages", "pkg", "fs", "mkdirSync", "packageName", "e", "packageDir", "rmSync"]
|
|
4
|
+
"sourcesContent": ["/** @fileoverview DLX (execute package) utilities for Socket ecosystem shared installations. */\n\nimport { existsSync, promises as fs } from 'node:fs'\n\nimport { readDirNamesSync, safeDelete } from './fs'\nimport { normalizePath } from './path'\nimport { getSocketDlxDir } from './paths'\nimport { pEach } from './promises'\n\nlet _path: typeof import('path') | undefined\n/**\n * Lazily load the path module to avoid Webpack errors.\n * @private\n */\n/*@__NO_SIDE_EFFECTS__*/\nfunction getPath() {\n if (_path === undefined) {\n // Use non-'node:' prefixed require to avoid Webpack errors.\n\n _path = /*@__PURE__*/ require('node:path')\n }\n return _path!\n}\n\n/**\n * Clear all DLX package installations.\n */\nexport async function clearDlx(): Promise<void> {\n const packages = await listDlxPackagesAsync()\n await pEach(packages, pkg => removeDlxPackage(pkg))\n}\n\n/**\n * Clear all DLX package installations synchronously.\n */\nexport function clearDlxSync(): void {\n const packages = listDlxPackages()\n for (const pkg of packages) {\n removeDlxPackageSync(pkg)\n }\n}\n\n/**\n * Check if the DLX directory exists.\n */\nexport function dlxDirExists(): boolean {\n return existsSync(getSocketDlxDir())\n}\n\n/**\n * Check if the DLX directory exists asynchronously.\n */\nexport async function dlxDirExistsAsync(): Promise<boolean> {\n try {\n await fs.access(getSocketDlxDir())\n return true\n } catch {\n return false\n }\n}\n\n/**\n * Ensure the DLX directory exists, creating it if necessary.\n */\nexport async function ensureDlxDir(): Promise<void> {\n await fs.mkdir(getSocketDlxDir(), { recursive: true })\n}\n\n/**\n * Ensure the DLX directory exists synchronously, creating it if necessary.\n */\nexport function ensureDlxDirSync(): void {\n const { mkdirSync } = require('node:fs')\n mkdirSync(getSocketDlxDir(), { recursive: true })\n}\n\n/**\n * Get the installed package directory within DLX node_modules.\n */\nexport function getDlxInstalledPackageDir(packageName: string): string {\n const path = getPath()\n return normalizePath(\n path.join(getDlxPackageNodeModulesDir(packageName), packageName),\n )\n}\n\n/**\n * Get the DLX installation directory for a specific package.\n */\nexport function getDlxPackageDir(packageName: string): string {\n const path = getPath()\n return normalizePath(path.join(getSocketDlxDir(), packageName))\n}\n\n/**\n * Get the package.json path for a DLX installed package.\n */\nexport function getDlxPackageJsonPath(packageName: string): string {\n const path = getPath()\n return normalizePath(\n path.join(getDlxInstalledPackageDir(packageName), 'package.json'),\n )\n}\n\n/**\n * Get the node_modules directory for a DLX package installation.\n */\nexport function getDlxPackageNodeModulesDir(packageName: string): string {\n const path = getPath()\n return normalizePath(path.join(getDlxPackageDir(packageName), 'node_modules'))\n}\n\n/**\n * Check if a file path is within the Socket DLX directory.\n * This is useful for determining if a binary or file is managed by Socket's DLX system.\n *\n * @param filePath - Absolute or relative path to check\n * @returns true if the path is within ~/.socket/_dlx/, false otherwise\n *\n * @example\n * ```typescript\n * isInSocketDlx('/home/user/.socket/_dlx/abc123/bin/socket') // true\n * isInSocketDlx('/usr/local/bin/socket') // false\n * isInSocketDlx(process.argv[0]) // Check if current binary is in DLX\n * ```\n */\nexport function isInSocketDlx(filePath: string): boolean {\n if (!filePath) {\n return false\n }\n\n const path = getPath()\n const dlxDir = getSocketDlxDir()\n const absolutePath = path.resolve(filePath)\n\n // Check if the absolute path starts with the DLX directory.\n return absolutePath.startsWith(dlxDir + path.sep)\n}\n\n/**\n * Check if a package is installed in DLX.\n */\nexport function isDlxPackageInstalled(packageName: string): boolean {\n return existsSync(getDlxInstalledPackageDir(packageName))\n}\n\n/**\n * Check if a package is installed in DLX asynchronously.\n */\nexport async function isDlxPackageInstalledAsync(\n packageName: string,\n): Promise<boolean> {\n try {\n await fs.access(getDlxInstalledPackageDir(packageName))\n return true\n } catch {\n return false\n }\n}\n\n/**\n * List all packages installed in DLX.\n */\nexport function listDlxPackages(): string[] {\n try {\n return readDirNamesSync(getSocketDlxDir(), { sort: true })\n } catch {\n return []\n }\n}\n\n/**\n * List all packages installed in DLX asynchronously.\n */\nexport async function listDlxPackagesAsync(): Promise<string[]> {\n try {\n const entries = await fs.readdir(getSocketDlxDir(), {\n withFileTypes: true,\n })\n return entries\n .filter(e => e.isDirectory())\n .map(e => e.name)\n .sort()\n } catch {\n return []\n }\n}\n\n/**\n * Remove a DLX package installation.\n */\nexport async function removeDlxPackage(packageName: string): Promise<void> {\n const packageDir = getDlxPackageDir(packageName)\n try {\n await safeDelete(packageDir, { recursive: true, force: true })\n } catch (e) {\n throw new Error(`Failed to remove DLX package \"${packageName}\"`, {\n cause: e,\n })\n }\n}\n\n/**\n * Remove a DLX package installation synchronously.\n */\nexport function removeDlxPackageSync(packageName: string): void {\n const { rmSync } = require('node:fs')\n const packageDir = getDlxPackageDir(packageName)\n try {\n rmSync(packageDir, { recursive: true, force: true })\n } catch (e) {\n throw new Error(`Failed to remove DLX package \"${packageName}\"`, {\n cause: e,\n })\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["dlx_exports", "__export", "clearDlx", "clearDlxSync", "dlxDirExists", "dlxDirExistsAsync", "ensureDlxDir", "ensureDlxDirSync", "getDlxInstalledPackageDir", "getDlxPackageDir", "getDlxPackageJsonPath", "getDlxPackageNodeModulesDir", "isDlxPackageInstalled", "isDlxPackageInstalledAsync", "isInSocketDlx", "listDlxPackages", "listDlxPackagesAsync", "removeDlxPackage", "removeDlxPackageSync", "__toCommonJS", "import_node_fs", "import_fs", "import_path", "import_paths", "import_promises", "_path", "getPath", "packages", "pkg", "fs", "mkdirSync", "packageName", "filePath", "path", "dlxDir", "e", "packageDir", "rmSync"]
|
|
7
7
|
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Package manager type detected from environment.
|
|
3
|
+
*/
|
|
4
|
+
export type PackageManagerType = 'npm' | 'pnpm' | 'yarn' | 'bun' | null;
|
|
5
|
+
/**
|
|
6
|
+
* Detect which package manager is currently running based on environment variables.
|
|
7
|
+
* Checks npm_config_user_agent which all package managers set.
|
|
8
|
+
*
|
|
9
|
+
* Detection priority:
|
|
10
|
+
* 1. npm_config_user_agent (most reliable, set by all package managers)
|
|
11
|
+
* 2. Binary path analysis (fallback for non-standard environments)
|
|
12
|
+
*
|
|
13
|
+
* @returns The detected package manager or null if unable to determine
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* // During: npm install
|
|
18
|
+
* detectPackageManager() // 'npm'
|
|
19
|
+
*
|
|
20
|
+
* // During: pnpm install
|
|
21
|
+
* detectPackageManager() // 'pnpm'
|
|
22
|
+
*
|
|
23
|
+
* // During: yarn install
|
|
24
|
+
* detectPackageManager() // 'yarn'
|
|
25
|
+
*
|
|
26
|
+
* // Outside package manager context
|
|
27
|
+
* detectPackageManager() // null
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export declare function detectPackageManager(): PackageManagerType;
|
|
31
|
+
/**
|
|
32
|
+
* Get the package manager name and version from user agent.
|
|
33
|
+
*
|
|
34
|
+
* @returns Object with name and version, or null if not available
|
|
35
|
+
* @example
|
|
36
|
+
* ```typescript
|
|
37
|
+
* getPackageManagerInfo()
|
|
38
|
+
* // { name: 'pnpm', version: '8.15.1' }
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export declare function getPackageManagerInfo(): {
|
|
42
|
+
name: string;
|
|
43
|
+
version: string;
|
|
44
|
+
} | null;
|
|
45
|
+
/**
|
|
46
|
+
* Get the package manager user agent from environment.
|
|
47
|
+
* Package managers set npm_config_user_agent with format: "npm/8.19.2 node/v18.12.0 darwin arm64"
|
|
48
|
+
*
|
|
49
|
+
* @returns The user agent string or undefined
|
|
50
|
+
* @example
|
|
51
|
+
* ```typescript
|
|
52
|
+
* getPackageManagerUserAgent()
|
|
53
|
+
* // npm: "npm/10.2.4 node/v20.11.0 darwin arm64 workspaces/false"
|
|
54
|
+
* // pnpm: "pnpm/8.15.1 npm/? node/v20.11.0 darwin arm64"
|
|
55
|
+
* // yarn: "yarn/1.22.19 npm/? node/v20.11.0 darwin arm64"
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export declare function getPackageManagerUserAgent(): string | undefined;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
/* Socket Lib - Built with esbuild */
|
|
2
|
+
var t=Object.defineProperty;var s=Object.getOwnPropertyDescriptor;var g=Object.getOwnPropertyNames;var p=Object.prototype.hasOwnProperty;var l=(e,n)=>{for(var r in n)t(e,r,{get:n[r],enumerable:!0})},o=(e,n,r,c)=>{if(n&&typeof n=="object"||typeof n=="function")for(let a of g(n))!p.call(e,a)&&a!==r&&t(e,a,{get:()=>n[a],enumerable:!(c=s(n,a))||c.enumerable});return e};var m=e=>o(t({},"__esModule",{value:!0}),e);var y={};l(y,{detectPackageManager:()=>d,getPackageManagerInfo:()=>f,getPackageManagerUserAgent:()=>u});module.exports=m(y);var i=require("#env/rewire");function d(){const e=u();if(e){const r=e.match(/^(npm|pnpm|yarn|bun)\//);if(r)return r[1]}const n=process.argv[0];if(n){if(n.includes("/pnpm/")||n.includes("\\pnpm\\"))return"pnpm";if(n.includes("/yarn/")||n.includes("\\yarn\\")||n.includes("/.yarn/")||n.includes("\\.yarn\\"))return"yarn";if(n.includes("/bun/")||n.includes("\\bun\\"))return"bun";if(n.includes("/node_modules/")||n.includes("\\node_modules\\"))return"npm"}return null}function f(){const e=u();if(!e)return null;const n=e.match(/^([^/]+)\/([^\s]+)/);return n?{name:n[1],version:n[2]}:null}function u(){return(0,i.getEnvValue)("npm_config_user_agent")}0&&(module.exports={detectPackageManager,getPackageManagerInfo,getPackageManagerUserAgent});
|
|
3
|
+
//# sourceMappingURL=package-manager.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/env/package-manager.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * @fileoverview Package manager environment detection.\n * Provides utilities to detect which package manager (npm/pnpm/yarn/bun) is running.\n */\n\nimport { getEnvValue } from '#env/rewire'\n\n/**\n * Package manager type detected from environment.\n */\nexport type PackageManagerType = 'npm' | 'pnpm' | 'yarn' | 'bun' | null\n\n/**\n * Detect which package manager is currently running based on environment variables.\n * Checks npm_config_user_agent which all package managers set.\n *\n * Detection priority:\n * 1. npm_config_user_agent (most reliable, set by all package managers)\n * 2. Binary path analysis (fallback for non-standard environments)\n *\n * @returns The detected package manager or null if unable to determine\n *\n * @example\n * ```typescript\n * // During: npm install\n * detectPackageManager() // 'npm'\n *\n * // During: pnpm install\n * detectPackageManager() // 'pnpm'\n *\n * // During: yarn install\n * detectPackageManager() // 'yarn'\n *\n * // Outside package manager context\n * detectPackageManager() // null\n * ```\n */\nexport function detectPackageManager(): PackageManagerType {\n const userAgent = getPackageManagerUserAgent()\n\n if (userAgent) {\n // User agent format: \"pnpm/8.15.1 npm/? node/v20.11.0 darwin arm64\"\n // Extract the first part before the slash.\n const match = userAgent.match(/^(npm|pnpm|yarn|bun)\\//)\n if (match) {\n return match[1] as PackageManagerType\n }\n }\n\n // Fallback: Check binary path patterns.\n const argv0 = process.argv[0]\n if (argv0) {\n if (argv0.includes('/pnpm/') || argv0.includes('\\\\pnpm\\\\')) {\n return 'pnpm'\n }\n if (\n argv0.includes('/yarn/') ||\n argv0.includes('\\\\yarn\\\\') ||\n argv0.includes('/.yarn/') ||\n argv0.includes('\\\\.yarn\\\\')\n ) {\n return 'yarn'\n }\n if (argv0.includes('/bun/') || argv0.includes('\\\\bun\\\\')) {\n return 'bun'\n }\n // If in node_modules but no other match, assume npm.\n if (\n argv0.includes('/node_modules/') ||\n argv0.includes('\\\\node_modules\\\\')\n ) {\n return 'npm'\n }\n }\n\n return null\n}\n\n/**\n * Get the package manager name and version from user agent.\n *\n * @returns Object with name and version, or null if not available\n * @example\n * ```typescript\n * getPackageManagerInfo()\n * // { name: 'pnpm', version: '8.15.1' }\n * ```\n */\nexport function getPackageManagerInfo(): {\n name: string\n version: string\n} | null {\n const userAgent = getPackageManagerUserAgent()\n if (!userAgent) {\n return null\n }\n\n // Parse \"pnpm/8.15.1 npm/? node/v20.11.0 darwin arm64\".\n const match = userAgent.match(/^([^/]+)\\/([^\\s]+)/)\n if (match) {\n return {\n name: match[1],\n version: match[2],\n }\n }\n\n return null\n}\n\n/**\n * Get the package manager user agent from environment.\n * Package managers set npm_config_user_agent with format: \"npm/8.19.2 node/v18.12.0 darwin arm64\"\n *\n * @returns The user agent string or undefined\n * @example\n * ```typescript\n * getPackageManagerUserAgent()\n * // npm: \"npm/10.2.4 node/v20.11.0 darwin arm64 workspaces/false\"\n * // pnpm: \"pnpm/8.15.1 npm/? node/v20.11.0 darwin arm64\"\n * // yarn: \"yarn/1.22.19 npm/? node/v20.11.0 darwin arm64\"\n * ```\n */\nexport function getPackageManagerUserAgent(): string | undefined {\n return getEnvValue('npm_config_user_agent')\n}\n"],
|
|
5
|
+
"mappings": ";4ZAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,0BAAAE,EAAA,0BAAAC,EAAA,+BAAAC,IAAA,eAAAC,EAAAL,GAKA,IAAAM,EAA4B,uBAgCrB,SAASJ,GAA2C,CACzD,MAAMK,EAAYH,EAA2B,EAE7C,GAAIG,EAAW,CAGb,MAAMC,EAAQD,EAAU,MAAM,wBAAwB,EACtD,GAAIC,EACF,OAAOA,EAAM,CAAC,CAElB,CAGA,MAAMC,EAAQ,QAAQ,KAAK,CAAC,EAC5B,GAAIA,EAAO,CACT,GAAIA,EAAM,SAAS,QAAQ,GAAKA,EAAM,SAAS,UAAU,EACvD,MAAO,OAET,GACEA,EAAM,SAAS,QAAQ,GACvBA,EAAM,SAAS,UAAU,GACzBA,EAAM,SAAS,SAAS,GACxBA,EAAM,SAAS,WAAW,EAE1B,MAAO,OAET,GAAIA,EAAM,SAAS,OAAO,GAAKA,EAAM,SAAS,SAAS,EACrD,MAAO,MAGT,GACEA,EAAM,SAAS,gBAAgB,GAC/BA,EAAM,SAAS,kBAAkB,EAEjC,MAAO,KAEX,CAEA,OAAO,IACT,CAYO,SAASN,GAGP,CACP,MAAMI,EAAYH,EAA2B,EAC7C,GAAI,CAACG,EACH,OAAO,KAIT,MAAMC,EAAQD,EAAU,MAAM,oBAAoB,EAClD,OAAIC,EACK,CACL,KAAMA,EAAM,CAAC,EACb,QAASA,EAAM,CAAC,CAClB,EAGK,IACT,CAeO,SAASJ,GAAiD,CAC/D,SAAO,eAAY,uBAAuB,CAC5C",
|
|
6
|
+
"names": ["package_manager_exports", "__export", "detectPackageManager", "getPackageManagerInfo", "getPackageManagerUserAgent", "__toCommonJS", "import_rewire", "userAgent", "match", "argv0"]
|
|
7
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@socketsecurity/lib",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Core utilities and infrastructure for Socket.dev security tools",
|
|
6
6
|
"keywords": [
|
|
@@ -212,6 +212,10 @@
|
|
|
212
212
|
"types": "./dist/env/npm.d.ts",
|
|
213
213
|
"default": "./dist/env/npm.js"
|
|
214
214
|
},
|
|
215
|
+
"./env/package-manager": {
|
|
216
|
+
"types": "./dist/env/package-manager.d.ts",
|
|
217
|
+
"default": "./dist/env/package-manager.js"
|
|
218
|
+
},
|
|
215
219
|
"./env/path": {
|
|
216
220
|
"types": "./dist/env/path.d.ts",
|
|
217
221
|
"default": "./dist/env/path.js"
|