Skip to content

Commit c0b991a

Browse files
committed
refactor(dlx): use getSocketCacacheDir instead of getPacoteCachePath
- Replace getPacoteCachePath() with getSocketCacacheDir() in dlx/package.ts - Ensure consistent use of Socket's cacache directory (~/.socket/_cacache) - Fix getPacoteCachePath() to preserve empty string when cache path is empty - Remove pacote dependency from dlx/package.ts (already using Arborist)
1 parent 532b7a5 commit c0b991a

2 files changed

Lines changed: 14 additions & 22 deletions

File tree

src/constants/packages.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ export function getPacoteCachePath(): string {
9393
const cachePath = PacoteFetcherBase
9494
? new PacoteFetcherBase(/*dummy package spec*/ 'x', {}).cache
9595
: ''
96-
_pacoteCachePath = normalizePath(cachePath)
96+
_pacoteCachePath = cachePath ? normalizePath(cachePath) : ''
9797
} catch {
9898
_pacoteCachePath = ''
9999
}

src/dlx/package.ts

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -25,21 +25,19 @@
2525
* - dlx-package.ts: Installs npm packages from registries
2626
*
2727
* Implementation:
28-
* - Uses pacote for package installation (no npm CLI required)
28+
* - Uses Arborist for package installation (like npx, no npm CLI required)
2929
* - Split into downloadPackage() and executePackage() for flexibility
3030
* - dlxPackage() combines both for convenience
3131
*/
3232

3333
import { WIN32 } from '../constants/platform'
34-
import { getPacoteCachePath } from '../constants/packages'
3534
import { generateCacheKey } from './cache'
3635
import Arborist from '../external/@npmcli/arborist'
3736
import libnpmexec from '../external/libnpmexec'
3837
import npmPackageArg from '../external/npm-package-arg'
39-
import pacote from '../external/pacote'
4038
import { readJsonSync, safeMkdir } from '../fs'
4139
import { normalizePath } from '../paths/normalize'
42-
import { getSocketDlxDir } from '../paths/socket'
40+
import { getSocketCacacheDir, getSocketDlxDir } from '../paths/socket'
4341
import { processLock } from '../process-lock'
4442
import type { SpawnExtra, SpawnOptions } from '../spawn'
4543
import { spawn } from '../spawn'
@@ -261,24 +259,16 @@ async function ensurePackageInstalled(
261259
}
262260
}
263261

264-
// Use pacote to extract the package.
265-
// Pacote leverages npm cache when available but doesn't require npm CLI.
266-
const pacoteCachePath = getPacoteCachePath()
262+
// Install package and dependencies using Arborist (like npx does).
263+
// Arborist handles everything: fetching, extracting, dependency resolution, and bin links.
264+
// This creates the proper flat node_modules structure with .bin symlinks.
267265
try {
268-
/* c8 ignore next 4 - External pacote call */
269-
await pacote.extract(packageSpec, installedDir, {
270-
// Use consistent pacote cache path (respects npm cache locations when available).
271-
cache: pacoteCachePath || path.join(packageDir, '.cache'),
272-
})
273-
274-
// Install dependencies using Arborist.
275-
// pacote.extract() only extracts the package tarball, it does NOT install dependencies.
276-
// We must use Arborist to install dependencies after extraction.
277266
// Arborist is imported at the top
278267
/* c8 ignore next 3 - External Arborist constructor */
279268
const arb = new Arborist({
280-
path: installedDir,
281-
cache: pacoteCachePath || path.join(packageDir, '.cache'),
269+
path: packageDir,
270+
// Use Socket's shared cacache directory (~/.socket/_cacache).
271+
cache: getSocketCacacheDir(),
282272
// Skip devDependencies (production-only like npx).
283273
omit: ['dev'],
284274
// Security: Skip install/preinstall/postinstall scripts to prevent arbitrary code execution.
@@ -293,9 +283,11 @@ async function ensurePackageInstalled(
293283
silent: true,
294284
})
295285

296-
/* c8 ignore next 2 - External Arborist calls */
297-
await arb.buildIdealTree()
298-
await arb.reify({ save: false })
286+
// Use reify with 'add' to install the package and its dependencies in one step.
287+
// This matches npx's approach: arb.reify({ add: [packageSpec] })
288+
// save: true creates package.json and package-lock.json at the root (like npx).
289+
/* c8 ignore next - External Arborist call */
290+
await arb.reify({ save: true, add: [packageSpec] })
299291
} catch (e) {
300292
const code = (e as any).code
301293
if (code === 'E404' || code === 'ETARGET') {

0 commit comments

Comments
 (0)