Skip to content

Commit 577bbb0

Browse files
author
test
committed
feat(plugin-api): allow non-semver versioned dependencies (vuejs#1177)
npm supports multiple "version" strings when declaring deps in your `package.json`. This PR is an attempt to support some of these other formats in a plugin specification, while retaining the smart version merging. If a semver range can be extracted, it will be used for version conflict resolution. If not, a warning will be displayed to the developer
1 parent a0a7dc6 commit 577bbb0

File tree

2 files changed

+120
-4
lines changed

2 files changed

+120
-4
lines changed

packages/@vue/cli/__tests__/Generator.spec.js

+107
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,79 @@ test('api: extendPackage function', async () => {
114114
})
115115
})
116116

117+
test('api: extendPackage allow git, github, http, file version ranges', async () => {
118+
const generator = new Generator('/', { plugins: [
119+
{
120+
id: 'test',
121+
apply: api => {
122+
api.extendPackage({
123+
dependencies: {
124+
foo: 'git+ssh://[email protected]:npm/npm.git#v1.0.27',
125+
baz: 'git://github.com/npm/npm.git#v1.0.27',
126+
bar: 'expressjs/express',
127+
bad: 'mochajs/mocha#4727d357ea',
128+
bac: 'http://asdf.com/asdf.tar.gz',
129+
bae: 'file:../dyl',
130+
'my-lib': 'https://bitbucket.org/user/my-lib.git#semver:^1.0.0'
131+
}
132+
})
133+
}
134+
}
135+
] })
136+
137+
await generator.generate()
138+
139+
const pkg = JSON.parse(fs.readFileSync('/package.json', 'utf-8'))
140+
expect(pkg).toEqual({
141+
dependencies: {
142+
foo: 'git+ssh://[email protected]:npm/npm.git#v1.0.27',
143+
baz: 'git://github.com/npm/npm.git#v1.0.27',
144+
bar: 'expressjs/express',
145+
bad: 'mochajs/mocha#4727d357ea',
146+
bac: 'http://asdf.com/asdf.tar.gz',
147+
bae: 'file:../dyl',
148+
'my-lib': 'https://bitbucket.org/user/my-lib.git#semver:^1.0.0'
149+
}
150+
})
151+
})
152+
153+
test('api: extendPackage merge nonstrictly semver deps', async () => {
154+
const generator = new Generator('/', { plugins: [
155+
{
156+
id: 'test',
157+
apply: api => {
158+
api.extendPackage({
159+
dependencies: {
160+
'my-lib': 'https://bitbucket.org/user/my-lib.git#semver:1.0.0',
161+
bar: 'expressjs/express'
162+
}
163+
})
164+
}
165+
},
166+
{
167+
id: 'test2',
168+
apply: api => {
169+
api.extendPackage({
170+
dependencies: {
171+
'my-lib': 'https://bitbucket.org/user/my-lib.git#semver:1.2.0',
172+
bar: 'expressjs/express'
173+
}
174+
})
175+
}
176+
}
177+
] })
178+
179+
await generator.generate()
180+
181+
const pkg = JSON.parse(fs.readFileSync('/package.json', 'utf-8'))
182+
expect(pkg).toEqual({
183+
dependencies: {
184+
'my-lib': 'https://bitbucket.org/user/my-lib.git#semver:1.2.0',
185+
bar: 'expressjs/express'
186+
}
187+
})
188+
})
189+
117190
test('api: extendPackage merge dependencies', async () => {
118191
const generator = new Generator('/', { plugins: [
119192
{
@@ -208,6 +281,40 @@ test('api: extendPackage dependencies conflict', async () => {
208281
})).toBe(true)
209282
})
210283

284+
test('api: extendPackage merge warn nonstrictly semver deps', async () => {
285+
new Generator('/', { plugins: [
286+
{
287+
id: 'test3',
288+
apply: api => {
289+
api.extendPackage({
290+
dependencies: {
291+
bar: 'expressjs/express'
292+
}
293+
})
294+
}
295+
},
296+
{
297+
id: 'test4',
298+
apply: api => {
299+
api.extendPackage({
300+
dependencies: {
301+
bar: 'expressjs/express#1234'
302+
}
303+
})
304+
}
305+
}
306+
] })
307+
308+
expect(logs.warn.some(([msg]) => {
309+
return (
310+
msg.match(/conflicting versions for project dependency "bar"/) &&
311+
msg.match(/expressjs\/express injected by generator "test3"/) &&
312+
msg.match(/expressjs\/express#1234 injected by generator "test4"/) &&
313+
msg.match(/Using version \(expressjs\/express\)/)
314+
)
315+
})).toBe(true)
316+
})
317+
211318
test('api: render fs directory', async () => {
212319
const generator = new Generator('/', { plugins: [
213320
{

packages/@vue/cli/lib/util/mergeDeps.js

+13-4
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,13 @@ module.exports = function resolveDeps (generatorId, to, from, sources) {
77
const r1 = to[name]
88
const r2 = from[name]
99
const sourceGeneratorId = sources[name]
10+
const isValidURI = r2.match(/^(?:file|git|git\+ssh|git\+http|git\+https|git\+file|https?):/) != null
11+
const isValidGitHub = r2.match(/^[^/]+\/[^/]+/) != null
1012

11-
if (!semver.validRange(r2)) {
13+
// if they are the same, do nothing. Helps when non semver type deps are used
14+
if (r1 === r2) continue
15+
16+
if (!isValidGitHub && !isValidURI && !semver.validRange(r2)) {
1217
warn(
1318
`invalid version range for dependency "${name}":\n\n` +
1419
`- ${r2} injected by generator "${generatorId}"`
@@ -20,17 +25,19 @@ module.exports = function resolveDeps (generatorId, to, from, sources) {
2025
res[name] = r2
2126
sources[name] = generatorId
2227
} else {
23-
const r = tryGetNewerRange(r1, r2)
28+
const r1semver = extractSemver(r1)
29+
const r2semver = extractSemver(r2)
30+
const r = tryGetNewerRange(r1semver, r2semver)
2431
const didGetNewer = !!r
2532
// if failed to infer newer version, use existing one because it's likely
2633
// built-in
27-
res[name] = didGetNewer ? r : r1
34+
res[name] = didGetNewer ? injectSemver(r2, r) : r1
2835
// if changed, update source
2936
if (res[name] === r2) {
3037
sources[name] = generatorId
3138
}
3239
// warn incompatible version requirements
33-
if (!semver.intersects(r1, r2)) {
40+
if (!semver.validRange(r1semver) || !semver.validRange(r2semver) || !semver.intersects(r1semver, r2semver)) {
3441
warn(
3542
`conflicting versions for project dependency "${name}":\n\n` +
3643
`- ${r1} injected by generator "${sourceGeneratorId}"\n` +
@@ -45,6 +52,8 @@ module.exports = function resolveDeps (generatorId, to, from, sources) {
4552

4653
const leadRE = /^(~|\^|>=?)/
4754
const rangeToVersion = r => r.replace(leadRE, '').replace(/x/g, '0')
55+
const extractSemver = r => r.replace(/^.+#semver:/, '')
56+
const injectSemver = (r, v) => semver.validRange(r) ? v : r.replace(/#semver:.+$/, `#semver:${v}`)
4857

4958
function tryGetNewerRange (r1, r2) {
5059
const v1 = rangeToVersion(r1)

0 commit comments

Comments
 (0)