npq 3.10.1 → 3.11.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.
Files changed (46) hide show
  1. package/package.json +27 -20
  2. package/.editorconfig +0 -49
  3. package/.github/ISSUE_TEMPLATE.md +0 -32
  4. package/.github/Logo Horizontal.png +0 -0
  5. package/.github/Logo Vertical.png +0 -0
  6. package/.github/Logo.png +0 -0
  7. package/.github/PULL_REQUEST_TEMPLATE.md +0 -35
  8. package/.github/npq-demo-1.gif +0 -0
  9. package/.github/npq-demo-1.png +0 -0
  10. package/.github/npq-demo.gif +0 -0
  11. package/.github/npq.mov +0 -0
  12. package/.github/npq.mp4 +0 -0
  13. package/.github/npq.png +0 -0
  14. package/.github/workflows/automerge.yml +0 -39
  15. package/.github/workflows/main.yml +0 -58
  16. package/.husky/commit-msg +0 -4
  17. package/.husky/post-merge +0 -4
  18. package/.husky/pre-commit +0 -4
  19. package/.husky/pre-push +0 -4
  20. package/.prettierrc.js +0 -9
  21. package/CHANGELOG.md +0 -27
  22. package/CODE_OF_CONDUCT.md +0 -73
  23. package/CONTRIBUTING.md +0 -55
  24. package/SECURITY.md +0 -23
  25. package/__tests__/__fixtures__/test.marshall.js +0 -58
  26. package/__tests__/cli.parser.test.js +0 -121
  27. package/__tests__/cli.test.js +0 -110
  28. package/__tests__/cliPrompt.test.js +0 -409
  29. package/__tests__/env-var-integration.test.js +0 -109
  30. package/__tests__/marshalls.base.test.js +0 -113
  31. package/__tests__/marshalls.classMethods.test.js +0 -34
  32. package/__tests__/marshalls.expiredDomains.test.js +0 -100
  33. package/__tests__/marshalls.newBin.test.js +0 -441
  34. package/__tests__/marshalls.provenance.test.js +0 -383
  35. package/__tests__/marshalls.repo.test.js +0 -126
  36. package/__tests__/marshalls.signatures.test.js +0 -132
  37. package/__tests__/marshalls.snyk.test.js +0 -294
  38. package/__tests__/marshalls.tasks.test.js +0 -130
  39. package/__tests__/marshalls.typosquatting.test.js +0 -76
  40. package/__tests__/marshalls.version-maturity.test.js +0 -194
  41. package/__tests__/mocks/registryPackageOk.mock.json +0 -146
  42. package/__tests__/mocks/registryPackageUnpublished.mock.json +0 -31
  43. package/__tests__/packageManager.test.js +0 -93
  44. package/__tests__/packageRepoUtils.test.js +0 -251
  45. package/__tests__/reportResults.test.js +0 -772
  46. package/__tests__/scripts.test.js +0 -146
@@ -1,109 +0,0 @@
1
- // __tests__/env-var-integration.test.js
2
-
3
- // Test the NPQ_PKG_MGR environment variable functionality
4
- // This tests the key logic change: process.env.NPQ_PKG_MGR || values.packageManager || values.pkgMgr || 'npm'
5
-
6
- const packageManager = require('../lib/packageManager')
7
-
8
- const childProcess = require('child_process')
9
-
10
- jest.mock('child_process', () => {
11
- return {
12
- spawn: jest.fn((cmd, options) => {
13
- return { pid: 12345 }
14
- })
15
- }
16
- })
17
-
18
- describe('NPQ_PKG_MGR Environment Variable Integration', () => {
19
- let originalNPQ_PKG_MGR
20
-
21
- beforeEach(() => {
22
- originalNPQ_PKG_MGR = process.env.NPQ_PKG_MGR
23
- delete process.env.NPQ_PKG_MGR
24
- childProcess.spawn.mockClear()
25
- })
26
-
27
- afterEach(() => {
28
- if (originalNPQ_PKG_MGR !== undefined) {
29
- process.env.NPQ_PKG_MGR = originalNPQ_PKG_MGR
30
- } else {
31
- delete process.env.NPQ_PKG_MGR
32
- }
33
- })
34
-
35
- test('package manager process should handle pnpm correctly', async () => {
36
- process.argv = ['node', 'npq', 'install', 'fastify']
37
-
38
- // Test that the package manager can spawn pnpm (which would be passed from CLI parsing)
39
- await packageManager.process('pnpm')
40
-
41
- expect(childProcess.spawn).toHaveBeenCalledWith('pnpm install fastify', {
42
- stdio: 'inherit',
43
- shell: true
44
- })
45
- })
46
-
47
- test('package manager process should handle yarn correctly', async () => {
48
- process.argv = ['node', 'npq', 'install', 'express', 'lodash']
49
-
50
- await packageManager.process('yarn')
51
-
52
- expect(childProcess.spawn).toHaveBeenCalledWith('yarn install express lodash', {
53
- stdio: 'inherit',
54
- shell: true
55
- })
56
- })
57
-
58
- test('package manager process should handle various package managers', async () => {
59
- const packageManagers = ['npm', 'yarn', 'pnpm', 'bun']
60
-
61
- for (const pm of packageManagers) {
62
- process.argv = ['node', 'npq', 'install', 'test-package']
63
-
64
- await packageManager.process(pm)
65
-
66
- expect(childProcess.spawn).toHaveBeenCalledWith(`${pm} install test-package`, {
67
- stdio: 'inherit',
68
- shell: true
69
- })
70
-
71
- childProcess.spawn.mockClear()
72
- }
73
- })
74
-
75
- test('should demonstrate NPQ_PKG_MGR environment variable precedence logic', () => {
76
- // This test documents the specific logic that was implemented:
77
- // packageManager: process.env.NPQ_PKG_MGR || values.packageManager || values.pkgMgr || 'npm'
78
-
79
- // Test 1: Environment variable takes precedence
80
- process.env.NPQ_PKG_MGR = 'pnpm'
81
- const values1 = { packageManager: 'yarn', pkgMgr: 'npm' }
82
- const result1 = process.env.NPQ_PKG_MGR || values1.packageManager || values1.pkgMgr || 'npm'
83
- expect(result1).toBe('pnpm')
84
-
85
- // Test 2: Falls back to packageManager when env var not set
86
- delete process.env.NPQ_PKG_MGR
87
- const values2 = { packageManager: 'yarn', pkgMgr: 'npm' }
88
- const result2 = process.env.NPQ_PKG_MGR || values2.packageManager || values2.pkgMgr || 'npm'
89
- expect(result2).toBe('yarn')
90
-
91
- // Test 3: Falls back to pkgMgr when env var and packageManager not set
92
- delete process.env.NPQ_PKG_MGR
93
- const values3 = { pkgMgr: 'pnpm' }
94
- const result3 = process.env.NPQ_PKG_MGR || values3.packageManager || values3.pkgMgr || 'npm'
95
- expect(result3).toBe('pnpm')
96
-
97
- // Test 4: Falls back to npm default when nothing is set
98
- delete process.env.NPQ_PKG_MGR
99
- const values4 = {}
100
- const result4 = process.env.NPQ_PKG_MGR || values4.packageManager || values4.pkgMgr || 'npm'
101
- expect(result4).toBe('npm')
102
-
103
- // Test 5: Empty string environment variable falls back to CLI options
104
- process.env.NPQ_PKG_MGR = ''
105
- const values5 = { packageManager: 'yarn' }
106
- const result5 = process.env.NPQ_PKG_MGR || values5.packageManager || values5.pkgMgr || 'npm'
107
- expect(result5).toBe('yarn')
108
- })
109
- })
@@ -1,113 +0,0 @@
1
- const TestMarshall = require('./__fixtures__/test.marshall')
2
- const TEST_MARSHALL_NAME = 'test.marshall'
3
- const BaseMarshall = require('../lib/marshalls/baseMarshall')
4
-
5
- test('base marshall implemented isEnabled', async () => {
6
- const testMarshall = new TestMarshall({
7
- packageRepoUtils: null
8
- })
9
-
10
- expect(testMarshall.isEnabled()).toBeTruthy()
11
- })
12
-
13
- test('checkPackage returns validation data if it was a success', async () => {
14
- const testMarshall = new TestMarshall({
15
- packageRepoUtils: null
16
- })
17
-
18
- const ctx = {
19
- marshalls: {
20
- [TEST_MARSHALL_NAME]: {
21
- data: {}
22
- }
23
- }
24
- }
25
-
26
- const result = await testMarshall.checkPackage({ packageName: 'express' }, ctx, {})
27
- expect(result).toEqual('validation-result')
28
- })
29
-
30
- test('checkPackage sets the error property if the validation failed', async () => {
31
- const testMarshall = new TestMarshall({
32
- packageRepoUtils: null
33
- })
34
-
35
- const pkg = {
36
- packageString: 'trojan'
37
- }
38
-
39
- const ctx = {
40
- marshalls: {
41
- [TEST_MARSHALL_NAME]: {
42
- data: {}
43
- }
44
- }
45
- }
46
-
47
- testMarshall.init(ctx)
48
- await testMarshall.checkPackage(pkg, ctx, {})
49
- expect(ctx.marshalls[TEST_MARSHALL_NAME].errors[0].pkg).toEqual(pkg.packageString)
50
- })
51
-
52
- test('setError sets the errors properly', () => {
53
- const testMarshall = new TestMarshall({
54
- packageRepoUtils: null
55
- })
56
-
57
- const ctx = {
58
- marshalls: {
59
- [TEST_MARSHALL_NAME]: {
60
- data: {}
61
- }
62
- }
63
- }
64
- const err = {
65
- pkg: 'test',
66
- message: 'error message'
67
- }
68
-
69
- testMarshall.init(ctx)
70
- testMarshall.setMessage(err)
71
- expect(ctx.marshalls[TEST_MARSHALL_NAME].errors.length).toEqual(1)
72
- expect(ctx.marshalls[TEST_MARSHALL_NAME].errors[0]).toEqual(err)
73
- })
74
-
75
- test('setWarning sets the warnings properly', () => {
76
- const testMarshall = new TestMarshall({
77
- packageRepoUtils: null
78
- })
79
-
80
- const ctx = {
81
- marshalls: {
82
- [TEST_MARSHALL_NAME]: {
83
- data: {}
84
- }
85
- }
86
- }
87
- const warn = {
88
- pkg: 'test',
89
- message: 'warning message'
90
- }
91
-
92
- testMarshall.init(ctx)
93
-
94
- testMarshall.setMessage(warn, true)
95
- expect(ctx.marshalls[TEST_MARSHALL_NAME].warnings.length).toEqual(1)
96
- expect(ctx.marshalls[TEST_MARSHALL_NAME].warnings[0]).toEqual(warn)
97
- })
98
-
99
- test('base marshall implemented isEnabled', async () => {
100
- const testMarshall = new BaseMarshall({
101
- packageRepoUtils: null
102
- })
103
-
104
- testMarshall.validate = jest.fn(() => {
105
- return Promise.reject(new Error('some mock error'))
106
- })
107
-
108
- const ctx = { pkgs: ['pkg1'], marshalls: {} }
109
- const task = {}
110
- testMarshall.init(ctx, task)
111
- const result = await testMarshall.run(ctx, task)
112
- expect(result).toStrictEqual([undefined])
113
- })
@@ -1,34 +0,0 @@
1
- beforeEach(() => {
2
- jest.resetModules()
3
- })
4
-
5
- test('collecting marshalls resolves with files array', async () => {
6
- const marshalls = require('../lib/marshalls')
7
-
8
- const marshallFiles = await marshalls.collectMarshalls()
9
- expect(marshallFiles.length).toBeGreaterThan(0)
10
- expect(marshallFiles.every((file) => file.endsWith('.marshall.js'))).toBe(true)
11
- })
12
-
13
- test('collecting marshalls handles directory read errors', async () => {
14
- const fs = require('node:fs')
15
- const marshalls = require('../lib/marshalls')
16
-
17
- // Mock fs.promises.readdir to throw an error
18
- const originalReaddir = fs.promises.readdir
19
- fs.promises.readdir = jest.fn().mockRejectedValue(new Error('Directory read error'))
20
-
21
- await expect(marshalls.collectMarshalls()).rejects.toThrow('Directory read error')
22
-
23
- // Restore original function
24
- fs.promises.readdir = originalReaddir
25
- })
26
-
27
- test('build marshalls without any should throw error', () => {
28
- const marshalls = require('../lib/marshalls')
29
-
30
- expect(marshalls.buildMarshallTasks([])).rejects.toEqual(expect.any(Error))
31
- expect(marshalls.buildMarshallTasks({})).rejects.toEqual(expect.any(Error))
32
- expect(marshalls.buildMarshallTasks(5)).rejects.toEqual(expect.any(Error))
33
- expect(marshalls.buildMarshallTasks('something')).rejects.toEqual(expect.any(Error))
34
- })
@@ -1,100 +0,0 @@
1
- const ExpiredDomainsMarshall = require('../lib/marshalls/expiredDomains.marshall')
2
-
3
- const testMarshall = new ExpiredDomainsMarshall({
4
- packageRepoUtils: {
5
- getPackageInfo: (pkgInfo) => {
6
- return new Promise((resolve) => {
7
- resolve(pkgInfo)
8
- })
9
- }
10
- }
11
- })
12
-
13
- describe('Expired domains test suites', () => {
14
- beforeEach(() => {
15
- jest.clearAllMocks()
16
- jest.resetAllMocks()
17
- })
18
-
19
- test('has the right title', async () => {
20
- expect(testMarshall.title()).toEqual('Detecting expired domains for authors account...')
21
- })
22
-
23
- test('throws the right error when an email domain cant be verified', async () => {
24
- const nonExistentEmailAddress =
25
- 'liran.tal+test1234@somenonexistentdomainongoogle109dubv98g39ujasdasda.com'
26
- const pkgData = {
27
- packageName: {
28
- 'dist-tags': {
29
- latest: '1.0.0'
30
- },
31
- versions: {
32
- '1.0.0': {
33
- maintainers: [
34
- { name: 'lirantal', email: 'liran.tal@gmail.com' },
35
- {
36
- name: 'lirantal_test_user',
37
- email: nonExistentEmailAddress
38
- }
39
- ]
40
- }
41
- }
42
- }
43
- }
44
-
45
- await expect(testMarshall.validate(pkgData)).rejects.toThrow(
46
- /Detected expired domain can be abused for account takeover/
47
- )
48
- })
49
-
50
- test('if email hostname is empty then show an unknown message', async () => {
51
- const nonExistentEmailAddress = ''
52
- const pkgData = {
53
- packageName: {
54
- 'dist-tags': {
55
- latest: '1.0.0'
56
- },
57
- versions: {
58
- '1.0.0': {
59
- maintainers: [
60
- { name: 'lirantal', email: 'liran.tal@gmail.com' },
61
- {
62
- name: 'lirantal_test_user',
63
- email: nonExistentEmailAddress
64
- }
65
- ]
66
- }
67
- }
68
- }
69
- }
70
-
71
- await expect(testMarshall.validate(pkgData)).rejects.toThrow(
72
- /Detected expired domain can be abused for account takeover: <unknown>/
73
- )
74
- })
75
-
76
- test('does not throw any errors if the domain resolves well', async () => {
77
- jest.setTimeout(15000)
78
-
79
- const pkgData = {
80
- packageName: {
81
- 'dist-tags': {
82
- latest: '1.0.0'
83
- },
84
- versions: {
85
- '1.0.0': {
86
- maintainers: [
87
- { name: 'lirantal', email: 'liran.tal@gmail.com' },
88
- {
89
- name: 'lirantal_test_user',
90
- email: 'liran.tal@gmail.com'
91
- }
92
- ]
93
- }
94
- }
95
- }
96
- }
97
-
98
- await expect(testMarshall.validate(pkgData)).resolves.toEqual(expect.anything())
99
- })
100
- })