npq 3.11.3 → 3.11.4

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.
@@ -19,48 +19,47 @@ class Marshall extends BaseMarshall {
19
19
  return 'Checking package maturity'
20
20
  }
21
21
 
22
- validate(pkg) {
23
- let packageData = null
24
- return this.packageRepoUtils
25
- .getPackageInfo(pkg.packageName)
26
- .then((data) => {
27
- if (data && data.time && data.time.created) {
28
- packageData = data
29
- const pkgCreatedDate = data.time.created
30
- const dateDiff = Date.now() - Date.parse(pkgCreatedDate)
22
+ async validate(pkg) {
23
+ const data = await this.packageRepoUtils.getPackageInfo(pkg.packageName)
31
24
 
32
- if (dateDiff < PACKAGE_AGE_THRESHOLD) {
33
- throw new Error(
34
- `Detected a newly published package (created < ${PACKAGE_AGE_THRESHOLD} days) act carefully`
35
- )
36
- }
25
+ if (!data || !data.time || !data.time.created) {
26
+ throw new Warning('Could not determine package age')
27
+ }
37
28
 
38
- return pkg
39
- } else {
40
- throw new Warning('Could not determine package age')
41
- }
42
- })
43
- .then((pkg) => {
44
- return this.packageRepoUtils.getSemVer(pkg.packageName, pkg.packageVersion)
45
- })
46
- .then((versionResolved) => {
47
- const versionReleaseDate = packageData.time[versionResolved]
48
- const versionDateDiff = new Date() - new Date(versionReleaseDate)
29
+ const pkgCreatedDate = data.time.created
30
+ const dateDiff = Date.now() - Date.parse(pkgCreatedDate)
49
31
 
50
- const versionDateDiffInDays = Math.round(versionDateDiff / (1000 * 60 * 60 * 24))
32
+ if (dateDiff < PACKAGE_AGE_THRESHOLD) {
33
+ throw new Error(
34
+ `Detected a newly published package (created < ${PACKAGE_AGE_THRESHOLD} days) act carefully`
35
+ )
36
+ }
51
37
 
52
- let timeAgoText = 'days'
53
- let timeAgoNumber = versionDateDiffInDays
38
+ const packageVersion = await this.resolvePackageVersion(
39
+ pkg.packageName,
40
+ pkg.packageVersion,
41
+ data
42
+ )
54
43
 
55
- if (versionDateDiffInDays >= 365) {
56
- timeAgoText = 'years'
57
- timeAgoNumber = Math.floor(versionDateDiffInDays / 365)
58
- }
44
+ if (!packageVersion || !data.time[packageVersion]) {
45
+ throw new Warning('Could not determine package version release date')
46
+ }
59
47
 
60
- if (versionDateDiffInDays >= PACKAGE_AGE_UNMAINTAINED_RISK) {
61
- throw new Warning(`Detected an old package (created ${timeAgoNumber} ${timeAgoText} ago)`)
62
- }
63
- })
48
+ const versionReleaseDate = data.time[packageVersion]
49
+ const versionDateDiff = new Date() - new Date(versionReleaseDate)
50
+ const versionDateDiffInDays = Math.round(versionDateDiff / (1000 * 60 * 60 * 24))
51
+
52
+ let timeAgoText = 'days'
53
+ let timeAgoNumber = versionDateDiffInDays
54
+
55
+ if (versionDateDiffInDays >= 365) {
56
+ timeAgoText = 'years'
57
+ timeAgoNumber = Math.floor(versionDateDiffInDays / 365)
58
+ }
59
+
60
+ if (versionDateDiffInDays >= PACKAGE_AGE_UNMAINTAINED_RISK) {
61
+ throw new Warning(`Detected an old package (created ${timeAgoNumber} ${timeAgoText} ago)`)
62
+ }
64
63
  }
65
64
  }
66
65
 
@@ -67,6 +67,32 @@ class BaseMarshall {
67
67
  message: msg.message
68
68
  })
69
69
  }
70
+
71
+ /**
72
+ * Resolves a package version string to an actual semver version
73
+ * Handles dist-tags (latest, beta, etc.) and direct semver versions
74
+ * @param {string} packageName - The package name
75
+ * @param {string} versionSpec - The version specification (could be dist-tag or semver)
76
+ * @param {Object} packageData - Optional package data to avoid re-fetching
77
+ * @returns {Promise<string|null>} - The resolved semver version or null if not found
78
+ */
79
+ async resolvePackageVersion(packageName, versionSpec, packageData = null) {
80
+ // Get package data if not provided
81
+ const data = packageData || (await this.packageRepoUtils.getPackageInfo(packageName))
82
+
83
+ if (!data || !data['dist-tags']) {
84
+ return null
85
+ }
86
+
87
+ // Check if versionSpec is a dist-tag
88
+ if (Object.prototype.hasOwnProperty.call(data['dist-tags'], versionSpec)) {
89
+ return data['dist-tags'][versionSpec]
90
+ }
91
+
92
+ // If not a dist-tag, try parsing as semver
93
+ const parsed = this.packageRepoUtils.parsePackageVersion(versionSpec)
94
+ return parsed ? parsed.version : null
95
+ }
70
96
  }
71
97
 
72
98
  module.exports = BaseMarshall
@@ -16,27 +16,32 @@ class Marshall extends BaseMarshall {
16
16
  return 'Checking package for deprecation flag'
17
17
  }
18
18
 
19
- validate(pkg) {
20
- return this.packageRepoUtils.getPackageInfo(pkg.packageName).then((data) => {
21
- const packageVersion =
22
- pkg.packageVersion === 'latest'
23
- ? data['dist-tags'] && data['dist-tags'].latest
24
- : this.packageRepoUtils.parsePackageVersion(pkg.packageVersion).version
25
-
26
- if (!packageVersion) {
27
- return true
28
- }
29
-
30
- const packageDeprecated =
31
- data &&
32
- data.versions &&
33
- data.versions[packageVersion] &&
34
- data.versions[packageVersion].deprecated
35
-
36
- if (packageDeprecated) {
37
- throw new Error(`Package deprecated: ${packageDeprecated}`)
38
- }
39
- })
19
+ async validate(pkg) {
20
+ const data = await this.packageRepoUtils.getPackageInfo(pkg.packageName)
21
+
22
+ if (!data) {
23
+ return true
24
+ }
25
+
26
+ const packageVersion = await this.resolvePackageVersion(
27
+ pkg.packageName,
28
+ pkg.packageVersion,
29
+ data
30
+ )
31
+
32
+ if (!packageVersion) {
33
+ return true
34
+ }
35
+
36
+ const packageDeprecated =
37
+ data &&
38
+ data.versions &&
39
+ data.versions[packageVersion] &&
40
+ data.versions[packageVersion].deprecated
41
+
42
+ if (packageDeprecated) {
43
+ throw new Error(`Package deprecated: ${packageDeprecated}`)
44
+ }
40
45
  }
41
46
  }
42
47
 
@@ -25,9 +25,10 @@ class NewBinMarshall extends BaseMarshall {
25
25
  return
26
26
  }
27
27
 
28
- const targetVersionString = await this.packageRepoUtils.getSemVer(
28
+ const targetVersionString = await this.resolvePackageVersion(
29
29
  pkg.packageName,
30
- pkg.packageVersion
30
+ pkg.packageVersion,
31
+ fullPackageInfo
31
32
  )
32
33
 
33
34
  if (!targetVersionString || !fullPackageInfo.versions[targetVersionString]) {
@@ -22,6 +22,8 @@ class Marshall extends BaseMarshall {
22
22
  validate(pkg) {
23
23
  const validationMetadata = {}
24
24
 
25
+ // removed debug log
26
+
25
27
  return (
26
28
  this.packageRepoUtils
27
29
  .getPackageInfo(pkg.packageName)
@@ -16,40 +16,46 @@ class Marshall extends BaseMarshall {
16
16
  return 'Checking package for pre/post install scripts'
17
17
  }
18
18
 
19
- validate(pkg) {
20
- return this.packageRepoUtils.getPackageInfo(pkg.packageName).then((data) => {
21
- const packageVersion =
22
- pkg.packageVersion === 'latest'
23
- ? data['dist-tags'] && data['dist-tags'].latest
24
- : this.packageRepoUtils.parsePackageVersion(pkg.packageVersion).version
25
-
26
- if (!packageVersion) {
27
- return true
28
- }
19
+ async validate(pkg) {
20
+ const data = await this.packageRepoUtils.getPackageInfo(pkg.packageName)
21
+
22
+ if (!data) {
23
+ return true
24
+ }
29
25
 
30
- const packageScripts =
31
- data &&
32
- data.versions &&
33
- data.versions[packageVersion] &&
34
- data.versions[packageVersion].scripts
35
-
36
- // blacklisted scripts due to possible malicious intent:
37
- const blacklistScripts = ['install', 'preinstall', 'postinstall']
38
-
39
- blacklistScripts.forEach((scriptName) => {
40
- if (
41
- packageScripts &&
42
- Object.prototype.hasOwnProperty.call(packageScripts, scriptName) &&
43
- packageScripts[scriptName].length > 0
44
- ) {
45
- throw new Error(
46
- `Detected a possible malicious intent script, audit required: ${scriptName}: ${packageScripts[scriptName]}`
47
- )
48
- }
49
- })
26
+ const packageVersion = await this.resolvePackageVersion(
27
+ pkg.packageName,
28
+ pkg.packageVersion,
29
+ data
30
+ )
50
31
 
32
+ if (!packageVersion) {
51
33
  return true
34
+ }
35
+
36
+ const packageScripts =
37
+ data &&
38
+ data.versions &&
39
+ data.versions[packageVersion] &&
40
+ data.versions[packageVersion].scripts
41
+
42
+ // blacklisted scripts due to possible malicious intent:
43
+ const blacklistScripts = ['install', 'preinstall', 'postinstall']
44
+
45
+ blacklistScripts.forEach((scriptName) => {
46
+ if (
47
+ packageScripts &&
48
+ packageScripts[scriptName] &&
49
+ String(packageScripts[scriptName]).length > 0
50
+ ) {
51
+ const scriptContent = packageScripts[scriptName]
52
+ throw new Error(
53
+ `Detected a possible malicious intent script, audit required: ${scriptName}: ${scriptContent}`
54
+ )
55
+ }
52
56
  })
57
+
58
+ return true
53
59
  }
54
60
  }
55
61
 
@@ -17,50 +17,45 @@ class Marshall extends BaseMarshall {
17
17
  return 'Checking version maturity'
18
18
  }
19
19
 
20
- validate(pkg) {
21
- let packageData = null
22
- return this.packageRepoUtils
23
- .getPackageInfo(pkg.packageName)
24
- .then((data) => {
25
- if (data && data.time) {
26
- packageData = data
27
- return pkg
28
- } else {
29
- throw new Error('Could not determine package version information')
30
- }
31
- })
32
- .then((pkg) => {
33
- return this.packageRepoUtils.getSemVer(pkg.packageName, pkg.packageVersion)
34
- })
35
- .then((versionResolved) => {
36
- const versionReleaseDate = packageData.time[versionResolved]
37
-
38
- if (!versionReleaseDate) {
39
- throw new Error(`Could not determine release date for version ${versionResolved}`)
40
- }
41
-
42
- const versionDateDiff = new Date() - new Date(versionReleaseDate)
43
- const versionDateDiffInDays = Math.round(versionDateDiff / (1000 * 60 * 60 * 24))
44
-
45
- if (versionDateDiffInDays < VERSION_AGE_THRESHOLD) {
46
- let timeAgoText = 'days'
47
- let timeAgoNumber = versionDateDiffInDays
48
-
49
- if (versionDateDiffInDays === 0) {
50
- timeAgoText = 'hours'
51
- const versionDateDiffInHours = Math.round(versionDateDiff / (1000 * 60 * 60))
52
- timeAgoNumber = versionDateDiffInHours
53
- } else if (versionDateDiffInDays === 1) {
54
- timeAgoText = 'day'
55
- }
56
-
57
- throw new Error(
58
- `Detected a recently published version (published ${timeAgoNumber} ${timeAgoText} ago) - consider waiting for community review`
59
- )
60
- }
61
-
62
- return pkg
63
- })
20
+ async validate(pkg) {
21
+ const data = await this.packageRepoUtils.getPackageInfo(pkg.packageName)
22
+
23
+ if (!data || !data.time) {
24
+ throw new Error('Could not determine package version information')
25
+ }
26
+
27
+ const packageVersion = await this.resolvePackageVersion(
28
+ pkg.packageName,
29
+ pkg.packageVersion,
30
+ data
31
+ )
32
+
33
+ if (!packageVersion || !Object.prototype.hasOwnProperty.call(data.time, packageVersion)) {
34
+ throw new Error(`Could not determine release date for version ${packageVersion}`)
35
+ }
36
+
37
+ const versionReleaseDate = data.time[packageVersion]
38
+ const versionDateDiff = new Date() - new Date(versionReleaseDate)
39
+ const versionDateDiffInDays = Math.round(versionDateDiff / (1000 * 60 * 60 * 24))
40
+
41
+ if (versionDateDiffInDays < VERSION_AGE_THRESHOLD) {
42
+ let timeAgoText = 'days'
43
+ let timeAgoNumber = versionDateDiffInDays
44
+
45
+ if (versionDateDiffInDays === 0) {
46
+ timeAgoText = 'hours'
47
+ const versionDateDiffInHours = Math.round(versionDateDiff / (1000 * 60 * 60))
48
+ timeAgoNumber = versionDateDiffInHours
49
+ } else if (versionDateDiffInDays === 1) {
50
+ timeAgoText = 'day'
51
+ }
52
+
53
+ throw new Error(
54
+ `Detected a recently published version (published ${timeAgoNumber} ${timeAgoText} ago) - consider waiting for community review`
55
+ )
56
+ }
57
+
58
+ return pkg
64
59
  }
65
60
  }
66
61
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "npq",
3
- "version": "3.11.3",
3
+ "version": "3.11.4",
4
4
  "description": "marshall your npm/npm package installs with high quality and class 🎖",
5
5
  "bin": {
6
6
  "npq": "./bin/npq.js",