npq 3.8.0 → 3.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/npq.mov +0 -0
- package/.github/npq.mp4 +0 -0
- package/.github/npq.png +0 -0
- package/.github/workflows/main.yml +2 -2
- package/README.md +18 -9
- package/__tests__/__fixtures__/test.marshall.js +5 -6
- package/__tests__/cli.test.js +110 -0
- package/__tests__/cliPrompt.test.js +409 -0
- package/__tests__/marshalls.base.test.js +1 -1
- package/__tests__/marshalls.classMethods.test.js +11 -14
- package/__tests__/marshalls.expiredDomains.test.js +2 -2
- package/__tests__/marshalls.provenance.test.js +181 -4
- package/__tests__/marshalls.repo.test.js +6 -6
- package/__tests__/marshalls.signatures.test.js +0 -4
- package/__tests__/marshalls.snyk.test.js +294 -0
- package/__tests__/marshalls.tasks.test.js +48 -24
- package/__tests__/marshalls.typosquatting.test.js +16 -9
- package/__tests__/marshalls.version-maturity.test.js +6 -6
- package/__tests__/packageRepoUtils.test.js +4 -4
- package/__tests__/reportResults.test.js +772 -0
- package/__tests__/scripts.test.js +2 -2
- package/bin/npq-hero.js +70 -20
- package/bin/npq.js +113 -21
- package/lib/cli.js +127 -24
- package/lib/helpers/cliPrompt.js +97 -0
- package/lib/helpers/cliSpinner.js +104 -0
- package/lib/helpers/cliSupportHandler.js +50 -7
- package/lib/helpers/packageRepoUtils.js +7 -2
- package/lib/helpers/promiseThrottler.js +96 -0
- package/lib/helpers/reportResults.js +304 -0
- package/lib/helpers/sourcePackages.js +36 -0
- package/lib/marshall.js +42 -65
- package/lib/marshalls/age.marshall.js +4 -3
- package/lib/marshalls/author.marshall.js +38 -9
- package/lib/marshalls/baseMarshall.js +9 -17
- package/lib/marshalls/deprecation.marshall.js +43 -0
- package/lib/marshalls/downloads.marshall.js +3 -3
- package/lib/marshalls/expiredDomains.marshall.js +7 -5
- package/lib/marshalls/index.js +110 -80
- package/lib/marshalls/license.marshall.js +3 -3
- package/lib/marshalls/newbin.marshall.js +1 -2
- package/lib/marshalls/provenance.marshall.js +152 -33
- package/lib/marshalls/repo.marshall.js +8 -7
- package/lib/marshalls/scripts.marshall.js +1 -1
- package/lib/marshalls/signatures.marshall.js +26 -2
- package/lib/marshalls/snyk.marshall.js +61 -15
- package/lib/marshalls/typosquatting.marshall.js +8 -5
- package/lib/marshalls/version-maturity.marshall.js +4 -4
- package/lib/marshallsDecomissioned/readme.marshall.js +2 -2
- package/package.json +16 -19
- package/scripts/postinstall.js +10 -11
- package/lib/cliCommons.js +0 -80
|
@@ -13,19 +13,19 @@ test('running marshall tasks succeeds', async () => {
|
|
|
13
13
|
})
|
|
14
14
|
|
|
15
15
|
const config = {
|
|
16
|
-
pkgs: ['express', 'semver'],
|
|
16
|
+
pkgs: [{ packageName: 'express' }, { packageName: 'semver' }],
|
|
17
17
|
packageRepoUtils: new PackageRepoUtilsMock()
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
expect(
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
20
|
+
const results = await marshalls.tasks(config)
|
|
21
|
+
|
|
22
|
+
expect(results[0]['test.marshall']).toEqual({
|
|
23
|
+
status: null,
|
|
24
|
+
errors: [],
|
|
25
|
+
warnings: [],
|
|
26
|
+
data: { express: 'mock data check', semver: 'mock data check' },
|
|
27
|
+
marshall: 'test.marshall',
|
|
28
|
+
categoryId: 'PackageHealth'
|
|
29
29
|
})
|
|
30
30
|
})
|
|
31
31
|
|
|
@@ -35,13 +35,12 @@ test('running marshall tasks fails', async () => {
|
|
|
35
35
|
})
|
|
36
36
|
|
|
37
37
|
const config = {
|
|
38
|
-
pkgs: ['express', 'dockly'],
|
|
38
|
+
pkgs: [{ packageName: 'express' }, { packageName: 'dockly' }],
|
|
39
39
|
packageRepoUtils: new PackageRepoUtilsMock()
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
marshalls: {
|
|
42
|
+
const mockedResults = [
|
|
43
|
+
{
|
|
45
44
|
'test.marshall': {
|
|
46
45
|
status: null,
|
|
47
46
|
errors: [{ pkg: 'dockly', message: 'simulating mock error' }],
|
|
@@ -49,12 +48,12 @@ test('running marshall tasks fails', async () => {
|
|
|
49
48
|
data: { express: 'mock data check' }
|
|
50
49
|
}
|
|
51
50
|
}
|
|
52
|
-
|
|
51
|
+
]
|
|
53
52
|
|
|
54
|
-
await expect(marshalls.tasks(config)).resolves.toMatchObject(
|
|
53
|
+
await expect(marshalls.tasks(config)).resolves.toMatchObject(mockedResults)
|
|
55
54
|
})
|
|
56
55
|
|
|
57
|
-
test('running marshall tasks
|
|
56
|
+
test('running marshall tasks includes an error when single package is not found', async () => {
|
|
58
57
|
const PackageRepoUtilsNotFoundMock = class Fake {
|
|
59
58
|
getPackageInfo() {
|
|
60
59
|
return Promise.resolve({ error: 'Not found' })
|
|
@@ -70,10 +69,20 @@ test('running marshall tasks throws error when single package is not found', asy
|
|
|
70
69
|
packageRepoUtils: new PackageRepoUtilsNotFoundMock()
|
|
71
70
|
}
|
|
72
71
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
72
|
+
const mockedResults = [
|
|
73
|
+
{
|
|
74
|
+
not_found: {
|
|
75
|
+
status: null,
|
|
76
|
+
errors: [{ pkg: 'nonexistent-package', message: 'Package not found' }],
|
|
77
|
+
warnings: [],
|
|
78
|
+
data: {},
|
|
79
|
+
marshall: 'not_found',
|
|
80
|
+
categoryId: 'PackageHealth'
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
]
|
|
84
|
+
|
|
85
|
+
await expect(marshalls.tasks(config)).resolves.toMatchObject(mockedResults)
|
|
77
86
|
})
|
|
78
87
|
|
|
79
88
|
test('running marshall tasks filters out not found packages when multiple packages provided', async () => {
|
|
@@ -100,7 +109,22 @@ test('running marshall tasks filters out not found packages when multiple packag
|
|
|
100
109
|
}
|
|
101
110
|
|
|
102
111
|
const result = await marshalls.tasks(config)
|
|
103
|
-
|
|
104
|
-
expect(result
|
|
105
|
-
|
|
112
|
+
|
|
113
|
+
expect(result[0]['not_found']).toEqual({
|
|
114
|
+
status: null,
|
|
115
|
+
errors: [{ pkg: 'nonexistent-package', message: 'Package not found' }],
|
|
116
|
+
warnings: [],
|
|
117
|
+
data: {},
|
|
118
|
+
marshall: 'not_found',
|
|
119
|
+
categoryId: 'PackageHealth'
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
expect(result[1]['test.marshall']).toEqual({
|
|
123
|
+
status: null,
|
|
124
|
+
errors: [],
|
|
125
|
+
warnings: [],
|
|
126
|
+
data: { express: 'mock data check', semver: 'mock data check' },
|
|
127
|
+
marshall: 'test.marshall',
|
|
128
|
+
categoryId: 'PackageHealth'
|
|
129
|
+
})
|
|
106
130
|
})
|
|
@@ -3,12 +3,13 @@ const TyposquattingMarshall = require('../lib/marshalls/typosquatting.marshall')
|
|
|
3
3
|
describe('Typosquatting Marshall', () => {
|
|
4
4
|
test('should remove duplicate entries from similar packages', async () => {
|
|
5
5
|
const typosquattingMarshall = new TyposquattingMarshall({
|
|
6
|
-
packageRepoUtils:
|
|
6
|
+
packageRepoUtils: {
|
|
7
|
+
isPackageInAllowList: jest.fn(() => {
|
|
8
|
+
return false // Simulate that the package is not in the allow list
|
|
9
|
+
})
|
|
10
|
+
}
|
|
7
11
|
})
|
|
8
12
|
|
|
9
|
-
// Mock the top packages data to include duplicates
|
|
10
|
-
const originalTopPackages = require('../data/top-packages.json')
|
|
11
|
-
|
|
12
13
|
// Create a test package that would match multiple similar packages
|
|
13
14
|
const pkg = {
|
|
14
15
|
packageName: 'ghtml' // This should match 'html' which appears multiple times in the data
|
|
@@ -21,9 +22,7 @@ describe('Typosquatting Marshall', () => {
|
|
|
21
22
|
} catch (error) {
|
|
22
23
|
// Check that the error message doesn't contain duplicate entries
|
|
23
24
|
const errorMessage = error.message
|
|
24
|
-
expect(errorMessage).toContain(
|
|
25
|
-
'Package name could be a typosquatting attempt for popular package(s):'
|
|
26
|
-
)
|
|
25
|
+
expect(errorMessage).toContain('Potential typosquatting with popular package(s):')
|
|
27
26
|
|
|
28
27
|
// Extract the package names from the error message
|
|
29
28
|
const packagesList = errorMessage.split('popular package(s): ')[1]
|
|
@@ -41,7 +40,11 @@ describe('Typosquatting Marshall', () => {
|
|
|
41
40
|
|
|
42
41
|
test('should not report typosquatting for packages in top packages list', async () => {
|
|
43
42
|
const typosquattingMarshall = new TyposquattingMarshall({
|
|
44
|
-
packageRepoUtils:
|
|
43
|
+
packageRepoUtils: {
|
|
44
|
+
isPackageInAllowList: jest.fn(() => {
|
|
45
|
+
return true
|
|
46
|
+
})
|
|
47
|
+
}
|
|
45
48
|
})
|
|
46
49
|
|
|
47
50
|
// Test with a package that exists in the top packages list
|
|
@@ -55,7 +58,11 @@ describe('Typosquatting Marshall', () => {
|
|
|
55
58
|
|
|
56
59
|
test('should not report typosquatting for packages with no similar matches', async () => {
|
|
57
60
|
const typosquattingMarshall = new TyposquattingMarshall({
|
|
58
|
-
packageRepoUtils:
|
|
61
|
+
packageRepoUtils: {
|
|
62
|
+
isPackageInAllowList: jest.fn(() => {
|
|
63
|
+
return false // Simulate that the package is not in the allow list
|
|
64
|
+
})
|
|
65
|
+
}
|
|
59
66
|
})
|
|
60
67
|
|
|
61
68
|
// Test with a package that has no similar matches
|
|
@@ -34,7 +34,7 @@ describe('Version Maturity Marshall', () => {
|
|
|
34
34
|
packageVersion: '1.0.0'
|
|
35
35
|
})
|
|
36
36
|
).rejects.toThrow(
|
|
37
|
-
'
|
|
37
|
+
'Detected a recently published version (published 2 hours ago) - consider waiting for community review'
|
|
38
38
|
)
|
|
39
39
|
})
|
|
40
40
|
|
|
@@ -61,7 +61,7 @@ describe('Version Maturity Marshall', () => {
|
|
|
61
61
|
packageVersion: '1.0.0'
|
|
62
62
|
})
|
|
63
63
|
).rejects.toThrow(
|
|
64
|
-
'
|
|
64
|
+
'Detected a recently published version (published 3 days ago) - consider waiting for community review'
|
|
65
65
|
)
|
|
66
66
|
})
|
|
67
67
|
|
|
@@ -88,7 +88,7 @@ describe('Version Maturity Marshall', () => {
|
|
|
88
88
|
packageVersion: '1.0.0'
|
|
89
89
|
})
|
|
90
90
|
).rejects.toThrow(
|
|
91
|
-
'
|
|
91
|
+
'Detected a recently published version (published 1 day ago) - consider waiting for community review'
|
|
92
92
|
)
|
|
93
93
|
})
|
|
94
94
|
|
|
@@ -135,7 +135,7 @@ describe('Version Maturity Marshall', () => {
|
|
|
135
135
|
packageName: 'test-package',
|
|
136
136
|
packageVersion: '1.0.0'
|
|
137
137
|
})
|
|
138
|
-
).rejects.toThrow('
|
|
138
|
+
).rejects.toThrow('Could not determine package version information')
|
|
139
139
|
})
|
|
140
140
|
|
|
141
141
|
test('should throw error when version release date is missing', async () => {
|
|
@@ -157,7 +157,7 @@ describe('Version Maturity Marshall', () => {
|
|
|
157
157
|
packageName: 'test-package',
|
|
158
158
|
packageVersion: '1.0.0'
|
|
159
159
|
})
|
|
160
|
-
).rejects.toThrow('
|
|
160
|
+
).rejects.toThrow('Could not determine release date for version 1.0.0')
|
|
161
161
|
})
|
|
162
162
|
|
|
163
163
|
test('should handle version aliases correctly', async () => {
|
|
@@ -188,7 +188,7 @@ describe('Version Maturity Marshall', () => {
|
|
|
188
188
|
packageVersion: 'latest'
|
|
189
189
|
})
|
|
190
190
|
).rejects.toThrow(
|
|
191
|
-
'
|
|
191
|
+
'Detected a recently published version (published 2 days ago) - consider waiting for community review'
|
|
192
192
|
)
|
|
193
193
|
})
|
|
194
194
|
})
|
|
@@ -157,7 +157,7 @@ test('repo utils returns valid semver for different cases of version asked', asy
|
|
|
157
157
|
expect(result).toEqual('3.1.0')
|
|
158
158
|
|
|
159
159
|
await expect(packageRepoUtils.getSemVer(packageName, 'next')).rejects.toThrow(
|
|
160
|
-
'
|
|
160
|
+
'Could not find dist-tag next for package testPackage'
|
|
161
161
|
)
|
|
162
162
|
})
|
|
163
163
|
|
|
@@ -186,12 +186,12 @@ test('repo utils resolves semver ranges by finding the highest satisfying versio
|
|
|
186
186
|
|
|
187
187
|
// Test invalid semver range that doesn't match any version
|
|
188
188
|
await expect(packageRepoUtils.getSemVer(packageName, '^10.0.0')).rejects.toThrow(
|
|
189
|
-
'
|
|
189
|
+
'Could not find dist-tag ^10.0.0 for package testPackage'
|
|
190
190
|
)
|
|
191
191
|
|
|
192
192
|
// Test invalid semver range with version 2 (no 2.x versions in mock)
|
|
193
193
|
await expect(packageRepoUtils.getSemVer(packageName, '2')).rejects.toThrow(
|
|
194
|
-
'
|
|
194
|
+
'Could not find dist-tag 2 for package testPackage'
|
|
195
195
|
)
|
|
196
196
|
})
|
|
197
197
|
|
|
@@ -246,6 +246,6 @@ test('repo utils resolves semver ranges with multiple versions', async () => {
|
|
|
246
246
|
|
|
247
247
|
// Test that non-existent major versions still fail appropriately
|
|
248
248
|
await expect(packageRepoUtils.getSemVer(packageName, '10')).rejects.toThrow(
|
|
249
|
-
'
|
|
249
|
+
'Could not find dist-tag 10 for package @astrojs/vue'
|
|
250
250
|
)
|
|
251
251
|
})
|