npq 2.1.0 → 2.1.2
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/.prettierrc.js +9 -0
- package/__tests__/__fixtures__/test.marshall.js +1 -1
- package/__tests__/marshalls.base.test.js +1 -3
- package/__tests__/marshalls.classMethods.test.js +1 -3
- package/__tests__/marshalls.repo.test.js +6 -13
- package/__tests__/marshalls.tasks.test.js +5 -7
- package/__tests__/packageManager.test.js +11 -11
- package/__tests__/packageRepoUtils.test.js +37 -23
- package/__tests__/scripts.test.js +13 -3
- package/bin/npq-hero.js +4 -5
- package/bin/npq.js +3 -3
- package/lib/cli.js +2 -3
- package/lib/cliCommons.js +3 -2
- package/lib/helpers/packageRepoUtils.js +9 -17
- package/lib/marshall.js +3 -3
- package/lib/marshalls/age.marshall.js +1 -1
- package/lib/marshalls/author.marshall.js +3 -5
- package/lib/marshalls/baseMarshall.js +3 -4
- package/lib/marshalls/downloads.marshall.js +8 -10
- package/lib/marshalls/index.js +7 -7
- package/lib/marshalls/license.marshall.js +11 -21
- package/lib/marshalls/readme.marshall.js +11 -21
- package/lib/marshalls/repo.marshall.js +17 -11
- package/lib/marshalls/scripts.marshall.js +4 -7
- package/lib/marshalls/snyk.marshall.js +9 -8
- package/lib/packageManager.js +1 -1
- package/package.json +14 -4
- package/scripts/postinstall.js +13 -7
- package/scripts/scriptHelpers.js +2 -3
package/.prettierrc.js
ADDED
|
@@ -46,9 +46,7 @@ test('checkPackage sets the error property if the validaiton failed', async () =
|
|
|
46
46
|
|
|
47
47
|
testMarshall.init(ctx)
|
|
48
48
|
await testMarshall.checkPackage(pkg, ctx, {})
|
|
49
|
-
expect(ctx.marshalls[TEST_MARSHALL_NAME].errors[0].pkg).toEqual(
|
|
50
|
-
pkg.packageString
|
|
51
|
-
)
|
|
49
|
+
expect(ctx.marshalls[TEST_MARSHALL_NAME].errors[0].pkg).toEqual(pkg.packageString)
|
|
52
50
|
})
|
|
53
51
|
|
|
54
52
|
test('setError sets the errors properly', () => {
|
|
@@ -33,7 +33,5 @@ test('build marshalls without any should throw error', () => {
|
|
|
33
33
|
expect(marshalls.buildMarshallTasks([])).rejects.toEqual(expect.any(Error))
|
|
34
34
|
expect(marshalls.buildMarshallTasks({})).rejects.toEqual(expect.any(Error))
|
|
35
35
|
expect(marshalls.buildMarshallTasks(5)).rejects.toEqual(expect.any(Error))
|
|
36
|
-
expect(marshalls.buildMarshallTasks('something')).rejects.toEqual(
|
|
37
|
-
expect.any(Error)
|
|
38
|
-
)
|
|
36
|
+
expect(marshalls.buildMarshallTasks('something')).rejects.toEqual(expect.any(Error))
|
|
39
37
|
})
|
|
@@ -81,9 +81,7 @@ describe('Repo test suites', () => {
|
|
|
81
81
|
})
|
|
82
82
|
|
|
83
83
|
test('throws the right error when the repository url does not exist', async () => {
|
|
84
|
-
fetch.mockImplementationOnce(() =>
|
|
85
|
-
Promise.reject(new Error('error'))
|
|
86
|
-
)
|
|
84
|
+
fetch.mockImplementationOnce(() => Promise.reject(new Error('error')))
|
|
87
85
|
|
|
88
86
|
await expect(testMarshall.validate(fullPkgData)).rejects.toThrow(
|
|
89
87
|
'no valid repository is associated with the package'
|
|
@@ -91,20 +89,17 @@ describe('Repo test suites', () => {
|
|
|
91
89
|
})
|
|
92
90
|
|
|
93
91
|
test('throws the right error when the repository url is unreachable', async () => {
|
|
94
|
-
fetch.mockImplementationOnce(() =>
|
|
95
|
-
Promise.reject(new Error('error'))
|
|
96
|
-
)
|
|
92
|
+
fetch.mockImplementationOnce(() => Promise.reject(new Error('error')))
|
|
97
93
|
|
|
98
|
-
fullPkgData.packageName.versions['1.0.0'].repository.url =
|
|
94
|
+
fullPkgData.packageName.versions['1.0.0'].repository.url =
|
|
95
|
+
'https://dsfsdfsdfs.abcdeugwecwekjasda.com/'
|
|
99
96
|
await expect(testMarshall.validate(fullPkgData)).rejects.toThrow(
|
|
100
97
|
'the repository associated with the package (https://dsfsdfsdfs.abcdeugwecwekjasda.com/) does not exist or is unreachable at the moment.'
|
|
101
98
|
)
|
|
102
99
|
})
|
|
103
100
|
|
|
104
101
|
test('throws the right error when the homepage url does not exist', async () => {
|
|
105
|
-
fetch.mockImplementationOnce(() =>
|
|
106
|
-
Promise.reject(new Error('error'))
|
|
107
|
-
)
|
|
102
|
+
fetch.mockImplementationOnce(() => Promise.reject(new Error('error')))
|
|
108
103
|
|
|
109
104
|
const pkgData = {
|
|
110
105
|
packageName: {
|
|
@@ -126,9 +121,7 @@ describe('Repo test suites', () => {
|
|
|
126
121
|
})
|
|
127
122
|
|
|
128
123
|
test('does not throw any errors if the url exists', async () => {
|
|
129
|
-
fetch.mockImplementationOnce(() =>
|
|
130
|
-
Promise.resolve('success')
|
|
131
|
-
)
|
|
124
|
+
fetch.mockImplementationOnce(() => Promise.resolve('success'))
|
|
132
125
|
|
|
133
126
|
fullPkgData.packageName.versions['1.0.0'].repository.url = 'https://google.com'
|
|
134
127
|
await expect(testMarshall.validate(fullPkgData)).resolves.toEqual(expect.anything())
|
|
@@ -2,14 +2,14 @@ const path = require('path')
|
|
|
2
2
|
const marshalls = require('../lib/marshalls')
|
|
3
3
|
|
|
4
4
|
const PackageRepoUtilsMock = class Fake {
|
|
5
|
-
getPackageInfo () {
|
|
5
|
+
getPackageInfo () {
|
|
6
|
+
return Promise.resolve(true)
|
|
7
|
+
}
|
|
6
8
|
}
|
|
7
9
|
|
|
8
10
|
test('running marshall tasks succeeds', async () => {
|
|
9
11
|
marshalls.collectMarshalls = jest.fn(() => {
|
|
10
|
-
return Promise.resolve([
|
|
11
|
-
path.join(process.cwd(), '__tests__/__fixtures__/test.marshall.js')
|
|
12
|
-
])
|
|
12
|
+
return Promise.resolve([path.join(process.cwd(), '__tests__/__fixtures__/test.marshall.js')])
|
|
13
13
|
})
|
|
14
14
|
|
|
15
15
|
const config = {
|
|
@@ -31,9 +31,7 @@ test('running marshall tasks succeeds', async () => {
|
|
|
31
31
|
|
|
32
32
|
test('running marshall tasks fails', async () => {
|
|
33
33
|
marshalls.collectMarshalls = jest.fn(() => {
|
|
34
|
-
return Promise.resolve([
|
|
35
|
-
path.join(process.cwd(), '__tests__/__fixtures__/test.marshall.js')
|
|
36
|
-
])
|
|
34
|
+
return Promise.resolve([path.join(process.cwd(), '__tests__/__fixtures__/test.marshall.js')])
|
|
37
35
|
})
|
|
38
36
|
|
|
39
37
|
const config = {
|
|
@@ -55,25 +55,25 @@ test('package manager spawns successfully when provided array of packages to han
|
|
|
55
55
|
expect(childProcess.spawn.mock.calls.length).toBe(1)
|
|
56
56
|
expect(childProcess.spawn.mock.calls[0][0]).toBe('npm')
|
|
57
57
|
|
|
58
|
-
expect(childProcess.spawn.mock.calls[0][1]).toEqual([
|
|
59
|
-
'install',
|
|
60
|
-
'semver',
|
|
61
|
-
'express'
|
|
62
|
-
])
|
|
58
|
+
expect(childProcess.spawn.mock.calls[0][1]).toEqual(['install', 'semver', 'express'])
|
|
63
59
|
childProcess.spawn.mockReset()
|
|
64
60
|
})
|
|
65
61
|
|
|
66
62
|
test('package manager spawns successfully and ignore npqs own internal commands when spawning package manager', async () => {
|
|
67
|
-
process.argv = [
|
|
63
|
+
process.argv = [
|
|
64
|
+
'node',
|
|
65
|
+
'script name',
|
|
66
|
+
'install',
|
|
67
|
+
'semver',
|
|
68
|
+
'express',
|
|
69
|
+
'--dry-run',
|
|
70
|
+
'--packageManager'
|
|
71
|
+
]
|
|
68
72
|
await packageManager.process('npm')
|
|
69
73
|
expect(childProcess.spawn).toHaveBeenCalled()
|
|
70
74
|
expect(childProcess.spawn.mock.calls.length).toBe(1)
|
|
71
75
|
expect(childProcess.spawn.mock.calls[0][0]).toBe('npm')
|
|
72
76
|
|
|
73
|
-
expect(childProcess.spawn.mock.calls[0][1]).toEqual([
|
|
74
|
-
'install',
|
|
75
|
-
'semver',
|
|
76
|
-
'express'
|
|
77
|
-
])
|
|
77
|
+
expect(childProcess.spawn.mock.calls[0][1]).toEqual(['install', 'semver', 'express'])
|
|
78
78
|
childProcess.spawn.mockReset()
|
|
79
79
|
})
|
|
@@ -2,9 +2,11 @@ const PackageRepoUtils = require('../lib/helpers/packageRepoUtils')
|
|
|
2
2
|
const fetch = require('node-fetch')
|
|
3
3
|
|
|
4
4
|
jest.mock('node-fetch')
|
|
5
|
-
fetch.mockImplementation(() =>
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
fetch.mockImplementation(() =>
|
|
6
|
+
Promise.resolve({
|
|
7
|
+
json: () => require('./mocks/registryPackageOk.mock.json')
|
|
8
|
+
})
|
|
9
|
+
)
|
|
8
10
|
|
|
9
11
|
beforeEach(() => {
|
|
10
12
|
fetch.mockClear()
|
|
@@ -62,9 +64,11 @@ test('repo utils retrieves package README information', async () => {
|
|
|
62
64
|
|
|
63
65
|
test('repo utils retrieves package latest version as null if not exists', async () => {
|
|
64
66
|
const PackageRepoUtils = require('../lib/helpers/packageRepoUtils')
|
|
65
|
-
fetch.mockReturnValue(
|
|
66
|
-
|
|
67
|
-
|
|
67
|
+
fetch.mockReturnValue(
|
|
68
|
+
Promise.resolve({
|
|
69
|
+
json: () => require('./mocks/registryPackageUnpublished.mock.json')
|
|
70
|
+
})
|
|
71
|
+
)
|
|
68
72
|
|
|
69
73
|
const packageRepoUtils = new PackageRepoUtils()
|
|
70
74
|
const packageName = 'testPackage'
|
|
@@ -74,14 +78,16 @@ test('repo utils retrieves package latest version as null if not exists', async
|
|
|
74
78
|
|
|
75
79
|
test('repo utils retrieves package download count', async () => {
|
|
76
80
|
const PackageRepoUtils = require('../lib/helpers/packageRepoUtils')
|
|
77
|
-
fetch.mockReturnValue(
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
fetch.mockReturnValue(
|
|
82
|
+
Promise.resolve({
|
|
83
|
+
json: () => ({
|
|
84
|
+
downloads: 1950,
|
|
85
|
+
start: '2017-11-26',
|
|
86
|
+
end: '2017-12-25',
|
|
87
|
+
package: 'express-version-route'
|
|
88
|
+
})
|
|
83
89
|
})
|
|
84
|
-
|
|
90
|
+
)
|
|
85
91
|
|
|
86
92
|
const packageRepoUtils = new PackageRepoUtils()
|
|
87
93
|
const packageName = 'testPackage'
|
|
@@ -91,9 +97,11 @@ test('repo utils retrieves package download count', async () => {
|
|
|
91
97
|
|
|
92
98
|
test('repo utils retrieves package README information even when not available', async () => {
|
|
93
99
|
const PackageRepoUtils = require('../lib/helpers/packageRepoUtils')
|
|
94
|
-
fetch.mockReturnValue(
|
|
95
|
-
|
|
96
|
-
|
|
100
|
+
fetch.mockReturnValue(
|
|
101
|
+
Promise.resolve({
|
|
102
|
+
json: () => require('./mocks/registryPackageUnpublished.mock.json')
|
|
103
|
+
})
|
|
104
|
+
)
|
|
97
105
|
|
|
98
106
|
const packageRepoUtils = new PackageRepoUtils()
|
|
99
107
|
const packageName = 'testPackage'
|
|
@@ -103,9 +111,11 @@ test('repo utils retrieves package README information even when not available',
|
|
|
103
111
|
|
|
104
112
|
test('repo utils retrieves package LICENSE information', async () => {
|
|
105
113
|
const PackageRepoUtils = require('../lib/helpers/packageRepoUtils')
|
|
106
|
-
fetch.mockReturnValue(
|
|
107
|
-
|
|
108
|
-
|
|
114
|
+
fetch.mockReturnValue(
|
|
115
|
+
Promise.resolve({
|
|
116
|
+
json: () => require('./mocks/registryPackageOk.mock.json')
|
|
117
|
+
})
|
|
118
|
+
)
|
|
109
119
|
|
|
110
120
|
const packageRepoUtils = new PackageRepoUtils()
|
|
111
121
|
const packageName = 'testPackage'
|
|
@@ -115,12 +125,16 @@ test('repo utils retrieves package LICENSE information', async () => {
|
|
|
115
125
|
|
|
116
126
|
test('repo utils parses package version', async () => {
|
|
117
127
|
const PackageRepoUtils = require('../lib/helpers/packageRepoUtils')
|
|
118
|
-
fetch.mockReturnValue(
|
|
119
|
-
|
|
120
|
-
|
|
128
|
+
fetch.mockReturnValue(
|
|
129
|
+
Promise.resolve({
|
|
130
|
+
json: () => require('./mocks/registryPackageOk.mock.json')
|
|
131
|
+
})
|
|
132
|
+
)
|
|
121
133
|
|
|
122
134
|
const packageRepoUtils = new PackageRepoUtils()
|
|
123
135
|
const packageName = 'testPackage'
|
|
124
|
-
const result = await packageRepoUtils.parsePackageVersion(
|
|
136
|
+
const result = await packageRepoUtils.parsePackageVersion(
|
|
137
|
+
await packageRepoUtils.getLatestVersion(packageName)
|
|
138
|
+
)
|
|
125
139
|
expect(result).toBeTruthy()
|
|
126
140
|
})
|
|
@@ -16,7 +16,11 @@ let mockIsRunningInYarn
|
|
|
16
16
|
let mockGetNpmVersion
|
|
17
17
|
|
|
18
18
|
beforeEach(() => {
|
|
19
|
-
mockGetShellConfig = jest.spyOn(helpers, 'getShellConfig').mockImplementation(() => ({
|
|
19
|
+
mockGetShellConfig = jest.spyOn(helpers, 'getShellConfig').mockImplementation(() => ({
|
|
20
|
+
name: 'testShell',
|
|
21
|
+
profilePath: TEST_PROFILE_PATH,
|
|
22
|
+
aliases: TEST_ALIAS
|
|
23
|
+
}))
|
|
20
24
|
// Our install script does not run when installing with yarn, but we still want to be able to run tests with yarn
|
|
21
25
|
mockIsRunningInYarn = jest.spyOn(helpers, 'isRunningInYarn').mockImplementation(() => false)
|
|
22
26
|
// Our install script does not run when installing with npm V7, but we still want to be able to run tests with all npm versions
|
|
@@ -88,7 +92,10 @@ test('postinstall script does not create duplicate aliases', async () => {
|
|
|
88
92
|
await postinstall.runPostInstall()
|
|
89
93
|
|
|
90
94
|
const containsAlias = await helpers.fileContains(TEST_PROFILE_PATH, TEST_ALIAS)
|
|
91
|
-
const containsDoubleAlias = await helpers.fileContains(
|
|
95
|
+
const containsDoubleAlias = await helpers.fileContains(
|
|
96
|
+
TEST_PROFILE_PATH,
|
|
97
|
+
`${TEST_ALIAS}${TEST_ALIAS}`
|
|
98
|
+
)
|
|
92
99
|
expect(containsAlias).toBe(true)
|
|
93
100
|
expect(containsDoubleAlias).toBe(false)
|
|
94
101
|
})
|
|
@@ -115,7 +122,10 @@ test('uninstall script does nothing in unknown shell', async () => {
|
|
|
115
122
|
test('uninstall handles empty profile', async () => {
|
|
116
123
|
await preuninstall.runPreUninstall()
|
|
117
124
|
|
|
118
|
-
const profileExists = await fs.promises
|
|
125
|
+
const profileExists = await fs.promises
|
|
126
|
+
.access(TEST_PROFILE_PATH, fs.constants.F_OK)
|
|
127
|
+
.then(() => true)
|
|
128
|
+
.catch(() => false)
|
|
119
129
|
expect(profileExists).toBe(false)
|
|
120
130
|
})
|
|
121
131
|
|
package/bin/npq-hero.js
CHANGED
|
@@ -3,8 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
// Require minimum node version or bail out
|
|
5
5
|
const cliSupport = require('../lib/helpers/cliSupportHandler')
|
|
6
|
-
cliSupport.isEnvSupport() ||
|
|
7
|
-
(cliSupport.noSupportError() && cliSupport.packageManagerPassthrough())
|
|
6
|
+
cliSupport.isEnvSupport() || (cliSupport.noSupportError() && cliSupport.packageManagerPassthrough())
|
|
8
7
|
|
|
9
8
|
const inquirer = require('inquirer')
|
|
10
9
|
const yargs = require('yargs')
|
|
@@ -26,7 +25,7 @@ const marshall = new Marshall({
|
|
|
26
25
|
|
|
27
26
|
marshall
|
|
28
27
|
.process()
|
|
29
|
-
.then(result => {
|
|
28
|
+
.then((result) => {
|
|
30
29
|
if (result && result.error) {
|
|
31
30
|
// eslint-disable-next-line no-console
|
|
32
31
|
console.log()
|
|
@@ -42,12 +41,12 @@ marshall
|
|
|
42
41
|
|
|
43
42
|
return { install: true }
|
|
44
43
|
})
|
|
45
|
-
.then(status => {
|
|
44
|
+
.then((status) => {
|
|
46
45
|
if (status && status.hasOwnProperty('install') && status.install === true) {
|
|
47
46
|
pkgMgr.process(PACKAGE_MANAGER_TOOL, cli.package)
|
|
48
47
|
}
|
|
49
48
|
})
|
|
50
|
-
.catch(error => {
|
|
49
|
+
.catch((error) => {
|
|
51
50
|
// eslint-disable-next-line no-console
|
|
52
51
|
console.error(error)
|
|
53
52
|
process.exit(-1)
|
package/bin/npq.js
CHANGED
|
@@ -16,7 +16,7 @@ const marshall = new Marshall({
|
|
|
16
16
|
|
|
17
17
|
marshall
|
|
18
18
|
.process()
|
|
19
|
-
.then(result => {
|
|
19
|
+
.then((result) => {
|
|
20
20
|
if (cli.dryRun) {
|
|
21
21
|
process.exit(0)
|
|
22
22
|
}
|
|
@@ -36,12 +36,12 @@ marshall
|
|
|
36
36
|
|
|
37
37
|
return { install: true }
|
|
38
38
|
})
|
|
39
|
-
.then(status => {
|
|
39
|
+
.then((status) => {
|
|
40
40
|
if (status && status.hasOwnProperty('install') && status.install === true) {
|
|
41
41
|
pkgMgr.process(cli.packageManager)
|
|
42
42
|
}
|
|
43
43
|
})
|
|
44
|
-
.catch(error => {
|
|
44
|
+
.catch((error) => {
|
|
45
45
|
// eslint-disable-next-line no-console
|
|
46
46
|
console.error(error)
|
|
47
47
|
process.exit(-1)
|
package/lib/cli.js
CHANGED
|
@@ -14,12 +14,11 @@ const argv = yargs
|
|
|
14
14
|
command: '--packageManager [packageManager]',
|
|
15
15
|
aliases: ['--pkgMgr'],
|
|
16
16
|
desc: 'the package manager to offload handling the command',
|
|
17
|
-
builder: yargs => yargs.default('packageManager', 'npm')
|
|
17
|
+
builder: (yargs) => yargs.default('packageManager', 'npm')
|
|
18
18
|
})
|
|
19
19
|
.command({
|
|
20
20
|
command: '--dry-run',
|
|
21
|
-
desc:
|
|
22
|
-
'npq will run checks only and will not proceed with actually installing a package'
|
|
21
|
+
desc: 'npq will run checks only and will not proceed with actually installing a package'
|
|
23
22
|
})
|
|
24
23
|
.example('npq install express')
|
|
25
24
|
.epilogue('curated by Liran Tal at https://github.com/lirantal/npq').argv
|
package/lib/cliCommons.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
1
|
const npa = require('npm-package-arg')
|
|
3
2
|
class cliCommons {
|
|
4
3
|
static getInstallCommand () {
|
|
@@ -10,8 +9,10 @@ class cliCommons {
|
|
|
10
9
|
if (argv && argv.package) {
|
|
11
10
|
for (let i = 0; i < argv.package.length; i++) {
|
|
12
11
|
const parsedPackage = npa(argv.package[i])
|
|
12
|
+
const versionModifier =
|
|
13
|
+
parsedPackage.fetchSpec === '*' ? 'latest' : parsedPackage.fetchSpec
|
|
13
14
|
// eslint-disable-next-line security/detect-object-injection
|
|
14
|
-
argv.package[i] = `${parsedPackage.name}@${
|
|
15
|
+
argv.package[i] = `${parsedPackage.name}@${versionModifier}`
|
|
15
16
|
}
|
|
16
17
|
}
|
|
17
18
|
}
|
|
@@ -8,9 +8,7 @@ const NPM_REGISTRY_API = 'https://api.npmjs.org'
|
|
|
8
8
|
class PackageRepoUtils {
|
|
9
9
|
constructor (options = {}) {
|
|
10
10
|
this.registryUrl = options.registryUrl ? options.registryUrl : NPM_REGISTRY
|
|
11
|
-
this.registryApiUrl = options.registryApiUrl
|
|
12
|
-
? options.registryApiUrl
|
|
13
|
-
: NPM_REGISTRY_API
|
|
11
|
+
this.registryApiUrl = options.registryApiUrl ? options.registryApiUrl : NPM_REGISTRY_API
|
|
14
12
|
this.pkgInfoCache = {}
|
|
15
13
|
}
|
|
16
14
|
|
|
@@ -23,8 +21,8 @@ class PackageRepoUtils {
|
|
|
23
21
|
return Promise.resolve(this.pkgInfoCache[pkg])
|
|
24
22
|
} else {
|
|
25
23
|
return fetch(`${this.registryUrl}/${this.formatPackageForUrl(pkg)}`)
|
|
26
|
-
.then(response => response.json())
|
|
27
|
-
.then(data => {
|
|
24
|
+
.then((response) => response.json())
|
|
25
|
+
.then((data) => {
|
|
28
26
|
this.pkgInfoCache[pkg] = data
|
|
29
27
|
return data
|
|
30
28
|
})
|
|
@@ -32,29 +30,23 @@ class PackageRepoUtils {
|
|
|
32
30
|
}
|
|
33
31
|
|
|
34
32
|
getLatestVersion (pkg) {
|
|
35
|
-
return this.getPackageInfo(pkg)
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
data['dist-tags']['latest']
|
|
39
|
-
? data['dist-tags']['latest']
|
|
40
|
-
: null
|
|
41
|
-
})
|
|
33
|
+
return this.getPackageInfo(pkg).then((data) => {
|
|
34
|
+
return data['dist-tags'] && data['dist-tags']['latest'] ? data['dist-tags']['latest'] : null
|
|
35
|
+
})
|
|
42
36
|
}
|
|
43
37
|
|
|
44
38
|
getDownloadInfo (pkg) {
|
|
45
39
|
return fetch(`${this.registryApiUrl}/downloads/point/last-month/${pkg}`)
|
|
46
|
-
.then(response => response.json())
|
|
40
|
+
.then((response) => response.json())
|
|
47
41
|
.then(({ downloads }) => downloads)
|
|
48
42
|
}
|
|
49
43
|
|
|
50
44
|
getReadmeInfo (pkg) {
|
|
51
|
-
return this.getPackageInfo(pkg)
|
|
52
|
-
.then(({ readme }) => readme)
|
|
45
|
+
return this.getPackageInfo(pkg).then(({ readme }) => readme)
|
|
53
46
|
}
|
|
54
47
|
|
|
55
48
|
getLicenseInfo (pkg) {
|
|
56
|
-
return this.getPackageInfo(pkg)
|
|
57
|
-
.then(({ license }) => license)
|
|
49
|
+
return this.getPackageInfo(pkg).then(({ license }) => license)
|
|
58
50
|
}
|
|
59
51
|
|
|
60
52
|
parsePackageVersion (version) {
|
package/lib/marshall.js
CHANGED
|
@@ -28,7 +28,7 @@ class Marshall {
|
|
|
28
28
|
packageRepoUtils: this.packageRepoUtils
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
return Marshalls.tasks(config).catch(ctx => {
|
|
31
|
+
return Marshalls.tasks(config).catch((ctx) => {
|
|
32
32
|
if (ctx && ctx.context && ctx.context.marshalls) {
|
|
33
33
|
return this.report(ctx.context.marshalls)
|
|
34
34
|
}
|
|
@@ -69,7 +69,7 @@ class Marshall {
|
|
|
69
69
|
const packageMessages = messages[packageName]
|
|
70
70
|
console.log(` [${chalk.red(packageName)}]`)
|
|
71
71
|
|
|
72
|
-
packageMessages.forEach(message => {
|
|
72
|
+
packageMessages.forEach((message) => {
|
|
73
73
|
if (message.type === MESSAGE_TYPE.ERROR) {
|
|
74
74
|
console.log(` - ${chalk.red(message.text)}`)
|
|
75
75
|
} else {
|
|
@@ -93,7 +93,7 @@ class Marshall {
|
|
|
93
93
|
|
|
94
94
|
prepareMessages (allPackageMessages, messages, isWarning) {
|
|
95
95
|
if (Array.isArray(messages) && messages.length > 0) {
|
|
96
|
-
messages.forEach(msg => {
|
|
96
|
+
messages.forEach((msg) => {
|
|
97
97
|
this.appendPackageMessage(allPackageMessages, msg.pkg, {
|
|
98
98
|
text: msg.message,
|
|
99
99
|
type: isWarning ? MESSAGE_TYPE.WARNING : MESSAGE_TYPE.ERROR
|
|
@@ -16,7 +16,7 @@ class Marshall extends BaseMarshall {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
validate (pkg) {
|
|
19
|
-
return this.packageRepoUtils.getPackageInfo(pkg.packageName).then(data => {
|
|
19
|
+
return this.packageRepoUtils.getPackageInfo(pkg.packageName).then((data) => {
|
|
20
20
|
const pkgCreatedDate = data.time.created
|
|
21
21
|
const dateDiff = Date.now() - Date.parse(pkgCreatedDate)
|
|
22
22
|
|
|
@@ -17,11 +17,9 @@ class Marshall extends BaseMarshall {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
validate (pkg) {
|
|
20
|
-
return this.packageRepoUtils.getPackageInfo(pkg.packageName).then(data => {
|
|
20
|
+
return this.packageRepoUtils.getPackageInfo(pkg.packageName).then((data) => {
|
|
21
21
|
const lastVersionData =
|
|
22
|
-
data.versions &&
|
|
23
|
-
data['dist-tags'] &&
|
|
24
|
-
data.versions[data['dist-tags']['latest']]
|
|
22
|
+
data.versions && data['dist-tags'] && data.versions[data['dist-tags']['latest']]
|
|
25
23
|
|
|
26
24
|
const hasAuthorEmail =
|
|
27
25
|
(lastVersionData &&
|
|
@@ -33,7 +31,7 @@ class Marshall extends BaseMarshall {
|
|
|
33
31
|
lastVersionData.authors &&
|
|
34
32
|
lastVersionData.authors.filter &&
|
|
35
33
|
lastVersionData.authors.filter(
|
|
36
|
-
author => author.email && validator.isEmail(author.email).length
|
|
34
|
+
(author) => author.email && validator.isEmail(author.email).length
|
|
37
35
|
))
|
|
38
36
|
|
|
39
37
|
if (!hasAuthorEmail) {
|
|
@@ -29,14 +29,14 @@ class BaseMarshall {
|
|
|
29
29
|
|
|
30
30
|
checkPackage (pkg, ctx, task) {
|
|
31
31
|
return this.validate(pkg)
|
|
32
|
-
.then(data => {
|
|
32
|
+
.then((data) => {
|
|
33
33
|
task.output = `querying ${pkg.packageString}...`
|
|
34
34
|
ctx.marshalls[this.name].data[pkg.packageString] = data
|
|
35
35
|
|
|
36
36
|
// not explicitly required, but a task can return its results
|
|
37
37
|
return data
|
|
38
38
|
})
|
|
39
|
-
.catch(err => {
|
|
39
|
+
.catch((err) => {
|
|
40
40
|
if (err instanceof Warning) {
|
|
41
41
|
this.setMessage(
|
|
42
42
|
{
|
|
@@ -55,8 +55,7 @@ class BaseMarshall {
|
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
isEnabled () {
|
|
58
|
-
const isMarshallSilent =
|
|
59
|
-
process.env[`MARSHALL_DISABLE_${this.name.toUpperCase()}`] || false
|
|
58
|
+
const isMarshallSilent = process.env[`MARSHALL_DISABLE_${this.name.toUpperCase()}`] || false
|
|
60
59
|
|
|
61
60
|
return !isMarshallSilent
|
|
62
61
|
}
|
|
@@ -16,17 +16,15 @@ class Marshall extends BaseMarshall {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
validate (pkg) {
|
|
19
|
-
return this.packageRepoUtils
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
)
|
|
26
|
-
}
|
|
19
|
+
return this.packageRepoUtils.getDownloadInfo(pkg.packageName).then((downloadCount) => {
|
|
20
|
+
if (downloadCount < DOWNLOAD_COUNT_THRESHOLD) {
|
|
21
|
+
throw new Error(
|
|
22
|
+
`detected a low download-count package (downloads last month < ${DOWNLOAD_COUNT_THRESHOLD})`
|
|
23
|
+
)
|
|
24
|
+
}
|
|
27
25
|
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
return downloadCount
|
|
27
|
+
})
|
|
30
28
|
}
|
|
31
29
|
}
|
|
32
30
|
|
package/lib/marshalls/index.js
CHANGED
|
@@ -25,9 +25,7 @@ class Marshalls {
|
|
|
25
25
|
|
|
26
26
|
static buildMarshallTasks (marshalls, config) {
|
|
27
27
|
if (!marshalls || !Array.isArray(marshalls) || marshalls.length === 0) {
|
|
28
|
-
return Promise.reject(
|
|
29
|
-
new Error('unable to collect marshalls, or no marshalls found')
|
|
30
|
-
)
|
|
28
|
+
return Promise.reject(new Error('unable to collect marshalls, or no marshalls found'))
|
|
31
29
|
}
|
|
32
30
|
|
|
33
31
|
const marshallTasks = marshalls.reduce((prev, curr) => {
|
|
@@ -37,7 +35,7 @@ class Marshalls {
|
|
|
37
35
|
|
|
38
36
|
return prev.concat({
|
|
39
37
|
title: marshall.title(),
|
|
40
|
-
enabled: ctx => marshall.isEnabled(ctx),
|
|
38
|
+
enabled: (ctx) => marshall.isEnabled(ctx),
|
|
41
39
|
task: (ctx, task) => {
|
|
42
40
|
marshall.init(ctx, task)
|
|
43
41
|
return marshall.run(ctx, task).then(() => marshall.handleMessages())
|
|
@@ -51,12 +49,12 @@ class Marshalls {
|
|
|
51
49
|
static tasks (options) {
|
|
52
50
|
return this.warmUpPackagesCache(options)
|
|
53
51
|
.then(() => this.collectMarshalls())
|
|
54
|
-
.then(marshalls => {
|
|
52
|
+
.then((marshalls) => {
|
|
55
53
|
return this.buildMarshallTasks(marshalls, {
|
|
56
54
|
packageRepoUtils: options.packageRepoUtils
|
|
57
55
|
})
|
|
58
56
|
})
|
|
59
|
-
.then(tasks => {
|
|
57
|
+
.then((tasks) => {
|
|
60
58
|
return this.runTasks(tasks, options)
|
|
61
59
|
})
|
|
62
60
|
}
|
|
@@ -64,7 +62,9 @@ class Marshalls {
|
|
|
64
62
|
static warmUpPackagesCache (options) {
|
|
65
63
|
const fetchPackagesInfoPromises = []
|
|
66
64
|
options.pkgs.forEach((packageMeta) => {
|
|
67
|
-
fetchPackagesInfoPromises.push(
|
|
65
|
+
fetchPackagesInfoPromises.push(
|
|
66
|
+
options.packageRepoUtils.getPackageInfo(packageMeta.packageName)
|
|
67
|
+
)
|
|
68
68
|
})
|
|
69
69
|
|
|
70
70
|
return Promise.all(fetchPackagesInfoPromises)
|
|
@@ -15,27 +15,17 @@ class Marshall extends BaseMarshall {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
validate (pkg) {
|
|
18
|
-
return this.packageRepoUtils
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
)
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
licenseContents &&
|
|
30
|
-
licenseContents.indexOf('# Security holding package') === 0
|
|
31
|
-
) {
|
|
32
|
-
throw new Error(
|
|
33
|
-
'package flagged for security issues and served as place-holder'
|
|
34
|
-
)
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
return licenseContents
|
|
38
|
-
})
|
|
18
|
+
return this.packageRepoUtils.getLicenseInfo(pkg.packageName).then((licenseContents) => {
|
|
19
|
+
if (!licenseContents || licenseContents === 'ERROR: No LICENSE data found!') {
|
|
20
|
+
throw new Error('package has no LICENSE file available')
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (licenseContents && licenseContents.indexOf('# Security holding package') === 0) {
|
|
24
|
+
throw new Error('package flagged for security issues and served as place-holder')
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return licenseContents
|
|
28
|
+
})
|
|
39
29
|
}
|
|
40
30
|
}
|
|
41
31
|
|
|
@@ -15,27 +15,17 @@ class Marshall extends BaseMarshall {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
validate (pkg) {
|
|
18
|
-
return this.packageRepoUtils
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
)
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
readmeContents &&
|
|
30
|
-
readmeContents.indexOf('# Security holding package') === 0
|
|
31
|
-
) {
|
|
32
|
-
throw new Error(
|
|
33
|
-
'package flagged for security issues and served as place-holder'
|
|
34
|
-
)
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
return readmeContents
|
|
38
|
-
})
|
|
18
|
+
return this.packageRepoUtils.getReadmeInfo(pkg.packageName).then((readmeContents) => {
|
|
19
|
+
if (!readmeContents || readmeContents === 'ERROR: No README data found!') {
|
|
20
|
+
throw new Error('package has no README file available')
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (readmeContents && readmeContents.indexOf('# Security holding package') === 0) {
|
|
24
|
+
throw new Error('package flagged for security issues and served as place-holder')
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return readmeContents
|
|
28
|
+
})
|
|
39
29
|
}
|
|
40
30
|
}
|
|
41
31
|
|
|
@@ -16,9 +16,13 @@ class Marshall extends BaseMarshall {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
validate (pkg) {
|
|
19
|
-
return this.packageRepoUtils.getPackageInfo(pkg.packageName).then(data => {
|
|
20
|
-
const lastVersionData =
|
|
21
|
-
data.versions
|
|
19
|
+
return this.packageRepoUtils.getPackageInfo(pkg.packageName).then((data) => {
|
|
20
|
+
const lastVersionData =
|
|
21
|
+
(data.versions &&
|
|
22
|
+
data['dist-tags'] &&
|
|
23
|
+
data['dist-tags'].latest &&
|
|
24
|
+
data.versions[data['dist-tags'].latest]) ||
|
|
25
|
+
data
|
|
22
26
|
if (lastVersionData && lastVersionData.repository && lastVersionData.repository.url) {
|
|
23
27
|
let urlStructure, urlOfGitRepository
|
|
24
28
|
try {
|
|
@@ -27,15 +31,17 @@ class Marshall extends BaseMarshall {
|
|
|
27
31
|
} catch (error) {
|
|
28
32
|
throw new Error(`no valid repository is associated with the package`)
|
|
29
33
|
}
|
|
30
|
-
return fetch(urlOfGitRepository.href)
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
+
return fetch(urlOfGitRepository.href).catch(() => {
|
|
35
|
+
throw new Error(
|
|
36
|
+
`the repository associated with the package (${urlOfGitRepository.href}) does not exist or is unreachable at the moment.`
|
|
37
|
+
)
|
|
38
|
+
})
|
|
34
39
|
} else if (lastVersionData && lastVersionData.homepage) {
|
|
35
|
-
return fetch(lastVersionData.homepage)
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
40
|
+
return fetch(lastVersionData.homepage).catch(() => {
|
|
41
|
+
throw new Error(
|
|
42
|
+
`the homepage associated with the package (${lastVersionData.homepage}) does not exist or is unreachable at the moment.`
|
|
43
|
+
)
|
|
44
|
+
})
|
|
39
45
|
} else {
|
|
40
46
|
throw new Error('the package has no associated repository or homepage.')
|
|
41
47
|
}
|
|
@@ -15,12 +15,11 @@ class Marshall extends BaseMarshall {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
validate (pkg) {
|
|
18
|
-
return this.packageRepoUtils.getPackageInfo(pkg.packageName).then(data => {
|
|
18
|
+
return this.packageRepoUtils.getPackageInfo(pkg.packageName).then((data) => {
|
|
19
19
|
const packageVersion =
|
|
20
20
|
pkg.packageVersion === 'latest'
|
|
21
21
|
? data['dist-tags'] && data['dist-tags']['latest']
|
|
22
|
-
: this.packageRepoUtils.parsePackageVersion(pkg.packageVersion)
|
|
23
|
-
.version
|
|
22
|
+
: this.packageRepoUtils.parsePackageVersion(pkg.packageVersion).version
|
|
24
23
|
|
|
25
24
|
if (!packageVersion) {
|
|
26
25
|
return true
|
|
@@ -35,16 +34,14 @@ class Marshall extends BaseMarshall {
|
|
|
35
34
|
// blacklisted scripts due to possible malicious intent:
|
|
36
35
|
const blacklistScripts = ['install', 'preinstall', 'postinstall']
|
|
37
36
|
|
|
38
|
-
blacklistScripts.forEach(scriptName => {
|
|
37
|
+
blacklistScripts.forEach((scriptName) => {
|
|
39
38
|
if (
|
|
40
39
|
packageScripts &&
|
|
41
40
|
packageScripts.hasOwnProperty(scriptName) &&
|
|
42
41
|
packageScripts[scriptName].length > 0
|
|
43
42
|
) {
|
|
44
43
|
throw new Error(
|
|
45
|
-
`detected a possible malicious intent script, act carefully: ${scriptName}: ${
|
|
46
|
-
packageScripts[scriptName]
|
|
47
|
-
}`
|
|
44
|
+
`detected a possible malicious intent script, act carefully: ${scriptName}: ${packageScripts[scriptName]}`
|
|
48
45
|
)
|
|
49
46
|
}
|
|
50
47
|
})
|
|
@@ -37,15 +37,16 @@ class Marshall extends BaseMarshall {
|
|
|
37
37
|
return Promise.resolve()
|
|
38
38
|
.then(() => {
|
|
39
39
|
if (!pkg.packageVersion || pkg.packageVersion === 'latest') {
|
|
40
|
-
return this.packageRepoUtils
|
|
41
|
-
.getLatestVersion(pkg.packageName)
|
|
40
|
+
return this.packageRepoUtils.getLatestVersion(pkg.packageName)
|
|
42
41
|
}
|
|
43
|
-
})
|
|
42
|
+
})
|
|
43
|
+
.then((versionResolved) => {
|
|
44
44
|
return this.getSnykVulnInfo({
|
|
45
45
|
packageName: pkg.packageName,
|
|
46
46
|
packageVersion: versionResolved || pkg.packageVersion
|
|
47
47
|
})
|
|
48
|
-
})
|
|
48
|
+
})
|
|
49
|
+
.then((data) => {
|
|
49
50
|
if (!data) {
|
|
50
51
|
throw new Error('Unable to query vulnerabilities for packages')
|
|
51
52
|
}
|
|
@@ -63,8 +64,8 @@ class Marshall extends BaseMarshall {
|
|
|
63
64
|
const url = encodeURI(`${SNYK_TEST_URL}/${packageName}/${packageVersion}?type=json`)
|
|
64
65
|
|
|
65
66
|
return fetch(url)
|
|
66
|
-
.then(response => response.json())
|
|
67
|
-
.then(data => {
|
|
67
|
+
.then((response) => response.json())
|
|
68
|
+
.then((data) => {
|
|
68
69
|
// format returned results the way that the
|
|
69
70
|
// official test API endpoint returns them in
|
|
70
71
|
if (data && data.hasOwnProperty('totalVulns')) {
|
|
@@ -88,8 +89,8 @@ class Marshall extends BaseMarshall {
|
|
|
88
89
|
Authorization: `token ${this.snykApiToken}`
|
|
89
90
|
}
|
|
90
91
|
})
|
|
91
|
-
.then(response => response.json())
|
|
92
|
-
.then(data => {
|
|
92
|
+
.then((response) => response.json())
|
|
93
|
+
.then((data) => {
|
|
93
94
|
if (data && data.vulnerabilities) {
|
|
94
95
|
return {
|
|
95
96
|
issuesCount: data.vulnerabilities.length
|
package/lib/packageManager.js
CHANGED
|
@@ -13,7 +13,7 @@ class packageManager {
|
|
|
13
13
|
static spawnPackageManager (packageManager) {
|
|
14
14
|
let args = []
|
|
15
15
|
|
|
16
|
-
args = args.concat(process.argv.slice(2)).filter(item => {
|
|
16
|
+
args = args.concat(process.argv.slice(2)).filter((item) => {
|
|
17
17
|
switch (item) {
|
|
18
18
|
case '--packageManager':
|
|
19
19
|
case '--pkgMgr':
|
package/package.json
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "npq",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.2",
|
|
4
4
|
"description": "marshall your npm/yarn package installs with high quality and class 🎖",
|
|
5
5
|
"bin": {
|
|
6
6
|
"npq": "./bin/npq.js",
|
|
7
7
|
"npq-hero": "./bin/npq-hero.js"
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
|
-
"lint": "standard && eslint . --ignore-path .gitignore && yarn run lint:lockfile",
|
|
10
|
+
"lint": "standard --fix && eslint . --ignore-path .gitignore && yarn run lint:lockfile",
|
|
11
11
|
"lint:lockfile": "lockfile-lint --path yarn.lock --type yarn --validate-https --allowed-hosts npm yarn",
|
|
12
12
|
"test": "jest",
|
|
13
13
|
"test:watch": "jest --watch",
|
|
14
14
|
"coverage:view": "opn coverage/lcov-report/index.html",
|
|
15
15
|
"commit": "git-cz",
|
|
16
|
+
"format": "prettier --config .prettierrc.js --write '**/*.js'",
|
|
16
17
|
"docs": "yarn run docs:code && yarn run docs:api",
|
|
17
18
|
"docs:api": "doxdox *.js --layout bootstrap --output docs/index.html",
|
|
18
19
|
"docs:code": "docco *.js --output docs/code",
|
|
@@ -47,8 +48,10 @@
|
|
|
47
48
|
"eslint-plugin-security": "^1.3.0",
|
|
48
49
|
"husky": "^3.0.0",
|
|
49
50
|
"jest": "^24.9.0",
|
|
51
|
+
"lint-staged": "^13.1.0",
|
|
50
52
|
"lockfile-lint": "^2.0.1",
|
|
51
53
|
"opn-cli": "^4.0.0",
|
|
54
|
+
"prettier": "^2.8.3",
|
|
52
55
|
"semantic-release": "^15.0.0",
|
|
53
56
|
"standard": "^12.0.0"
|
|
54
57
|
},
|
|
@@ -91,7 +94,7 @@
|
|
|
91
94
|
"husky": {
|
|
92
95
|
"hooks": {
|
|
93
96
|
"commit-msg": "commitlint --env HUSKY_GIT_PARAMS",
|
|
94
|
-
"pre-commit": "
|
|
97
|
+
"pre-commit": "lint-staged",
|
|
95
98
|
"pre-push": "yarn run lint && yarn run test",
|
|
96
99
|
"post-commit": "git status",
|
|
97
100
|
"post-checkout": "git status",
|
|
@@ -103,6 +106,13 @@
|
|
|
103
106
|
"@commitlint/config-angular"
|
|
104
107
|
]
|
|
105
108
|
},
|
|
109
|
+
"lint-staged": {
|
|
110
|
+
"**/*.js": [
|
|
111
|
+
"yarn run format",
|
|
112
|
+
"yarn run lint",
|
|
113
|
+
"git add"
|
|
114
|
+
]
|
|
115
|
+
},
|
|
106
116
|
"standard": {
|
|
107
117
|
"env": [
|
|
108
118
|
"node",
|
|
@@ -178,7 +188,7 @@
|
|
|
178
188
|
"node-fetch": "^2.6.7",
|
|
179
189
|
"npm-package-arg": "^10.1.0",
|
|
180
190
|
"semver": "^7.3.8",
|
|
181
|
-
"update-notifier": "^
|
|
191
|
+
"update-notifier": "^5",
|
|
182
192
|
"validator": "^13.6.0",
|
|
183
193
|
"yargs": "^17.6.2"
|
|
184
194
|
},
|
package/scripts/postinstall.js
CHANGED
|
@@ -29,13 +29,19 @@ const runPostInstall = async () => {
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
try {
|
|
32
|
-
console.log(
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
32
|
+
console.log(
|
|
33
|
+
'Thank you for installing npq! We want to help you make conscious decisions before installing potentially dangerous packages.'
|
|
34
|
+
)
|
|
35
|
+
console.log(
|
|
36
|
+
'To do that, we can alias npm and yarn to npq, so that e.g. `npm install <package>` will first use npq to verify the package and prompt you if it finds any issues.'
|
|
37
|
+
)
|
|
38
|
+
const answers = await inquirer.prompt([
|
|
39
|
+
{
|
|
40
|
+
type: 'confirm',
|
|
41
|
+
name: 'install',
|
|
42
|
+
message: `Do you want to add ${shellConfig.name} aliases for npm and yarn?`
|
|
43
|
+
}
|
|
44
|
+
])
|
|
39
45
|
if (answers['install']) {
|
|
40
46
|
// eslint-disable-next-line security/detect-non-literal-fs-filename
|
|
41
47
|
await fs.promises.appendFile(shellConfig.profilePath, shellConfig.aliases)
|
package/scripts/scriptHelpers.js
CHANGED
|
@@ -5,11 +5,11 @@ const semver = require('semver')
|
|
|
5
5
|
|
|
6
6
|
const BASH_ZSH_ALIASES = '\nalias npm="npq-hero"\nalias yarn="NPQ_PKG_MGR=yarn npq-hero"\n'
|
|
7
7
|
const SHELLS = {
|
|
8
|
-
|
|
8
|
+
bash: {
|
|
9
9
|
profilePath: `${os.homedir()}/.bash_profile`,
|
|
10
10
|
aliases: BASH_ZSH_ALIASES
|
|
11
11
|
},
|
|
12
|
-
|
|
12
|
+
zsh: {
|
|
13
13
|
profilePath: `${os.homedir()}/.zshrc`,
|
|
14
14
|
aliases: BASH_ZSH_ALIASES
|
|
15
15
|
}
|
|
@@ -61,7 +61,6 @@ const getProfile = async (profilePath) => {
|
|
|
61
61
|
return profileData
|
|
62
62
|
} catch (err) {
|
|
63
63
|
if (err && err.code === 'ENOENT') {
|
|
64
|
-
|
|
65
64
|
} else if (err) {
|
|
66
65
|
throw err
|
|
67
66
|
}
|