diff --git a/node_modules/@npmcli/agent/lib/agents.js b/node_modules/@npmcli/agent/lib/agents.js index c541b93001517..e9624dfeb9009 100644 --- a/node_modules/@npmcli/agent/lib/agents.js +++ b/node_modules/@npmcli/agent/lib/agents.js @@ -203,4 +203,56 @@ module.exports = class Agent extends AgentBase { return super.addRequest(request, options) } + + // When connect() rejects, agent-base removes only its placeholder socket, so Node never drains this.requests[name] and requests queued past maxSockets hang forever. + // On a failure we dispatch the next queued request ourselves. + // See npm/cli#9386 and TooTallNate/proxy-agents#427. + createSocket (req, options, cb) { + super.createSocket(req, options, (err, socket) => { + if (err) { + this.#drainPendingRequests(req, options) + } + cb(err, socket) + }) + } + + // Dispatch the next request queued behind maxSockets, reusing the slot the failed connection freed. + #drainPendingRequests (failedReq, options) { + const name = this.getName(options) + const queue = this.requests[name] + if (!queue || queue.length === 0) { + return + } + + // Node's removeSocket() picks a queued request without shifting it off, so drop the failed one to avoid dispatching it twice. + const failedIndex = queue.indexOf(failedReq) + if (failedIndex !== -1) { + queue.splice(failedIndex, 1) + } + if (queue.length === 0) { + delete this.requests[name] + return + } + + // Safety belt: only dispatch if a socket slot is genuinely free. + const socketCount = this.sockets[name] ? this.sockets[name].length : 0 + if (socketCount >= this.maxSockets || this.totalSocketCount >= this.maxTotalSockets) { + return + } + + const nextReq = queue.shift() + if (queue.length === 0) { + delete this.requests[name] + } + + // All queued requests share this origin, so the failed request's options suit the next one. + // createSocket() recurses here if this connection also fails, draining the whole queue. + this.createSocket(nextReq, options, (err, socket) => { + if (err) { + nextReq.onSocket(null, err) + } else { + nextReq.onSocket(socket) + } + }) + } } diff --git a/node_modules/@npmcli/agent/lib/options.js b/node_modules/@npmcli/agent/lib/options.js index 0bf53f725f084..a6ae490a89c3b 100644 --- a/node_modules/@npmcli/agent/lib/options.js +++ b/node_modules/@npmcli/agent/lib/options.js @@ -37,6 +37,10 @@ const normalizeOptions = (opts) => { // remove timeout since we already used it to set our own idle timeout delete normalized.timeout + // since opts is often passed when initiating requests, it may contain + // headers, which should not be saved in an agent + delete normalized.headers + return normalized } diff --git a/node_modules/@npmcli/agent/package.json b/node_modules/@npmcli/agent/package.json index 67670a0c1c484..8c0d358b02a71 100644 --- a/node_modules/@npmcli/agent/package.json +++ b/node_modules/@npmcli/agent/package.json @@ -1,6 +1,6 @@ { "name": "@npmcli/agent", - "version": "4.0.0", + "version": "4.0.2", "description": "the http/https agent used by the npm cli", "main": "lib/index.js", "scripts": { @@ -29,8 +29,10 @@ }, "templateOSS": { "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.", - "version": "4.25.0", - "publish": "true" + "version": "4.30.0", + "publish": "true", + "updateNpm": false, + "latestCiVersion": 24 }, "dependencies": { "agent-base": "^7.1.0", @@ -40,11 +42,11 @@ "socks-proxy-agent": "^8.0.3" }, "devDependencies": { - "@npmcli/eslint-config": "^5.0.0", - "@npmcli/template-oss": "4.25.0", - "minipass-fetch": "^4.0.1", + "@npmcli/eslint-config": "^6.0.0", + "@npmcli/template-oss": "4.30.0", + "ip-address": "^10.1.0", + "minipass-fetch": "^5.0.0", "nock": "^14.0.3", - "socksv5": "^0.0.6", "tap": "^16.3.0" }, "repository": { diff --git a/node_modules/@sigstore/core/dist/dsse.js b/node_modules/@sigstore/core/dist/dsse.js index ca7b63630e2ba..9dcc2649198c1 100644 --- a/node_modules/@sigstore/core/dist/dsse.js +++ b/node_modules/@sigstore/core/dist/dsse.js @@ -19,12 +19,11 @@ limitations under the License. const PAE_PREFIX = 'DSSEv1'; // DSSE Pre-Authentication Encoding function preAuthEncoding(payloadType, payload) { - const prefix = [ - PAE_PREFIX, - payloadType.length, - payloadType, - payload.length, - '', - ].join(' '); - return Buffer.concat([Buffer.from(prefix, 'ascii'), payload]); + const typeBytes = Buffer.from(payloadType, 'utf-8'); + return Buffer.concat([ + Buffer.from(`${PAE_PREFIX} ${typeBytes.length} `, 'ascii'), + typeBytes, + Buffer.from(` ${payload.length} `, 'ascii'), + payload, + ]); } diff --git a/node_modules/@sigstore/core/package.json b/node_modules/@sigstore/core/package.json index 0564a373c6fa3..82cab44654a1c 100644 --- a/node_modules/@sigstore/core/package.json +++ b/node_modules/@sigstore/core/package.json @@ -1,6 +1,6 @@ { "name": "@sigstore/core", - "version": "3.2.0", + "version": "3.2.1", "description": "Base library for Sigstore", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/node_modules/@sigstore/verify/dist/key/index.js b/node_modules/@sigstore/verify/dist/key/index.js index c966ccb1e925e..880ad04bd235d 100644 --- a/node_modules/@sigstore/verify/dist/key/index.js +++ b/node_modules/@sigstore/verify/dist/key/index.js @@ -56,9 +56,17 @@ function getSigner(cert) { else { issuer = cert.extension(OID_FULCIO_ISSUER_V1)?.value.toString('ascii'); } + const oids = cert.extensions.map((ext) => { + const oid = ext.subs[0].toOID(); + return { + oid: { id: oid.split('.').map(Number) }, + value: ext.subs[ext.subs.length - 1].value, + }; + }); const identity = { extensions: { issuer }, subjectAlternativeName: cert.subjectAltName, + oids, }; return { key: core_1.crypto.createPublicKey(cert.publicKey), diff --git a/node_modules/@sigstore/verify/dist/policy.js b/node_modules/@sigstore/verify/dist/policy.js index f5960cf047b84..b08d083a296fb 100644 --- a/node_modules/@sigstore/verify/dist/policy.js +++ b/node_modules/@sigstore/verify/dist/policy.js @@ -2,7 +2,12 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.verifySubjectAlternativeName = verifySubjectAlternativeName; exports.verifyExtensions = verifyExtensions; +exports.verifyOIDs = verifyOIDs; const error_1 = require("./error"); +// Verifies that the signer's SAN matches the policy identity. The +// policyIdentity is treated as a JavaScript regular expression pattern and +// tested against the full signerIdentity string. For exact matching, use +// anchored patterns (e.g. '^user@example\\.com$'). function verifySubjectAlternativeName(policyIdentity, signerIdentity) { if (signerIdentity === undefined || !signerIdentity.match(policyIdentity)) { throw new error_1.PolicyError({ @@ -22,3 +27,24 @@ function verifyExtensions(policyExtensions, signerExtensions = {}) { } } } +function verifyOIDs(policyOIDs, signerOIDs = []) { + for (const policyOID of policyOIDs) { + const match = signerOIDs.find((signerOID) => oidEquals(policyOID.oid?.id, signerOID.oid?.id) && + policyOID.value.equals(signerOID.value)); + if (!match) { + /* istanbul ignore next */ + const oid = policyOID.oid?.id.join('.') ?? ''; + throw new error_1.PolicyError({ + code: 'UNTRUSTED_SIGNER_ERROR', + message: `invalid certificate extension - missing OID ${oid}`, + }); + } + } +} +function oidEquals(a, b) { + /* istanbul ignore if */ + if (a === undefined || b === undefined) { + return false; + } + return a.length === b.length && a.every((v, i) => v === b[i]); +} diff --git a/node_modules/@sigstore/verify/dist/timestamp/index.js b/node_modules/@sigstore/verify/dist/timestamp/index.js index 03a51083e1082..603e559831a9d 100644 --- a/node_modules/@sigstore/verify/dist/timestamp/index.js +++ b/node_modules/@sigstore/verify/dist/timestamp/index.js @@ -12,6 +12,10 @@ function getTSATimestamp(timestamp, data, timestampAuthorities) { }; } function getTLogTimestamp(entry) { + // Only entries with an inclusion promise provide a verifiable timestamp + if (!entry.inclusionPromise) { + return undefined; + } return { type: 'transparency-log', logID: entry.logId.keyId, diff --git a/node_modules/@sigstore/verify/dist/verifier.js b/node_modules/@sigstore/verify/dist/verifier.js index 5751087ff178d..eeba4128fabe3 100644 --- a/node_modules/@sigstore/verify/dist/verifier.js +++ b/node_modules/@sigstore/verify/dist/verifier.js @@ -46,17 +46,22 @@ class Verifier { } // Checks that all of the timestamps in the entity are valid and returns them verifyTimestamps(entity) { - let timestampCount = 0; - const timestamps = entity.timestamps.map((timestamp) => { + const timestamps = []; + for (const timestamp of entity.timestamps) { switch (timestamp.$case) { case 'timestamp-authority': - timestampCount++; - return (0, timestamp_1.getTSATimestamp)(timestamp.timestamp, entity.signature.signature, this.trustMaterial.timestampAuthorities); - case 'transparency-log': - timestampCount++; - return (0, timestamp_1.getTLogTimestamp)(timestamp.tlogEntry); + timestamps.push((0, timestamp_1.getTSATimestamp)(timestamp.timestamp, entity.signature.signature, this.trustMaterial.timestampAuthorities)); + break; + case 'transparency-log': { + const result = (0, timestamp_1.getTLogTimestamp)(timestamp.tlogEntry); + /* istanbul ignore else */ + if (result) { + timestamps.push(result); + } + break; + } } - }); + } // Check for duplicate timestamps if (containsDupes(timestamps)) { throw new error_1.VerificationError({ @@ -64,10 +69,10 @@ class Verifier { message: 'duplicate timestamp', }); } - if (timestampCount < this.options.timestampThreshold) { + if (timestamps.length < this.options.timestampThreshold) { throw new error_1.VerificationError({ code: 'TIMESTAMP_ERROR', - message: `expected ${this.options.timestampThreshold} timestamps, got ${timestampCount}`, + message: `expected ${this.options.timestampThreshold} timestamps, got ${timestamps.length}`, }); } return timestamps.map((t) => t.timestamp); @@ -133,6 +138,11 @@ class Verifier { if (policy.extensions) { (0, policy_1.verifyExtensions)(policy.extensions, identity.extensions); } + // Check that the OIDs of the signer match the policy + /* istanbul ignore if */ + if (policy.oids) { + (0, policy_1.verifyOIDs)(policy.oids, identity.oids); + } } } exports.Verifier = Verifier; diff --git a/node_modules/@sigstore/verify/package.json b/node_modules/@sigstore/verify/package.json index 79826a80bddeb..9c4e5dc7a727a 100644 --- a/node_modules/@sigstore/verify/package.json +++ b/node_modules/@sigstore/verify/package.json @@ -1,6 +1,6 @@ { "name": "@sigstore/verify", - "version": "3.1.0", + "version": "3.1.1", "description": "Verification of Sigstore signatures", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -28,7 +28,7 @@ "dependencies": { "@sigstore/protobuf-specs": "^0.5.0", "@sigstore/bundle": "^4.0.0", - "@sigstore/core": "^3.1.0" + "@sigstore/core": "^3.2.1" }, "engines": { "node": "^20.17.0 || >=22.9.0" diff --git a/node_modules/lru-cache/package.json b/node_modules/lru-cache/package.json index 760fee478270d..6ada2c211f2d6 100644 --- a/node_modules/lru-cache/package.json +++ b/node_modules/lru-cache/package.json @@ -1,7 +1,7 @@ { "name": "lru-cache", "description": "A cache object that deletes the least-recently-used items.", - "version": "11.5.0", + "version": "11.5.1", "author": "Isaac Z. Schlueter ", "keywords": [ "mru", diff --git a/node_modules/make-fetch-happen/package.json b/node_modules/make-fetch-happen/package.json index 1d06ac4889c3e..92c48b4587158 100644 --- a/node_modules/make-fetch-happen/package.json +++ b/node_modules/make-fetch-happen/package.json @@ -1,6 +1,6 @@ { "name": "make-fetch-happen", - "version": "15.0.5", + "version": "15.0.6", "description": "Opinionated, caching, retrying fetch client", "main": "lib/index.js", "files": [ diff --git a/node_modules/semver/classes/range.js b/node_modules/semver/classes/range.js index 94629ce6f5df6..c2e605e517360 100644 --- a/node_modules/semver/classes/range.js +++ b/node_modules/semver/classes/range.js @@ -98,6 +98,9 @@ class Range { } parseRange (range) { + // strip build metadata so it can't bleed into the version + range = range.replace(BUILDSTRIPRE, '') + // memoize range parsing for performance. // this is a very hot path, and fully deterministic. const memoOpts = @@ -223,6 +226,7 @@ const debug = require('../internal/debug') const SemVer = require('./semver') const { safeRe: re, + src, t, comparatorTrimReplace, tildeTrimReplace, @@ -230,6 +234,9 @@ const { } = require('../internal/re') const { FLAG_INCLUDE_PRERELEASE, FLAG_LOOSE } = require('../internal/constants') +// unbounded global build-metadata stripper used by parseRange +const BUILDSTRIPRE = new RegExp(src[t.BUILD], 'g') + const isNullSet = c => c.value === '<0.0.0-0' const isAny = c => c.value === '' diff --git a/node_modules/semver/package.json b/node_modules/semver/package.json index f8447c4951594..6edb9ab49d977 100644 --- a/node_modules/semver/package.json +++ b/node_modules/semver/package.json @@ -1,6 +1,6 @@ { "name": "semver", - "version": "7.8.0", + "version": "7.8.1", "description": "The semantic version parser used by npm.", "main": "index.js", "scripts": { diff --git a/node_modules/semver/ranges/subset.js b/node_modules/semver/ranges/subset.js index 99f43218075c8..a949832329003 100644 --- a/node_modules/semver/ranges/subset.js +++ b/node_modules/semver/ranges/subset.js @@ -174,7 +174,7 @@ const simpleSubset = (sub, dom, options) => { if (higher === c && higher !== gt) { return false } - } else if (gt.operator === '>=' && !satisfies(gt.semver, String(c), options)) { + } else if (gt.operator === '>=' && !c.test(gt.semver)) { return false } } @@ -192,7 +192,7 @@ const simpleSubset = (sub, dom, options) => { if (lower === c && lower !== lt) { return false } - } else if (lt.operator === '<=' && !satisfies(lt.semver, String(c), options)) { + } else if (lt.operator === '<=' && !c.test(lt.semver)) { return false } } diff --git a/node_modules/sigstore/dist/config.js b/node_modules/sigstore/dist/config.js index e8b2392f97f23..373149fe22fb7 100644 --- a/node_modules/sigstore/dist/config.js +++ b/node_modules/sigstore/dist/config.js @@ -65,6 +65,12 @@ function createVerificationPolicy(options) { if (options.certificateIssuer) { policy.extensions = { issuer: options.certificateIssuer }; } + if (options.certificateOIDs) { + policy.oids = Object.entries(options.certificateOIDs).map(([oid, value]) => ({ + oid: { id: oid.split('.').map(Number) }, + value: Buffer.from(value), + })); + } return policy; } // Instantiate the FulcioSigner based on the supplied options. diff --git a/node_modules/sigstore/package.json b/node_modules/sigstore/package.json index 5965f0889ca7d..e0acea6d96287 100644 --- a/node_modules/sigstore/package.json +++ b/node_modules/sigstore/package.json @@ -1,6 +1,6 @@ { "name": "sigstore", - "version": "4.1.0", + "version": "4.1.1", "description": "code-signing for npm packages", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -29,17 +29,17 @@ "devDependencies": { "@sigstore/rekor-types": "^4.0.0", "@sigstore/jest": "^0.0.0", - "@sigstore/mock": "^0.11.0", - "@tufjs/repo-mock": "^4.0.0", + "@sigstore/mock": "^0.12.1", + "@tufjs/repo-mock": "^4.0.1", "@types/make-fetch-happen": "^10.0.4" }, "dependencies": { "@sigstore/bundle": "^4.0.0", - "@sigstore/core": "^3.1.0", + "@sigstore/core": "^3.2.1", "@sigstore/protobuf-specs": "^0.5.0", - "@sigstore/sign": "^4.1.0", - "@sigstore/tuf": "^4.0.1", - "@sigstore/verify": "^3.1.0" + "@sigstore/sign": "^4.1.1", + "@sigstore/tuf": "^4.0.2", + "@sigstore/verify": "^3.1.1" }, "engines": { "node": "^20.17.0 || >=22.9.0" diff --git a/node_modules/undici/lib/dispatcher/agent.js b/node_modules/undici/lib/dispatcher/agent.js index db2f817d0fe97..90b46fe3aeb4b 100644 --- a/node_modules/undici/lib/dispatcher/agent.js +++ b/node_modules/undici/lib/dispatcher/agent.js @@ -24,7 +24,6 @@ function defaultFactory (origin, opts) { class Agent extends DispatcherBase { constructor ({ factory = defaultFactory, maxRedirections = 0, connect, ...options } = {}) { - if (typeof factory !== 'function') { throw new InvalidArgumentError('factory must be a function.') } diff --git a/node_modules/undici/lib/dispatcher/client-h1.js b/node_modules/undici/lib/dispatcher/client-h1.js index 2b8fa05da2942..ef3d38ea4f2ed 100644 --- a/node_modules/undici/lib/dispatcher/client-h1.js +++ b/node_modules/undici/lib/dispatcher/client-h1.js @@ -279,29 +279,71 @@ class Parser { const offset = llhttp.llhttp_get_error_pos(this.ptr) - currentBufferPtr - if (ret === constants.ERROR.PAUSED_UPGRADE) { - this.onUpgrade(data.slice(offset)) - } else if (ret === constants.ERROR.PAUSED) { - this.paused = true - socket.unshift(data.slice(offset)) - } else if (ret !== constants.ERROR.OK) { - const ptr = llhttp.llhttp_get_error_reason(this.ptr) - let message = '' - /* istanbul ignore else: difficult to make a test case for */ - if (ptr) { - const len = new Uint8Array(llhttp.memory.buffer, ptr).indexOf(0) - message = - 'Response does not match the HTTP/1.1 protocol (' + - Buffer.from(llhttp.memory.buffer, ptr, len).toString() + - ')' + if (ret !== constants.ERROR.OK) { + const body = data.subarray(offset) + + if (ret === constants.ERROR.PAUSED_UPGRADE) { + this.onUpgrade(body) + } else if (ret === constants.ERROR.PAUSED) { + this.paused = true + socket.unshift(body) + } else { + throw this.createError(ret, body) } - throw new HTTPParserError(message, constants.ERROR[ret], data.slice(offset)) } } catch (err) { util.destroy(socket, err) } } + finish () { + assert(currentParser === null) + assert(this.ptr != null) + assert(!this.paused) + + const { llhttp } = this + + let ret + + try { + currentParser = this + ret = llhttp.llhttp_finish(this.ptr) + } finally { + currentParser = null + } + + if (ret === constants.ERROR.OK) { + return null + } + + if (ret === constants.ERROR.PAUSED || ret === constants.ERROR.PAUSED_UPGRADE) { + this.paused = true + return null + } + + return this.createError(ret, EMPTY_BUF) + } + + createError (ret, data) { + const { llhttp, contentLength, bytesRead } = this + + if (contentLength && bytesRead !== parseInt(contentLength, 10)) { + return new ResponseContentLengthMismatchError() + } + + const ptr = llhttp.llhttp_get_error_reason(this.ptr) + let message = '' + if (ptr) { + const len = new Uint8Array(llhttp.memory.buffer, ptr).indexOf(0) + message = + 'Response does not match the HTTP/1.1 protocol (' + + Buffer.from(llhttp.memory.buffer, ptr, len).toString() + + ')' + } + + return new HTTPParserError(message, constants.ERROR[ret], data) + } + destroy () { assert(this.ptr != null) assert(currentParser == null) @@ -673,8 +715,11 @@ async function connectH1 (client, socket) { // On Mac OS, we get an ECONNRESET even if there is a full body to be forwarded // to the user. if (err.code === 'ECONNRESET' && parser.statusCode && !parser.shouldKeepAlive) { - // We treat all incoming data so for as a valid response. - parser.onMessageComplete() + const parserErr = parser.finish() + if (parserErr) { + this[kError] = parserErr + this[kClient][kOnError](parserErr) + } return } @@ -693,8 +738,10 @@ async function connectH1 (client, socket) { const parser = this[kParser] if (parser.statusCode && !parser.shouldKeepAlive) { - // We treat all incoming data so far as a valid response. - parser.onMessageComplete() + const parserErr = parser.finish() + if (parserErr) { + util.destroy(this, parserErr) + } return } @@ -706,8 +753,7 @@ async function connectH1 (client, socket) { if (parser) { if (!this[kError] && parser.statusCode && !parser.shouldKeepAlive) { - // We treat all incoming data so far as a valid response. - parser.onMessageComplete() + this[kError] = parser.finish() || this[kError] } this[kParser].destroy() diff --git a/node_modules/undici/package.json b/node_modules/undici/package.json index 46cb9a8292618..d1eef502c4169 100644 --- a/node_modules/undici/package.json +++ b/node_modules/undici/package.json @@ -1,6 +1,6 @@ { "name": "undici", - "version": "6.25.0", + "version": "6.26.0", "description": "An HTTP/1.1 client, written from scratch for Node.js", "homepage": "https://undici.nodejs.org", "bugs": { diff --git a/package-lock.json b/package-lock.json index a96554c319d5c..9ca6a2e1a9dda 100644 --- a/package-lock.json +++ b/package-lock.json @@ -118,7 +118,7 @@ "libnpmsearch": "^9.0.1", "libnpmteam": "^8.0.2", "libnpmversion": "^9.0.0-pre.0.0", - "make-fetch-happen": "^15.0.5", + "make-fetch-happen": "^15.0.6", "minimatch": "^10.2.5", "minipass": "^7.1.3", "minipass-pipeline": "^1.2.4", @@ -138,7 +138,7 @@ "proc-log": "^6.1.0", "qrcode-terminal": "^0.12.0", "read": "^5.0.1", - "semver": "^7.8.0", + "semver": "^7.8.1", "spdx-expression-parse": "^4.0.0", "ssri": "^13.0.1", "supports-color": "^10.2.2", @@ -315,9 +315,9 @@ } }, "mock-registry/node_modules/@npmcli/arborist": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-9.5.0.tgz", - "integrity": "sha512-qS+TtKWC58sjBjD+szLrhEj2TCLnwzUA9vlMyCnU9ztw01ZjQSu25iQPxeBa0sk9sS9/Hzs/xJMWl7J/vRCjGQ==", + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-9.6.0.tgz", + "integrity": "sha512-Dku9UWbrrX+UCu8rQ1obGKaQAL4kwdt3hHCNXrd0n0R/4B8oq3CzloUAShwFjfsAGM6KY27gPuNftOUEZ4nhOw==", "dev": true, "license": "ISC", "dependencies": { @@ -438,13 +438,13 @@ "license": "MIT" }, "node_modules/@babel/code-frame": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", - "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.28.5", + "@babel/helper-validator-identifier": "^7.29.7", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" }, @@ -453,9 +453,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.29.3", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.3.tgz", - "integrity": "sha512-LIVqM46zQWZhj17qA8wb4nW/ixr2y1Nw+r1etiAWgRM6U1IqP+LNhL1yg440jYZR72jCWcWbLWzIosH+uP1fqg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", "dev": true, "license": "MIT", "engines": { @@ -463,21 +463,21 @@ } }, "node_modules/@babel/core": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", - "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.29.0", - "@babel/generator": "^7.29.0", - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-module-transforms": "^7.28.6", - "@babel/helpers": "^7.28.6", - "@babel/parser": "^7.29.0", - "@babel/template": "^7.28.6", - "@babel/traverse": "^7.29.0", - "@babel/types": "^7.29.0", + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helpers": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", @@ -507,14 +507,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.29.1", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", - "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.7.tgz", + "integrity": "sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.29.0", - "@babel/types": "^7.29.0", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" @@ -524,14 +524,14 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", - "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", + "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.28.6", - "@babel/helper-validator-option": "^7.27.1", + "@babel/compat-data": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" @@ -562,7 +562,9 @@ "license": "ISC" }, "node_modules/@babel/helper-globals": { - "version": "7.28.0", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", + "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", "dev": true, "license": "MIT", "engines": { @@ -570,29 +572,29 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", - "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", + "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.28.6", - "@babel/types": "^7.28.6" + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", - "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", + "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.28.6", - "@babel/helper-validator-identifier": "^7.28.5", - "@babel/traverse": "^7.28.6" + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -602,7 +604,9 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", "dev": true, "license": "MIT", "engines": { @@ -610,9 +614,9 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", - "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", "dev": true, "license": "MIT", "engines": { @@ -620,7 +624,9 @@ } }, "node_modules/@babel/helper-validator-option": { - "version": "7.27.1", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", + "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", "dev": true, "license": "MIT", "engines": { @@ -628,27 +634,27 @@ } }, "node_modules/@babel/helpers": { - "version": "7.29.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz", - "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.28.6", - "@babel/types": "^7.29.0" + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.29.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.3.tgz", - "integrity": "sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz", + "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.29.0" + "@babel/types": "^7.29.7" }, "bin": { "parser": "bin/babel-parser.js" @@ -658,33 +664,33 @@ } }, "node_modules/@babel/template": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", - "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", + "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.28.6", - "@babel/parser": "^7.28.6", - "@babel/types": "^7.28.6" + "@babel/code-frame": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", - "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.7.tgz", + "integrity": "sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.29.0", - "@babel/generator": "^7.29.0", - "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.29.0", - "@babel/template": "^7.28.6", - "@babel/types": "^7.29.0", + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-globals": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7", "debug": "^4.3.1" }, "engines": { @@ -692,14 +698,14 @@ } }, "node_modules/@babel/types": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", - "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz", + "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.28.5" + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1196,9 +1202,9 @@ "peer": true }, "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", - "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", "dev": true, "license": "MIT", "peer": true, @@ -1438,9 +1444,9 @@ "peer": true }, "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", - "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", "dev": true, "license": "MIT", "peer": true, @@ -1704,7 +1710,9 @@ } }, "node_modules/@npmcli/agent": { - "version": "4.0.0", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-4.0.2.tgz", + "integrity": "sha512-EUEuWAxnL07Sp5/iC/1X6Xj+XThUvnbei9zfRWZdEXa7lss9RTHMhAHBeg+MZ5To9s/gGaSI+UwZTPdYMvKSeg==", "inBundle": true, "license": "ISC", "dependencies": { @@ -2011,9 +2019,9 @@ } }, "node_modules/@npmcli/template-oss/node_modules/@npmcli/arborist": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-9.5.0.tgz", - "integrity": "sha512-qS+TtKWC58sjBjD+szLrhEj2TCLnwzUA9vlMyCnU9ztw01ZjQSu25iQPxeBa0sk9sS9/Hzs/xJMWl7J/vRCjGQ==", + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-9.6.0.tgz", + "integrity": "sha512-Dku9UWbrrX+UCu8rQ1obGKaQAL4kwdt3hHCNXrd0n0R/4B8oq3CzloUAShwFjfsAGM6KY27gPuNftOUEZ4nhOw==", "dev": true, "license": "ISC", "dependencies": { @@ -2166,9 +2174,9 @@ } }, "node_modules/@octokit/request": { - "version": "10.0.9", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-10.0.9.tgz", - "integrity": "sha512-o8Bi3f608eyM+7BmBiUWxFsdjLb3/ym1cQek5LZOv9KkZcxRrHCPhhRzm6xjO6HVZ85ItD6+sTsjxo821SVa/A==", + "version": "10.0.10", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-10.0.10.tgz", + "integrity": "sha512-KxNC2pTqqhszMNrf12ZRd4PonRgyJdsM4F/jySiddQK+DsRcfBtUvqn8t7UsyZhnRJHvX46OohDt5N3VqIWC2w==", "dev": true, "license": "MIT", "dependencies": { @@ -2176,7 +2184,6 @@ "@octokit/request-error": "^7.0.2", "@octokit/types": "^16.0.0", "content-type": "^2.0.0", - "fast-content-type-parse": "^3.0.0", "json-with-bigint": "^3.5.3", "universal-user-agent": "^7.0.2" }, @@ -2241,9 +2248,9 @@ } }, "node_modules/@sigstore/core": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@sigstore/core/-/core-3.2.0.tgz", - "integrity": "sha512-kxHrDQ9YgfrWUSXU0cjsQGv8JykOFZQ9ErNKbFPWzk3Hgpwu8x2hHrQ9IdA8yl+j9RTLTC3sAF3Tdq1IQCP4oA==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@sigstore/core/-/core-3.2.1.tgz", + "integrity": "sha512-qRsxPnCrbC/puegGxKuynfnxgLiHqWStrSjxkoB4YKqq3Z3s4cyZyj42ZdWFAEblNP65C+rBH8EuREHIXoi83g==", "inBundle": true, "license": "Apache-2.0", "engines": { @@ -2293,14 +2300,14 @@ } }, "node_modules/@sigstore/verify": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@sigstore/verify/-/verify-3.1.0.tgz", - "integrity": "sha512-mNe0Iigql08YupSOGv197YdHpPPr+EzDZmfCgMc7RPNaZTw5aLN01nBl6CHJOh3BGtnMIj83EeN4butBchc8Ag==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@sigstore/verify/-/verify-3.1.1.tgz", + "integrity": "sha512-qv7+G3J2cc6wwFj3yKvXOamzqhMwSk1ogPGmhpS8iXllcPrJaIIBA+4HbttlHVu1pqWTdmaCH/WE7UOC51kdoA==", "inBundle": true, "license": "Apache-2.0", "dependencies": { "@sigstore/bundle": "^4.0.0", - "@sigstore/core": "^3.1.0", + "@sigstore/core": "^3.2.1", "@sigstore/protobuf-specs": "^0.5.0" }, "engines": { @@ -3014,9 +3021,9 @@ } }, "node_modules/baseline-browser-mapping": { - "version": "2.10.31", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.31.tgz", - "integrity": "sha512-MujYO3eP72uvmSE0i4wltsodRfIpZATP3jvzRNRGGxgzId7aVocVJJV3nf01qnzzKFGxQVC9bpWxl5cjxTr/7Q==", + "version": "2.10.32", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.32.tgz", + "integrity": "sha512-wbPvpyjJPC0zdfdKXxqEL3Ea+bOMD/87X4lftiJkkaBiuG6ALQy1SLmEd7BSmVCuwCQsBrCamgBoLyfFDD1EPg==", "dev": true, "license": "Apache-2.0", "bin": { @@ -3700,9 +3707,9 @@ "license": "Apache-2.0" }, "node_modules/code-suggester/node_modules/brace-expansion": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", - "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", "dev": true, "license": "MIT", "dependencies": { @@ -4541,9 +4548,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.360", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.360.tgz", - "integrity": "sha512-GkcBt6YYAw9SxFWn+xVar4cLVGlXVuswwtRLBozi2zp0GjXs4ZnOrqV4zbXzg35n7w81hCkyJNYicgXlVHAmBA==", + "version": "1.5.362", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.362.tgz", + "integrity": "sha512-PUY2DrLvkjkUuWqq+KPL2iWshrJsZOcIojzRQ7eXFacc9dWga7MGMJAa15VbiejSZB1PAXaRLAiKgruHP8LB1w==", "dev": true, "license": "ISC" }, @@ -4667,7 +4674,9 @@ } }, "node_modules/es-object-atoms": { - "version": "1.1.1", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", "dev": true, "license": "MIT", "peer": true, @@ -4723,9 +4732,9 @@ } }, "node_modules/es-toolkit": { - "version": "1.46.1", - "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.46.1.tgz", - "integrity": "sha512-5eNtXOs3tbfxXOj04tjjseeWkRWaoCjdEI+96DgwzZoe6c9juL49pXlzAFTI72aWC9Y8p7168g6XIKjh7k6pyQ==", + "version": "1.47.0", + "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.47.0.tgz", + "integrity": "sha512-n1GuoD0WEQZMBk5tttoZSqwgyLx01oqa5XsBmCHwPyNe1S9jPBEmtR2pSgp2kJuWE3ciFZ6yRHmY4pM4C3OOkw==", "dev": true, "license": "MIT", "workspaces": [ @@ -4947,9 +4956,9 @@ "peer": true }, "node_modules/eslint-plugin-import/node_modules/brace-expansion": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", - "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", "dev": true, "license": "MIT", "peer": true, @@ -5031,9 +5040,9 @@ "peer": true }, "node_modules/eslint-plugin-node/node_modules/brace-expansion": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", - "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", "dev": true, "license": "MIT", "peer": true, @@ -5174,9 +5183,9 @@ "peer": true }, "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", - "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", "dev": true, "license": "MIT", "peer": true, @@ -5415,21 +5424,6 @@ "dev": true, "license": "MIT" }, - "node_modules/fast-content-type-parse": { - "version": "3.0.0", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "MIT" - }, "node_modules/fast-deep-equal": { "version": "3.1.3", "dev": true, @@ -5577,9 +5571,9 @@ "peer": true }, "node_modules/flat-cache/node_modules/brace-expansion": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", - "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", "dev": true, "license": "MIT", "peer": true, @@ -6981,9 +6975,9 @@ "license": "MIT" }, "node_modules/istanbul-lib-processinfo/node_modules/brace-expansion": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", - "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", "dev": true, "license": "MIT", "dependencies": { @@ -7447,9 +7441,9 @@ } }, "node_modules/lru-cache": { - "version": "11.5.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.0.tgz", - "integrity": "sha512-5YgH9UJd7wVb9hIouI2adWpgqrrICkt070Dnj8EUY1+B4B2P9eRLPAkAAo6NICA7CEhOIeBHl46u9zSNpNu7zA==", + "version": "11.5.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.1.tgz", + "integrity": "sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A==", "inBundle": true, "license": "BlueOak-1.0.0", "engines": { @@ -7479,9 +7473,9 @@ } }, "node_modules/make-fetch-happen": { - "version": "15.0.5", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-15.0.5.tgz", - "integrity": "sha512-uCbIa8jWWmQZt4dSnEStkVC6gdakiinAm4PiGsywIkguF0eWMdcjDz0ECYhUolFU3pFLOev9VNPCEygydXnddg==", + "version": "15.0.6", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-15.0.6.tgz", + "integrity": "sha512-Je0fLJ0F5atA7F+eIlLzk+Wkcl57JDf4kf+EW8xiP5E31xOQxkIxTbgf1Oi1Lw9tRI9UEMRdI5Vz2xTzoNU1Jw==", "inBundle": true, "license": "ISC", "dependencies": { @@ -8712,11 +8706,14 @@ } }, "node_modules/node-releases": { - "version": "2.0.44", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.44.tgz", - "integrity": "sha512-5WUyunoPMsvvEhS8AxHtRzP+oA8UCkJ7YRxatWKjngndhDGLiqEVAQKWjFAiAiuL8zMRGzGSJxFnLetoa43qGQ==", + "version": "2.0.46", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.46.tgz", + "integrity": "sha512-GYVXHE2KnrzAfsAjl4uP++evGFCrAU1jta4ubEjIG7YWt/64Gqv66a30yKwWczVjA6j3bM4nBwH7Pk1JmDHaxQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=18" + } }, "node_modules/nopt": { "version": "9.0.0", @@ -8951,9 +8948,9 @@ "license": "MIT" }, "node_modules/nyc/node_modules/brace-expansion": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", - "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", "dev": true, "license": "MIT", "dependencies": { @@ -10002,9 +9999,9 @@ } }, "node_modules/release-please": { - "version": "17.6.0", - "resolved": "https://registry.npmjs.org/release-please/-/release-please-17.6.0.tgz", - "integrity": "sha512-ItzkkEBeEbKsCrx7N1QlADrCahoONA4WPlsOinSnXTkqUBIWlHC6+S28VJ9PaHy7ZPSJwSQsRuDjI0/HL5G6hw==", + "version": "17.6.1", + "resolved": "https://registry.npmjs.org/release-please/-/release-please-17.6.1.tgz", + "integrity": "sha512-4KtlVBnvccYZWepgFuRO5qVLc3Y0NicyBM4nqSt+sTKRWvagEJbPXUgErcWLJLW63KHzDphdwZQbbRmyqt2eIQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -10693,9 +10690,9 @@ } }, "node_modules/semver": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.0.tgz", - "integrity": "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==", + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.1.tgz", + "integrity": "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg==", "inBundle": true, "license": "ISC", "bin": { @@ -10860,18 +10857,18 @@ } }, "node_modules/sigstore": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-4.1.0.tgz", - "integrity": "sha512-/fUgUhYghuLzVT/gaJoeVehLCgZiUxPCPMcyVNY0lIf/cTCz58K/WTI7PefDarXxp9nUKpEwg1yyz3eSBMTtgA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-4.1.1.tgz", + "integrity": "sha512-endqECJkfhozrXMK5ngu/UAA0xVcVEFdnHJCElGaExypjW+HK5i6zu3NteLoaX/iFbRUbC3+DjttQs0GARr+5w==", "inBundle": true, "license": "Apache-2.0", "dependencies": { "@sigstore/bundle": "^4.0.0", - "@sigstore/core": "^3.1.0", + "@sigstore/core": "^3.2.1", "@sigstore/protobuf-specs": "^0.5.0", - "@sigstore/sign": "^4.1.0", - "@sigstore/tuf": "^4.0.1", - "@sigstore/verify": "^3.1.0" + "@sigstore/sign": "^4.1.1", + "@sigstore/tuf": "^4.0.2", + "@sigstore/verify": "^3.1.1" }, "engines": { "node": "^20.17.0 || >=22.9.0" @@ -10993,9 +10990,9 @@ "license": "MIT" }, "node_modules/spawn-wrap/node_modules/brace-expansion": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", - "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", "dev": true, "license": "MIT", "dependencies": { @@ -11186,9 +11183,9 @@ } }, "node_modules/streamx": { - "version": "2.25.0", - "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.25.0.tgz", - "integrity": "sha512-0nQuG6jf1w+wddNEEXCF4nTg3LtufWINB5eFEN+5TNZW7KWJp6x87+JFL43vaAUPyCfH1wID+mNVyW6OHtFamg==", + "version": "2.26.0", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.26.0.tgz", + "integrity": "sha512-VvNG1K72Po/xwJzxZFnZ++Tbrv4lwSptsbkFuzXCJAYZvCK5nnxsvXU6ajqkv7chyiI1Y0YXq2Jh8Iy8Y7NF/A==", "dev": true, "license": "MIT", "dependencies": { @@ -11446,9 +11443,9 @@ "license": "MIT" }, "node_modules/tap-mocha-reporter/node_modules/brace-expansion": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", - "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", "dev": true, "license": "MIT", "dependencies": { @@ -13649,9 +13646,9 @@ "license": "MIT" }, "node_modules/test-exclude/node_modules/brace-expansion": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", - "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", "dev": true, "license": "MIT", "dependencies": { @@ -13717,9 +13714,9 @@ "license": "MIT" }, "node_modules/tinyexec": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.1.2.tgz", - "integrity": "sha512-dAqSqE/RabpBKI8+h26GfLq6Vb3JVXs30XYQjdMjaj/c2tS8IYYMbIzP599KtRj7c57/wYApb3QjgRgXmrCukA==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.2.2.tgz", + "integrity": "sha512-M/Q0B2cp4K7kynaT/vnED1j8TlLY+Pp7C6Wl2bl/7u/F0mUVwdyOpwomQb8JpYLitHUssAJRmLZdMCGsrx7i+g==", "dev": true, "license": "MIT", "engines": { @@ -13773,22 +13770,22 @@ } }, "node_modules/tldts": { - "version": "7.0.30", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.30.tgz", - "integrity": "sha512-ELrFxuqsDdHUwoh0XxDbxuLD3Wnz49Z57IFvTtvWy1hJdcMZjXLIuonjilCiWHlT2GbE4Wlv1wKVTzDFnXH1aw==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.4.0.tgz", + "integrity": "sha512-yHBe+zVfzNZ3QfTPW/Z6KK1G2t340gFjMHqI/4KKSt/abzYydzuCnpqdaF5gCCABby+9Yfbj59oR5F2Fd5CBzg==", "dev": true, "license": "MIT", "dependencies": { - "tldts-core": "^7.0.30" + "tldts-core": "^7.4.0" }, "bin": { "tldts": "bin/cli.js" } }, "node_modules/tldts-core": { - "version": "7.0.30", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.30.tgz", - "integrity": "sha512-uiHN8PIB1VmWyS98eZYja4xzlYqeFZVjb4OuYlJQnZAuJhMw4PbKQOKgHKhBdJR3FE/t5mUQ1Kd80++B+qhD1Q==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.4.0.tgz", + "integrity": "sha512-/mb9kRld+x1sIMXxWNOAp5m6C+D4GrAORWlJkOJ5dElvxdN1eutz/o7qHLp9gFvDF4Y3/L2xeScoxz6AbEo8rQ==", "dev": true, "license": "MIT" }, @@ -14093,9 +14090,9 @@ } }, "node_modules/undici": { - "version": "6.25.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-6.25.0.tgz", - "integrity": "sha512-ZgpWDC5gmNiuY9CnLVXEH8rl50xhRCuLNA97fAUnKi8RRuV4E6KG31pDTsLVUKnohJE0I3XDrTeEydAXRw47xg==", + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.26.0.tgz", + "integrity": "sha512-4yqz8a3n5HmGTlsbADNtr/dJlhkh/55Rq798G6ibiULcXbDtaLpTl1pvdqcbFfeoj3iSi52lePFM7h9H21cw/A==", "inBundle": true, "license": "MIT", "engines": { @@ -14508,15 +14505,15 @@ "license": "ISC" }, "node_modules/which-typed-array": { - "version": "1.1.20", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.20.tgz", - "integrity": "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==", + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.21.tgz", + "integrity": "sha512-zbRA8cVm6io/d5W8uIe2hblzN76/Wm3v/yiythQvr+dpBWeqhPSWIDNj4zOyHi4zKbMK6DN34Xsr9jPHJERAEw==", "dev": true, "license": "MIT", "peer": true, "dependencies": { "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", + "call-bind": "^1.0.9", "call-bound": "^1.0.4", "for-each": "^0.3.5", "get-proto": "^1.0.1", @@ -14562,9 +14559,9 @@ } }, "node_modules/ws": { - "version": "8.20.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.1.tgz", - "integrity": "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==", + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz", + "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==", "dev": true, "license": "MIT", "engines": { diff --git a/package.json b/package.json index 25f0cd6edab09..bc68b84449b6f 100644 --- a/package.json +++ b/package.json @@ -82,7 +82,7 @@ "libnpmsearch": "^9.0.1", "libnpmteam": "^8.0.2", "libnpmversion": "^9.0.0-pre.0.0", - "make-fetch-happen": "^15.0.5", + "make-fetch-happen": "^15.0.6", "minimatch": "^10.2.5", "minipass": "^7.1.3", "minipass-pipeline": "^1.2.4", @@ -102,7 +102,7 @@ "proc-log": "^6.1.0", "qrcode-terminal": "^0.12.0", "read": "^5.0.1", - "semver": "^7.8.0", + "semver": "^7.8.1", "spdx-expression-parse": "^4.0.0", "ssri": "^13.0.1", "supports-color": "^10.2.2", diff --git a/tap-snapshots/test/lib/commands/config.js.test.cjs b/tap-snapshots/test/lib/commands/config.js.test.cjs index 769bbde3723e0..57956a4f5171e 100644 --- a/tap-snapshots/test/lib/commands/config.js.test.cjs +++ b/tap-snapshots/test/lib/commands/config.js.test.cjs @@ -71,6 +71,7 @@ exports[`test/lib/commands/config.js TAP config list --json > output matches sna "git-tag-version": true, "global": false, "globalconfig": "{CWD}/global/etc/npmrc", + "global-ignore-file": "{CWD}/global/etc/npmignore", "global-style": false, "heading": "npm", "https-proxy": null, @@ -255,6 +256,7 @@ fund = true git = "git" git-tag-version = true global = false +global-ignore-file = "{CWD}/global/etc/npmignore" global-style = false globalconfig = "{CWD}/global/etc/npmrc" heading = "npm" diff --git a/tap-snapshots/test/lib/commands/publish.js.test.cjs b/tap-snapshots/test/lib/commands/publish.js.test.cjs index 8e4e0255b223f..691e67c5571ae 100644 --- a/tap-snapshots/test/lib/commands/publish.js.test.cjs +++ b/tap-snapshots/test/lib/commands/publish.js.test.cjs @@ -173,6 +173,28 @@ exports[`test/lib/commands/publish.js TAP prioritize CLI flags over publishConfi + @npmcli/test-package@1.0.0 ` +exports[`test/lib/commands/publish.js TAP private access > must match snapshot 1`] = ` +Array [ + "package: @npm/test-package@1.0.0", + "Tarball Contents", + "55B package.json", + "Tarball Details", + "name: @npm/test-package", + "version: 1.0.0", + "filename: npm-test-package-1.0.0.tgz", + "package size: {size}", + "unpacked size: 55 B", + "shasum: {sha}", + "integrity: {integrity} + "total files: 1", + "Publishing to https://registry.npmjs.org/ with tag latest and restricted access", +] +` + +exports[`test/lib/commands/publish.js TAP private access > new package version 1`] = ` ++ @npm/test-package@1.0.0 +` + exports[`test/lib/commands/publish.js TAP public access > must match snapshot 1`] = ` Array [ "package: @npm/test-package@1.0.0", diff --git a/tap-snapshots/test/lib/docs.js.test.cjs b/tap-snapshots/test/lib/docs.js.test.cjs index 31e4c7b9b120c..1c36192f7c225 100644 --- a/tap-snapshots/test/lib/docs.js.test.cjs +++ b/tap-snapshots/test/lib/docs.js.test.cjs @@ -189,7 +189,7 @@ safer to use a registry-provided authentication bearer token stored in the * Default: 'public' for new packages, existing packages it will not change the current level -* Type: null, "restricted", or "public" +* Type: null, "restricted", "public", or "private" If you do not want your scoped package to be publicly viewable (and installable) set \`--access=restricted\`. @@ -201,6 +201,8 @@ packages. Specifying a value of \`restricted\` or \`public\` during publish will change the access for an existing package the same way that \`npm access set status\` would. +The value \`private\` is an alias for \`restricted\`. + #### \`all\` @@ -863,6 +865,25 @@ folder instead of the current working directory. See +#### \`global-ignore-file\` + +* Default: The global --prefix setting plus 'etc/npmignore'. For example, + '/usr/local/etc/npmignore' +* Type: Path + +An additional ignore file applied during \`npm pack\` and \`npm publish\`, owned +by the current user rather than the package. Patterns follow the same syntax +as a package's local \`.npmignore\` file. Useful for keeping editor metadata +(such as \`.idea/\` or \`*.iml\`) and scratch directories out of every package +you publish, without adding them to each package's own ignore rules. + +The global rules apply in addition to a package's local \`.npmignore\`. When a +package uses a \`files\` field in its \`package.json\`, an entry in \`files\` that +contradicts a global rule (i.e., explicitly includes a path the global rule +would exclude) still wins. + + + #### \`globalconfig\` * Default: The global --prefix setting plus 'etc/npmrc'. For example, @@ -2435,6 +2456,7 @@ Array [ "git-tag-version", "global", "globalconfig", + "global-ignore-file", "global-style", "heading", "https-proxy", @@ -2617,6 +2639,7 @@ Array [ "git-tag-version", "global", "globalconfig", + "global-ignore-file", "global-style", "heading", "https-proxy", @@ -2798,6 +2821,7 @@ Object { "gitTagVersion": true, "global": false, "globalconfig": "{CWD}/global/etc/npmrc", + "globalIgnoreFile": "{CWD}/global/etc/npmignore", "heading": "npm", "httpsProxy": null, "ifPresent": false, @@ -5416,7 +5440,7 @@ Usage: npm publish Options: -[--tag ] [--access ] [--dry-run] [--otp ] +[--tag ] [--access ] [--dry-run] [--otp ] [-w|--workspace [-w|--workspace ...]] [--workspaces] [--include-workspace-root] [--provenance|--provenance-file ] diff --git a/test/lib/commands/publish.js b/test/lib/commands/publish.js index 692f0ce68c1e3..8765ebea7b8b9 100644 --- a/test/lib/commands/publish.js +++ b/test/lib/commands/publish.js @@ -742,6 +742,27 @@ t.test('restricted access', async t => { t.matchSnapshot(logs.notice) }) +t.test('private access', async t => { + const packageJson = { + name: '@npm/test-package', + version: '1.0.0', + } + const { npm, joinedOutput, logs, registry } = await loadNpmWithRegistry(t, { + config: { + ...auth, + access: 'private', + }, + prefixDir: { + 'package.json': JSON.stringify(packageJson, null, 2), + }, + authorization: token, + }) + registry.publish('@npm/test-package', { packageJson, access: 'restricted' }) + await npm.exec('publish', []) + t.matchSnapshot(joinedOutput(), 'new package version') + t.matchSnapshot(logs.notice) +}) + t.test('public access', async t => { const { npm, joinedOutput, logs, registry } = await loadNpmWithRegistry(t, { config: { diff --git a/workspaces/arborist/lib/arborist/isolated-reifier.js b/workspaces/arborist/lib/arborist/isolated-reifier.js index d0a49c3650636..5f0041e74857e 100644 --- a/workspaces/arborist/lib/arborist/isolated-reifier.js +++ b/workspaces/arborist/lib/arborist/isolated-reifier.js @@ -293,7 +293,8 @@ module.exports = cls => class IsolatedReifier extends cls { root.inventory.set(workspace.location, workspace) root.workspaces.set(wsName, workspace.path) - // Create workspace Link. For root declared deps, link at root node_modules/. For undeclared deps, link at the workspace's own node_modules/ (self-link). + // Declared workspaces are symlinked at root node_modules/. + // Undeclared workspaces get a tree-only Link kept for diff/filter participation but not materialized on disk. const isDeclared = this.#rootDeclaredDeps.has(wsName) const wsLink = new IsolatedLink({ location: isDeclared ? join('node_modules', wsName) : join(c.localLocation, 'node_modules', wsName), @@ -306,7 +307,7 @@ module.exports = cls => class IsolatedReifier extends cls { target: workspace, }) if (!isDeclared) { - workspace.children.set(wsName, wsLink) + wsLink.isUndeclaredWorkspaceLink = true } root.children.set(wsName, wsLink) root.inventory.set(wsLink.location, wsLink) diff --git a/workspaces/arborist/lib/arborist/reify.js b/workspaces/arborist/lib/arborist/reify.js index 0d3a36af6902c..40e6c1853287d 100644 --- a/workspaces/arborist/lib/arborist/reify.js +++ b/workspaces/arborist/lib/arborist/reify.js @@ -237,7 +237,7 @@ module.exports = cls => class Reifier extends cls { this.actualTree = this.idealTree this.idealTree = null - if (!this.options.global) { + if (!this.options.global && !this.options.dryRun) { await this.actualTree.meta.save() const ignoreScripts = !!this.options.ignoreScripts // if we aren't doing a dry run or ignoring scripts and we actually made changes to the dep @@ -723,6 +723,12 @@ module.exports = cls => class Reifier extends cls { } // node.isLink + + // Tree-only Link: present in the tree for diff/filter participation, never materialized on disk. + if (node.isUndeclaredWorkspaceLink) { + return + } + await rm(node.path, { recursive: true, force: true }) // symlink @@ -1341,6 +1347,10 @@ module.exports = cls => class Reifier extends cls { if (!child.isLink) { continue } + // Tree-only Links never exist on disk; skipping them lets the sweep remove any stale self-link left by an older npm version. + if (child.isUndeclaredWorkspaceLink) { + continue + } const nmIdx = loc.lastIndexOf(NM_PREFIX) if (nmIdx === -1 || loc.includes(STORE_MARKER)) { continue diff --git a/workspaces/arborist/test/arborist/reify.js b/workspaces/arborist/test/arborist/reify.js index 731d602b12939..e825ed2ee2001 100644 --- a/workspaces/arborist/test/arborist/reify.js +++ b/workspaces/arborist/test/arborist/reify.js @@ -1613,6 +1613,26 @@ t.test('save complete lockfile on update-all', async t => { t.matchSnapshot(lock(), 'should update, but not drop root metadata') }) +t.test('dry-run update does not save lockfiles', async t => { + const path = t.testdir({ + 'package.json': JSON.stringify({ + name: 'dry-run-update-lockfile-test', + version: '1.0.0', + }), + }) + createRegistry(t, true) + await reify(path, { add: ['abbrev@1.0.4'] }) + + const lock = filename => fs.readFileSync(resolve(path, filename), 'utf8') + const packageLock = lock('package-lock.json') + const hiddenLock = lock('node_modules/.package-lock.json') + + await reify(path, { update: true, dryRun: true, save: false }) + + t.equal(lock('package-lock.json'), packageLock, 'package-lock.json unchanged') + t.equal(lock('node_modules/.package-lock.json'), hiddenLock, 'hidden lockfile unchanged') +}) + t.test('save proper lockfile with bins when upgrading lockfile', async t => { for (const complete of [true, false]) { await t.test(`complete=${complete}`, async t => { diff --git a/workspaces/arborist/test/isolated-mode.js b/workspaces/arborist/test/isolated-mode.js index 86bb2f0ea23ed..2be8561806b3f 100644 --- a/workspaces/arborist/test/isolated-mode.js +++ b/workspaces/arborist/test/isolated-mode.js @@ -42,7 +42,8 @@ const rule1 = { apply: (t, dir, resolvedGraph, alreadyAsserted) => { const graph = parseGraph(resolvedGraph) const allPackages = getAllPackages(withRequireChain(graph)) - allPackages.filter(p => p.chain.length !== 0).forEach(p => { + // Workspaces are excluded: linked-strategy workspaces have no self-symlink, so self-referencing requires an `exports` field (matching pnpm). + allPackages.filter(p => p.chain.length !== 0 && !p.workspace).forEach(p => { const resolveChain = [...p.chain, p.name] const key = p.initialDir + ' => ' + resolveChain.join(' => ') if (alreadyAsserted.has(key)) { @@ -1672,8 +1673,8 @@ tap.test('workspace links are not affected by store resolved fix', async t => { const arb2 = new Arborist({ path: dir, registry, packumentCache: new Map(), cache }) await arb2.reify({ installStrategy: 'linked' }) - // Verify workspace is still correctly linked (workspace can resolve itself via self-link) - t.ok(setupRequire(path.join(dir, 'packages', 'mypkg'))('mypkg'), 'workspace is requireable via self-link after second install') + // Verify the workspace's own deps still resolve from inside the workspace after the second install + t.ok(setupRequire(path.join(dir, 'packages', 'mypkg'))('abbrev'), 'workspace dep is requireable from inside workspace after second install') t.ok(setupRequire(dir)('abbrev'), 'registry dep is requireable after second install') // Verify the diff has unchanged nodes (store entries are correctly matched) @@ -2405,6 +2406,50 @@ tap.test('undeclared workspaces are not hoisted to root node_modules', async t = 'ws-c cannot access ws-b (no dependency declared)') }) +tap.test('undeclared workspaces do not get a self-link in their own node_modules', async t => { + // Undeclared workspaces used to be self-symlinked into their own node_modules/. + // Cross-workspace dep links remain unaffected, and stale self-links from older npm versions are swept on the next install. + const graph = { + registry: [ + { name: 'abbrev', version: '1.0.0' }, + ], + root: { + name: 'myapp', + version: '1.0.0', + dependencies: { '@scope/a': '*' }, + }, + workspaces: [ + { name: '@scope/a', version: '1.0.0', dependencies: { '@scope/test': '*', abbrev: '1.0.0' } }, + { name: '@scope/test', version: '1.0.0' }, + ], + } + + const { dir, registry } = await getRepo(graph) + const cache = fs.mkdtempSync(`${getTempDir()}/test-`) + const arborist = new Arborist({ path: dir, registry, packumentCache: new Map(), cache }) + await arborist.reify({ installStrategy: 'linked' }) + + // No self-link inside the undeclared workspace's own node_modules + t.notOk(fs.lstatSync(path.join(dir, 'packages', '@scope', 'test', 'node_modules', '@scope', 'test'), { throwIfNoEntry: false }), + 'undeclared workspace has no self-link in its own node_modules') + + // Cross-workspace dep link still works: @scope/a depends on @scope/test + t.ok(fs.lstatSync(path.join(dir, 'packages', '@scope', 'a', 'node_modules', '@scope', 'test'), { throwIfNoEntry: false })?.isSymbolicLink(), + '@scope/a still has a symlink to @scope/test in its node_modules') + + // Stale self-link from an older npm version must be swept on a subsequent install + fs.mkdirSync(path.join(dir, 'packages', '@scope', 'test', 'node_modules', '@scope'), { recursive: true }) + fs.symlinkSync('../../..', path.join(dir, 'packages', '@scope', 'test', 'node_modules', '@scope', 'test')) + t.ok(fs.lstatSync(path.join(dir, 'packages', '@scope', 'test', 'node_modules', '@scope', 'test'), { throwIfNoEntry: false }), + 'stale self-link planted') + + const arb2 = new Arborist({ path: dir, registry, packumentCache: new Map(), cache }) + await arb2.reify({ installStrategy: 'linked' }) + + t.notOk(fs.lstatSync(path.join(dir, 'packages', '@scope', 'test', 'node_modules', '@scope', 'test'), { throwIfNoEntry: false }), + 'stale self-link is removed by the orphan sweep on the next install') +}) + tap.test('omit dev dependencies with linked strategy', async t => { const graph = { registry: [ diff --git a/workspaces/config/lib/definitions/definitions.js b/workspaces/config/lib/definitions/definitions.js index bbd4aae64d673..346e936c39021 100644 --- a/workspaces/config/lib/definitions/definitions.js +++ b/workspaces/config/lib/definitions/definitions.js @@ -154,7 +154,7 @@ const definitions = { defaultDescription: ` 'public' for new packages, existing packages it will not change the current level `, - type: [null, 'restricted', 'public'], + type: [null, 'restricted', 'public', 'private'], description: ` If you do not want your scoped package to be publicly viewable (and installable) set \`--access=restricted\`. @@ -165,8 +165,13 @@ const definitions = { packages. Specifying a value of \`restricted\` or \`public\` during publish will change the access for an existing package the same way that \`npm access set status\` would. + + The value \`private\` is an alias for \`restricted\`. `, - flatten, + flatten (key, obj, flatOptions) { + const value = obj[key] + flatOptions.access = value === 'private' ? 'restricted' : value + }, }), all: new Definition('all', { default: false, @@ -930,6 +935,29 @@ const definitions = { `, flatten, }), + // the global-ignore-file has its default defined outside of this module + 'global-ignore-file': new Definition('global-ignore-file', { + type: path, + default: '', + defaultDescription: ` + The global --prefix setting plus 'etc/npmignore'. For example, + '/usr/local/etc/npmignore' + `, + description: ` + An additional ignore file applied during \`npm pack\` and \`npm + publish\`, owned by the current user rather than the package. Patterns + follow the same syntax as a package's local \`.npmignore\` file. + Useful for keeping editor metadata (such as \`.idea/\` or \`*.iml\`) + and scratch directories out of every package you publish, without + adding them to each package's own ignore rules. + + The global rules apply in addition to a package's local \`.npmignore\`. + When a package uses a \`files\` field in its \`package.json\`, an entry + in \`files\` that contradicts a global rule (i.e., explicitly includes + a path the global rule would exclude) still wins. + `, + flatten, + }), 'global-style': new Definition('global-style', { default: false, type: Boolean, diff --git a/workspaces/config/lib/index.js b/workspaces/config/lib/index.js index 2aae7efbefb09..4121c2a7a3840 100644 --- a/workspaces/config/lib/index.js +++ b/workspaces/config/lib/index.js @@ -317,6 +317,24 @@ class Config { configurable: true, enumerable: true, }) + + // like globalconfig, the global-ignore-file default is computed from + // the current prefix. since prefix may be overridden after defaults + // load (via cli, env, or userconfig), expose a getter and only freeze + // to a value once explicitly set. + Object.defineProperty(data, 'global-ignore-file', { + get: () => resolve(this.#get('prefix'), 'etc/npmignore'), + set (value) { + Object.defineProperty(data, 'global-ignore-file', { + value, + configurable: true, + writable: true, + enumerable: true, + }) + }, + configurable: true, + enumerable: true, + }) } loadHome () { diff --git a/workspaces/config/tap-snapshots/test/type-description.js.test.cjs b/workspaces/config/tap-snapshots/test/type-description.js.test.cjs index e88013ae3b4e5..8a1f464cf4b92 100644 --- a/workspaces/config/tap-snapshots/test/type-description.js.test.cjs +++ b/workspaces/config/tap-snapshots/test/type-description.js.test.cjs @@ -15,6 +15,7 @@ Object { null, "restricted", "public", + "private", ], "all": Array [ "boolean value (true or false)", @@ -223,6 +224,9 @@ Object { "global": Array [ "boolean value (true or false)", ], + "global-ignore-file": Array [ + "valid filesystem path", + ], "global-style": Array [ "boolean value (true or false)", ], diff --git a/workspaces/config/test/definitions/definitions.js b/workspaces/config/test/definitions/definitions.js index f358899b17d9e..ad50d3e0111f2 100644 --- a/workspaces/config/test/definitions/definitions.js +++ b/workspaces/config/test/definitions/definitions.js @@ -33,6 +33,23 @@ t.test('basic flattening function camelCases from css-case', t => { t.end() }) +t.test('access flattening maps private to restricted', t => { + const definitions = mockDefs() + const flatPrivate = {} + definitions.access.flatten('access', { access: 'private' }, flatPrivate) + t.equal(flatPrivate.access, 'restricted', 'private is mapped to restricted') + const flatRestricted = {} + definitions.access.flatten('access', { access: 'restricted' }, flatRestricted) + t.equal(flatRestricted.access, 'restricted', 'restricted is passed through') + const flatPublic = {} + definitions.access.flatten('access', { access: 'public' }, flatPublic) + t.equal(flatPublic.access, 'public', 'public is passed through') + const flatNull = {} + definitions.access.flatten('access', { access: null }, flatNull) + t.equal(flatNull.access, null, 'null is passed through') + t.end() +}) + t.test('editor', t => { t.test('has EDITOR and VISUAL, use EDITOR', t => { mockGlobals(t, { 'process.env': { EDITOR: 'vim', VISUAL: 'mate' } }) @@ -1157,3 +1174,19 @@ t.test('dangerously-allow-all-scripts', t => { t.strictSame(flat, { dangerouslyAllowAllScripts: true }) t.end() }) + +t.test('global-ignore-file', t => { + const defs = mockDefs() + const def = defs['global-ignore-file'] + + t.ok(def, 'global-ignore-file definition is exported') + t.equal(def.type, require('../../lib/type-defs.js').path.type, 'is a path typed config') + t.equal(def.default, '', 'default value is empty (computed at load time)') + t.ok(/ignore/i.test(def.description), 'has a descriptive entry') + + const flat = {} + def.flatten('global-ignore-file', { 'global-ignore-file': '/path/to/npmignore' }, flat) + t.strictSame(flat, { globalIgnoreFile: '/path/to/npmignore' }, 'flattens to camelCase') + + t.end() +}) diff --git a/workspaces/config/test/index.js b/workspaces/config/test/index.js index b5f59aab5768c..1097243ffb194 100644 --- a/workspaces/config/test/index.js +++ b/workspaces/config/test/index.js @@ -412,7 +412,7 @@ loglevel = yolo ['warn', 'invalid config', 'omit="cucumber"', 'set in command line options'], ['warn', 'invalid config', 'Must be one or more of:', 'dev, optional, peer'], ['warn', 'invalid config', 'access="blueberry"', 'set in command line options'], - ['warn', 'invalid config', 'Must be one of:', 'null, restricted, public'], + ['warn', 'invalid config', 'Must be one of:', 'null, restricted, public, private'], ['warn', 'invalid config', 'multiple-numbers="what kind of fruit is not a number"', 'set in command line options'], ['warn', 'invalid config', 'Must be one or more', 'numeric value'], @@ -608,7 +608,7 @@ loglevel = yolo ['warn', 'invalid config', 'omit="cucumber"', 'set in command line options'], ['warn', 'invalid config', 'Must be one or more of:', 'dev, optional, peer'], ['warn', 'invalid config', 'access="blueberry"', 'set in command line options'], - ['warn', 'invalid config', 'Must be one of:', 'null, restricted, public'], + ['warn', 'invalid config', 'Must be one of:', 'null, restricted, public, private'], ['warn', 'invalid config', 'multiple-numbers="what kind of fruit is not a number"', 'set in command line options'], ['warn', 'invalid config', 'Must be one or more', 'numeric value'], @@ -2315,3 +2315,46 @@ t.test('CLI --min-release-age beats env npm_config_min_release_age', async t => 'CLI --min-release-age=3 overrides env npm_config_min_release_age=30' ) }) + +t.test('global-ignore-file defaults to ${prefix}/etc/npmignore', async t => { + const path = t.testdir() + const config = new Config({ + npmPath: `${path}/npm`, + env: {}, + argv: [process.execPath, __filename, '--prefix', `${path}/global`], + cwd: path, + definitions, + shorthands, + flatten, + }) + await config.load() + t.equal( + config.get('global-ignore-file'), + resolve(`${path}/global/etc/npmignore`), + 'computed from --prefix, mirrors globalconfig' + ) + t.equal(config.flat.globalIgnoreFile, resolve(`${path}/global/etc/npmignore`), 'flattens to camelCase') +}) + +t.test('global-ignore-file follows an explicit override', async t => { + const path = t.testdir() + const config = new Config({ + npmPath: `${path}/npm`, + env: {}, + argv: [ + process.execPath, __filename, + '--prefix', `${path}/global`, + '--global-ignore-file', `${path}/custom/.npmignore`, + ], + cwd: path, + definitions, + shorthands, + flatten, + }) + await config.load() + t.equal( + config.get('global-ignore-file'), + resolve(`${path}/custom/.npmignore`), + 'cli override wins over computed default' + ) +})