"Fossies" - the Fresh Open Source Software Archive

Member "Atom/resources/app/apm/node_modules/npm-registry-client/lib/publish.js" (8 Mar 2017, 5498 Bytes) of archive /windows/misc/atom-windows.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Javascript source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 module.exports = publish
    2 
    3 var url = require('url')
    4 var semver = require('semver')
    5 var crypto = require('crypto')
    6 var Stream = require('stream').Stream
    7 var assert = require('assert')
    8 var fixer = require('normalize-package-data').fixer
    9 var concat = require('concat-stream')
   10 
   11 function escaped (name) {
   12   return name.replace('/', '%2f')
   13 }
   14 
   15 function publish (uri, params, cb) {
   16   assert(typeof uri === 'string', 'must pass registry URI to publish')
   17   assert(params && typeof params === 'object', 'must pass params to publish')
   18   assert(typeof cb === 'function', 'must pass callback to publish')
   19 
   20   var access = params.access
   21   assert(
   22     (!access) || ['public', 'restricted'].indexOf(access) !== -1,
   23     "if present, access level must be either 'public' or 'restricted'"
   24   )
   25 
   26   var auth = params.auth
   27   assert(auth && typeof auth === 'object', 'must pass auth to publish')
   28   if (!(auth.token ||
   29         (auth.password && auth.username && auth.email))) {
   30     var er = new Error('auth required for publishing')
   31     er.code = 'ENEEDAUTH'
   32     return cb(er)
   33   }
   34 
   35   var metadata = params.metadata
   36   assert(
   37     metadata && typeof metadata === 'object',
   38     'must pass package metadata to publish'
   39   )
   40   try {
   41     fixer.fixNameField(metadata, {strict: true, allowLegacyCase: true})
   42   } catch (er) {
   43     return cb(er)
   44   }
   45   var version = semver.clean(metadata.version)
   46   if (!version) return cb(new Error('invalid semver: ' + metadata.version))
   47   metadata.version = version
   48 
   49   var body = params.body
   50   assert(body, 'must pass package body to publish')
   51   assert(body instanceof Stream, 'package body passed to publish must be a stream')
   52   var client = this
   53   var sink = concat(function (tarbuffer) {
   54     putFirst.call(client, uri, metadata, tarbuffer, access, auth, cb)
   55   })
   56   sink.on('error', cb)
   57   body.pipe(sink)
   58 }
   59 
   60 function putFirst (registry, data, tarbuffer, access, auth, cb) {
   61   // optimistically try to PUT all in one single atomic thing.
   62   // If 409, then GET and merge, try again.
   63   // If other error, then fail.
   64 
   65   var root = {
   66     _id: data.name,
   67     name: data.name,
   68     description: data.description,
   69     'dist-tags': {},
   70     versions: {},
   71     readme: data.readme || ''
   72   }
   73 
   74   if (access) root.access = access
   75 
   76   if (!auth.token) {
   77     root.maintainers = [{ name: auth.username, email: auth.email }]
   78     data.maintainers = JSON.parse(JSON.stringify(root.maintainers))
   79   }
   80 
   81   root.versions[ data.version ] = data
   82   var tag = data.tag || this.config.defaultTag
   83   root['dist-tags'][tag] = data.version
   84 
   85   var tbName = data.name + '-' + data.version + '.tgz'
   86   var tbURI = data.name + '/-/' + tbName
   87 
   88   data._id = data.name + '@' + data.version
   89   data.dist = data.dist || {}
   90   data.dist.shasum = crypto.createHash('sha1').update(tarbuffer).digest('hex')
   91   data.dist.tarball = url.resolve(registry, tbURI)
   92                          .replace(/^https:\/\//, 'http://')
   93 
   94   root._attachments = {}
   95   root._attachments[ tbName ] = {
   96     'content_type': 'application/octet-stream',
   97     'data': tarbuffer.toString('base64'),
   98     'length': tarbuffer.length
   99   }
  100 
  101   var fixed = url.resolve(registry, escaped(data.name))
  102   var client = this
  103   var options = {
  104     method: 'PUT',
  105     body: root,
  106     auth: auth
  107   }
  108   this.request(fixed, options, function (er, parsed, json, res) {
  109     var r409 = 'must supply latest _rev to update existing package'
  110     var r409b = 'Document update conflict.'
  111     var conflict = res && res.statusCode === 409
  112     if (parsed && (parsed.reason === r409 || parsed.reason === r409b)) {
  113       conflict = true
  114     }
  115 
  116     // a 409 is typical here.  GET the data and merge in.
  117     if (er && !conflict) {
  118       client.log.error('publish', 'Failed PUT ' + (res && res.statusCode))
  119       return cb(er)
  120     }
  121 
  122     if (!er && !conflict) return cb(er, parsed, json, res)
  123 
  124     // let's see what versions are already published.
  125     client.request(fixed + '?write=true', { auth: auth }, function (er, current) {
  126       if (er) return cb(er)
  127 
  128       putNext.call(client, registry, data.version, root, current, auth, cb)
  129     })
  130   })
  131 }
  132 
  133 function putNext (registry, newVersion, root, current, auth, cb) {
  134   // already have the tardata on the root object
  135   // just merge in existing stuff
  136   var curVers = Object.keys(current.versions || {}).map(function (v) {
  137     return semver.clean(v, true)
  138   }).concat(Object.keys(current.time || {}).map(function (v) {
  139     if (semver.valid(v, true)) return semver.clean(v, true)
  140   }).filter(function (v) {
  141     return v
  142   }))
  143 
  144   if (curVers.indexOf(newVersion) !== -1) {
  145     return cb(conflictError(root.name, newVersion))
  146   }
  147 
  148   current.versions[newVersion] = root.versions[newVersion]
  149   current._attachments = current._attachments || {}
  150   for (var i in root) {
  151     switch (i) {
  152       // objects that copy over the new stuffs
  153       case 'dist-tags':
  154       case 'versions':
  155       case '_attachments':
  156         for (var j in root[i])
  157           current[i][j] = root[i][j]
  158         break
  159 
  160       // ignore these
  161       case 'maintainers':
  162         break
  163 
  164       // copy
  165       default:
  166         current[i] = root[i]
  167     }
  168   }
  169   var maint = JSON.parse(JSON.stringify(root.maintainers))
  170   root.versions[newVersion].maintainers = maint
  171 
  172   var uri = url.resolve(registry, escaped(root.name))
  173   var options = {
  174     method: 'PUT',
  175     body: current,
  176     auth: auth
  177   }
  178   this.request(uri, options, cb)
  179 }
  180 
  181 function conflictError (pkgid, version) {
  182   var e = new Error('cannot modify pre-existing version')
  183   e.code = 'EPUBLISHCONFLICT'
  184   e.pkgid = pkgid
  185   e.version = version
  186   return e
  187 }