Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 7 additions & 9 deletions lib/commands/sbom.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,9 @@ class SBOM extends BaseCommand {
// Build the selector and query the tree for the list of nodes
const selector = this.#buildSelector({ wsNodes })
log.info('sbom', `Using dependency selector: ${selector}`)
const items = await tree.querySelectorAll(selector)
const omit = new Set(this.npm.flatOptions.omit)
const items = [...await tree.querySelectorAll(selector)]
.filter(node => !node.shouldOmit(omit))

const errors = items.flatMap(node => detectErrors(node))
if (errors.length) {
Expand All @@ -72,23 +74,19 @@ class SBOM extends BaseCommand {
return this.exec(args)
}

// Build the selector from all of the specified filter options
// Build the selector from the specified workspace options
#buildSelector ({ wsNodes }) {
let selector
const omit = this.npm.flatOptions.omit
const workspacesEnabled = this.npm.flatOptions.workspacesEnabled

// If omit is specified, omit all nodes and their children which match the specified selectors
const omits = omit.reduce((acc, o) => `${acc}:not(.${o})`, '')

if (!workspacesEnabled) {
// If workspaces are disabled, omit all workspace nodes and their children
selector = `:root > :not(.workspace)${omits},:root > :not(.workspace) *${omits},:extraneous`
selector = ':root > :not(.workspace),:root > :not(.workspace) *,:extraneous'
} else if (wsNodes && wsNodes.length > 0) {
// If one or more workspaces are selected, select only those workspaces and their children
selector = wsNodes.map(ws => `#${ws.name},#${ws.name} *${omits}`).join(',')
selector = wsNodes.map(ws => `#${ws.name},#${ws.name} *`).join(',')
} else {
selector = `:root *${omits},:extraneous`
selector = ':root *,:extraneous'
}

// Always include the root node
Expand Down
42 changes: 42 additions & 0 deletions test/lib/commands/sbom.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,48 @@ t.test('sbom', async t => {
t.matchSnapshot(result())
})

t.test('--omit dev keeps production dependencies also referenced as dev', async t => {
const config = {
'sbom-format': 'spdx',
omit: ['dev'],
}
const { result, sbom } = await mockSbom(t, {
config,
prefixDir: {
'package.json': JSON.stringify({
name: 'test-npm-sbom',
version: '1.0.0',
dependencies: {
foo: '^1.0.0',
},
devDependencies: {
chai: '^1.0.0',
},
}),
node_modules: {
foo: {
'package.json': JSON.stringify({
name: 'foo',
version: '1.0.0',
dependencies: {
chai: '^1.0.0',
},
}),
},
chai: {
'package.json': JSON.stringify({
name: 'chai',
version: '1.0.0',
}),
},
},
},
})
await sbom.exec([])
const packages = JSON.parse(result()).packages.map(pkg => pkg.name)
t.strictSame(packages, ['test-npm-sbom', 'chai', 'foo'])
})

t.test('--omit optional', async t => {
const config = {
'sbom-format': 'spdx',
Expand Down