diff --git a/node_modules/@npmcli/query/lib/index.js b/node_modules/@npmcli/query/lib/index.js index 9373a4f7adbf0..c7888d5bb5de6 100644 --- a/node_modules/@npmcli/query/lib/index.js +++ b/node_modules/@npmcli/query/lib/index.js @@ -85,31 +85,57 @@ const fixupNestedPseudo = astNode => { transformAst(newRootNode) } -// :semver(, [selector], [function]) +// :semver(, [version|range|selector], [function]) +// note: the first or second parameter must be a static version or range const fixupSemverSpecs = astNode => { - // the first child node contains the version or range, most likely as a tag and a series of - // classes. we combine them into a single string here. this is the only required input. - const children = astNode.nodes.shift().nodes - const value = children.reduce((res, i) => `${res}${String(i)}`, '') - - // next, if we have 2 nodes left then the user called us with a total of 3. that means the - // last one tells us what specific semver function the user is requesting, so we pull that out - let semverFunc - if (astNode.nodes.length === 2) { + // if we have three nodes, the last is the semver function to use, pull that out first + if (astNode.nodes.length === 3) { const funcNode = astNode.nodes.pop().nodes[0] if (funcNode.type === 'tag') { - semverFunc = funcNode.value + astNode.semverFunc = funcNode.value + } else if (funcNode.type === 'string') { + // a string is always in some type of quotes, we don't want those so slice them off + astNode.semverFunc = funcNode.value.slice(1, -1) + } else { + // anything that isn't a tag or a string isn't a function name + throw Object.assign( + new Error('`:semver` pseudo-class expects a function name as last value'), + { code: 'ESEMVERFUNC' } + ) + } + } + + // now if we have 1 node, it's a static value + // istanbul ignore else + if (astNode.nodes.length === 1) { + const semverNode = astNode.nodes.pop() + astNode.semverValue = semverNode.nodes.reduce((res, next) => `${res}${String(next)}`, '') + } else if (astNode.nodes.length === 2) { + // and if we have two nodes, one of them is a static value and we need to determine which it is + for (let i = 0; i < astNode.nodes.length; ++i) { + const type = astNode.nodes[i].nodes[0].type + // the type of the first child may be combinator for ranges, such as >14 + if (type === 'tag' || type === 'combinator') { + const semverNode = astNode.nodes.splice(i, 1)[0] + astNode.semverValue = semverNode.nodes.reduce((res, next) => `${res}${String(next)}`, '') + astNode.semverPosition = i + break + } + } + + if (typeof astNode.semverValue === 'undefined') { + throw Object.assign( + new Error('`:semver` pseudo-class expects a static value in the first or second position'), + { code: 'ESEMVERVALUE' } + ) } } - // now if there's a node left, that node is our selector. since that is the last remaining - // child node, we call fixupAttr on ourselves so that the attribute selectors get parsed + // if we got here, the last remaining child should be attribute selector if (astNode.nodes.length === 1) { fixupAttr(astNode) } else { - // we weren't provided a selector, so we default to `[version]`. note, there's no default - // operator here. that's because we don't know yet if the user has provided us a version - // or range to assert against + // if we don't have a selector, we default to `[version]` astNode.attributeMatcher = { insensitive: false, attribute: 'version', @@ -118,8 +144,6 @@ const fixupSemverSpecs = astNode => { astNode.lookupProperties = [] } - astNode.semverFunc = semverFunc - astNode.semverValue = value astNode.nodes.length = 0 } diff --git a/node_modules/@npmcli/query/package.json b/node_modules/@npmcli/query/package.json index 1e4abd37656f6..5f9fb2744538a 100644 --- a/node_modules/@npmcli/query/package.json +++ b/node_modules/@npmcli/query/package.json @@ -1,6 +1,6 @@ { "name": "@npmcli/query", - "version": "3.0.0", + "version": "3.0.1", "description": "npm query parser and tools", "main": "lib/index.js", "scripts": { @@ -39,11 +39,12 @@ }, "templateOSS": { "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.", - "version": "4.5.1" + "version": "4.18.0", + "publish": true }, "devDependencies": { - "@npmcli/eslint-config": "^3.0.1", - "@npmcli/template-oss": "4.5.1", + "@npmcli/eslint-config": "^4.0.0", + "@npmcli/template-oss": "4.18.0", "tap": "^16.2.0" }, "dependencies": { diff --git a/package-lock.json b/package-lock.json index 2898980c3fa42..cdc10006ddd6b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2638,9 +2638,9 @@ } }, "node_modules/@npmcli/query": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/query/-/query-3.0.0.tgz", - "integrity": "sha512-MFNDSJNgsLZIEBVZ0Q9w9K7o07j5N4o4yjtdz2uEpuCZlXGMuPENiRaFYk0vRqAA64qVuUQwC05g27fRtfUgnA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/query/-/query-3.0.1.tgz", + "integrity": "sha512-0jE8iHBogf/+bFDj+ju6/UMLbJ39c8h6nSe6qile+dB7PJ0iV3gNqcb2vtt6WWCBrxv9uAjzUT/8vroluulidA==", "dependencies": { "postcss-selector-parser": "^6.0.10" }, @@ -17009,7 +17009,7 @@ "@npmcli/name-from-folder": "^2.0.0", "@npmcli/node-gyp": "^3.0.0", "@npmcli/package-json": "^5.0.0", - "@npmcli/query": "^3.0.0", + "@npmcli/query": "^3.0.1", "@npmcli/run-script": "^7.0.1", "bin-links": "^4.0.1", "cacache": "^18.0.0", diff --git a/workspaces/arborist/package.json b/workspaces/arborist/package.json index ab9c51e0cff79..b15f6bb983f13 100644 --- a/workspaces/arborist/package.json +++ b/workspaces/arborist/package.json @@ -11,7 +11,7 @@ "@npmcli/name-from-folder": "^2.0.0", "@npmcli/node-gyp": "^3.0.0", "@npmcli/package-json": "^5.0.0", - "@npmcli/query": "^3.0.0", + "@npmcli/query": "^3.0.1", "@npmcli/run-script": "^7.0.1", "bin-links": "^4.0.1", "cacache": "^18.0.0",