npq 3.19.6 → 3.20.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/README.md +4 -0
- package/data/top-packages.json +17198 -49858
- package/lib/marshalls/typosquatting.marshall.js +7 -6
- package/package.json +6 -4
- package/scripts/build.js +37 -6
|
@@ -6,6 +6,7 @@ const { marshallCategories } = require('./constants')
|
|
|
6
6
|
const path = require('path')
|
|
7
7
|
const { levenshteinDistance } = require('../helpers/levenshteinDistance')
|
|
8
8
|
const topPackagesRawJSON = require(path.join(__dirname, '../../data/top-packages.json'))
|
|
9
|
+
const topPackages = new Set(topPackagesRawJSON)
|
|
9
10
|
|
|
10
11
|
const MARSHALL_NAME = 'typosquatting'
|
|
11
12
|
|
|
@@ -29,13 +30,13 @@ class Marshall extends BaseMarshall {
|
|
|
29
30
|
return resolve([])
|
|
30
31
|
}
|
|
31
32
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
33
|
+
// If the package to be installed is itself found within the Top Packages dataset
|
|
34
|
+
// then we don't report on it
|
|
35
|
+
if (topPackages.has(pkg.packageName)) {
|
|
36
|
+
return resolve([])
|
|
37
|
+
}
|
|
38
38
|
|
|
39
|
+
for (const popularPackageNameInRepository of topPackagesRawJSON) {
|
|
39
40
|
editDistance = levenshteinDistance(pkg.packageName, popularPackageNameInRepository)
|
|
40
41
|
|
|
41
42
|
if (editDistance > 0 && editDistance < 3) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "npq",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.20.0",
|
|
4
4
|
"description": "marshall your npm/npm package installs with high quality and class 🎖",
|
|
5
5
|
"bin": {
|
|
6
6
|
"npq": "./bin/npq.js",
|
|
@@ -14,13 +14,14 @@
|
|
|
14
14
|
"build": "node scripts/build.js",
|
|
15
15
|
"test:watch": "jest --watch",
|
|
16
16
|
"format": "prettier --config .prettierrc.js --write \"**/*.js\"",
|
|
17
|
-
"semantic-release": "
|
|
17
|
+
"semantic-release": "semantic-release",
|
|
18
18
|
"#postinstall": "node scripts/postinstall.js",
|
|
19
19
|
"#preuninstall": "node scripts/preuninstall.js",
|
|
20
20
|
"prepare": "husky || true"
|
|
21
21
|
},
|
|
22
22
|
"engines": {
|
|
23
|
-
"
|
|
23
|
+
"npm": ">=11.10.0",
|
|
24
|
+
"node": ">=24.0.0"
|
|
24
25
|
},
|
|
25
26
|
"files": [
|
|
26
27
|
"bin/",
|
|
@@ -57,7 +58,8 @@
|
|
|
57
58
|
"jest": "^30.3.0",
|
|
58
59
|
"lint-staged": "^16.4.0",
|
|
59
60
|
"lockfile-lint": "^5.0.0",
|
|
60
|
-
"prettier": "^3.6.2"
|
|
61
|
+
"prettier": "^3.6.2",
|
|
62
|
+
"semantic-release": "25.0.3"
|
|
61
63
|
},
|
|
62
64
|
"lint-staged": {
|
|
63
65
|
"**/*.js": [
|
package/scripts/build.js
CHANGED
|
@@ -3,15 +3,46 @@
|
|
|
3
3
|
const fs = require('fs/promises')
|
|
4
4
|
const path = require('path')
|
|
5
5
|
|
|
6
|
-
const TOP_PACKAGES_ASSET_URL =
|
|
7
|
-
'https://github.com/lirantal/npm-rank/releases/download/latest/list-package-names.json'
|
|
8
|
-
|
|
9
6
|
const TOP_PACKAGES_FILE_PATH = path.join(__dirname, '../data/top-packages.json')
|
|
7
|
+
const NPM_HIGH_IMPACT_TOP_PACKAGES_URL = 'https://unpkg.com/npm-high-impact@1.13.0/lib/top.js'
|
|
8
|
+
const TOP_PACKAGES_EXPORT_PATTERN = /^export const top = \[\n([\s\S]*)\n\]\n?$/
|
|
9
|
+
const TOP_PACKAGE_NAME_PATTERN = /^[ ]{2}'([^'\\]+)',?$/
|
|
10
|
+
|
|
11
|
+
function parseTopPackages(source) {
|
|
12
|
+
const topPackagesExport = source.match(TOP_PACKAGES_EXPORT_PATTERN)
|
|
13
|
+
|
|
14
|
+
if (!topPackagesExport) {
|
|
15
|
+
throw new Error('Unexpected npm-high-impact top packages export format')
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const topPackages = topPackagesExport[1].split('\n').map((line) => {
|
|
19
|
+
const packageName = line.match(TOP_PACKAGE_NAME_PATTERN)
|
|
20
|
+
|
|
21
|
+
if (!packageName) {
|
|
22
|
+
throw new Error(`Unexpected npm-high-impact package entry: ${line}`)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return packageName[1]
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
if (topPackages.length === 0) {
|
|
29
|
+
throw new Error('npm-high-impact top packages export is empty')
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return [...new Set(topPackages)]
|
|
33
|
+
}
|
|
10
34
|
|
|
11
35
|
async function downloadTopPackages() {
|
|
12
|
-
|
|
13
|
-
const
|
|
14
|
-
|
|
36
|
+
// Keep this pinned to a published npm-high-impact artifact for reproducible builds.
|
|
37
|
+
const response = await fetch(NPM_HIGH_IMPACT_TOP_PACKAGES_URL)
|
|
38
|
+
|
|
39
|
+
if (!response.ok) {
|
|
40
|
+
throw new Error(
|
|
41
|
+
`Failed to download npm-high-impact top packages: ${response.status} ${response.statusText}`
|
|
42
|
+
)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return parseTopPackages(await response.text())
|
|
15
46
|
}
|
|
16
47
|
|
|
17
48
|
async function saveTopPackagesToFile() {
|