npq 3.7.0 → 3.8.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.
|
@@ -53,3 +53,54 @@ test('running marshall tasks fails', async () => {
|
|
|
53
53
|
|
|
54
54
|
await expect(marshalls.tasks(config)).resolves.toMatchObject(context)
|
|
55
55
|
})
|
|
56
|
+
|
|
57
|
+
test('running marshall tasks throws error when single package is not found', async () => {
|
|
58
|
+
const PackageRepoUtilsNotFoundMock = class Fake {
|
|
59
|
+
getPackageInfo() {
|
|
60
|
+
return Promise.resolve({ error: 'Not found' })
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
marshalls.collectMarshalls = jest.fn(() => {
|
|
65
|
+
return Promise.resolve([path.join(process.cwd(), '__tests__/__fixtures__/test.marshall.js')])
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
const config = {
|
|
69
|
+
pkgs: [{ packageName: 'nonexistent-package' }],
|
|
70
|
+
packageRepoUtils: new PackageRepoUtilsNotFoundMock()
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
await expect(marshalls.tasks(config)).resolves.toEqual({
|
|
74
|
+
error: true,
|
|
75
|
+
message: 'Package not found: nonexistent-package'
|
|
76
|
+
})
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
test('running marshall tasks filters out not found packages when multiple packages provided', async () => {
|
|
80
|
+
const PackageRepoUtilsMixedMock = class Fake {
|
|
81
|
+
getPackageInfo(packageName) {
|
|
82
|
+
if (packageName === 'nonexistent-package') {
|
|
83
|
+
return Promise.resolve({ error: 'Not found' })
|
|
84
|
+
}
|
|
85
|
+
return Promise.resolve(true)
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
marshalls.collectMarshalls = jest.fn(() => {
|
|
90
|
+
return Promise.resolve([path.join(process.cwd(), '__tests__/__fixtures__/test.marshall.js')])
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
const config = {
|
|
94
|
+
pkgs: [
|
|
95
|
+
{ packageName: 'express' },
|
|
96
|
+
{ packageName: 'nonexistent-package' },
|
|
97
|
+
{ packageName: 'semver' }
|
|
98
|
+
],
|
|
99
|
+
packageRepoUtils: new PackageRepoUtilsMixedMock()
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const result = await marshalls.tasks(config)
|
|
103
|
+
// Should filter out the nonexistent package and keep only express and semver
|
|
104
|
+
expect(result.pkgs).toHaveLength(2)
|
|
105
|
+
expect(result.pkgs).toEqual([{ packageName: 'express' }, { packageName: 'semver' }])
|
|
106
|
+
})
|
|
@@ -160,3 +160,92 @@ test('repo utils returns valid semver for different cases of version asked', asy
|
|
|
160
160
|
'could not find dist-tag next for package testPackage'
|
|
161
161
|
)
|
|
162
162
|
})
|
|
163
|
+
|
|
164
|
+
test('repo utils resolves semver ranges by finding the highest satisfying version', async () => {
|
|
165
|
+
const PackageRepoUtils = require('../lib/helpers/packageRepoUtils')
|
|
166
|
+
global.fetch = jest.fn().mockImplementation(() =>
|
|
167
|
+
Promise.resolve({
|
|
168
|
+
json: () => require('./mocks/registryPackageOk.mock.json')
|
|
169
|
+
})
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
const packageRepoUtils = new PackageRepoUtils()
|
|
173
|
+
const packageName = 'testPackage'
|
|
174
|
+
|
|
175
|
+
// Test major version range - should find highest 3.x version (3.1.0)
|
|
176
|
+
let result = await packageRepoUtils.getSemVer(packageName, '^3.0.0')
|
|
177
|
+
expect(result).toEqual('3.1.0')
|
|
178
|
+
|
|
179
|
+
// Test simple major version - should find highest 3.x version (3.1.0)
|
|
180
|
+
result = await packageRepoUtils.getSemVer(packageName, '3')
|
|
181
|
+
expect(result).toEqual('3.1.0')
|
|
182
|
+
|
|
183
|
+
// Test tilde range - should find 3.1.x version (3.1.0)
|
|
184
|
+
result = await packageRepoUtils.getSemVer(packageName, '~3.1.0')
|
|
185
|
+
expect(result).toEqual('3.1.0')
|
|
186
|
+
|
|
187
|
+
// Test invalid semver range that doesn't match any version
|
|
188
|
+
await expect(packageRepoUtils.getSemVer(packageName, '^10.0.0')).rejects.toThrow(
|
|
189
|
+
'could not find dist-tag ^10.0.0 for package testPackage'
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
// Test invalid semver range with version 2 (no 2.x versions in mock)
|
|
193
|
+
await expect(packageRepoUtils.getSemVer(packageName, '2')).rejects.toThrow(
|
|
194
|
+
'could not find dist-tag 2 for package testPackage'
|
|
195
|
+
)
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
test('repo utils resolves semver ranges with multiple versions', async () => {
|
|
199
|
+
const PackageRepoUtils = require('../lib/helpers/packageRepoUtils')
|
|
200
|
+
|
|
201
|
+
// Create a more comprehensive mock that includes multiple versions
|
|
202
|
+
const comprehensiveMock = {
|
|
203
|
+
name: '@astrojs/vue',
|
|
204
|
+
'dist-tags': {
|
|
205
|
+
latest: '4.5.0'
|
|
206
|
+
},
|
|
207
|
+
versions: {
|
|
208
|
+
'1.2.0': { name: '@astrojs/vue', version: '1.2.0' },
|
|
209
|
+
'2.0.0': { name: '@astrojs/vue', version: '2.0.0' },
|
|
210
|
+
'2.1.0': { name: '@astrojs/vue', version: '2.1.0' },
|
|
211
|
+
'2.2.1': { name: '@astrojs/vue', version: '2.2.1' },
|
|
212
|
+
'3.0.0': { name: '@astrojs/vue', version: '3.0.0' },
|
|
213
|
+
'3.1.0': { name: '@astrojs/vue', version: '3.1.0' },
|
|
214
|
+
'3.2.2': { name: '@astrojs/vue', version: '3.2.2' },
|
|
215
|
+
'4.0.0': { name: '@astrojs/vue', version: '4.0.0' },
|
|
216
|
+
'4.5.0': { name: '@astrojs/vue', version: '4.5.0' }
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
global.fetch = jest.fn().mockImplementation(() =>
|
|
221
|
+
Promise.resolve({
|
|
222
|
+
json: () => comprehensiveMock
|
|
223
|
+
})
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
const packageRepoUtils = new PackageRepoUtils()
|
|
227
|
+
const packageName = '@astrojs/vue'
|
|
228
|
+
|
|
229
|
+
// Test the problematic case mentioned in the issue: "@astrojs/vue@3"
|
|
230
|
+
let result = await packageRepoUtils.getSemVer(packageName, '3')
|
|
231
|
+
expect(result).toEqual('3.2.2') // Should find highest 3.x version
|
|
232
|
+
|
|
233
|
+
// Test other major versions
|
|
234
|
+
result = await packageRepoUtils.getSemVer(packageName, '2')
|
|
235
|
+
expect(result).toEqual('2.2.1') // Should find highest 2.x version
|
|
236
|
+
|
|
237
|
+
result = await packageRepoUtils.getSemVer(packageName, '4')
|
|
238
|
+
expect(result).toEqual('4.5.0') // Should find highest 4.x version
|
|
239
|
+
|
|
240
|
+
// Test caret ranges
|
|
241
|
+
result = await packageRepoUtils.getSemVer(packageName, '^3.0.0')
|
|
242
|
+
expect(result).toEqual('3.2.2')
|
|
243
|
+
|
|
244
|
+
result = await packageRepoUtils.getSemVer(packageName, '^2.1.0')
|
|
245
|
+
expect(result).toEqual('2.2.1')
|
|
246
|
+
|
|
247
|
+
// Test that non-existent major versions still fail appropriately
|
|
248
|
+
await expect(packageRepoUtils.getSemVer(packageName, '10')).rejects.toThrow(
|
|
249
|
+
'could not find dist-tag 10 for package @astrojs/vue'
|
|
250
|
+
)
|
|
251
|
+
})
|
|
@@ -64,13 +64,28 @@ class PackageRepoUtils {
|
|
|
64
64
|
throw new Error(`could not find dist-tags for package ${packageName}`)
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
if (packageInfo['dist-tags'][packageVersion]
|
|
68
|
-
|
|
67
|
+
if (packageInfo['dist-tags'][packageVersion] !== undefined) {
|
|
68
|
+
const semverVersion = packageInfo['dist-tags'][packageVersion]
|
|
69
|
+
return semverVersion
|
|
69
70
|
}
|
|
70
71
|
|
|
71
|
-
|
|
72
|
+
// If not found in dist-tags, try to find the highest version that satisfies
|
|
73
|
+
// the semver range from the versions object
|
|
74
|
+
if (packageInfo.versions) {
|
|
75
|
+
const availableVersions = Object.keys(packageInfo.versions).filter((v) => semver.valid(v))
|
|
72
76
|
|
|
73
|
-
|
|
77
|
+
try {
|
|
78
|
+
const satisfyingVersion = semver.maxSatisfying(availableVersions, packageVersion)
|
|
79
|
+
|
|
80
|
+
if (satisfyingVersion) {
|
|
81
|
+
return satisfyingVersion
|
|
82
|
+
}
|
|
83
|
+
} catch (error) {
|
|
84
|
+
// semver.maxSatisfying throws if the range is invalid, continue to error below
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
throw new Error(`could not find dist-tag ${packageVersion} for package ${packageName}`)
|
|
74
89
|
}
|
|
75
90
|
}
|
|
76
91
|
}
|
package/lib/marshalls/index.js
CHANGED
|
@@ -65,7 +65,26 @@ class Marshalls {
|
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
static tasks(options) {
|
|
68
|
+
// console.log(options);
|
|
69
|
+
// process.exit(1);
|
|
68
70
|
return Marshalls.warmUpPackagesCache(options)
|
|
71
|
+
.then((packagesDataList) => {
|
|
72
|
+
// handle error in case we get just one package and it is not found
|
|
73
|
+
if (packagesDataList && packagesDataList.length === 1) {
|
|
74
|
+
if (packagesDataList[0].error && packagesDataList[0].error === 'Not found') {
|
|
75
|
+
throw new Error(`Package not found: ${options.pkgs[0].packageName}`)
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// handle error in case we get more than one package and at least one is not found
|
|
80
|
+
// in which we case we simply remove the package from the `options` array
|
|
81
|
+
// which lists objects (each have a property of packageName)
|
|
82
|
+
if (packagesDataList && packagesDataList.length > 1) {
|
|
83
|
+
options.pkgs = options.pkgs.filter((pkg, index) => {
|
|
84
|
+
return !packagesDataList[index].error || packagesDataList[index].error !== 'Not found'
|
|
85
|
+
})
|
|
86
|
+
}
|
|
87
|
+
})
|
|
69
88
|
.then(() => Marshalls.collectMarshalls())
|
|
70
89
|
.then((marshalls) => {
|
|
71
90
|
return Marshalls.buildMarshallTasks(marshalls, {
|
|
@@ -75,6 +94,12 @@ class Marshalls {
|
|
|
75
94
|
.then((tasks) => {
|
|
76
95
|
return Marshalls.runTasks(tasks, options)
|
|
77
96
|
})
|
|
97
|
+
.catch((err) => {
|
|
98
|
+
// console.error('Error:', err.message)
|
|
99
|
+
// avoid implementing a custom error message for a not found package
|
|
100
|
+
// because the package manager will yield its own error message
|
|
101
|
+
return { error: true, message: err.message }
|
|
102
|
+
})
|
|
78
103
|
}
|
|
79
104
|
|
|
80
105
|
static warmUpPackagesCache(options) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "npq",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.8.0",
|
|
4
4
|
"description": "marshall your npm/npm package installs with high quality and class 🎖",
|
|
5
5
|
"bin": {
|
|
6
6
|
"npq": "./bin/npq.js",
|
|
@@ -135,7 +135,7 @@
|
|
|
135
135
|
"security/detect-no-csrf-before-method-override": "error",
|
|
136
136
|
"security/detect-non-literal-regexp": "error",
|
|
137
137
|
"security/detect-non-literal-require": "warn",
|
|
138
|
-
"security/detect-object-injection": "
|
|
138
|
+
"security/detect-object-injection": "off",
|
|
139
139
|
"security/detect-possible-timing-attacks": "error",
|
|
140
140
|
"security/detect-pseudoRandomBytes": "error",
|
|
141
141
|
"node/no-unsupported-features/node-builtins": [
|