Skip to content

Commit b70fad2

Browse files
committed
feat: use isSecurityHeld included in algolia api response
1 parent 146ba25 commit b70fad2

File tree

5 files changed

+103
-17
lines changed

5 files changed

+103
-17
lines changed

app/composables/npm/useAlgoliaSearch.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ interface AlgoliaHit {
5050
deprecated: boolean | string
5151
isDeprecated: boolean
5252
license: string | null
53+
isSecurityHeld: boolean
5354
}
5455

5556
const ATTRIBUTES_TO_RETRIEVE = [
@@ -67,6 +68,7 @@ const ATTRIBUTES_TO_RETRIEVE = [
6768
'deprecated',
6869
'isDeprecated',
6970
'license',
71+
'isSecurityHeld',
7072
]
7173

7274
const EXISTENCE_CHECK_ATTRS = ['name']
@@ -90,6 +92,7 @@ function hitToSearchResult(hit: AlgoliaHit): NpmSearchResult {
9092
email: owner.email,
9193
}))
9294
: [],
95+
isSecurityHeld: hit.isSecurityHeld,
9396
},
9497
searchScore: 0,
9598
downloads: {

app/pages/search.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,8 @@ const visibleResults = computed(() => {
9494
9595
let objects = raw.objects
9696
97-
// Filter out "Security holding package" package takendown by npm registory
98-
objects = objects.filter(r => r.package.repository?.url !== 'npm/security-holder')
97+
// Filter out "Security holding package" packages taken down by npm registry
98+
objects = objects.filter(r => !r.package.isSecurityHeld)
9999
100100
// Filter out platform-specific packages if setting is enabled
101101
if (settings.value.hidePlatformPackages) {

shared/types/npm-registry.ts

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,8 @@ export interface NpmSearchPackage {
189189
publisher?: NpmSearchPublisher
190190
maintainers?: NpmPerson[]
191191
license?: string
192-
repository?: NpmSearchRepository
192+
/** Algolia-only: package is an npm-owned security-holder takedown */
193+
isSecurityHeld?: boolean
193194
}
194195

195196
/**
@@ -306,20 +307,6 @@ export interface NpmTrustedPublisher {
306307
ciConfigPath?: string
307308
}
308309

309-
/**
310-
* Repository types
311-
* Note: Not covered by @npm/types
312-
*/
313-
export interface NpmSearchRepository {
314-
type: 'git'
315-
url: string
316-
project: string
317-
user: string
318-
host: string
319-
path: string
320-
branch: string
321-
}
322-
323310
/**
324311
* jsDelivr API Types
325312
* Used for package file browsing
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
[
2+
{
3+
"name": "vuln-npm",
4+
"downloadsLast30Days": 0,
5+
"downloadsRatio": 0,
6+
"popular": false,
7+
"version": "0.0.1-security",
8+
"description": "security holding package",
9+
"repository": {
10+
"type": "git",
11+
"url": "npm/security-holder",
12+
"project": "security-holder",
13+
"user": "npm",
14+
"host": "github.com",
15+
"path": "",
16+
"branch": "master"
17+
},
18+
"deprecated": false,
19+
"isDeprecated": false,
20+
"isSecurityHeld": true,
21+
"homepage": null,
22+
"license": null,
23+
"keywords": [],
24+
"modified": 1692592458394,
25+
"owners": [
26+
{
27+
"email": "npm@npmjs.com",
28+
"name": "npm",
29+
"avatar": "https://gravatar.com/avatar/46d8d00e190be647053f7d97fd0478e4",
30+
"link": "https://www.npmjs.com/~npm"
31+
}
32+
],
33+
"objectID": "vuln-npm"
34+
},
35+
{
36+
"name": "npmx-connector",
37+
"downloadsLast30Days": 1047,
38+
"downloadsRatio": 0,
39+
"popular": false,
40+
"version": "0.9.0",
41+
"description": "Local connector for npmx.dev - enables authenticated npm operations from the web UI",
42+
"repository": {
43+
"type": "git",
44+
"url": "https://github.com/npmx-dev/npmx.dev",
45+
"project": "npmx.dev",
46+
"user": "npmx-dev",
47+
"host": "github.com",
48+
"path": "",
49+
"head": "1f574e52f494032683c1aec7f64f6de72d4413a0",
50+
"branch": "1f574e52f494032683c1aec7f64f6de72d4413a0"
51+
},
52+
"deprecated": false,
53+
"isDeprecated": false,
54+
"isSecurityHeld": false,
55+
"homepage": "https://npmx.dev",
56+
"license": "MIT",
57+
"keywords": [],
58+
"modified": 1776194979856,
59+
"owners": [
60+
{
61+
"name": "danielroe",
62+
"email": "daniel@roe.dev",
63+
"avatar": "https://gravatar.com/avatar/f366ee6556b7307a1a2a253c8fb842ca",
64+
"link": "https://www.npmjs.com/~danielroe"
65+
}
66+
],
67+
"objectID": "npmx-connector"
68+
}
69+
]
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { describe, expect, it, vi } from 'vitest'
2+
import fixture from '~~/test/fixtures/algolia/search/security-holder.json'
3+
4+
const mockSearch = vi.fn()
5+
vi.mock('algoliasearch/lite', () => ({
6+
liteClient: () => ({ search: mockSearch }),
7+
}))
8+
9+
describe('useAlgoliaSearch', () => {
10+
it('maps isSecurityHeld through to NpmSearchResult.package', async () => {
11+
mockSearch.mockResolvedValue({
12+
results: [{ hits: fixture, nbHits: fixture.length }],
13+
})
14+
15+
const { search } = useAlgoliaSearch()
16+
const { objects } = await search('')
17+
18+
const bad = objects.find(o => o.package.name === 'vuln-npm')
19+
const good = objects.find(o => o.package.name === 'npmx-connector')
20+
21+
expect(bad?.package.isSecurityHeld).toBe(true)
22+
expect(good?.package.isSecurityHeld).toBe(false)
23+
24+
const filtered = objects.filter(o => !o.package.isSecurityHeld).map(o => o.package.name)
25+
expect(filtered).toEqual(['npmx-connector'])
26+
})
27+
})

0 commit comments

Comments
 (0)