@@ -15,6 +15,19 @@ import type { CliCommandConfig } from '../../utils/meow-with-subcommands.mts'
15
15
const { DRY_RUN_BAILING_NOW } = constants
16
16
17
17
const ECOSYSTEMS = new Set ( [ 'gem' , 'golang' , 'maven' , 'npm' , 'nuget' , 'pypi' ] )
18
+ const TYPE_FILTERS = new Set ( [
19
+ 'anom' ,
20
+ 'c' ,
21
+ 'fp' ,
22
+ 'joke' ,
23
+ 'mal' ,
24
+ 'secret' ,
25
+ 'spy' ,
26
+ 'tp' ,
27
+ 'typo' ,
28
+ 'u' ,
29
+ 'vuln' ,
30
+ ] )
18
31
19
32
const config : CliCommandConfig = {
20
33
commandName : 'threat-feed' ,
@@ -30,13 +43,11 @@ const config: CliCommandConfig = {
30
43
} ,
31
44
eco : {
32
45
type : 'string' ,
33
- shortFlag : 'e' ,
34
46
default : '' ,
35
47
description : 'Only show threats for a particular ecosystem' ,
36
48
} ,
37
49
filter : {
38
50
type : 'string' ,
39
- shortFlag : 'f' ,
40
51
default : 'mal' ,
41
52
description : 'Filter what type of threats to return' ,
42
53
} ,
@@ -53,7 +64,6 @@ const config: CliCommandConfig = {
53
64
} ,
54
65
page : {
55
66
type : 'string' ,
56
- shortFlag : 'p' ,
57
67
default : '1' ,
58
68
description : 'Page token' ,
59
69
} ,
@@ -65,10 +75,12 @@ const config: CliCommandConfig = {
65
75
} ,
66
76
pkg : {
67
77
type : 'string' ,
78
+ default : '' ,
68
79
description : 'Filter by this package name' ,
69
80
} ,
70
81
version : {
71
82
type : 'string' ,
83
+ default : '' ,
72
84
description : 'Filter by this package version' ,
73
85
} ,
74
86
} ,
@@ -115,11 +127,20 @@ const config: CliCommandConfig = {
115
127
doubt, look at the threat-feed and see the names in the name/version
116
128
column. That's what you want to search for.
117
129
130
+ You can put filters as args instead, we'll try to match the strings with the
131
+ correct filter type but since this would not allow you to search for a package
132
+ called "mal", you can also specify the filters through flags.
133
+
134
+ First arg that matches a typo, eco, or version enum is used as such. First arg
135
+ that matches none of them becomes the package name filter. Rest is ignored.
136
+
137
+ Note: The version filter is a prefix search, pkg name is a substring search.
138
+
118
139
Examples
119
140
$ ${ command }
120
141
$ ${ command } maven --json
121
142
$ ${ command } typo
122
- $ ${ command } npm joke --perPage=5 --page=2 --direction=asc
143
+ $ ${ command } npm joke 1.0.0 --perPage=5 --page=2 --direction=asc
123
144
` ,
124
145
}
125
146
@@ -143,17 +164,57 @@ async function run(
143
164
144
165
const {
145
166
dryRun,
167
+ eco,
146
168
interactive,
147
169
json,
148
170
markdown,
149
171
org : orgFlag ,
150
172
pkg,
173
+ type : typef ,
151
174
version,
152
175
} = cli . flags
153
176
const outputKind = getOutputKind ( json , markdown )
154
- const [ filter1 = '' , filter2 = '' ] = cli . input
155
- const ecoFilter = ECOSYSTEMS . has ( filter1 ) ? filter1 : ''
156
- const typeFilter = ( ecoFilter ? filter2 : filter1 ) || ''
177
+
178
+ const argSet = new Set ( cli . input )
179
+ let ecoFilter = String ( eco || '' )
180
+ let versionFilter = String ( version || '' )
181
+ let typeFilter = String ( typef || '' )
182
+ let nameFilter = String ( pkg || '' )
183
+ cli . input . some ( str => {
184
+ if ( ECOSYSTEMS . has ( str ) ) {
185
+ ecoFilter = str
186
+ argSet . delete ( str )
187
+ return true
188
+ }
189
+ } )
190
+ cli . input . some ( str => {
191
+ if ( / ^ v ? \d + \. \d + \. \d + $ / . test ( str ) ) {
192
+ versionFilter = str
193
+ argSet . delete ( str )
194
+ return true
195
+ }
196
+ } )
197
+ cli . input . some ( str => {
198
+ if ( TYPE_FILTERS . has ( str ) ) {
199
+ typeFilter = str
200
+ argSet . delete ( str )
201
+ return true
202
+ }
203
+ } )
204
+ const haves = new Set ( [ ecoFilter , versionFilter , typeFilter ] )
205
+ cli . input . some ( str => {
206
+ if ( ! haves . has ( str ) ) {
207
+ nameFilter = str
208
+ argSet . delete ( str )
209
+ return true
210
+ }
211
+ } )
212
+
213
+ if ( argSet . size ) {
214
+ logger . info (
215
+ `Warning: ignoring these excessive args: ${ Array . from ( argSet ) . join ( ', ' ) } ` ,
216
+ )
217
+ }
157
218
158
219
const [ orgSlug ] = await determineOrgSlug (
159
220
String ( orgFlag || '' ) ,
@@ -172,14 +233,6 @@ async function run(
172
233
pass : 'ok' ,
173
234
fail : 'missing' ,
174
235
} ,
175
- {
176
- nook : true ,
177
- test : ! ! typeFilter || ! filter2 ,
178
- message :
179
- 'Second arg should only be given with first arg being a valid ecosystem' ,
180
- pass : 'ok' ,
181
- fail : 'first arg was not ecosystem and second arg received too' ,
182
- } ,
183
236
{
184
237
nook : true ,
185
238
test : ! json || ! markdown ,
@@ -213,7 +266,7 @@ async function run(
213
266
orgSlug,
214
267
page : String ( cli . flags [ 'page' ] || '1' ) ,
215
268
perPage : Number ( cli . flags [ 'perPage' ] ) || 30 ,
216
- pkg : String ( pkg || '' ) ,
217
- version : String ( version || '' ) ,
269
+ pkg : nameFilter ,
270
+ version : versionFilter ,
218
271
} )
219
272
}
0 commit comments