├── .gitignore ├── .travis.yml ├── LICENSE ├── Makefile ├── README.md ├── copy.sh ├── load-views.sh ├── package-lock.json ├── package.json ├── push.sh ├── registry ├── _auth.js ├── app.js ├── lists.js ├── modules.js ├── rewrites.js ├── shadow.js ├── shows.js ├── test.js ├── updates.js ├── validate_doc_update.js └── views.js └── test ├── 00-setup.js ├── 01-adduser.js ├── 01b-user-views.js ├── 01c-user-updates.js ├── 01d-whoami.js ├── 02-publish.js ├── 02b-dist-tags.js ├── 03-star.js ├── 04-deprecate.js ├── 04b-registry-views-expect.js ├── 04b-registry-views.js ├── 04c-lists.js ├── 05-unpublish.js ├── 06-not-implemented.js ├── common.js ├── fixtures ├── couch.ini ├── hoodie-new.json ├── hoodie-old.json ├── install │ └── package.json ├── meta-goog-put.json ├── meta-goog.json ├── package │ ├── 0.0.2 │ │ ├── README │ │ └── package.json │ ├── 0.2.3 │ │ ├── README.md │ │ ├── package.json │ │ └── test.js │ ├── 0.2.3alpha │ │ ├── README.md │ │ ├── package.json │ │ └── test.js │ └── 0.2.4 │ │ ├── README.md │ │ ├── package.json │ │ └── test.js ├── scoped-package.json ├── star-nopt-put.json ├── star-nopt.json ├── vdu-auth │ ├── 01-new.json │ ├── 01-throw.json │ ├── 02-new.json │ ├── 02-throw.json │ ├── 03-new.json │ └── 03-throw.json ├── vdu │ ├── 01-new.json │ ├── 01-old.json │ ├── 01-throw.json │ ├── 01-user.json │ ├── 02-new.json │ ├── 02-old.json │ ├── 02-user.json │ ├── 03-new.json │ ├── 03-old.json │ ├── 03-throw.json │ ├── 03-user.json │ ├── 04-new.json │ ├── 04-old.json │ ├── 04-throw.json │ ├── 04-user.json │ ├── 05-new.json │ ├── 05-old.json │ ├── 05-throw.json │ ├── 05-user.json │ ├── 06-new.json │ ├── 06-old.json │ ├── 06-user.json │ ├── 07-new.json │ ├── 07-old.json │ ├── 07-user.json │ ├── 08-new.json │ ├── 08-old.json │ ├── 08-throw.json │ ├── 08-user.json │ ├── 09-new.json │ ├── 09-throw.json │ └── 09-user.json ├── yui-new.json └── yui-old.json ├── ping.js ├── pkg-update-copy-fields.js ├── pkg-update-deprecate-msg.js ├── pkg-update-hoodie.js ├── pkg-update-metadata.js ├── pkg-update-star-nopt.js ├── pkg-update-yui-error.js ├── vdu-auth.js ├── vdu.js └── zz-teardown.js /.gitignore: -------------------------------------------------------------------------------- 1 | npm-debug.log 2 | couch.log 3 | .delete 4 | test/fixtures/npmrc* 5 | .*.swp 6 | node_modules 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: "node_js" 2 | node_js: 3 | - "5" 4 | - "4" 5 | - iojs 6 | - "0.12" 7 | - "0.10" 8 | sudo: false 9 | before_install: 10 | - "npm config set spin false" 11 | env: 12 | - DEPLOY_VERSION=testing 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The ISC License 2 | 3 | Copyright (c) npm, Inc. and Contributors 4 | 5 | Permission to use, copy, modify, and/or distribute this software for any 6 | purpose with or without fee is hereby granted, provided that the above 7 | copyright notice and this permission notice appear in all copies. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 15 | IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | 17 | 18 | "Node.js" and "node" trademark Joyent, Inc. npm is not officially 19 | part of the Node.js project, and is neither owned by nor 20 | officially affiliated with Joyent, Inc. 21 | 22 | Packages published in the npm registry are not part of npm 23 | itself, and are the sole property of their respective 24 | maintainers. 25 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | push: 2 | npm start 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # npm-registry-couchapp 2 | 3 | [![Build Status](https://img.shields.io/travis/npm/npm-registry-couchapp/master.svg)](https://travis-ci.org/npm/npm-registry-couchapp) 4 | 5 | __deprecation notice: as npm has scaled, the registry architecture has gradually migrated towards 6 | a complex distributed architecture, of which npm-registry-couchapp is only a small part. FOSS 7 | is an important part of npm, and over time we plan on exposing more APIs, and [better documenting 8 | the existing API](https://github.com/npm/public-api).__ 9 | 10 | __npm-registry-couchapp is still a core part of our functionality, but all new registry features are 11 | now added to the micro-services that now make up npm. For this reason, we will not be accepting any 12 | pull requests, or making any changes to this codebase going forward.__ 13 | 14 | __For issues with the npmjs.com website, please open an issue on the 15 | [npm/www](https://github.com/npm/www) repo. For issues wih the registry 16 | service (for example, slow package downloads, or inability to publish a 17 | package), see the [npm/registry](https://github.com/npm/registry) repo.__ 18 | 19 | The design doc for The npm Registry CouchApp 20 | 21 | # Installing 22 | 23 | You need CouchDB version 1.4.0 or higher. 1.5.0 or higher is best. 24 | 25 | Once you have CouchDB installed, create a new database: 26 | 27 | curl -X PUT http://localhost:5984/registry 28 | 29 | You'll need the following entries added in your `local.ini` 30 | 31 | ```ini 32 | [couch_httpd_auth] 33 | public_fields = appdotnet, avatar, avatarMedium, avatarLarge, date, email, fields, freenode, fullname, github, homepage, name, roles, twitter, type, _id, _rev 34 | users_db_public = true 35 | 36 | [httpd] 37 | secure_rewrites = false 38 | 39 | [couchdb] 40 | delayed_commits = false 41 | ``` 42 | 43 | Clone the repository if you haven't already, and cd into it: 44 | 45 | git clone git://github.com/npm/npm-registry-couchapp 46 | cd npm-registry-couchapp 47 | 48 | Now install the stuff: 49 | 50 | npm install 51 | 52 | Sync the ddoc to `_design/scratch` 53 | 54 | npm start \ 55 | --npm-registry-couchapp:couch=http://admin:password@localhost:5984/registry 56 | 57 | Next, make sure that views are loaded: 58 | 59 | npm run load \ 60 | --npm-registry-couchapp:couch=http://admin:password@localhost:5984/registry 61 | 62 | And finally, copy the ddoc from `_design/scratch` to `_design/app` 63 | 64 | npm run copy \ 65 | --npm-registry-couchapp:couch=http://admin:password@localhost:5984/registry 66 | 67 | Of course, you can avoid the command-line flag by setting it in your 68 | ~/.npmrc file: 69 | 70 | _npm-registry-couchapp:couch=http://admin:password@localhost:5984/registry 71 | 72 | The `_` prevents any other packages from seeing the setting (with a 73 | password) in their environment when npm runs scripts for those other 74 | packages. 75 | 76 | # Replicating the Registry 77 | 78 | To replicate the registry **without attachments**, you can point your 79 | CouchDB replicator at . Note that 80 | attachments for public packages will still be loaded from the public 81 | location, but anything you publish into your private registry will 82 | stay private. 83 | 84 | To replicate the registry **with attachments**, consider using 85 | [npm-fullfat-registry](https://npmjs.org/npm-fullfat-registry). 86 | The fullfatdb CouchDB instance is 87 | [deprecated](http://blog.npmjs.org/post/83774616862/deprecating-fullfatdb). 88 | 89 | # Using the registry with the npm client 90 | 91 | With the setup so far, you can point the npm client at the registry by 92 | putting this in your ~/.npmrc file: 93 | 94 | registry = http://localhost:5984/registry/_design/app/_rewrite 95 | 96 | You can also set the npm registry config property like: 97 | 98 | npm config set \ 99 | registry=http://localhost:5984/registry/_design/app/_rewrite 100 | 101 | Or you can simple override the registry config on each call: 102 | 103 | npm \ 104 | --registry=http://localhost:5984/registry/_design/app/_rewrite \ 105 | install 106 | 107 | # Optional: top-of-host urls 108 | 109 | To be snazzier, add a vhost config: 110 | 111 | [vhosts] 112 | registry.mydomain.com:5984 = /registry/_design/app/_rewrite 113 | 114 | Where `registry.mydomain.com` is the hostname where you're running the 115 | thing, and `5984` is the port that CouchDB is running on. If you're 116 | running on port 80, then omit the port altogether. 117 | 118 | Then for example you can reference the repository like so: 119 | 120 | npm config set registry http://registry.mydomain.com:5984 121 | -------------------------------------------------------------------------------- /copy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | c=${npm_package_config_couch} 4 | 5 | if [ "$c" == "" ]; then 6 | cat >&2 <<-ERR 7 | Please set a valid 'npmjs.org:couch' npm config. 8 | 9 | You can put PASSWORD in the setting somewhere to 10 | have it prompt you for a password each time, so 11 | it doesn't get dropped in your config file. 12 | 13 | If you have PASSWORD in there, it'll also be read 14 | from the PASSWORD environment variable, so you 15 | can set it in the env and not have to enter it 16 | each time. 17 | ERR 18 | exit 1 19 | fi 20 | 21 | case $c in 22 | *PASSWORD*) 23 | if [ "$PASSWORD" == "" ]; then 24 | echo -n "Password: " 25 | read -s PASSWORD 26 | fi 27 | ;; 28 | *);; 29 | esac 30 | 31 | c=${c/PASSWORD/$PASSWORD} 32 | c=${c// /%20} 33 | 34 | c="$(node -p 'process.argv[1].replace(/\/$/, "")' "$c")" 35 | u="$(node -p 'require("url").resolve(process.argv[1], "_users")' "$c")" 36 | 37 | if [ "$NO_PROMPT" == "" ]; then 38 | echo "Did you already run the load-views.sh script? (type 'yes')" 39 | read didLoad 40 | if ! [ "$didLoad" == "yes" ]; then 41 | echo "do that first." 42 | exit 1 43 | fi 44 | fi 45 | 46 | rev=$(curl -k "$c"/_design/app | json _rev) 47 | if [ "$rev" != "" ]; then 48 | rev="?rev=$rev" 49 | fi 50 | auth="$(node -pe 'require("url").parse(process.argv[1]).auth || ""' "$c")" 51 | url="$(node -pe 'u=require("url");p=u.parse(process.argv[1]);delete p.auth;u.format(p)' "$c")" 52 | if [ "$auth" != "" ]; then 53 | auth=(-u "$auth") 54 | fi 55 | 56 | curl "$url/_design/scratch" \ 57 | "${auth[@]}" \ 58 | -k \ 59 | -X COPY \ 60 | -H destination:'_design/app'$rev 61 | 62 | 63 | 64 | rev=$(curl -k "$u"/_design/_auth | json _rev) 65 | if [ "$rev" != "" ]; then 66 | rev="?rev=$rev" 67 | fi 68 | auth="$(node -pe 'require("url").parse(process.argv[1]).auth || ""' "$u")" 69 | url="$(node -pe 'u=require("url");p=u.parse(process.argv[1]);delete p.auth;u.format(p)' "$u")" 70 | if [ "$auth" != "" ]; then 71 | auth=(-u "$auth") 72 | fi 73 | 74 | curl "$url/_design/scratch" \ 75 | "${auth[@]}" \ 76 | -k \ 77 | -X COPY \ 78 | -H destination:'_design/_auth'$rev 79 | -------------------------------------------------------------------------------- /load-views.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | c=${npm_package_config_couch} 4 | 5 | if [ "$c" == "" ]; then 6 | cat >&2 <<-ERR 7 | Please set a valid 'npmjs.org:couch' npm config. 8 | 9 | You can put PASSWORD in the setting somewhere to 10 | have it prompt you for a password each time, so 11 | it doesn't get dropped in your config file. 12 | 13 | If you have PASSWORD in there, it'll also be read 14 | from the PASSWORD environment variable, so you 15 | can set it in the env and not have to enter it 16 | each time. 17 | ERR 18 | exit 1 19 | fi 20 | 21 | case $c in 22 | *PASSWORD*) 23 | if [ "$PASSWORD" == "" ]; then 24 | echo -n "Password: " 25 | read -s PASSWORD 26 | fi 27 | ;; 28 | *);; 29 | esac 30 | 31 | host="$(node -pe 'require("url").parse(process.argv[1]).host' "$c")" 32 | hostname="$(node -pe 'require("url").parse(process.argv[1]).hostname' "$c")" 33 | ips=($(dig +short "$hostname" | egrep '^[0-9]')) 34 | 35 | DEPLOY_VERSION=test \ 36 | node -pe 'Object.keys(require("./registry/app.js").views).join("\n")' \ 37 | | while read view; do 38 | echo "LOADING: $view" 39 | curl -Ik "$c/_design/scratch/_view/$view" -H "host:$host" 40 | done 41 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "npm-registry-couchapp", 3 | "version": "3.0.0", 4 | "description": "The CouchApp implementation of an npm registry", 5 | "scripts": { 6 | "start": "bash ./push.sh", 7 | "load": "bash ./load-views.sh", 8 | "copy": "bash ./copy.sh", 9 | "test": "tap --timeout 240 test/*.js" 10 | }, 11 | "dependencies": { 12 | "couchapp": "~0.11.0", 13 | "json": "~9.0.2", 14 | "semver": "4" 15 | }, 16 | "devDependencies": { 17 | "parse-json-response": "~1.0.1", 18 | "request": "~2.42.0", 19 | "rimraf": "~2.2.6", 20 | "tap": "^12.7.0", 21 | "which": "~1.0.5" 22 | }, 23 | "repository": { 24 | "type": "git", 25 | "url": "git://github.com/npm/npm-registry-couchapp" 26 | }, 27 | "keywords": [ 28 | "npm", 29 | "registry", 30 | "couchapp", 31 | "design", 32 | "doc", 33 | "ddoc", 34 | "couchdb", 35 | "couch" 36 | ], 37 | "author": "Isaac Z. Schlueter (http://blog.izs.me/)", 38 | "license": "ISC", 39 | "bugs": { 40 | "url": "https://github.com/npm/npm-registry-couchapp/issues" 41 | }, 42 | "homepage": "https://github.com/npm/npm-registry-couchapp" 43 | } 44 | -------------------------------------------------------------------------------- /push.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | export NODE_TLS_REJECT_UNAUTHORIZED=0 3 | 4 | c=${npm_package_config_couch} 5 | 6 | if [ "$c" == "" ]; then 7 | cat >&2 <<-ERR 8 | Please set a valid 'npm-registry-couchapp:couch' npm config. 9 | 10 | You can put PASSWORD in the setting somewhere to 11 | have it prompt you for a password each time, so 12 | it doesn't get dropped in your config file. 13 | 14 | If you have PASSWORD in there, it'll also be read 15 | from the PASSWORD environment variable, so you 16 | can set it in the env and not have to enter it 17 | each time. 18 | ERR 19 | exit 1 20 | fi 21 | 22 | case $c in 23 | *PASSWORD*) 24 | if [ "$PASSWORD" == "" ]; then 25 | echo -n "Password: " 26 | read -s PASSWORD 27 | fi 28 | ;; 29 | *);; 30 | esac 31 | 32 | # echo "couch=$c" 33 | 34 | scratch_message () { 35 | cat <<-EOF 36 | 37 | Pushed to scratch ddoc. To make it real, use a COPY request. 38 | Something like this: 39 | 40 | curl -u "\$username:\$password" \\ 41 | \$couch/registry/_design/scratch \\ 42 | -X COPY \\ 43 | -H destination:'_design/app?rev=\$rev' 44 | 45 | But, before you do that, make sure to fetch the views and give 46 | them time to load, so that real users don't feel the pain of 47 | view generation latency. 48 | 49 | You can do it like this using npm: 50 | 51 | npm run load 52 | # Go get lunch and come back. 53 | # Go take the dog for a walk, and play some frisbee in the park. 54 | # If you don't have a dog, go get a puppy, provide it with love 55 | # and appropriate discipline until it gets older, train it to play 56 | # frisbee in the park, and then take it to the park and play frisbee. 57 | # Wait some more. It's probably almost done now. 58 | # Make it live: 59 | npm run copy 60 | EOF 61 | } 62 | 63 | c=${c/PASSWORD/$PASSWORD} 64 | c=${c// /%20} 65 | 66 | c="$(node -p 'process.argv[1].replace(/\/$/, "")' "$c")" 67 | u="$(node -p 'require("url").resolve(process.argv[1], "_users")' "$c")" 68 | 69 | which couchapp 70 | 71 | # allow deploy version to be overridden 72 | # with `DEPLOY_VERSION=testing npm start`. 73 | if [ "$DEPLOY_VERSION" == "" ]; then 74 | DEPLOY_VERSION=`git describe --tags` 75 | fi 76 | 77 | DEPLOY_VERSION="$DEPLOY_VERSION" couchapp push registry/app.js "$c" && \ 78 | DEPLOY_VERSION="$DEPLOY_VERSION" couchapp push registry/_auth.js "$u" && \ 79 | scratch_message && \ 80 | exit 0 || \ 81 | ( ret=$? 82 | echo "Failed with code $ret" 83 | exit $ret ) 84 | -------------------------------------------------------------------------------- /registry/_auth.js: -------------------------------------------------------------------------------- 1 | // sync to $host/_users/_design/_auth 2 | 3 | var isArray = Array.isArray 4 | var ddoc = {_id:"_design/scratch", language:"javascript"} 5 | 6 | module.exports = ddoc 7 | 8 | ddoc.lists = { 9 | index: function (head,req) { 10 | var row 11 | , out = {} 12 | , id, data 13 | while (row = getRow()) { 14 | id = row.id.replace(/^org\.couchdb\.user:/, '') 15 | data = row.value 16 | delete data._id 17 | delete data._rev 18 | delete data.salt 19 | delete data.password_sha 20 | delete data.type 21 | delete data.roles 22 | delete data._deleted_conflicts 23 | out[id] = data 24 | } 25 | send(toJSON(out)) 26 | }, 27 | email:function (head, req) { 28 | var row 29 | , data 30 | , id 31 | , email = req.query.email || undefined 32 | , out = [] 33 | while (row = getRow()) { 34 | id = row.id.replace(/^org\.couchdb\.user:/, '') 35 | data = row.value 36 | var dm = data.email || undefined 37 | if (data.email !== email) continue 38 | out.push(row.value.name) 39 | } 40 | send(toJSON(out)) 41 | } 42 | 43 | } 44 | 45 | 46 | ddoc.validate_doc_update = function (newDoc, oldDoc, userCtx, secObj) { 47 | if (newDoc._deleted === true) { 48 | // allow deletes by admins 49 | if (userCtx && (userCtx.roles.indexOf('_admin') !== -1)) { 50 | return; 51 | } else { 52 | throw({forbidden: 'Only admins may delete user docs.'}); 53 | } 54 | } 55 | 56 | if ((oldDoc && oldDoc.type !== 'user') || newDoc.type !== 'user') { 57 | throw({forbidden : 'doc.type must be user'}); 58 | } // we only allow user docs for now 59 | 60 | if (!newDoc.name) { 61 | throw({forbidden: 'doc.name is required'}); 62 | } 63 | 64 | if (newDoc.roles && !isArray(newDoc.roles)) { 65 | throw({forbidden: 'doc.roles must be an array'}); 66 | } 67 | 68 | if (newDoc._id !== ('org.couchdb.user:' + newDoc.name)) { 69 | throw({ 70 | forbidden: 'Doc ID must be of the form org.couchdb.user:name' 71 | }); 72 | } 73 | 74 | if (newDoc.name !== newDoc.name.toLowerCase()) { 75 | throw({ 76 | forbidden: 'Name must be lower-case' 77 | }) 78 | } 79 | 80 | if (newDoc.name !== encodeURIComponent(newDoc.name)) { 81 | throw({ 82 | forbidden: 'Name cannot contain non-url-safe characters' 83 | }) 84 | } 85 | 86 | if (newDoc.name.charAt(0) === '.') { 87 | throw({ 88 | forbidden: 'Name cannot start with .' 89 | }) 90 | } 91 | 92 | if (!(newDoc.email && newDoc.email.match(/^.+@.+\..+$/))) { 93 | throw({forbidden: 'Email must be an email address'}) 94 | } 95 | 96 | if (oldDoc) { // validate all updates 97 | if (oldDoc.name !== newDoc.name) { 98 | throw({forbidden: 'Usernames can not be changed.'}); 99 | } 100 | } 101 | 102 | if (newDoc.password_sha && !newDoc.salt) { 103 | throw({ 104 | forbidden: 'Users with password_sha must have a salt.' 105 | }); 106 | } 107 | 108 | var is_server_or_database_admin = function(userCtx, secObj) { 109 | // see if the user is a server admin 110 | if(userCtx && userCtx.roles.indexOf('_admin') !== -1) { 111 | return true; // a server admin 112 | } 113 | 114 | // see if the user a database admin specified by name 115 | if(secObj && secObj.admins && secObj.admins.names) { 116 | if(secObj.admins.names.indexOf(userCtx.name) !== -1) { 117 | return true; // database admin 118 | } 119 | } 120 | 121 | // see if the user a database admin specified by role 122 | if(secObj && secObj.admins && secObj.admins.roles) { 123 | var db_roles = secObj.admins.roles; 124 | for(var idx = 0; idx < userCtx.roles.length; idx++) { 125 | var user_role = userCtx.roles[idx]; 126 | if(db_roles.indexOf(user_role) !== -1) { 127 | return true; // role matches! 128 | } 129 | } 130 | } 131 | 132 | return false; // default to no admin 133 | } 134 | 135 | if (newDoc.name.length > 50) { 136 | throw({ 137 | forbidden: 'Username is too long. Pick a shorter one.' 138 | }) 139 | } 140 | 141 | if (!is_server_or_database_admin(userCtx, secObj)) { 142 | if (oldDoc) { // validate non-admin updates 143 | if (userCtx.name !== newDoc.name) { 144 | throw({ 145 | forbidden: 'You may only update your own user document.' 146 | }); 147 | } 148 | if (oldDoc.email !== newDoc.email) { 149 | throw({ 150 | forbidden: 'You may not change your email address\n' + 151 | 'Please visit https://npmjs.org/email-edit to do so.' 152 | }) 153 | } 154 | // validate role updates 155 | var oldRoles = oldDoc.roles.sort(); 156 | var newRoles = newDoc.roles.sort(); 157 | 158 | if (oldRoles.length !== newRoles.length) { 159 | throw({forbidden: 'Only _admin may edit roles'}); 160 | } 161 | 162 | for (var i = 0; i < oldRoles.length; i++) { 163 | if (oldRoles[i] !== newRoles[i]) { 164 | throw({forbidden: 'Only _admin may edit roles'}); 165 | } 166 | } 167 | } else if (newDoc.roles.length > 0) { 168 | throw({forbidden: 'Only _admin may set roles'}); 169 | } 170 | } 171 | 172 | // no system roles in users db 173 | for (var i = 0; i < newDoc.roles.length; i++) { 174 | if (newDoc.roles[i][0] === '_') { 175 | throw({ 176 | forbidden: 'No system roles (starting with underscore) in users db.' 177 | }); 178 | } 179 | } 180 | 181 | // no system names as names 182 | if (newDoc.name[0] === '_') { 183 | throw({forbidden: 'Username may not start with underscore.'}); 184 | } 185 | 186 | var badUserNameChars = [':']; 187 | 188 | for (var i = 0; i < badUserNameChars.length; i++) { 189 | if (newDoc.name.indexOf(badUserNameChars[i]) >= 0) { 190 | throw({forbidden: 'Character `' + badUserNameChars[i] + 191 | '` is not allowed in usernames.'}); 192 | } 193 | } 194 | 195 | if (newDoc.password) 196 | throw {forbidden: 'Plain-text passwords may not be stored in the db'} 197 | 198 | if (newDoc.password_scheme === 'pbkdf2') { 199 | if (newDoc.password_sha) 200 | throw {forbidden: 'may not mix password_sha and pbkdf2\n' + 201 | 'You may need to upgrade your version of npm:\n' + 202 | ' npm install npm -g\n' + 203 | 'Note that this may need to be run as root/admin (sudo, etc.)\n\n' } 204 | if (!newDoc.derived_key) 205 | throw {forbidden: 'missing pbkdf2 derived_key'} 206 | if (typeof newDoc.derived_key !== 'string') 207 | throw {forbidden: 'pbkdf2 derived_key must be a string'} 208 | if (!newDoc.derived_key.match(/^[a-f0-9]{40}$/)) 209 | throw {forbidden: 'pbkdf2 derived_key must be 20 hex bytes'} 210 | if (!newDoc.salt) 211 | throw {forbidden: 'missing pbkdf2 salt'} 212 | if (typeof newDoc.iterations !== 'number') 213 | throw {forbidden: 'doc.iterations must be a number'} 214 | if (newDoc.iterations < 10) 215 | throw {forbidden: 'not enough pbkdf2 iterations'} 216 | if (newDoc.iterations > 100) 217 | throw {forbidden: 'too many pbkdf2 iterations'} 218 | } else { 219 | if (!newDoc.salt) 220 | throw {forbidden: 'missing salt'} 221 | if (!newDoc.password_sha) 222 | throw {forbidden: 'missing password_sha'} 223 | } 224 | } 225 | 226 | ddoc.views = { 227 | listAll: { 228 | map: function (doc) { 229 | return emit(doc._id, doc) 230 | } 231 | }, 232 | 233 | userByEmail: { 234 | map: function (doc) { 235 | if (doc.email || doc.name) { 236 | emit([ doc.email, doc.name ], 1) 237 | } 238 | }, 239 | reduce: "_sum" 240 | }, 241 | 242 | invalidUser: { 243 | map: function (doc) { 244 | var errors = [] 245 | if (doc.type !== 'user') { 246 | errors.push('doc.type must be user') 247 | } 248 | 249 | if (!doc.name) { 250 | errors.push('doc.name is required') 251 | } 252 | 253 | if (doc.roles && !isArray(doc.roles)) { 254 | errors.push('doc.roles must be an array') 255 | } 256 | 257 | if (doc._id !== ('org.couchdb.user:' + doc.name)) { 258 | errors.push('Doc ID must be of the form org.couchdb.user:name') 259 | } 260 | 261 | if (doc.name !== doc.name.toLowerCase()) { 262 | errors.push('Name must be lower-case') 263 | } 264 | 265 | if (doc.name !== encodeURIComponent(doc.name)) { 266 | errors.push('Name cannot contain non-url-safe characters') 267 | } 268 | 269 | if (doc.name.charAt(0) === '.') { 270 | errors.push('Name cannot start with .') 271 | } 272 | 273 | if (!(doc.email && doc.email.match(/^.+@.+\..+$/))) { 274 | errors.push('Email must be an email address') 275 | } 276 | 277 | if (doc.password_sha && !doc.salt) { 278 | errors.push('Users with password_sha must have a salt.') 279 | } 280 | if (!errors.length) return 281 | emit([doc.name, doc.email], errors) 282 | } 283 | }, 284 | 285 | invalid: { 286 | map: function (doc) { 287 | if (doc.type !== 'user') { 288 | return emit(['doc.type must be user', doc.email, doc.name], 1) 289 | } 290 | 291 | if (!doc.name) { 292 | return emit(['doc.name is required', doc.email, doc.name], 1) 293 | } 294 | 295 | if (doc.roles && !isArray(doc.roles)) { 296 | return emit(['doc.roles must be an array', doc.email, doc.name], 1) 297 | } 298 | 299 | if (doc._id !== ('org.couchdb.user:' + doc.name)) { 300 | return emit(['Doc ID must be of the form org.couchdb.user:name', doc.email, doc.name], 1) 301 | } 302 | 303 | if (doc.name !== doc.name.toLowerCase()) { 304 | return emit(['Name must be lower-case', doc.email, doc.name], 1) 305 | } 306 | 307 | if (doc.name !== encodeURIComponent(doc.name)) { 308 | return emit(['Name cannot contain non-url-safe characters', doc.email, doc.name], 1) 309 | } 310 | 311 | if (doc.name.charAt(0) === '.') { 312 | return emit(['Name cannot start with .', doc.email, doc.name], 1) 313 | } 314 | 315 | if (!(doc.email && doc.email.match(/^.+@.+\..+$/))) { 316 | return emit(['Email must be an email address', doc.email, doc.name], 1) 317 | } 318 | 319 | if (doc.password_sha && !doc.salt) { 320 | return emit(['Users with password_sha must have a salt.', doc.email, doc.name], 1) 321 | } 322 | }, 323 | reduce: '_sum' 324 | }, 325 | 326 | pbkdfsha: { 327 | map: function(doc) { 328 | if (doc.password_sha && doc.derived_key) { 329 | emit([doc._id, doc], 1) 330 | } 331 | }, 332 | reduce: "_sum" 333 | }, 334 | 335 | string_iterations: { 336 | map: function(doc) { 337 | if (typeof doc.iterations === 'string') { 338 | emit([doc._id, doc], 1) 339 | } 340 | }, 341 | reduce: "_sum" 342 | }, 343 | 344 | conflicts: { 345 | map: function (doc) { 346 | if (doc._conflicts) { 347 | for (var i = 0; i < doc._conflicts.length; i++) { 348 | emit([doc._id, doc._conflicts[i]], 1) 349 | } 350 | } 351 | }, 352 | reduce: "_sum" 353 | } 354 | } 355 | 356 | ddoc.updates = { 357 | email: function (doc, req) { 358 | if (req.method !== "POST") 359 | return [ { _id: ".error.", forbidden: "Method not allowed" }, 360 | { error: "method not allowed" } ] 361 | 362 | var data = JSON.parse(req.body) 363 | 364 | doc.email = data.email 365 | 366 | return [doc, JSON.stringify({ok: "updated email address"})] 367 | }, 368 | 369 | profile: function (doc, req) { 370 | if (req.method !== "POST") 371 | return [ { _id: ".error.", forbidden: "Method not allowed" }, 372 | { error: "method not allowed" } ] 373 | 374 | var WHITELISTED = [ 'appdotnet', 'avatar', 'avatarMedium', 'avatarLarge', 375 | 'date', 'email', 'fields', 'freenode', 'fullname', 376 | 'github', 'homepage', 'name', 'roles', 'twitter', 'type' ] 377 | 378 | var data = JSON.parse(req.body) 379 | 380 | for (var i in data) { 381 | if (WHITELISTED.indexOf(i) !== -1) { 382 | doc[i] = data[i] 383 | } 384 | } 385 | 386 | return [doc, JSON.stringify({ok: "updated profile"})] 387 | } 388 | } 389 | 390 | if (require.main === module) 391 | console.log(JSON.stringify(ddoc, function (k, v) { 392 | if (typeof v !== 'function') return v; 393 | return v.toString() 394 | })) 395 | else if (process.env.DEPLOY_VERSION) 396 | ddoc.deploy_version = process.env.DEPLOY_VERSION 397 | else 398 | throw new Error('Must set DEPLOY_VERSION env to `git describe` output') 399 | -------------------------------------------------------------------------------- /registry/app.js: -------------------------------------------------------------------------------- 1 | var ddoc = module.exports = 2 | { _id:'_design/scratch' 3 | , shows: require("./shows.js") 4 | , updates: require("./updates.js") 5 | , rewrites: require("./rewrites.js") 6 | , views: require("./views.js") 7 | , lists: require("./lists.js") 8 | , validate_doc_update: require("./validate_doc_update.js") 9 | , language: "javascript" 10 | } 11 | 12 | if (process.env.DEPLOY_VERSION) 13 | ddoc.deploy_version = process.env.DEPLOY_VERSION 14 | else 15 | throw new Error('Must set DEPLOY_VERSION env to `git describe` output') 16 | 17 | var modules = require("./modules.js") 18 | for (var i in modules) ddoc[i] = modules[i] 19 | -------------------------------------------------------------------------------- /registry/lists.js: -------------------------------------------------------------------------------- 1 | var lists = module.exports = {} 2 | 3 | lists.short = function (head, req) { 4 | require("monkeypatch").patch(Object, Date, Array, String) 5 | 6 | var out = {} 7 | , row 8 | , show = (req.query.show || "").split(",") 9 | , v = show.indexOf("version") !== -1 10 | , t = show.indexOf("tag") !== -1 11 | while (row = getRow()) { 12 | if (!row.id) continue 13 | if (!t && !v) { 14 | out[row.id] = true 15 | continue 16 | } 17 | var val = row.value 18 | if (t) Object.keys(val["dist-tags"] || {}).forEach(function (t) { 19 | out[row.id + "@" + t] = true 20 | }) 21 | if (v) Object.keys(val.versions || {}).forEach(function (v) { 22 | out[row.id + "@" + v] = true 23 | }) 24 | } 25 | send(toJSON(Object.keys(out))) 26 | } 27 | 28 | 29 | lists.rss = function (head, req) { 30 | function pad(n){return n<10 ? '0'+n : n} 31 | Date.prototype.toISOString = Date.prototype.toISOString || 32 | function toISOString(){ 33 | var d = this; 34 | return d.getUTCFullYear()+'-' 35 | + pad(d.getUTCMonth()+1)+'-' 36 | + pad(d.getUTCDate())+'T' 37 | + pad(d.getUTCHours())+':' 38 | + pad(d.getUTCMinutes())+':' 39 | + pad(d.getUTCSeconds())+'Z'} 40 | 41 | var limit = +req.query.limit 42 | , desc = req.query.descending 43 | if (!desc || !limit || limit > 50 || limit < 0) { 44 | start({ code: 403 45 | , headers: { 'Content-type': 'text/xml' }}) 46 | send('') 48 | return 49 | } 50 | 51 | start({ code: 200 52 | // application/rss+xml is correcter, but also annoyinger 53 | , headers: { "Content-Type": "text/xml" } }) 54 | send('' 55 | +'\n' 57 | +'\n' 58 | +'\n ' 59 | +'\n npm recent updates' 60 | +'\n http://search.npmjs.org/' 61 | +'\n Updates to the npm package registry' 62 | +'\n en') 63 | 64 | var row 65 | while (row = getRow()) { 66 | if (!row.value || !row.value["dist-tags"]) continue 67 | 68 | var doc = row.value 69 | var authors = doc.maintainers.map(function (m) { 70 | return '' + m.name + '' 71 | }).join('\n ') 72 | 73 | var latest = doc["dist-tags"].latest 74 | var time = doc.time && doc.time[latest] 75 | var date = new Date(time) 76 | doc = doc.versions[latest] 77 | if (!doc || !time || !date) continue 78 | 79 | var url = "https://npmjs.org/package/" + doc.name 80 | 81 | send('\n ' 82 | +'\n ' + doc._id + '' 83 | +'\n ' + url + '' 84 | +'\n ' + authors 85 | +'\n ' 88 | +'\n ' + date.toISOString() + '' 89 | +'\n ') 90 | } 91 | send('\n ' 92 | +'\n') 93 | } 94 | 95 | 96 | 97 | lists.index = function (head, req) { 98 | require("monkeypatch").patch(Object, Date, Array, String) 99 | var basePath = req.requested_path 100 | if (basePath.indexOf("_list") === -1) basePath = "" 101 | else { 102 | basePath = basePath.slice(0, basePath.indexOf("_list")) 103 | .concat(["_rewrite", ""]).join("/") 104 | } 105 | 106 | var row 107 | , semver = require("semver") 108 | , res = [] 109 | 110 | if (req.query.jsonp) send(req.query.jsonp + "(") 111 | send('{"_updated":' + Date.now()) 112 | while (row = getRow()) { 113 | if (!row.id) continue 114 | 115 | var doc = row.value 116 | 117 | // We are intentionally not showing scoped modules in this list. 118 | // Since they may potentially be user-restricted, showing them 119 | // in the search endpoint leaks information. They get left out 120 | // by the fact that their _id is equal to the uri-encoded _id 121 | if (!doc.name || !doc._id || 122 | encodeURIComponent(doc._id) !== doc._id) continue 123 | 124 | var p = {} 125 | 126 | // legacy kludge 127 | delete doc.mtime 128 | delete doc.ctime 129 | if (doc.versions) for (var v in doc.versions) { 130 | var clean = semver.clean(v) 131 | delete doc.versions[v].ctime 132 | delete doc.versions[v].mtime 133 | if (clean !== v) { 134 | var x = doc.versions[v] 135 | delete doc.versions[v] 136 | x.version = v = clean 137 | doc.versions[clean] = x 138 | } 139 | } 140 | if (doc["dist-tags"]) for (var tag in doc["dist-tags"]) { 141 | var clean = semver.clean(doc["dist-tags"][tag]) 142 | if (!clean) delete doc["dist-tags"][tag] 143 | else doc["dist-tags"][tag] = clean 144 | } 145 | // end kludge 146 | 147 | for (var i in doc) { 148 | if (i === "versions" || i.charAt(0) === "_" || i === 'readme' || 149 | i === 'time') continue 150 | p[i] = doc[i] 151 | } 152 | if (doc.time) { 153 | p.time = { modified: doc.time.modified } 154 | } 155 | if (p['dist-tags'] && typeof p['dist-tags'] === 'object') { 156 | p.versions = Object.keys(p['dist-tags']).reduce(function (ac, v) { 157 | ac[ p['dist-tags'][v] ] = v 158 | return ac 159 | }, {}) 160 | } 161 | if (doc.repositories && Array.isArray(doc.repositories)) { 162 | doc.repository = doc.repositories[0] 163 | delete doc.repositories 164 | } 165 | if (doc.repository) p.repository = doc.repository 166 | if (doc.description) p.description = doc.description 167 | for (var i in doc.versions) { 168 | if (doc.versions[i].repository && !doc.repository) { 169 | p.repository = doc.versions[i].repository 170 | } 171 | if (doc.versions[i].keywords) p.keywords = doc.versions[i].keywords 172 | } 173 | send(',' + JSON.stringify(doc._id) + ':' + JSON.stringify(p)) 174 | } 175 | send('}') 176 | if (req.query.jsonp) send(')') 177 | 178 | } 179 | 180 | 181 | lists.byField = function (head, req) { 182 | require("monkeypatch").patch(Object, Date, Array, String) 183 | 184 | if (!req.query.field) { 185 | start({"code":"400", "headers": {"Content-Type": "application/json"}}) 186 | send('{"error":"Please specify a field parameter"}') 187 | return 188 | } 189 | 190 | start({"code": 200, "headers": {"Content-Type": "application/json"}}) 191 | var row 192 | , out = {} 193 | , field = req.query.field 194 | , not = field.charAt(0) === "!" 195 | if (not) field = field.substr(1) 196 | while (row = getRow()) { 197 | if (!row.id) continue 198 | var has = row.value.hasOwnProperty(field) 199 | if (!not && !has || not && has) continue 200 | out[row.key] = { "maintainers": row.value.maintainers.map(function (m) { 201 | return m.name + " <" + m.email + ">" 202 | }) } 203 | if (has) out[row.key][field] = row.value[field] 204 | } 205 | send(JSON.stringify(out)) 206 | } 207 | 208 | 209 | 210 | lists.needBuild = function (head, req) { 211 | start({"code": 200, "headers": {"Content-Type": "text/plain"}}); 212 | var row 213 | , first = true 214 | while (row = getRow()) { 215 | if (!row.id) continue 216 | if (req.query.bindist && row.value[req.query.bindist]) continue 217 | // out.push(row.key) 218 | send((first ? "{" : ",") 219 | + JSON.stringify(row.key) 220 | + ":" 221 | + JSON.stringify(Object.keys(row.value)) 222 | + "\n") 223 | first = false 224 | } 225 | send("}\n") 226 | } 227 | 228 | lists.scripts = function (head, req) { 229 | var row 230 | , out = {} 231 | , scripts = req.query.scripts && req.query.scripts.split(",") 232 | , match = req.query.match 233 | 234 | if (match) match = new RegExp(match) 235 | 236 | while (row = getRow()) { 237 | inc = true 238 | if (!row.id) continue 239 | if (req.query.package && row.id !== req.query.package) continue 240 | if (scripts && scripts.length) { 241 | var inc = false 242 | for (var s = 0, l = scripts.length; s < l && !inc; s ++) { 243 | inc = row.value[scripts[s]] 244 | if (match) inc = inc && row.value[scripts[s]].match(match) 245 | } 246 | if (!inc) continue 247 | } 248 | out[row.id] = row.value 249 | } 250 | send(toJSON(out)) 251 | } 252 | 253 | lists.byUser = function (head, req) { 254 | var out = {} 255 | , user = req.query.user && req.query.user !== "-" ? req.query.user : null 256 | , users = user && user.split("|") 257 | while (row = getRow()) { 258 | if (!user || users.indexOf(row.key) !== -1) { 259 | var l = out[row.key] = out[row.key] || [] 260 | l.push(row.value) 261 | } 262 | } 263 | send(toJSON(out)) 264 | } 265 | 266 | lists.sortCount = function (head, req) { 267 | var out = [] 268 | while (row = getRow()) { 269 | out.push([row.key, row.value]) 270 | } 271 | out = out.sort(function (a, b) { 272 | return a[1] === b[1] ? 0 273 | : a[1] < b[1] ? 1 : -1 274 | }) 275 | var outObj = {} 276 | for (var i = 0, l = out.length; i < l; i ++) { 277 | outObj[out[i][0]] = out[i][1] 278 | } 279 | send(toJSON(outObj)) 280 | } 281 | -------------------------------------------------------------------------------- /registry/modules.js: -------------------------------------------------------------------------------- 1 | // Each of these is a string that will be require()'d in the couchapp 2 | 3 | exports.deep = 4 | [ "exports.deepEquals = deepEquals" 5 | , "exports.extend = deepExtend" 6 | , function deepExtend(o1, o2) { 7 | // extend o1 with o2 (in-place) 8 | for (var prop in o2) { 9 | if (hOP(o2, prop)) { 10 | if (hOP(o1, prop)) { 11 | if (typeof o1[prop] === "object") { 12 | deepExtend(o1[prop], o2[prop]) 13 | } 14 | } else { 15 | o1[prop] = o2[prop] 16 | } 17 | } 18 | } 19 | return o1 20 | } 21 | , function fullPath(pathPrefix, p){ 22 | return pathPrefix.concat([p]) 23 | } 24 | , function isObject(v){ 25 | return typeof v === 'object' 26 | } 27 | , function arrayInArray(v, arr) { 28 | // Check whether `arr` contains an array that's shallowly equal to `v`. 29 | return arr.some(function(e) { 30 | if (e.length !== v.length) return false 31 | for (var i=0; i@:%\s\\\*'"!~`]/) 103 | || n.toLowerCase() === "node_modules" 104 | || n !== encodeURIComponent(n) 105 | || n.toLowerCase() === "favicon.ico") { 106 | return false 107 | } 108 | return n 109 | } 110 | , function validPackage (pkg) { 111 | return validName(pkg.name) && semver.valid(pkg.version) 112 | } 113 | ].map(function (s) { return s.toString() }).join("\n") 114 | 115 | 116 | // monkey patchers 117 | exports.Date = 118 | [ "exports.parse = parse" 119 | , "exports.toISOString = toISOString" 120 | , "exports.now = now" 121 | , function now () { 122 | return new Date().getTime() 123 | } 124 | , function parse (s) { 125 | // s is something like "2010-12-29T07:31:06Z" 126 | s = s.split("T") 127 | var ds = s[0] 128 | , ts = s[1] 129 | , d = new Date() 130 | ds = ds.split("-") 131 | ts = ts.split(":") 132 | var tz = ts[2].substr(2) 133 | ts[2] = ts[2].substr(0, 2) 134 | d.setUTCFullYear(+ds[0]) 135 | d.setUTCMonth(+ds[1]-1) 136 | d.setUTCDate(+ds[2]) 137 | d.setUTCHours(+ts[0]) 138 | d.setUTCMinutes(+ts[1]) 139 | d.setUTCSeconds(+ts[2]) 140 | d.setUTCMilliseconds(0) 141 | return d.getTime() 142 | } 143 | , "exports.toISOString = toISOString" 144 | , function toISOString () { return ISODateString(this) } 145 | , function pad(n){return n<10 ? '0'+n : n} 146 | , function ISODateString(d){ 147 | return d.getUTCFullYear()+'-' 148 | + pad(d.getUTCMonth()+1)+'-' 149 | + pad(d.getUTCDate())+'T' 150 | + pad(d.getUTCHours())+':' 151 | + pad(d.getUTCMinutes())+':' 152 | + pad(d.getUTCSeconds())+'Z'} 153 | ].map(function (s) { return s.toString() }).join("\n") 154 | 155 | exports.Object = 156 | [ "exports.keys = keys" 157 | , function keys (o) { 158 | var a = [] 159 | for (var i in o) a.push(i) 160 | return a } 161 | ].map(function (s) { return s.toString() }).join("\n") 162 | 163 | exports.Array = 164 | [ "exports.isArray = isArray" 165 | , "exports.forEach = forEach", 166 | , "exports.reduce = reduce", 167 | , function forEach (fn) { 168 | for (var i = 0, l = this.length; i < l; i ++) { 169 | if (this.hasOwnProperty(i)) { 170 | fn(this[i], i, this) 171 | } 172 | } 173 | } 174 | , function reduce (callback, initialValue) { 175 | var previousValue = initialValue || this[0]; 176 | for (var i = initialValue ? 0 : 1; i < this.length; i++) { 177 | previousValue = callback(previousValue, this[i], i, this); 178 | } 179 | return previousValue; 180 | } 181 | , function isArray (a) { 182 | return a instanceof Array 183 | || Object.prototype.toString.call(a) === "[object Array]" 184 | || (typeof a === "object" && typeof a.length === "number") } 185 | ].map(function (s) { return s.toString() }).join("\n") 186 | 187 | exports.String = 188 | [ "exports.trim = trim" 189 | , function trim () { 190 | return this.replace(/^\s+|\s+$/g, "") 191 | } 192 | ].map(function (s) { return s.toString() }).join("\n") 193 | 194 | exports.monkeypatch = 195 | [ "exports.patch = patch" 196 | , function patch (Object, Date, Array, String) { 197 | if (!Date.parse || isNaN(Date.parse("2010-12-29T07:31:06Z"))) { 198 | Date.parse = require("Date").parse 199 | } 200 | 201 | Date.prototype.toISOString = Date.prototype.toISOString 202 | || require("Date").toISOString 203 | 204 | Date.now = Date.now 205 | || require("Date").now 206 | 207 | Object.keys = Object.keys 208 | || require("Object").keys 209 | 210 | Array.prototype.forEach = Array.prototype.forEach 211 | || require("Array").forEach 212 | 213 | Array.prototype.reduce = Array.prototype.reduce 214 | || require("Array").reduce 215 | 216 | Array.isArray = Array.isArray 217 | || require("Array").isArray 218 | 219 | String.prototype.trim = String.prototype.trim 220 | || require("String").trim 221 | } 222 | ].map(function (s) { return s.toString() }).join("\n") 223 | -------------------------------------------------------------------------------- /registry/rewrites.js: -------------------------------------------------------------------------------- 1 | module.exports = 2 | [ { from: "/", to:"../..", method: "GET" } 3 | 4 | , { from: "/_session", to: "../../../_session", method: "GET" } 5 | , { from: "/_session", to: "../../../_session", method: "PUT" } 6 | , { from: "/_session", to: "../../../_session", method: "POST" } 7 | , { from: "/_session", to: "../../../_session", method: "DELETE" } 8 | , { from: "/_session", to: "../../../_session", method: "HEAD" } 9 | 10 | , { from: "/-/ping", to: "/_show/ping", method: "GET" } 11 | , { from: "/-/ping/*", to: "/_show/ping", method: "GET" } 12 | , { from: "/-/whoami", to: "/_show/whoami", method: "GET" } 13 | 14 | // Stuff to support restricted-access modules, which this couchapp doesn't 15 | , { from: "/-/package/:pkg/access", to: "/_show/notImplemented"} 16 | 17 | , { from: "/-/package/:pkg/dist-tags", to: "/_show/distTags/:pkg", method: "GET" } 18 | , { from: "/-/package/:pkg/dist-tags/:tag", to: "/_update/distTags/:pkg", method: "DELETE" } 19 | , { from: "/-/package/:pkg/dist-tags/:tag", to: "/_update/distTags/:pkg", method: "PUT" } 20 | , { from: "/-/package/:pkg/dist-tags/:tag", to: "/_update/distTags/:pkg", method: "POST" } 21 | , { from: "/-/package/:pkg/dist-tags", to: "/_update/distTags/:pkg", method: "PUT" } 22 | , { from: "/-/package/:pkg/dist-tags", to: "/_update/distTags/:pkg", method: "POST" } 23 | 24 | , { from: "/-/all/since", to:"_list/index/modified", method: "GET" } 25 | 26 | , { from: "/-/rss", to: "_list/rss/modified" 27 | , method: "GET" } 28 | 29 | , { from: "/-/rss/:package", to: "_list/rss/modifiedPackage" 30 | , method: "GET" } 31 | 32 | , { from: "/-/all", to:"_list/index/listAll", method: "GET" } 33 | , { from: "/-/all/-/jsonp/:jsonp", to:"_list/index/listAll", method: "GET" } 34 | 35 | , { from: "/-/scripts", to:"_list/scripts/scripts", method: "GET" } 36 | , { from: "/-/by-field", to:"_list/byField/byField", method: "GET" } 37 | , { from: "/-/fields", to:"_list/sortCount/fieldsInUse", method: "GET", 38 | query: { group: "true" } } 39 | 40 | , { from: "/-/needbuild", to:"_list/needBuild/needBuild", method: "GET" } 41 | , { from : "/favicon.ico", to:"../../npm/favicon.ico", method:"GET" } 42 | 43 | , { from: "/-/user/:user", to:"../../../_users/:user", method: "PUT" } 44 | 45 | , { from: "/-/user/:user/-rev/:rev", to:"../../../_users/:user" 46 | , method: "PUT" } 47 | 48 | , { from: "/-/user/:user", to:"../../../_users/:user", method: "GET" } 49 | 50 | // Just have it work like a regular old couchdb thing 51 | // this means that the couch-login module can be used to create accounts. 52 | , { from: "/_users/:user", to:"../../../_users/:user", method: "PUT" } 53 | , { from: "/_users/:user", to:"../../../_users/:user", method: "GET" } 54 | , { from: "/public_users/:user", to:"../../../public_users/:user", method: "PUT" } 55 | , { from: "/public_users/:user", to:"../../../public_users/:user", method: "GET" } 56 | 57 | , { from: "/-/user-by-email/:email" 58 | , to:"../../../_users/_design/_auth/_list/email/listAll" 59 | , method: "GET" } 60 | 61 | , { from: "/-/top" 62 | , to:"_view/npmTop" 63 | , query: { group_level: 1 } 64 | , method: "GET" } 65 | 66 | , { from: "/-/by-user/:user", to: "_list/byUser/byUser", method: "GET" } 67 | , { from: "/-/starred-by-user/:user", to: "_list/byUser/starredByUser", method: "GET" } 68 | , { from: "/-/starred-by-package/:user", to: "_list/byUser/starredByPackage", method: "GET" } 69 | 70 | , { from: "/:pkg", to: "/_show/package/:pkg", method: "GET" } 71 | , { from: "/:pkg/-/jsonp/:jsonp", to: "/_show/package/:pkg", method: "GET" } 72 | , { from: "/:pkg/:version", to: "_show/package/:pkg", method: "GET" } 73 | , { from: "/:pkg/:version/-/jsonp/:jsonp", to: "_show/package/:pkg" 74 | , method: "GET" } 75 | 76 | , { from: "/npm/public/registry/:firstletter/:pkg/_attachments/:att", to: "../../:pkg/:att", method: "GET" } 77 | , { from: "/npm/public/registry/:firstletter/:pkg/_attachments/:att/:rev", to: "../../:pkg/:att", method: "PUT" } 78 | , { from: "/npm/public/registry/:firstletter/:pkg/_attachments/:att/-rev/:rev", to: "../../:pkg/:att", method: "PUT" } 79 | , { from: "/npm/public/registry/:firstletter/:pkg/_attachments/:att/:rev", to: "../../:pkg/:att", method: "DELETE" } 80 | , { from: "/npm/public/registry/:firstletter/:pkg/_attachments/:att/-rev/:rev", to: "../../:pkg/:att", method: "DELETE" } 81 | 82 | , { from: "/npm/public/registry/:pkg/_attachments/:att", to: "../../:pkg/:att", method: "GET" } 83 | , { from: "/npm/public/registry/:pkg/_attachments/:att/:rev", to: "../../:pkg/:att", method: "PUT" } 84 | , { from: "/npm/public/registry/:pkg/_attachments/:att/-rev/:rev", to: "../../:pkg/:att", method: "PUT" } 85 | , { from: "/npm/public/registry/:pkg/_attachments/:att/:rev", to: "../../:pkg/:att", method: "DELETE" } 86 | , { from: "/npm/public/registry/:pkg/_attachments/:att/-rev/:rev", to: "../../:pkg/:att", method: "DELETE" } 87 | 88 | , { from: "/:pkg/-/:att", to: "../../:pkg/:att", method: "GET" } 89 | , { from: "/:pkg/-/:att/:rev", to: "../../:pkg/:att", method: "PUT" } 90 | , { from: "/:pkg/-/:att/-rev/:rev", to: "../../:pkg/:att", method: "PUT" } 91 | , { from: "/:pkg/-/:att/:rev", to: "../../:pkg/:att", method: "DELETE" } 92 | , { from: "/:pkg/-/:att/-rev/:rev", to: "../../:pkg/:att", method: "DELETE" } 93 | 94 | , { from: "/:pkg", to: "/_update/package/:pkg", method: "PUT" } 95 | , { from: "/:pkg/-rev/:rev", to: "/_update/package/:pkg", method: "PUT" } 96 | 97 | , { from: "/:pkg/:version", to: "_update/package/:pkg", method: "PUT" } 98 | , { from: "/:pkg/:version/-rev/:rev", to: "_update/package/:pkg" 99 | , method: "PUT" } 100 | 101 | , { from: "/:pkg/:version/-tag/:tag", to: "_update/package/:pkg" 102 | , method: "PUT" } 103 | , { from: "/:pkg/:version/-tag/:tag/-rev/:rev", to: "_update/package/:pkg" 104 | , method: "PUT" } 105 | 106 | , { from: "/-metadata/:pkg", to: "_update/metadata/:pkg", method: "PUT" } 107 | 108 | , { from: "/:pkg/:version/-pre/:pre", to: "_update/package/:pkg" 109 | , method: "PUT" } 110 | , { from: "/:pkg/:version/-pre/:pre/-rev/:rev", to: "_update/package/:pkg" 111 | , method: "PUT" } 112 | 113 | , { from: "/:pkg/-rev/:rev", to: "_update/delete/:pkg", method: "DELETE" } 114 | 115 | 116 | , {from:'/-/_view/*', to:'_view/*', method: 'GET'} 117 | , {from:'/-/_list/*', to:'_list/*', method: 'GET'} 118 | , {from:'/-/_show/*', to:'_show/*', method: 'GET'} 119 | ] 120 | -------------------------------------------------------------------------------- /registry/shadow.js: -------------------------------------------------------------------------------- 1 | module.exports = 2 | { _id:'_design/ghost' 3 | , rewrites: ghostRewrites() 4 | , language: "javascript" 5 | } 6 | 7 | function ghostRewrites () { 8 | return require("./rewrites.js").map(function (rule) { 9 | 10 | var to = rule.to 11 | // Note: requests to /_users/blah are still passed through directly. 12 | if (rule.to.match(/\/_users(?:\/|$)/) && 13 | !rule.from.match(/^\/?_users/)) { 14 | if (rule.method === "GET") { 15 | to = to.replace(/\/_users(\/|$)/, "/public_users$1") 16 | } else if (rule.method === "PUT") { 17 | // when couchdb lets us PUT to _update functions on _users, 18 | // uncomment this. For now, we'll just leave it as-is, 19 | // and use newedits=false to sync the rev fields to public_users. 20 | // 21 | // to = to.replace(/\/_users(\/|$)/, 22 | // "/_users/_design/auth/_update/norev$1") 23 | } 24 | } else { 25 | to = "../app/" + to 26 | } 27 | to = to.replace(/\/\/+/g, '/') 28 | 29 | return { from: rule.from 30 | , method: rule.method 31 | , query: rule.query 32 | , to: to 33 | } 34 | }) 35 | } 36 | 37 | if (require.main === module) console.log(module.exports) 38 | -------------------------------------------------------------------------------- /registry/shows.js: -------------------------------------------------------------------------------- 1 | 2 | var shows = exports 3 | 4 | shows.notImplemented = function (doc, req) { 5 | return { 6 | code: 501, 7 | headers: { 8 | "content-type": "application/json" 9 | }, 10 | body: JSON.stringify({ 11 | error: "Not Implemented", 12 | reason: "This server does not support this endpoint" 13 | }) 14 | } 15 | } 16 | 17 | shows.whoami = function (doc, req) { 18 | return { 19 | code: 200, 20 | headers: { 21 | "content-type": "application/json" 22 | }, 23 | body: JSON.stringify({ 24 | username: req.userCtx.name 25 | }) 26 | } 27 | } 28 | 29 | shows.distTags = function (doc, req) { 30 | return { 31 | code: 200, 32 | headers: { 33 | "content-type": "application/json" 34 | }, 35 | body: JSON.stringify(doc["dist-tags"]) 36 | } 37 | } 38 | 39 | shows.package = function (doc, req) { 40 | require("monkeypatch").patch(Object, Date, Array, String) 41 | 42 | var semver = require("semver") 43 | , code = 200 44 | , headers = {"Content-Type":"application/json"} 45 | , body = null 46 | 47 | delete doc.ctime 48 | delete doc.mtime 49 | if (!doc._attachments) doc._attachments = {} 50 | 51 | if (doc.time && doc.time.unpublished) { 52 | delete doc._revisions 53 | return { 54 | code : 404, 55 | body : JSON.stringify(doc), 56 | headers : headers 57 | } 58 | } 59 | 60 | if (doc.versions) Object.keys(doc.versions).forEach(function (v) { 61 | delete doc.versions[v].ctime 62 | delete doc.versions[v].mtime 63 | }) 64 | 65 | // legacy kludge 66 | if (doc.versions) for (var v in doc.versions) { 67 | var clean = semver.clean(v, true) 68 | doc.versions[v].directories = doc.versions[v].directories || {} 69 | if (clean !== v) { 70 | var p = doc.versions[v] 71 | delete doc.versions[v] 72 | p.version = v = clean 73 | p._id = p.name + '@' + p.version 74 | doc.versions[clean] = p 75 | } 76 | 77 | if (doc.versions[v].dist.tarball) { 78 | // if there is an attachment for this tarball, then use that. 79 | // make it point at THIS registry that is being requested, 80 | // with the full /db/_design/app/_rewrite if that is being used, 81 | // or just the /name if not. 82 | 83 | var t = doc.versions[v].dist.tarball 84 | t = t.replace(/^https?:\/\/[^\/:]+(:[0-9]+)?/, '') 85 | var f = t.match(/[^\/]+$/)[0] 86 | var requestedPath = req.requested_path 87 | if (doc._attachments && doc._attachments[f]) { 88 | // workaround for old couch versions that didn't 89 | // have requested_path 90 | if (requestedPath && -1 === requestedPath.indexOf('show')) 91 | requestedPath = requestedPath.slice(0) 92 | else { 93 | var path = req.path 94 | if (path) { 95 | var i = path.indexOf('_show') 96 | if (i !== -1) { 97 | requestedPath = path.slice(0) 98 | requestedPath.splice(i, i + 2, '_rewrite') 99 | } 100 | } else return { 101 | code : 500, 102 | body : JSON.stringify({error: 'bad couch'}), 103 | headers : headers 104 | } 105 | } 106 | 107 | // doc.versions[v].dist._origTarball = doc.versions[v].dist.tarball 108 | // doc.versions[v].dist._headers = req.headers 109 | // doc.versions[v].dist._query = req.query 110 | // doc.versions[v].dist._reqPath = req.requested_path 111 | // doc.versions[v].dist._path = req.path 112 | // doc.versions[v].dist._t = t.slice(0) 113 | 114 | // actual location of tarball should always be: 115 | // .../_rewrite/pkg/-/pkg-version.tgz 116 | // or: /pkg/-/pkg-version.tgz 117 | // depending on what requested path is. 118 | var tf = [doc.name, '-', t.split('/').pop()] 119 | var i = requestedPath.indexOf('_rewrite') 120 | if (i !== -1) { 121 | tf = requestedPath.slice(0, i + 1).concat(tf) 122 | } 123 | t = '/' + tf.join('/') 124 | var proto = req.headers['X-Forwarded-Proto'] || 'http'; 125 | var h = proto + "://" + ( req.headers['X-Forwarded-Host'] || req.headers.Host ); 126 | 127 | doc.versions[v].dist.tarball = h + t 128 | } 129 | } 130 | } 131 | if (doc["dist-tags"]) for (var tag in doc["dist-tags"]) { 132 | var clean = semver.clean(doc["dist-tags"][tag], true) 133 | if (!clean) delete doc["dist-tags"][tag] 134 | else doc["dist-tags"][tag] = clean 135 | } 136 | // end kludge 137 | 138 | 139 | if (req.query.version) { 140 | // could be either one! 141 | // if it's a fuzzy version or a range, use the max satisfying version 142 | var ver = req.query.version 143 | var clean = semver.maxSatisfying(Object.keys(doc.versions), ver, true) 144 | 145 | if (clean && clean !== ver && (clean in doc.versions)) 146 | ver = clean 147 | 148 | // if not a valid version, then treat as a tag. 149 | if ((!(ver in doc.versions) && (ver in doc["dist-tags"])) 150 | || !semver.valid(ver)) { 151 | ver = doc["dist-tags"][ver] 152 | } 153 | body = doc.versions[ver] 154 | if (!body) { 155 | code = 404 156 | body = {"error" : "version not found: "+req.query.version} 157 | } 158 | } else { 159 | body = doc 160 | delete body._revisions 161 | } 162 | 163 | body = req.query.jsonp 164 | ? req.query.jsonp + "(" + JSON.stringify(body) + ")" 165 | : toJSON(body) 166 | 167 | return { 168 | code : code, 169 | body : body, 170 | headers : headers 171 | } 172 | } 173 | 174 | 175 | shows.new_package = function (doc, req) { 176 | var semver = require("semver") 177 | , code = 200 178 | , headers = {"Content-Type":"application/json"} 179 | , body = null 180 | 181 | if (!doc._attachments) doc._attachments = {} 182 | 183 | if (req.query.version) { 184 | // could be either one! 185 | // if it's a fuzzy version or a range, use the max satisfying version 186 | var ver = req.query.version 187 | var clean = semver.maxSatisfying(Object.keys(doc.versions), ver, true) 188 | 189 | if (clean && clean !== ver && (clean in doc.versions)) 190 | ver = clean 191 | 192 | // if not a valid version, then treat as a tag. 193 | if ((!(ver in doc.versions) && (ver in doc["dist-tags"])) 194 | || !semver.valid(ver)) { 195 | ver = doc["dist-tags"][ver] 196 | } 197 | body = doc.versions[ver] 198 | if (!body) { 199 | code = 404 200 | body = {"error" : "version not found: "+req.query.version} 201 | } 202 | } else { 203 | body = doc 204 | } 205 | 206 | body = toJSON(body) 207 | 208 | return { 209 | code : code, 210 | body : body, 211 | headers : headers 212 | } 213 | } 214 | 215 | shows.ping = function (doc, req) { 216 | var code = 200 217 | , headers = {"Content-Type":"application/json"} 218 | 219 | var body = { 220 | host: req.headers["Host"] 221 | , ok: true 222 | , username: req.userCtx.name 223 | , peer: req.peer 224 | } 225 | 226 | body = toJSON(body) 227 | 228 | return { 229 | code : code 230 | , body : body 231 | , headers : headers 232 | } 233 | } 234 | -------------------------------------------------------------------------------- /registry/test.js: -------------------------------------------------------------------------------- 1 | var http = require("http"), 2 | url = require("url"), 3 | sys = require("sys"); 4 | 5 | function request (path, method, headers, body, callback) { 6 | if (!headers) { 7 | headers = {'Content-Type':'application/json', "Accept":'application/json', "Host":"jsregistry:5984"}; 8 | } 9 | if (!method) { 10 | method = "GET" 11 | } 12 | if (body) { 13 | if (typeof body !== "string") { 14 | body = JSON.stringify(body) 15 | } 16 | } 17 | 18 | var client = http.createClient(5984, "jsregistry"); 19 | var request = client.request(method, path, headers); 20 | request.addListener("response", function (response) { 21 | var buffer = '' 22 | response.addListener("data", function (chunk) { 23 | buffer += chunk; 24 | }) 25 | response.addListener("end", function () { 26 | callback(response, buffer); 27 | }) 28 | }) 29 | request.write(body) 30 | request.close() 31 | 32 | } 33 | 34 | function requestQueue (args, doneCallback) { 35 | var runner = function (args, i) { 36 | var validation = args[i].pop(); 37 | args[i].push(function (request, response) { 38 | validation(request, response); 39 | if (i<(args.length - 1)) { 40 | runner(args, i + 1) 41 | } else if (doneCallback) { 42 | doneCallback(); 43 | } 44 | }) 45 | request.apply(request, args[i]) 46 | } 47 | runner(args, 0); 48 | } 49 | 50 | // Test new module creation 51 | 52 | function assertStatus (code) { 53 | var c = code; 54 | return function (response, body) { 55 | if (response.statusCode != c) { 56 | sys.puts("Status is not "+c+" it is "+response.statusCode+'. '+body) 57 | throw "Status is not "+c+" it is "+response.statusCode+'. '+body; 58 | } else { 59 | sys.puts(body); 60 | } 61 | } 62 | } 63 | 64 | // request('/foo', "PUT", undefined, {id:"foo", description:"new module"}, function () {sys.puts('done')}) 65 | 66 | var sha = require('./deps/sha1'), 67 | base64 = require('./deps/base64'); 68 | 69 | var userDoc = {_id:"org.couchdb.user:testuser", 70 | name:"testuser", 71 | password_sha: sha.hex_sha1('testing' + 'pepper'), 72 | salt:"pepper", type:"user", roles:[]} 73 | var auth = {'Content-Type':'application/json', 74 | accept:'application/json', 75 | authorization:'Basic ' + base64.encode('testuser:testing'), 76 | host:"jsregistry:5984"} 77 | 78 | requestQueue([ 79 | ["/adduser/org.couchdb.user:testuser", "PUT", undefined, userDoc, assertStatus(201)], 80 | // ["/session", "POST", undefined, "user=testuser&password=testing", function (response, body) { 81 | // sys.puts('s', body, 'd') 82 | // auth.cookie = response.headers['set-cookie']; 83 | // }], 84 | ["/foo", "PUT", auth, {_id:"foo", description:"new module"}, assertStatus(201)], 85 | ["/foo/0.1.0", "PUT", auth, 86 | {_id:"foo", description:"new module", dist:{tarball:"http://path/to/tarball"}}, assertStatus(201)], 87 | ["/foo/stable", "PUT", auth, "0.1.0", assertStatus(201)], 88 | ["/foo", "GET", undefined, "0.1.0", assertStatus(200)], 89 | ["/foo/0.1.0", "GET", undefined, "0.1.0", assertStatus(200)], 90 | ["/foo/stable", "GET", undefined, "0.1.0", assertStatus(200)], 91 | ], function () {sys.puts('done')}) 92 | -------------------------------------------------------------------------------- /test/00-setup.js: -------------------------------------------------------------------------------- 1 | // start the couchdb spinning as a detached child process. 2 | // the zz-teardown.js test kills it. 3 | 4 | var spawn = require('child_process').spawn 5 | var exec = require('child_process').exec 6 | var test = require('tap').test 7 | var path = require('path') 8 | var fs = require('fs') 9 | var http = require('http') 10 | var url = require('url') 11 | 12 | // just in case it was still alive from a previous run, kill it. 13 | require('./zz-teardown.js') 14 | 15 | // run with the cwd of the main program. 16 | var cwd = path.dirname(__dirname) 17 | 18 | var timeout = 300000; // 5 minutes 19 | var conf = path.resolve(__dirname, 'fixtures', 'couch.ini') 20 | var pidfile = path.resolve(__dirname, 'fixtures', 'pid') 21 | var logfile = path.resolve(__dirname, 'fixtures', 'couch.log') 22 | var started = /Apache CouchDB has started on http:\/\/127\.0\.0\.1:15986\/\n$/ 23 | var configFiles 24 | 25 | test('setup', function (t) { 26 | exec('couchdb -c', function (_, stdout) { 27 | configFiles = stdout.trim().split(/\n/).filter(function (file) { 28 | try { 29 | return fs.readFileSync(file) 30 | } catch (e) { 31 | console.error('#', "Couldn't read", file) 32 | return false 33 | } 34 | }) 35 | configFiles.push(conf) 36 | t.end() 37 | }) 38 | }) 39 | 40 | test('start couch as a zombie child', function (t) { 41 | var fd = fs.openSync(pidfile, 'wx') 42 | 43 | try { fs.unlinkSync(logfile) } catch (er) {} 44 | 45 | var cmd = 'couchdb' 46 | var args = ['-n'] 47 | configFiles.forEach(function (file) { 48 | args.push('-a', file) 49 | }) 50 | 51 | console.log('# spawning: ', cmd, args) 52 | var child = spawn(cmd, args, { 53 | detached: true, 54 | stdio: 'ignore', 55 | cwd: cwd 56 | }) 57 | child.unref() 58 | child.on('close', function (code, signal) { 59 | console.error('Couch exited unexpectedly with a code of', code, 'and a signal of', signal) 60 | t.bailout() 61 | }) 62 | t.ok(child.pid, 'got child pid from spawn') 63 | fs.writeSync(fd, child.pid + '\n') 64 | fs.closeSync(fd) 65 | 66 | // wait for it to create a log, give it 5 seconds 67 | var start = Date.now() 68 | fs.readFile(logfile, function R (er, log) { 69 | log = log ? log.toString() : '' 70 | if (!er && !log.match(started)) 71 | er = new Error('not started yet') 72 | if (er) { 73 | if (Date.now() - start < timeout) 74 | return setTimeout(function () { 75 | fs.readFile(logfile, R) 76 | }, 100) 77 | else 78 | throw er 79 | } 80 | t.pass('relax, jeez') 81 | t.end() 82 | }) 83 | }) 84 | 85 | test('create test db', function(t) { 86 | var u = url.parse('http://admin:admin@localhost:15986/registry') 87 | u.method = 'PUT' 88 | http.request(u, function(res) { 89 | t.equal(res.statusCode, 201) 90 | var c = '' 91 | res.setEncoding('utf8') 92 | res.on('data', function(chunk) { 93 | c += chunk 94 | }) 95 | res.on('end', function() { 96 | c = JSON.parse(c) 97 | t.same(c, { ok: true }) 98 | t.end() 99 | }) 100 | }).end() 101 | }) 102 | 103 | 104 | if (!process.env.TRAVIS) { 105 | test('get the git-describe output', function (t) { 106 | var c = spawn('git', ['describe', '--tags']) 107 | c.stderr.pipe(process.stderr) 108 | var desc = '' 109 | c.stdout.on('data', function (d) { 110 | desc += d 111 | }) 112 | 113 | c.stdout.on('end', function () { 114 | process.env.DEPLOY_VERSION = desc.trim() 115 | t.end() 116 | }) 117 | }) 118 | } 119 | 120 | test('ddoc', function(t) { 121 | var app = require.resolve('../registry/app.js') 122 | var couch = 'http://admin:admin@localhost:15986/registry' 123 | var c = spawn('couchapp', ['push', app, couch]) 124 | c.stderr.pipe(process.stderr) 125 | c.stdout.pipe(process.stdout) 126 | c.on('exit', function(code) { 127 | t.notOk(code) 128 | t.end() 129 | }) 130 | }) 131 | 132 | test('users ddoc', function(t) { 133 | var app = require.resolve('../registry/_auth.js') 134 | var couch = 'http://admin:admin@localhost:15986/_users' 135 | var c = spawn('couchapp', ['push', app, couch]) 136 | c.stderr.pipe(process.stderr) 137 | c.stdout.pipe(process.stdout) 138 | c.on('exit', function(code) { 139 | t.notOk(code) 140 | t.end() 141 | }) 142 | }) 143 | -------------------------------------------------------------------------------- /test/01-adduser.js: -------------------------------------------------------------------------------- 1 | var common = require('./common.js') 2 | var test = require('tap').test 3 | var reg = 'http://127.0.0.1:15986/' 4 | var path = require('path') 5 | 6 | var conf = path.resolve(__dirname, 'fixtures', 'npmrc') 7 | var conf2 = path.resolve(__dirname, 'fixtures', 'npmrc2') 8 | var conf3 = path.resolve(__dirname, 'fixtures', 'npmrc3') 9 | 10 | var fs = require('fs') 11 | 12 | try { fs.unlinkSync(conf) } catch (er) {} 13 | try { fs.unlinkSync(conf2) } catch (er) {} 14 | try { fs.unlinkSync(conf3) } catch (er) {} 15 | 16 | var u = { u: 'user', p: 'pass@:!%\'', e: 'email@example.com' } 17 | var o = { u: 'other', p: 'pass@:!%\'', e: 'other@example.com' } 18 | var t = { u: 'third', p: 'pass@:!%\'', e: '3@example.com' } 19 | 20 | test('adduser', fn.bind(null, conf, u)) 21 | test('adduser again', fn.bind(null, conf, u)) 22 | 23 | test('adduser 2', fn.bind(null, conf2, o)) 24 | test('adduser 2 again', fn.bind(null, conf2, o)) 25 | 26 | test('adduser 3', fn.bind(null, conf3, t)) 27 | test('adduser 3 again', fn.bind(null, conf3, t)) 28 | 29 | function fn(conf, u, t) { 30 | var c = common.npm([ 31 | '--registry=' + reg, 32 | '--userconf=' + conf, 33 | 'adduser' 34 | ]) 35 | c.stderr.pipe(process.stderr) 36 | var buf = '' 37 | c.stdout.setEncoding('utf8') 38 | c.stdout.on('data', function(d) { 39 | buf += d 40 | if (buf.match(/: /)) { 41 | console.log(buf) 42 | switch (buf.split(':')[0]) { 43 | case 'Username': 44 | c.stdin.write(u.u + '\r\n') 45 | break 46 | case 'Password': 47 | c.stdin.write(u.p + '\r\n') 48 | break 49 | case 'Email': 50 | c.stdin.end(u.e + '\r\n') 51 | break 52 | default: 53 | throw 'wtf: ' + JSON.stringify(buf) 54 | } 55 | buf = '' 56 | } 57 | }) 58 | c.on('exit', function(code) { 59 | t.notOk(code) 60 | t.end() 61 | }) 62 | } 63 | -------------------------------------------------------------------------------- /test/01b-user-views.js: -------------------------------------------------------------------------------- 1 | var expect = { 2 | 'userByEmail?group=true' : { 3 | "rows": [ 4 | { 5 | "key": [ 6 | "3@example.com", 7 | "third" 8 | ], 9 | "value": 1 10 | }, 11 | { 12 | "key": [ 13 | "email@example.com", 14 | "user" 15 | ], 16 | "value": 1 17 | }, 18 | { 19 | "key": [ 20 | "other@example.com", 21 | "other" 22 | ], 23 | "value": 1 24 | } 25 | ] 26 | }, 27 | 'invalidUser': { 28 | "total_rows": 0, 29 | "offset": 0, 30 | "rows": [] 31 | }, 32 | 'invalid?group=true': { "rows": [] }, 33 | 'conflicts?group=true': { "rows": [] } 34 | } 35 | 36 | var test = require('tap').test 37 | var u = 'http://admin:admin@localhost:15986/_users/_design/scratch/_view/' 38 | var http = require('http') 39 | var parse = require('parse-json-response') 40 | 41 | Object.keys(expect).forEach(function(view) { 42 | test(view, function(t) { 43 | http.get(u + view, parse(function(er, data, res) { 44 | if (er) 45 | throw er 46 | t.same(data, expect[view]) 47 | t.end() 48 | })) 49 | }) 50 | }) 51 | -------------------------------------------------------------------------------- /test/01c-user-updates.js: -------------------------------------------------------------------------------- 1 | var test = require('tap').test 2 | var request = require('request') 3 | var parse = require('parse-json-response') 4 | 5 | test('update profile', function (t) { 6 | 7 | var id = 'org.couchdb.user:user' 8 | var u = 'http://admin:admin@localhost:15986/_users/' + id 9 | 10 | request.get({ 11 | url: u 12 | , json: true 13 | }, function (err, res, prof) { 14 | prof.github = 'user' 15 | prof.homepage = 'http://www.user.com' 16 | 17 | request.post({ 18 | url: 'http://admin:admin@localhost:15986/_users/_design/scratch/_update/profile/' + id 19 | , body: prof 20 | , json: true 21 | }, function (err, res, body) { 22 | if (err) throw err 23 | 24 | request.get({ 25 | url: u 26 | , json: true 27 | }, function (err, res, body) { 28 | 29 | t.same(body.github, prof.github) 30 | t.same(body.homepage, prof.homepage) 31 | t.end() 32 | }) 33 | }) 34 | }) 35 | }) 36 | 37 | test('update email', function (t) { 38 | 39 | var id = 'org.couchdb.user:user' 40 | var u = 'http://admin:admin@localhost:15986/_users/' + id 41 | 42 | request.get({ 43 | url: u 44 | , json: true 45 | }, function (err, res, prof) { 46 | t.ifError(err, 'user metadata fetched') 47 | prof.email = 'new@email.com' 48 | 49 | request.post({ 50 | url: 'http://admin:admin@localhost:15986/_users/_design/scratch/_update/email/' + id 51 | , body: prof 52 | , json: true 53 | }, function (err, res, body) { 54 | t.ifError(err, 'user email address changed') 55 | 56 | request.get({ 57 | url: u 58 | , json: true 59 | }, function (err, res, body) { 60 | t.ifError(err, 'user record updated on second fetch') 61 | t.same(body.email, prof.email) 62 | t.end() 63 | }) 64 | }) 65 | }) 66 | }) 67 | -------------------------------------------------------------------------------- /test/01d-whoami.js: -------------------------------------------------------------------------------- 1 | var url = 'http://127.0.0.1:15986/-/whoami' 2 | var auth = new Buffer("user:pass@:!%'").toString('base64') 3 | var badauth = new Buffer("user:wrong").toString('base64') 4 | var test = require('tap').test 5 | var request = require('request') 6 | 7 | test('hit whoami endpoint as user', function (t) { 8 | request({ 9 | url: url, 10 | headers: { 11 | authorization: 'Basic ' + auth 12 | }, 13 | json: true 14 | }, function (er, res, body) { 15 | t.same(body, { 16 | username: 'user' 17 | }) 18 | t.end() 19 | }) 20 | }) 21 | 22 | test('hit whoami endpoint as anon', function (t) { 23 | request({ 24 | url: url, 25 | json: true 26 | }, function (er, res, body) { 27 | t.same(body, { username: null }) 28 | t.end() 29 | }) 30 | }) 31 | 32 | test('hit whoami with wrong pass', function (t) { 33 | request({ 34 | url: url, 35 | headers: { 36 | authorization: 'Basic ' + badauth 37 | }, 38 | json: true 39 | }, function (er, res, body) { 40 | t.same(body, { 41 | error: "unauthorized", 42 | reason: "Name or password is incorrect." 43 | }) 44 | t.end() 45 | }) 46 | }) 47 | -------------------------------------------------------------------------------- /test/02-publish.js: -------------------------------------------------------------------------------- 1 | var common = require('./common.js') 2 | var test = require('tap').test 3 | var reg = 'http://127.0.0.1:15986/' 4 | var request = require('request') 5 | var db = 'http://localhost:15986/registry/' 6 | var fs = require('fs') 7 | var path = require('path') 8 | var rimraf = require('rimraf') 9 | var conf = path.resolve(__dirname, 'fixtures', 'npmrc') 10 | var conf2 = path.resolve(__dirname, 'fixtures', 'npmrc2') 11 | var pkg = path.resolve(__dirname, 'fixtures/package') 12 | var pkg002 = path.resolve(pkg, '0.0.2') 13 | var pkg023a = path.resolve(pkg, '0.2.3alpha') 14 | var pkg023 = path.resolve(pkg, '0.2.3') 15 | var inst = path.resolve(__dirname, 'fixtures/install') 16 | var http = require('http') 17 | var maintainers = [ 18 | { 19 | "name": "user", 20 | "email": "email@example.com" 21 | } 22 | ] 23 | var url = require("url") 24 | 25 | var expect = null 26 | 27 | var version002 = { 28 | "name": "package", 29 | "version": "0.0.2", 30 | "description": "just an npm test", 31 | "_id": "package@0.0.2", 32 | "dist": { 33 | "tarball": "http://127.0.0.1:15986/package/-/package-0.0.2.tgz" 34 | }, 35 | "_npmUser": { 36 | "name": "user", 37 | "email": "email@example.com" 38 | }, 39 | "maintainers": [ 40 | { 41 | "name": "user", 42 | "email": "email@example.com" 43 | } 44 | ], 45 | "directories": {} 46 | } 47 | 48 | var version023a = { 49 | "name": "package", 50 | "version": "0.2.3-alpha", 51 | "description": "just an npm test, but with a **markdown** readme.", 52 | "_id": "package@0.2.3-alpha", 53 | "dist": { 54 | "tarball": "http://127.0.0.1:15986/package/-/package-0.2.3-alpha.tgz" 55 | }, 56 | "_npmUser": { 57 | "name": "user", 58 | "email": "email@example.com" 59 | }, 60 | "maintainers": [ 61 | { 62 | "name": "user", 63 | "email": "email@example.com" 64 | } 65 | ], 66 | "directories": {} 67 | } 68 | 69 | var version023 = { 70 | "name": "package", 71 | "version": "0.2.3", 72 | "description": "just an npm test, but with a **markdown** readme.", 73 | "_id": "package@0.2.3", 74 | "dist": { 75 | "tarball": "http://127.0.0.1:15986/package/-/package-0.2.3.tgz" 76 | }, 77 | "_npmUser": { 78 | "name": "other", 79 | "email": "other@example.com" 80 | }, 81 | "maintainers": [ 82 | { 83 | "name": "user", 84 | "email": "email@example.com" 85 | }, 86 | { 87 | "name": "other", 88 | "email": "other@example.com" 89 | } 90 | ], 91 | "directories": {} 92 | } 93 | 94 | var time = {} 95 | var npmVersion = null 96 | var env = { PATH: process.env.PATH, npm_config_loglevel: "error" } 97 | 98 | test('get npm version', function(t) { 99 | var c = common.npm([ '--version' ], { env: env }) 100 | var v = '' 101 | c.stdout.on('data', function(d) { 102 | v += d 103 | }) 104 | c.on('close', function(code) { 105 | npmVersion = v.trim() 106 | version002._npmVersion = npmVersion 107 | version023a._npmVersion = npmVersion 108 | version023._npmVersion = npmVersion 109 | t.notOk(code) 110 | t.end() 111 | }) 112 | }) 113 | 114 | 115 | test('first publish', function(t) { 116 | var c = common.npm([ 117 | '--registry=' + reg, 118 | '--userconf=' + conf, 119 | 'publish' 120 | ], { cwd: pkg002, env: env }) 121 | c.stderr.pipe(process.stderr) 122 | var out = '' 123 | c.stdout.setEncoding('utf8') 124 | c.stdout.on('data', function(d) { 125 | out += d 126 | }) 127 | c.on('close', function(code) { 128 | t.notOk(code) 129 | t.equal(out, "+ package@0.0.2\n") 130 | t.end() 131 | }) 132 | }) 133 | 134 | var urls = [ 135 | 'package/-/package-0.0.2.tgz', 136 | 'npm/public/registry/package/_attachments/package-0.0.2.tgz', 137 | 'npm/public/registry/p/package/_attachments/package-0.0.2.tgz' 138 | ] 139 | 140 | urls.forEach(function(u) { 141 | test('attachment: ' + u, function(t) { 142 | r = url.parse(reg + u) 143 | r.method = 'HEAD' 144 | r.headers = {connection: 'close'} 145 | http.request(r, function(res) { 146 | t.equal(res.statusCode, 200) 147 | t.end() 148 | }).end() 149 | }) 150 | }) 151 | 152 | test('GET after publish', function(t) { 153 | expect = { 154 | "_id": "package", 155 | "name": "package", 156 | "description": "just an npm test", 157 | "dist-tags": { 158 | "latest": "0.0.2" 159 | }, 160 | "versions": { 161 | "0.0.2": version002 162 | }, 163 | "readme": "just an npm test\n", 164 | "maintainers": maintainers, 165 | "time": time, 166 | "readmeFilename": "README", 167 | "_attachments": { 168 | "package-0.0.2.tgz": { 169 | "content_type": "application/octet-stream", 170 | "revpos": 1, 171 | "stub": true 172 | } 173 | } 174 | } 175 | 176 | http.get(reg + 'package', function(res) { 177 | t.equal(res.statusCode, 200) 178 | var c = '' 179 | res.setEncoding('utf8') 180 | res.on('data', function(d) { 181 | c += d 182 | }) 183 | res.on('end', function() { 184 | c = JSON.parse(c) 185 | // rev and time will be different 186 | t.like(c._rev, /1-[0-9a-f]+$/) 187 | expect._rev = c._rev 188 | expect.time['0.0.2'] = c.time['0.0.2'] 189 | t.has(c, expect) 190 | t.end() 191 | }) 192 | }) 193 | }) 194 | 195 | test('GET with x-forwarded-for', function (t) { 196 | var wanted = 'http://fooblz/registry/_design/scratch/_rewrite/package/-/package-0.0.2.tgz' 197 | 198 | var g = url.parse('http://localhost:15986/registry/_design/scratch/_rewrite/package') 199 | g.headers = { 200 | 'x-forwarded-host': 'fooblz' 201 | } 202 | 203 | http.get(g, function(res) { 204 | t.equal(res.statusCode, 200) 205 | var c = '' 206 | res.setEncoding('utf8') 207 | res.on('data', function(d) { 208 | c += d 209 | }) 210 | res.on('end', function() { 211 | c = JSON.parse(c) 212 | var actual = c.versions[c['dist-tags'].latest].dist.tarball 213 | t.equal(actual, wanted) 214 | t.end() 215 | }) 216 | }) 217 | }) 218 | 219 | test('fail to clobber', function(t) { 220 | var c = common.npm([ 221 | '--registry=' + reg, 222 | '--userconf=' + conf, 223 | 'publish' 224 | ], { cwd: pkg002, env: env }) 225 | c.on('close', function(code) { 226 | t.ok(code) 227 | t.end() 228 | }) 229 | }) 230 | 231 | test('fail to publish as other user', function(t) { 232 | var c = common.npm([ 233 | '--registry=' + reg, 234 | '--userconf=' + conf2, 235 | 'publish' 236 | ], { cwd: pkg023a, env: env }) 237 | c.on('close', function(code) { 238 | t.ok(code) 239 | t.end() 240 | }) 241 | }) 242 | 243 | test('publish update as non-latest', function(t) { 244 | var c = common.npm([ 245 | '--registry=' + reg, 246 | '--userconf=' + conf, 247 | '--tag=alpha', 248 | 'publish' 249 | ], { cwd: pkg023a, env: env }) 250 | c.stderr.pipe(process.stderr) 251 | var out = '' 252 | c.stdout.setEncoding('utf8') 253 | c.stdout.on('data', function(d) { 254 | out += d 255 | }) 256 | c.on('close', function(code) { 257 | t.notOk(code) 258 | t.equal(out, "+ package@0.2.3-alpha\n") 259 | t.end() 260 | }) 261 | }) 262 | 263 | test('GET after update', function(t) { 264 | expect = { 265 | "_id": "package", 266 | "name": "package", 267 | "description": "just an npm test", 268 | "dist-tags": { 269 | "latest": "0.0.2", 270 | "alpha": "0.2.3-alpha" 271 | }, 272 | "versions": { 273 | "0.0.2": version002, 274 | "0.2.3-alpha": version023a 275 | }, 276 | "readme": "just an npm test\n", 277 | "maintainers": maintainers, 278 | "time": time, 279 | "readmeFilename": "README", 280 | "_attachments": { 281 | "package-0.0.2.tgz": { 282 | "content_type": "application/octet-stream", 283 | "revpos": 1, 284 | "stub": true 285 | }, 286 | "package-0.2.3-alpha.tgz": { 287 | "content_type": "application/octet-stream", 288 | "revpos": 2, 289 | "stub": true 290 | } 291 | } 292 | } 293 | 294 | http.get(reg + 'package', function(res) { 295 | t.equal(res.statusCode, 200) 296 | var c = '' 297 | res.setEncoding('utf8') 298 | res.on('data', function(d) { 299 | c += d 300 | }) 301 | res.on('end', function() { 302 | c = JSON.parse(c) 303 | // rev and time will be different 304 | t.like(c._rev, /2-[0-9a-f]+$/) 305 | expect._rev = c._rev 306 | time['0.2.3-alpha'] = c.time['0.2.3-alpha'] 307 | t.has(c, expect) 308 | t.end() 309 | }) 310 | }) 311 | }) 312 | 313 | test('add second publisher', function(t) { 314 | var c = common.npm([ 315 | '--registry=' + reg, 316 | '--userconf=' + conf, 317 | 'owner', 318 | 'add', 319 | 'other', 320 | 'package' 321 | ], { env: env }) 322 | c.stderr.pipe(process.stderr) 323 | c.on('close', function(code) { 324 | t.notOk(code) 325 | t.end() 326 | }) 327 | }) 328 | 329 | test('get after owner add', function(t) { 330 | http.get(reg + 'package', function(res) { 331 | t.equal(res.statusCode, 200) 332 | var c = '' 333 | res.setEncoding('utf8') 334 | res.on('data', function(d) { 335 | c += d 336 | }) 337 | res.on('end', function() { 338 | c = JSON.parse(c) 339 | // rev and time will be different 340 | t.like(c._rev, /3-[0-9a-f]+$/) 341 | expect._rev = c._rev 342 | expect.maintainers.push({ 343 | name: 'other', 344 | email: 'other@example.com' 345 | }) 346 | expect.time = time 347 | t.has(c, expect) 348 | t.end() 349 | }) 350 | }) 351 | }) 352 | 353 | test('other owner publish', function(t) { 354 | var c = common.npm([ 355 | '--registry=' + reg, 356 | '--userconf=' + conf2, 357 | 'publish' 358 | ], { cwd: pkg023, env: env }) 359 | c.stderr.pipe(process.stderr) 360 | var out = '' 361 | c.stdout.setEncoding('utf8') 362 | c.stdout.on('data', function(d) { 363 | out += d 364 | }) 365 | c.on('close', function(code) { 366 | t.notOk(code) 367 | t.equal(out, "+ package@0.2.3\n") 368 | t.end() 369 | }) 370 | }) 371 | 372 | test('get after other publish (and x-forwarded-proto)', function(t) { 373 | var r = url.parse(reg + 'package') 374 | r.headers = { 'x-forwarded-proto': 'foobar' } 375 | 376 | http.get(r, function(res) { 377 | t.equal(res.statusCode, 200) 378 | var c = '' 379 | res.setEncoding('utf8') 380 | res.on('data', function(d) { 381 | c += d 382 | }) 383 | res.on('end', function() { 384 | c = JSON.parse(c) 385 | // rev and time will be different 386 | t.like(c._rev, /4-[0-9a-f]+$/) 387 | expect._rev = c._rev 388 | expect.description = "just an npm test, but with a **markdown** readme." 389 | expect.readmeFilename = "README.md" 390 | expect.readme = "just an npm test, but with a **markdown** readme.\n" 391 | expect['dist-tags'] = { 392 | "latest": "0.2.3", 393 | "alpha": "0.2.3-alpha" 394 | } 395 | expect.versions['0.2.3'] = version023 396 | expect._attachments["package-0.2.3.tgz"] = { 397 | "content_type" : "application/octet-stream", 398 | "revpos" : 4, 399 | "stub" : true 400 | } 401 | expect.time['0.2.3'] = c.time['0.2.3'] 402 | // should get x-forwarded-proto back 403 | Object.keys(expect.versions).forEach(function(v) { 404 | var tgz = expect.versions[v].dist.tarball 405 | expect.versions[v].dist.tarball = tgz.replace(/^https?/, 'foobar') 406 | }) 407 | t.has(c, expect) 408 | t.end() 409 | }) 410 | }) 411 | }) 412 | 413 | test('install the thing we published', function(t) { 414 | rimraf.sync(path.resolve(inst, 'node_modules')) 415 | rimraf.sync(path.resolve(inst, 'package-lock.json')) 416 | var c = common.npm([ 417 | '--registry=' + reg, 418 | 'install' 419 | ], { env: env, cwd: inst }) 420 | c.stdout.pipe(process.stderr) 421 | c.stderr.pipe(process.stderr) 422 | c.on('close', function(code) { 423 | t.is(code, 0) 424 | c = common.npm(['--registry=' + reg, 'ls'], {env: env, cwd: inst}) 425 | c.stderr.pipe(process.stderr) 426 | var out = '' 427 | c.stdout.setEncoding('utf8') 428 | c.stdout.on('data', function(d) { 429 | out += d 430 | }) 431 | c.on('close', function(code) { 432 | t.notOk(code) 433 | t.similar(out, /package@0.2.3/) 434 | rimraf.sync(path.resolve(inst, 'node_modules')) 435 | rimraf.sync(path.resolve(inst, 'package-lock.json')) 436 | t.end() 437 | }) 438 | }) 439 | }) 440 | 441 | test('remove all the tarballs', function(t) { 442 | http.get(db + 'package', function(res) { 443 | t.equal(res.statusCode, 200) 444 | var c = '' 445 | res.setEncoding('utf8') 446 | res.on('data', function (d) { 447 | c += d 448 | }) 449 | res.on('end', function() { 450 | var doc = JSON.parse(c) 451 | doc._attachments = {} 452 | var body = new Buffer(JSON.stringify(doc), 'utf8') 453 | var p = url.parse(db + 'package') 454 | p.auth = 'admin:admin' 455 | p.headers = { 456 | 'content-type': 'application/json', 457 | 'content-length': body.length, 458 | connection: 'close' 459 | } 460 | p.method = 'PUT' 461 | http.request(p, function(res) { 462 | if (res.statusCode !== 201) 463 | res.pipe(process.stderr) 464 | else 465 | res.resume() 466 | t.equal(res.statusCode, 201) 467 | res.on('end', t.end.bind(t)) 468 | }).end(body) 469 | }) 470 | }) 471 | }) 472 | 473 | test('try to attach a new tarball (and fail)', function(t) { 474 | http.get(db + 'package', function(res) { 475 | t.equal(res.statusCode, 200) 476 | var c = '' 477 | res.setEncoding('utf8') 478 | res.on('data', function (d) { 479 | c += d 480 | }) 481 | res.on('end', function() { 482 | var doc = JSON.parse(c) 483 | var rev = doc._rev 484 | var p = url.parse(db + 'package/package-0.2.3.tgz?rev=' + rev) 485 | body = new Buffer("this is the attachment data") 486 | p.auth = 'other:pass@:!%\'' 487 | p.headers = { 488 | 'content-type': 'application/octet-stream', 489 | 'content-length': body.length, 490 | connection: 'close' 491 | } 492 | p.method = 'PUT' 493 | http.request(p, function(res) { 494 | if (res.statusCode !== 403) 495 | res.pipe(process.stderr) 496 | else 497 | res.resume() 498 | res.on('end', t.end.bind(t)) 499 | t.equal(res.statusCode, 403) 500 | }).end(body) 501 | }) 502 | }) 503 | }) 504 | 505 | test('admin user can publish scoped package', function(t) { 506 | var packageJson = JSON.parse(fs.readFileSync(path.resolve(__dirname, 'fixtures', 'scoped-package.json'), 'utf-8')) 507 | var url = 'http://admin:admin@localhost:15986/registry/_design/scratch/_update/package/' + packageJson.name 508 | 509 | request.put({ 510 | url: url, 511 | body: packageJson, 512 | json: true 513 | }, function(err, resp, body) { 514 | t.equal(body.ok, "created new entry") 515 | t.end() 516 | }) 517 | }) 518 | -------------------------------------------------------------------------------- /test/02b-dist-tags.js: -------------------------------------------------------------------------------- 1 | var common = require('./common.js') 2 | var path = require('path') 3 | var url = require('url') 4 | var test = require('tap').test 5 | var reg = 'http://127.0.0.1:15986/' 6 | var request = require('request') 7 | var db = 'http://localhost:15986/registry/' 8 | var conf = path.resolve(__dirname, 'fixtures', 'npmrc') 9 | var dturl = url.resolve(reg, '/-/package/package/dist-tags') 10 | var auth = 'Basic ' + new Buffer('user:pass@:!%\'').toString('base64') 11 | var origdt = { 12 | latest : "0.2.3", 13 | alpha : "0.2.3-alpha" 14 | } 15 | 16 | test('GET dist-tags', function (t) { 17 | request({ url: dturl, json: true }, function (er, res, body) { 18 | t.same(body, origdt) 19 | t.end() 20 | }) 21 | }) 22 | 23 | test('PUT new dist tag set', function (t) { 24 | var newdt = { 25 | "latest" : "0.2.3", 26 | "alpha" : "0.2.3-alpha", 27 | "foo": "0.0.2" 28 | } 29 | 30 | t.plan(3) 31 | 32 | t.test('fail as anon', function (t) { 33 | request.put({ 34 | url: dturl, 35 | body: newdt, 36 | json: true 37 | }, function (er, res, body) { 38 | t.equal(res.statusCode, 403) 39 | t.same(body, { 40 | error: 'forbidden', 41 | reason: 'Please log in before writing to the db' 42 | }) 43 | t.end() 44 | }) 45 | }) 46 | 47 | t.test('succeed with auth', function (t) { 48 | request.put({ 49 | url: dturl, 50 | body: newdt, 51 | headers: { 52 | authorization: auth 53 | }, 54 | json: true 55 | }, function (er, res, body) { 56 | t.equal(res.statusCode, 201) 57 | t.same(body, { ok: 'dist-tags updated' }) 58 | t.end() 59 | }) 60 | }) 61 | 62 | t.test('GET after success', function (t) { 63 | request({url: dturl, json: true }, function (er, res, body) { 64 | t.same(body, newdt) 65 | t.end() 66 | }) 67 | }) 68 | }) 69 | 70 | test('POST new dist tag set', function (t) { 71 | var newdt = { 72 | latest : "0.2.3-alpha", 73 | alpha : "0.2.3-alpha", 74 | foo: "0.0.2", 75 | blerb: "0.2.3" 76 | } 77 | 78 | var post = { 79 | latest: "0.2.3-alpha", 80 | blerb: "0.2.3" 81 | } 82 | 83 | request.post({ 84 | url: dturl, 85 | body: post, 86 | headers: { 87 | authorization: auth 88 | }, 89 | json: true 90 | }, function (er, res, body) { 91 | t.equal(res.statusCode, 201) 92 | t.same(body, { ok: 'dist-tags updated' }) 93 | request({ url: dturl, json: true }, function (er, res, body) { 94 | t.same(body, newdt) 95 | t.end() 96 | }) 97 | }) 98 | }) 99 | 100 | test('PUT one new tag', function (t) { 101 | var newdt = { 102 | latest : "0.2.3-alpha", 103 | alpha : "0.2.3-alpha", 104 | foo: "0.0.2", 105 | blerb: "0.0.2" 106 | } 107 | 108 | request.put({ 109 | url: dturl + '/blerb', 110 | body: JSON.stringify(newdt.blerb), 111 | headers: { 112 | authorization: auth 113 | } 114 | }, function (er, res, body) { 115 | body = JSON.parse(body) 116 | t.equal(res.statusCode, 201) 117 | t.same(body, { ok: 'dist-tags updated' }) 118 | request({ url: dturl, json: true }, function (er, res, body) { 119 | t.same(body, newdt) 120 | t.end() 121 | }) 122 | }) 123 | }) 124 | 125 | test('POST one new tag', function (t) { 126 | var newdt = { 127 | latest : "0.2.3-alpha", 128 | alpha : "0.2.3-alpha", 129 | foo: "0.0.2", 130 | blerb: "0.2.3" 131 | } 132 | 133 | request.post({ 134 | url: dturl + '/blerb', 135 | body: JSON.stringify(newdt.blerb), 136 | headers: { 137 | authorization: auth 138 | } 139 | }, function (er, res, body) { 140 | body = JSON.parse(body) 141 | t.equal(res.statusCode, 201) 142 | t.same(body, { ok: 'dist-tags updated' }) 143 | request({ url: dturl, json: true }, function (er, res, body) { 144 | t.same(body, newdt) 145 | t.end() 146 | }) 147 | }) 148 | }) 149 | 150 | test('DELETE blerb tag', function (t) { 151 | var newdt = { 152 | latest : "0.2.3-alpha", 153 | alpha : "0.2.3-alpha", 154 | foo: "0.0.2" 155 | } 156 | 157 | request.del({ 158 | url: dturl + '/blerb', 159 | headers: { 160 | authorization: auth 161 | }, 162 | json: true 163 | }, function (er, res, body) { 164 | t.equal(res.statusCode, 201) 165 | t.same(body, { ok: 'dist-tags updated' }) 166 | request({ url: dturl, json: true }, function (er, res, body) { 167 | t.same(body, newdt) 168 | t.end() 169 | }) 170 | }) 171 | }) 172 | 173 | test('Cannot DELETE latest tag', function (t) { 174 | var newdt = { 175 | latest : "0.2.3-alpha", 176 | alpha : "0.2.3-alpha", 177 | foo: "0.0.2" 178 | } 179 | 180 | request.del({ 181 | url: dturl + '/latest', 182 | headers: { 183 | authorization: auth 184 | }, 185 | json: true 186 | }, function (er, res, body) { 187 | t.equal(res.statusCode, 403) 188 | t.same(body, { error: 'forbidden', reason: 'must have a "latest" dist-tag' }) 189 | request({ url: dturl, json: true }, function (er, res, body) { 190 | t.same(body, newdt) 191 | t.end() 192 | }) 193 | }) 194 | }) 195 | 196 | test('cannot set tag to invalid version', function (t) { 197 | request.put({ 198 | url: dturl + '/latest', 199 | headers: { 200 | authorization: auth 201 | }, 202 | body: JSON.stringify('999.999.999') 203 | }, function (er, res, body) { 204 | body = JSON.parse(body) 205 | t.equal(res.statusCode, 403) 206 | t.same(body, { 207 | error: 'forbidden', 208 | reason: 'tag points to invalid version: latest' 209 | }) 210 | t.end() 211 | }) 212 | }) 213 | 214 | test('put tags back like we found them', function (t) { 215 | request.put({ 216 | url: dturl, 217 | headers: { 218 | authorization: auth 219 | }, 220 | json: true, 221 | body: origdt 222 | }, function (er, res, body) { 223 | t.equal(res.statusCode, 201) 224 | t.same(body, { ok: 'dist-tags updated' }) 225 | t.end() 226 | }) 227 | }) 228 | -------------------------------------------------------------------------------- /test/03-star.js: -------------------------------------------------------------------------------- 1 | var common = require('./common.js') 2 | var test = require('tap').test 3 | var reg = 'http://127.0.0.1:15986/' 4 | var path = require('path') 5 | var rimraf = require('rimraf') 6 | var conf = path.resolve(__dirname, 'fixtures', 'npmrc') 7 | var conf2 = path.resolve(__dirname, 'fixtures', 'npmrc2') 8 | var conf3 = path.resolve(__dirname, 'fixtures', 'npmrc3') 9 | var spawn = require('child_process').spawn 10 | var pkg = path.resolve(__dirname, 'fixtures/package') 11 | var http = require('http') 12 | var env = { PATH: process.env.PATH } 13 | var url = require('url') 14 | 15 | test('non-owner can star package', function(t) { 16 | var c = common.npm([ 17 | '--registry=' + reg, 18 | '--userconf=' + conf3, 19 | 'star', 'package' 20 | ], { env: env }) 21 | c.stderr.pipe(process.stderr) 22 | var out = '' 23 | c.stdout.setEncoding('utf8') 24 | c.stdout.on('data', function(d) { 25 | out += d 26 | }) 27 | c.on('close', function(code) { 28 | t.notOk(code) 29 | t.equal(out, "★ package\n") 30 | t.end() 31 | }) 32 | }) 33 | 34 | test('non-owner can unstar package', function(t) { 35 | var c = common.npm([ 36 | '--registry=' + reg, 37 | '--userconf=' + conf3, 38 | 'unstar', 'package' 39 | ], { env: env }) 40 | c.stderr.pipe(process.stderr) 41 | var out = '' 42 | c.stdout.setEncoding('utf8') 43 | c.stdout.on('data', function(d) { 44 | out += d 45 | }) 46 | c.on('close', function(code) { 47 | t.notOk(code) 48 | t.equal(out, "☆ package\n") 49 | t.end() 50 | }) 51 | }) 52 | 53 | test('simulate old-style multi-readme doc', function(t) { 54 | http.get('http://localhost:15986/registry/package', function(res) { 55 | var j = '' 56 | res.setEncoding('utf8') 57 | res.on('data', function(d) { j += d }) 58 | res.on('end', function() { 59 | var p = JSON.parse(j) 60 | p.versions['0.0.2'].readme = 'foo' 61 | p.versions['0.2.3-alpha'].readme = 'bar' 62 | var b = new Buffer(JSON.stringify(p)) 63 | var u = url.parse('http://admin:admin@localhost:15986/registry/package') 64 | u.method = 'PUT' 65 | u.headers = { 66 | 'content-type': 'application/json', 67 | 'content-length': b.length, 68 | 'connection': 'close' 69 | } 70 | http.request(u, function(res) { 71 | t.equal(res.statusCode, 201) 72 | t.end() 73 | res.resume() 74 | }).end(b) 75 | }) 76 | }) 77 | }) 78 | 79 | test('non-owner can star package', function(t) { 80 | var c = common.npm([ 81 | '--registry=' + reg, 82 | '--userconf=' + conf3, 83 | 'star', 'package' 84 | ], { env: env }) 85 | c.stderr.pipe(process.stderr) 86 | var out = '' 87 | c.stdout.setEncoding('utf8') 88 | c.stdout.on('data', function(d) { 89 | out += d 90 | }) 91 | c.on('close', function(code) { 92 | t.notOk(code) 93 | t.equal(out, "★ package\n") 94 | t.end() 95 | }) 96 | }) 97 | 98 | test('non-owner can unstar package', function(t) { 99 | var c = common.npm([ 100 | '--registry=' + reg, 101 | '--userconf=' + conf3, 102 | 'unstar', 'package' 103 | ], { env: env }) 104 | c.stderr.pipe(process.stderr) 105 | var out = '' 106 | c.stdout.setEncoding('utf8') 107 | c.stdout.on('data', function(d) { 108 | out += d 109 | }) 110 | c.on('close', function(code) { 111 | t.notOk(code) 112 | t.equal(out, "☆ package\n") 113 | t.end() 114 | }) 115 | }) 116 | 117 | -------------------------------------------------------------------------------- /test/04-deprecate.js: -------------------------------------------------------------------------------- 1 | var common = require('./common.js') 2 | var test = require('tap').test 3 | var reg = 'http://127.0.0.1:15986/' 4 | var path = require('path') 5 | var conf = path.resolve(__dirname, 'fixtures', 'npmrc') 6 | var pkg = path.resolve(__dirname, 'fixtures/package') 7 | var http = require('http') 8 | var env = { PATH: process.env.PATH } 9 | 10 | test('deprecate', function (t) { 11 | var c = common.npm([ 12 | '--color=always', 13 | '--registry=' + reg, 14 | '--userconf=' + conf, 15 | 'deprecate', 'package@0.0.2', 'message goes here' 16 | ], { env: env }) 17 | 18 | c.stderr.pipe(process.stderr) 19 | 20 | var v = '' 21 | c.stdout.setEncoding('utf8') 22 | c.stdout.on('data', function(d) { 23 | v += d 24 | }) 25 | c.on('close', function(code) { 26 | t.notOk(code) 27 | t.equal(v, '') 28 | t.end() 29 | }) 30 | }) 31 | 32 | test('get data after deprecation', function (t) { 33 | http.get('http://127.0.0.1:15986/package', function(res) { 34 | var c = '' 35 | res.setEncoding('utf8') 36 | res.on('data', function (d) { 37 | c += d 38 | }) 39 | res.on('end', function () { 40 | c = JSON.parse(c) 41 | t.equal(c.versions['0.0.2'].deprecated, 'message goes here') 42 | t.end() 43 | }) 44 | }) 45 | }) 46 | 47 | test('un-deprecate', function (t) { 48 | var c = common.npm([ 49 | '--color=always', 50 | '--registry=' + reg, 51 | '--userconf=' + conf, 52 | 'deprecate', 'package@0.0.2', '' 53 | ], { env: env }) 54 | 55 | c.stderr.pipe(process.stderr) 56 | 57 | var v = '' 58 | c.stdout.setEncoding('utf8') 59 | c.stdout.on('data', function(d) { 60 | v += d 61 | }) 62 | c.on('close', function(code) { 63 | t.notOk(code) 64 | t.equal(v, '') 65 | t.end() 66 | }) 67 | }) 68 | 69 | test('get data after un-deprecation', function (t) { 70 | http.get('http://127.0.0.1:15986/package', function(res) { 71 | var c = '' 72 | res.setEncoding('utf8') 73 | res.on('data', function (d) { 74 | c += d 75 | }) 76 | res.on('end', function () { 77 | c = JSON.parse(c) 78 | t.notOk(c.versions['0.0.2'].deprecated) 79 | t.end() 80 | }) 81 | }) 82 | }) 83 | -------------------------------------------------------------------------------- /test/04b-registry-views-expect.js: -------------------------------------------------------------------------------- 1 | var dateRe = /^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3}Z$/ 2 | var shaRe = /^[a-f0-9]{40}$/i 3 | var semverRe = /^v?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][a-zA-Z0-9-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][a-zA-Z0-9-]*))*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$/ 4 | var revRe = /^[0-9]+\-[0-9a-f]{32}$/i 5 | 6 | module.exports = 7 | { 8 | "norevs": { 9 | "rows": [] 10 | }, 11 | "mixedcase": { 12 | "total_rows": 0, 13 | "offset": 0, 14 | "rows": [] 15 | }, 16 | "conflicts": { 17 | "rows": [] 18 | }, 19 | "oddhost": { 20 | "rows": [ 21 | { 22 | "key": null, 23 | "value": 3 24 | } 25 | ] 26 | }, 27 | "updated": { 28 | "total_rows": 1, 29 | "offset": 0, 30 | "rows": [ 31 | { 32 | "id": "package", 33 | "key": dateRe, 34 | "value": 1 35 | } 36 | ] 37 | }, 38 | "listAll": { 39 | "total_rows": 1, 40 | "offset": 0, 41 | "rows": [ 42 | { 43 | "id": "package", 44 | "key": "package", 45 | "value": { 46 | "_id": "package", 47 | "_rev": revRe, 48 | "name": "package", 49 | "description": "just an npm test, but with a **markdown** readme.", 50 | "dist-tags": { 51 | "latest": "0.2.3", 52 | "alpha": "0.2.3-alpha" 53 | }, 54 | "versions": { 55 | "0.0.2": { 56 | "name": "package", 57 | "version": "0.0.2", 58 | "description": "just an npm test", 59 | "_id": "package@0.0.2", 60 | "scripts": {}, 61 | "_shasum": shaRe, 62 | "_from": ".", 63 | "_npmVersion": semverRe, 64 | "_npmUser": { 65 | "name": "user", 66 | "email": "email@example.com" 67 | }, 68 | "maintainers": [ 69 | { 70 | "name": "user", 71 | "email": "email@example.com" 72 | } 73 | ], 74 | "dist": { 75 | "shasum": shaRe, 76 | "tarball": "http://127.0.0.1:15986/package/-/package-0.0.2.tgz" 77 | } 78 | }, 79 | "0.2.3-alpha": { 80 | "name": "package", 81 | "version": "0.2.3-alpha", 82 | "description": "just an npm test, but with a **markdown** readme.", 83 | "_id": "package@0.2.3-alpha", 84 | "scripts": {}, 85 | "_shasum": shaRe, 86 | "_from": ".", 87 | "_npmVersion": semverRe, 88 | "_npmUser": { 89 | "name": "user", 90 | "email": "email@example.com" 91 | }, 92 | "maintainers": [ 93 | { 94 | "name": "user", 95 | "email": "email@example.com" 96 | } 97 | ], 98 | "dist": { 99 | "shasum": shaRe, 100 | "tarball": "http://127.0.0.1:15986/package/-/package-0.2.3-alpha.tgz" 101 | } 102 | }, 103 | "0.2.3": { 104 | "name": "package", 105 | "version": "0.2.3", 106 | "description": "just an npm test, but with a **markdown** readme.", 107 | "_id": "package@0.2.3", 108 | "scripts": {}, 109 | "_shasum": shaRe, 110 | "_from": ".", 111 | "_npmVersion": semverRe, 112 | "_npmUser": { 113 | "name": "other", 114 | "email": "other@example.com" 115 | }, 116 | "maintainers": [ 117 | { 118 | "name": "user", 119 | "email": "email@example.com" 120 | }, 121 | { 122 | "name": "other", 123 | "email": "other@example.com" 124 | } 125 | ], 126 | "dist": { 127 | "shasum": shaRe, 128 | "tarball": "http://127.0.0.1:15986/package/-/package-0.2.3.tgz" 129 | } 130 | } 131 | }, 132 | "readme": "just an npm test, but with a **markdown** readme.\n", 133 | "maintainers": [ 134 | { 135 | "name": "user", 136 | "email": "email@example.com" 137 | }, 138 | { 139 | "name": "other", 140 | "email": "other@example.com" 141 | } 142 | ], 143 | "time": { 144 | "modified": dateRe, 145 | "created": dateRe, 146 | "0.0.2": dateRe, 147 | "0.2.3-alpha": dateRe, 148 | "0.2.3": dateRe 149 | }, 150 | "readmeFilename": "README.md", 151 | "users": {} 152 | } 153 | } 154 | ] 155 | }, 156 | "allVersions": { 157 | "rows": [ 158 | { 159 | "key": null, 160 | "value": 3 161 | } 162 | ] 163 | }, 164 | "noShasum": { 165 | "rows": [] 166 | }, 167 | "byEngine": { 168 | "total_rows": 0, 169 | "offset": 0, 170 | "rows": [] 171 | }, 172 | "countVersions": { 173 | "rows": [ 174 | { 175 | "key": null, 176 | "value": 1 177 | } 178 | ] 179 | }, 180 | "byKeyword": { 181 | "rows": [] 182 | }, 183 | "byField": { 184 | "total_rows": 1, 185 | "offset": 0, 186 | "rows": [ 187 | { 188 | "id": "package", 189 | "key": "package", 190 | "value": { 191 | "name": "package", 192 | "version": "0.2.3", 193 | "description": "just an npm test, but with a **markdown** readme.", 194 | "_id": "package@0.2.3", 195 | "scripts": {}, 196 | "_shasum": shaRe, 197 | "_from": ".", 198 | "_npmVersion": semverRe, 199 | "_npmUser": { 200 | "name": "other", 201 | "email": "other@example.com" 202 | }, 203 | "maintainers": [ 204 | { 205 | "name": "user", 206 | "email": "email@example.com" 207 | }, 208 | { 209 | "name": "other", 210 | "email": "other@example.com" 211 | } 212 | ], 213 | "dist": { 214 | "shasum": shaRe, 215 | "tarball": "http://127.0.0.1:15986/package/-/package-0.2.3.tgz" 216 | } 217 | } 218 | } 219 | ] 220 | }, 221 | "needBuild": { 222 | "total_rows": 0, 223 | "offset": 0, 224 | "rows": [] 225 | }, 226 | "scripts": { 227 | "total_rows": 0, 228 | "offset": 0, 229 | "rows": [] 230 | }, 231 | "nodeWafInstall": { 232 | "total_rows": 0, 233 | "offset": 0, 234 | "rows": [] 235 | }, 236 | "orphanAttachments": { 237 | "total_rows": 0, 238 | "offset": 0, 239 | "rows": [] 240 | }, 241 | "noAttachment": { 242 | "rows": [ 243 | { 244 | "key": null, 245 | "value": 3 246 | } 247 | ] 248 | }, 249 | "starredByUser": { 250 | "total_rows": 0, 251 | "offset": 0, 252 | "rows": [] 253 | }, 254 | "starredByPackage": { 255 | "total_rows": 0, 256 | "offset": 0, 257 | "rows": [] 258 | }, 259 | "byUser": { 260 | "total_rows": 2, 261 | "offset": 0, 262 | "rows": [ 263 | { 264 | "id": "package", 265 | "key": "other", 266 | "value": "package" 267 | }, 268 | { 269 | "id": "package", 270 | "key": "user", 271 | "value": "package" 272 | } 273 | ] 274 | }, 275 | "browseAuthorsRecent": { 276 | "rows": [ 277 | { 278 | "key": null, 279 | "value": 1 280 | } 281 | ] 282 | }, 283 | "npmTop": { 284 | "rows": [ 285 | { 286 | "key": null, 287 | "value": 2 288 | } 289 | ] 290 | }, 291 | "browseAuthors": { 292 | "rows": [ 293 | { 294 | "key": null, 295 | "value": 2 296 | } 297 | ] 298 | }, 299 | "browseUpdated": { 300 | "rows": [ 301 | { 302 | "key": null, 303 | "value": 1 304 | } 305 | ] 306 | }, 307 | "browseAll": { 308 | "rows": [ 309 | { 310 | "key": null, 311 | "value": 1 312 | } 313 | ] 314 | }, 315 | "analytics": { 316 | "rows": [ 317 | { 318 | "key": null, 319 | "value": 5 320 | } 321 | ] 322 | }, 323 | "dependedUpon": { 324 | "rows": [] 325 | }, 326 | "dependentVersions": { 327 | "rows": [] 328 | }, 329 | "browseStarUser": { 330 | "rows": [] 331 | }, 332 | "browseStarPackage": { 333 | "rows": [] 334 | }, 335 | "fieldsInUse": { 336 | "rows": [ 337 | { 338 | "key": null, 339 | "value": 11 340 | } 341 | ] 342 | }, 343 | "norevs?group=true": { 344 | "rows": [] 345 | }, 346 | "conflicts?group=true": { 347 | "rows": [] 348 | }, 349 | "oddhost?group=true": { 350 | "rows": [ 351 | { 352 | "key": [ 353 | "package", 354 | "package@0.0.2", 355 | "http://127.0.0.1:15986/package/-/package-0.0.2.tgz" 356 | ], 357 | "value": 1 358 | }, 359 | { 360 | "key": [ 361 | "package", 362 | "package@0.2.3", 363 | "http://127.0.0.1:15986/package/-/package-0.2.3.tgz" 364 | ], 365 | "value": 1 366 | }, 367 | { 368 | "key": [ 369 | "package", 370 | "package@0.2.3-alpha", 371 | "http://127.0.0.1:15986/package/-/package-0.2.3-alpha.tgz" 372 | ], 373 | "value": 1 374 | } 375 | ] 376 | }, 377 | "allVersions?group=true": { 378 | "rows": [ 379 | { 380 | "key": [ 381 | "0.0.2", 382 | "package" 383 | ], 384 | "value": 1 385 | }, 386 | { 387 | "key": [ 388 | "0.2.3", 389 | "package" 390 | ], 391 | "value": 1 392 | }, 393 | { 394 | "key": [ 395 | "0.2.3-alpha", 396 | "package" 397 | ], 398 | "value": 1 399 | } 400 | ] 401 | }, 402 | "noShasum?group=true": { 403 | "rows": [] 404 | }, 405 | "countVersions?group=true": { 406 | "rows": [ 407 | { 408 | "key": [ 409 | 3, 410 | "package" 411 | ], 412 | "value": 1 413 | } 414 | ] 415 | }, 416 | "byKeyword?group=true": { 417 | "rows": [] 418 | }, 419 | "noAttachment?group=true": { 420 | "rows": [ 421 | { 422 | "key": [ 423 | "package", 424 | "0.0.2", 425 | "http://127.0.0.1:15986/package/-/package-0.0.2.tgz" 426 | ], 427 | "value": 1 428 | }, 429 | { 430 | "key": [ 431 | "package", 432 | "0.2.3", 433 | "http://127.0.0.1:15986/package/-/package-0.2.3.tgz" 434 | ], 435 | "value": 1 436 | }, 437 | { 438 | "key": [ 439 | "package", 440 | "0.2.3-alpha", 441 | "http://127.0.0.1:15986/package/-/package-0.2.3-alpha.tgz" 442 | ], 443 | "value": 1 444 | } 445 | ] 446 | }, 447 | "browseAuthorsRecent?group=true": { 448 | "rows": [ 449 | { 450 | "key": [ 451 | dateRe, 452 | "other", 453 | "package", 454 | "just an npm test, but with a **markdown** readme." 455 | ], 456 | "value": 1 457 | } 458 | ] 459 | }, 460 | "npmTop?group=true": { 461 | "rows": [ 462 | { 463 | "key": [ 464 | "other", 465 | "package", 466 | "just an npm test, but with a **markdown** readme.", 467 | dateRe 468 | ], 469 | "value": 1 470 | }, 471 | { 472 | "key": [ 473 | "user", 474 | "package", 475 | "just an npm test, but with a **markdown** readme.", 476 | dateRe 477 | ], 478 | "value": 1 479 | } 480 | ] 481 | }, 482 | "browseAuthors?group=true": { 483 | "rows": [ 484 | { 485 | "key": [ 486 | "other", 487 | "package", 488 | "just an npm test, but with a **markdown** readme.", 489 | dateRe 490 | ], 491 | "value": 1 492 | }, 493 | { 494 | "key": [ 495 | "user", 496 | "package", 497 | "just an npm test, but with a **markdown** readme.", 498 | dateRe 499 | ], 500 | "value": 1 501 | } 502 | ] 503 | }, 504 | "browseUpdated?group=true": { 505 | "rows": [ 506 | { 507 | "key": [ 508 | dateRe, 509 | "package", 510 | "just an npm test, but with a **markdown** readme." 511 | ], 512 | "value": 1 513 | } 514 | ] 515 | }, 516 | "browseAll?group=true": { 517 | "rows": [ 518 | { 519 | "key": [ 520 | "package", 521 | "just an npm test, but with a **markdown** readme." 522 | ], 523 | "value": 1 524 | } 525 | ] 526 | }, 527 | "analytics?group=true": { 528 | "rows": [ 529 | { 530 | "key": [ 531 | "created", 532 | 2014, 533 | 8, 534 | 28, 535 | "package" 536 | ], 537 | "value": 1 538 | }, 539 | { 540 | "key": [ 541 | "latest", 542 | 2014, 543 | 8, 544 | 28, 545 | "package" 546 | ], 547 | "value": 1 548 | }, 549 | { 550 | "key": [ 551 | "update", 552 | 2014, 553 | 8, 554 | 28, 555 | "package" 556 | ], 557 | "value": 3 558 | } 559 | ] 560 | }, 561 | "dependedUpon?group=true": { 562 | "rows": [] 563 | }, 564 | "dependentVersions?group=true": { 565 | "rows": [] 566 | }, 567 | "browseStarUser?group=true": { 568 | "rows": [] 569 | }, 570 | "browseStarPackage?group=true": { 571 | "rows": [] 572 | }, 573 | "fieldsInUse?group=true": { 574 | "rows": [ 575 | { 576 | "key": "_from", 577 | "value": 1 578 | }, 579 | { 580 | "key": "_id", 581 | "value": 1 582 | }, 583 | { 584 | "key": "_npmUser", 585 | "value": 1 586 | }, 587 | { 588 | "key": "_npmVersion", 589 | "value": 1 590 | }, 591 | { 592 | "key": "_shasum", 593 | "value": 1 594 | }, 595 | { 596 | "key": "description", 597 | "value": 1 598 | }, 599 | { 600 | "key": "dist", 601 | "value": 1 602 | }, 603 | { 604 | "key": "maintainers", 605 | "value": 1 606 | }, 607 | { 608 | "key": "name", 609 | "value": 1 610 | }, 611 | { 612 | "key": "scripts", 613 | "value": 1 614 | }, 615 | { 616 | "key": "version", 617 | "value": 1 618 | } 619 | ] 620 | } 621 | } 622 | 623 | if (module === require.main) { 624 | console.log('1..1') 625 | console.log('ok - just setting things up for other tests') 626 | } 627 | -------------------------------------------------------------------------------- /test/04b-registry-views.js: -------------------------------------------------------------------------------- 1 | var expect = require('./04b-registry-views-expect.js') 2 | 3 | var test = require('tap').test 4 | var u = 'http://admin:admin@localhost:15986/registry/_design/scratch/_view/' 5 | var http = require('http') 6 | var parse = require('parse-json-response') 7 | 8 | Object.keys(expect).forEach(function(view) { 9 | test(view, function(t) { 10 | http.get(u + view, parse(function(er, data, res) { 11 | if (er) 12 | throw er 13 | expect[view] = data 14 | t.similar(data, expect[view]) 15 | t.end() 16 | })) 17 | }) 18 | }) 19 | -------------------------------------------------------------------------------- /test/04c-lists.js: -------------------------------------------------------------------------------- 1 | var test = require('tap').test 2 | var u = 'http://admin:admin@localhost:15986/registry/_design/scratch/_list/' 3 | var http = require('http') 4 | var parse = require('parse-json-response') 5 | 6 | test('lists global packages', function(t) { 7 | http.get(u + 'index/listAll' , parse(function(er, data, res) { 8 | t.ok(data.package, 'global package listed') 9 | t.end() 10 | })) 11 | }) 12 | 13 | test('hides scoped packages', function(t) { 14 | http.get(u + 'index/listAll' , parse(function(er, data, res) { 15 | t.notOk(data['@npm/package'], 'scoped package listed') 16 | t.end() 17 | })) 18 | }) 19 | -------------------------------------------------------------------------------- /test/05-unpublish.js: -------------------------------------------------------------------------------- 1 | // npm --userconfig=test/fixtures/npmrc unpublish -f package 2 | // --registry=http://127.0.0.1:15986; ( echo "now unpublish"; cd 3 | // test/fixtures/package/0.2.4/; npm publish 4 | // --registry=http://127.0.0.1:15986/ 5 | // --userconfig=$HOME/dev/npm/npmjs.org/test/fixtures/npmrc3) 6 | 7 | var common = require('./common.js') 8 | var test = require('tap').test 9 | var reg = 'http://127.0.0.1:15986/' 10 | var path = require('path') 11 | var conf = path.resolve(__dirname, 'fixtures', 'npmrc') 12 | var conf3 = path.resolve(__dirname, 'fixtures', 'npmrc3') 13 | var pkg = path.resolve(__dirname, 'fixtures/package') 14 | var pkg002 = path.resolve(pkg, '0.0.2') 15 | var pkg024 = path.resolve(pkg, '0.2.4') 16 | var http = require('http') 17 | var env = { PATH: process.env.PATH, npm_config_loglevel: "error" } 18 | 19 | test('unpublish', function(t) { 20 | var c = common.npm([ 21 | '--registry=' + reg, 22 | '--userconf=' + conf, 23 | 'unpublish', '-f', 'package' 24 | ], { env: env }) 25 | var v = '' 26 | c.stdout.setEncoding('utf8') 27 | c.stdout.on('data', function(d) { 28 | v += d 29 | }) 30 | c.on('close', function(code) { 31 | t.notOk(code) 32 | t.match(v, /- ?package\n/) 33 | t.end() 34 | }) 35 | }) 36 | 37 | test('GET after unpublish', function(t) { 38 | var expect = { 39 | "_id": "package", 40 | "name": "package", 41 | "time": { 42 | "modified": "xx", 43 | "created": "xx", 44 | "0.0.2": "xx", 45 | "0.2.3-alpha": "xx", 46 | "0.2.3": "xx", 47 | "unpublished": { 48 | "name": "user", 49 | "time": "xx" 50 | } 51 | } 52 | } 53 | 54 | http.get(reg + 'package', function(res) { 55 | t.equal(res.statusCode, 404) 56 | var c = '' 57 | res.setEncoding('utf8') 58 | res.on('data', function(d) { 59 | c += d 60 | }) 61 | res.on('end', function() { 62 | c = JSON.parse(c) 63 | // rev and time will be different 64 | t.like(c._rev, /[0-9]+-[0-9a-f]+$/) 65 | expect._rev = c._rev 66 | t.equal(c.name, c._id) 67 | t.same(Object.keys(c).sort().join(","), 68 | "_attachments,_id,_rev,name,time") 69 | t.same(Object.keys(c.time).sort().join(","), 70 | '0.0.2,0.2.3,0.2.3-alpha,created,modified,unpublished') 71 | t.equal(c.time.unpublished.name, "user") 72 | t.end() 73 | }) 74 | }) 75 | }) 76 | 77 | test('fail to clobber', function(t) { 78 | var c = common.npm([ 79 | '--registry=' + reg, 80 | '--userconf=' + conf3, 81 | '--force', 82 | 'publish' 83 | ], { cwd: pkg002, env: env }) 84 | c.on('close', function(code) { 85 | t.ok(code) 86 | t.end() 87 | }) 88 | }) 89 | 90 | test('publish new version as new user', function(t) { 91 | var c = common.npm([ 92 | '--registry=' + reg, 93 | '--userconf=' + conf3, 94 | '--force', 95 | 'publish' 96 | ], { cwd: pkg024, env: env }) 97 | var v = '' 98 | c.stderr.pipe(process.stderr) 99 | c.stdout.setEncoding('utf8') 100 | c.stdout.on('data', function(d) { 101 | v += d 102 | }) 103 | c.on('close', function(code) { 104 | t.notOk(code) 105 | t.equal(v, '+ package@0.2.4\n') 106 | t.end() 107 | }) 108 | }) 109 | 110 | test('now unpublish the new version', function(t) { 111 | var c = common.npm([ 112 | '--registry=' + reg, 113 | '--userconf=' + conf3, 114 | 'unpublish', 'package@0.2.4' 115 | ], { env: env }) 116 | var v = '' 117 | c.stdout.setEncoding('utf8') 118 | c.stdout.on('data', function(d) { 119 | v += d 120 | }) 121 | c.on('close', function(code) { 122 | t.notOk(code) 123 | t.match(v, /- ?package@0.2.4\n/) 124 | t.end() 125 | }) 126 | }) 127 | 128 | test('GET after unpublish', function(t) { 129 | var expect = { 130 | "_id": "package", 131 | "name": "package", 132 | "time": { 133 | "modified": "xx", 134 | "created": "xx", 135 | "0.0.2": "xx", 136 | "0.2.3-alpha": "xx", 137 | "0.2.3": "xx", 138 | "0.2.4": "xx", 139 | "unpublished": { 140 | "name": "third", 141 | "time": "xx" 142 | } 143 | } 144 | } 145 | 146 | http.get(reg + 'package', function(res) { 147 | t.equal(res.statusCode, 404) 148 | var c = '' 149 | res.setEncoding('utf8') 150 | res.on('data', function(d) { 151 | c += d 152 | }) 153 | res.on('end', function() { 154 | c = JSON.parse(c) 155 | // rev and time will be different 156 | t.like(c._rev, /[0-9]+-[0-9a-f]+$/) 157 | expect._rev = c._rev 158 | t.equal(c.name, c._id) 159 | t.same(Object.keys(c).sort().join(","), 160 | "_attachments,_id,_rev,name,time") 161 | t.same(Object.keys(c.time).sort().join(","), 162 | '0.0.2,0.2.3,0.2.3-alpha,0.2.4,created,modified,unpublished') 163 | t.equal(c.time.unpublished.name, "third") 164 | t.equal(c.time.unpublished.description, "just an npm test, but with a **markdown** readme.") 165 | t.same(c.time.unpublished.maintainers, [{"name":"third","email":"3@example.com"}]) 166 | t.same(c.time.unpublished.versions, ["0.2.4"]) 167 | t.same(c.time.unpublished.tags, { latest: "0.2.4" }) 168 | t.end() 169 | }) 170 | }) 171 | }) 172 | 173 | -------------------------------------------------------------------------------- /test/06-not-implemented.js: -------------------------------------------------------------------------------- 1 | var common = require('./common.js') 2 | var path = require('path') 3 | var url = require('url') 4 | var test = require('tap').test 5 | var reg = 'http://127.0.0.1:15986/' 6 | var request = require('request') 7 | var accessurl = url.resolve(reg, '/-/package/package/access') 8 | 9 | test('not implemented endpoints should 501', function (t) { 10 | var methods = ['get', 'put', 'post', 'del'] 11 | var urls = [ '/-/package/package/access' ] 12 | 13 | t.plan(methods.length * urls.length) 14 | 15 | urls.forEach(function (u) { 16 | methods.forEach(function (method) { 17 | t.test(method + ' ' + u, function (t) { 18 | request[method]({ 19 | url: url.resolve(reg, u), 20 | json: true 21 | }, function (er, res, body) { 22 | t.equal(res.statusCode, 501) 23 | t.same(body, { 24 | error: "Not Implemented", 25 | reason: "This server does not support this endpoint" 26 | }) 27 | t.end() 28 | }) 29 | }) 30 | }) 31 | }) 32 | }) 33 | -------------------------------------------------------------------------------- /test/common.js: -------------------------------------------------------------------------------- 1 | var which = require('which') 2 | 3 | exports.npmPath = process.env.npm || which.sync('npm') 4 | const cache = require('path').resolve(__dirname, 'fixtures', 'test-cache') 5 | require('mkdirp').sync(cache) 6 | 7 | var spawn = require('child_process').spawn 8 | exports.npm = function (args, opts) { 9 | var cmd = exports.npmPath 10 | if (exports.npmPath.match(/\.js$/)) { 11 | args = [exports.npmPath, `--cache=${cache}`].concat(args) 12 | cmd = process.execPath 13 | } 14 | if (!opts) opts = {} 15 | if (!opts.env) opts.env = process.env 16 | opts.env.LC_CTYPE = 'UTF-8' 17 | return spawn(cmd, args, opts) 18 | } 19 | 20 | if (module === require.main) { 21 | console.log('1..1') 22 | console.log('ok - nothing to see here') 23 | } 24 | -------------------------------------------------------------------------------- /test/fixtures/couch.ini: -------------------------------------------------------------------------------- 1 | [couchdb] 2 | database_dir = test/fixtures 3 | view_index_dir = test/fixtures 4 | uuid = 3ec49bc6c314484cb21d684dc3fc778f 5 | delayed_commits = false 6 | uri_file = test/fixtures/couch.uri 7 | 8 | [httpd] 9 | port = 15986 10 | bind_address = 127.0.0.1 11 | secure_rewrites = false 12 | allow_jsonp = true 13 | config_whitelist = [{uuids,algorithm},{vhosts,"*"},{admins,"*"},{log,level},{httpd,allow_jsonp},{httpd,secure_rewrites},{httpd,mobile_futon},{httpd,sammy_futon},{httpd,cors},{httpd,x_forwarded_host},{httpd,'WWW-Authenticate'},{cors,"*"},{compactions,"*"},{replicator,db},{attachments,compression_level},{attachments,compressible_types},{couch_httpd_auth,authentication_db},{couch_httpd_auth,allow_persistent_cookies},{couch_httpd_auth,authentication_redirect},{couch_httpd_auth,require_valid_user},{couch_httpd_auth,timeout},{couch_httpd_auth,secret},{couchdb,os_process_timeout},{query_server_config,reduce_limit},{couch_httpd_oauth,"*"},{oauth_token_users,"*"},{oauth_token_secrets,"*"},{oauth_consumer_secrets,"*"},{browserid,enabled},{browserid,hash_secret},{fb,"*"}] 14 | 15 | [log] 16 | file = test/fixtures/couch.log 17 | 18 | [couch_httpd_auth] 19 | secret = cafebad0000deadbeef0000019790701 20 | timeout = 36000 21 | allow_persistent_cookies = true 22 | public_fields = appdotnet, avatar, avatarMedium, avatarLarge, date, email, fields, freenode, fullname, github, homepage, name, roles, twitter, type, _id, _rev 23 | users_db_public = true 24 | 25 | [admins] 26 | admin = -pbkdf2-3600026e937b60b9cdb6f5d41d279e248a793e30,2e1f502750e0fa201a9056e38929bfa6,10 27 | 28 | [vhosts] 29 | 127.0.0.1:15986 = /registry/_design/scratch/_rewrite/ 30 | -------------------------------------------------------------------------------- /test/fixtures/hoodie-new.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hoodie-plugin-global-share", 3 | "version": "1.0.10", 4 | "main": "worker.js", 5 | "description": "Hoodie.js Global Share Plugin", 6 | "scripts": { 7 | "test": "grunt --verbose" 8 | }, 9 | "author": "", 10 | "dependencies": { 11 | "async": "0.2.10", 12 | "lodash": "2.4.1", 13 | "hoodie-server": "0.9.19", 14 | "hoodie": "0.6.5" 15 | }, 16 | "devDependencies": { 17 | "grunt": "0.4.1", 18 | "expect.js": "0.2.0", 19 | "grunt-simple-mocha": "0.4.0", 20 | "grunt-contrib-jshint": "0.6.2", 21 | "grunt-contrib-watch": "0.5.1", 22 | "grunt-shell": "0.6.4", 23 | "sinon": "1.8.2", 24 | "request": "2.34.0", 25 | "shelljs": "0.2.6", 26 | "mocha": "1.17.1" 27 | }, 28 | "hoodie": { 29 | "plugins": [] 30 | }, 31 | "readme": "ERROR: No README data found!", 32 | "_id": "hoodie-plugin-global-share@1.0.10", 33 | "dist": { 34 | "shasum": "baca2c68ad643bd33f96f4cbe2d25984dc8bfb0e", 35 | "tarball": "http://127.0.0.1:15986/hoodie-plugin-global-share/-/hoodie-plugin-global-share-1.0.10.tgz" 36 | }, 37 | "_from": ".", 38 | "_npmVersion": "1.3.11", 39 | "_npmUser": { 40 | "name": "third", 41 | "email": "3@example.com" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /test/fixtures/hoodie-old.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "_id": "hoodie-plugin-global-share", 4 | "_rev": "26-322ba6e2b95e328df1ce03484e75cf14", 5 | "name": "hoodie-plugin-global-share", 6 | "description": "Hoodie.js Global Share Plugin", 7 | "dist-tags": { 8 | "latest": "1.0.4" 9 | }, 10 | "versions": { 11 | "1.0.0": { 12 | "name": "hoodie-plugin-global-share", 13 | "version": "1.0.0", 14 | "main": "worker.js", 15 | "description": "Hoodie.js Global Share Plugin", 16 | "scripts": { 17 | "test": "echo \"Error: no test specified\" && exit 1" 18 | }, 19 | "author": "", 20 | "dependencies": { 21 | "async": "~0.2.10", 22 | "lodash": "~2.4.1" 23 | }, 24 | "_id": "hoodie-plugin-global-share@1.0.0", 25 | "dist": { 26 | "shasum": "dc122cda6752fbdd51014f9f64af31337229f87c", 27 | "tarball": "http://registry.npmjs.org/hoodie-plugin-global-share/-/hoodie-plugin-global-share-1.0.0.tgz" 28 | }, 29 | "_from": ".", 30 | "_npmVersion": "1.3.2", 31 | "_npmUser": { 32 | "name": "caolan", 33 | "email": "caolan.mcmahon@gmail.com" 34 | }, 35 | "maintainers": [ 36 | { 37 | "name": "caolan", 38 | "email": "caolan.mcmahon@gmail.com" 39 | } 40 | ], 41 | "directories": {} 42 | }, 43 | "1.0.1": { 44 | "name": "hoodie-plugin-global-share", 45 | "version": "1.0.1", 46 | "main": "worker.js", 47 | "description": "Hoodie.js Global Share Plugin", 48 | "scripts": { 49 | "test": "echo \"Error: no test specified\" && exit 1" 50 | }, 51 | "author": "", 52 | "dependencies": { 53 | "async": "~0.2.10", 54 | "lodash": "~2.4.1" 55 | }, 56 | "_id": "hoodie-plugin-global-share@1.0.1", 57 | "dist": { 58 | "shasum": "6e3ed5af1053c85e0a450009af3bcaa539c3a785", 59 | "tarball": "http://registry.npmjs.org/hoodie-plugin-global-share/-/hoodie-plugin-global-share-1.0.1.tgz" 60 | }, 61 | "_from": ".", 62 | "_npmVersion": "1.3.21", 63 | "_npmUser": { 64 | "name": "caolan", 65 | "email": "caolan.mcmahon@gmail.com" 66 | }, 67 | "maintainers": [ 68 | { 69 | "name": "caolan", 70 | "email": "caolan.mcmahon@gmail.com" 71 | } 72 | ], 73 | "directories": {} 74 | }, 75 | "1.0.2": { 76 | "name": "hoodie-plugin-global-share", 77 | "version": "1.0.2", 78 | "main": "worker.js", 79 | "description": "Hoodie.js Global Share Plugin", 80 | "scripts": { 81 | "test": "echo \"Error: no test specified\" && exit 1" 82 | }, 83 | "author": "", 84 | "dependencies": { 85 | "async": "~0.2.10", 86 | "lodash": "~2.4.1" 87 | }, 88 | "devDependencies": { 89 | "mocha": "*", 90 | "grunt": "~0.4.1", 91 | "expect.js": "~0.2.0", 92 | "grunt-simple-mocha": "~0.4.0", 93 | "grunt-contrib-jshint": "~0.6.2", 94 | "grunt-contrib-watch": "~0.5.1" 95 | }, 96 | "_id": "hoodie-plugin-global-share@1.0.2", 97 | "dist": { 98 | "shasum": "084d8624065f83b6df5d4c1ece5d2f02127e3db0", 99 | "tarball": "http://registry.npmjs.org/hoodie-plugin-global-share/-/hoodie-plugin-global-share-1.0.2.tgz" 100 | }, 101 | "_from": ".", 102 | "_npmVersion": "1.3.21", 103 | "_npmUser": { 104 | "name": "caolan", 105 | "email": "caolan.mcmahon@gmail.com" 106 | }, 107 | "maintainers": [ 108 | { 109 | "name": "caolan", 110 | "email": "caolan.mcmahon@gmail.com" 111 | } 112 | ], 113 | "directories": {} 114 | }, 115 | "1.0.3": { 116 | "name": "hoodie-plugin-global-share", 117 | "version": "1.0.3", 118 | "main": "worker.js", 119 | "description": "Hoodie.js Global Share Plugin", 120 | "scripts": { 121 | "test": "grunt --verbose" 122 | }, 123 | "author": "", 124 | "dependencies": { 125 | "async": "0.2.10", 126 | "lodash": "2.4.1", 127 | "hoodie-server": "0.9.19", 128 | "hoodie": "0.6.5" 129 | }, 130 | "devDependencies": { 131 | "grunt": "0.4.1", 132 | "expect.js": "0.2.0", 133 | "grunt-simple-mocha": "0.4.0", 134 | "grunt-contrib-jshint": "0.6.2", 135 | "grunt-contrib-watch": "0.5.1", 136 | "grunt-shell": "0.6.4", 137 | "sinon": "1.8.2", 138 | "request": "2.34.0", 139 | "shelljs": "0.2.6", 140 | "mocha": "1.17.1" 141 | }, 142 | "hoodie": { 143 | "plugins": [] 144 | }, 145 | "_id": "hoodie-plugin-global-share@1.0.3", 146 | "dist": { 147 | "shasum": "bc4d181ac4ff4ce0c85cdf6bd005925484e14c2b", 148 | "tarball": "http://registry.npmjs.org/hoodie-plugin-global-share/-/hoodie-plugin-global-share-1.0.3.tgz" 149 | }, 150 | "_from": ".", 151 | "_npmVersion": "1.3.24", 152 | "_npmUser": { 153 | "name": "svnlto", 154 | "email": "me@svenlito.com" 155 | }, 156 | "maintainers": [ 157 | { 158 | "name": "caolan", 159 | "email": "caolan.mcmahon@gmail.com" 160 | }, 161 | { 162 | "name": "svnlto", 163 | "email": "me@svenlito.com" 164 | }, 165 | { 166 | "name": "espy", 167 | "email": "hello@alexfeyerke.com" 168 | }, 169 | { 170 | "name": "gr2m", 171 | "email": "gregor@martynus.net" 172 | }, 173 | { 174 | "name": "jan", 175 | "email": "jan@apache.org" 176 | } 177 | ], 178 | "directories": {} 179 | }, 180 | "1.0.4": { 181 | "name": "hoodie-plugin-global-share", 182 | "version": "1.0.4", 183 | "main": "worker.js", 184 | "description": "Hoodie.js Global Share Plugin", 185 | "scripts": { 186 | "test": "grunt --verbose" 187 | }, 188 | "author": "", 189 | "dependencies": { 190 | "async": "0.2.10", 191 | "lodash": "2.4.1", 192 | "hoodie-server": "0.9.19", 193 | "hoodie": "0.6.5" 194 | }, 195 | "devDependencies": { 196 | "grunt": "0.4.1", 197 | "expect.js": "0.2.0", 198 | "grunt-simple-mocha": "0.4.0", 199 | "grunt-contrib-jshint": "0.6.2", 200 | "grunt-contrib-watch": "0.5.1", 201 | "grunt-shell": "0.6.4", 202 | "sinon": "1.8.2", 203 | "request": "2.34.0", 204 | "shelljs": "0.2.6", 205 | "mocha": "1.17.1" 206 | }, 207 | "hoodie": { 208 | "plugins": [] 209 | }, 210 | "_id": "hoodie-plugin-global-share@1.0.4", 211 | "dist": { 212 | "shasum": "90934bd9fa14c464f6a547f2ad537f42d76a24c5", 213 | "tarball": "http://registry.npmjs.org/hoodie-plugin-global-share/-/hoodie-plugin-global-share-1.0.4.tgz" 214 | }, 215 | "_from": ".", 216 | "_npmVersion": "1.4.3", 217 | "_npmUser": { 218 | "name": "caolan", 219 | "email": "caolan.mcmahon@gmail.com" 220 | }, 221 | "maintainers": [ 222 | { 223 | "name": "caolan", 224 | "email": "caolan.mcmahon@gmail.com" 225 | }, 226 | { 227 | "name": "svnlto", 228 | "email": "me@svenlito.com" 229 | }, 230 | { 231 | "name": "espy", 232 | "email": "hello@alexfeyerke.com" 233 | }, 234 | { 235 | "name": "gr2m", 236 | "email": "gregor@martynus.net" 237 | }, 238 | { 239 | "name": "jan", 240 | "email": "jan@apache.org" 241 | } 242 | ], 243 | "directories": {} 244 | }, 245 | "1.0.5": { 246 | "name": "hoodie-plugin-global-share", 247 | "version": "1.0.5", 248 | "main": "worker.js", 249 | "description": "Hoodie.js Global Share Plugin", 250 | "scripts": { 251 | "test": "grunt --verbose" 252 | }, 253 | "author": "", 254 | "dependencies": { 255 | "async": "0.2.10", 256 | "lodash": "2.4.1", 257 | "hoodie-server": "0.9.19", 258 | "hoodie": "0.6.5" 259 | }, 260 | "devDependencies": { 261 | "grunt": "0.4.1", 262 | "expect.js": "0.2.0", 263 | "grunt-simple-mocha": "0.4.0", 264 | "grunt-contrib-jshint": "0.6.2", 265 | "grunt-contrib-watch": "0.5.1", 266 | "grunt-shell": "0.6.4", 267 | "sinon": "1.8.2", 268 | "request": "2.34.0", 269 | "shelljs": "0.2.6", 270 | "mocha": "1.17.1" 271 | }, 272 | "hoodie": { 273 | "plugins": [] 274 | }, 275 | "_id": "hoodie-plugin-global-share@1.0.5", 276 | "dist": { 277 | "shasum": "cbc47d27766deabd0bd81984bd1e369fccec6bec", 278 | "tarball": "http://registry.npmjs.org/hoodie-plugin-global-share/-/hoodie-plugin-global-share-1.0.5.tgz" 279 | }, 280 | "_from": ".", 281 | "_npmVersion": "1.3.11", 282 | "_npmUser": { 283 | "name": "jan", 284 | "email": "jan@apache.org" 285 | }, 286 | "maintainers": [ 287 | { 288 | "name": "caolan", 289 | "email": "caolan.mcmahon@gmail.com" 290 | }, 291 | { 292 | "name": "svnlto", 293 | "email": "me@svenlito.com" 294 | }, 295 | { 296 | "name": "espy", 297 | "email": "hello@alexfeyerke.com" 298 | }, 299 | { 300 | "name": "gr2m", 301 | "email": "gregor@martynus.net" 302 | }, 303 | { 304 | "name": "jan", 305 | "email": "jan@apache.org" 306 | } 307 | ], 308 | "directories": {} 309 | }, 310 | "1.0.6": { 311 | "name": "hoodie-plugin-global-share", 312 | "version": "1.0.6", 313 | "main": "worker.js", 314 | "description": "Hoodie.js Global Share Plugin", 315 | "scripts": { 316 | "test": "grunt --verbose" 317 | }, 318 | "author": "", 319 | "dependencies": { 320 | "async": "0.2.10", 321 | "lodash": "2.4.1", 322 | "hoodie-server": "0.9.19", 323 | "hoodie": "0.6.5" 324 | }, 325 | "devDependencies": { 326 | "grunt": "0.4.1", 327 | "expect.js": "0.2.0", 328 | "grunt-simple-mocha": "0.4.0", 329 | "grunt-contrib-jshint": "0.6.2", 330 | "grunt-contrib-watch": "0.5.1", 331 | "grunt-shell": "0.6.4", 332 | "sinon": "1.8.2", 333 | "request": "2.34.0", 334 | "shelljs": "0.2.6", 335 | "mocha": "1.17.1" 336 | }, 337 | "hoodie": { 338 | "plugins": [] 339 | }, 340 | "_id": "hoodie-plugin-global-share@1.0.6", 341 | "dist": { 342 | "shasum": "90e83296c7634d03148e88d95df41f94a5c6c3c5", 343 | "tarball": "http://registry.npmjs.org/hoodie-plugin-global-share/-/hoodie-plugin-global-share-1.0.6.tgz" 344 | }, 345 | "_from": ".", 346 | "_npmVersion": "1.3.11", 347 | "_npmUser": { 348 | "name": "jan", 349 | "email": "jan@apache.org" 350 | }, 351 | "maintainers": [ 352 | { 353 | "name": "caolan", 354 | "email": "caolan.mcmahon@gmail.com" 355 | }, 356 | { 357 | "name": "svnlto", 358 | "email": "me@svenlito.com" 359 | }, 360 | { 361 | "name": "espy", 362 | "email": "hello@alexfeyerke.com" 363 | }, 364 | { 365 | "name": "gr2m", 366 | "email": "gregor@martynus.net" 367 | }, 368 | { 369 | "name": "jan", 370 | "email": "jan@apache.org" 371 | } 372 | ], 373 | "directories": {} 374 | } 375 | }, 376 | "readme": "# hoodie-plugin-global-share [![Build Status](https://travis-ci.org/hoodiehq/hoodie-plugin-global-share.png?branch=master)](https://travis-ci.org/hoodiehq/hoodie-plugin-global-share)\n\n### Installation:\n\n```bash\nhoodie install global-share\n```\n\n### Usage:\n\nAssuming you have a running hoodie setup.\n\nCreate a few documents you'd like to make publicly available:\n\n```js\nvar docs = [\n {\n name: 'sleep'\n },\n {\n name: 'eat'\n },\n {\n name: 'sleep some more'\n }\n];\n\nhoodie.store.add('tasks', docs).done(function(newDocs) { /.../ });\n```\n\nMake all 'tasks' publicly available:\n\n```js\nhoodie.store.findAll('tasks').publish();\n```\n\nor publish a single task:\n\n```js\nhoodie.store.find('tasks', 'taskID12345').publish();\n```\n\nSame goes for unpublishing:\n\n```js\nhoodie.store.findAll('tasks').unpublish();\n\nhoodie.store.find('tasks', 'taskID12345').unpublish();\n```\n\n### Testing:\n\n```bash\ngrunt\n```\n", 377 | "maintainers": [ 378 | { 379 | "name": "third", 380 | "email": "3@example.com" 381 | }, 382 | { 383 | "name": "caolan", 384 | "email": "caolan.mcmahon@gmail.com" 385 | }, 386 | { 387 | "name": "svnlto", 388 | "email": "me@svenlito.com" 389 | }, 390 | { 391 | "name": "espy", 392 | "email": "hello@alexfeyerke.com" 393 | }, 394 | { 395 | "name": "gr2m", 396 | "email": "gregor@martynus.net" 397 | }, 398 | { 399 | "name": "jan", 400 | "email": "jan@apache.org" 401 | } 402 | ], 403 | "time": { 404 | "modified": "2014-02-28T17:53:05.151Z", 405 | "created": "2014-02-12T12:28:02.189Z", 406 | "1.0.0": "2014-02-12T12:28:03.627Z", 407 | "1.0.1": "2014-02-18T13:02:38.021Z", 408 | "1.0.2": "2014-02-18T17:48:19.633Z", 409 | "1.0.3": "2014-02-26T16:12:05.894Z", 410 | "1.0.4": "2014-02-28T17:30:56.460Z", 411 | "1.0.5": "2014-02-28T17:49:43.440Z", 412 | "1.0.6": "2014-02-28T17:53:05.151Z" 413 | }, 414 | "readmeFilename": "README.md", 415 | "_attachments": {} 416 | } 417 | -------------------------------------------------------------------------------- /test/fixtures/install/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "install", 3 | "version": "1.2.3", 4 | "dependencies": { 5 | "package": "0.2" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /test/fixtures/meta-goog-put.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "googalytics", 3 | "description": "A totally-outdated-and-should-be-removed Google Analytics API for Node projects" 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/meta-goog.json: -------------------------------------------------------------------------------- 1 | { 2 | "_id": "googalytics", 3 | "_rev": "5-7cee349987ab75585b4815bd7ee893fa", 4 | "name": "googalytics", 5 | "description": "Google Analytics API for Node projects", 6 | "dist-tags": { 7 | "latest": "0.0.1" 8 | }, 9 | "versions": { 10 | "0.0.1": { 11 | "author": { 12 | "name": "Raquel Velez", 13 | "email": "raquel@skookum.com" 14 | }, 15 | "name": "googalytics", 16 | "description": "Google Analytics API for Node projects", 17 | "version": "0.0.1", 18 | "repository": { 19 | "type": "git", 20 | "url": "git://github.com/rockbot/googalytics.git" 21 | }, 22 | "main": "lib/main.js", 23 | "scripts": { 24 | "test": "mocha tests/*.js" 25 | }, 26 | "engines": { 27 | "node": "*" 28 | }, 29 | "dependencies": { 30 | "request": "2.9.203" 31 | }, 32 | "devDependencies": { 33 | "should": "1.0.0", 34 | "mocha": "1.3.0", 35 | "underscore": "1.3.3" 36 | }, 37 | "optionalDependencies": {}, 38 | "_npmUser": { 39 | "name": "rockbot", 40 | "email": "hiya@raquelvelez.com" 41 | }, 42 | "_id": "googalytics@0.0.1", 43 | "_engineSupported": true, 44 | "_npmVersion": "1.1.12", 45 | "_nodeVersion": "v0.6.6", 46 | "_defaultsLoaded": true, 47 | "dist": { 48 | "shasum": "51d8341ceca37a01ac3f987667969ab39c89eb92", 49 | "tarball": "http://registry.npmjs.org/googalytics/-/googalytics-0.0.1.tgz" 50 | }, 51 | "maintainers": [ 52 | { 53 | "name": "rockbot", 54 | "email": "hiya@raquelvelez.com" 55 | } 56 | ], 57 | "directories": {} 58 | } 59 | }, 60 | "readme": "# Googalytics\n\nSimple node module to send custom server-side events to Google Analytics\n\nHeavily influenced by the Gabba project from the guys at the Hybrid Group (http://github.com/hybridgroup/gabba)\n\n## Examples\n\n### Initialize\n\n```javascript\nvar GA = require(\"googalytics\");\nGA.initialize('UA-12345678-1', 'someplace.com', function () {\n GA.trackPage('page title', 'pageName', function (err, resp) {\n if (!err, resp.statusCode === 200) {\n console.log('it worked!');\n }\n });\n});\n```\n\n### What do those variables mean?!\n\nThe answers, as per usual, can be learned from the Google: https://developers.google.com/analytics/resources/articles/gaTrackingTroubleshooting#gifParameters", 61 | "maintainers": [ 62 | { 63 | "name": "third", 64 | "email": "3@example.com" 65 | }, 66 | { 67 | "name": "rockbot", 68 | "email": "hiya@raquelvelez.com" 69 | } 70 | ], 71 | "time": { 72 | "modified": "2012-08-30T01:24:55.224Z", 73 | "created": "2012-08-30T01:24:54.725Z", 74 | "0.0.1": "2012-08-30T01:24:55.224Z" 75 | }, 76 | "author": { 77 | "name": "Raquel Velez", 78 | "email": "raquel@skookum.com" 79 | }, 80 | "repository": { 81 | "type": "git", 82 | "url": "git://github.com/rockbot/googalytics.git" 83 | }, 84 | "_attachments": {} 85 | } -------------------------------------------------------------------------------- /test/fixtures/package/0.0.2/README: -------------------------------------------------------------------------------- 1 | just an npm test 2 | -------------------------------------------------------------------------------- /test/fixtures/package/0.0.2/package.json: -------------------------------------------------------------------------------- 1 | {"name":"package","version":"0.0.2"} 2 | -------------------------------------------------------------------------------- /test/fixtures/package/0.2.3/README.md: -------------------------------------------------------------------------------- 1 | just an npm test, but with a **markdown** readme. 2 | -------------------------------------------------------------------------------- /test/fixtures/package/0.2.3/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "package", 3 | "version": "0.2.3" 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/package/0.2.3/test.js: -------------------------------------------------------------------------------- 1 | 2 | var assert = require("assert") 3 | assert.equal(undefined, process.env.npm_config__password, "password exposed!") 4 | assert.equal(undefined, process.env.npm_config__auth, "auth exposed!") 5 | assert.equal(undefined, process.env.npm_config__authCrypt, "authCrypt exposed!") 6 | -------------------------------------------------------------------------------- /test/fixtures/package/0.2.3alpha/README.md: -------------------------------------------------------------------------------- 1 | just an npm test, but with a **markdown** readme. 2 | -------------------------------------------------------------------------------- /test/fixtures/package/0.2.3alpha/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "package", 3 | "version": "0.2.3alpha" 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/package/0.2.3alpha/test.js: -------------------------------------------------------------------------------- 1 | 2 | var assert = require("assert") 3 | assert.equal(undefined, process.env.npm_config__password, "password exposed!") 4 | assert.equal(undefined, process.env.npm_config__auth, "auth exposed!") 5 | assert.equal(undefined, process.env.npm_config__authCrypt, "authCrypt exposed!") 6 | -------------------------------------------------------------------------------- /test/fixtures/package/0.2.4/README.md: -------------------------------------------------------------------------------- 1 | just an npm test, but with a **markdown** readme. 2 | -------------------------------------------------------------------------------- /test/fixtures/package/0.2.4/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "package", 3 | "version": "0.2.4" 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/package/0.2.4/test.js: -------------------------------------------------------------------------------- 1 | 2 | var assert = require("assert") 3 | assert.equal(undefined, process.env.npm_config__password, "password exposed!") 4 | assert.equal(undefined, process.env.npm_config__auth, "auth exposed!") 5 | assert.equal(undefined, process.env.npm_config__authCrypt, "authCrypt exposed!") 6 | -------------------------------------------------------------------------------- /test/fixtures/scoped-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@npm/package", 3 | "version": "0.2.5", 4 | "maintainers": [ 5 | { 6 | "name": "seldo", 7 | "email": "laurie@npmjs.com" 8 | } 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /test/fixtures/star-nopt-put.json: -------------------------------------------------------------------------------- 1 | { 2 | "_id": "nopt", 3 | "_rev": "47-53cb2cfc4b22238ec73f12e4f4812266", 4 | "users": { 5 | "agnat": true, 6 | "fgribreau": true, 7 | "lupomontero": true, 8 | "chrisdickinson": true, 9 | "pid": true, 10 | "kastor": true, 11 | "testuser": true 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /test/fixtures/vdu-auth/01-new.json: -------------------------------------------------------------------------------- 1 | { 2 | "_id":"org.couchdb.user:noemail", 3 | "name":"noemail", 4 | "password_sha":"deadbeefdeadbeefdeadbeefdeadbeef", 5 | "salt":"deadbeef", 6 | "type":"user", 7 | "roles":[] 8 | } 9 | -------------------------------------------------------------------------------- /test/fixtures/vdu-auth/01-throw.json: -------------------------------------------------------------------------------- 1 | { "forbidden":"Email must be an email address"} 2 | -------------------------------------------------------------------------------- /test/fixtures/vdu-auth/02-new.json: -------------------------------------------------------------------------------- 1 | {"name":"string-iterations" 2 | ,"_id":"org.couchdb.user:string-iterations" 3 | ,"password_scheme":"pbkdf2" 4 | ,"iterations":"10" 5 | ,"derived_key":"deadbeefdeadbeefdeadbeefdeadbeefdeadbeef" 6 | ,"salt":"deadbeefdeadbeefdeadbeefdeadbeefdeadbeef" 7 | ,"email":"deadbeef@deadbeef.com" 8 | ,"type":"user" 9 | ,"roles":[] 10 | } 11 | -------------------------------------------------------------------------------- /test/fixtures/vdu-auth/02-throw.json: -------------------------------------------------------------------------------- 1 | {"forbidden":"doc.iterations must be a number"} 2 | -------------------------------------------------------------------------------- /test/fixtures/vdu-auth/03-new.json: -------------------------------------------------------------------------------- 1 | { 2 | "_id":"org.couchdb.user:pbkdfsha", 3 | "email":"pbkdfsha@trolol.lol", 4 | "name":"pbkdfsha", 5 | "password_sha":"deadbeefdeadbeefdeadbeefdeadbeef", 6 | "derived_key":"deadbeefdeadbeefdeadbeefdeadbeef", 7 | "password_scheme": "pbkdf2", 8 | "iterations":10, 9 | "salt":"deadbeef", 10 | "type":"user", 11 | "roles":[] 12 | } 13 | -------------------------------------------------------------------------------- /test/fixtures/vdu-auth/03-throw.json: -------------------------------------------------------------------------------- 1 | {"forbidden": 2 | "may not mix password_sha and pbkdf2\nYou may need to upgrade your version of npm:\n npm install npm -g\nNote that this may need to be run as root/admin (sudo, etc.)\n\n"} 3 | -------------------------------------------------------------------------------- /test/fixtures/vdu/01-new.json: -------------------------------------------------------------------------------- 1 | { 2 | "_id": "npm-test-blerg", 3 | "_rev": "7-74b6b63207c2d6dde2361a69a61d0aa6", 4 | "name": "npm-test-blerg", 5 | "description": "just an npm test", 6 | "dist-tags": { 7 | "foo": "0.0.3", 8 | "latest": "0.0.2" 9 | }, 10 | "versions": { 11 | "0.0.2": { 12 | "name": "npm-test-blerg", 13 | "version": "0.0.2", 14 | "scripts": { 15 | "test": "node test.js" 16 | }, 17 | "publishConfig": { 18 | "tag": "foo" 19 | }, 20 | "description": "just an npm test", 21 | "_id": "npm-test-blerg@0.0.2", 22 | "dist": { 23 | "shasum": "b8cb2269c44197fc3f37bd8b0b8edc82a79ef674", 24 | "tarball": "http://registry.npmjs.org/npm-test-blerg/-/npm-test-blerg-0.0.2.tgz" 25 | }, 26 | "_from": ".", 27 | "_npmVersion": "1.4.3", 28 | "_npmUser": { 29 | "name": "testuser", 30 | "email": "i@izs.me" 31 | }, 32 | "maintainers": [ 33 | { 34 | "name": "testuser", 35 | "email": "i@izs.me" 36 | } 37 | ] 38 | }, 39 | "0.0.3": { 40 | "name": "npm-test-blerg", 41 | "version": "0.0.3", 42 | "scripts": { 43 | "test": "node test.js" 44 | }, 45 | "publishConfig": { 46 | "tag": "foo" 47 | }, 48 | "description": "just an npm test", 49 | "_id": "npm-test-blerg@0.0.3", 50 | "dist": { 51 | "shasum": "c1682c0e4f0cb61ca2e48b147c3d81d52598a8a1", 52 | "tarball": "http://registry.npmjs.org/npm-test-blerg/-/npm-test-blerg-0.0.3.tgz" 53 | }, 54 | "_from": ".", 55 | "_npmVersion": "1.4.3", 56 | "_npmUser": { 57 | "name": "testuser", 58 | "email": "i@izs.me" 59 | }, 60 | "maintainers": [ 61 | { 62 | "name": "testuser", 63 | "email": "i@izs.me" 64 | } 65 | ] 66 | } 67 | }, 68 | "readme": "just an npm test\n", 69 | "maintainers": [ 70 | { 71 | "name": "testuser", 72 | "email": "i@izs.me" 73 | } 74 | ], 75 | "time": { 76 | "modified": "2014-02-17T22:59:37.521Z", 77 | "created": "2014-02-17T22:58:03.202Z", 78 | "0.0.2": "2014-02-17T22:58:03.202Z", 79 | "0.0.3": "2014-02-17T22:58:29.024Z" 80 | }, 81 | "readmeFilename": "README" 82 | } 83 | -------------------------------------------------------------------------------- /test/fixtures/vdu/01-old.json: -------------------------------------------------------------------------------- 1 | { 2 | "_id": "npm-test-blerg", 3 | "_rev": "6-566c2c2c0dbf15aca0f8113c50aaaa5c", 4 | "name": "npm-test-blerg", 5 | "description": "just an npm test", 6 | "dist-tags": { 7 | "foo": "0.0.3", 8 | "latest": "0.0.2" 9 | }, 10 | "versions": { 11 | "0.0.2": { 12 | "name": "npm-test-blerg", 13 | "version": "0.0.2", 14 | "scripts": { 15 | "test": "node test.js" 16 | }, 17 | "publishConfig": { 18 | "tag": "foo" 19 | }, 20 | "description": "just an npm test", 21 | "_id": "npm-test-blerg@0.0.2", 22 | "dist": { 23 | "shasum": "b8cb2269c44197fc3f37bd8b0b8edc82a79ef674", 24 | "tarball": "http://registry.npmjs.org/npm-test-blerg/-/npm-test-blerg-0.0.2.tgz" 25 | }, 26 | "_from": ".", 27 | "_npmVersion": "1.4.3", 28 | "_npmUser": { 29 | "name": "other-user", 30 | "email": "i@izs.me" 31 | }, 32 | "maintainers": [ 33 | { 34 | "name": "testuser", 35 | "email": "i@izs.me" 36 | } 37 | ] 38 | }, 39 | "0.0.3": { 40 | "name": "npm-test-blerg", 41 | "version": "0.0.3", 42 | "scripts": { 43 | "test": "node test.js" 44 | }, 45 | "publishConfig": { 46 | "tag": "foo" 47 | }, 48 | "description": "just an npm test", 49 | "_id": "npm-test-blerg@0.0.3", 50 | "dist": { 51 | "shasum": "c1682c0e4f0cb61ca2e48b147c3d81d52598a8a1", 52 | "tarball": "http://registry.npmjs.org/npm-test-blerg/-/npm-test-blerg-0.0.3.tgz" 53 | }, 54 | "_from": ".", 55 | "_npmVersion": "1.4.3", 56 | "_npmUser": { 57 | "name": "testuser", 58 | "email": "i@izs.me" 59 | }, 60 | "maintainers": [ 61 | { 62 | "name": "testuser", 63 | "email": "i@izs.me" 64 | } 65 | ] 66 | } 67 | }, 68 | "readme": "just an npm test\n", 69 | "maintainers": [ 70 | { 71 | "name": "testuser", 72 | "email": "i@izs.me" 73 | } 74 | ], 75 | "time": { 76 | "modified": "2014-02-17T22:59:37.521Z", 77 | "created": "2014-02-17T22:58:03.202Z", 78 | "0.0.2": "2014-02-17T22:58:03.202Z", 79 | "0.0.3": "2014-02-17T22:58:29.024Z" 80 | }, 81 | "readmeFilename": "README" 82 | } 83 | -------------------------------------------------------------------------------- /test/fixtures/vdu/01-throw.json: -------------------------------------------------------------------------------- 1 | { "forbidden": "Changing published version metadata is not allowed" } 2 | -------------------------------------------------------------------------------- /test/fixtures/vdu/01-user.json: -------------------------------------------------------------------------------- 1 | { "name": "testuser", "roles": []} 2 | -------------------------------------------------------------------------------- /test/fixtures/vdu/02-new.json: -------------------------------------------------------------------------------- 1 | { 2 | "_id": "flexpmd", 3 | "_rev": "4-432e2aec1fd4a3a85025e832e7a51316", 4 | "name": "flexpmd", 5 | "time": { 6 | "modified": "2014-02-17T16:20:03.577Z", 7 | "created": "2014-02-17T16:20:02.181Z", 8 | "1.3.0": "2014-02-17T16:20:03.577Z", 9 | "unpublished": { 10 | "name": "jamesmgreene", 11 | "time": "2014-02-18T00:31:50.133Z" 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /test/fixtures/vdu/02-old.json: -------------------------------------------------------------------------------- 1 | { 2 | "_id": "flexpmd", 3 | "_rev": "4-432e2aec1fd4a3a85025e832e7a51316", 4 | "name": "flexpmd", 5 | "description": "A Node.js module to download and \"install\" the FlexPMD infrastructure for linting/analyzing ActionScript/Flash/Flex/AIR code.", 6 | "dist-tags": { 7 | "latest": "1.3.0" 8 | }, 9 | "versions": { 10 | "1.3.0": { 11 | "name": "flexpmd", 12 | "description": "A Node.js module to download and \"install\" the FlexPMD infrastructure for linting/analyzing ActionScript/Flash/Flex/AIR code.", 13 | "version": "1.3.0", 14 | "flexPmd": { 15 | "url": "https://github.com/JamesMGreene/adobe-flex-pmd/releases/download/v1.3/adobe-flex-pmd.zip" 16 | }, 17 | "homepage": "https://github.com/JamesMGreene/node-flexpmd", 18 | "author": { 19 | "name": "James M. Greene", 20 | "email": "the-email@example.com", 21 | "url": "http://jamesgreene.net/" 22 | }, 23 | "repository": { 24 | "type": "git", 25 | "url": "git://github.com/JamesMGreene/node-flexpmd.git" 26 | }, 27 | "bugs": { 28 | "url": "https://github.com/JamesMGreene/node-flexpmd/issues" 29 | }, 30 | "licenses": [ 31 | { 32 | "type": "MIT", 33 | "url": "https://github.com/JamesMGreene/node-flexpmd/blob/master/LICENSE-MIT" 34 | } 35 | ], 36 | "main": "lib/flexpmd", 37 | "engines": { 38 | "node": ">= 0.8.0" 39 | }, 40 | "scripts": { 41 | "prepublish": "node prepublish.js", 42 | "test": "grunt travis --verbose" 43 | }, 44 | "devDependencies": { 45 | "grunt-contrib-jshint": "~0.8.0", 46 | "grunt-contrib-nodeunit": "~0.3.0", 47 | "grunt-contrib-watch": "~0.5.3", 48 | "grunt": "~0.4.2", 49 | "xpath": "0.0.6", 50 | "xmldom": "~0.1.19" 51 | }, 52 | "keywords": [ 53 | "download", 54 | "install", 55 | "apache", 56 | "adobe", 57 | "flexpmd", 58 | "aslint", 59 | "open source", 60 | "compiler", 61 | "flex", 62 | "mxml", 63 | "actionscript", 64 | "flv", 65 | "flash", 66 | "air" 67 | ], 68 | "dependencies": { 69 | "follow-redirects": "0.0.3", 70 | "glob": "~3.2.8" 71 | }, 72 | "_id": "flexpmd@1.3.0", 73 | "dist": { 74 | "shasum": "9376062b1fa373e65f301c40079cadee52390590", 75 | "tarball": "http://registry.npmjs.org/flexpmd/-/flexpmd-1.3.0.tgz" 76 | }, 77 | "_from": ".", 78 | "_npmVersion": "1.2.24", 79 | "_npmUser": { 80 | "name": "jamesmgreene", 81 | "email": "the-email@example.com" 82 | }, 83 | "maintainers": [ 84 | { 85 | "name": "jamesmgreene", 86 | "email": "the-email@example.com" 87 | } 88 | ], 89 | "directories": {} 90 | } 91 | }, 92 | "readme": "# flexpmd [![Build Status](https://secure.travis-ci.org/JamesMGreene/node-flexpmd.png?branch=master)](http://travis-ci.org/JamesMGreene/node-flexpmd)\r\n\r\nA Node.js module to download and \"install\" the FlexPMD infrastructure for linting/analyzing ActionScript/Flash/Flex/AIR code.\r\n\r\n\r\n## Getting Started\r\nInstall the module with: `npm install flexpmd`\r\n\r\n```javascript\r\nvar flexlint = require('flexpmd');\r\nconsole.log(flexlint.path); // path to the main directory of JARs\r\nconsole.log(flexlint.cmd); // path to the JAR to use like a command line executable\r\n```\r\n\r\n\r\n## External Dependencies\r\nWhile this Node/NPM module does not have any external dependencies itself, the FlexPMD tool requires Java.\r\n\r\n\r\n## Examples\r\nSee the unit tests for example usage.\r\n\r\n\r\n## Contributing\r\nIn lieu of a formal styleguide, take care to maintain the existing coding style.\r\nAdd unit tests for any new or changed functionality.\r\nLint and test your code using [Grunt](http://gruntjs.com/).\r\n\r\n\r\n## Release History\r\n- 1.3.0: Published to NPM on 2014-02-17.\r\n - Initial release. Version number aligned with FlexPMD version number.\r\n\r\n\r\n## License\r\nCopyright (c) 2014 James M. Greene \r\nLicensed under the MIT license.\r\n\r\n\r\n## Background Information on FlexPMD\r\n - [Home](http://sourceforge.net/adobe/flexpmd/)\r\n - [Overview](http://sourceforge.net/adobe/flexpmd/wiki/Overview/)\r\n - [About](http://sourceforge.net/adobe/flexpmd/wiki/About/)\r\n - [How to invoke FlexPMD](http://sourceforge.net/adobe/flexpmd/wiki/How%20to%20invoke%20FlexPMD/)\r\n - [How to interpret FlexPMD results](http://sourceforge.net/adobe/flexpmd/wiki/How%20to%20interpret%20results/)\r\n - [How to add your own rule](http://sourceforge.net/adobe/flexpmd/wiki/How%20to%20add%20your%20own%20rule/)\r\n - [Developer documentation](http://sourceforge.net/adobe/flexpmd/wiki/Developer%20documentation/)\r\n - [Mind Map: \"What is FlexPMD?\"](http://www.xmind.net/m/F2Ft/)\r\n - [FlashDevelop4's integrated FlexPMD source folder](http://flashdevelop.googlecode.com/svn/trunk/FD4/FlashDevelop/Bin/Debug/Tools/flexpmd/) _(→ Tools → Flash Tools → Analyse Project Source code.)_\r\n - [FlashDevelop3's FlexPMD plugin wrapper and usage discussion](http://www.flashdevelop.org/community/viewtopic.php?f=4&t=5403)\r\n - [FlashDevelop3's FlexPMD plugin wrapper setup guide](http://www.swfgeek.net/2009/09/18/using-flex-pmd-in-flashdevelop-3/)\r\n", 93 | "maintainers": [ 94 | { 95 | "name": "jamesmgreene", 96 | "email": "the-email@example.com" 97 | } 98 | ], 99 | "time": { 100 | "modified": "2014-02-17T16:20:03.577Z", 101 | "created": "2014-02-17T16:20:02.181Z", 102 | "1.3.0": "2014-02-17T16:20:03.577Z" 103 | }, 104 | "readmeFilename": "README.md", 105 | "author": { 106 | "name": "James M. Greene", 107 | "email": "the-email@example.com", 108 | "url": "http://jamesgreene.net/" 109 | }, 110 | "repository": { 111 | "type": "git", 112 | "url": "git://github.com/JamesMGreene/node-flexpmd.git" 113 | }, 114 | "_attachments": {} 115 | } 116 | -------------------------------------------------------------------------------- /test/fixtures/vdu/02-user.json: -------------------------------------------------------------------------------- 1 | { "name": "jamesmgreene", "roles": [] } 2 | -------------------------------------------------------------------------------- /test/fixtures/vdu/03-new.json: -------------------------------------------------------------------------------- 1 | { 2 | "_id": "npm-test-blerg", 3 | "_rev": "7-74b6b63207c2d6dde2361a69a61d0aa6", 4 | "name": "npm-test-blerg", 5 | "description": "just an npm test", 6 | "dist-tags": { 7 | "latest": "0.0.3" 8 | }, 9 | "versions": { 10 | "0.0.2": { 11 | "name": "npm-test-blerg", 12 | "version": "0.0.2", 13 | "scripts": { 14 | "test": "node test.js" 15 | }, 16 | "publishConfig": { 17 | "tag": "foo" 18 | }, 19 | "description": "just an npm test", 20 | "_id": "npm-test-blerg@0.0.2", 21 | "dist": { 22 | "shasum": "b8cb2269c44197fc3f37bd8b0b8edc82a79ef674", 23 | "tarball": "http://registry.npmjs.org/npm-test-blerg/-/npm-test-blerg-0.0.2.tgz" 24 | }, 25 | "_from": ".", 26 | "_npmVersion": "1.4.3", 27 | "_npmUser": { 28 | "name": "testuser", 29 | "email": "i@izs.me" 30 | }, 31 | "maintainers": [ 32 | { 33 | "name": "testuser", 34 | "email": "i@izs.me" 35 | } 36 | ] 37 | }, 38 | "0.0.3": { 39 | "name": "npm-test-blerg", 40 | "version": "0.0.3", 41 | "scripts": { 42 | "test": "node test.js" 43 | }, 44 | "publishConfig": { 45 | "tag": "foo" 46 | }, 47 | "description": "just an npm test", 48 | "_id": "npm-test-blerg@0.0.3", 49 | "dist": { 50 | "shasum": "c1682c0e4f0cb61ca2e48b147c3d81d52598a8a1", 51 | "tarball": "http://registry.npmjs.org/npm-test-blerg/-/npm-test-blerg-0.0.3.tgz" 52 | }, 53 | "_from": ".", 54 | "_npmVersion": "1.4.3", 55 | "_npmUser": { 56 | "name": "other-user", 57 | "email": "i@izs.me" 58 | }, 59 | "maintainers": [ 60 | { 61 | "name": "testuser", 62 | "email": "i@izs.me" 63 | } 64 | ] 65 | } 66 | }, 67 | "readme": "just an npm test\n", 68 | "maintainers": [ 69 | { 70 | "name": "testuser", 71 | "email": "i@izs.me" 72 | } 73 | ], 74 | "time": { 75 | "modified": "2014-02-17T22:59:37.521Z", 76 | "created": "2014-02-17T22:58:03.202Z", 77 | "0.0.2": "2014-02-17T22:58:03.202Z", 78 | "0.0.3": "2014-02-17T22:58:29.024Z" 79 | }, 80 | "readmeFilename": "README" 81 | } 82 | -------------------------------------------------------------------------------- /test/fixtures/vdu/03-old.json: -------------------------------------------------------------------------------- 1 | { 2 | "_id": "npm-test-blerg", 3 | "_rev": "6-566c2c2c0dbf15aca0f8113c50aaaa5c", 4 | "name": "npm-test-blerg", 5 | "description": "just an npm test", 6 | "dist-tags": { 7 | "latest": "0.0.2" 8 | }, 9 | "versions": { 10 | "0.0.2": { 11 | "name": "npm-test-blerg", 12 | "version": "0.0.2", 13 | "scripts": { 14 | "test": "node test.js" 15 | }, 16 | "publishConfig": { 17 | "tag": "foo" 18 | }, 19 | "description": "just an npm test", 20 | "_id": "npm-test-blerg@0.0.2", 21 | "dist": { 22 | "shasum": "b8cb2269c44197fc3f37bd8b0b8edc82a79ef674", 23 | "tarball": "http://registry.npmjs.org/npm-test-blerg/-/npm-test-blerg-0.0.2.tgz" 24 | }, 25 | "_from": ".", 26 | "_npmVersion": "1.4.3", 27 | "_npmUser": { 28 | "name": "testuser", 29 | "email": "i@izs.me" 30 | }, 31 | "maintainers": [ 32 | { 33 | "name": "testuser", 34 | "email": "i@izs.me" 35 | } 36 | ] 37 | } 38 | }, 39 | "readme": "just an npm test\n", 40 | "maintainers": [ 41 | { 42 | "name": "testuser", 43 | "email": "i@izs.me" 44 | } 45 | ], 46 | "time": { 47 | "modified": "2014-02-17T22:59:37.521Z", 48 | "created": "2014-02-17T22:58:03.202Z", 49 | "0.0.2": "2014-02-17T22:58:03.202Z" 50 | }, 51 | "readmeFilename": "README" 52 | } 53 | -------------------------------------------------------------------------------- /test/fixtures/vdu/03-throw.json: -------------------------------------------------------------------------------- 1 | {"forbidden":"_npmUser.name must match user.name: 0.0.3"} 2 | -------------------------------------------------------------------------------- /test/fixtures/vdu/03-user.json: -------------------------------------------------------------------------------- 1 | { "name": "testuser", "roles": []} 2 | -------------------------------------------------------------------------------- /test/fixtures/vdu/04-new.json: -------------------------------------------------------------------------------- 1 | { 2 | "_id": "npm-test-blerg", 3 | "_rev": "6-566c2c2c0dbf15aca0f8113c50aaaa5c", 4 | "name": "npm-test-blerg", 5 | "description": "just an npm test", 6 | "dist-tags": {}, 7 | "versions": { 8 | "0.0.2": { 9 | "name": "npm-test-blerg", 10 | "version": "0.0.2", 11 | "scripts": { 12 | "test": "node test.js" 13 | }, 14 | "publishConfig": { 15 | "tag": "foo" 16 | }, 17 | "description": "just an npm test", 18 | "_id": "npm-test-blerg@0.0.2", 19 | "dist": { 20 | "shasum": "b8cb2269c44197fc3f37bd8b0b8edc82a79ef674", 21 | "tarball": "http://registry.npmjs.org/npm-test-blerg/-/npm-test-blerg-0.0.2.tgz" 22 | }, 23 | "_from": ".", 24 | "_npmVersion": "1.4.3", 25 | "_npmUser": { 26 | "name": "other-user", 27 | "email": "i@izs.me" 28 | }, 29 | "maintainers": [ 30 | { 31 | "name": "testuser", 32 | "email": "i@izs.me" 33 | } 34 | ] 35 | }, 36 | "0.0.3": { 37 | "name": "npm-test-blerg", 38 | "version": "0.0.3", 39 | "scripts": { 40 | "test": "node test.js" 41 | }, 42 | "publishConfig": { 43 | "tag": "foo" 44 | }, 45 | "description": "just an npm test", 46 | "_id": "npm-test-blerg@0.0.3", 47 | "dist": { 48 | "shasum": "c1682c0e4f0cb61ca2e48b147c3d81d52598a8a1", 49 | "tarball": "http://registry.npmjs.org/npm-test-blerg/-/npm-test-blerg-0.0.3.tgz" 50 | }, 51 | "_from": ".", 52 | "_npmVersion": "1.4.3", 53 | "_npmUser": { 54 | "name": "testuser", 55 | "email": "i@izs.me" 56 | }, 57 | "maintainers": [ 58 | { 59 | "name": "testuser", 60 | "email": "i@izs.me" 61 | } 62 | ] 63 | } 64 | }, 65 | "readme": "just an npm test\n", 66 | "maintainers": [ 67 | { 68 | "name": "testuser", 69 | "email": "i@izs.me" 70 | } 71 | ], 72 | "time": { 73 | "modified": "2014-02-17T22:59:37.521Z", 74 | "created": "2014-02-17T22:58:03.202Z", 75 | "0.0.2": "2014-02-17T22:58:03.202Z", 76 | "0.0.3": "2014-02-17T22:58:29.024Z" 77 | }, 78 | "readmeFilename": "README" 79 | } 80 | -------------------------------------------------------------------------------- /test/fixtures/vdu/04-old.json: -------------------------------------------------------------------------------- 1 | { 2 | "_id": "npm-test-blerg", 3 | "_rev": "6-566c2c2c0dbf15aca0f8113c50aaaa5c", 4 | "name": "npm-test-blerg", 5 | "description": "just an npm test", 6 | "dist-tags": { 7 | "foo": "0.0.3", 8 | "latest": "0.0.2" 9 | }, 10 | "versions": { 11 | "0.0.2": { 12 | "name": "npm-test-blerg", 13 | "version": "0.0.2", 14 | "scripts": { 15 | "test": "node test.js" 16 | }, 17 | "publishConfig": { 18 | "tag": "foo" 19 | }, 20 | "description": "just an npm test", 21 | "_id": "npm-test-blerg@0.0.2", 22 | "dist": { 23 | "shasum": "b8cb2269c44197fc3f37bd8b0b8edc82a79ef674", 24 | "tarball": "http://registry.npmjs.org/npm-test-blerg/-/npm-test-blerg-0.0.2.tgz" 25 | }, 26 | "_from": ".", 27 | "_npmVersion": "1.4.3", 28 | "_npmUser": { 29 | "name": "other-user", 30 | "email": "i@izs.me" 31 | }, 32 | "maintainers": [ 33 | { 34 | "name": "testuser", 35 | "email": "i@izs.me" 36 | } 37 | ] 38 | }, 39 | "0.0.3": { 40 | "name": "npm-test-blerg", 41 | "version": "0.0.3", 42 | "scripts": { 43 | "test": "node test.js" 44 | }, 45 | "publishConfig": { 46 | "tag": "foo" 47 | }, 48 | "description": "just an npm test", 49 | "_id": "npm-test-blerg@0.0.3", 50 | "dist": { 51 | "shasum": "c1682c0e4f0cb61ca2e48b147c3d81d52598a8a1", 52 | "tarball": "http://registry.npmjs.org/npm-test-blerg/-/npm-test-blerg-0.0.3.tgz" 53 | }, 54 | "_from": ".", 55 | "_npmVersion": "1.4.3", 56 | "_npmUser": { 57 | "name": "testuser", 58 | "email": "i@izs.me" 59 | }, 60 | "maintainers": [ 61 | { 62 | "name": "testuser", 63 | "email": "i@izs.me" 64 | } 65 | ] 66 | } 67 | }, 68 | "readme": "just an npm test\n", 69 | "maintainers": [ 70 | { 71 | "name": "testuser", 72 | "email": "i@izs.me" 73 | } 74 | ], 75 | "time": { 76 | "modified": "2014-02-17T22:59:37.521Z", 77 | "created": "2014-02-17T22:58:03.202Z", 78 | "0.0.2": "2014-02-17T22:58:03.202Z", 79 | "0.0.3": "2014-02-17T22:58:29.024Z" 80 | }, 81 | "readmeFilename": "README" 82 | } 83 | -------------------------------------------------------------------------------- /test/fixtures/vdu/04-throw.json: -------------------------------------------------------------------------------- 1 | {"forbidden":"may not remove dist-tags"} -------------------------------------------------------------------------------- /test/fixtures/vdu/04-user.json: -------------------------------------------------------------------------------- 1 | { "name": "testuser", "roles": []} 2 | -------------------------------------------------------------------------------- /test/fixtures/vdu/05-new.json: -------------------------------------------------------------------------------- 1 | { 2 | "_id": "package", 3 | "_rev": "5-76fdaadbe33c912a9b96c070170a5595", 4 | "name": "package", 5 | "description": "just an npm test, but with a **markdown** readme.", 6 | "dist-tags": { 7 | "latest": "0.2.3" 8 | }, 9 | "versions": { 10 | "0.0.2": { 11 | "name": "package", 12 | "version": "0.0.2", 13 | "description": "just an npm test", 14 | "_id": "package@0.0.2", 15 | "dist": { 16 | "shasum": "c633471c3673ac68d432670cef7c5c0263ae524b", 17 | "tarball": "http://127.0.0.1:15986/package/-/package-0.0.2.tgz" 18 | }, 19 | "_from": ".", 20 | "_npmVersion": "1.4.4", 21 | "_npmUser": { 22 | "name": "user", 23 | "email": "email@example.com" 24 | }, 25 | "maintainers": [ 26 | { 27 | "name": "user", 28 | "email": "email@example.com" 29 | } 30 | ] 31 | }, 32 | "0.2.3-alpha": { 33 | "name": "package", 34 | "version": "0.2.3-alpha", 35 | "description": "just an npm test, but with a **markdown** readme.", 36 | "_id": "package@0.2.3-alpha", 37 | "dist": { 38 | "shasum": "b145d84e98f8b506d02038a6842d25c70236c6e5", 39 | "tarball": "http://127.0.0.1:15986/package/-/package-0.2.3-alpha.tgz" 40 | }, 41 | "_from": ".", 42 | "_npmVersion": "1.4.4", 43 | "_npmUser": { 44 | "name": "user", 45 | "email": "email@example.com" 46 | }, 47 | "maintainers": [ 48 | { 49 | "name": "user", 50 | "email": "email@example.com" 51 | } 52 | ] 53 | }, 54 | "0.2.3": { 55 | "name": "package", 56 | "version": "0.2.3", 57 | "description": "just an npm test, but with a **markdown** readme.", 58 | "_id": "package@0.2.3", 59 | "dist": { 60 | "shasum": "40c38d32b5c6642c6256b44a00b0f3bd6ac6cea2", 61 | "tarball": "http://127.0.0.1:15986/package/-/package-0.2.3.tgz" 62 | }, 63 | "_from": ".", 64 | "_npmVersion": "1.4.4", 65 | "_npmUser": { 66 | "name": "other", 67 | "email": "other@example.com" 68 | }, 69 | "maintainers": [ 70 | { 71 | "name": "user", 72 | "email": "email@example.com" 73 | }, 74 | { 75 | "name": "other", 76 | "email": "other@example.com" 77 | } 78 | ] 79 | } 80 | }, 81 | "readme": "just an npm test, but with a **markdown** readme.\n", 82 | "maintainers": [ 83 | { 84 | "name": "user", 85 | "email": "email@example.com" 86 | }, 87 | { 88 | "name": "other", 89 | "email": "other@example.com" 90 | } 91 | ], 92 | "time": { 93 | "modified": "2014-02-21T22:29:35.449Z", 94 | "created": "2014-02-21T22:29:33.772Z", 95 | "0.0.2": "2014-02-21T22:29:33.772Z", 96 | "0.2.3-alpha": "2014-02-21T22:29:34.809Z", 97 | "0.2.3": "2014-02-21T22:29:35.449Z" 98 | }, 99 | "readmeFilename": "README.md", 100 | "users": { 101 | "third": "this is not a boolean value" 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /test/fixtures/vdu/05-old.json: -------------------------------------------------------------------------------- 1 | { 2 | "_id": "package", 3 | "_rev": "5-76fdaadbe33c912a9b96c070170a5595", 4 | "name": "package", 5 | "description": "just an npm test, but with a **markdown** readme.", 6 | "dist-tags": { 7 | "latest": "0.2.3" 8 | }, 9 | "versions": { 10 | "0.0.2": { 11 | "name": "package", 12 | "version": "0.0.2", 13 | "description": "just an npm test", 14 | "_id": "package@0.0.2", 15 | "dist": { 16 | "shasum": "c633471c3673ac68d432670cef7c5c0263ae524b", 17 | "tarball": "http://127.0.0.1:15986/package/-/package-0.0.2.tgz" 18 | }, 19 | "_from": ".", 20 | "_npmVersion": "1.4.4", 21 | "_npmUser": { 22 | "name": "user", 23 | "email": "email@example.com" 24 | }, 25 | "maintainers": [ 26 | { 27 | "name": "user", 28 | "email": "email@example.com" 29 | } 30 | ] 31 | }, 32 | "0.2.3-alpha": { 33 | "name": "package", 34 | "version": "0.2.3-alpha", 35 | "description": "just an npm test, but with a **markdown** readme.", 36 | "_id": "package@0.2.3-alpha", 37 | "dist": { 38 | "shasum": "b145d84e98f8b506d02038a6842d25c70236c6e5", 39 | "tarball": "http://127.0.0.1:15986/package/-/package-0.2.3-alpha.tgz" 40 | }, 41 | "_from": ".", 42 | "_npmVersion": "1.4.4", 43 | "_npmUser": { 44 | "name": "user", 45 | "email": "email@example.com" 46 | }, 47 | "maintainers": [ 48 | { 49 | "name": "user", 50 | "email": "email@example.com" 51 | } 52 | ] 53 | }, 54 | "0.2.3": { 55 | "name": "package", 56 | "version": "0.2.3", 57 | "description": "just an npm test, but with a **markdown** readme.", 58 | "_id": "package@0.2.3", 59 | "dist": { 60 | "shasum": "40c38d32b5c6642c6256b44a00b0f3bd6ac6cea2", 61 | "tarball": "http://127.0.0.1:15986/package/-/package-0.2.3.tgz" 62 | }, 63 | "_from": ".", 64 | "_npmVersion": "1.4.4", 65 | "_npmUser": { 66 | "name": "other", 67 | "email": "other@example.com" 68 | }, 69 | "maintainers": [ 70 | { 71 | "name": "user", 72 | "email": "email@example.com" 73 | }, 74 | { 75 | "name": "other", 76 | "email": "other@example.com" 77 | } 78 | ] 79 | } 80 | }, 81 | "readme": "just an npm test, but with a **markdown** readme.\n", 82 | "maintainers": [ 83 | { 84 | "name": "user", 85 | "email": "email@example.com" 86 | }, 87 | { 88 | "name": "other", 89 | "email": "other@example.com" 90 | } 91 | ], 92 | "time": { 93 | "modified": "2014-02-21T22:29:35.449Z", 94 | "created": "2014-02-21T22:29:33.772Z", 95 | "0.0.2": "2014-02-21T22:29:33.772Z", 96 | "0.2.3-alpha": "2014-02-21T22:29:34.809Z", 97 | "0.2.3": "2014-02-21T22:29:35.449Z" 98 | }, 99 | "readmeFilename": "README.md" 100 | } 101 | -------------------------------------------------------------------------------- /test/fixtures/vdu/05-throw.json: -------------------------------------------------------------------------------- 1 | {"forbidden":"star setting must be a boolean, got string"} 2 | -------------------------------------------------------------------------------- /test/fixtures/vdu/05-user.json: -------------------------------------------------------------------------------- 1 | { "name": "third", "roles": []} 2 | -------------------------------------------------------------------------------- /test/fixtures/vdu/06-new.json: -------------------------------------------------------------------------------- 1 | { 2 | "_id": "flexpmd", 3 | "_rev": "4-432e2aec1fd4a3a85025e832e7a51316", 4 | "name": "flexpmd", 5 | "time": { 6 | "modified": "2014-02-17T16:20:03.577Z", 7 | "created": "2014-02-17T16:20:02.181Z", 8 | "1.3.0": "2014-02-17T16:20:03.577Z", 9 | "unpublished": { 10 | "name": "jamesmgreene", 11 | "time": "2014-02-18T00:31:50.133Z" 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /test/fixtures/vdu/06-old.json: -------------------------------------------------------------------------------- 1 | { 2 | "_id": "flexpmd", 3 | "_rev": "4-432e2aec1fd4a3a85025e832e7a51316", 4 | "name": "flexpmd", 5 | "description": "A Node.js module to download and \"install\" the FlexPMD infrastructure for linting/analyzing ActionScript/Flash/Flex/AIR code.", 6 | "dist-tags": { 7 | "latest": "1.3.0" 8 | }, 9 | "versions": { 10 | "1.3.0": { 11 | "name": "flexpmd", 12 | "description": "A Node.js module to download and \"install\" the FlexPMD infrastructure for linting/analyzing ActionScript/Flash/Flex/AIR code.", 13 | "version": "1.3.0", 14 | "flexPmd": { 15 | "url": "https://github.com/JamesMGreene/adobe-flex-pmd/releases/download/v1.3/adobe-flex-pmd.zip" 16 | }, 17 | "homepage": "https://github.com/JamesMGreene/node-flexpmd", 18 | "author": { 19 | "name": "James M. Greene", 20 | "email": "the-email@example.com", 21 | "url": "http://jamesgreene.net/" 22 | }, 23 | "repository": { 24 | "type": "git", 25 | "url": "git://github.com/JamesMGreene/node-flexpmd.git" 26 | }, 27 | "bugs": { 28 | "url": "https://github.com/JamesMGreene/node-flexpmd/issues" 29 | }, 30 | "licenses": [ 31 | { 32 | "type": "MIT", 33 | "url": "https://github.com/JamesMGreene/node-flexpmd/blob/master/LICENSE-MIT" 34 | } 35 | ], 36 | "main": "lib/flexpmd", 37 | "engines": { 38 | "node": ">= 0.8.0" 39 | }, 40 | "scripts": { 41 | "prepublish": "node prepublish.js", 42 | "test": "grunt travis --verbose" 43 | }, 44 | "devDependencies": { 45 | "grunt-contrib-jshint": "~0.8.0", 46 | "grunt-contrib-nodeunit": "~0.3.0", 47 | "grunt-contrib-watch": "~0.5.3", 48 | "grunt": "~0.4.2", 49 | "xpath": "0.0.6", 50 | "xmldom": "~0.1.19" 51 | }, 52 | "keywords": [ 53 | "download", 54 | "install", 55 | "apache", 56 | "adobe", 57 | "flexpmd", 58 | "aslint", 59 | "open source", 60 | "compiler", 61 | "flex", 62 | "mxml", 63 | "actionscript", 64 | "flv", 65 | "flash", 66 | "air" 67 | ], 68 | "dependencies": { 69 | "follow-redirects": "0.0.3", 70 | "glob": "~3.2.8" 71 | }, 72 | "_id": "flexpmd@1.3.0", 73 | "dist": { 74 | "shasum": "9376062b1fa373e65f301c40079cadee52390590", 75 | "tarball": "http://registry.npmjs.org/flexpmd/-/flexpmd-1.3.0.tgz" 76 | }, 77 | "_from": ".", 78 | "_npmVersion": "1.2.24", 79 | "_npmUser": { 80 | "name": "jamesmgreene", 81 | "email": "the-email@example.com" 82 | }, 83 | "maintainers": [ 84 | { 85 | "role": "foo" 86 | } 87 | ], 88 | "directories": {} 89 | } 90 | }, 91 | "readme": "# flexpmd [![Build Status](https://secure.travis-ci.org/JamesMGreene/node-flexpmd.png?branch=master)](http://travis-ci.org/JamesMGreene/node-flexpmd)\r\n\r\nA Node.js module to download and \"install\" the FlexPMD infrastructure for linting/analyzing ActionScript/Flash/Flex/AIR code.\r\n\r\n\r\n## Getting Started\r\nInstall the module with: `npm install flexpmd`\r\n\r\n```javascript\r\nvar flexlint = require('flexpmd');\r\nconsole.log(flexlint.path); // path to the main directory of JARs\r\nconsole.log(flexlint.cmd); // path to the JAR to use like a command line executable\r\n```\r\n\r\n\r\n## External Dependencies\r\nWhile this Node/NPM module does not have any external dependencies itself, the FlexPMD tool requires Java.\r\n\r\n\r\n## Examples\r\nSee the unit tests for example usage.\r\n\r\n\r\n## Contributing\r\nIn lieu of a formal styleguide, take care to maintain the existing coding style.\r\nAdd unit tests for any new or changed functionality.\r\nLint and test your code using [Grunt](http://gruntjs.com/).\r\n\r\n\r\n## Release History\r\n- 1.3.0: Published to NPM on 2014-02-17.\r\n - Initial release. Version number aligned with FlexPMD version number.\r\n\r\n\r\n## License\r\nCopyright (c) 2014 James M. Greene \r\nLicensed under the MIT license.\r\n\r\n\r\n## Background Information on FlexPMD\r\n - [Home](http://sourceforge.net/adobe/flexpmd/)\r\n - [Overview](http://sourceforge.net/adobe/flexpmd/wiki/Overview/)\r\n - [About](http://sourceforge.net/adobe/flexpmd/wiki/About/)\r\n - [How to invoke FlexPMD](http://sourceforge.net/adobe/flexpmd/wiki/How%20to%20invoke%20FlexPMD/)\r\n - [How to interpret FlexPMD results](http://sourceforge.net/adobe/flexpmd/wiki/How%20to%20interpret%20results/)\r\n - [How to add your own rule](http://sourceforge.net/adobe/flexpmd/wiki/How%20to%20add%20your%20own%20rule/)\r\n - [Developer documentation](http://sourceforge.net/adobe/flexpmd/wiki/Developer%20documentation/)\r\n - [Mind Map: \"What is FlexPMD?\"](http://www.xmind.net/m/F2Ft/)\r\n - [FlashDevelop4's integrated FlexPMD source folder](http://flashdevelop.googlecode.com/svn/trunk/FD4/FlashDevelop/Bin/Debug/Tools/flexpmd/) _(→ Tools → Flash Tools → Analyse Project Source code.)_\r\n - [FlashDevelop3's FlexPMD plugin wrapper and usage discussion](http://www.flashdevelop.org/community/viewtopic.php?f=4&t=5403)\r\n - [FlashDevelop3's FlexPMD plugin wrapper setup guide](http://www.swfgeek.net/2009/09/18/using-flex-pmd-in-flashdevelop-3/)\r\n", 92 | "maintainers": [ 93 | { 94 | "name": "jamesmgreene", 95 | "email": "the-email@example.com" 96 | } 97 | ], 98 | "time": { 99 | "modified": "2014-02-17T16:20:03.577Z", 100 | "created": "2014-02-17T16:20:02.181Z", 101 | "1.3.0": "2014-02-17T16:20:03.577Z" 102 | }, 103 | "readmeFilename": "README.md", 104 | "author": { 105 | "name": "James M. Greene", 106 | "email": "the-email@example.com", 107 | "url": "http://jamesgreene.net/" 108 | }, 109 | "repository": { 110 | "type": "git", 111 | "url": "git://github.com/JamesMGreene/node-flexpmd.git" 112 | }, 113 | "_attachments": {} 114 | } 115 | -------------------------------------------------------------------------------- /test/fixtures/vdu/06-user.json: -------------------------------------------------------------------------------- 1 | { "name": "jamesmgreene", "roles": ["foo"] } 2 | -------------------------------------------------------------------------------- /test/fixtures/vdu/07-new.json: -------------------------------------------------------------------------------- 1 | { 2 | "_id": "@npm/npm-test-blerg", 3 | "_rev": "7-74b6b63207c2d6dde2361a69a61d0aa6", 4 | "name": "@npm/npm-test-blerg", 5 | "description": "just an npm test", 6 | "dist-tags": { 7 | "latest": "0.0.2" 8 | }, 9 | "versions": { 10 | "0.0.2": { 11 | "name": "@npm/npm-test-blerg", 12 | "version": "0.0.2", 13 | "scripts": { 14 | "test": "node test.js" 15 | }, 16 | "publishConfig": { 17 | "tag": "foo" 18 | }, 19 | "description": "just an npm test", 20 | "_id": "@npm/npm-test-blerg@0.0.2", 21 | "dist": { 22 | "shasum": "b8cb2269c44197fc3f37bd8b0b8edc82a79ef674", 23 | "tarball": "http://registry.npmjs.org/@npm/npm-test-blerg/-/npm-test-blerg-0.0.2.tgz" 24 | }, 25 | "_from": ".", 26 | "_npmVersion": "1.4.3", 27 | "_npmUser": { 28 | "name": "testuser", 29 | "email": "i@izs.me" 30 | }, 31 | "maintainers": [ 32 | { 33 | "name": "testuser", 34 | "email": "i@izs.me" 35 | } 36 | ] 37 | }, 38 | "0.0.3": { 39 | "name": "@npm/npm-test-blerg", 40 | "version": "0.0.3", 41 | "scripts": { 42 | "test": "node test.js" 43 | }, 44 | "publishConfig": { 45 | "tag": "foo" 46 | }, 47 | "description": "just an npm test", 48 | "_id": "@npm/npm-test-blerg@0.0.3", 49 | "dist": { 50 | "shasum": "c1682c0e4f0cb61ca2e48b147c3d81d52598a8a1", 51 | "tarball": "http://registry.npmjs.org/@npm/npm-test-blerg/-/npm-test-blerg-0.0.3.tgz" 52 | }, 53 | "_from": ".", 54 | "_npmVersion": "1.4.3", 55 | "_npmUser": { 56 | "name": "testuser", 57 | "email": "i@izs.me" 58 | }, 59 | "maintainers": [ 60 | { 61 | "name": "testuser", 62 | "email": "i@izs.me" 63 | } 64 | ] 65 | } 66 | }, 67 | "readme": "just an npm test\n", 68 | "maintainers": [ 69 | { 70 | "name": "testuser", 71 | "email": "i@izs.me" 72 | } 73 | ], 74 | "time": { 75 | "modified": "2014-02-17T22:59:37.521Z", 76 | "created": "2014-02-17T22:58:03.202Z", 77 | "0.0.2": "2014-02-17T22:58:03.202Z", 78 | "0.0.3": "2014-02-17T22:58:29.024Z" 79 | }, 80 | "readmeFilename": "README" 81 | } 82 | -------------------------------------------------------------------------------- /test/fixtures/vdu/07-old.json: -------------------------------------------------------------------------------- 1 | { 2 | "_id": "@npm/npm-test-blerg", 3 | "_rev": "6-566c2c2c0dbf15aca0f8113c50aaaa5c", 4 | "name": "@npm/npm-test-blerg", 5 | "description": "just an npm test", 6 | "dist-tags": { 7 | "latest": "0.0.2" 8 | }, 9 | "versions": { 10 | "0.0.2": { 11 | "name": "@npm/npm-test-blerg", 12 | "version": "0.0.2", 13 | "scripts": { 14 | "test": "node test.js" 15 | }, 16 | "publishConfig": { 17 | "tag": "foo" 18 | }, 19 | "description": "just an npm test", 20 | "_id": "@npm/npm-test-blerg@0.0.2", 21 | "dist": { 22 | "shasum": "b8cb2269c44197fc3f37bd8b0b8edc82a79ef674", 23 | "tarball": "http://registry.npmjs.org/@npm/npm-test-blerg/-/npm-test-blerg-0.0.2.tgz" 24 | }, 25 | "_from": ".", 26 | "_npmVersion": "1.4.3", 27 | "_npmUser": { 28 | "name": "testuser", 29 | "email": "i@izs.me" 30 | }, 31 | "maintainers": [ 32 | { 33 | "name": "testuser", 34 | "email": "i@izs.me" 35 | } 36 | ] 37 | }, 38 | "0.0.3": { 39 | "name": "@npm/npm-test-blerg", 40 | "version": "0.0.3", 41 | "scripts": { 42 | "test": "node test.js" 43 | }, 44 | "publishConfig": { 45 | "tag": "foo" 46 | }, 47 | "description": "just an npm test", 48 | "_id": "@npm/npm-test-blerg@0.0.3", 49 | "dist": { 50 | "shasum": "c1682c0e4f0cb61ca2e48b147c3d81d52598a8a1", 51 | "tarball": "http://registry.npmjs.org/@npm/npm-test-blerg/-/npm-test-blerg-0.0.3.tgz" 52 | }, 53 | "_from": ".", 54 | "_npmVersion": "1.4.3", 55 | "_npmUser": { 56 | "name": "testuser", 57 | "email": "i@izs.me" 58 | }, 59 | "maintainers": [ 60 | { 61 | "name": "testuser", 62 | "email": "i@izs.me" 63 | } 64 | ] 65 | } 66 | }, 67 | "readme": "just an npm test\n", 68 | "maintainers": [ 69 | { 70 | "name": "testuser", 71 | "email": "i@izs.me" 72 | } 73 | ], 74 | "time": { 75 | "modified": "2014-02-17T22:59:37.521Z", 76 | "created": "2014-02-17T22:58:03.202Z", 77 | "0.0.2": "2014-02-17T22:58:03.202Z", 78 | "0.0.3": "2014-02-17T22:58:29.024Z" 79 | }, 80 | "readmeFilename": "README" 81 | } 82 | -------------------------------------------------------------------------------- /test/fixtures/vdu/07-user.json: -------------------------------------------------------------------------------- 1 | { "name": "testuser", "roles": ["npm"]} 2 | -------------------------------------------------------------------------------- /test/fixtures/vdu/08-new.json: -------------------------------------------------------------------------------- 1 | { 2 | "_id": "npm-test-blerg", 3 | "_rev": "7-74b6b63207c2d6dde2361a69a61d0aa6", 4 | "name": "npm-test-blerg", 5 | "description": "just an npm test", 6 | "dist-tags": { 7 | "latest": "0.0.2" 8 | }, 9 | "versions": { 10 | "0.0.2": { 11 | "name": "npm-test-blerg", 12 | "version": "0.0.2", 13 | "scripts": { 14 | "test": "node test.js" 15 | }, 16 | "publishConfig": { 17 | "tag": "foo" 18 | }, 19 | "description": "just an npm test", 20 | "_id": "npm-test-blerg@0.0.2", 21 | "dist": { 22 | "shasum": "b8cb2269c44197fc3f37bd8b0b8edc82a79ef674", 23 | "tarball": "http://registry.npmjs.org/npm-test-blerg/-/npm-test-blerg-0.0.2.tgz" 24 | }, 25 | "_from": ".", 26 | "_npmVersion": "1.4.3", 27 | "_npmUser": { 28 | "name": "testuser", 29 | "email": "i@izs.me" 30 | }, 31 | "maintainers": [ 32 | { 33 | "name": "testuser", 34 | "email": "i@izs.me" 35 | } 36 | ] 37 | }, 38 | "0.0.3": { 39 | "name": "npm-test-blerg", 40 | "version": "0.0.3", 41 | "scripts": { 42 | "test": "node test.js" 43 | }, 44 | "publishConfig": { 45 | "tag": "foo" 46 | }, 47 | "description": "just an npm test", 48 | "_id": "npm-test-blerg@0.0.3", 49 | "dist": { 50 | "shasum": "c1682c0e4f0cb61ca2e48b147c3d81d52598a8a1", 51 | "tarball": "http://registry.npmjs.org/npm-test-blerg/-/npm-test-blerg-0.0.3.tgz" 52 | }, 53 | "_from": ".", 54 | "_npmVersion": "1.4.3", 55 | "_npmUser": { 56 | "name": "testuser", 57 | "email": "i@izs.me" 58 | }, 59 | "maintainers": [ 60 | { 61 | "name": "testuser", 62 | "email": "i@izs.me" 63 | } 64 | ], 65 | "dependencies": { 66 | "@npm/foo": "1.2.3" 67 | } 68 | } 69 | }, 70 | "readme": "just an npm test\n", 71 | "maintainers": [ 72 | { 73 | "name": "testuser", 74 | "email": "i@izs.me" 75 | } 76 | ], 77 | "time": { 78 | "modified": "2014-02-17T22:59:37.521Z", 79 | "created": "2014-02-17T22:58:03.202Z", 80 | "0.0.2": "2014-02-17T22:58:03.202Z", 81 | "0.0.3": "2014-02-17T22:58:29.024Z" 82 | }, 83 | "readmeFilename": "README" 84 | } 85 | -------------------------------------------------------------------------------- /test/fixtures/vdu/08-old.json: -------------------------------------------------------------------------------- 1 | { 2 | "_id": "@npm/npm-test-blerg", 3 | "_rev": "6-566c2c2c0dbf15aca0f8113c50aaaa5c", 4 | "name": "@npm/npm-test-blerg", 5 | "description": "just an npm test", 6 | "dist-tags": { 7 | "latest": "0.0.2" 8 | }, 9 | "versions": { 10 | "0.0.2": { 11 | "name": "@npm/npm-test-blerg", 12 | "version": "0.0.2", 13 | "scripts": { 14 | "test": "node test.js" 15 | }, 16 | "publishConfig": { 17 | "tag": "foo" 18 | }, 19 | "description": "just an npm test", 20 | "_id": "@npm/npm-test-blerg@0.0.2", 21 | "dist": { 22 | "shasum": "b8cb2269c44197fc3f37bd8b0b8edc82a79ef674", 23 | "tarball": "http://registry.npmjs.org/@npm/npm-test-blerg/-/npm-test-blerg-0.0.2.tgz" 24 | }, 25 | "_from": ".", 26 | "_npmVersion": "1.4.3", 27 | "_npmUser": { 28 | "name": "testuser", 29 | "email": "i@izs.me" 30 | }, 31 | "maintainers": [ 32 | { 33 | "name": "testuser", 34 | "email": "i@izs.me" 35 | } 36 | ] 37 | }, 38 | "0.0.3": { 39 | "name": "@npm/npm-test-blerg", 40 | "version": "0.0.3", 41 | "scripts": { 42 | "test": "node test.js" 43 | }, 44 | "publishConfig": { 45 | "tag": "foo" 46 | }, 47 | "description": "just an npm test", 48 | "_id": "@npm/npm-test-blerg@0.0.3", 49 | "dist": { 50 | "shasum": "c1682c0e4f0cb61ca2e48b147c3d81d52598a8a1", 51 | "tarball": "http://registry.npmjs.org/@npm/npm-test-blerg/-/npm-test-blerg-0.0.3.tgz" 52 | }, 53 | "_from": ".", 54 | "_npmVersion": "1.4.3", 55 | "_npmUser": { 56 | "name": "testuser", 57 | "email": "i@izs.me" 58 | }, 59 | "maintainers": [ 60 | { 61 | "name": "testuser", 62 | "email": "i@izs.me" 63 | } 64 | ] 65 | } 66 | }, 67 | "readme": "just an npm test\n", 68 | "maintainers": [ 69 | { 70 | "name": "testuser", 71 | "email": "i@izs.me" 72 | } 73 | ], 74 | "time": { 75 | "modified": "2014-02-17T22:59:37.521Z", 76 | "created": "2014-02-17T22:58:03.202Z", 77 | "0.0.2": "2014-02-17T22:58:03.202Z", 78 | "0.0.3": "2014-02-17T22:58:29.024Z" 79 | }, 80 | "readmeFilename": "README" 81 | } 82 | -------------------------------------------------------------------------------- /test/fixtures/vdu/08-throw.json: -------------------------------------------------------------------------------- 1 | {"forbidden":"Changing published version metadata is not allowed"} -------------------------------------------------------------------------------- /test/fixtures/vdu/08-user.json: -------------------------------------------------------------------------------- 1 | { "name": "testuser", "roles": ["npm"]} 2 | -------------------------------------------------------------------------------- /test/fixtures/vdu/09-new.json: -------------------------------------------------------------------------------- 1 | { 2 | "_id": "@npm/npm-test-blerg", 3 | "name": "@npm/npm-test-blerg", 4 | "description": "just an npm test", 5 | "dist-tags": { 6 | "latest": "0.0.2" 7 | }, 8 | "versions": { 9 | "0.0.2": { 10 | "name": "@npm/npm-test-blerg", 11 | "version": "0.0.2", 12 | "scripts": { 13 | "test": "node test.js" 14 | }, 15 | "publishConfig": { 16 | "tag": "foo" 17 | }, 18 | "description": "just an npm test", 19 | "_id": "@npm/npm-test-blerg@0.0.2", 20 | "dist": { 21 | "shasum": "b8cb2269c44197fc3f37bd8b0b8edc82a79ef674", 22 | "tarball": "http://registry.npmjs.org/@npm/npm-test-blerg/-/npm-test-blerg-0.0.2.tgz" 23 | }, 24 | "_from": ".", 25 | "_npmVersion": "1.4.3", 26 | "_npmUser": { 27 | "name": "testuser", 28 | "email": "i@izs.me" 29 | }, 30 | "maintainers": [ 31 | { 32 | "name": "testuser", 33 | "email": "i@izs.me" 34 | } 35 | ] 36 | } 37 | }, 38 | "readme": "just an npm test\n", 39 | "maintainers": [ 40 | { 41 | "name": "testuser", 42 | "email": "i@izs.me" 43 | } 44 | ], 45 | "time": { 46 | "modified": "2014-02-17T22:58:03.202Z", 47 | "created": "2014-02-17T22:58:03.202Z", 48 | "0.0.2": "2014-02-17T22:58:03.202Z" 49 | }, 50 | "readmeFilename": "README" 51 | } 52 | -------------------------------------------------------------------------------- /test/fixtures/vdu/09-throw.json: -------------------------------------------------------------------------------- 1 | { 2 | "forbidden": "user: testuser not authorized to modify @npm/npm-test-blerg\nAdded: _id\nAdded: name\nAdded: description\nAdded: dist-tags\nAdded: versions\nAdded: readme\nAdded: maintainers\nAdded: time\nAdded: readmeFilename\nAdded: users" 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/vdu/09-user.json: -------------------------------------------------------------------------------- 1 | { "name": "testuser", "roles": []} 2 | -------------------------------------------------------------------------------- /test/fixtures/yui-new.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "yui", 3 | "description": "YUI 3 Source", 4 | "dist-tags": { 5 | "latest": "3.15.0-rc-1" 6 | }, 7 | "maintainers": [ 8 | { 9 | "name": "ezequiel", 10 | "email": "ezequiel@yahoo-inc.com" 11 | } 12 | ], 13 | "versions": { 14 | "3.15.0-rc-1": { 15 | "name": "yui", 16 | "version": "3.15.0-rc-1", 17 | "description": "YUI 3 Source", 18 | "author": { 19 | "name": "Dav Glass", 20 | "email": "davglass@gmail.com" 21 | }, 22 | "bugs": { 23 | "url": "https://github.com/yui/yui3/issues" 24 | }, 25 | "engines": { 26 | "node": ">=0.8.0" 27 | }, 28 | "directories": { 29 | "lib": "." 30 | }, 31 | "main": "./index.js", 32 | "dependencies": { 33 | "request": "~2.21.0" 34 | }, 35 | "devDependencies": { 36 | "yogi": "~0.1.0", 37 | "parserlib": "~0.2.2", 38 | "grunt": "~0.4.1", 39 | "grunt-cli": "~0.1.7", 40 | "grunt-yui-contrib": "~0.0.17", 41 | "grunt-lib-contrib": "~0.5.3", 42 | "grunt-contrib-compress": "0.4.10", 43 | "grunt-css-selectors": "~0.1.2", 44 | "bower": "~1.2.8", 45 | "archiver": "0.4.10" 46 | }, 47 | "licenses": [ 48 | { 49 | "type": "BSD", 50 | "url": "http://yuilibrary.com/license/" 51 | } 52 | ], 53 | "repository": { 54 | "type": "git", 55 | "url": "http://github.com/yui/yui3.git" 56 | }, 57 | "readme": "YUI 3: blerg", 58 | "readmeFilename": "README.md", 59 | "homepage": "https://github.com/yui/yui3", 60 | "_id": "yui@3.15.0-rc-1", 61 | "dist": { 62 | "tarball": "http://registry.npmjs.org/yui/-/yui-3.15.0-rc-1.tgz", 63 | "shasum": "87cabefaf0742a2da45bdd9dd553a29ce29ca94b" 64 | }, 65 | "_from": "npm" 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /test/ping.js: -------------------------------------------------------------------------------- 1 | var http = require('http') 2 | var parse = require('parse-json-response') 3 | var test = require('tap').test 4 | 5 | var reg = 'http://admin:admin@localhost:15986/registry' 6 | var ping = reg + '/_design/scratch/_show/ping' 7 | var rw = reg + '/_design/scratch/_rewrite/-/ping' 8 | 9 | var wanted = { 10 | host: 'localhost:15986' 11 | , ok: true 12 | , username: 'admin' 13 | , peer: '127.0.0.1' 14 | } 15 | 16 | ;[ping, ping + '/any', rw, rw + '/any'].forEach(function (uri) { 17 | test('ping ' + uri, function (t) { 18 | t.plan(2) 19 | http.get(uri, parse(function (er, data, res) { 20 | t.ok(!er) 21 | t.same(data, wanted) 22 | t.end() 23 | })) 24 | }) 25 | }) 26 | -------------------------------------------------------------------------------- /test/pkg-update-copy-fields.js: -------------------------------------------------------------------------------- 1 | if (process.version.match(/^v[0-9][0-9]\./)) { 2 | console.log('1..0 # monkeypatching natives stopped working in node v10') 3 | process.exit(0) 4 | } 5 | var test = require("tap").test 6 | 7 | var mod = require("../registry/modules.js") 8 | Object.keys(mod).forEach(function (m) { 9 | process.binding('natives')[m] = mod[m] 10 | }) 11 | 12 | process.env.DEPLOY_VERSION = 'testing' 13 | var pkg = require("../registry/app.js").updates.package 14 | 15 | var doc = 16 | { 17 | "_id": "video.js", 18 | "_rev": "17-8dd44999858bb8937548c253d50d472d", 19 | "maintainers": [ { name: "user" } ], 20 | "name": "video.js", 21 | "description": "foo", 22 | "readme": "Blerg.", 23 | "access": "public", 24 | "repository": { 25 | "url": "git://bliorasdf" 26 | }, 27 | "dist-tags": { 28 | "latest":"1.2.3" 29 | }, 30 | "versions": { 31 | "1.2.3": { 32 | name: "video.js", 33 | _id: "video.js@1.2.3", 34 | "description": "foo", 35 | "readme": "Blerg.", 36 | "repository": { 37 | "url": "git://bliorasdf" 38 | } 39 | } 40 | }, 41 | "time": { 42 | "created": "2014-02-18T23:19:45.467Z", 43 | "modified": "2014-02-18T23:19:45.474Z", 44 | "1.2.3": "2014-02-18T23:19:45.468Z" 45 | } 46 | } 47 | 48 | var newdoc = JSON.parse(JSON.stringify(doc)) 49 | newdoc.versions['2.3.4'] = { 50 | name: "video.js", 51 | _id: "video.js@2.3.4", 52 | "version": "2.3.4", 53 | "description": "foo and blz", 54 | "readme": "a new readme", 55 | "repository": { 56 | "url": "git://new-url" 57 | } 58 | } 59 | newdoc.time['2.3.4'] = "2014-02-18T23:19:45.474Z" 60 | newdoc['dist-tags'].latest = '2.3.4' 61 | 62 | var expect = 63 | { 64 | "_id": "video.js", 65 | "_rev": "17-8dd44999858bb8937548c253d50d472d", 66 | "maintainers": [ 67 | { 68 | "name": "user" 69 | } 70 | ], 71 | "name": "video.js", 72 | "description": "foo and blz", 73 | "readme": "a new readme", 74 | "repository": { 75 | "url": "git://new-url" 76 | }, 77 | "dist-tags": { 78 | "latest": "2.3.4" 79 | }, 80 | "versions": { 81 | "1.2.3": { 82 | "name": "video.js", 83 | "_id": "video.js@1.2.3", 84 | "description": "foo", 85 | "repository": { 86 | "url": "git://bliorasdf" 87 | } 88 | }, 89 | "2.3.4": { 90 | "name": "video.js", 91 | "_id": "video.js@2.3.4", 92 | "description": "foo and blz", 93 | "repository": { 94 | "url": "git://new-url" 95 | }, 96 | "version": "2.3.4", 97 | "maintainers": [ 98 | { 99 | "name": "user" 100 | } 101 | ], 102 | "_npmUser" : { 103 | "name" : "user" // != undefined 104 | } 105 | } 106 | }, 107 | "time": { 108 | "created": "2014-02-18T23:19:45.467Z", 109 | "modified": "2014-02-18T23:19:45.474Z", 110 | "1.2.3": "2014-02-18T23:19:45.468Z", 111 | "2.3.4": "2014-02-18T23:19:45.474Z" 112 | }, 113 | "readmeFilename": "" 114 | } 115 | 116 | var req = { 117 | method: 'PUT', 118 | query: {}, 119 | body: JSON.stringify(newdoc), 120 | userCtx: { name: "user" } 121 | } 122 | 123 | test("hange the things", function (t) { 124 | var res = pkg(doc, req) 125 | expect.time.modified = doc.time.modified 126 | expect.time['2.3.4'] = doc.time['2.3.4'] 127 | t.same(res[1], '{"ok":"updated package"}') 128 | t.same(res[0], expect) 129 | t.end() 130 | }) 131 | -------------------------------------------------------------------------------- /test/pkg-update-deprecate-msg.js: -------------------------------------------------------------------------------- 1 | if (process.version.match(/^v[0-9][0-9]\./)) { 2 | console.log('1..0 # monkeypatching natives stopped working in node v10') 3 | process.exit(0) 4 | } 5 | var test = require("tap").test 6 | 7 | var mod = require("../registry/modules.js") 8 | Object.keys(mod).forEach(function (m) { 9 | process.binding('natives')[m] = mod[m] 10 | }) 11 | 12 | process.env.DEPLOY_VERSION = 'testing' 13 | var pkg = require("../registry/app.js").updates.package 14 | 15 | var doc = 16 | { 17 | "_id": "package", 18 | "_rev": "10-8a93c0cb475461352ee3e20eabffb2de", 19 | "name": "package", 20 | "description": "just an npm test, but with a **markdown** readme.", 21 | "dist-tags": { 22 | "latest": "0.2.3" 23 | }, 24 | "versions": { 25 | "0.0.2": { 26 | "name": "package", 27 | "version": "0.0.2", 28 | "description": "just an npm test", 29 | "_id": "package@0.0.2", 30 | "dist": { 31 | "shasum": "c633471c3673ac68d432670cef7c5c0263ae524b", 32 | "tarball": "http://127.0.0.1:15986/package/-/package-0.0.2.tgz" 33 | }, 34 | "_from": ".", 35 | "_npmVersion": "1.4.3", 36 | "_npmUser": { 37 | "name": "user", 38 | "email": "email@example.com" 39 | }, 40 | "maintainers": [ 41 | { 42 | "name": "user", 43 | "email": "email@example.com" 44 | } 45 | ], 46 | "directories": {} 47 | }, 48 | "0.2.3-alpha": { 49 | "name": "package", 50 | "version": "0.2.3-alpha", 51 | "description": "just an npm test, but with a **markdown** readme.", 52 | "_id": "package@0.2.3-alpha", 53 | "dist": { 54 | "shasum": "b145d84e98f8b506d02038a6842d25c70236c6e5", 55 | "tarball": "http://127.0.0.1:15986/package/-/package-0.2.3-alpha.tgz" 56 | }, 57 | "_from": ".", 58 | "_npmVersion": "1.4.3", 59 | "_npmUser": { 60 | "name": "user", 61 | "email": "email@example.com" 62 | }, 63 | "maintainers": [ 64 | { 65 | "name": "user", 66 | "email": "email@example.com" 67 | } 68 | ], 69 | "directories": {} 70 | }, 71 | "0.2.3": { 72 | "name": "package", 73 | "version": "0.2.3", 74 | "description": "just an npm test, but with a **markdown** readme.", 75 | "_id": "package@0.2.3", 76 | "dist": { 77 | "shasum": "40c38d32b5c6642c6256b44a00b0f3bd6ac6cea2", 78 | "tarball": "http://127.0.0.1:15986/package/-/package-0.2.3.tgz" 79 | }, 80 | "_from": ".", 81 | "_npmVersion": "1.4.3", 82 | "_npmUser": { 83 | "name": "other", 84 | "email": "other@example.com" 85 | }, 86 | "maintainers": [ 87 | { 88 | "name": "user", 89 | "email": "email@example.com" 90 | }, 91 | { 92 | "name": "other", 93 | "email": "other@example.com" 94 | } 95 | ], 96 | "directories": {} 97 | } 98 | }, 99 | "readme": "just an npm test, but with a **markdown** readme.\n", 100 | "maintainers": [ 101 | { 102 | "name": "user", 103 | "email": "email@example.com" 104 | }, 105 | { 106 | "name": "other", 107 | "email": "other@example.com" 108 | } 109 | ], 110 | "time": { 111 | "modified": "2014-02-17T23:54:53.763Z", 112 | "created": "2014-02-17T23:54:50.312Z", 113 | "0.0.2": "2014-02-17T23:54:50.312Z", 114 | "0.2.3-alpha": "2014-02-17T23:54:51.395Z", 115 | "0.2.3": "2014-02-17T23:54:52.051Z" 116 | }, 117 | "readmeFilename": "README.md", 118 | "users": {}, 119 | "_attachments": { 120 | "package-0.0.2.tgz": { 121 | "content_type": "application/octet-stream", 122 | "revpos": 1, 123 | "digest": "md5-MpzHQbQmBCguhkRiAZECDA==", 124 | "length": 200, 125 | "stub": true 126 | }, 127 | "package-0.2.3-alpha.tgz": { 128 | "content_type": "application/octet-stream", 129 | "revpos": 2, 130 | "digest": "md5-nlx0drFAVoxE+U8FjVMh7Q==", 131 | "length": 366, 132 | "stub": true 133 | }, 134 | "package-0.2.3.tgz": { 135 | "content_type": "application/octet-stream", 136 | "revpos": 4, 137 | "digest": "md5-77CJ7t17gBQvbdwv4ulabw==", 138 | "length": 363, 139 | "stub": true 140 | } 141 | } 142 | } 143 | 144 | var newdoc = JSON.parse(JSON.stringify(doc)) 145 | newdoc.versions['0.0.2'].deprecated = 'deprecation message' 146 | 147 | var req = { 148 | method: 'PUT', 149 | query: {}, 150 | body: JSON.stringify(newdoc), 151 | userCtx: { name: "user" } 152 | } 153 | 154 | test("deprecation update", function (t) { 155 | var res = pkg(doc, req) 156 | t.same(res[1], '{"ok":"updated package"}') 157 | t.same(res[0].versions, newdoc.versions) 158 | t.end() 159 | }) 160 | -------------------------------------------------------------------------------- /test/pkg-update-hoodie.js: -------------------------------------------------------------------------------- 1 | if (process.version.match(/^v[0-9][0-9]\./)) { 2 | console.log('1..0 # monkeypatching natives stopped working in node v10') 3 | process.exit(0) 4 | } 5 | var test = require("tap").test 6 | 7 | var mod = require("../registry/modules.js") 8 | Object.keys(mod).forEach(function (m) { 9 | process.binding('natives')[m] = mod[m] 10 | }) 11 | 12 | process.env.DEPLOY_VERSION = 'testing' 13 | var pkg = require("../registry/app.js").updates.package 14 | 15 | var doc = require("./fixtures/hoodie-old.json") 16 | var old = JSON.parse(JSON.stringify(doc)) 17 | 18 | var put = require("./fixtures/hoodie-new.json") 19 | 20 | var req = { 21 | method: 'PUT', 22 | query: { tag: "latest" }, 23 | body: JSON.stringify(put), 24 | userCtx: { name: "third", roles: [] } 25 | } 26 | 27 | var vdu = require("../registry/app.js").validate_doc_update 28 | 29 | test("new hoodie version", function (t) { 30 | var res = pkg(doc, req) 31 | t.same(doc['dist-tags'].latest, '1.0.10') 32 | try { 33 | vdu(res[0], old, req.userCtx) 34 | } catch (er) { 35 | t.fail("should not get error") 36 | console.error(er) 37 | } 38 | t.end() 39 | }) 40 | -------------------------------------------------------------------------------- /test/pkg-update-metadata.js: -------------------------------------------------------------------------------- 1 | if (process.version.match(/^v[0-9][0-9]\./)) { 2 | console.log('1..0 # monkeypatching natives stopped working in node v10') 3 | process.exit(0) 4 | } 5 | var test = require("tap").test 6 | 7 | var mod = require("../registry/modules.js") 8 | Object.keys(mod).forEach(function (m) { 9 | process.binding('natives')[m] = mod[m] 10 | }) 11 | 12 | process.env.DEPLOY_VERSION = 'testing' 13 | var pkg = require("../registry/app.js").updates.metadata 14 | 15 | var doc = require("./fixtures/meta-goog.json") 16 | var old = JSON.parse(JSON.stringify(doc)) 17 | 18 | var put = require("./fixtures/meta-goog-put.json") 19 | 20 | var reqFail = { 21 | method: 'PUT', 22 | query: {}, 23 | body: JSON.stringify(put), 24 | userCtx: { name: "testuser", roles: [] } 25 | } 26 | 27 | var reqPass = { 28 | method: 'PUT', 29 | query: {}, 30 | body: JSON.stringify(put), 31 | userCtx: { name: "third", roles: [] } 32 | } 33 | 34 | var vdu = require("../registry/app.js").validate_doc_update 35 | 36 | test("new googalytics description by non-maintainer", function (t) { 37 | var res = pkg(doc, reqFail) 38 | t.same(res[0].users, put.users) 39 | try { 40 | vdu(res[0], old, reqFail.userCtx) 41 | } catch (er) { 42 | t.fail(er.message || er.stack || er.forbidden || er) 43 | console.error("FAIL: " + er.forbidden) 44 | } 45 | t.end() 46 | }) 47 | 48 | test("new googalytics description by maintainer", function (t) { 49 | var res = pkg(doc, reqPass) 50 | t.same(doc['dist-tags'].latest, '0.0.1') 51 | t.same(doc.description, 'A totally-outdated-and-should-be-removed Google Analytics API for Node projects') 52 | try { 53 | vdu(res[0], old, reqPass.userCtx) 54 | } catch (er) { 55 | t.fail("should not get error") 56 | console.error(er) 57 | } 58 | t.end() 59 | }) 60 | -------------------------------------------------------------------------------- /test/pkg-update-star-nopt.js: -------------------------------------------------------------------------------- 1 | if (process.version.match(/^v[0-9][0-9]\./)) { 2 | console.log('1..0 # monkeypatching natives stopped working in node v10') 3 | process.exit(0) 4 | } 5 | var test = require("tap").test 6 | 7 | var mod = require("../registry/modules.js") 8 | Object.keys(mod).forEach(function (m) { 9 | process.binding('natives')[m] = mod[m] 10 | }) 11 | 12 | process.env.DEPLOY_VERSION = 'testing' 13 | var pkg = require("../registry/app.js").updates.package 14 | var star = require("../registry/app.js").updates.star 15 | var unstar = require("../registry/app.js").updates.unstar 16 | 17 | var doc = require("./fixtures/star-nopt.json") 18 | var oriUsers = doc.users 19 | var old = JSON.parse(JSON.stringify(doc)) 20 | 21 | var put = require("./fixtures/star-nopt-put.json") 22 | 23 | var req = { 24 | method: 'PUT', 25 | query: {}, 26 | body: JSON.stringify(put), 27 | userCtx: { name: "testuser", roles: [] } 28 | } 29 | 30 | var vdu = require("../registry/app.js").validate_doc_update 31 | 32 | test("new yui version", function (t) { 33 | var res = pkg(doc, req) 34 | t.same(res[0].users, put.users) 35 | try { 36 | vdu(res[0], old, req.userCtx) 37 | } catch (er) { 38 | t.fail(er.message || er.stack || er.forbidden || er) 39 | console.error("FAIL: " + er.forbidden) 40 | } 41 | t.end() 42 | }) 43 | 44 | test("atomic put for star", function (t) { 45 | var req = { 46 | method: 'PUT', 47 | query: {}, 48 | body: '"testuser"', 49 | userCtx: { name: 'testuser', roles: [] } 50 | } 51 | 52 | var res = star(doc, req) 53 | t.same(res[0].users, put.users) 54 | try { 55 | vdu(res[0], old, req.userCtx) 56 | } catch (er) { 57 | t.fail(er.message || er.stack || er.forbidden || er) 58 | console.error("FAIL: " + er.forbidden) 59 | } 60 | t.end() 61 | }) 62 | 63 | test("atomic put for unstar", function (t) { 64 | var req = { 65 | method: 'PUT', 66 | query: {}, 67 | body: '"testuser"', 68 | userCtx: { name: 'testuser', roles: [] } 69 | } 70 | 71 | var res = unstar(doc, req) 72 | t.same(res[0].users, oriUsers) 73 | try { 74 | vdu(res[0], old, req.userCtx) 75 | } catch (er) { 76 | t.fail(er.message || er.stack || er.forbidden || er) 77 | console.error("FAIL: " + er.forbidden) 78 | } 79 | t.end() 80 | }) 81 | -------------------------------------------------------------------------------- /test/pkg-update-yui-error.js: -------------------------------------------------------------------------------- 1 | if (process.version.match(/^v[0-9][0-9]\./)) { 2 | console.log('1..0 # monkeypatching natives stopped working in node v10') 3 | process.exit(0) 4 | } 5 | var test = require("tap").test 6 | 7 | var mod = require("../registry/modules.js") 8 | Object.keys(mod).forEach(function (m) { 9 | process.binding('natives')[m] = mod[m] 10 | }) 11 | 12 | process.env.DEPLOY_VERSION = 'testing' 13 | var pkg = require("../registry/app.js").updates.package 14 | 15 | var doc = require("./fixtures/yui-old.json") 16 | var old = JSON.parse(JSON.stringify(doc)) 17 | 18 | var put = require("./fixtures/yui-new.json") 19 | 20 | var req = { 21 | method: 'PUT', 22 | query: {}, 23 | body: JSON.stringify(put), 24 | userCtx: { name: "ezequiel", roles: [] } 25 | } 26 | 27 | var vdu = require("../registry/app.js").validate_doc_update 28 | 29 | test("new yui version", function (t) { 30 | var res = pkg(doc, req) 31 | t.same(doc.versions['3.10.0-pr1'], old.versions['3.10.0-pr1']) 32 | try { 33 | vdu(res[0], old, req.userCtx) 34 | } catch (er) { 35 | t.fail("should not get error") 36 | console.error(er) 37 | } 38 | t.end() 39 | }) 40 | -------------------------------------------------------------------------------- /test/vdu-auth.js: -------------------------------------------------------------------------------- 1 | if (process.version.match(/^v[0-9][0-9]\./)) { 2 | console.log('1..0 # monkeypatching natives stopped working in node v10') 3 | process.exit(0) 4 | } 5 | 6 | var fs = require("fs") 7 | var cases = {} 8 | fs.readdirSync(__dirname + "/fixtures/vdu-auth/").forEach(function(d) { 9 | var m = d.match(/^([0-9]+)-(old|new|throw|user|db)\.json$/) 10 | if (!m) return; 11 | var n = m[1] 12 | if (process.argv[2] && n !== process.argv[2]) return 13 | var c = cases[n] = cases[n] || {} 14 | var t = m[2] 15 | c[t] = require("./fixtures/vdu-auth/" + d) 16 | }) 17 | 18 | var mod = require("../registry/modules.js") 19 | Object.keys(mod).forEach(function (m) { 20 | process.binding('natives')[m] = mod[m] 21 | }) 22 | 23 | process.env.DEPLOY_VERSION = 'testing' 24 | var vdu = require("../registry/_auth.js").validate_doc_update 25 | 26 | var test = require("tap").test 27 | 28 | for (var i in cases) (function(i) { 29 | test("vdu test case " + i, function (t) { 30 | var c = cases[i] 31 | var threw = true 32 | try { 33 | vdu(c.new, c.old, c.user, c.db) 34 | threw = false 35 | } catch (er) { 36 | if (!er.forbidden) 37 | throw er 38 | 39 | if (c.throw) 40 | t.same(er, c.throw, "got expected error") 41 | else { 42 | t.notOk(er, JSON.stringify(er)) 43 | } 44 | } finally { 45 | if (c.throw) 46 | t.ok(threw, "Expected throw:\n" + JSON.stringify(c.throw)) 47 | else if (threw) 48 | t.notOk(threw, "should not throw") 49 | } 50 | t.end() 51 | }) 52 | })(i) 53 | -------------------------------------------------------------------------------- /test/vdu.js: -------------------------------------------------------------------------------- 1 | if (process.version.match(/^v[0-9][0-9]\./)) { 2 | console.log('1..0 # monkeypatching natives stopped working in node v10') 3 | process.exit(0) 4 | } 5 | 6 | var fs = require("fs") 7 | var cases = {} 8 | fs.readdirSync(__dirname + "/fixtures/vdu/").forEach(function(d) { 9 | var m = d.match(/^([0-9]+)-(old|new|throw|user|db)\.json$/) 10 | if (!m) return; 11 | var n = m[1] 12 | if (process.argv[2] && n !== process.argv[2]) return 13 | var c = cases[n] = cases[n] || {} 14 | var t = m[2] 15 | c[t] = require("./fixtures/vdu/" + d) 16 | }) 17 | 18 | var mod = require("../registry/modules.js") 19 | Object.keys(mod).forEach(function (m) { 20 | process.binding('natives')[m] = mod[m] 21 | }) 22 | 23 | process.env.DEPLOY_VERSION = 'testing' 24 | var vdu = require("../registry/app.js").validate_doc_update 25 | 26 | var test = require("tap").test 27 | 28 | for (var i in cases) (function(i) { 29 | test("vdu test case " + i, function (t) { 30 | var c = cases[i] 31 | var threw = true 32 | try { 33 | vdu(c.new, c.old, c.user, c.db) 34 | threw = false 35 | } catch (er) { 36 | if (er.stack) { 37 | // *probably* not what we wanted. 38 | console.error(er.stack) 39 | } 40 | if (c.throw) 41 | t.same(er, c.throw, "got expected error") 42 | else { 43 | t.notOk(er, JSON.stringify(er)) 44 | } 45 | } finally { 46 | if (c.throw) 47 | t.ok(threw, "Expected throw:\n" + JSON.stringify(c.throw)) 48 | else 49 | t.notOk(threw, "should not throw") 50 | } 51 | t.end() 52 | }) 53 | })(i) 54 | -------------------------------------------------------------------------------- /test/zz-teardown.js: -------------------------------------------------------------------------------- 1 | // kill the couchdb process that's running as a detached child process 2 | // started by the 00-setup.js test 3 | 4 | var fs = require('fs') 5 | var rimraf = require('rimraf') 6 | var test = require('tap').test 7 | var path = require('path') 8 | var pidfile = path.resolve(__dirname, 'fixtures', 'pid') 9 | var _users = path.resolve(__dirname, 'fixtures', '_users.couch') 10 | var db = path.resolve(__dirname, 'fixtures', 'registry.couch') 11 | var log = path.resolve(__dirname, 'fixtures', 'couch.log') 12 | var repl = path.resolve(__dirname, 'fixtures', '_replicator.couch') 13 | var rdes = path.resolve(__dirname, 'fixtures', '.registry_design') 14 | var udes = path.resolve(__dirname, 'fixtures', '._users_design') 15 | var dotDelete = path.resolve(__dirname, 'fixtures', '.delete') 16 | var urifile = path.resolve(__dirname, 'fixtures', 'couch.uri') 17 | const cache = path.resolve(__dirname, 'fixtures', 'test-cache') 18 | 19 | if (process.env.TRAVIS) { 20 | test('nocleanup', function (t) { 21 | t.pass('No cleanup on travis') 22 | t.end() 23 | }) 24 | } else { 25 | test('cleanup', function (t) { 26 | try { 27 | var pid = fs.readFileSync(pidfile) 28 | } catch (er) {} 29 | 30 | if (pid) { 31 | try { process.kill(pid) } catch (er) { 32 | // ok if already killed 33 | t.equal(er.code, 'ESRCH') 34 | } 35 | } 36 | var files = [ pidfile, repl, log, _users, db, rdes, dotDelete, urifile, cache ] 37 | if (!process.env.TRAVIS) { 38 | files.push(udes); 39 | } 40 | files.forEach(function(file) { 41 | rimraf.sync(file) 42 | }) 43 | 44 | t.pass('couch is no more') 45 | t.end() 46 | }) 47 | } 48 | --------------------------------------------------------------------------------