🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

pacote

Package Overview
Dependencies
Maintainers
4
Versions
238
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

pacote - npm Package Compare versions

Comparing version
21.5.1
to
22.0.0
+60
-5
lib/dir.js

@@ -1,2 +0,4 @@

const { resolve } = require('node:path')
const { resolve, join } = require('node:path')
const { mkdtemp, writeFile, rm } = require('node:fs/promises')
const { tmpdir } = require('node:os')
const packlist = require('npm-packlist')

@@ -6,2 +8,3 @@ const runScript = require('@npmcli/run-script')

const { Minipass } = require('minipass')
const PackageJson = require('@npmcli/package-json')
const Fetcher = require('./fetcher.js')

@@ -70,3 +73,3 @@ const FileFetcher = require('./file.js')

const { prefix, workspaces } = this.opts
const { prefix, workspaces, globalIgnoreFile } = this.opts

@@ -81,6 +84,12 @@ // run the prepare script, get the list of files, and tar it up

}
return packlist(this.tree, { path: this.resolved, prefix, workspaces })
return packlist(this.tree, { path: this.resolved, prefix, workspaces, globalIgnoreFile })
})
.then(files => tar.c(tarCreateOptions(this.package), files)
.on('error', er => stream.emit('error', er)).pipe(stream))
.then(async files => {
const { options, cleanup } = await this.#tarOptions()
const source = tar.c(options, files)
// the strip temp file must outlive content consumption, so clean up once the stream is done
source.once('end', cleanup)
source.once('error', cleanup)
return source.on('error', er => stream.emit('error', er)).pipe(stream)
})
.catch(er => stream.emit('error', er))

@@ -90,2 +99,48 @@ return stream

// Build the tar create options.
// When the packed package.json declares patchedDependencies, redirect it to a stripped copy so project-local patches never ship.
// Non-patched packs are unchanged.
async #tarOptions () {
const options = tarCreateOptions(this.package)
// read package.json from disk after prepare so the strip reflects the actually-packed manifest.
const pkgJson = await PackageJson.load(this.resolved)
if (!('patchedDependencies' in pkgJson.content)) {
return { options, cleanup: () => {} }
}
// serialize the package.json minus patchedDependencies, preserving its indent and newline.
// JSON.stringify ignores the indent and newline symbols @npmcli/package-json attaches to content.
delete pkgJson.content.patchedDependencies
const { content } = pkgJson
const indent = content[Symbol.for('indent')]
const newline = content[Symbol.for('newline')]
const stripped = `${JSON.stringify(content, null, indent)}\n`.replace(/\n/g, newline)
// write the stripped copy to a temp dir, removing it if the write itself fails.
const dir = await mkdtemp(join(tmpdir(), 'pacote-pack-'))
const strippedPath = join(dir, 'package.json')
try {
await writeFile(strippedPath, stripped)
} catch (er) {
/* istanbul ignore next - writing to a freshly created temp dir is not deterministically failable */
await rm(dir, { recursive: true, force: true })
/* istanbul ignore next */
throw er
}
const size = Buffer.byteLength(stripped)
// point only the top-level package.json entry at the stripped copy; every other file is untouched.
// onWriteEntry runs before the tar header and the file's hardlink check, so size and nlink here are honored.
options.onWriteEntry = (entry) => {
if (entry.path === 'package.json') {
entry.absolute = strippedPath
entry.stat.size = size
entry.stat.nlink = 1
}
}
return { options, cleanup: () => rm(dir, { recursive: true, force: true }) }
}
manifest () {

@@ -92,0 +147,0 @@ if (this.package) {

@@ -121,2 +121,6 @@ // This is the base class that the other fetcher types in lib

'--no-dry-run',
// override npm_config_global from the parent process: this inner
// `npm install` is preparing deps inside a tmp git clone, and it
// must reify into that clone's cwd, never the outer global prefix.
'--global=false',
]

@@ -123,0 +127,0 @@ }

+11
-3

@@ -22,3 +22,3 @@ const cacache = require('cacache')

const repoUrl = (h, opts) =>
h.sshurl && !(h.https && h.auth) && addGitPlus(h.sshurl(opts)) ||
h.sshurl && !(h.https && (h.auth || h.default === 'https')) && addGitPlus(h.sshurl(opts)) ||
h.https && addGitPlus(h.https(opts))

@@ -175,2 +175,7 @@

// honor ignoreScripts: spawning `npm install` here would run lifecycle scripts (install, preinstall, postinstall, prepare) from the cloned repo, defeating the caller's explicit opt-out.
if (this.opts.ignoreScripts) {
return
}
// to avoid cases where we have an cycle of git deps that depend

@@ -259,4 +264,7 @@ // on one another, we only ever do preparation for one instance

}).extract(tmp).then(() => handler(`${tmp}${this.spec.gitSubdir || ''}`), er => {
// fall back to ssh download if tarball fails
if (er.constructor.name.match(/^Http/)) {
// fall back to clone if the tarball download fails due to an
// HTTP error or if the response is not a valid tarball (e.g.
// a hosted provider returning an HTML sign-in page with 200)
if ((typeof er.statusCode === 'number' && er.statusCode >= 400) ||
/^TAR_/.test(er.code)) {
return this.#clone(handler, false)

@@ -263,0 +271,0 @@ } else {

@@ -6,3 +6,3 @@ // add a sha to a git remote url spec

const opt = { noCommittish: true }
const base = h.https && h.auth ? h.https(opt) : h.shortcut(opt)
const base = h.https && (h.auth || h.default === 'https') ? h.https(opt) : h.shortcut(opt)

@@ -9,0 +9,0 @@ return `${base}#${sha}`

{
"name": "pacote",
"version": "21.5.1",
"version": "22.0.0",
"description": "JavaScript package downloader",

@@ -30,5 +30,5 @@ "author": "GitHub Inc.",

"@npmcli/arborist": "^9.0.2",
"@npmcli/eslint-config": "^6.0.0",
"@npmcli/eslint-config": "^7.0.0",
"@npmcli/template-oss": "5.1.0",
"hosted-git-info": "^9.0.0",
"hosted-git-info": "^10.1.1",
"mutate-fs": "^2.1.1",

@@ -51,21 +51,21 @@ "nock": "^13.2.4",

"@gar/promise-retry": "^1.0.0",
"@npmcli/git": "^7.0.0",
"@npmcli/installed-package-contents": "^4.0.0",
"@npmcli/package-json": "^7.0.0",
"@npmcli/promise-spawn": "^9.0.0",
"@npmcli/run-script": "^10.0.0",
"cacache": "^20.0.0",
"@npmcli/git": "^8.0.0",
"@npmcli/installed-package-contents": "^5.0.0",
"@npmcli/package-json": "^8.0.0",
"@npmcli/promise-spawn": "^10.0.0",
"@npmcli/run-script": "^11.0.0",
"cacache": "^21.0.1",
"fs-minipass": "^3.0.0",
"minipass": "^7.0.2",
"npm-package-arg": "^13.0.0",
"npm-packlist": "^10.0.1",
"npm-pick-manifest": "^11.0.1",
"npm-registry-fetch": "^19.0.0",
"proc-log": "^6.0.0",
"sigstore": "^4.0.0",
"ssri": "^13.0.0",
"npm-package-arg": "^14.0.0",
"npm-packlist": "^11.2.0",
"npm-pick-manifest": "^12.0.0",
"npm-registry-fetch": "^20.0.1",
"proc-log": "^7.0.0",
"sigstore": "^5.0.0",
"ssri": "^14.0.0",
"tar": "^7.4.3"
},
"engines": {
"node": "^20.17.0 || >=22.9.0"
"node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},

@@ -80,4 +80,5 @@ "repository": {

"windowsCI": false,
"publish": "true"
"publish": "true",
"updateNpm": false
}
}