+85
-22
lines changedFilter options
+85
-22
lines changed Original file line number Diff line number Diff line change
@@ -114,12 +114,14 @@ class Publish extends BaseCommand {
114
114
// so that we send the latest and greatest thing to the registry
115
115
// note that publishConfig might have changed as well!
116
116
manifest = await this.#getManifest(spec, opts, true)
117
-
118
-
const isPreRelease = Boolean(semver.parse(manifest.version).prerelease.length)
117
+
const force = this.npm.config.get('force')
119
118
const isDefaultTag = this.npm.config.isDefault('tag') && !manifest.publishConfig?.tag
120
119
121
-
if (isPreRelease && isDefaultTag) {
122
-
throw new Error('You must specify a tag using --tag when publishing a prerelease version.')
120
+
if (!force) {
121
+
const isPreRelease = Boolean(semver.parse(manifest.version).prerelease.length)
122
+
if (isPreRelease && isDefaultTag) {
123
+
throw new Error('You must specify a tag using --tag when publishing a prerelease version.')
124
+
}
123
125
}
124
126
125
127
// If we are not in JSON mode then we show the user the contents of the tarball
@@ -156,11 +158,18 @@ class Publish extends BaseCommand {
156
158
}
157
159
}
158
160
159
-
const latestVersion = await this.#highestPublishedVersion(resolved, registry)
160
-
const latestSemverIsGreater = !!latestVersion && semver.gte(latestVersion, manifest.version)
161
+
if (!force) {
162
+
const { highestVersion, versions } = await this.#registryVersions(resolved, registry)
163
+
/* eslint-disable-next-line max-len */
164
+
const highestVersionIsGreater = !!highestVersion && semver.gte(highestVersion, manifest.version)
161
165
162
-
if (latestSemverIsGreater && isDefaultTag) {
163
-
throw new Error(`Cannot implicitly apply the "latest" tag because published version ${latestVersion} is higher than the new version ${manifest.version}. You must specify a tag using --tag.`)
166
+
if (versions.includes(manifest.version)) {
167
+
throw new Error(`You cannot publish over the previously published versions: ${manifest.version}.`)
168
+
}
169
+
170
+
if (highestVersionIsGreater && isDefaultTag) {
171
+
throw new Error(`Cannot implicitly apply the "latest" tag because previously published version ${highestVersion} is higher than the new version ${manifest.version}. You must specify a tag using --tag.`)
172
+
}
164
173
}
165
174
166
175
const access = opts.access === null ? 'default' : opts.access
@@ -202,15 +211,15 @@ class Publish extends BaseCommand {
202
211
}
203
212
}
204
213
205
-
async #highestPublishedVersion (spec, registry) {
214
+
async #registryVersions (spec, registry) {
206
215
try {
207
216
const packument = await pacote.packument(spec, {
208
217
...this.npm.flatOptions,
209
218
preferOnline: true,
210
219
registry,
211
220
})
212
221
if (typeof packument?.versions === 'undefined') {
213
-
return null
222
+
return { versions: [], highestVersion: null }
214
223
}
215
224
const ordered = Object.keys(packument?.versions)
216
225
.flatMap(v => {
@@ -221,9 +230,11 @@ class Publish extends BaseCommand {
221
230
return s
222
231
})
223
232
.sort((a, b) => b.compare(a))
224
-
return ordered.length >= 1 ? ordered[0].version : null
233
+
const highestVersion = ordered.length >= 1 ? ordered[0].version : null
234
+
const versions = ordered.map(v => v.version)
235
+
return { versions, highestVersion }
225
236
} catch (e) {
226
-
return null
237
+
return { versions: [], highestVersion: null }
227
238
}
228
239
}
229
240
Original file line number Diff line number Diff line change
@@ -359,16 +359,18 @@ class MockRegistry {
359
359
}
360
360
361
361
publish (name, {
362
-
packageJson, access, noPut, putCode, manifest, packuments,
362
+
packageJson, access, noGet, noPut, putCode, manifest, packuments,
363
363
} = {}) {
364
-
// this getPackage call is used to get the latest semver version before publish
365
-
if (manifest) {
366
-
this.getPackage(name, { code: 200, resp: manifest })
367
-
} else if (packuments) {
368
-
this.getPackage(name, { code: 200, resp: this.manifest({ name, packuments }) })
369
-
} else {
370
-
// assumes the package does not exist yet and will 404 x2 from pacote.manifest
371
-
this.getPackage(name, { times: 2, code: 404 })
364
+
if (!noGet) {
365
+
// this getPackage call is used to get the latest semver version before publish
366
+
if (manifest) {
367
+
this.getPackage(name, { code: 200, resp: manifest })
368
+
} else if (packuments) {
369
+
this.getPackage(name, { code: 200, resp: this.manifest({ name, packuments }) })
370
+
} else {
371
+
// assumes the package does not exist yet and will 404 x2 from pacote.manifest
372
+
this.getPackage(name, { times: 2, code: 404 })
373
+
}
372
374
}
373
375
if (!noPut) {
374
376
this.putPackage(name, { code: putCode, packageJson, access })
Original file line number Diff line number Diff line change
@@ -853,6 +853,28 @@ t.test('prerelease dist tag', (t) => {
853
853
await npm.exec('publish', [])
854
854
})
855
855
856
+
t.test('does not abort when prerelease and force', async t => {
857
+
const packageJson = {
858
+
...pkgJson,
859
+
version: '1.0.0-0',
860
+
publishConfig: { registry: alternateRegistry },
861
+
}
862
+
const { npm, registry } = await loadNpmWithRegistry(t, {
863
+
config: {
864
+
loglevel: 'silent',
865
+
force: true,
866
+
[`${alternateRegistry.slice(6)}/:_authToken`]: 'test-other-token',
867
+
},
868
+
prefixDir: {
869
+
'package.json': JSON.stringify(packageJson, null, 2),
870
+
},
871
+
registry: alternateRegistry,
872
+
authorization: 'test-other-token',
873
+
})
874
+
registry.publish(pkg, { noGet: true, packageJson })
875
+
await npm.exec('publish', [])
876
+
})
877
+
856
878
t.end()
857
879
})
858
880
@@ -886,7 +908,7 @@ t.test('semver highest dist tag', async t => {
886
908
registry.publish(pkg, { noPut: true, packuments })
887
909
await t.rejects(async () => {
888
910
await npm.exec('publish', [])
889
-
}, new Error('Cannot implicitly apply the "latest" tag because published version 100.0.0 is higher than the new version 99.0.0. You must specify a tag using --tag.'))
911
+
}, new Error('Cannot implicitly apply the "latest" tag because previously published version 100.0.0 is higher than the new version 99.0.0. You must specify a tag using --tag.'))
890
912
})
891
913
892
914
await t.test('ALLOWS publish when highest is HIGHER than publishing version and flag', async t => {
@@ -933,4 +955,32 @@ t.test('semver highest dist tag', async t => {
933
955
registry.publish(pkg, { packuments })
934
956
await npm.exec('publish', [])
935
957
})
958
+
959
+
await t.test('PREVENTS publish when latest version is SAME AS publishing version', async t => {
960
+
const version = '100.0.0'
961
+
const { npm, registry } = await loadNpmWithRegistry(t, init({ version }))
962
+
registry.publish(pkg, { noPut: true, packuments })
963
+
await t.rejects(async () => {
964
+
await npm.exec('publish', [])
965
+
}, new Error('You cannot publish over the previously published versions: 100.0.0.'))
966
+
})
967
+
968
+
await t.test('PREVENTS publish when publishing version EXISTS ALREADY in the registry', async t => {
969
+
const version = '50.0.0'
970
+
const { npm, registry } = await loadNpmWithRegistry(t, init({ version }))
971
+
registry.publish(pkg, { noPut: true, packuments })
972
+
await t.rejects(async () => {
973
+
await npm.exec('publish', [])
974
+
}, new Error('You cannot publish over the previously published versions: 50.0.0.'))
975
+
})
976
+
977
+
await t.test('ALLOWS publish when latest is HIGHER than publishing version and flag --force', async t => {
978
+
const version = '99.0.0'
979
+
const { npm, registry } = await loadNpmWithRegistry(t, {
980
+
...init({ version }),
981
+
argv: ['--force'],
982
+
})
983
+
registry.publish(pkg, { noGet: true, packuments })
984
+
await npm.exec('publish', [])
985
+
})
936
986
})
You can’t perform that action at this time.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4