summaryrefslogtreecommitdiff
path: root/deps/npm/node_modules/libnpmpublish/publish.js
diff options
context:
space:
mode:
authorKat Marchán <kzm@zkat.tech>2019-01-29 14:43:00 -0800
committerMyles Borins <mylesborins@google.com>2019-02-12 00:06:29 -0800
commit43dd49c9782848c25e5b03448c8a0f923f13c158 (patch)
treef7ac5d645019b2b844f26be66c291bbae734d097 /deps/npm/node_modules/libnpmpublish/publish.js
parentb361f9577fbd72e518438d3fa0b01f7d34d814a5 (diff)
downloadandroid-node-v8-43dd49c9782848c25e5b03448c8a0f923f13c158.tar.gz
android-node-v8-43dd49c9782848c25e5b03448c8a0f923f13c158.tar.bz2
android-node-v8-43dd49c9782848c25e5b03448c8a0f923f13c158.zip
deps: upgrade npm to 6.7.0
PR-URL: https://github.com/nodejs/node/pull/25804 Reviewed-By: Myles Borins <myles.borins@gmail.com>
Diffstat (limited to 'deps/npm/node_modules/libnpmpublish/publish.js')
-rw-r--r--deps/npm/node_modules/libnpmpublish/publish.js218
1 files changed, 218 insertions, 0 deletions
diff --git a/deps/npm/node_modules/libnpmpublish/publish.js b/deps/npm/node_modules/libnpmpublish/publish.js
new file mode 100644
index 0000000000..de5af4f5d3
--- /dev/null
+++ b/deps/npm/node_modules/libnpmpublish/publish.js
@@ -0,0 +1,218 @@
+'use strict'
+
+const cloneDeep = require('lodash.clonedeep')
+const figgyPudding = require('figgy-pudding')
+const { fixer } = require('normalize-package-data')
+const getStream = require('get-stream')
+const npa = require('npm-package-arg')
+const npmAuth = require('npm-registry-fetch/auth.js')
+const npmFetch = require('npm-registry-fetch')
+const semver = require('semver')
+const ssri = require('ssri')
+const url = require('url')
+const validate = require('aproba')
+
+const PublishConfig = figgyPudding({
+ access: {},
+ algorithms: { default: ['sha512'] },
+ npmVersion: {},
+ tag: { default: 'latest' },
+ Promise: { default: () => Promise }
+})
+
+module.exports = publish
+function publish (manifest, tarball, opts) {
+ opts = PublishConfig(opts)
+ return new opts.Promise(resolve => resolve()).then(() => {
+ validate('OSO|OOO', [manifest, tarball, opts])
+ if (manifest.private) {
+ throw Object.assign(new Error(
+ 'This package has been marked as private\n' +
+ "Remove the 'private' field from the package.json to publish it."
+ ), { code: 'EPRIVATE' })
+ }
+ const spec = npa.resolve(manifest.name, manifest.version)
+ // NOTE: spec is used to pick the appropriate registry/auth combo.
+ opts = opts.concat(manifest.publishConfig, { spec })
+ const reg = npmFetch.pickRegistry(spec, opts)
+ const auth = npmAuth(reg, opts)
+ const pubManifest = patchedManifest(spec, auth, manifest, opts)
+
+ // registry-frontdoor cares about the access level, which is only
+ // configurable for scoped packages
+ if (!spec.scope && opts.access === 'restricted') {
+ throw Object.assign(
+ new Error("Can't restrict access to unscoped packages."),
+ { code: 'EUNSCOPED' }
+ )
+ }
+
+ return slurpTarball(tarball, opts).then(tardata => {
+ const metadata = buildMetadata(
+ spec, auth, reg, pubManifest, tardata, opts
+ )
+ return npmFetch(spec.escapedName, opts.concat({
+ method: 'PUT',
+ body: metadata,
+ ignoreBody: true
+ })).catch(err => {
+ if (err.code !== 'E409') { throw err }
+ return npmFetch.json(spec.escapedName, opts.concat({
+ query: { write: true }
+ })).then(
+ current => patchMetadata(current, metadata, opts)
+ ).then(newMetadata => {
+ return npmFetch(spec.escapedName, opts.concat({
+ method: 'PUT',
+ body: newMetadata,
+ ignoreBody: true
+ }))
+ })
+ })
+ })
+ }).then(() => true)
+}
+
+function patchedManifest (spec, auth, base, opts) {
+ const manifest = cloneDeep(base)
+ manifest._nodeVersion = process.versions.node
+ if (opts.npmVersion) {
+ manifest._npmVersion = opts.npmVersion
+ }
+ if (auth.username || auth.email) {
+ // NOTE: This is basically pointless, but reproduced because it's what
+ // legacy does: tl;dr `auth.username` and `auth.email` are going to be
+ // undefined in any auth situation that uses tokens instead of plain
+ // auth. I can only assume some registries out there decided that
+ // _npmUser would be of any use to them, but _npmUser in packuments
+ // currently gets filled in by the npm registry itself, based on auth
+ // information.
+ manifest._npmUser = {
+ name: auth.username,
+ email: auth.email
+ }
+ }
+
+ fixer.fixNameField(manifest, { strict: true, allowLegacyCase: true })
+ const version = semver.clean(manifest.version)
+ if (!version) {
+ throw Object.assign(
+ new Error('invalid semver: ' + manifest.version),
+ { code: 'EBADSEMVER' }
+ )
+ }
+ manifest.version = version
+ return manifest
+}
+
+function buildMetadata (spec, auth, registry, manifest, tardata, opts) {
+ const root = {
+ _id: manifest.name,
+ name: manifest.name,
+ description: manifest.description,
+ 'dist-tags': {},
+ versions: {},
+ readme: manifest.readme || ''
+ }
+
+ if (opts.access) root.access = opts.access
+
+ if (!auth.token) {
+ root.maintainers = [{ name: auth.username, email: auth.email }]
+ manifest.maintainers = JSON.parse(JSON.stringify(root.maintainers))
+ }
+
+ root.versions[ manifest.version ] = manifest
+ const tag = manifest.tag || opts.tag
+ root['dist-tags'][tag] = manifest.version
+
+ const tbName = manifest.name + '-' + manifest.version + '.tgz'
+ const tbURI = manifest.name + '/-/' + tbName
+ const integrity = ssri.fromData(tardata, {
+ algorithms: [...new Set(['sha1'].concat(opts.algorithms))]
+ })
+
+ manifest._id = manifest.name + '@' + manifest.version
+ manifest.dist = manifest.dist || {}
+ // Don't bother having sha1 in the actual integrity field
+ manifest.dist.integrity = integrity['sha512'][0].toString()
+ // Legacy shasum support
+ manifest.dist.shasum = integrity['sha1'][0].hexDigest()
+ manifest.dist.tarball = url.resolve(registry, tbURI)
+ .replace(/^https:\/\//, 'http://')
+
+ root._attachments = {}
+ root._attachments[ tbName ] = {
+ 'content_type': 'application/octet-stream',
+ 'data': tardata.toString('base64'),
+ 'length': tardata.length
+ }
+
+ return root
+}
+
+function patchMetadata (current, newData, opts) {
+ const curVers = Object.keys(current.versions || {}).map(v => {
+ return semver.clean(v, true)
+ }).concat(Object.keys(current.time || {}).map(v => {
+ if (semver.valid(v, true)) { return semver.clean(v, true) }
+ })).filter(v => v)
+
+ const newVersion = Object.keys(newData.versions)[0]
+
+ if (curVers.indexOf(newVersion) !== -1) {
+ throw ConflictError(newData.name, newData.version)
+ }
+
+ current.versions = current.versions || {}
+ current.versions[newVersion] = newData.versions[newVersion]
+ for (var i in newData) {
+ switch (i) {
+ // objects that copy over the new stuffs
+ case 'dist-tags':
+ case 'versions':
+ case '_attachments':
+ for (var j in newData[i]) {
+ current[i] = current[i] || {}
+ current[i][j] = newData[i][j]
+ }
+ break
+
+ // ignore these
+ case 'maintainers':
+ break
+
+ // copy
+ default:
+ current[i] = newData[i]
+ }
+ }
+ const maint = newData.maintainers && JSON.parse(JSON.stringify(newData.maintainers))
+ newData.versions[newVersion].maintainers = maint
+ return current
+}
+
+function slurpTarball (tarSrc, opts) {
+ if (Buffer.isBuffer(tarSrc)) {
+ return opts.Promise.resolve(tarSrc)
+ } else if (typeof tarSrc === 'string') {
+ return opts.Promise.resolve(Buffer.from(tarSrc, 'base64'))
+ } else if (typeof tarSrc.pipe === 'function') {
+ return getStream.buffer(tarSrc)
+ } else {
+ return opts.Promise.reject(Object.assign(
+ new Error('invalid tarball argument. Must be a Buffer, a base64 string, or a binary stream'), {
+ code: 'EBADTAR'
+ }))
+ }
+}
+
+function ConflictError (pkgid, version) {
+ return Object.assign(new Error(
+ `Cannot publish ${pkgid}@${version} over existing version.`
+ ), {
+ code: 'EPUBLISHCONFLICT',
+ pkgid,
+ version
+ })
+}