diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index 5629b6eccd358826722518792dd4e31d9e67b0ee..0000000000000000000000000000000000000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,5 +0,0 @@ -## v7 (2012-03-27) - -* remove build asset caching -* prevent installation of devDependencies -* add warning if no nodejs version specified diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 26def27f1a49005e6c0c56067bb6c9c9cc9bfb75..0000000000000000000000000000000000000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,74 +0,0 @@ -## Testing buildpack changes using Anvil - -[Anvil](https://github.com/ddollar/anvil) is a generic build server for Heroku. - -``` -gem install anvil-cli -``` - -The [heroku-anvil CLI plugin](https://github.com/ddollar/heroku-anvil) is a wrapper for anvil. - -``` -heroku plugins:install https://github.com/ddollar/heroku-anvil -``` - -The [ddollar/test buildpack](https://github.com/ddollar/buildpack-test) is for testing things: it runs `bin/test` on your app. - -``` -heroku build -b ddollar/test # -b can also point to a local directory -``` - -## Compiling new versions of node and npm using Vulcan - -Install [vulcan](https://github.com/heroku/vulcan) and create your own build server. Use any -app name you want and vulcan will remember it in a `~/.vulcan` config file. - -``` -gem install vulcan -vulcan create builder-bob -``` - -Store your S3 credentials in `~/.aws/` - -``` -mkdir -p ~/.aws -echo 'YOUR_AWS_KEY' > ~/.aws/key-nodejs.access -echo 'YOUR_AWS_SECRET' > ~/.aws/key-nodejs.secret -``` - -Add a credentials exporter to your `.bash_profile` or `.bashrc` - -``` -setup_nodejs_env () { - export AWS_ID=$(cat ~/.aws/key-nodejs.access) - export AWS_SECRET=$(cat ~/.aws/key-nodejs.secret) - export S3_BUCKET="heroku-buildpack-nodejs" -} -``` - -Build: - -``` -setup_nodejs_env -support/package_nodejs -support/package_npm -``` - -## Publishing buildpack updates - -``` -heroku plugins:install https://github.com/heroku/heroku-buildpacks - -cd heroku-buildpack-nodejs -git checkout master -heroku buildpacks:publish heroku/nodejs -``` - -- Email [dos@heroku.com](mailto:dos@heroku.com) if changes are significant. -- Add a [changelog item](https://devcenter.heroku.com/admin/changelog_items/new). -- Update [Node Devcenter articles](https://devcenter.heroku.com/admin/articles/owned) as necessary. - -## Keeping up with the Nodeses - -- Run `npm info npm version` to find out the latest available version of npm. -- Follow [@nodejs](https://twitter.com/nodejs) and [@npmjs](https://twitter.com/npmjs) on Twitter. \ No newline at end of file diff --git a/LICENSE b/LICENSE index ad04dc17147a632b77666bd48a716606242bcb1d..4972b450520a3517df1ceb17cc99a5ddc5ebf13b 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License: -Copyright (C) 2012 Heroku, Inc. +Copyright (C) 2012-2013 Heroku, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/README.md b/README.md index a509773155d97758155b014e3569c939a3a803da..5dbe7c42a421a6ef2ee5cb0ffcd90d493ede68f0 100644 --- a/README.md +++ b/README.md @@ -1,68 +1,59 @@ Heroku Buildpack for Node.js ============================ -This is a [Heroku buildpack](http://devcenter.heroku.com/articles/buildpacks) for Node.js apps. +This is the official [Heroku buildpack](http://devcenter.heroku.com/articles/buildpacks) for Node.js apps. If you fork this repository, please **update this README** to explain what your fork does and why it's special. -The buildpack will detect your app as Node.js if it has a `package.json` file in the root. It will use npm to install your dependencies, and vendors a version of the Node.js runtime into your slug. -Example Usage -------------- +How it Works +------------ - $ ls - Procfile package.json web.js - - $ heroku create - - $ git push heroku master - ... - -----> Heroku receiving push - -----> Fetching custom buildpack - -----> Node.js app detected - -----> Vendoring node 0.4.7 - -----> Installing dependencies with npm 1.0.8 - express@2.1.0 ./node_modules/express - ├── mime@1.2.2 - ├── qs@0.3.1 - └── connect@1.6.2 - Dependencies installed - -Node.js and npm versions ------------------------- - -You can specify the versions of Node.js and npm your application requires using `package.json` - -```json -{ - "name": "myapp", - "version": "0.0.1", - "engines": { - "node": "~0.10.13", - "npm": "~1.3.2" - } -} -``` +Here's an overview of what this buildpack does: -To list the available versions of Node.js and npm, see these manifests: +- Uses the [semver.io](http://semver.io) webservice to find the latest version of node that satisfies the [engines.node semver range](https://npmjs.org/doc/json.html#engines) in your package.json. +- Allows any recent version of node to be used, including [pre-release versions](http://semver.io/node.json). +- Uses an [S3 caching proxy](https://github.com/heroku/s3pository#readme) of nodejs.org for faster downloads of the node binary. +- Discourages use of dangerous semver ranges like `*` and `>0.10`. +- Uses the version of `npm` that comes bundled with `node`. +- Puts `node` and `npm` on the `PATH` so they can be executed with [heroku run](https://devcenter.heroku.com/articles/one-off-dynos#an-example-one-off-dyno). +- Caches the `node_modules` directory across builds for fast deploys. +- Doesn't use the cache if `node_modules` is checked into version control. +- Runs `npm rebuild` if `node_modules` is checked into version control. +- Always runs `npm install` to ensure [npm script hooks](https://npmjs.org/doc/misc/npm-scripts.html) are executed. +- Always runs `npm prune` after restoring cached modules to ensure cleanup of unused dependencies. + +For more technical details, see the [heavily-commented compile script](https://github.com/heroku/heroku-buildpack-nodejs/blob/master/bin/compile). -- [heroku-buildpack-nodejs.s3.amazonaws.com/manifest.nodejs](http://heroku-buildpack-nodejs.s3.amazonaws.com/manifest.nodejs) -- [heroku-buildpack-nodejs.s3.amazonaws.com/manifest.npm](http://heroku-buildpack-nodejs.s3.amazonaws.com/manifest.npm) Documentation ------------- -For more information about buildpacks and Node.js, see these Dev Center articles: +For more information about using Node.js and buildpacks on Heroku, see these Dev Center articles: -- [Getting Started with Node.js on Heroku](https://devcenter.heroku.com/articles/nodejs) - [Heroku Node.js Support](https://devcenter.heroku.com/articles/nodejs-support) +- [Getting Started with Node.js on Heroku](https://devcenter.heroku.com/articles/nodejs) - [Buildpacks](https://devcenter.heroku.com/articles/buildpacks) - [Buildpack API](https://devcenter.heroku.com/articles/buildpack-api) + +Legacy Compatibility +-------------------- + +For most Node.js apps this buildpack should work just fine. If, however, you're unable to deploy using this new version of the buildpack, you can get your app working again by using the legacy branch: + +``` +heroku config:set BUILDPACK_URL=https://github.com/heroku/heroku-buildpack-nodejs#legacy -a my-app +git commit -am "empty" --allow-empty # force a git commit +git push heroku master +``` + +Then please open a support ticket at [help.heroku.com](https://help.heroku.com/) so we can diagnose and get your app running on the default buildpack. + Hacking ------- To make changes to this buildpack, fork it on Github. Push up changes to your fork, then create a new Heroku app to test it, or configure an existing app to use your buildpack: -```sh +``` # Create a new Heroku app that uses your buildpack heroku create --buildpack @@ -73,4 +64,26 @@ heroku config:set BUILDPACK_URL= heroku config:set BUILDPACK_URL=#your-branch ``` -For more detailed information about testing buildpacks, see [CONTRIBUTING.md](CONTRIBUTING.md) \ No newline at end of file +For more detailed information about testing buildpacks, see [CONTRIBUTING.md](CONTRIBUTING.md) + + +Testing +------- + +[Anvil](https://github.com/ddollar/anvil) is a generic build server for Heroku. + +``` +gem install anvil-cli +``` + +The [heroku-anvil CLI plugin](https://github.com/ddollar/heroku-anvil) is a wrapper for anvil. + +``` +heroku plugins:install https://github.com/ddollar/heroku-anvil +``` + +The [ddollar/test](https://github.com/ddollar/buildpack-test) buildpack runs `bin/test` on your app/buildpack. + +``` +heroku build -b ddollar/test # -b can also point to a local directory +``` diff --git a/bin/common.sh b/bin/common.sh new file mode 100644 index 0000000000000000000000000000000000000000..49b790a5563bdb5f52010d399523006dc8c85578 --- /dev/null +++ b/bin/common.sh @@ -0,0 +1,30 @@ +error() { + echo " ! $*" >&2 + exit 1 +} + +status() { + echo "-----> $*" +} + +protip() { + echo + echo "PRO TIP: $*" | indent + echo "See https://devcenter.heroku.com/articles/nodejs-support" | indent + echo +} + +# sed -l basically makes sed replace and buffer through stdin to stdout +# so you get updates while the command runs and dont wait for the end +# e.g. npm install | indent +indent() { + c='s/^/ /' + case $(uname) in + Darwin) sed -l "$c";; # mac/bsd sed: -l buffers on line boundaries + *) sed -u "$c";; # unix/gnu sed: -u unbuffered (arbitrary) chunks of data + esac +} + +cat_npm_debug_log() { + test -f $build_dir/npm-debug.log && cat $build_dir/npm-debug.log +} diff --git a/bin/compile b/bin/compile index f91d1c2d9bbcafa125c3de00620286c69dc2b1e9..d14ba9ce0387c9dc613aea046bf09ef1cc78cf87 100755 --- a/bin/compile +++ b/bin/compile @@ -1,185 +1,98 @@ #!/usr/bin/env bash -# bin/compile - -# fail fast -set -e - -# debug -# set -x - -# clean up leaking environment -unset GIT_DIR - -# config -SCONS_VERSION="1.2.0" -S3_BUCKET="heroku-buildpack-nodejs" - -# parse and derive params -BUILD_DIR=$1 -CACHE_DIR=$2 -LP_DIR=`cd $(dirname $0); cd ..; pwd` - -function error() { - echo " ! $*" >&2 - exit 1 -} - -function mktmpdir() { - dir=$(mktemp -t node-$1-XXXX) - rm -rf $dir - mkdir -p $dir - echo $dir -} - -function indent() { - c='s/^/ /' - case $(uname) in - Darwin) sed -l "$c";; - *) sed -u "$c";; - esac -} - -function run_npm() { - command="$1" - - cd $BUILD_DIR - HOME="$BUILD_DIR" $VENDORED_NODE/bin/node $VENDORED_NPM/cli.js $command 2>&1 | indent - - if [ "${PIPESTATUS[*]}" != "0 0" ]; then - echo " ! Failed to $command dependencies with npm" - exit 1 - fi -} - -function manifest_versions() { - curl "http://${S3_BUCKET}.s3.amazonaws.com/manifest.${1}" -s -o - | tr -s '\n' ' ' -} - -function resolve_version() { - available_versions="$1" - requested_version="$2" - default_version="$3" - - args="" - for version in $available_versions; do args="${args} -v \"${version}\""; done - - if [ "$2" == "" ]; then - args="${args} -r \"${default_version}\""; - else - args="${args} -r \"${requested_version}\""; - fi - - evaluated_versions=$(eval $bootstrap_node/bin/node $LP_DIR/vendor/node-semver/bin/semver ${args} || echo "") - echo "$evaluated_versions" | tail -n 1 -} - -function package_engine_version() { - version=$(cat $BUILD_DIR/package.json | $bootstrap_node/bin/node $LP_DIR/vendor/json/json engines.$1 2>/dev/null) - if [ $? == 0 ]; then - echo $version | sed -e 's/\([<>=]\) /\1/g' - fi -} - -function package_resolve_version() { - engine="$1" - resolved_version=$(resolve_version "${engine_versions[$engine]}" "${engine_requests[$engine]}" "${engine_defaults[$engine]}") - - if [ "${resolved_version}" == "" ]; then - error "Requested engine $engine version ${engine_requests[$engine]} does not match available versions: ${engine_versions[$engine]}" - else - echo $resolved_version - fi -} - -function package_download() { - engine="$1" - version="$2" - location="$3" - - mkdir -p $location - package="http://${S3_BUCKET}.s3.amazonaws.com/$engine-$version.tgz" - curl $package -s -o - | tar xzf - -C $location -} - -function cat_npm_debug_log() { - if [ -f $BUILD_DIR/npm-debug.log ]; then - cat $BUILD_DIR/npm-debug.log - fi -} - -trap cat_npm_debug_log EXIT - -bootstrap_node=$(mktmpdir bootstrap_node) -package_download "nodejs" "0.4.7" $bootstrap_node - -# make some associative arrays -declare -A engine_versions -declare -A engine_defaults -declare -A engine_requests - -engine_defaults["node"]="0.10.x" -engine_defaults["npm"]="1.3.x" - -engine_versions["node"]=$(manifest_versions "nodejs") -engine_requests["node"]=$(package_engine_version "node") - -engine_versions["npm"]=$(manifest_versions "npm") -engine_requests["npm"]=$(package_engine_version "npm") - -echo "-----> Resolving engine versions" - -# add a warning if no version of node specified -if [ "${engine_requests["node"]}" == "" ]; then - echo - echo "WARNING: No version of Node.js specified in package.json, see:" | indent - echo "https://devcenter.heroku.com/articles/nodejs-support#versions" | indent - echo + +set -e # fail fast +set -o pipefail # don't ignore exit codes when piping output +# set -x # enable debugging + +# Configure directories +build_dir=$1 +cache_dir=$2 +bp_dir=$(cd $(dirname $0); cd ..; pwd) + +# Load some convenience functions like status(), echo(), and indent() +source $bp_dir/bin/common.sh + +# Output npm debug info on error +trap cat_npm_debug_log ERR + +# Look in package.json's engines.node field for a semver range +semver_range=$(cat $build_dir/package.json | $bp_dir/vendor/jq -r .engines.node) + +# Resolve node version using semver.io +node_version=$(curl --silent --get --data-urlencode "range=${semver_range}" http://semver.io/node/resolve) + +# Recommend using semver ranges in a safe manner +if [ "$semver_range" == "null" ]; then + protip "Specify a node version in package.json" + semver_range="" +elif [ "$semver_range" == "*" ]; then + protip "Avoid using semver ranges like '*' in engines.node" +elif [ ${semver_range:0:1} == ">" ]; then + protip "Avoid using semver ranges starting with '>' in engines.node" +fi + +# Output info about requested range and resolved node version +if [ "$semver_range" == "" ]; then + status "Defaulting to latest stable node: $node_version" +else + status "Requested node range: $semver_range" + status "Resolved node version: $node_version" +fi + +# Download node from Heroku's S3 mirror of nodejs.org/dist +status "Downloading and installing node" +node_url="http://s3pository.heroku.com/node/v$node_version/node-v$node_version-linux-x64.tar.gz" +curl $node_url -s -o - | tar xzf - -C $build_dir + +# Move node into ./vendor and make it executable +mkdir -p $build_dir/vendor +mv $build_dir/node-v$node_version-linux-x64 $build_dir/vendor/node +chmod +x $build_dir/vendor/node/bin/* +PATH=$PATH:$build_dir/vendor/node/bin + +# Run subsequent node/npm commands from the build path +cd $build_dir + +# If node_modules directory is checked into source control then +# rebuild any native deps. Otherwise, restore from the build cache. +if test -d $build_dir/node_modules; then + status "Using existing node_modules directory" + status "Rebuilding any native dependencies" + npm rebuild 2>&1 | indent +elif test -d $cache_dir/node_modules; then + status "Restoring node_modules from cache" + cp -r $cache_dir/node_modules $build_dir/ fi -NODE_VERSION=$(package_resolve_version "node") -echo "Using Node.js version: ${NODE_VERSION}" | indent - -NPM_VERSION=$(package_resolve_version "npm") -echo "Using npm version: ${NPM_VERSION}" | indent - -# cache directories -CACHE_STORE_DIR="$CACHE_DIR/node_modules/$NODE_VERSION/$NPM_VERSION" -CACHE_TARGET_DIR="$BUILD_DIR/node_modules" - -# s3 packages -NODE_PACKAGE="http://${S3_BUCKET}.s3.amazonaws.com/nodejs-${NODE_VERSION}.tgz" -NPM_PACKAGE="http://${S3_BUCKET}.s3.amazonaws.com/npm-${NPM_VERSION}.tgz" -SCONS_PACKAGE="http://${S3_BUCKET}.s3.amazonaws.com/scons-${SCONS_VERSION}.tgz" - -# vendor directories -VENDORED_NODE="$(mktmpdir node)" -VENDORED_NPM="$(mktmpdir npm)" -VENDORED_SCONS="$(mktmpdir scons)" - -# download and unpack packages -echo "-----> Fetching Node.js binaries" -package_download "nodejs" "${NODE_VERSION}" "${VENDORED_NODE}" -package_download "npm" "${NPM_VERSION}" "${VENDORED_NPM}" -package_download "scons" "${SCONS_VERSION}" "${VENDORED_SCONS}" - -# vendor node into the slug -PATH="$BUILD_DIR/bin:$PATH" -echo "-----> Vendoring node into slug" -mkdir -p "$BUILD_DIR/bin" -cp "$VENDORED_NODE/bin/node" "$BUILD_DIR/bin/node" - -# setting up paths for building -PATH="$VENDORED_SCONS:$VENDORED_NODE/bin:$PATH" -INCLUDE_PATH="$VENDORED_NODE/include" -export CPATH="$INCLUDE_PATH:$CPATH" -export CPPPATH="$INCLUDE_PATH:$CPPPATH" - -# install dependencies with npm -echo "-----> Installing dependencies with npm" -run_npm "install --production" -run_npm "rebuild" -echo "Dependencies installed" | indent - -echo "-----> Building runtime environment" -mkdir -p $BUILD_DIR/.profile.d -echo "export PATH=\"\$HOME/bin:\$HOME/node_modules/.bin:\$PATH\"" > $BUILD_DIR/.profile.d/nodejs.sh +# Make npm output to STDOUT instead of its default STDERR +status "Installing dependencies" +npm install --production 2>&1 | indent + +status "Pruning unused dependencies" +npm prune 2>&1 | indent + +status "Caching node_modules directory for future builds" +rm -rf $cache_dir +mkdir -p $cache_dir +test -d $build_dir/node_modules && cp -r $build_dir/node_modules $cache_dir/ + +status "Cleaning up node-gyp and npm artifacts" +rm -rf "$build_dir/.node-gyp" +rm -rf "$build_dir/.npm" + +# Update the PATH +status "Building runtime environment" +mkdir -p $build_dir/.profile.d +echo "export PATH=\"\$HOME/vendor/node/bin:\$HOME/bin:\$HOME/node_modules/.bin:\$PATH\"" > $build_dir/.profile.d/nodejs.sh + +# Post package.json to nomnom service +# Use a subshell so failures won't break the build. +( + curl \ + --data @$build_dir/package.json \ + --fail \ + --silent \ + --request POST \ + --header "content-type: application/json" \ + https://nomnom.heroku.com/?request_id=$REQUEST_ID +) & diff --git a/bin/release b/bin/release deleted file mode 100755 index 133982fd7e63652c3fcea474f9d5ed64d57606c4..0000000000000000000000000000000000000000 --- a/bin/release +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash -# bin/release - -cat <'" + assertCaptured "Requested node range: >" + assertCaptured "Resolved node version: 0.10." + assertCapturedSuccess } -testNothingCached() { - cache=$(mktmpdir) - compile "package-json-version" $cache +testRangeWithSpace() { + compile "range-with-space" + assertCaptured "Requested node range: >= 0.8.x" + assertCaptured "Resolved node version: 0.10." + assertCapturedSuccess +} + +testStableVersion() { + compile "stable-node" + assertNotCaptured "PRO TIP: Avoid using semver" + assertNotCaptured "PRO TIP: Specify" + assertCaptured "Resolved node version" + assertCapturedSuccess +} + +testUnstableVersion() { + compile "unstable-version" + assertCaptured "Requested node range: >0.11.0" + assertCaptured "Resolved node version: 0.11." assertCapturedSuccess - assertEquals "0" "$(ls -1 $cache | wc -l)" } testProfileCreated() { - compile "package-json-version" + compile "stable-node" assertCaptured "Building runtime environment" - assertFile "export PATH=\"\$HOME/bin:\$HOME/node_modules/.bin:\$PATH\"" ".profile.d/nodejs.sh" + assertFile "export PATH=\"\$HOME/vendor/node/bin:\$HOME/bin:\$HOME/node_modules/.bin:\$PATH\"" ".profile.d/nodejs.sh" + assertCapturedSuccess +} + +testInvalidDependency() { + compile "invalid-dependency" + assertCaptured "not in the npm registry" + assertCapturedError 1 "" +} + +testNodeModulesCached() { + cache=$(mktmpdir) + compile "caching" $cache + assertCaptured "Caching node" + assertEquals "1" "$(ls -1 $cache/ | wc -l)" +} + +testModulesCheckedIn() { + compile "modules-checked-in" + assertCaptured "Using existing node_modules directory" + assertCaptured "Rebuilding any native dependencies" assertCapturedSuccess } -## utils ######################################## +# Pending Tests + +# testNodeBinariesAddedToPath() { +# } + +# testNodeModulesRestoredFromCache() { +# } + +# TODO: Figure out how to test stuff like script hooks +# when restoring node_modules from cache +# testScriptHooks() { +# compile "script-hooks" +# assertCaptured "trigger script hooks" +# assertCaptured "preinstall hook message" +# assertCapturedSuccess +# } + +# testWithoutScriptHooks() { +# compile "no-script-hooks" +# assertNotCaptured "trigger script hooks" +# assertCapturedSuccess +# } + +# testInvalidVersion() { +# compile "invalid-node-version" +# assertCapturedError 1 "not found among available versions" +# } + +# Utils pushd $(dirname 0) >/dev/null -BASE=$(pwd) +bp_dir=$(pwd) popd >/dev/null -source ${BASE}/vendor/test-utils/test-utils +source ${bp_dir}/vendor/test-utils/test-utils mktmpdir() { dir=$(mktemp -t testXXXXX) @@ -70,19 +128,19 @@ mktmpdir() { } detect() { - capture ${BASE}/bin/detect ${BASE}/test/$1 + capture ${bp_dir}/bin/detect ${bp_dir}/test/$1 } -COMPILE_DIR="" +compile_dir="" compile() { - COMPILE_DIR=$(mktmpdir) - cp -r ${BASE}/test/$1/* ${COMPILE_DIR}/ - capture ${BASE}/bin/compile ${COMPILE_DIR} $2 + compile_dir=$(mktmpdir) + cp -r ${bp_dir}/test/$1/* ${compile_dir}/ + capture ${bp_dir}/bin/compile ${compile_dir} ${2:-$(mktmpdir)} } assertFile() { - assertEquals "$1" "$(cat ${COMPILE_DIR}/$2)" + assertEquals "$1" "$(cat ${compile_dir}/$2)" } -source ${BASE}/vendor/shunit2/shunit2 +source ${bp_dir}/vendor/shunit2/shunit2 diff --git a/support/aws/hmac b/support/aws/hmac deleted file mode 100755 index 5aa074a0defbf57803f0ed34968dcc6109dcaeda..0000000000000000000000000000000000000000 --- a/support/aws/hmac +++ /dev/null @@ -1,79 +0,0 @@ -#!/bin/bash -# Implement HMAC functionality on top of the OpenSSL digest functions. -# licensed under the terms of the GNU GPL v2 -# Copyright 2007 Victor Lowther - -die() { - echo $* - exit 1 -} - -check_deps() { - local res=0 - while [ $# -ne 0 ]; do - which "${1}" >& /dev/null || { res=1; echo "${1} not found."; } - shift - done - (( res == 0 )) || die "aborting." -} - -# write a byte (passed as hex) to stdout -write_byte() { - # $1 = byte to write - printf "\\x$(printf "%x" ${1})" -} - -# make an hmac pad out of a key. -# this is not the most secure way of doing it, but it is -# the most expedient. -make_hmac_pad() { - # using key in file $1 and byte in $2, create the appropriate hmac pad - # Pad keys out to $3 bytes - # if key is longer than $3, use hash $4 to hash the key first. - local x y a size remainder oifs - (( remainder = ${3} )) - # in case someone else was messing with IFS. - for x in $(echo -n "${1}" | od -v -t u1 | cut -b 9-); - do - write_byte $((${x} ^ ${2})) - (( remainder -= 1 )) - done - for ((y=0; remainder - y ;y++)); do - write_byte $((0 ^ ${2})) - done -} - -# utility functions for making hmac pads -hmac_ipad() { - make_hmac_pad "${1}" 0x36 ${2} "${3}" -} - -hmac_opad() { - make_hmac_pad "${1}" 0x5c ${2} "${3}" -} - -# hmac something -do_hmac() { - # $1 = algo to use. Must be one that openssl knows about - # $2 = keyfile to use - # $3 = file to hash. uses stdin if none is given. - # accepts input on stdin, leaves it on stdout. - # Output is binary, if you want something else pipe it accordingly. - local blocklen keysize x - case "${1}" in - sha) blocklen=64 ;; - sha1) blocklen=64 ;; - md5) blocklen=64 ;; - md4) blocklen=64 ;; - sha256) blocklen=64 ;; - sha512) blocklen=128 ;; - *) die "Unknown hash ${1} passed to hmac!" ;; - esac - cat <(hmac_ipad ${2} ${blocklen} "${1}") "${3:--}" | openssl dgst "-${1}" -binary | \ - cat <(hmac_opad ${2} ${blocklen} "${1}") - | openssl dgst "-${1}" -binary -} - -[[ ${1} ]] || die "Must pass the name of the hash function to use to ${0}". - -check_deps od openssl -do_hmac "${@}" diff --git a/support/aws/s3 b/support/aws/s3 deleted file mode 100755 index a25290bb7704dc2ed0f35c104a28fbf4627ab1ca..0000000000000000000000000000000000000000 --- a/support/aws/s3 +++ /dev/null @@ -1,230 +0,0 @@ -#!/bin/bash -# basic amazon s3 operations -# Licensed under the terms of the GNU GPL v2 -# Copyright 2007 Victor Lowther - -set -e - -basedir="$( cd -P "$( dirname "$0" )" && pwd )" -PATH="$basedir:$PATH" - -# print a message and bail -die() { - echo $* - exit 1 -} - -# check to see if the variable name passed exists and holds a value. -# Die if it does not. -check_or_die() { - [[ ${!1} ]] || die "Environment variable ${1} is not set." -} - -# check to see if we have all the needed S3 variables defined. -# Bail if we do not. -check_s3() { - local sak x - for x in AWS_ID AWS_SECRET; do - check_or_die ${x}; - done - sak="$(echo -n $AWS_SECRET | wc -c)" - (( ${sak%%[!0-9 ]*} == 40 )) || \ - die "S3 Secret Access Key is not exactly 40 bytes long. Please fix it." -} -# check to see if our external dependencies exist -check_dep() { - local res=0 - while [[ $# -ne 0 ]]; do - which "${1}" >& /dev/null || { res=1; echo "${1} not found."; } - shift - done - (( res == 0 )) || die "aborting." -} - -check_deps() { - check_dep openssl date hmac cat grep curl - check_s3 -} - -urlenc() { - # $1 = string to url encode - # output is on stdout - # we don't urlencode everything, just enough stuff. - echo -n "${1}" | - sed 's/%/%25/g - s/ /%20/g - s/#/%23/g - s/\$/%24/g - s/\&/%26/g - s/+/%2b/g - s/,/%2c/g - s/:/%3a/g - s/;/%3b/g - s/?/%3f/g - s/@/%40/g - s/ /%09/g' -} - -xmldec() { - # no parameters. - # accept input on stdin, put it on stdout. - # patches accepted to get more stuff - sed 's/\"/\"/g - s/\&/\&/g - s/\<//g' -} - -## basic S3 functionality. x-amz-header functionality is not implemented. -# make an S3 signature string, which will be output on stdout. -s3_signature_string() { - # $1 = HTTP verb - # $2 = date string, must be in UTC - # $3 = bucket name, if any - # $4 = resource path, if any - # $5 = content md5, if any - # $6 = content MIME type, if any - # $7 = canonicalized headers, if any - # signature string will be output on stdout - local verr="Must pass a verb to s3_signature_string!" - local verb="${1:?verr}" - local bucket="${3}" - local resource="${4}" - local derr="Must pass a date to s3_signature_string!" - local date="${2:?derr}" - local mime="${6}" - local md5="${5}" - local headers="${7}" - printf "%s\n%s\n%s\n%s\n%s\n%s%s" \ - "${verb}" "${md5}" "${mime}" "${date}" \ - "${headers}" "${bucket}" "${resource}" | \ - hmac sha1 "${AWS_SECRET}" | openssl base64 -e -a -} - -# cheesy, but it is the best way to have multiple headers. -curl_headers() { - # each arg passed will be output on its own line - local parms=$# - for ((;$#;)); do - echo "header = \"${1}\"" - shift - done -} - -s3_curl() { - # invoke curl to do all the heavy HTTP lifting - # $1 = method (one of GET, PUT, or DELETE. HEAD is not handled yet.) - # $2 = remote bucket. - # $3 = remote name - # $4 = local name. - # $5 = mime type - local bucket remote date sig md5 arg inout headers - # header handling is kinda fugly, but it works. - bucket="${2:+/${2}}/" # slashify the bucket - remote="$(urlenc "${3}")" # if you don't, strange things may happen. - stdopts="--connect-timeout 10 --fail --silent" - mime="${5}" - [[ $CURL_S3_DEBUG == true ]] && stdopts="${stdopts} --show-error --fail" - case "${1}" in - GET) arg="-o" inout="${4:--}" # stdout if no $4 - headers[${#headers[@]}]="x-amz-acl: public-read" - ;; - PUT) [[ ${2} ]] || die "PUT can has bucket?" - if [[ ! ${3} ]]; then - arg="-X PUT" - headers[${#headers[@]}]="Content-Length: 0" - elif [[ -f ${4} ]]; then - md5="$(openssl dgst -md5 -binary "${4}"|openssl base64 -e -a)" - arg="-T" inout="${4}" - headers[${#headers[@]}]="x-amz-acl: public-read" - headers[${#headers[@]}]="Expect: 100-continue" - if [ "$mime" != "" ]; then - headers[${#headers[@]}]="Content-Type: $mime" - fi - else - die "Cannot write non-existing file ${4}" - fi - ;; - DELETE) arg="-X DELETE" - ;; - HEAD) arg="-I" ;; - *) die "Unknown verb ${1}. It probably would not have worked anyways." ;; - esac - date="$(TZ=UTC date '+%a, %e %b %Y %H:%M:%S %z')" - sig=$(s3_signature_string ${1} "${date}" "${bucket}" "${remote}" "${md5}" "${mime}" "x-amz-acl:public-read") - - headers[${#headers[@]}]="Authorization: AWS ${AWS_ID}:${sig}" - headers[${#headers[@]}]="Date: ${date}" - [[ ${md5} ]] && headers[${#headers[@]}]="Content-MD5: ${md5}" - curl ${arg} "${inout}" ${stdopts} -o - -K <(curl_headers "${headers[@]}") \ - "http://s3.amazonaws.com${bucket}${remote}" - return $? -} - -s3_put() { - # $1 = remote bucket to put it into - # $2 = remote name to put - # $3 = file to put. This must be present if $2 is. - # $4 = mime type - s3_curl PUT "${1}" "${2}" "${3:-${2}}" "${4}" - return $? -} - -s3_get() { - # $1 = bucket to get file from - # $2 = remote file to get - # $3 = local file to get into. Will be overwritten if it exists. - # If this contains a path, that path must exist before calling this. - s3_curl GET "${1}" "${2}" "${3:-${2}}" - return $? -} - -s3_test() { - # same args as s3_get, but uses the HEAD verb instead of the GET verb. - s3_curl HEAD "${1}" "${2}" >/dev/null - return $? -} - -# Hideously ugly, but it works well enough. -s3_buckets() { - s3_get |grep -o '[^>]*' |sed 's/<[^>]*>//g' |xmldec - return $? -} - -# this will only return the first thousand entries, alas -# Mabye some kind soul can fix this without writing an XML parser in bash? -# Also need to add xml entity handling. -s3_list() { - # $1 = bucket to list - [ "x${1}" == "x" ] && return 1 - s3_get "${1}" |grep -o '[^>]*' |sed 's/<[^>]*>//g'| xmldec - return $? -} - -s3_delete() { - # $1 = bucket to delete from - # $2 = item to delete - s3_curl DELETE "${1}" "${2}" - return $? -} - -# because this uses s3_list, it suffers from the same flaws. -s3_rmrf() { - # $1 = bucket to delete everything from - s3_list "${1}" | while read f; do - s3_delete "${1}" "${f}"; - done -} - -check_deps -case $1 in - put) shift; s3_put "$@" ;; - get) shift; s3_get "$@" ;; - rm) shift; s3_delete "$@" ;; - ls) shift; s3_list "$@" ;; - test) shift; s3_test "$@" ;; - buckets) s3_buckets ;; - rmrf) shift; s3_rmrf "$@" ;; - *) die "Unknown command ${1}." - ;; -esac diff --git a/support/manifest b/support/manifest deleted file mode 100755 index b4376989f8c8e3db669499fd2556569969b66138..0000000000000000000000000000000000000000 --- a/support/manifest +++ /dev/null @@ -1,44 +0,0 @@ -#!/bin/sh - -set -e - -manifest_type="$1" - -if [ "$manifest_type" == "" ]; then - echo "usage: $0 " - exit 1 -fi - -if [ "$AWS_ID" == "" ]; then - echo "must set AWS_ID" - exit 1 -fi - -if [ "$AWS_SECRET" == "" ]; then - echo "must set AWS_SECRET" - exit 1 -fi - -if [ "$S3_BUCKET" == "" ]; then - echo "must set S3_BUCKET" - exit 1 -fi - -basedir="$( cd -P "$( dirname "$0" )" && pwd )" - -# make a temp directory -tempdir="$( mktemp -t node_XXXX )" -rm -rf $tempdir -mkdir -p $tempdir -pushd $tempdir - -# generate manifest -$basedir/aws/s3 ls $S3_BUCKET \ - | grep "^${manifest_type}" \ - | sed -e "s/${manifest_type}-\([0-9.]*\)\\.tgz/\\1/" \ - | awk 'BEGIN {FS="."} {printf("%03d.%03d.%03d %s\n",$1,$2,$3,$0)}' | sort -r | cut -d" " -f2 \ - > manifest.${manifest_type} - -# upload manifest to s3 -$basedir/aws/s3 put $S3_BUCKET \ - manifest.${manifest_type} "" "text/plain" diff --git a/support/package_nodejs b/support/package_nodejs deleted file mode 100755 index 22f62cbf5e65a48dd7cca606beb82deb46c80e03..0000000000000000000000000000000000000000 --- a/support/package_nodejs +++ /dev/null @@ -1,48 +0,0 @@ -#!/bin/sh - -set -e - -node_version="$1" - -if [ "$node_version" == "" ]; then - echo "usage: $0 VERSION" - exit 1 -fi - -if [ "$AWS_ID" == "" ]; then - echo "must set AWS_ID" - exit 1 -fi - -if [ "$AWS_SECRET" == "" ]; then - echo "must set AWS_SECRET" - exit 1 -fi - -if [ "$S3_BUCKET" == "" ]; then - echo "must set S3_BUCKET" - exit 1 -fi - -basedir="$( cd -P "$( dirname "$0" )" && pwd )" - -# make a temp directory -tempdir="$( mktemp -t node_XXXX )" -rm -rf $tempdir -mkdir -p $tempdir -cd $tempdir - -# build and package nodejs for heroku -vulcan build -v \ - -n node \ - -c "cd node-v${node_version} && ./configure --prefix=/app/vendor/node && make install" \ - -p /app/vendor/node \ - -s http://nodejs.org/dist/v${node_version}/node-v${node_version}.tar.gz \ - -o $tempdir/node-${node_version}.tgz - -# upload nodejs to s3 -$basedir/aws/s3 put $S3_BUCKET \ - nodejs-${node_version}.tgz $tempdir/node-${node_version}.tgz - -# generate manifest -$basedir/manifest nodejs diff --git a/support/package_npm b/support/package_npm deleted file mode 100755 index 7de93de08e1701ce077c821a7819b630fcfd73e0..0000000000000000000000000000000000000000 --- a/support/package_npm +++ /dev/null @@ -1,53 +0,0 @@ -#!/bin/sh - -set -e - -npm_version="$1" - -if [ "$npm_version" == "" ]; then - echo "usage: $0 VERSION" - exit 1 -fi - -if [ "$AWS_ID" == "" ]; then - echo "must set AWS_ID" - exit 1 -fi - -if [ "$AWS_SECRET" == "" ]; then - echo "must set AWS_SECRET" - exit 1 -fi - -if [ "$S3_BUCKET" == "" ]; then - echo "must set S3_BUCKET" - exit 1 -fi - -basedir="$( cd -P "$( dirname "$0" )" && pwd )" - -# make a temp directory -tempdir="$( mktemp -t node_XXXX )" -rm -rf $tempdir -mkdir -p $tempdir -cd $tempdir - -# download npm -git clone https://github.com/isaacs/npm.git - -# go into npm dir -pushd npm - -# grab the right version -git checkout v${npm_version} -git submodule update --init --recursive - -# package it up -tar czvf $tempdir/npm-${npm_version}.tgz * - -# upload npm to s3 -$basedir/aws/s3 put $S3_BUCKET \ - npm-${npm_version}.tgz $tempdir/npm-${npm_version}.tgz - -# generate manifest -$basedir/manifest npm diff --git a/test/caching/README.md b/test/caching/README.md new file mode 100644 index 0000000000000000000000000000000000000000..cda334ae1a9cf883f9d4b40537e4502e4324d401 --- /dev/null +++ b/test/caching/README.md @@ -0,0 +1 @@ +A fake README, to keep npm from polluting stderr. \ No newline at end of file diff --git a/test/caching/package.json b/test/caching/package.json new file mode 100644 index 0000000000000000000000000000000000000000..c4e987036d906b35f439ac7b6b517addb0a1ce3b --- /dev/null +++ b/test/caching/package.json @@ -0,0 +1,15 @@ +{ + "name": "node-buildpack-test-app", + "version": "0.0.1", + "description": "node buildpack integration test app", + "repository" : { + "type" : "git", + "url" : "http://github.com/example/example.git" + }, + "engines": { + "node": "0.10.18" + }, + "dependencies": { + "express": "latest" + } +} diff --git a/test/dangerous-range-greater-than/README.md b/test/dangerous-range-greater-than/README.md new file mode 100644 index 0000000000000000000000000000000000000000..cda334ae1a9cf883f9d4b40537e4502e4324d401 --- /dev/null +++ b/test/dangerous-range-greater-than/README.md @@ -0,0 +1 @@ +A fake README, to keep npm from polluting stderr. \ No newline at end of file diff --git a/test/dangerous-range-greater-than/package.json b/test/dangerous-range-greater-than/package.json new file mode 100644 index 0000000000000000000000000000000000000000..2c77516426942ebb74242c66e99d1c95c4ab9a78 --- /dev/null +++ b/test/dangerous-range-greater-than/package.json @@ -0,0 +1,12 @@ +{ + "name": "node-buildpack-test-app", + "version": "0.0.1", + "description": "node buildpack integration test app", + "repository" : { + "type" : "git", + "url" : "http://github.com/example/example.git" + }, + "engines": { + "node": ">0.4" + } +} diff --git a/test/dangerous-range-star/README.md b/test/dangerous-range-star/README.md new file mode 100644 index 0000000000000000000000000000000000000000..cda334ae1a9cf883f9d4b40537e4502e4324d401 --- /dev/null +++ b/test/dangerous-range-star/README.md @@ -0,0 +1 @@ +A fake README, to keep npm from polluting stderr. \ No newline at end of file diff --git a/test/dangerous-range-star/package.json b/test/dangerous-range-star/package.json new file mode 100644 index 0000000000000000000000000000000000000000..32841fe12dc6b3c705f833c645508a096c2af5f2 --- /dev/null +++ b/test/dangerous-range-star/package.json @@ -0,0 +1,12 @@ +{ + "name": "node-buildpack-test-app", + "version": "0.0.1", + "description": "node buildpack integration test app", + "repository" : { + "type" : "git", + "url" : "http://github.com/example/example.git" + }, + "engines": { + "node": "*" + } +} diff --git a/test/invalid-dependency/README.md b/test/invalid-dependency/README.md new file mode 100644 index 0000000000000000000000000000000000000000..cda334ae1a9cf883f9d4b40537e4502e4324d401 --- /dev/null +++ b/test/invalid-dependency/README.md @@ -0,0 +1 @@ +A fake README, to keep npm from polluting stderr. \ No newline at end of file diff --git a/test/invalid-dependency/package.json b/test/invalid-dependency/package.json new file mode 100644 index 0000000000000000000000000000000000000000..4784042fc909ee5fa759fe7d713000909d42b202 --- /dev/null +++ b/test/invalid-dependency/package.json @@ -0,0 +1,15 @@ +{ + "name": "node-buildpack-test-app", + "version": "0.0.1", + "description": "node buildpack integration test app", + "repository" : { + "type" : "git", + "url" : "http://github.com/example/example.git" + }, + "engines": { + "node": "~0.10.20" + }, + "dependencies": { + "some-crazy-dep-that-doesnt-exist": "*" + } +} diff --git a/test/invalid-node-version/README.md b/test/invalid-node-version/README.md new file mode 100644 index 0000000000000000000000000000000000000000..cda334ae1a9cf883f9d4b40537e4502e4324d401 --- /dev/null +++ b/test/invalid-node-version/README.md @@ -0,0 +1 @@ +A fake README, to keep npm from polluting stderr. \ No newline at end of file diff --git a/test/invalid-node-version/package.json b/test/invalid-node-version/package.json new file mode 100644 index 0000000000000000000000000000000000000000..8895f66c5adf046fa6e5b129d9ab9439c1524cc3 --- /dev/null +++ b/test/invalid-node-version/package.json @@ -0,0 +1,12 @@ +{ + "name": "node-buildpack-test-app", + "version": "0.0.1", + "description": "node buildpack integration test app", + "repository" : { + "type" : "git", + "url" : "http://github.com/example/example.git" + }, + "engines": { + "node": ">2.0" + } +} diff --git a/test/modules-checked-in/README.md b/test/modules-checked-in/README.md new file mode 100644 index 0000000000000000000000000000000000000000..cda334ae1a9cf883f9d4b40537e4502e4324d401 --- /dev/null +++ b/test/modules-checked-in/README.md @@ -0,0 +1 @@ +A fake README, to keep npm from polluting stderr. \ No newline at end of file diff --git a/test/modules-checked-in/node_modules/hashish/README.markdown b/test/modules-checked-in/node_modules/hashish/README.markdown new file mode 100644 index 0000000000000000000000000000000000000000..1f39d59d56302149116a8e39bb7a380e1b65ba78 --- /dev/null +++ b/test/modules-checked-in/node_modules/hashish/README.markdown @@ -0,0 +1,191 @@ +Hashish +======= + +Hashish is a node.js library for manipulating hash data structures. +It is distilled from the finest that ruby, perl, and haskell have to offer by +way of hash/map interfaces. + +Hashish provides a chaining interface, where you can do: + + var Hash = require('hashish'); + + Hash({ a : 1, b : 2, c : 3, d : 4 }) + .map(function (x) { return x * 10 }) + .filter(function (x) { return x < 30 }) + .forEach(function (x, key) { + console.log(key + ' => ' + x); + }) + ; + +Output: + + a => 10 + b => 20 + +Some functions and attributes in the chaining interface are terminal, like +`.items` or `.detect()`. They return values of their own instead of the chain +context. + +Each function in the chainable interface is also attached to `Hash` in chainless +form: + + var Hash = require('hashish'); + var obj = { a : 1, b : 2, c : 3, d : 4 }; + + var mapped = Hash.map(obj, function (x) { + return x * 10 + }); + + console.dir(mapped); + +Output: + + { a: 10, b: 20, c: 30, d: 40 } + +In either case, the 'this' context of the function calls is the same object that +the chained functions return, so you can make nested chains. + +Methods +======= + +forEach(cb) +----------- + +For each key/value in the hash, calls `cb(value, key)`. + +map(cb) +------- + +For each key/value in the hash, calls `cb(value, key)`. +The return value of `cb` is the new value at `key` in the resulting hash. + +filter(cb) +---------- + +For each key/value in the hash, calls `cb(value, key)`. +The resulting hash omits key/value pairs where `cb` returned a falsy value. + +detect(cb) +---------- + +Returns the first value in the hash for which `cb(value, key)` is non-falsy. +Order of hashes is not well-defined so watch out for that. + +reduce(cb) +---------- + +Returns the accumulated value of a left-fold over the key/value pairs. + +some(cb) +-------- + +Returns a boolean: whether or not `cb(value, key)` ever returned a non-falsy +value. + +update(obj1, [obj2, obj3, ...]) +----------- + +Mutate the context hash, merging the key/value pairs from the passed objects +and overwriting keys from the context hash if the current `obj` has keys of +the same name. Falsy arguments are silently ignored. + +updateAll([ obj1, obj2, ... ]) +------------------------------ + +Like multi-argument `update()` but operate on an array directly. + +merge(obj1, [obj2, obj3, ...]) +---------- + +Merge the key/value pairs from the passed objects into the resultant hash +without modifying the context hash. Falsy arguments are silently ignored. + +mergeAll([ obj1, obj2, ... ]) +------------------------------ + +Like multi-argument `merge()` but operate on an array directly. + +has(key) +-------- + +Return whether the hash has a key, `key`. + +valuesAt(keys) +-------------- + +Return an Array with the values at the keys from `keys`. + +tap(cb) +------- + +Call `cb` with the present raw hash. +This function is chainable. + +extract(keys) +------------- + +Filter by including only those keys in `keys` in the resulting hash. + +exclude(keys) +------------- + +Filter by excluding those keys in `keys` in the resulting hash. + +Attributes +========== + +These are attributes in the chaining interface and functions in the `Hash.xxx` +interface. + +keys +---- + +Return all the enumerable attribute keys in the hash. + +values +------ + +Return all the enumerable attribute values in the hash. + +compact +------- + +Filter out values which are `=== undefined`. + +clone +----- + +Make a deep copy of the hash. + +copy +---- + +Make a shallow copy of the hash. + +length +------ + +Return the number of key/value pairs in the hash. +Note: use `Hash.size()` for non-chain mode. + +size +---- + +Alias for `length` since `Hash.length` is masked by `Function.prototype`. + +See Also +======== + +See also [creationix's pattern/hash](http://github.com/creationix/pattern), +which does a similar thing except with hash inputs and array outputs. + +Installation +============ + +To install with [npm](http://github.com/isaacs/npm): + + npm install hashish + +To run the tests with [expresso](http://github.com/visionmedia/expresso): + + expresso diff --git a/test/modules-checked-in/node_modules/hashish/examples/chain.js b/test/modules-checked-in/node_modules/hashish/examples/chain.js new file mode 100644 index 0000000000000000000000000000000000000000..74ded5e1214d385f66f30714d0421985d30929d3 --- /dev/null +++ b/test/modules-checked-in/node_modules/hashish/examples/chain.js @@ -0,0 +1,9 @@ +var Hash = require('hashish'); + +Hash({ a : 1, b : 2, c : 3, d : 4 }) + .map(function (x) { return x * 10 }) + .filter(function (x) { return x < 30 }) + .forEach(function (x, key) { + console.log(key + ' => ' + x); + }) +; diff --git a/test/modules-checked-in/node_modules/hashish/examples/map.js b/test/modules-checked-in/node_modules/hashish/examples/map.js new file mode 100644 index 0000000000000000000000000000000000000000..119d3d935ecd8cd4c09549e6e97ff965b75fdcbc --- /dev/null +++ b/test/modules-checked-in/node_modules/hashish/examples/map.js @@ -0,0 +1,7 @@ +var Hash = require('hashish'); +var obj = { a : 1, b : 2, c : 3, d : 4 }; + +var mapped = Hash.map(obj, function (x) { + return x * 10 +}); +console.dir(mapped); diff --git a/test/modules-checked-in/node_modules/hashish/index.js b/test/modules-checked-in/node_modules/hashish/index.js new file mode 100644 index 0000000000000000000000000000000000000000..1bc28e2b6bdcb929d5739cd569518b69f431b72b --- /dev/null +++ b/test/modules-checked-in/node_modules/hashish/index.js @@ -0,0 +1,253 @@ +module.exports = Hash; +var Traverse = require('traverse'); + +function Hash (hash, xs) { + if (Array.isArray(hash) && Array.isArray(xs)) { + var to = Math.min(hash.length, xs.length); + var acc = {}; + for (var i = 0; i < to; i++) { + acc[hash[i]] = xs[i]; + } + return Hash(acc); + } + + if (hash === undefined) return Hash({}); + + var self = { + map : function (f) { + var acc = { __proto__ : hash.__proto__ }; + Object.keys(hash).forEach(function (key) { + acc[key] = f.call(self, hash[key], key); + }); + return Hash(acc); + }, + forEach : function (f) { + Object.keys(hash).forEach(function (key) { + f.call(self, hash[key], key); + }); + return self; + }, + filter : function (f) { + var acc = { __proto__ : hash.__proto__ }; + Object.keys(hash).forEach(function (key) { + if (f.call(self, hash[key], key)) { + acc[key] = hash[key]; + } + }); + return Hash(acc); + }, + detect : function (f) { + for (var key in hash) { + if (f.call(self, hash[key], key)) { + return hash[key]; + } + } + return undefined; + }, + reduce : function (f, acc) { + var keys = Object.keys(hash); + if (acc === undefined) acc = keys.shift(); + keys.forEach(function (key) { + acc = f.call(self, acc, hash[key], key); + }); + return acc; + }, + some : function (f) { + for (var key in hash) { + if (f.call(self, hash[key], key)) return true; + } + return false; + }, + update : function (obj) { + if (arguments.length > 1) { + self.updateAll([].slice.call(arguments)); + } + else { + Object.keys(obj).forEach(function (key) { + hash[key] = obj[key]; + }); + } + return self; + }, + updateAll : function (xs) { + xs.filter(Boolean).forEach(function (x) { + self.update(x); + }); + return self; + }, + merge : function (obj) { + if (arguments.length > 1) { + return self.copy.updateAll([].slice.call(arguments)); + } + else { + return self.copy.update(obj); + } + }, + mergeAll : function (xs) { + return self.copy.updateAll(xs); + }, + has : function (key) { // only operates on enumerables + return Array.isArray(key) + ? key.every(function (k) { return self.has(k) }) + : self.keys.indexOf(key.toString()) >= 0; + }, + valuesAt : function (keys) { + return Array.isArray(keys) + ? keys.map(function (key) { return hash[key] }) + : hash[keys] + ; + }, + tap : function (f) { + f.call(self, hash); + return self; + }, + extract : function (keys) { + var acc = {}; + keys.forEach(function (key) { + acc[key] = hash[key]; + }); + return Hash(acc); + }, + exclude : function (keys) { + return self.filter(function (_, key) { + return keys.indexOf(key) < 0 + }); + }, + end : hash, + items : hash + }; + + var props = { + keys : function () { return Object.keys(hash) }, + values : function () { + return Object.keys(hash).map(function (key) { return hash[key] }); + }, + compact : function () { + return self.filter(function (x) { return x !== undefined }); + }, + clone : function () { return Hash(Hash.clone(hash)) }, + copy : function () { return Hash(Hash.copy(hash)) }, + length : function () { return Object.keys(hash).length }, + size : function () { return self.length } + }; + + if (Object.defineProperty) { + // es5-shim has an Object.defineProperty but it throws for getters + try { + for (var key in props) { + Object.defineProperty(self, key, { get : props[key] }); + } + } + catch (err) { + for (var key in props) { + if (key !== 'clone' && key !== 'copy' && key !== 'compact') { + // ^ those keys use Hash() so can't call them without + // a stack overflow + self[key] = props[key](); + } + } + } + } + else if (self.__defineGetter__) { + for (var key in props) { + self.__defineGetter__(key, props[key]); + } + } + else { + // non-lazy version for browsers that suck >_< + for (var key in props) { + self[key] = props[key](); + } + } + + return self; +}; + +// deep copy +Hash.clone = function (ref) { + return Traverse.clone(ref); +}; + +// shallow copy +Hash.copy = function (ref) { + var hash = { __proto__ : ref.__proto__ }; + Object.keys(ref).forEach(function (key) { + hash[key] = ref[key]; + }); + return hash; +}; + +Hash.map = function (ref, f) { + return Hash(ref).map(f).items; +}; + +Hash.forEach = function (ref, f) { + Hash(ref).forEach(f); +}; + +Hash.filter = function (ref, f) { + return Hash(ref).filter(f).items; +}; + +Hash.detect = function (ref, f) { + return Hash(ref).detect(f); +}; + +Hash.reduce = function (ref, f, acc) { + return Hash(ref).reduce(f, acc); +}; + +Hash.some = function (ref, f) { + return Hash(ref).some(f); +}; + +Hash.update = function (a /*, b, c, ... */) { + var args = Array.prototype.slice.call(arguments, 1); + var hash = Hash(a); + return hash.update.apply(hash, args).items; +}; + +Hash.merge = function (a /*, b, c, ... */) { + var args = Array.prototype.slice.call(arguments, 1); + var hash = Hash(a); + return hash.merge.apply(hash, args).items; +}; + +Hash.has = function (ref, key) { + return Hash(ref).has(key); +}; + +Hash.valuesAt = function (ref, keys) { + return Hash(ref).valuesAt(keys); +}; + +Hash.tap = function (ref, f) { + return Hash(ref).tap(f).items; +}; + +Hash.extract = function (ref, keys) { + return Hash(ref).extract(keys).items; +}; + +Hash.exclude = function (ref, keys) { + return Hash(ref).exclude(keys).items; +}; + +Hash.concat = function (xs) { + var hash = Hash({}); + xs.forEach(function (x) { hash.update(x) }); + return hash.items; +}; + +Hash.zip = function (xs, ys) { + return Hash(xs, ys).items; +}; + +// .length is already defined for function prototypes +Hash.size = function (ref) { + return Hash(ref).size; +}; + +Hash.compact = function (ref) { + return Hash(ref).compact.items; +}; diff --git a/test/modules-checked-in/node_modules/hashish/node_modules/traverse/.npmignore b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/.npmignore new file mode 100644 index 0000000000000000000000000000000000000000..3c3629e647f5ddf82548912e337bea9826b434af --- /dev/null +++ b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/.npmignore @@ -0,0 +1 @@ +node_modules diff --git a/test/modules-checked-in/node_modules/hashish/node_modules/traverse/.travis.yml b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/.travis.yml new file mode 100644 index 0000000000000000000000000000000000000000..2d26206d58cbb7c8fc894e21646b93fc1aabf2d9 --- /dev/null +++ b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/.travis.yml @@ -0,0 +1,3 @@ +language: node_js +node_js: + - 0.6 diff --git a/test/modules-checked-in/node_modules/hashish/node_modules/traverse/LICENSE b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..7b75500c5e50ee4c236093a445eb33a2f64953ac --- /dev/null +++ b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/LICENSE @@ -0,0 +1,24 @@ +Copyright 2010 James Halliday (mail@substack.net) + +This project is free software released under the MIT/X11 license: +http://www.opensource.org/licenses/mit-license.php + +Copyright 2010 James Halliday (mail@substack.net) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/test/modules-checked-in/node_modules/hashish/node_modules/traverse/examples/json.js b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/examples/json.js new file mode 100755 index 0000000000000000000000000000000000000000..50d612e3a9d97ca1021cd1e64ed1388dd540acf2 --- /dev/null +++ b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/examples/json.js @@ -0,0 +1,16 @@ +var traverse = require('traverse'); + +var id = 54; +var callbacks = {}; +var obj = { moo : function () {}, foo : [2,3,4, function () {}] }; + +var scrubbed = traverse(obj).map(function (x) { + if (typeof x === 'function') { + callbacks[id] = { id : id, f : x, path : this.path }; + this.update('[Function]'); + id++; + } +}); + +console.dir(scrubbed); +console.dir(callbacks); diff --git a/test/modules-checked-in/node_modules/hashish/node_modules/traverse/examples/leaves.js b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/examples/leaves.js new file mode 100755 index 0000000000000000000000000000000000000000..c1b310b95a941b883955946e2ec14272fe7d50db --- /dev/null +++ b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/examples/leaves.js @@ -0,0 +1,15 @@ +var traverse = require('traverse'); + +var obj = { + a : [1,2,3], + b : 4, + c : [5,6], + d : { e : [7,8], f : 9 }, +}; + +var leaves = traverse(obj).reduce(function (acc, x) { + if (this.isLeaf) acc.push(x); + return acc; +}, []); + +console.dir(leaves); diff --git a/test/modules-checked-in/node_modules/hashish/node_modules/traverse/examples/negative.js b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/examples/negative.js new file mode 100755 index 0000000000000000000000000000000000000000..78608a0590cefc91a5326f18f4df02fdf4b95959 --- /dev/null +++ b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/examples/negative.js @@ -0,0 +1,8 @@ +var traverse = require('traverse'); +var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ]; + +traverse(obj).forEach(function (x) { + if (x < 0) this.update(x + 128); +}); + +console.dir(obj); diff --git a/test/modules-checked-in/node_modules/hashish/node_modules/traverse/examples/scrub.js b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/examples/scrub.js new file mode 100755 index 0000000000000000000000000000000000000000..5d15b9161ffe1d8d1c71e2a47138dd573af4271b --- /dev/null +++ b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/examples/scrub.js @@ -0,0 +1,10 @@ +// scrub out circular references +var traverse = require('traverse'); + +var obj = { a : 1, b : 2, c : [ 3, 4 ] }; +obj.c.push(obj); + +var scrubbed = traverse(obj).map(function (x) { + if (this.circular) this.remove() +}); +console.dir(scrubbed); diff --git a/test/modules-checked-in/node_modules/hashish/node_modules/traverse/examples/stringify.js b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/examples/stringify.js new file mode 100755 index 0000000000000000000000000000000000000000..167b68b231c729f68a46435a2c201d26d0c6e91e --- /dev/null +++ b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/examples/stringify.js @@ -0,0 +1,38 @@ +#!/usr/bin/env node +var traverse = require('traverse'); + +var obj = [ 'five', 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ]; + +var s = ''; +traverse(obj).forEach(function to_s (node) { + if (Array.isArray(node)) { + this.before(function () { s += '[' }); + this.post(function (child) { + if (!child.isLast) s += ','; + }); + this.after(function () { s += ']' }); + } + else if (typeof node == 'object') { + this.before(function () { s += '{' }); + this.pre(function (x, key) { + to_s(key); + s += ':'; + }); + this.post(function (child) { + if (!child.isLast) s += ','; + }); + this.after(function () { s += '}' }); + } + else if (typeof node == 'string') { + s += '"' + node.toString().replace(/"/g, '\\"') + '"'; + } + else if (typeof node == 'function') { + s += 'null'; + } + else { + s += node.toString(); + } +}); + +console.log('JSON.stringify: ' + JSON.stringify(obj)); +console.log('this stringify: ' + s); diff --git a/test/modules-checked-in/node_modules/hashish/node_modules/traverse/index.js b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/index.js new file mode 100644 index 0000000000000000000000000000000000000000..2f2cf673428c90cb8a3e14a6fae78778a11a0be7 --- /dev/null +++ b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/index.js @@ -0,0 +1,314 @@ +var traverse = module.exports = function (obj) { + return new Traverse(obj); +}; + +function Traverse (obj) { + this.value = obj; +} + +Traverse.prototype.get = function (ps) { + var node = this.value; + for (var i = 0; i < ps.length; i ++) { + var key = ps[i]; + if (!node || !hasOwnProperty.call(node, key)) { + node = undefined; + break; + } + node = node[key]; + } + return node; +}; + +Traverse.prototype.has = function (ps) { + var node = this.value; + for (var i = 0; i < ps.length; i ++) { + var key = ps[i]; + if (!node || !hasOwnProperty.call(node, key)) { + return false; + } + node = node[key]; + } + return true; +}; + +Traverse.prototype.set = function (ps, value) { + var node = this.value; + for (var i = 0; i < ps.length - 1; i ++) { + var key = ps[i]; + if (!hasOwnProperty.call(node, key)) node[key] = {}; + node = node[key]; + } + node[ps[i]] = value; + return value; +}; + +Traverse.prototype.map = function (cb) { + return walk(this.value, cb, true); +}; + +Traverse.prototype.forEach = function (cb) { + this.value = walk(this.value, cb, false); + return this.value; +}; + +Traverse.prototype.reduce = function (cb, init) { + var skip = arguments.length === 1; + var acc = skip ? this.value : init; + this.forEach(function (x) { + if (!this.isRoot || !skip) { + acc = cb.call(this, acc, x); + } + }); + return acc; +}; + +Traverse.prototype.paths = function () { + var acc = []; + this.forEach(function (x) { + acc.push(this.path); + }); + return acc; +}; + +Traverse.prototype.nodes = function () { + var acc = []; + this.forEach(function (x) { + acc.push(this.node); + }); + return acc; +}; + +Traverse.prototype.clone = function () { + var parents = [], nodes = []; + + return (function clone (src) { + for (var i = 0; i < parents.length; i++) { + if (parents[i] === src) { + return nodes[i]; + } + } + + if (typeof src === 'object' && src !== null) { + var dst = copy(src); + + parents.push(src); + nodes.push(dst); + + forEach(objectKeys(src), function (key) { + dst[key] = clone(src[key]); + }); + + parents.pop(); + nodes.pop(); + return dst; + } + else { + return src; + } + })(this.value); +}; + +function walk (root, cb, immutable) { + var path = []; + var parents = []; + var alive = true; + + return (function walker (node_) { + var node = immutable ? copy(node_) : node_; + var modifiers = {}; + + var keepGoing = true; + + var state = { + node : node, + node_ : node_, + path : [].concat(path), + parent : parents[parents.length - 1], + parents : parents, + key : path.slice(-1)[0], + isRoot : path.length === 0, + level : path.length, + circular : null, + update : function (x, stopHere) { + if (!state.isRoot) { + state.parent.node[state.key] = x; + } + state.node = x; + if (stopHere) keepGoing = false; + }, + 'delete' : function (stopHere) { + delete state.parent.node[state.key]; + if (stopHere) keepGoing = false; + }, + remove : function (stopHere) { + if (isArray(state.parent.node)) { + state.parent.node.splice(state.key, 1); + } + else { + delete state.parent.node[state.key]; + } + if (stopHere) keepGoing = false; + }, + keys : null, + before : function (f) { modifiers.before = f }, + after : function (f) { modifiers.after = f }, + pre : function (f) { modifiers.pre = f }, + post : function (f) { modifiers.post = f }, + stop : function () { alive = false }, + block : function () { keepGoing = false } + }; + + if (!alive) return state; + + function updateState() { + if (typeof state.node === 'object' && state.node !== null) { + if (!state.keys || state.node_ !== state.node) { + state.keys = objectKeys(state.node) + } + + state.isLeaf = state.keys.length == 0; + + for (var i = 0; i < parents.length; i++) { + if (parents[i].node_ === node_) { + state.circular = parents[i]; + break; + } + } + } + else { + state.isLeaf = true; + state.keys = null; + } + + state.notLeaf = !state.isLeaf; + state.notRoot = !state.isRoot; + } + + updateState(); + + // use return values to update if defined + var ret = cb.call(state, state.node); + if (ret !== undefined && state.update) state.update(ret); + + if (modifiers.before) modifiers.before.call(state, state.node); + + if (!keepGoing) return state; + + if (typeof state.node == 'object' + && state.node !== null && !state.circular) { + parents.push(state); + + updateState(); + + forEach(state.keys, function (key, i) { + path.push(key); + + if (modifiers.pre) modifiers.pre.call(state, state.node[key], key); + + var child = walker(state.node[key]); + if (immutable && hasOwnProperty.call(state.node, key)) { + state.node[key] = child.node; + } + + child.isLast = i == state.keys.length - 1; + child.isFirst = i == 0; + + if (modifiers.post) modifiers.post.call(state, child); + + path.pop(); + }); + parents.pop(); + } + + if (modifiers.after) modifiers.after.call(state, state.node); + + return state; + })(root).node; +} + +function copy (src) { + if (typeof src === 'object' && src !== null) { + var dst; + + if (isArray(src)) { + dst = []; + } + else if (isDate(src)) { + dst = new Date(src.getTime ? src.getTime() : src); + } + else if (isRegExp(src)) { + dst = new RegExp(src); + } + else if (isError(src)) { + dst = { message: src.message }; + } + else if (isBoolean(src)) { + dst = new Boolean(src); + } + else if (isNumber(src)) { + dst = new Number(src); + } + else if (isString(src)) { + dst = new String(src); + } + else if (Object.create && Object.getPrototypeOf) { + dst = Object.create(Object.getPrototypeOf(src)); + } + else if (src.constructor === Object) { + dst = {}; + } + else { + var proto = + (src.constructor && src.constructor.prototype) + || src.__proto__ + || {} + ; + var T = function () {}; + T.prototype = proto; + dst = new T; + } + + forEach(objectKeys(src), function (key) { + dst[key] = src[key]; + }); + return dst; + } + else return src; +} + +var objectKeys = Object.keys || function keys (obj) { + var res = []; + for (var key in obj) res.push(key) + return res; +}; + +function toS (obj) { return Object.prototype.toString.call(obj) } +function isDate (obj) { return toS(obj) === '[object Date]' } +function isRegExp (obj) { return toS(obj) === '[object RegExp]' } +function isError (obj) { return toS(obj) === '[object Error]' } +function isBoolean (obj) { return toS(obj) === '[object Boolean]' } +function isNumber (obj) { return toS(obj) === '[object Number]' } +function isString (obj) { return toS(obj) === '[object String]' } + +var isArray = Array.isArray || function isArray (xs) { + return Object.prototype.toString.call(xs) === '[object Array]'; +}; + +var forEach = function (xs, fn) { + if (xs.forEach) return xs.forEach(fn) + else for (var i = 0; i < xs.length; i++) { + fn(xs[i], i, xs); + } +}; + +forEach(objectKeys(Traverse.prototype), function (key) { + traverse[key] = function (obj) { + var args = [].slice.call(arguments, 1); + var t = new Traverse(obj); + return t[key].apply(t, args); + }; +}); + +var hasOwnProperty = Object.hasOwnProperty || function (obj, key) { + return key in obj; +}; diff --git a/test/modules-checked-in/node_modules/hashish/node_modules/traverse/package.json b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/package.json new file mode 100644 index 0000000000000000000000000000000000000000..0b30f3dbe3b5b638073965d77403b8d54bfa3b91 --- /dev/null +++ b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/package.json @@ -0,0 +1,72 @@ +{ + "name": "traverse", + "version": "0.6.6", + "description": "traverse and transform objects by visiting every node on a recursive walk", + "main": "index.js", + "directories": { + "example": "example", + "test": "test" + }, + "devDependencies": { + "tape": "~1.0.4" + }, + "scripts": { + "test": "tape test/*.js" + }, + "testling": { + "files": "test/*.js", + "browsers": { + "iexplore": [ + "6.0", + "7.0", + "8.0", + "9.0" + ], + "chrome": [ + "10.0", + "20.0" + ], + "firefox": [ + "10.0", + "15.0" + ], + "safari": [ + "5.1" + ], + "opera": [ + "12.0" + ] + } + }, + "repository": { + "type": "git", + "url": "git://github.com/substack/js-traverse.git" + }, + "homepage": "https://github.com/substack/js-traverse", + "keywords": [ + "traverse", + "walk", + "recursive", + "map", + "forEach", + "deep", + "clone" + ], + "author": { + "name": "James Halliday", + "email": "mail@substack.net", + "url": "http://substack.net" + }, + "license": "MIT", + "readme": "# traverse\n\nTraverse and transform objects by visiting every node on a recursive walk.\n\n[![browser support](http://ci.testling.com/substack/js-traverse.png)](http://ci.testling.com/substack/js-traverse)\n\n[![build status](https://secure.travis-ci.org/substack/js-traverse.png)](http://travis-ci.org/substack/js-traverse)\n\n# examples\n\n## transform negative numbers in-place\n\nnegative.js\n\n````javascript\nvar traverse = require('traverse');\nvar obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ];\n\ntraverse(obj).forEach(function (x) {\n if (x < 0) this.update(x + 128);\n});\n\nconsole.dir(obj);\n````\n\nOutput:\n\n [ 5, 6, 125, [ 7, 8, 126, 1 ], { f: 10, g: 115 } ]\n\n## collect leaf nodes\n\nleaves.js\n\n````javascript\nvar traverse = require('traverse');\n\nvar obj = {\n a : [1,2,3],\n b : 4,\n c : [5,6],\n d : { e : [7,8], f : 9 },\n};\n\nvar leaves = traverse(obj).reduce(function (acc, x) {\n if (this.isLeaf) acc.push(x);\n return acc;\n}, []);\n\nconsole.dir(leaves);\n````\n\nOutput:\n\n [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]\n\n## scrub circular references\n\nscrub.js:\n\n````javascript\nvar traverse = require('traverse');\n\nvar obj = { a : 1, b : 2, c : [ 3, 4 ] };\nobj.c.push(obj);\n\nvar scrubbed = traverse(obj).map(function (x) {\n if (this.circular) this.remove()\n});\nconsole.dir(scrubbed);\n````\n\noutput:\n\n { a: 1, b: 2, c: [ 3, 4 ] }\n\n# methods\n\nEach method that takes an `fn` uses the context documented below in the context\nsection.\n\n## .map(fn)\n\nExecute `fn` for each node in the object and return a new object with the\nresults of the walk. To update nodes in the result use `this.update(value)`.\n\n## .forEach(fn)\n\nExecute `fn` for each node in the object but unlike `.map()`, when\n`this.update()` is called it updates the object in-place.\n\n## .reduce(fn, acc)\n\nFor each node in the object, perform a\n[left-fold](http://en.wikipedia.org/wiki/Fold_(higher-order_function))\nwith the return value of `fn(acc, node)`.\n\nIf `acc` isn't specified, `acc` is set to the root object for the first step\nand the root element is skipped.\n\n## .paths()\n\nReturn an `Array` of every possible non-cyclic path in the object.\nPaths are `Array`s of string keys.\n\n## .nodes()\n\nReturn an `Array` of every node in the object.\n\n## .clone()\n\nCreate a deep clone of the object.\n\n## .get(path)\n\nGet the element at the array `path`.\n\n## .set(path, value)\n\nSet the element at the array `path` to `value`.\n\n## .has(path)\n\nReturn whether the element at the array `path` exists.\n\n# context\n\nEach method that takes a callback has a context (its `this` object) with these\nattributes:\n\n## this.node\n\nThe present node on the recursive walk\n\n## this.path\n\nAn array of string keys from the root to the present node\n\n## this.parent\n\nThe context of the node's parent.\nThis is `undefined` for the root node.\n\n## this.key\n\nThe name of the key of the present node in its parent.\nThis is `undefined` for the root node.\n\n## this.isRoot, this.notRoot\n\nWhether the present node is the root node\n\n## this.isLeaf, this.notLeaf\n\nWhether or not the present node is a leaf node (has no children)\n\n## this.level\n\nDepth of the node within the traversal\n\n## this.circular\n\nIf the node equals one of its parents, the `circular` attribute is set to the\ncontext of that parent and the traversal progresses no deeper.\n\n## this.update(value, stopHere=false)\n\nSet a new value for the present node.\n\nAll the elements in `value` will be recursively traversed unless `stopHere` is\ntrue.\n\n## this.remove(stopHere=false)\n\nRemove the current element from the output. If the node is in an Array it will\nbe spliced off. Otherwise it will be deleted from its parent.\n\n## this.delete(stopHere=false)\n\nDelete the current element from its parent in the output. Calls `delete` even on\nArrays.\n\n## this.before(fn)\n\nCall this function before any of the children are traversed.\n\nYou can assign into `this.keys` here to traverse in a custom order.\n\n## this.after(fn)\n\nCall this function after any of the children are traversed.\n\n## this.pre(fn)\n\nCall this function before each of the children are traversed.\n\n## this.post(fn)\n\nCall this function after each of the children are traversed.\n\n\n# install\n\nUsing [npm](http://npmjs.org) do:\n\n $ npm install traverse\n\n# license\n\nMIT\n", + "readmeFilename": "readme.markdown", + "bugs": { + "url": "https://github.com/substack/js-traverse/issues" + }, + "_id": "traverse@0.6.6", + "dist": { + "shasum": "887acce42e0d9aa00e0e7e4c00c29529d7df90f2" + }, + "_from": "traverse@>=0.2.4", + "_resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz" +} diff --git a/test/modules-checked-in/node_modules/hashish/node_modules/traverse/readme.markdown b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/readme.markdown new file mode 100644 index 0000000000000000000000000000000000000000..fbfd06e208c57e1b7b93c92a5ac0f7f46229c9ec --- /dev/null +++ b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/readme.markdown @@ -0,0 +1,209 @@ +# traverse + +Traverse and transform objects by visiting every node on a recursive walk. + +[![browser support](http://ci.testling.com/substack/js-traverse.png)](http://ci.testling.com/substack/js-traverse) + +[![build status](https://secure.travis-ci.org/substack/js-traverse.png)](http://travis-ci.org/substack/js-traverse) + +# examples + +## transform negative numbers in-place + +negative.js + +````javascript +var traverse = require('traverse'); +var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ]; + +traverse(obj).forEach(function (x) { + if (x < 0) this.update(x + 128); +}); + +console.dir(obj); +```` + +Output: + + [ 5, 6, 125, [ 7, 8, 126, 1 ], { f: 10, g: 115 } ] + +## collect leaf nodes + +leaves.js + +````javascript +var traverse = require('traverse'); + +var obj = { + a : [1,2,3], + b : 4, + c : [5,6], + d : { e : [7,8], f : 9 }, +}; + +var leaves = traverse(obj).reduce(function (acc, x) { + if (this.isLeaf) acc.push(x); + return acc; +}, []); + +console.dir(leaves); +```` + +Output: + + [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ] + +## scrub circular references + +scrub.js: + +````javascript +var traverse = require('traverse'); + +var obj = { a : 1, b : 2, c : [ 3, 4 ] }; +obj.c.push(obj); + +var scrubbed = traverse(obj).map(function (x) { + if (this.circular) this.remove() +}); +console.dir(scrubbed); +```` + +output: + + { a: 1, b: 2, c: [ 3, 4 ] } + +# methods + +Each method that takes an `fn` uses the context documented below in the context +section. + +## .map(fn) + +Execute `fn` for each node in the object and return a new object with the +results of the walk. To update nodes in the result use `this.update(value)`. + +## .forEach(fn) + +Execute `fn` for each node in the object but unlike `.map()`, when +`this.update()` is called it updates the object in-place. + +## .reduce(fn, acc) + +For each node in the object, perform a +[left-fold](http://en.wikipedia.org/wiki/Fold_(higher-order_function)) +with the return value of `fn(acc, node)`. + +If `acc` isn't specified, `acc` is set to the root object for the first step +and the root element is skipped. + +## .paths() + +Return an `Array` of every possible non-cyclic path in the object. +Paths are `Array`s of string keys. + +## .nodes() + +Return an `Array` of every node in the object. + +## .clone() + +Create a deep clone of the object. + +## .get(path) + +Get the element at the array `path`. + +## .set(path, value) + +Set the element at the array `path` to `value`. + +## .has(path) + +Return whether the element at the array `path` exists. + +# context + +Each method that takes a callback has a context (its `this` object) with these +attributes: + +## this.node + +The present node on the recursive walk + +## this.path + +An array of string keys from the root to the present node + +## this.parent + +The context of the node's parent. +This is `undefined` for the root node. + +## this.key + +The name of the key of the present node in its parent. +This is `undefined` for the root node. + +## this.isRoot, this.notRoot + +Whether the present node is the root node + +## this.isLeaf, this.notLeaf + +Whether or not the present node is a leaf node (has no children) + +## this.level + +Depth of the node within the traversal + +## this.circular + +If the node equals one of its parents, the `circular` attribute is set to the +context of that parent and the traversal progresses no deeper. + +## this.update(value, stopHere=false) + +Set a new value for the present node. + +All the elements in `value` will be recursively traversed unless `stopHere` is +true. + +## this.remove(stopHere=false) + +Remove the current element from the output. If the node is in an Array it will +be spliced off. Otherwise it will be deleted from its parent. + +## this.delete(stopHere=false) + +Delete the current element from its parent in the output. Calls `delete` even on +Arrays. + +## this.before(fn) + +Call this function before any of the children are traversed. + +You can assign into `this.keys` here to traverse in a custom order. + +## this.after(fn) + +Call this function after any of the children are traversed. + +## this.pre(fn) + +Call this function before each of the children are traversed. + +## this.post(fn) + +Call this function after each of the children are traversed. + + +# install + +Using [npm](http://npmjs.org) do: + + $ npm install traverse + +# license + +MIT diff --git a/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/circular.js b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/circular.js new file mode 100644 index 0000000000000000000000000000000000000000..f56506a202785e011acffdb843387387d324e2bc --- /dev/null +++ b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/circular.js @@ -0,0 +1,117 @@ +var test = require('tape'); +var traverse = require('../'); +var deepEqual = require('./lib/deep_equal'); +var util = require('util'); + +test('circular', function (t) { + t.plan(1); + + var obj = { x : 3 }; + obj.y = obj; + traverse(obj).forEach(function (x) { + if (this.path.join('') == 'y') { + t.equal( + util.inspect(this.circular.node), + util.inspect(obj) + ); + } + }); +}); + +test('deepCirc', function (t) { + t.plan(2); + var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] }; + obj.y[2] = obj; + + var times = 0; + traverse(obj).forEach(function (x) { + if (this.circular) { + t.same(this.circular.path, []); + t.same(this.path, [ 'y', 2 ]); + } + }); +}); + +test('doubleCirc', function (t) { + var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] }; + obj.y[2] = obj; + obj.x.push(obj.y); + + var circs = []; + traverse(obj).forEach(function (x) { + if (this.circular) { + circs.push({ circ : this.circular, self : this, node : x }); + } + }); + + t.same(circs[0].self.path, [ 'x', 3, 2 ]); + t.same(circs[0].circ.path, []); + + t.same(circs[1].self.path, [ 'y', 2 ]); + t.same(circs[1].circ.path, []); + + t.same(circs.length, 2); + t.end(); +}); + +test('circDubForEach', function (t) { + var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] }; + obj.y[2] = obj; + obj.x.push(obj.y); + + traverse(obj).forEach(function (x) { + if (this.circular) this.update('...'); + }); + + t.same(obj, { x : [ 1, 2, 3, [ 4, 5, '...' ] ], y : [ 4, 5, '...' ] }); + t.end(); +}); + +test('circDubMap', function (t) { + var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] }; + obj.y[2] = obj; + obj.x.push(obj.y); + + var c = traverse(obj).map(function (x) { + if (this.circular) { + this.update('...'); + } + }); + + t.same(c, { x : [ 1, 2, 3, [ 4, 5, '...' ] ], y : [ 4, 5, '...' ] }); + t.end(); +}); + +test('circClone', function (t) { + var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] }; + obj.y[2] = obj; + obj.x.push(obj.y); + + var clone = traverse.clone(obj); + t.ok(obj !== clone); + + t.ok(clone.y[2] === clone); + t.ok(clone.y[2] !== obj); + t.ok(clone.x[3][2] === clone); + t.ok(clone.x[3][2] !== obj); + t.same(clone.x.slice(0,3), [1,2,3]); + t.same(clone.y.slice(0,2), [4,5]); + t.end(); +}); + +test('circMapScrub', function (t) { + var obj = { a : 1, b : 2 }; + obj.c = obj; + + var scrubbed = traverse(obj).map(function (node) { + if (this.circular) this.remove(); + }); + t.same( + Object.keys(scrubbed).sort(), + [ 'a', 'b' ] + ); + t.ok(deepEqual(scrubbed, { a : 1, b : 2 })); + + t.equal(obj.c, obj); + t.end(); +}); diff --git a/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/date.js b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/date.js new file mode 100644 index 0000000000000000000000000000000000000000..54db4b0aecebe8224320c0b62482ca3a2f72d2f8 --- /dev/null +++ b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/date.js @@ -0,0 +1,37 @@ +var test = require('tape'); +var traverse = require('../'); + +test('dateEach', function (t) { + var obj = { x : new Date, y : 10, z : 5 }; + + var counts = {}; + + traverse(obj).forEach(function (node) { + var t = (node instanceof Date && 'Date') || typeof node; + counts[t] = (counts[t] || 0) + 1; + }); + + t.same(counts, { + object : 1, + Date : 1, + number : 2, + }); + t.end(); +}); + +test('dateMap', function (t) { + var obj = { x : new Date, y : 10, z : 5 }; + + var res = traverse(obj).map(function (node) { + if (typeof node === 'number') this.update(node + 100); + }); + + t.ok(obj.x !== res.x); + t.same(res, { + x : obj.x, + y : 110, + z : 105, + }); + t.end(); +}); + diff --git a/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/equal.js b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/equal.js new file mode 100644 index 0000000000000000000000000000000000000000..fd0463cc49bcf76790a1db8b953853ef83c9d242 --- /dev/null +++ b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/equal.js @@ -0,0 +1,240 @@ +var test = require('tape'); +var traverse = require('../'); +var deepEqual = require('./lib/deep_equal'); + +test('deepDates', function (t) { + t.plan(2); + + t.ok( + deepEqual( + { d : new Date, x : [ 1, 2, 3 ] }, + { d : new Date, x : [ 1, 2, 3 ] } + ), + 'dates should be equal' + ); + + var d0 = new Date; + setTimeout(function () { + t.ok( + !deepEqual( + { d : d0, x : [ 1, 2, 3 ], }, + { d : new Date, x : [ 1, 2, 3 ] } + ), + 'microseconds should count in date equality' + ); + }, 5); +}); + +test('deepCircular', function (t) { + var a = [1]; + a.push(a); // a = [ 1, *a ] + + var b = [1]; + b.push(a); // b = [ 1, [ 1, *a ] ] + + t.ok( + !deepEqual(a, b), + 'circular ref mount points count towards equality' + ); + + var c = [1]; + c.push(c); // c = [ 1, *c ] + t.ok( + deepEqual(a, c), + 'circular refs are structurally the same here' + ); + + var d = [1]; + d.push(a); // c = [ 1, [ 1, *d ] ] + t.ok( + deepEqual(b, d), + 'non-root circular ref structural comparison' + ); + + t.end(); +}); + +test('deepInstances', function (t) { + t.ok( + !deepEqual([ new Boolean(false) ], [ false ]), + 'boolean instances are not real booleans' + ); + + t.ok( + !deepEqual([ new String('x') ], [ 'x' ]), + 'string instances are not real strings' + ); + + t.ok( + !deepEqual([ new Number(4) ], [ 4 ]), + 'number instances are not real numbers' + ); + + t.ok( + deepEqual([ new RegExp('x') ], [ /x/ ]), + 'regexp instances are real regexps' + ); + + t.ok( + !deepEqual([ new RegExp(/./) ], [ /../ ]), + 'these regexps aren\'t the same' + ); + + t.ok( + !deepEqual( + [ function (x) { return x * 2 } ], + [ function (x) { return x * 2 } ] + ), + 'functions with the same .toString() aren\'t necessarily the same' + ); + + var f = function (x) { return x * 2 }; + t.ok( + deepEqual([ f ], [ f ]), + 'these functions are actually equal' + ); + + t.end(); +}); + +test('deepEqual', function (t) { + t.ok( + !deepEqual([ 1, 2, 3 ], { 0 : 1, 1 : 2, 2 : 3 }), + 'arrays are not objects' + ); + t.end(); +}); + +test('falsy', function (t) { + t.ok( + !deepEqual([ undefined ], [ null ]), + 'null is not undefined!' + ); + + t.ok( + !deepEqual([ null ], [ undefined ]), + 'undefined is not null!' + ); + + t.ok( + !deepEqual( + { a : 1, b : 2, c : [ 3, undefined, 5 ] }, + { a : 1, b : 2, c : [ 3, null, 5 ] } + ), + 'undefined is not null, however deeply!' + ); + + t.ok( + !deepEqual( + { a : 1, b : 2, c : [ 3, undefined, 5 ] }, + { a : 1, b : 2, c : [ 3, null, 5 ] } + ), + 'null is not undefined, however deeply!' + ); + + t.ok( + !deepEqual( + { a : 1, b : 2, c : [ 3, undefined, 5 ] }, + { a : 1, b : 2, c : [ 3, null, 5 ] } + ), + 'null is not undefined, however deeply!' + ); + + t.end(); +}); + +test('deletedArrayEqual', function (t) { + var xs = [ 1, 2, 3, 4 ]; + delete xs[2]; + + var ys = Object.create(Array.prototype); + ys[0] = 1; + ys[1] = 2; + ys[3] = 4; + + t.ok( + deepEqual(xs, ys), + 'arrays with deleted elements are only equal to' + + ' arrays with similarly deleted elements' + ); + + t.ok( + !deepEqual(xs, [ 1, 2, undefined, 4 ]), + 'deleted array elements cannot be undefined' + ); + + t.ok( + !deepEqual(xs, [ 1, 2, null, 4 ]), + 'deleted array elements cannot be null' + ); + + t.end(); +}); + +test('deletedObjectEqual', function (t) { + var obj = { a : 1, b : 2, c : 3 }; + delete obj.c; + + t.ok( + deepEqual(obj, { a : 1, b : 2 }), + 'deleted object elements should not show up' + ); + + t.ok( + !deepEqual(obj, { a : 1, b : 2, c : undefined }), + 'deleted object elements are not undefined' + ); + + t.ok( + !deepEqual(obj, { a : 1, b : 2, c : null }), + 'deleted object elements are not null' + ); + + t.end(); +}); + +test('emptyKeyEqual', function (t) { + t.ok(!deepEqual( + { a : 1 }, { a : 1, '' : 55 } + )); + + t.end(); +}); + +test('deepArguments', function (t) { + t.ok( + !deepEqual( + [ 4, 5, 6 ], + (function () { return arguments })(4, 5, 6) + ), + 'arguments are not arrays' + ); + + t.ok( + deepEqual( + (function () { return arguments })(4, 5, 6), + (function () { return arguments })(4, 5, 6) + ), + 'arguments should equal' + ); + + t.end(); +}); + +test('deepUn', function (t) { + t.ok(!deepEqual({ a : 1, b : 2 }, undefined)); + t.ok(!deepEqual({ a : 1, b : 2 }, {})); + t.ok(!deepEqual(undefined, { a : 1, b : 2 })); + t.ok(!deepEqual({}, { a : 1, b : 2 })); + t.ok(deepEqual(undefined, undefined)); + t.ok(deepEqual(null, null)); + t.ok(!deepEqual(undefined, null)); + + t.end(); +}); + +test('deepLevels', function (t) { + var xs = [ 1, 2, [ 3, 4, [ 5, 6 ] ] ]; + t.ok(!deepEqual(xs, [])); + t.end(); +}); diff --git a/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/error.js b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/error.js new file mode 100644 index 0000000000000000000000000000000000000000..447c725753a22cde15e38ec59590d7d63d34fab5 --- /dev/null +++ b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/error.js @@ -0,0 +1,11 @@ +var test = require('tape'); +var traverse = require('../'); + +test('traverse an Error', function (t) { + var obj = new Error("test"); + var results = traverse(obj).map(function (node) {}); + t.same(results, { message: 'test' }); + + t.end(); +}); + diff --git a/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/has.js b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/has.js new file mode 100644 index 0000000000000000000000000000000000000000..94a50c6a2b5776d92c25c7a08d73158ec9944f5d --- /dev/null +++ b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/has.js @@ -0,0 +1,15 @@ +var test = require('tape'); +var traverse = require('../'); + +test('has', function (t) { + var obj = { a : 2, b : [ 4, 5, { c : 6 } ] }; + + t.equal(traverse(obj).has([ 'b', 2, 'c' ]), true) + t.equal(traverse(obj).has([ 'b', 2, 'c', 0 ]), false) + t.equal(traverse(obj).has([ 'b', 2, 'd' ]), false) + t.equal(traverse(obj).has([]), true) + t.equal(traverse(obj).has([ 'a' ]), true) + t.equal(traverse(obj).has([ 'a', 2 ]), false) + + t.end(); +}); diff --git a/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/instance.js b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/instance.js new file mode 100644 index 0000000000000000000000000000000000000000..112f47721bcace9876429d2e595bd566c873f74d --- /dev/null +++ b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/instance.js @@ -0,0 +1,17 @@ +var test = require('tape'); +var traverse = require('../'); +var EventEmitter = require('events').EventEmitter; + +test('check instanceof on node elems', function (t) { + var counts = { emitter : 0 }; + + traverse([ new EventEmitter, 3, 4, { ev : new EventEmitter }]) + .forEach(function (node) { + if (node instanceof EventEmitter) counts.emitter ++; + }) + ; + + t.equal(counts.emitter, 2); + + t.end(); +}); diff --git a/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/interface.js b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/interface.js new file mode 100644 index 0000000000000000000000000000000000000000..f454c27f5126a7d43402bdc0e9f3a79d46e82cc3 --- /dev/null +++ b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/interface.js @@ -0,0 +1,43 @@ +var test = require('tape'); +var traverse = require('../'); + +test('interface map', function (t) { + var obj = { a : [ 5,6,7 ], b : { c : [8] } }; + + t.same( + traverse.paths(obj) + .sort() + .map(function (path) { return path.join('/') }) + .slice(1) + .join(' ') + , + 'a a/0 a/1 a/2 b b/c b/c/0' + ); + + t.same( + traverse.nodes(obj), + [ + { a: [ 5, 6, 7 ], b: { c: [ 8 ] } }, + [ 5, 6, 7 ], 5, 6, 7, + { c: [ 8 ] }, [ 8 ], 8 + ] + ); + + t.same( + traverse.map(obj, function (node) { + if (typeof node == 'number') { + return node + 1000; + } + else if (Array.isArray(node)) { + return node.join(' '); + } + }), + { a: '5 6 7', b: { c: '8' } } + ); + + var nodes = 0; + traverse.forEach(obj, function (node) { nodes ++ }); + t.same(nodes, 8); + + t.end(); +}); diff --git a/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/json.js b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/json.js new file mode 100644 index 0000000000000000000000000000000000000000..46d55e69cf39786fbc13337a48337ecc46d949f5 --- /dev/null +++ b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/json.js @@ -0,0 +1,49 @@ +var test = require('tape'); +var traverse = require('../'); + +test('json test', function (t) { + var id = 54; + var callbacks = {}; + var obj = { moo : function () {}, foo : [2,3,4, function () {}] }; + + var scrubbed = traverse(obj).map(function (x) { + if (typeof x === 'function') { + callbacks[id] = { id : id, f : x, path : this.path }; + this.update('[Function]'); + id++; + } + }); + + t.equal( + scrubbed.moo, '[Function]', + 'obj.moo replaced with "[Function]"' + ); + + t.equal( + scrubbed.foo[3], '[Function]', + 'obj.foo[3] replaced with "[Function]"' + ); + + t.same(scrubbed, { + moo : '[Function]', + foo : [ 2, 3, 4, "[Function]" ] + }, 'Full JSON string matches'); + + t.same( + typeof obj.moo, 'function', + 'Original obj.moo still a function' + ); + + t.same( + typeof obj.foo[3], 'function', + 'Original obj.foo[3] still a function' + ); + + t.same(callbacks, { + 54: { id: 54, f : obj.moo, path: [ 'moo' ] }, + 55: { id: 55, f : obj.foo[3], path: [ 'foo', '3' ] }, + }, 'Check the generated callbacks list'); + + t.end(); +}); + diff --git a/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/keys.js b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/keys.js new file mode 100644 index 0000000000000000000000000000000000000000..96611408db6de11d50ed96df4c2cb483d4cb84ec --- /dev/null +++ b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/keys.js @@ -0,0 +1,31 @@ +var test = require('tape'); +var traverse = require('../'); + +test('sort test', function (t) { + var acc = []; + traverse({ + a: 30, + b: 22, + id: 9 + }).forEach(function (node) { + if ((! Array.isArray(node)) && typeof node === 'object') { + this.before(function(node) { + this.keys = Object.keys(node); + this.keys.sort(function(a, b) { + a = [a === "id" ? 0 : 1, a]; + b = [b === "id" ? 0 : 1, b]; + return a < b ? -1 : a > b ? 1 : 0; + }); + }); + } + if (this.isLeaf) acc.push(node); + }); + + t.equal( + acc.join(' '), + '9 30 22', + 'Traversal in a custom order' + ); + + t.end(); +}); diff --git a/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/leaves.js b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/leaves.js new file mode 100644 index 0000000000000000000000000000000000000000..c04ad5f8b152d9ab245597ed98dab943f5794662 --- /dev/null +++ b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/leaves.js @@ -0,0 +1,22 @@ +var test = require('tape'); +var traverse = require('../'); + +test('leaves test', function (t) { + var acc = []; + traverse({ + a : [1,2,3], + b : 4, + c : [5,6], + d : { e : [7,8], f : 9 } + }).forEach(function (x) { + if (this.isLeaf) acc.push(x); + }); + + t.equal( + acc.join(' '), + '1 2 3 4 5 6 7 8 9', + 'Traversal in the right(?) order' + ); + + t.end(); +}); diff --git a/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/lib/deep_equal.js b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/lib/deep_equal.js new file mode 100644 index 0000000000000000000000000000000000000000..c75b04c2d36d45b168a021c1f6b7e82acdcabd7e --- /dev/null +++ b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/lib/deep_equal.js @@ -0,0 +1,96 @@ +var traverse = require('../../'); + +module.exports = function (a, b) { + if (arguments.length !== 2) { + throw new Error( + 'deepEqual requires exactly two objects to compare against' + ); + } + + var equal = true; + var node = b; + + traverse(a).forEach(function (y) { + var notEqual = (function () { + equal = false; + //this.stop(); + return undefined; + }).bind(this); + + //if (node === undefined || node === null) return notEqual(); + + if (!this.isRoot) { + /* + if (!Object.hasOwnProperty.call(node, this.key)) { + return notEqual(); + } + */ + if (typeof node !== 'object') return notEqual(); + node = node[this.key]; + } + + var x = node; + + this.post(function () { + node = x; + }); + + var toS = function (o) { + return Object.prototype.toString.call(o); + }; + + if (this.circular) { + if (traverse(b).get(this.circular.path) !== x) notEqual(); + } + else if (typeof x !== typeof y) { + notEqual(); + } + else if (x === null || y === null || x === undefined || y === undefined) { + if (x !== y) notEqual(); + } + else if (x.__proto__ !== y.__proto__) { + notEqual(); + } + else if (x === y) { + // nop + } + else if (typeof x === 'function') { + if (x instanceof RegExp) { + // both regexps on account of the __proto__ check + if (x.toString() != y.toString()) notEqual(); + } + else if (x !== y) notEqual(); + } + else if (typeof x === 'object') { + if (toS(y) === '[object Arguments]' + || toS(x) === '[object Arguments]') { + if (toS(x) !== toS(y)) { + notEqual(); + } + } + else if (toS(y) === '[object RegExp]' + || toS(x) === '[object RegExp]') { + if (!x || !y || x.toString() !== y.toString()) notEqual(); + } + else if (x instanceof Date || y instanceof Date) { + if (!(x instanceof Date) || !(y instanceof Date) + || x.getTime() !== y.getTime()) { + notEqual(); + } + } + else { + var kx = Object.keys(x); + var ky = Object.keys(y); + if (kx.length !== ky.length) return notEqual(); + for (var i = 0; i < kx.length; i++) { + var k = kx[i]; + if (!Object.hasOwnProperty.call(y, k)) { + notEqual(); + } + } + } + } + }); + + return equal; +}; diff --git a/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/mutability.js b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/mutability.js new file mode 100644 index 0000000000000000000000000000000000000000..3ab90dada32a8af6708cd5703d016891bcf7ac6b --- /dev/null +++ b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/mutability.js @@ -0,0 +1,300 @@ +var test = require('tape'); +var traverse = require('../'); +var deepEqual = require('./lib/deep_equal'); + +test('mutate', function (t) { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = traverse(obj).forEach(function (x) { + if (typeof x === 'number' && x % 2 === 0) { + this.update(x * 10); + } + }); + t.same(obj, res); + t.same(obj, { a : 1, b : 20, c : [ 3, 40 ] }); + t.end(); +}); + +test('mutateT', function (t) { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = traverse.forEach(obj, function (x) { + if (typeof x === 'number' && x % 2 === 0) { + this.update(x * 10); + } + }); + t.same(obj, res); + t.same(obj, { a : 1, b : 20, c : [ 3, 40 ] }); + t.end(); +}); + +test('map', function (t) { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = traverse(obj).map(function (x) { + if (typeof x === 'number' && x % 2 === 0) { + this.update(x * 10); + } + }); + t.same(obj, { a : 1, b : 2, c : [ 3, 4 ] }); + t.same(res, { a : 1, b : 20, c : [ 3, 40 ] }); + t.end(); +}); + +test('mapT', function (t) { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = traverse.map(obj, function (x) { + if (typeof x === 'number' && x % 2 === 0) { + this.update(x * 10); + } + }); + t.same(obj, { a : 1, b : 2, c : [ 3, 4 ] }); + t.same(res, { a : 1, b : 20, c : [ 3, 40 ] }); + t.end(); +}); + +test('clone', function (t) { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = traverse(obj).clone(); + t.same(obj, res); + t.ok(obj !== res); + obj.a ++; + t.same(res.a, 1); + obj.c.push(5); + t.same(res.c, [ 3, 4 ]); + t.end(); +}); + +test('cloneT', function (t) { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = traverse.clone(obj); + t.same(obj, res); + t.ok(obj !== res); + obj.a ++; + t.same(res.a, 1); + obj.c.push(5); + t.same(res.c, [ 3, 4 ]); + t.end(); +}); + +test('reduce', function (t) { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = traverse(obj).reduce(function (acc, x) { + if (this.isLeaf) acc.push(x); + return acc; + }, []); + t.same(obj, { a : 1, b : 2, c : [ 3, 4 ] }); + t.same(res, [ 1, 2, 3, 4 ]); + t.end(); +}); + +test('reduceInit', function (t) { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = traverse(obj).reduce(function (acc, x) { + if (this.isRoot) assert.fail('got root'); + return acc; + }); + t.same(obj, { a : 1, b : 2, c : [ 3, 4 ] }); + t.same(res, obj); + t.end(); +}); + +test('remove', function (t) { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + traverse(obj).forEach(function (x) { + if (this.isLeaf && x % 2 == 0) this.remove(); + }); + + t.same(obj, { a : 1, c : [ 3 ] }); + t.end(); +}); + +exports.removeNoStop = function() { + var obj = { a : 1, b : 2, c : { d: 3, e: 4 }, f: 5 }; + + var keys = []; + traverse(obj).forEach(function (x) { + keys.push(this.key) + if (this.key == 'c') this.remove(); + }); + + t.same(keys, [undefined, 'a', 'b', 'c', 'd', 'e', 'f']) + t.end(); +} + +exports.removeStop = function() { + var obj = { a : 1, b : 2, c : { d: 3, e: 4 }, f: 5 }; + + var keys = []; + traverse(obj).forEach(function (x) { + keys.push(this.key) + if (this.key == 'c') this.remove(true); + }); + + t.same(keys, [undefined, 'a', 'b', 'c', 'f']) + t.end(); +} + +test('removeMap', function (t) { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = traverse(obj).map(function (x) { + if (this.isLeaf && x % 2 == 0) this.remove(); + }); + + t.same(obj, { a : 1, b : 2, c : [ 3, 4 ] }); + t.same(res, { a : 1, c : [ 3 ] }); + t.end(); +}); + +test('delete', function (t) { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + traverse(obj).forEach(function (x) { + if (this.isLeaf && x % 2 == 0) this.delete(); + }); + + t.ok(!deepEqual( + obj, { a : 1, c : [ 3, undefined ] } + )); + + t.ok(deepEqual( + obj, { a : 1, c : [ 3 ] } + )); + + t.ok(!deepEqual( + obj, { a : 1, c : [ 3, null ] } + )); + t.end(); +}); + +test('deleteNoStop', function (t) { + var obj = { a : 1, b : 2, c : { d: 3, e: 4 } }; + + var keys = []; + traverse(obj).forEach(function (x) { + keys.push(this.key) + if (this.key == 'c') this.delete(); + }); + + t.same(keys, [undefined, 'a', 'b', 'c', 'd', 'e']) + t.end(); +}); + +test('deleteStop', function (t) { + var obj = { a : 1, b : 2, c : { d: 3, e: 4 } }; + + var keys = []; + traverse(obj).forEach(function (x) { + keys.push(this.key) + if (this.key == 'c') this.delete(true); + }); + + t.same(keys, [undefined, 'a', 'b', 'c']) + t.end(); +}); + +test('deleteRedux', function (t) { + var obj = { a : 1, b : 2, c : [ 3, 4, 5 ] }; + traverse(obj).forEach(function (x) { + if (this.isLeaf && x % 2 == 0) this.delete(); + }); + + t.ok(!deepEqual( + obj, { a : 1, c : [ 3, undefined, 5 ] } + )); + + t.ok(deepEqual( + obj, { a : 1, c : [ 3 ,, 5 ] } + )); + + t.ok(!deepEqual( + obj, { a : 1, c : [ 3, null, 5 ] } + )); + + t.ok(!deepEqual( + obj, { a : 1, c : [ 3, 5 ] } + )); + + t.end(); +}); + +test('deleteMap', function (t) { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = traverse(obj).map(function (x) { + if (this.isLeaf && x % 2 == 0) this.delete(); + }); + + t.ok(deepEqual( + obj, + { a : 1, b : 2, c : [ 3, 4 ] } + )); + + var xs = [ 3, 4 ]; + delete xs[1]; + + t.ok(deepEqual( + res, { a : 1, c : xs } + )); + + t.ok(deepEqual( + res, { a : 1, c : [ 3, ] } + )); + + t.ok(deepEqual( + res, { a : 1, c : [ 3 ] } + )); + + t.end(); +}); + +test('deleteMapRedux', function (t) { + var obj = { a : 1, b : 2, c : [ 3, 4, 5 ] }; + var res = traverse(obj).map(function (x) { + if (this.isLeaf && x % 2 == 0) this.delete(); + }); + + t.ok(deepEqual( + obj, + { a : 1, b : 2, c : [ 3, 4, 5 ] } + )); + + var xs = [ 3, 4, 5 ]; + delete xs[1]; + + t.ok(deepEqual( + res, { a : 1, c : xs } + )); + + t.ok(!deepEqual( + res, { a : 1, c : [ 3, 5 ] } + )); + + t.ok(deepEqual( + res, { a : 1, c : [ 3 ,, 5 ] } + )); + + t.end(); +}); + +test('objectToString', function (t) { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = traverse(obj).forEach(function (x) { + if (typeof x === 'object' && !this.isRoot) { + this.update(JSON.stringify(x)); + } + }); + t.same(obj, res); + t.same(obj, { a : 1, b : 2, c : "[3,4]" }); + t.end(); +}); + +test('stringToObject', function (t) { + var obj = { a : 1, b : 2, c : "[3,4]" }; + var res = traverse(obj).forEach(function (x) { + if (typeof x === 'string') { + this.update(JSON.parse(x)); + } + else if (typeof x === 'number' && x % 2 === 0) { + this.update(x * 10); + } + }); + t.deepEqual(obj, res); + t.deepEqual(obj, { a : 1, b : 20, c : [ 3, 40 ] }); + t.end(); +}); diff --git a/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/negative.js b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/negative.js new file mode 100644 index 0000000000000000000000000000000000000000..91566c80aafd8b7215e05d280074a3d33d4828fa --- /dev/null +++ b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/negative.js @@ -0,0 +1,21 @@ +var traverse = require('../'); +var test = require('tape'); + +test('negative update test', function (t) { + var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ]; + var fixed = traverse.map(obj, function (x) { + if (x < 0) this.update(x + 128); + }); + + t.same(fixed, + [ 5, 6, 125, [ 7, 8, 126, 1 ], { f: 10, g: 115 } ], + 'Negative values += 128' + ); + + t.same(obj, + [ 5, 6, -3, [ 7, 8, -2, 1 ], { f: 10, g: -13 } ], + 'Original references not modified' + ); + + t.end(); +}); diff --git a/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/obj.js b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/obj.js new file mode 100644 index 0000000000000000000000000000000000000000..8bcf58aefcf97ed961c8a83c11c2c53a91418e1f --- /dev/null +++ b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/obj.js @@ -0,0 +1,11 @@ +var test = require('tape'); +var traverse = require('../'); + +test('traverse an object with nested functions', function (t) { + t.plan(1); + + function Cons (x) { + t.equal(x, 10) + }; + traverse(new Cons(10)); +}); diff --git a/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/siblings.js b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/siblings.js new file mode 100644 index 0000000000000000000000000000000000000000..c59e557791a5f910779defc4dbde0015c62a61a2 --- /dev/null +++ b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/siblings.js @@ -0,0 +1,37 @@ +var test = require('tape'); +var traverse = require('../'); + +test('siblings', function (t) { + var obj = { a : 1, b : 2, c : [ 4, 5, 6 ] }; + + var res = traverse(obj).reduce(function (acc, x) { + var p = '/' + this.path.join('/'); + if (this.parent) { + acc[p] = { + siblings : this.parent.keys, + key : this.key, + index : this.parent.keys.indexOf(this.key) + }; + } + else { + acc[p] = { + siblings : [], + key : this.key, + index : -1 + } + } + return acc; + }, {}); + + t.same(res, { + '/' : { siblings : [], key : undefined, index : -1 }, + '/a' : { siblings : [ 'a', 'b', 'c' ], key : 'a', index : 0 }, + '/b' : { siblings : [ 'a', 'b', 'c' ], key : 'b', index : 1 }, + '/c' : { siblings : [ 'a', 'b', 'c' ], key : 'c', index : 2 }, + '/c/0' : { siblings : [ '0', '1', '2' ], key : '0', index : 0 }, + '/c/1' : { siblings : [ '0', '1', '2' ], key : '1', index : 1 }, + '/c/2' : { siblings : [ '0', '1', '2' ], key : '2', index : 2 } + }); + + t.end(); +}); diff --git a/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/stop.js b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/stop.js new file mode 100644 index 0000000000000000000000000000000000000000..9ce15b065682b090100aac3eaa9030593b602c75 --- /dev/null +++ b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/stop.js @@ -0,0 +1,44 @@ +var test = require('tape'); +var traverse = require('../'); + +test('stop', function (t) { + var visits = 0; + traverse('abcdefghij'.split('')).forEach(function (node) { + if (typeof node === 'string') { + visits ++; + if (node === 'e') this.stop() + } + }); + + t.equal(visits, 5); + t.end(); +}); + +test('stopMap', function (t) { + var s = traverse('abcdefghij'.split('')).map(function (node) { + if (typeof node === 'string') { + if (node === 'e') this.stop() + return node.toUpperCase(); + } + }).join(''); + + t.equal(s, 'ABCDEfghij'); + t.end(); +}); + +test('stopReduce', function (t) { + var obj = { + a : [ 4, 5 ], + b : [ 6, [ 7, 8, 9 ] ] + }; + var xs = traverse(obj).reduce(function (acc, node) { + if (this.isLeaf) { + if (node === 7) this.stop(); + else acc.push(node) + } + return acc; + }, []); + + t.same(xs, [ 4, 5, 6 ]); + t.end(); +}); diff --git a/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/stringify.js b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/stringify.js new file mode 100644 index 0000000000000000000000000000000000000000..f1680d8c9a7bc596bff04098fed79da513fae8d7 --- /dev/null +++ b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/stringify.js @@ -0,0 +1,36 @@ +var test = require('tape'); +var traverse = require('../'); + +test('stringify', function (t) { + var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ]; + + var s = ''; + traverse(obj).forEach(function (node) { + if (Array.isArray(node)) { + this.before(function () { s += '[' }); + this.post(function (child) { + if (!child.isLast) s += ','; + }); + this.after(function () { s += ']' }); + } + else if (typeof node == 'object') { + this.before(function () { s += '{' }); + this.pre(function (x, key) { + s += '"' + key + '"' + ':'; + }); + this.post(function (child) { + if (!child.isLast) s += ','; + }); + this.after(function () { s += '}' }); + } + else if (typeof node == 'function') { + s += 'null'; + } + else { + s += node.toString(); + } + }); + + t.equal(s, JSON.stringify(obj)); + t.end(); +}); diff --git a/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/subexpr.js b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/subexpr.js new file mode 100644 index 0000000000000000000000000000000000000000..768260888c1423b2b34767b0ab12e140ae8e7f26 --- /dev/null +++ b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/subexpr.js @@ -0,0 +1,36 @@ +var traverse = require('../'); +var test = require('tape'); + +test('subexpr', function (t) { + var obj = [ 'a', 4, 'b', 5, 'c', 6 ]; + var r = traverse(obj).map(function (x) { + if (typeof x === 'number') { + this.update([ x - 0.1, x, x + 0.1 ], true); + } + }); + + t.same(obj, [ 'a', 4, 'b', 5, 'c', 6 ]); + t.same(r, [ + 'a', [ 3.9, 4, 4.1 ], + 'b', [ 4.9, 5, 5.1 ], + 'c', [ 5.9, 6, 6.1 ], + ]); + t.end(); +}); + +test('block', function (t) { + var obj = [ [ 1 ], [ 2 ], [ 3 ] ]; + var r = traverse(obj).map(function (x) { + if (Array.isArray(x) && !this.isRoot) { + if (x[0] === 5) this.block() + else this.update([ [ x[0] + 1 ] ]) + } + }); + + t.same(r, [ + [ [ [ [ [ 5 ] ] ] ] ], + [ [ [ [ 5 ] ] ] ], + [ [ [ 5 ] ] ], + ]); + t.end(); +}); diff --git a/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/super_deep.js b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/super_deep.js new file mode 100644 index 0000000000000000000000000000000000000000..1eb9e26edb3962f387c09345c339ac933fadf86e --- /dev/null +++ b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/test/super_deep.js @@ -0,0 +1,56 @@ +var test = require('tape'); +var traverse = require('../'); +var deepEqual = require('./lib/deep_equal'); + +test('super_deep', function (t) { + var util = require('util'); + var a0 = make(); + var a1 = make(); + t.ok(deepEqual(a0, a1)); + + a0.c.d.moo = true; + t.ok(!deepEqual(a0, a1)); + + a1.c.d.moo = true; + t.ok(deepEqual(a0, a1)); + + // TODO: this one + //a0.c.a = a1; + //t.ok(!deepEqual(a0, a1)); + t.end(); +}); + +function make () { + var a = { self : 'a' }; + var b = { self : 'b' }; + var c = { self : 'c' }; + var d = { self : 'd' }; + var e = { self : 'e' }; + + a.a = a; + a.b = b; + a.c = c; + + b.a = a; + b.b = b; + b.c = c; + + c.a = a; + c.b = b; + c.c = c; + c.d = d; + + d.a = a; + d.b = b; + d.c = c; + d.d = d; + d.e = e; + + e.a = a; + e.b = b; + e.c = c; + e.d = d; + e.e = e; + + return a; +} diff --git a/test/modules-checked-in/node_modules/hashish/node_modules/traverse/testling/leaves.js b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/testling/leaves.js new file mode 100644 index 0000000000000000000000000000000000000000..29968dd13af8dd816d5d5b25accdc49084eed9bc --- /dev/null +++ b/test/modules-checked-in/node_modules/hashish/node_modules/traverse/testling/leaves.js @@ -0,0 +1,22 @@ +var traverse = require('./'); +var test = require('testling'); + +test('leaves', function (t) { + var obj = { + a : [1,2,3], + b : 4, + c : [5,6], + d : { e : [7,8], f : 9 } + }; + + var acc = []; + traverse(obj).forEach(function (x) { + if (this.isLeaf) acc.push(x); + }); + + t.deepEqual( + acc, [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + 'traversal in the proper order' + ); + t.end(); +}); diff --git a/test/modules-checked-in/node_modules/hashish/package.json b/test/modules-checked-in/node_modules/hashish/package.json new file mode 100644 index 0000000000000000000000000000000000000000..d77f2a614c67368cd02c166d3736474eafebedd5 --- /dev/null +++ b/test/modules-checked-in/node_modules/hashish/package.json @@ -0,0 +1,46 @@ +{ + "name": "hashish", + "version": "0.0.4", + "description": "Hash data structure manipulation functions", + "main": "./index.js", + "repository": { + "type": "git", + "url": "http://github.com/substack/node-hashish.git" + }, + "keywords": [ + "hash", + "object", + "convenience", + "manipulation", + "data structure" + ], + "author": { + "name": "James Halliday", + "email": "mail@substack.net", + "url": "http://substack.net" + }, + "dependencies": { + "traverse": ">=0.2.4" + }, + "devDependencies": { + "expresso": ">=0.6.0" + }, + "scripts": { + "test": "expresso" + }, + "license": "MIT/X11", + "engine": [ + "node >=0.2.0" + ], + "readme": "Hashish\n=======\n\nHashish is a node.js library for manipulating hash data structures.\nIt is distilled from the finest that ruby, perl, and haskell have to offer by\nway of hash/map interfaces.\n\nHashish provides a chaining interface, where you can do:\n\n var Hash = require('hashish');\n \n Hash({ a : 1, b : 2, c : 3, d : 4 })\n .map(function (x) { return x * 10 })\n .filter(function (x) { return x < 30 })\n .forEach(function (x, key) {\n console.log(key + ' => ' + x);\n })\n ;\n \nOutput:\n\n a => 10\n b => 20\n\nSome functions and attributes in the chaining interface are terminal, like\n`.items` or `.detect()`. They return values of their own instead of the chain\ncontext.\n\nEach function in the chainable interface is also attached to `Hash` in chainless\nform:\n\n var Hash = require('hashish');\n var obj = { a : 1, b : 2, c : 3, d : 4 };\n \n var mapped = Hash.map(obj, function (x) {\n return x * 10\n });\n \n console.dir(mapped);\n\nOutput:\n\n { a: 10, b: 20, c: 30, d: 40 }\n\nIn either case, the 'this' context of the function calls is the same object that\nthe chained functions return, so you can make nested chains.\n\nMethods\n=======\n\nforEach(cb)\n-----------\n\nFor each key/value in the hash, calls `cb(value, key)`.\n\nmap(cb)\n-------\n\nFor each key/value in the hash, calls `cb(value, key)`.\nThe return value of `cb` is the new value at `key` in the resulting hash.\n\nfilter(cb)\n----------\n\nFor each key/value in the hash, calls `cb(value, key)`.\nThe resulting hash omits key/value pairs where `cb` returned a falsy value.\n\ndetect(cb)\n----------\n\nReturns the first value in the hash for which `cb(value, key)` is non-falsy.\nOrder of hashes is not well-defined so watch out for that.\n\nreduce(cb)\n----------\n\nReturns the accumulated value of a left-fold over the key/value pairs.\n\nsome(cb)\n--------\n\nReturns a boolean: whether or not `cb(value, key)` ever returned a non-falsy\nvalue.\n\nupdate(obj1, [obj2, obj3, ...])\n-----------\n\nMutate the context hash, merging the key/value pairs from the passed objects\nand overwriting keys from the context hash if the current `obj` has keys of\nthe same name. Falsy arguments are silently ignored.\n\nupdateAll([ obj1, obj2, ... ])\n------------------------------\n\nLike multi-argument `update()` but operate on an array directly.\n\nmerge(obj1, [obj2, obj3, ...])\n----------\n\nMerge the key/value pairs from the passed objects into the resultant hash\nwithout modifying the context hash. Falsy arguments are silently ignored.\n\nmergeAll([ obj1, obj2, ... ])\n------------------------------\n\nLike multi-argument `merge()` but operate on an array directly.\n\nhas(key)\n--------\n\nReturn whether the hash has a key, `key`.\n\nvaluesAt(keys)\n--------------\n\nReturn an Array with the values at the keys from `keys`.\n\ntap(cb)\n-------\n\nCall `cb` with the present raw hash.\nThis function is chainable.\n\nextract(keys)\n-------------\n\nFilter by including only those keys in `keys` in the resulting hash.\n\nexclude(keys)\n-------------\n\nFilter by excluding those keys in `keys` in the resulting hash.\n\nAttributes\n==========\n\nThese are attributes in the chaining interface and functions in the `Hash.xxx`\ninterface.\n\nkeys\n----\n\nReturn all the enumerable attribute keys in the hash.\n\nvalues\n------\n\nReturn all the enumerable attribute values in the hash.\n\ncompact\n-------\n\nFilter out values which are `=== undefined`.\n\nclone\n-----\n\nMake a deep copy of the hash.\n\ncopy\n----\n\nMake a shallow copy of the hash.\n\nlength\n------\n\nReturn the number of key/value pairs in the hash.\nNote: use `Hash.size()` for non-chain mode.\n\nsize\n----\n\nAlias for `length` since `Hash.length` is masked by `Function.prototype`.\n\nSee Also\n========\n\nSee also [creationix's pattern/hash](http://github.com/creationix/pattern),\nwhich does a similar thing except with hash inputs and array outputs.\n\nInstallation\n============\n\nTo install with [npm](http://github.com/isaacs/npm):\n \n npm install hashish\n\nTo run the tests with [expresso](http://github.com/visionmedia/expresso):\n\n expresso\n", + "readmeFilename": "README.markdown", + "bugs": { + "url": "https://github.com/substack/node-hashish/issues" + }, + "_id": "hashish@0.0.4", + "dist": { + "shasum": "ef5af4bf63fee968e4dc040692c558a8fb4429f6" + }, + "_from": "hashish@*", + "_resolved": "https://registry.npmjs.org/hashish/-/hashish-0.0.4.tgz" +} diff --git a/test/modules-checked-in/node_modules/hashish/test/hash.js b/test/modules-checked-in/node_modules/hashish/test/hash.js new file mode 100644 index 0000000000000000000000000000000000000000..6afce60a15573ae1d6966db444ac41c8450fce2d --- /dev/null +++ b/test/modules-checked-in/node_modules/hashish/test/hash.js @@ -0,0 +1,250 @@ +var Hash = require('hashish'); +var assert = require('assert'); + +exports.map = function () { + var ref = { a : 1, b : 2 }; + var items = Hash(ref).map(function (v) { return v + 1 }).items; + var hash = Hash.map(ref, function (v) { return v + 1 }); + assert.deepEqual(ref, { a : 1, b : 2 }); + assert.deepEqual(items, { a : 2, b : 3 }); + assert.deepEqual(hash, { a : 2, b : 3 }); +}; + +exports['cloned map'] = function () { + var ref = { foo : [1,2], bar : [4,5] }; + var hash = Hash(ref).clone.map( + function (v) { v.unshift(v[0] - 1); return v } + ).items; + assert.deepEqual(ref.foo, [1,2]); + assert.deepEqual(ref.bar, [4,5]); + assert.deepEqual(hash.foo, [0,1,2]); + assert.deepEqual(hash.bar, [3,4,5]); +}; + +exports.forEach = function () { + var ref = { a : 5, b : 2, c : 7, 1337 : 'leet' }; + var xs = []; + Hash(ref).forEach(function (x, i) { + xs.push([ i, x ]); + }); + + assert.eql( + xs.map(function (x) { return x[0] }).sort(), + [ '1337', 'a', 'b', 'c' ] + ); + + assert.eql( + xs.map(function (x) { return x[1] }).sort(), + [ 2, 5, 7, 'leet' ] + ); + + var ys = []; + Hash.forEach(ref, function (x, i) { + ys.push([ i, x ]); + }); + + assert.eql(xs.sort(), ys.sort()); +}; + +exports.filter_items = function () { + var ref = { a : 5, b : 2, c : 7, 1337 : 'leet' }; + var items = Hash(ref).filter(function (v, k) { + return v > 5 || k > 5 + }).items; + var hash = Hash.filter(ref, function (v, k) { return v > 5 || k > 5 }); + assert.deepEqual(items, { 1337 : 'leet', c : 7 }); + assert.deepEqual(hash, { 1337 : 'leet', c : 7 }); + assert.deepEqual(ref, { a : 5, b : 2, c : 7, 1337 : 'leet' }); + assert.equal(Hash(ref).length, 4); +}; + +exports.detect = function () { + var h = { a : 5, b : 6, c : 7, d : 8 }; + var hh = Hash(h); + var gt6hh = hh.detect(function (x) { return x > 6 }); + assert.ok(gt6hh == 7 || gt6hh == 8); + var gt6h = Hash.detect(h, function (x) { return x > 6 }); + assert.ok(gt6h == 7 || gt6h == 8); + assert.equal(hh.detect(function (x) { return x > 100 }), undefined); +}; + +exports.reduce = function () { + var ref = { foo : [1,2], bar : [4,5] }; + + var sum1 = Hash(ref).reduce(function (acc, v) { + return acc + v.length + }, 0); + assert.equal(sum1, 4); + + var sum2 = Hash.reduce(ref, function (acc, v) { + return acc + v.length + }, 0); + assert.equal(sum2, 4); +}; + +exports.some = function () { + var h = { a : 5, b : 6, c : 7, d : 8 }; + var hh = Hash(h); + assert.ok(Hash.some(h, function (x) { return x > 7 })); + assert.ok(Hash.some(h, function (x) { return x < 6 })); + assert.ok(!Hash.some(h, function (x) { return x > 10 })); + assert.ok(!Hash.some(h, function (x) { return x < 0 })); + + assert.ok(hh.some(function (x) { return x > 7 })); + assert.ok(hh.some(function (x) { return x < 6 })); + assert.ok(!hh.some(function (x) { return x > 10 })); + assert.ok(!hh.some(function (x) { return x < 0 })); +}; + +exports.update = function () { + var ref = { a : 1, b : 2 }; + var items = Hash(ref).clone.update({ c : 3, a : 0 }).items; + assert.deepEqual(ref, { a : 1, b : 2 }); + assert.deepEqual(items, { a : 0, b : 2, c : 3 }); + + var hash = Hash.update(ref, { c : 3, a : 0 }); + assert.deepEqual(ref, hash); + assert.deepEqual(hash, { a : 0, b : 2, c : 3 }); + + var ref2 = {a: 1}; + var hash2 = Hash.update(ref2, { b: 2, c: 3 }, undefined, { d: 4 }); + assert.deepEqual(ref2, { a: 1, b: 2, c: 3, d: 4 }); +}; + +exports.merge = function () { + var ref = { a : 1, b : 2 }; + var items = Hash(ref).merge({ b : 3, c : 3.14 }).items; + var hash = Hash.merge(ref, { b : 3, c : 3.14 }); + + assert.deepEqual(ref, { a : 1, b : 2 }); + assert.deepEqual(items, { a : 1, b : 3, c : 3.14 }); + assert.deepEqual(hash, { a : 1, b : 3, c : 3.14 }); + + var ref2 = { a : 1 }; + var hash2 = Hash.merge(ref, { b: 2, c: 3 }, undefined, { d: 4 }); + assert.deepEqual(hash2, { a: 1, b: 2, c: 3, d: 4 }); +}; + +exports.has = function () { + var h = { a : 4, b : 5 }; + var hh = Hash(h); + + assert.ok(hh.has('a')); + assert.equal(hh.has('c'), false); + assert.ok(hh.has(['a','b'])); + assert.equal(hh.has(['a','b','c']), false); + + assert.ok(Hash.has(h, 'a')); + assert.equal(Hash.has(h, 'c'), false); + assert.ok(Hash.has(h, ['a','b'])); + assert.equal(Hash.has(h, ['a','b','c']), false); +}; + +exports.valuesAt = function () { + var h = { a : 4, b : 5, c : 6 }; + assert.equal(Hash(h).valuesAt('a'), 4); + assert.equal(Hash(h).valuesAt(['a'])[0], 4); + assert.deepEqual(Hash(h).valuesAt(['a','b']), [4,5]); + assert.equal(Hash.valuesAt(h, 'a'), 4); + assert.deepEqual(Hash.valuesAt(h, ['a']), [4]); + assert.deepEqual(Hash.valuesAt(h, ['a','b']), [4,5]); +}; + +exports.tap = function () { + var h = { a : 4, b : 5, c : 6 }; + var hh = Hash(h); + hh.tap(function (x) { + assert.ok(this === hh) + assert.eql(x, h); + }); + + Hash.tap(h, function (x) { + assert.eql( + Object.keys(this).sort(), + Object.keys(hh).sort() + ); + assert.eql(x, h); + }); +}; + +exports.extract = function () { + var hash = Hash({ a : 1, b : 2, c : 3 }).clone; + var extracted = hash.extract(['a','b']); + assert.equal(extracted.length, 2); + assert.deepEqual(extracted.items, { a : 1, b : 2 }); +}; + +exports.exclude = function () { + var hash = Hash({ a : 1, b : 2, c : 3 }).clone; + var extracted = hash.exclude(['a','b']); + assert.equal(extracted.length, 1); + assert.deepEqual(extracted.items, { c : 3 }); +}; + +exports.concat = function () { + var ref1 = { a : 1, b : 2 }; + var ref2 = { foo : 100, bar : 200 }; + var ref3 = { b : 3, c : 4, bar : 300 }; + + assert.deepEqual( + Hash.concat([ ref1, ref2 ]), + { a : 1, b : 2, foo : 100, bar : 200 } + ); + + assert.deepEqual( + Hash.concat([ ref1, ref2, ref3 ]), + { a : 1, b : 3, c : 4, foo : 100, bar : 300 } + ); +}; + +exports.zip = function () { + var xs = ['a','b','c']; + var ys = [1,2,3,4]; + var h = Hash(xs,ys); + assert.equal(h.length, 3); + assert.deepEqual(h.items, { a : 1, b : 2, c : 3 }); + + var zipped = Hash.zip(xs,ys); + assert.deepEqual(zipped, { a : 1, b : 2, c : 3 }); +}; + +exports.length = function () { + assert.equal(Hash({ a : 1, b : [2,3], c : 4 }).length, 3); + assert.equal(Hash({ a : 1, b : [2,3], c : 4 }).size, 3); + assert.equal(Hash.size({ a : 1, b : [2,3], c : 4 }), 3); +}; + +exports.compact = function () { + var hash = { + a : 1, + b : undefined, + c : false, + d : 4, + e : [ undefined, 4 ], + f : null + }; + var compacted = Hash(hash).compact; + assert.deepEqual( + { + a : 1, + b : undefined, + c : false, + d : 4, + e : [ undefined, 4 ], + f : null + }, + hash, 'compact modified the hash' + ); + assert.deepEqual( + compacted.items, + { + a : 1, + c : false, + d : 4, + e : [ undefined, 4 ], + f : null + } + ); + var h = Hash.compact(hash); + assert.deepEqual(h, compacted.items); +}; diff --git a/test/modules-checked-in/node_modules/hashish/test/property.js b/test/modules-checked-in/node_modules/hashish/test/property.js new file mode 100644 index 0000000000000000000000000000000000000000..1183c5d03ee31498611c9fe975e4b5d7977a7ead --- /dev/null +++ b/test/modules-checked-in/node_modules/hashish/test/property.js @@ -0,0 +1,69 @@ +var Hash = require('hashish'); +var assert = require('assert'); +var vm = require('vm'); +var fs = require('fs'); + +var src = fs.readFileSync(__dirname + '/../index.js', 'utf8'); + +exports.defineGetter = function () { + var context = { + module : { exports : {} }, + Object : { + keys : Object.keys, + defineProperty : undefined, + }, + require : require, + }; + context.exports = context.module.exports; + + vm.runInNewContext('(function () {' + src + '})()', context); + var Hash_ = context.module.exports; + + var times = 0; + Hash_.__proto__.__proto__.__defineGetter__ = function () { + times ++; + return Object.__defineGetter__.apply(this, arguments); + }; + + assert.equal(vm.runInNewContext('Object.defineProperty', context), null); + + assert.deepEqual( + Hash_({ a : 1, b : 2, c : 3 }).values, + [ 1, 2, 3 ] + ); + + assert.ok(times > 5); +}; + +exports.defineProperty = function () { + var times = 0; + var context = { + module : { exports : {} }, + Object : { + keys : Object.keys, + defineProperty : function (prop) { + times ++; + if (prop.get) throw new TypeError('engine does not support') + assert.fail('should have asserted by now'); + }, + }, + require : require + }; + context.exports = context.module.exports; + + vm.runInNewContext('(function () {' + src + '})()', context); + var Hash_ = context.module.exports; + + Hash_.__proto__.__proto__.__defineGetter__ = function () { + assert.fail('getter called when a perfectly good' + + ' defineProperty was available' + ); + }; + + assert.deepEqual( + Hash_({ a : 1, b : 2, c : 3 }).values, + [ 1, 2, 3 ] + ); + + assert.equal(times, 1); +}; diff --git a/test/modules-checked-in/package.json b/test/modules-checked-in/package.json new file mode 100644 index 0000000000000000000000000000000000000000..d5561df40ac0fe050f901cbd215eab1d2d95968d --- /dev/null +++ b/test/modules-checked-in/package.json @@ -0,0 +1,15 @@ +{ + "name": "node-buildpack-test-app", + "version": "0.0.1", + "description": "node buildpack integration test app", + "repository" : { + "type" : "git", + "url" : "http://github.com/example/example.git" + }, + "dependencies": { + "hashish": "*" + }, + "engines": { + "node": "~0.10.0" + } +} diff --git a/test/no-script-hooks/README.md b/test/no-script-hooks/README.md new file mode 100644 index 0000000000000000000000000000000000000000..cda334ae1a9cf883f9d4b40537e4502e4324d401 --- /dev/null +++ b/test/no-script-hooks/README.md @@ -0,0 +1 @@ +A fake README, to keep npm from polluting stderr. \ No newline at end of file diff --git a/test/no-script-hooks/package.json b/test/no-script-hooks/package.json new file mode 100644 index 0000000000000000000000000000000000000000..fe43c0312d012b816bbb4551706390e03c06fc5c --- /dev/null +++ b/test/no-script-hooks/package.json @@ -0,0 +1,12 @@ +{ + "name": "node-buildpack-test-app", + "version": "0.0.1", + "description": "node buildpack integration test app", + "repository" : { + "type" : "git", + "url" : "http://github.com/example/example.git" + }, + "engines": { + "node": "~0.10.0" + } +} diff --git a/test/no-version/README.md b/test/no-version/README.md new file mode 100644 index 0000000000000000000000000000000000000000..cda334ae1a9cf883f9d4b40537e4502e4324d401 --- /dev/null +++ b/test/no-version/README.md @@ -0,0 +1 @@ +A fake README, to keep npm from polluting stderr. \ No newline at end of file diff --git a/test/no-version/package.json b/test/no-version/package.json new file mode 100644 index 0000000000000000000000000000000000000000..e5379cb5b7efe323b0745a77abc3dac10ca51b50 --- /dev/null +++ b/test/no-version/package.json @@ -0,0 +1,9 @@ +{ + "name": "node-buildpack-test-app", + "version": "0.0.1", + "description": "node buildpack integration test app", + "repository" : { + "type" : "git", + "url" : "http://github.com/example/example.git" + } +} diff --git a/test/package-json-invalidversion/package.json b/test/package-json-invalidversion/package.json deleted file mode 100644 index 78c12adfb98d9e4441151207a2daa14e0be26260..0000000000000000000000000000000000000000 --- a/test/package-json-invalidversion/package.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "myapp", - "version": "0.0.1", - - "engines": { - "node": "0.6.11", - "npm": "1.1.5" - } -} diff --git a/test/package-json-noversion/package.json b/test/package-json-noversion/package.json deleted file mode 100644 index e9c82de3b22e7c14e157a7fa77dba0b8b7982b3a..0000000000000000000000000000000000000000 --- a/test/package-json-noversion/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "myapp", - "version": "0.0.1" -} diff --git a/test/package-json-version/package.json b/test/package-json-version/package.json deleted file mode 100644 index ce13aa44dcf9cb4998205b9334e4bef87a8ac883..0000000000000000000000000000000000000000 --- a/test/package-json-version/package.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "myapp", - "version": "0.0.1", - - "engines": { - "node": "0.6.11", - "npm": "1.1.9" - } -} diff --git a/test/range-with-space/README.md b/test/range-with-space/README.md new file mode 100644 index 0000000000000000000000000000000000000000..cda334ae1a9cf883f9d4b40537e4502e4324d401 --- /dev/null +++ b/test/range-with-space/README.md @@ -0,0 +1 @@ +A fake README, to keep npm from polluting stderr. \ No newline at end of file diff --git a/test/range-with-space/package.json b/test/range-with-space/package.json new file mode 100644 index 0000000000000000000000000000000000000000..5f95fe6ac762ed9e28454c814863a35e4199e942 --- /dev/null +++ b/test/range-with-space/package.json @@ -0,0 +1,12 @@ +{ + "name": "node-buildpack-test-app", + "version": "0.0.1", + "description": "node buildpack integration test app", + "repository" : { + "type" : "git", + "url" : "http://github.com/example/example.git" + }, + "engines": { + "node": ">= 0.8.x" + } +} diff --git a/test/script-hooks/README.md b/test/script-hooks/README.md new file mode 100644 index 0000000000000000000000000000000000000000..cda334ae1a9cf883f9d4b40537e4502e4324d401 --- /dev/null +++ b/test/script-hooks/README.md @@ -0,0 +1 @@ +A fake README, to keep npm from polluting stderr. \ No newline at end of file diff --git a/test/script-hooks/package.json b/test/script-hooks/package.json new file mode 100644 index 0000000000000000000000000000000000000000..dd1a3a22d479af9a56bf88955f37d88611d9eed9 --- /dev/null +++ b/test/script-hooks/package.json @@ -0,0 +1,15 @@ +{ + "name": "node-buildpack-test-app", + "version": "0.0.1", + "description": "node buildpack integration test app", + "repository" : { + "type" : "git", + "url" : "http://github.com/example/example.git" + }, + "engines": { + "node": "~0.10.0" + }, + "scripts" : { + "preinstall" : "echo preinstall hook message" + } +} diff --git a/test/stable-node/README.md b/test/stable-node/README.md new file mode 100644 index 0000000000000000000000000000000000000000..cda334ae1a9cf883f9d4b40537e4502e4324d401 --- /dev/null +++ b/test/stable-node/README.md @@ -0,0 +1 @@ +A fake README, to keep npm from polluting stderr. \ No newline at end of file diff --git a/test/stable-node/package.json b/test/stable-node/package.json new file mode 100644 index 0000000000000000000000000000000000000000..d5561df40ac0fe050f901cbd215eab1d2d95968d --- /dev/null +++ b/test/stable-node/package.json @@ -0,0 +1,15 @@ +{ + "name": "node-buildpack-test-app", + "version": "0.0.1", + "description": "node buildpack integration test app", + "repository" : { + "type" : "git", + "url" : "http://github.com/example/example.git" + }, + "dependencies": { + "hashish": "*" + }, + "engines": { + "node": "~0.10.0" + } +} diff --git a/test/unstable-version/README.md b/test/unstable-version/README.md new file mode 100644 index 0000000000000000000000000000000000000000..cda334ae1a9cf883f9d4b40537e4502e4324d401 --- /dev/null +++ b/test/unstable-version/README.md @@ -0,0 +1 @@ +A fake README, to keep npm from polluting stderr. \ No newline at end of file diff --git a/test/unstable-version/package.json b/test/unstable-version/package.json new file mode 100644 index 0000000000000000000000000000000000000000..916c34a4a6e31f9f03d843055e80482e9a79dc5f --- /dev/null +++ b/test/unstable-version/package.json @@ -0,0 +1,12 @@ +{ + "name": "node-buildpack-test-app", + "version": "0.0.1", + "description": "node buildpack integration test app", + "repository" : { + "type" : "git", + "url" : "http://github.com/example/example.git" + }, + "engines": { + "node": ">0.11.0" + } +} diff --git a/vendor/jq b/vendor/jq new file mode 100755 index 0000000000000000000000000000000000000000..96241f766694c180c240cb887952f1e04f288330 Binary files /dev/null and b/vendor/jq differ diff --git a/vendor/json/json b/vendor/json/json deleted file mode 100755 index 0eb8ed47fed92e477fe7e84af19f392568e5c164..0000000000000000000000000000000000000000 --- a/vendor/json/json +++ /dev/null @@ -1,640 +0,0 @@ -#!/usr/bin/env node -// -// json -- pipe in your JSON for nicer output and for extracting data bits -// -// See . -// - -var VERSION = "2.0.4"; - -var util = require('util'); -var pathlib = require('path'); -var runInNewContext = require('vm').runInNewContext; -var warn = console.warn; - - - -//--- exports for module usage - -exports.main = main; -exports.getVersion = getVersion; -exports.parseLookup = parseLookup; - -// As an exported API, these are still experimental: -exports.lookupDatum = lookupDatum; -exports.printDatum = printDatum; - - - -//---- globals and constants - -// Output modes. -var OM_JSONY = 1; -var OM_JSON = 2; -var OM_INSPECT = 3; -var OM_COMPACT = 4; -var OM_FROM_NAME = { - "jsony": OM_JSONY, - "json": OM_JSON, - "inspect": OM_INSPECT, - "compact": OM_COMPACT -} - - - -//---- support functions - -function getVersion() { - return VERSION; -} - -function isArray(ar) { - return ar instanceof Array || - Array.isArray(ar) || - (ar && ar !== Object.prototype && isArray(ar.__proto__)); -} - -function printHelp() { - util.puts("Usage:"); - util.puts(" | json [OPTIONS] [LOOKUPS...]"); - util.puts(""); - util.puts("Pipe in your JSON for nicer output or supply one or more `LOOKUPS`"); - util.puts("to extract a subset of the JSON. HTTP header blocks (as from `curl -i`)"); - util.puts("are skipped by default."); - util.puts(""); - util.puts("Auto-arrayification:"); - util.puts(" Adjacent objects or arrays are 'arrayified'. To attempt to avoid"); - util.puts(" false positives inside JSON strings, *adjacent* elements must"); - util.puts(" have either no whitespace separation or at least a newline"); - util.puts(" separation."); - util.puts(""); - util.puts("Examples:"); - util.puts(" # pretty printing"); - util.puts(" $ curl -s http://search.twitter.com/search.json?q=node.js | json"); - util.puts(""); - util.puts(" # lookup fields"); - util.puts(" $ curl -s http://search.twitter.com/search.json?q=node.js | json results[0]"); - util.puts(" {"); - util.puts(" \"created_at\": \"Tue, 08 Nov 2011 19:07:25 +0000\","); - util.puts(" \"from_user\": \"im2b\","); - util.puts(" ..."); - util.puts(""); - util.puts(" # array processing"); - util.puts(" $ curl -s http://search.twitter.com/search.json?q=node.js | json results \\"); - util.puts(" json -a from_user"); - util.puts(" im2b"); - util.puts(" myalltop_paul"); - util.puts(" ..."); - util.puts(""); - util.puts(" # auto-arrayification") - util.puts(" $ echo '{\"a\":1}{\"b\":2}' | json -o json-0"); - util.puts(" [{\"a\":1},{\"b\":2}]"); - util.puts(" $ echo '[1,2][3,4]' | json -o json-0"); - util.puts(" [{\"a\":1},{\"b\":2}]"); - util.puts(""); - util.puts("Options:"); - util.puts(" -h, --help print this help info and exit"); - util.puts(" --version print version of this command and exit"); - util.puts(" -q, --quiet don't warn if input isn't valid JSON"); - util.puts(""); - util.puts(" -H drop any HTTP header block (as from `curl -i ...`)"); - util.puts(" -a, --array process input as an array of separate inputs"); - util.puts(" and output in tabular form"); - util.puts(" -d DELIM delimiter string for tabular output (default is ' ')"); - util.puts(""); - util.puts(" -o, --output MODE Specify an output mode. One of"); - util.puts(" jsony (default): JSON with string quotes elided"); - util.puts(" json: JSON output, 2-space indent"); - util.puts(" json-N: JSON output, N-space indent, e.g. 'json-4'"); - util.puts(" inspect: node.js `util.inspect` output"); - util.puts(" -i shortcut for `-o inspect`"); - util.puts(" -j shortcut for `-o json`"); - util.puts(""); - util.puts("See for more complete docs."); -} - - -/** - * Parse the command-line options and arguments into an object. - * - * { - * 'args': [...] // arguments - * 'help': true, // true if '-h' option given - * // etc. - * } - * - * @return {Object} The parsed options. `.args` is the argument list. - * @throws {Error} If there is an error parsing argv. - */ -function parseArgv(argv) { - var parsed = { - args: [], - help: false, - quiet: false, - dropHeaders: false, - outputMode: OM_JSONY, - jsonIndent: 2, - delim: ' ' - }; - - // Turn '-iH' into '-i -H', except for argument-accepting options. - var args = argv.slice(2); // drop ['node', 'scriptname'] - var newArgs = []; - var optTakesArg = {'d': true, 'o': true}; - for (var i = 0; i < args.length; i++) { - if (args[i].charAt(0) === "-" && args[i].charAt(1) !== '-' && args[i].length > 2) { - var splitOpts = args[i].slice(1).split(""); - for (var j = 0; j < splitOpts.length; j++) { - newArgs.push('-' + splitOpts[j]) - if (optTakesArg[splitOpts[j]]) { - var optArg = splitOpts.slice(j+1).join(""); - if (optArg.length) { - newArgs.push(optArg); - } - break; - } - } - } else { - newArgs.push(args[i]); - } - } - args = newArgs; - - endOfOptions = false; - while (args.length > 0) { - var arg = args.shift(); - switch(arg) { - case "--": - endOfOptions = true; - break; - case "-h": // display help and exit - case "--help": - parsed.help = true; - break; - case "--version": - parsed.version = true; - break; - case "-q": - case "--quiet": - parsed.quiet = true; - break; - case "-H": // drop any headers - parsed.dropHeaders = true; - break; - case "-o": - case "--output": - var name = args.shift(); - var idx = name.lastIndexOf('-'); - if (idx !== -1) { - var indent = Number(name.slice(idx+1)); - if (! isNaN(indent)) { - parsed.jsonIndent = indent; - name = name.slice(0, idx); - } - } - parsed.outputMode = OM_FROM_NAME[name]; - if (parsed.outputMode === undefined) { - throw new Error("unknown output mode: '"+name+"'"); - } - break; - case "-i": // output with util.inspect - parsed.outputMode = OM_INSPECT; - break; - case "-j": // output with JSON.stringify - parsed.outputMode = OM_JSON; - break; - case "-a": - case "--array": - parsed.array = true; - break; - case "-d": - parsed.delim = args.shift(); - break; - default: // arguments - if (!endOfOptions && arg.length > 0 && arg[0] === '-') { - throw new Error("unknown option '"+arg+"'"); - } - parsed.args.push(arg); - break; - } - } - //TODO: '--' handling and error on a first arg that looks like an option. - - return parsed; -} - - - -function isInteger(s) { - return (s.search(/^-?[0-9]+$/) == 0); -} - - -// Parse a lookup string into a list of lookup bits. E.g.: -// "a.b.c" -> ["a","b","c"] -// "b['a']" -> ["b","['a']"] -function parseLookup(lookup) { - //var debug = console.warn; - var debug = function () {}; - - var bits = []; - debug("\n*** "+lookup+" ***") - - bits = []; - var bit = ""; - var states = [null]; - var escaped = false; - var ch = null; - for (var i=0; i < lookup.length; ++i) { - var escaped = (!escaped && ch === '\\'); - var ch = lookup[i]; - debug("-- i="+i+", ch="+JSON.stringify(ch)+" escaped="+JSON.stringify(escaped)) - debug("states: "+JSON.stringify(states)) - - if (escaped) { - bit += ch; - continue; - } - - switch (states[states.length-1]) { - case null: - switch (ch) { - case '"': - case "'": - states.push(ch); - bit += ch; - break; - case '[': - states.push(ch); - if (bit !== "") { - bits.push(bit); - bit = "" - } - bit += ch; - break; - case '.': - if (bit !== "") { - bits.push(bit); - bit = "" - } - break; - default: - bit += ch; - break; - } - break; - - case '[': - bit += ch; - switch (ch) { - case '"': - case "'": - case '[': - states.push(ch); - break; - case ']': - states.pop(); - if (states[states.length-1] === null) { - bits.push(bit); - bit = "" - } - break; - } - break; - - case '"': - bit += ch; - switch (ch) { - case '"': - states.pop(); - if (states[states.length-1] === null) { - bits.push(bit); - bit = "" - } - break; - } - break; - - case "'": - bit += ch; - switch (ch) { - case "'": - states.pop(); - if (states[states.length-1] === null) { - bits.push(bit); - bit = "" - } - break; - } - break; - } - debug("bit: "+JSON.stringify(bit)) - debug("bits: "+JSON.stringify(bits)) - } - - if (bit !== "") { - bits.push(bit); - bit = "" - } - - debug(JSON.stringify(lookup)+" -> "+JSON.stringify(bits)) - return bits -} - - -/** - * Parse the given stdin input into: - * { - * "error": ... error object if there was an error ..., - * "datum": ... parsed object if content was JSON ... - * } - */ -function parseInput(buffer) { - try { - return {datum: JSON.parse(buffer)}; - } catch(e) { - // Special case: Auto-arrayification of unjoined list of objects: - // {"one": 1}{"two": 2} - // and auto-concatenation of unjoined list of arrays: - // ["a", "b"]["c", "d"] - // - // This can be nice to process a stream of JSON objects generated from - // multiple calls to another tool or `cat *.json | json`. - // - // Rules: - // - Only JS objects and arrays. Don't see strong need for basic - // JS types right now and this limitation simplifies. - // - The break between JS objects has to include a newline: - // {"one": 1} - // {"two": 2} - // or no spaces at all: - // {"one": 1}{"two": 2} - // I.e., not this: - // {"one": 1} {"two": 2} - // This condition should be fine for typical use cases and ensures - // no false matches inside JS strings. - var newBuffer = buffer; - [/(})\s*\n\s*({)/g, /(})({")/g].forEach(function (pat) { - newBuffer = newBuffer.replace(pat, "$1,\n$2"); - }); - [/(\])\s*\n\s*(\[)/g, /(\])(\[)/g].forEach(function (pat) { - newBuffer = newBuffer.replace(pat, ",\n"); - }); - if (buffer !== newBuffer) { - newBuffer = newBuffer.trim(); - if (newBuffer[0] !== '[') { - newBuffer = '[\n' + newBuffer; - } - if (newBuffer.slice(-1) !== ']') { - newBuffer = newBuffer + '\n]\n'; - } - try { - return {datum: JSON.parse(newBuffer)}; - } catch (e2) { - } - } - - return {error: e} - } -} - - -/** - * Apply a lookup to the given datum. - * - * @argument datum {Object} - * @argument lookup {Array} The parsed lookup (from - * `parseLookup()`). Might be empty. - * @returns {Object} The result of the lookup. - */ -function lookupDatum(datum, lookup) { - // Put it back together with some convenience transformations. - var lookupCode = ""; - var isJSIdentifier = /^[$A-Za-z_][0-9A-Za-z_]*$/; - for (var i=0; i < lookup.length; i++) { - var bit = lookup[i]; - if (bit[0] === '[') { - lookupCode += bit; - } else if (! isJSIdentifier.exec(lookup[i])) { - // Allow a non-JS-indentifier token, e.g. `json foo-bar`. - lookupCode += '["' + lookup[i].replace('"', '\\"') + '"]'; - } else { - lookupCode += '.' + lookup[i]; - } - } - return runInNewContext("(" + JSON.stringify(datum) + ")" + lookupCode); -} - - - -/** - * Print out a single result, considering input options. - */ -function printDatum(datum, opts, sep, alwaysPrintSep) { - var output = null; - switch (opts.outputMode) { - case OM_INSPECT: - output = util.inspect(datum, false, Infinity, true); - break; - case OM_JSON: - if (typeof datum !== 'undefined') { - output = JSON.stringify(datum, null, opts.jsonIndent); - } - break; - case OM_COMPACT: - // Dev Note: A still relatively experimental attempt at a more - // compact ouput somewhat a la Python's repr of a dict. I.e. try to - // fit elements on one line as much as reasonable. - if (datum === undefined) { - // pass - } else if (isArray(datum)) { - var bits = ['[\n']; - datum.forEach(function (d) { - bits.push(' ') - bits.push(JSON.stringify(d, null, 0).replace(/,"(?![,:])/g, ', "')); - bits.push(',\n'); - }); - bits.push(bits.pop().slice(0, -2) + '\n') // drop last comma - bits.push(']'); - output = bits.join(''); - } else { - output = JSON.stringify(datum, null, 0); - } - break; - case OM_JSONY: - if (typeof datum === 'string') { - output = datum; - } else if (typeof datum !== 'undefined') { - output = JSON.stringify(datum, null, opts.jsonIndent); - } - break; - default: - throw new Error("unknown output mode: "+opts.outputMode); - } - if (output && output.length) { - emit(output); - emit(sep); - } else if (alwaysPrintSep) { - emit(sep); - } -} - - -var stdoutFlushed = true; -function emit(s) { - // TODO:PERF If this is try/catch is too slow (too granular): move up to - // mainline and be sure to only catch this particular error. - try { - stdoutFlushed = process.stdout.write(s); - } catch (e) { - // Handle any exceptions in stdout writing in the "error" event above. - } -} - -process.stdout.on("error", function (err) { - if (err.code === "EPIPE") { - // Pass. See . - } else { - warn(err) - drainStdoutAndExit(1); - } -}); - - -/** - * A hacked up version of "process.exit" that will first drain stdout - * before exiting. *WARNING: This doesn't stop event processing.* IOW, - * callers have to be careful that code following this call isn't - * accidentally executed. - * - * In node v0.6 "process.stdout and process.stderr are blocking when they - * refer to regular files or TTY file descriptors." However, this hack might - * still be necessary in a shell pipeline. - */ -function drainStdoutAndExit(code) { - process.stdout.on('drain', function () { - process.exit(code); - }); - if (stdoutFlushed) { - process.exit(code); - } -} - - - -//---- mainline - -function main(argv) { - var opts; - try { - opts = parseArgv(argv); - } catch (e) { - warn("json: error: %s", e.message) - return drainStdoutAndExit(1); - } - //warn(opts); - if (opts.help) { - printHelp(); - return; - } - if (opts.version) { - util.puts("json " + getVersion()); - return; - } - var lookupStrs = opts.args; - //XXX ditch this hack - if (lookupStrs.length == 0) { - lookupStrs.push(""); - } - - var buffer = ""; - - var stdin = process.openStdin(); - stdin.setEncoding('utf8'); - stdin.on('data', function (chunk) { - buffer += chunk; - }); - - stdin.on('end', function () { - // Take off a leading HTTP header if any and pass it through. - while (true) { - if (buffer.slice(0,5) === "HTTP/") { - var index = buffer.indexOf('\r\n\r\n'); - var sepLen = 4; - if (index == -1) { - index = buffer.indexOf('\n\n'); - sepLen = 2; - } - if (index != -1) { - if (! opts.dropHeaders) { - emit(buffer.slice(0, index+sepLen)); - } - var is100Continue = (buffer.slice(0, 21) === "HTTP/1.1 100 Continue"); - buffer = buffer.slice(index+sepLen); - if (is100Continue) { - continue; - } - } - } - break; - } - - // Expect the remainder to be JSON. - if (! buffer.length) { - return; - } - var input = parseInput(buffer); // -> {datum: , error: } - if (input.error) { - // Doesn't look like JSON. Just print it out and move on. - if (! opts.quiet) { - warn("json: error: doesn't look like JSON: %s (input='%s')", - input.error, JSON.stringify(buffer)); - } - emit(buffer); - if (buffer.length && buffer[buffer.length-1] !== "\n") { - emit('\n'); - } - return drainStdoutAndExit(1); - } - - // Process and output the input JSON. - var lookups = lookupStrs.map(parseLookup); - var results = []; - if (opts.array) { - var data = (isArray(input.datum) ? input.datum : [input.datum]); - if (lookups.length === 0) { - results = input.datum; - } else { - for (var j=0; j < data.length; j++) { - var result = []; - for (var i=0; i < lookups.length; i++) { - result.push(lookupDatum(data[j], lookups[i])); - } - results.push(result); - } - } - results.forEach(function (row) { - var c; - for (c = 0; c < row.length-1; c++) { - printDatum(row[c], opts, opts.delim, true); - } - printDatum(row[c], opts, '\n', true); - }); - } else { - if (lookups.length === 0) { - results = input.datum; - } else { - for (var i=0; i < lookups.length; i++) { - results.push(lookupDatum(input.datum, lookups[i])); - } - } - results.forEach(function (r) { - printDatum(r, opts, '\n', false); - }); - } - }); -} - -if (require.main === module) { - main(process.argv); -} diff --git a/vendor/node-semver/LICENSE b/vendor/node-semver/LICENSE deleted file mode 100644 index 05a4010949cac33c91988978137261559ed853f8..0000000000000000000000000000000000000000 --- a/vendor/node-semver/LICENSE +++ /dev/null @@ -1,23 +0,0 @@ -Copyright 2009, 2010, 2011 Isaac Z. Schlueter. -All rights reserved. - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/node-semver/README.md b/vendor/node-semver/README.md deleted file mode 100644 index 6fa37a3d89c5c53629b88366da918267fb6daa0a..0000000000000000000000000000000000000000 --- a/vendor/node-semver/README.md +++ /dev/null @@ -1,119 +0,0 @@ -semver(1) -- The semantic versioner for npm -=========================================== - -## Usage - - $ npm install semver - - semver.valid('1.2.3') // true - semver.valid('a.b.c') // false - semver.clean(' =v1.2.3 ') // '1.2.3' - semver.satisfies('1.2.3', '1.x || >=2.5.0 || 5.0.0 - 7.2.3') // true - semver.gt('1.2.3', '9.8.7') // false - semver.lt('1.2.3', '9.8.7') // true - -As a command-line utility: - - $ semver -h - - Usage: semver -v [-r ] - Test if version(s) satisfy the supplied range(s), - and sort them. - - Multiple versions or ranges may be supplied. - - Program exits successfully if any valid version satisfies - all supplied ranges, and prints all satisfying versions. - - If no versions are valid, or ranges are not satisfied, - then exits failure. - - Versions are printed in ascending order, so supplying - multiple versions to the utility will just sort them. - -## Versions - -A version is the following things, in this order: - -* a number (Major) -* a period -* a number (minor) -* a period -* a number (patch) -* OPTIONAL: a hyphen, followed by a number (build) -* OPTIONAL: a collection of pretty much any non-whitespace characters - (tag) - -A leading `"="` or `"v"` character is stripped off and ignored. - -## Comparisons - -The ordering of versions is done using the following algorithm, given -two versions and asked to find the greater of the two: - -* If the majors are numerically different, then take the one - with a bigger major number. `2.3.4 > 1.3.4` -* If the minors are numerically different, then take the one - with the bigger minor number. `2.3.4 > 2.2.4` -* If the patches are numerically different, then take the one with the - bigger patch number. `2.3.4 > 2.3.3` -* If only one of them has a build number, then take the one with the - build number. `2.3.4-0 > 2.3.4` -* If they both have build numbers, and the build numbers are numerically - different, then take the one with the bigger build number. - `2.3.4-10 > 2.3.4-9` -* If only one of them has a tag, then take the one without the tag. - `2.3.4 > 2.3.4-beta` -* If they both have tags, then take the one with the lexicographically - larger tag. `2.3.4-beta > 2.3.4-alpha` -* At this point, they're equal. - -## Ranges - -The following range styles are supported: - -* `>1.2.3` Greater than a specific version. -* `<1.2.3` Less than -* `1.2.3 - 2.3.4` := `>=1.2.3 <=2.3.4` -* `~1.2.3` := `>=1.2.3 <1.3.0` -* `~1.2` := `>=1.2.0 <2.0.0` -* `~1` := `>=1.0.0 <2.0.0` -* `1.2.x` := `>=1.2.0 <1.3.0` -* `1.x` := `>=1.0.0 <2.0.0` - -Ranges can be joined with either a space (which implies "and") or a -`||` (which implies "or"). - -## Functions - -* valid(v): Return the parsed version, or null if it's not valid. -* inc(v, release): Return the version incremented by the release type - (major, minor, patch, or build), or null if it's not valid. - -### Comparison - -* gt(v1, v2): `v1 > v2` -* gte(v1, v2): `v1 >= v2` -* lt(v1, v2): `v1 < v2` -* lte(v1, v2): `v1 <= v2` -* eq(v1, v2): `v1 == v2` This is true if they're logically equivalent, - even if they're not the exact same string. You already know how to - compare strings. -* neq(v1, v2): `v1 != v2` The opposite of eq. -* cmp(v1, comparator, v2): Pass in a comparison string, and it'll call - the corresponding function above. `"==="` and `"!=="` do simple - string comparison, but are included for completeness. Throws if an - invalid comparison string is provided. -* compare(v1, v2): Return 0 if v1 == v2, or 1 if v1 is greater, or -1 if - v2 is greater. Sorts in ascending order if passed to Array.sort(). -* rcompare(v1, v2): The reverse of compare. Sorts an array of versions - in descending order when passed to Array.sort(). - - -### Ranges - -* validRange(range): Return the valid range or null if it's not valid -* satisfies(version, range): Return true if the version satisfies the - range. -* maxSatisfying(versions, range): Return the highest version in the list - that satisfies the range, or null if none of them do. diff --git a/vendor/node-semver/bin/semver b/vendor/node-semver/bin/semver deleted file mode 100755 index 3e6afb40d8af8fa7282baf21dd91bb843e4aa49d..0000000000000000000000000000000000000000 --- a/vendor/node-semver/bin/semver +++ /dev/null @@ -1,71 +0,0 @@ -#!/usr/bin/env node -// Standalone semver comparison program. -// Exits successfully and prints matching version(s) if -// any supplied version is valid and passes all tests. - -var argv = process.argv.slice(2) - , versions = [] - , range = [] - , gt = [] - , lt = [] - , eq = [] - , semver = require("../semver") - -main() - -function main () { - if (!argv.length) return help() - while (argv.length) { - var a - switch (a = argv.shift()) { - case "-v": case "--version": - versions.push(argv.shift()) - break - case "-r": case "--range": - range.push(argv.shift()) - break - case "-h": case "--help": case "-?": - return help() - default: - versions.push(a) - break - } - } - - versions = versions.filter(semver.valid) - for (var i = 0, l = range.length; i < l ; i ++) { - versions = versions.filter(function (v) { - return semver.satisfies(v, range[i]) - }) - if (!versions.length) return fail() - } - return success(versions) -} - -function fail () { process.exit(1) } - -function success () { - versions.sort(semver.compare) - .map(semver.clean) - .forEach(function (v,i,_) { console.log(v) }) -} - -function help () { - console.log(["Usage: semver -v [-r ]" - ,"Test if version(s) satisfy the supplied range(s)," - ,"and sort them." - ,"" - ,"Multiple versions or ranges may be supplied." - ,"" - ,"Program exits successfully if any valid version satisfies" - ,"all supplied ranges, and prints all satisfying versions." - ,"" - ,"If no versions are valid, or ranges are not satisfied," - ,"then exits failure." - ,"" - ,"Versions are printed in ascending order, so supplying" - ,"multiple versions to the utility will just sort them." - ].join("\n")) -} - - diff --git a/vendor/node-semver/package.json b/vendor/node-semver/package.json deleted file mode 100644 index cd10e341ceb2bc3d39a86ecfa8f3c7c940e84fa1..0000000000000000000000000000000000000000 --- a/vendor/node-semver/package.json +++ /dev/null @@ -1,11 +0,0 @@ -{ "name" : "semver" -, "version" : "1.0.12" -, "description" : "The semantic version parser used by npm." -, "main" : "semver.js" -, "scripts" : { "test" : "tap test.js" } -, "devDependencies": { "tap" : "0.x >=0.0.4" } -, "license" : - { "type" : "MIT" - , "url" : "https://github.com/isaacs/semver/raw/master/LICENSE" } -, "repository" : "git://github.com/isaacs/node-semver.git" -, "bin" : { "semver" : "./bin/semver" } } diff --git a/vendor/node-semver/semver.js b/vendor/node-semver/semver.js deleted file mode 100644 index ab9c652465d1b6dfb9dedfe09be8d34f42ff9698..0000000000000000000000000000000000000000 --- a/vendor/node-semver/semver.js +++ /dev/null @@ -1,304 +0,0 @@ -;(function (exports) { // nothing in here is node-specific. - -// See http://semver.org/ -// This implementation is a *hair* less strict in that it allows -// v1.2.3 things, and also tags that don't begin with a char. - -var semver = "\\s*[v=]*\\s*([0-9]+)" // major - + "\\.([0-9]+)" // minor - + "\\.([0-9]+)" // patch - + "(-[0-9]+-?)?" // build - + "([a-zA-Z-][a-zA-Z0-9-\.:]*)?" // tag - , exprComparator = "^((<|>)?=?)\s*("+semver+")$|^$" - , xRangePlain = "[v=]*([0-9]+|x|X|\\*)" - + "(?:\\.([0-9]+|x|X|\\*)" - + "(?:\\.([0-9]+|x|X|\\*)" - + "([a-zA-Z-][a-zA-Z0-9-\.:]*)?)?)?" - , xRange = "((?:<|>)?=?)?\\s*" + xRangePlain - , exprSpermy = "(?:~>?)"+xRange - , expressions = exports.expressions = - { parse : new RegExp("^\\s*"+semver+"\\s*$") - , parsePackage : new RegExp("^\\s*([^\/]+)[-@](" +semver+")\\s*$") - , parseRange : new RegExp( - "^\\s*(" + semver + ")\\s+-\\s+(" + semver + ")\\s*$") - , validComparator : new RegExp("^"+exprComparator+"$") - , parseXRange : new RegExp("^"+xRange+"$") - , parseSpermy : new RegExp("^"+exprSpermy+"$") - } - - -Object.getOwnPropertyNames(expressions).forEach(function (i) { - exports[i] = function (str) { - return ("" + (str || "")).match(expressions[i]) - } -}) - -exports.rangeReplace = ">=$1 <=$7" -exports.clean = clean -exports.compare = compare -exports.satisfies = satisfies -exports.gt = gt -exports.gte = gte -exports.lt = lt -exports.lte = lte -exports.eq = eq -exports.neq = neq -exports.cmp = cmp -exports.inc = inc - -exports.valid = valid -exports.validPackage = validPackage -exports.validRange = validRange -exports.maxSatisfying = maxSatisfying - -exports.replaceStars = replaceStars -exports.toComparators = toComparators - -function stringify (version) { - var v = version - return [v[1]||'', v[2]||'', v[3]||''].join(".") + (v[4]||'') + (v[5]||'') -} - -function clean (version) { - version = exports.parse(version) - if (!version) return version - return stringify(version) -} - -function valid (version) { - if (typeof version !== "string") return null - return exports.parse(version) && version.trim().replace(/^[v=]+/, '') -} - -function validPackage (version) { - if (typeof version !== "string") return null - return version.match(expressions.parsePackage) && version.trim() -} - -// range can be one of: -// "1.0.3 - 2.0.0" range, inclusive, like ">=1.0.3 <=2.0.0" -// ">1.0.2" like 1.0.3 - 9999.9999.9999 -// ">=1.0.2" like 1.0.2 - 9999.9999.9999 -// "<2.0.0" like 0.0.0 - 1.9999.9999 -// ">1.0.2 <2.0.0" like 1.0.3 - 1.9999.9999 -var starExpression = /(<|>)?=?\s*\*/g - , starReplace = "" - , compTrimExpression = new RegExp("((<|>)?=?)\\s*(" - +semver+"|"+xRangePlain+")", "g") - , compTrimReplace = "$1$3" - -function toComparators (range) { - var ret = (range || "").trim() - .replace(expressions.parseRange, exports.rangeReplace) - .replace(compTrimExpression, compTrimReplace) - .split(/\s+/) - .join(" ") - .split("||") - .map(function (orchunk) { - return orchunk - .split(" ") - .map(replaceXRanges) - .map(replaceSpermies) - .map(replaceStars) - .join(" ").trim() - }) - .map(function (orchunk) { - return orchunk - .trim() - .split(/\s+/) - .filter(function (c) { return c.match(expressions.validComparator) }) - }) - .filter(function (c) { return c.length }) - return ret -} - -function replaceStars (stars) { - return stars.trim().replace(starExpression, starReplace) -} - -// "2.x","2.x.x" --> ">=2.0.0- <2.1.0-" -// "2.3.x" --> ">=2.3.0- <2.4.0-" -function replaceXRanges (ranges) { - return ranges.split(/\s+/) - .map(replaceXRange) - .join(" ") -} - -function replaceXRange (version) { - return version.trim().replace(expressions.parseXRange, - function (v, gtlt, M, m, p, t) { - var anyX = !M || M.toLowerCase() === "x" || M === "*" - || !m || m.toLowerCase() === "x" || m === "*" - || !p || p.toLowerCase() === "x" || p === "*" - , ret = v - - if (gtlt && anyX) { - // just replace x'es with zeroes - ;(!M || M === "*" || M.toLowerCase() === "x") && (M = 0) - ;(!m || m === "*" || m.toLowerCase() === "x") && (m = 0) - ;(!p || p === "*" || p.toLowerCase() === "x") && (p = 0) - ret = gtlt + M+"."+m+"."+p+"-" - } else if (!M || M === "*" || M.toLowerCase() === "x") { - ret = "*" // allow any - } else if (!m || m === "*" || m.toLowerCase() === "x") { - // append "-" onto the version, otherwise - // "1.x.x" matches "2.0.0beta", since the tag - // *lowers* the version value - ret = ">="+M+".0.0- <"+(+M+1)+".0.0-" - } else if (!p || p === "*" || p.toLowerCase() === "x") { - ret = ">="+M+"."+m+".0- <"+M+"."+(+m+1)+".0-" - } - //console.error("parseXRange", [].slice.call(arguments), ret) - return ret - }) -} - -// ~, ~> --> * (any, kinda silly) -// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0 -// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0 -// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0 -// ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0 -// ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0 -function replaceSpermies (version) { - return version.trim().replace(expressions.parseSpermy, - function (v, gtlt, M, m, p, t) { - if (gtlt) throw new Error( - "Using '"+gtlt+"' with ~ makes no sense. Don't do it.") - - if (!M || M.toLowerCase() === "x") { - return "" - } - // ~1 == >=1.0.0- <2.0.0- - if (!m || m.toLowerCase() === "x") { - return ">="+M+".0.0- <"+(+M+1)+".0.0-" - } - // ~1.2 == >=1.2.0- <1.3.0- - if (!p || p.toLowerCase() === "x") { - return ">="+M+"."+m+".0- <"+M+"."+(+m+1)+".0-" - } - // ~1.2.3 == >=1.2.3- <1.3.0- - t = t || "-" - return ">="+M+"."+m+"."+p+t+" <"+M+"."+(+m+1)+".0-" - }) -} - -function validRange (range) { - range = replaceStars(range) - var c = toComparators(range) - return (c.length === 0) - ? null - : c.map(function (c) { return c.join(" ") }).join("||") -} - -// returns the highest satisfying version in the list, or undefined -function maxSatisfying (versions, range) { - return versions - .filter(function (v) { return satisfies(v, range) }) - .sort(compare) - .pop() -} -function satisfies (version, range) { - version = valid(version) - if (!version) return false - range = toComparators(range) - for (var i = 0, l = range.length ; i < l ; i ++) { - var ok = false - for (var j = 0, ll = range[i].length ; j < ll ; j ++) { - var r = range[i][j] - , gtlt = r.charAt(0) === ">" ? gt - : r.charAt(0) === "<" ? lt - : false - , eq = r.charAt(!!gtlt) === "=" - , sub = (!!eq) + (!!gtlt) - if (!gtlt) eq = true - r = r.substr(sub) - r = (r === "") ? r : valid(r) - ok = (r === "") || (eq && r === version) || (gtlt && gtlt(version, r)) - if (!ok) break - } - if (ok) return true - } - return false -} - -// return v1 > v2 ? 1 : -1 -function compare (v1, v2) { - var g = gt(v1, v2) - return g === null ? 0 : g ? 1 : -1 -} - -function rcompare (v1, v2) { - return compare(v2, v1) -} - -function lt (v1, v2) { return gt(v2, v1) } -function gte (v1, v2) { return !lt(v1, v2) } -function lte (v1, v2) { return !gt(v1, v2) } -function eq (v1, v2) { return gt(v1, v2) === null } -function neq (v1, v2) { return gt(v1, v2) !== null } -function cmp (v1, c, v2) { - switch (c) { - case ">": return gt(v1, v2) - case "<": return lt(v1, v2) - case ">=": return gte(v1, v2) - case "<=": return lte(v1, v2) - case "==": return eq(v1, v2) - case "!=": return neq(v1, v2) - case "===": return v1 === v2 - case "!==": return v1 !== v2 - default: throw new Error("Y U NO USE VALID COMPARATOR!? "+c) - } -} - -// return v1 > v2 -function num (v) { - return v === undefined ? -1 : parseInt((v||"0").replace(/[^0-9]+/g, ''), 10) -} -function gt (v1, v2) { - v1 = exports.parse(v1) - v2 = exports.parse(v2) - if (!v1 || !v2) return false - - for (var i = 1; i < 5; i ++) { - v1[i] = num(v1[i]) - v2[i] = num(v2[i]) - if (v1[i] > v2[i]) return true - else if (v1[i] !== v2[i]) return false - } - // no tag is > than any tag, or use lexicographical order. - var tag1 = v1[5] || "" - , tag2 = v2[5] || "" - - // kludge: null means they were equal. falsey, and detectable. - // embarrassingly overclever, though, I know. - return tag1 === tag2 ? null - : !tag1 ? true - : !tag2 ? false - : tag1 > tag2 -} - -function inc (version, release) { - version = exports.parse(version) - if (!version) return null - - var parsedIndexLookup = - { 'major': 1 - , 'minor': 2 - , 'patch': 3 - , 'build': 4 } - var incIndex = parsedIndexLookup[release] - if (incIndex === undefined) return null - - var current = num(version[incIndex]) - version[incIndex] = current === -1 ? 1 : current + 1 - - for (var i = incIndex + 1; i < 5; i ++) { - if (num(version[i]) !== -1) version[i] = "0" - } - - if (version[4]) version[4] = "-" + version[4] - version[5] = "" - - return stringify(version) -} -})(typeof exports === "object" ? exports : semver = {}) diff --git a/vendor/node-semver/test.js b/vendor/node-semver/test.js deleted file mode 100644 index c28fe39701a4f2ce5da3f93794c941c9d300dd00..0000000000000000000000000000000000000000 --- a/vendor/node-semver/test.js +++ /dev/null @@ -1,397 +0,0 @@ -var tap = require("tap") - , test = tap.test - , semver = require("./semver.js") - , eq = semver.eq - , gt = semver.gt - , lt = semver.lt - , neq = semver.neq - , cmp = semver.cmp - , gte = semver.gte - , lte = semver.lte - , satisfies = semver.satisfies - , validRange = semver.validRange - , inc = semver.inc - , replaceStars = semver.replaceStars - , toComparators = semver.toComparators - -tap.plan(8) - -test("\ncomparison tests", function (t) { -; [ ["0.0.0", "0.0.0foo"] - , ["0.0.1", "0.0.0"] - , ["1.0.0", "0.9.9"] - , ["0.10.0", "0.9.0"] - , ["0.99.0", "0.10.0"] - , ["2.0.0", "1.2.3"] - , ["v0.0.0", "0.0.0foo"] - , ["v0.0.1", "0.0.0"] - , ["v1.0.0", "0.9.9"] - , ["v0.10.0", "0.9.0"] - , ["v0.99.0", "0.10.0"] - , ["v2.0.0", "1.2.3"] - , ["0.0.0", "v0.0.0foo"] - , ["0.0.1", "v0.0.0"] - , ["1.0.0", "v0.9.9"] - , ["0.10.0", "v0.9.0"] - , ["0.99.0", "v0.10.0"] - , ["2.0.0", "v1.2.3"] - , ["1.2.3", "1.2.3-asdf"] - , ["1.2.3-4", "1.2.3"] - , ["1.2.3-4-foo", "1.2.3"] - , ["1.2.3-5", "1.2.3-5-foo"] - , ["1.2.3-5", "1.2.3-4"] - , ["1.2.3-5-foo", "1.2.3-5-Foo"] - ].forEach(function (v) { - var v0 = v[0] - , v1 = v[1] - t.ok(gt(v0, v1), "gt('"+v0+"', '"+v1+"')") - t.ok(lt(v1, v0), "lt('"+v1+"', '"+v0+"')") - t.ok(!gt(v1, v0), "!gt('"+v1+"', '"+v0+"')") - t.ok(!lt(v0, v1), "!lt('"+v0+"', '"+v1+"')") - t.ok(eq(v0, v0), "eq('"+v0+"', '"+v0+"')") - t.ok(eq(v1, v1), "eq('"+v1+"', '"+v1+"')") - t.ok(neq(v0, v1), "neq('"+v0+"', '"+v1+"')") - t.ok(cmp(v1, "==", v1), "cmp('"+v1+"' == '"+v1+"')") - t.ok(cmp(v0, ">=", v1), "cmp('"+v0+"' >= '"+v1+"')") - t.ok(cmp(v1, "<=", v0), "cmp('"+v1+"' <= '"+v0+"')") - t.ok(cmp(v0, "!=", v1), "cmp('"+v0+"' != '"+v1+"')") - }) - t.end() -}) - -test("\nequality tests", function (t) { -; [ ["1.2.3", "v1.2.3"] - , ["1.2.3", "=1.2.3"] - , ["1.2.3", "v 1.2.3"] - , ["1.2.3", "= 1.2.3"] - , ["1.2.3", " v1.2.3"] - , ["1.2.3", " =1.2.3"] - , ["1.2.3", " v 1.2.3"] - , ["1.2.3", " = 1.2.3"] - , ["1.2.3-0", "v1.2.3-0"] - , ["1.2.3-0", "=1.2.3-0"] - , ["1.2.3-0", "v 1.2.3-0"] - , ["1.2.3-0", "= 1.2.3-0"] - , ["1.2.3-0", " v1.2.3-0"] - , ["1.2.3-0", " =1.2.3-0"] - , ["1.2.3-0", " v 1.2.3-0"] - , ["1.2.3-0", " = 1.2.3-0"] - , ["1.2.3-01", "v1.2.3-1"] - , ["1.2.3-01", "=1.2.3-1"] - , ["1.2.3-01", "v 1.2.3-1"] - , ["1.2.3-01", "= 1.2.3-1"] - , ["1.2.3-01", " v1.2.3-1"] - , ["1.2.3-01", " =1.2.3-1"] - , ["1.2.3-01", " v 1.2.3-1"] - , ["1.2.3-01", " = 1.2.3-1"] - , ["1.2.3beta", "v1.2.3beta"] - , ["1.2.3beta", "=1.2.3beta"] - , ["1.2.3beta", "v 1.2.3beta"] - , ["1.2.3beta", "= 1.2.3beta"] - , ["1.2.3beta", " v1.2.3beta"] - , ["1.2.3beta", " =1.2.3beta"] - , ["1.2.3beta", " v 1.2.3beta"] - , ["1.2.3beta", " = 1.2.3beta"] - ].forEach(function (v) { - var v0 = v[0] - , v1 = v[1] - t.ok(eq(v0, v1), "eq('"+v0+"', '"+v1+"')") - t.ok(!neq(v0, v1), "!neq('"+v0+"', '"+v1+"')") - t.ok(cmp(v0, "==", v1), "cmp("+v0+"=="+v1+")") - t.ok(!cmp(v0, "!=", v1), "!cmp("+v0+"!="+v1+")") - t.ok(!cmp(v0, "===", v1), "!cmp("+v0+"==="+v1+")") - t.ok(cmp(v0, "!==", v1), "cmp("+v0+"!=="+v1+")") - t.ok(!gt(v0, v1), "!gt('"+v0+"', '"+v1+"')") - t.ok(gte(v0, v1), "gte('"+v0+"', '"+v1+"')") - t.ok(!lt(v0, v1), "!lt('"+v0+"', '"+v1+"')") - t.ok(lte(v0, v1), "lte('"+v0+"', '"+v1+"')") - }) - t.end() -}) - - -test("\nrange tests", function (t) { -; [ ["1.0.0 - 2.0.0", "1.2.3"] - , ["1.0.0", "1.0.0"] - , [">=*", "0.2.4"] - , ["", "1.0.0"] - , ["*", "1.2.3"] - , ["*", "v1.2.3-foo"] - , [">=1.0.0", "1.0.0"] - , [">=1.0.0", "1.0.1"] - , [">=1.0.0", "1.1.0"] - , [">1.0.0", "1.0.1"] - , [">1.0.0", "1.1.0"] - , ["<=2.0.0", "2.0.0"] - , ["<=2.0.0", "1.9999.9999"] - , ["<=2.0.0", "0.2.9"] - , ["<2.0.0", "1.9999.9999"] - , ["<2.0.0", "0.2.9"] - , [">= 1.0.0", "1.0.0"] - , [">= 1.0.0", "1.0.1"] - , [">= 1.0.0", "1.1.0"] - , ["> 1.0.0", "1.0.1"] - , ["> 1.0.0", "1.1.0"] - , ["<= 2.0.0", "2.0.0"] - , ["<= 2.0.0", "1.9999.9999"] - , ["<= 2.0.0", "0.2.9"] - , ["< 2.0.0", "1.9999.9999"] - , ["<\t2.0.0", "0.2.9"] - , [">=0.1.97", "v0.1.97"] - , [">=0.1.97", "0.1.97"] - , ["0.1.20 || 1.2.4", "1.2.4"] - , [">=0.2.3 || <0.0.1", "0.0.0"] - , [">=0.2.3 || <0.0.1", "0.2.3"] - , [">=0.2.3 || <0.0.1", "0.2.4"] - , ["||", "1.3.4"] - , ["2.x.x", "2.1.3"] - , ["1.2.x", "1.2.3"] - , ["1.2.x || 2.x", "2.1.3"] - , ["1.2.x || 2.x", "1.2.3"] - , ["x", "1.2.3"] - , ["2.*.*", "2.1.3"] - , ["1.2.*", "1.2.3"] - , ["1.2.* || 2.*", "2.1.3"] - , ["1.2.* || 2.*", "1.2.3"] - , ["*", "1.2.3"] - , ["2", "2.1.2"] - , ["2.3", "2.3.1"] - , ["~2.4", "2.4.0"] // >=2.4.0 <2.5.0 - , ["~2.4", "2.4.5"] - , ["~>3.2.1", "3.2.2"] // >=3.2.1 <3.3.0 - , ["~1", "1.2.3"] // >=1.0.0 <2.0.0 - , ["~>1", "1.2.3"] - , ["~> 1", "1.2.3"] - , ["~1.0", "1.0.2"] // >=1.0.0 <1.1.0 - , ["~ 1.0", "1.0.2"] - , [">=1", "1.0.0"] - , [">= 1", "1.0.0"] - , ["<1.2", "1.1.1"] - , ["< 1.2", "1.1.1"] - , ["1", "1.0.0beta"] - , ["~v0.5.4-pre", "0.5.5"] - , ["~v0.5.4-pre", "0.5.4"] - ].forEach(function (v) { - t.ok(satisfies(v[1], v[0]), v[0]+" satisfied by "+v[1]) - }) - t.end() -}) - -test("\nnegative range tests", function (t) { -; [ ["1.0.0 - 2.0.0", "2.2.3"] - , ["1.0.0", "1.0.1"] - , [">=1.0.0", "0.0.0"] - , [">=1.0.0", "0.0.1"] - , [">=1.0.0", "0.1.0"] - , [">1.0.0", "0.0.1"] - , [">1.0.0", "0.1.0"] - , ["<=2.0.0", "3.0.0"] - , ["<=2.0.0", "2.9999.9999"] - , ["<=2.0.0", "2.2.9"] - , ["<2.0.0", "2.9999.9999"] - , ["<2.0.0", "2.2.9"] - , [">=0.1.97", "v0.1.93"] - , [">=0.1.97", "0.1.93"] - , ["0.1.20 || 1.2.4", "1.2.3"] - , [">=0.2.3 || <0.0.1", "0.0.3"] - , [">=0.2.3 || <0.0.1", "0.2.2"] - , ["2.x.x", "1.1.3"] - , ["2.x.x", "3.1.3"] - , ["1.2.x", "1.3.3"] - , ["1.2.x || 2.x", "3.1.3"] - , ["1.2.x || 2.x", "1.1.3"] - , ["2.*.*", "1.1.3"] - , ["2.*.*", "3.1.3"] - , ["1.2.*", "1.3.3"] - , ["1.2.* || 2.*", "3.1.3"] - , ["1.2.* || 2.*", "1.1.3"] - , ["2", "1.1.2"] - , ["2.3", "2.4.1"] - , ["~2.4", "2.5.0"] // >=2.4.0 <2.5.0 - , ["~2.4", "2.3.9"] - , ["~>3.2.1", "3.3.2"] // >=3.2.1 <3.3.0 - , ["~>3.2.1", "3.2.0"] // >=3.2.1 <3.3.0 - , ["~1", "0.2.3"] // >=1.0.0 <2.0.0 - , ["~>1", "2.2.3"] - , ["~1.0", "1.1.0"] // >=1.0.0 <1.1.0 - , ["<1", "1.0.0"] - , [">=1.2", "1.1.1"] - , ["1", "2.0.0beta"] - , ["~v0.5.4-beta", "0.5.4-alpha"] - , ["<1", "1.0.0beta"] - , ["< 1", "1.0.0beta"] - ].forEach(function (v) { - t.ok(!satisfies(v[1], v[0]), v[0]+" not satisfied by "+v[1]) - }) - t.end() -}) - -test("\nincrement versions test", function (t) { -; [ [ "1.2.3", "major", "2.0.0" ] - , [ "1.2.3", "minor", "1.3.0" ] - , [ "1.2.3", "patch", "1.2.4" ] - , [ "1.2.3", "build", "1.2.3-1" ] - , [ "1.2.3-4", "build", "1.2.3-5" ] - , [ "1.2.3tag", "major", "2.0.0" ] - , [ "1.2.3-tag", "major", "2.0.0" ] - , [ "1.2.3tag", "build", "1.2.3-1" ] - , [ "1.2.3-tag", "build", "1.2.3-1" ] - , [ "1.2.3-4-tag", "build", "1.2.3-5" ] - , [ "1.2.3-4tag", "build", "1.2.3-5" ] - , [ "1.2.3", "fake", null ] - , [ "fake", "major", null ] - ].forEach(function (v) { - t.equal(inc(v[0], v[1]), v[2], "inc("+v[0]+", "+v[1]+") === "+v[2]) - }) - - t.end() -}) - -test("\nreplace stars test", function (t) { -; [ [ "", "" ] - , [ "*", "" ] - , [ "> *", "" ] - , [ "<*", "" ] - , [ " >= *", "" ] - , [ "* || 1.2.3", " || 1.2.3" ] - ].forEach(function (v) { - t.equal(replaceStars(v[0]), v[1], "replaceStars("+v[0]+") === "+v[1]) - }) - - t.end() -}) - -test("\nvalid range test", function (t) { -; [ ["1.0.0 - 2.0.0", ">=1.0.0 <=2.0.0"] - , ["1.0.0", "1.0.0"] - , [">=*", ""] - , ["", ""] - , ["*", ""] - , ["*", ""] - , [">=1.0.0", ">=1.0.0"] - , [">1.0.0", ">1.0.0"] - , ["<=2.0.0", "<=2.0.0"] - , ["1", ">=1.0.0- <2.0.0-"] - , ["<=2.0.0", "<=2.0.0"] - , ["<=2.0.0", "<=2.0.0"] - , ["<2.0.0", "<2.0.0"] - , ["<2.0.0", "<2.0.0"] - , [">= 1.0.0", ">=1.0.0"] - , [">= 1.0.0", ">=1.0.0"] - , [">= 1.0.0", ">=1.0.0"] - , ["> 1.0.0", ">1.0.0"] - , ["> 1.0.0", ">1.0.0"] - , ["<= 2.0.0", "<=2.0.0"] - , ["<= 2.0.0", "<=2.0.0"] - , ["<= 2.0.0", "<=2.0.0"] - , ["< 2.0.0", "<2.0.0"] - , ["< 2.0.0", "<2.0.0"] - , [">=0.1.97", ">=0.1.97"] - , [">=0.1.97", ">=0.1.97"] - , ["0.1.20 || 1.2.4", "0.1.20||1.2.4"] - , [">=0.2.3 || <0.0.1", ">=0.2.3||<0.0.1"] - , [">=0.2.3 || <0.0.1", ">=0.2.3||<0.0.1"] - , [">=0.2.3 || <0.0.1", ">=0.2.3||<0.0.1"] - , ["||", "||"] - , ["2.x.x", ">=2.0.0- <3.0.0-"] - , ["1.2.x", ">=1.2.0- <1.3.0-"] - , ["1.2.x || 2.x", ">=1.2.0- <1.3.0-||>=2.0.0- <3.0.0-"] - , ["1.2.x || 2.x", ">=1.2.0- <1.3.0-||>=2.0.0- <3.0.0-"] - , ["x", ""] - , ["2.*.*", null] - , ["1.2.*", null] - , ["1.2.* || 2.*", null] - , ["1.2.* || 2.*", null] - , ["*", ""] - , ["2", ">=2.0.0- <3.0.0-"] - , ["2.3", ">=2.3.0- <2.4.0-"] - , ["~2.4", ">=2.4.0- <2.5.0-"] - , ["~2.4", ">=2.4.0- <2.5.0-"] - , ["~>3.2.1", ">=3.2.1- <3.3.0-"] - , ["~1", ">=1.0.0- <2.0.0-"] - , ["~>1", ">=1.0.0- <2.0.0-"] - , ["~> 1", ">=1.0.0- <2.0.0-"] - , ["~1.0", ">=1.0.0- <1.1.0-"] - , ["~ 1.0", ">=1.0.0- <1.1.0-"] - , ["<1", "<1.0.0-"] - , ["< 1", "<1.0.0-"] - , [">=1", ">=1.0.0-"] - , [">= 1", ">=1.0.0-"] - , ["<1.2", "<1.2.0-"] - , ["< 1.2", "<1.2.0-"] - , ["1", ">=1.0.0- <2.0.0-"] - ].forEach(function (v) { - t.equal(validRange(v[0]), v[1], "validRange("+v[0]+") === "+v[1]) - }) - - t.end() -}) - -test("\ncomparators test", function (t) { -; [ ["1.0.0 - 2.0.0", [[">=1.0.0", "<=2.0.0"]] ] - , ["1.0.0", [["1.0.0"]] ] - , [">=*", [[">=0.0.0-"]] ] - , ["", [[""]]] - , ["*", [[""]] ] - , ["*", [[""]] ] - , [">=1.0.0", [[">=1.0.0"]] ] - , [">=1.0.0", [[">=1.0.0"]] ] - , [">=1.0.0", [[">=1.0.0"]] ] - , [">1.0.0", [[">1.0.0"]] ] - , [">1.0.0", [[">1.0.0"]] ] - , ["<=2.0.0", [["<=2.0.0"]] ] - , ["1", [[">=1.0.0-", "<2.0.0-"]] ] - , ["<=2.0.0", [["<=2.0.0"]] ] - , ["<=2.0.0", [["<=2.0.0"]] ] - , ["<2.0.0", [["<2.0.0"]] ] - , ["<2.0.0", [["<2.0.0"]] ] - , [">= 1.0.0", [[">=1.0.0"]] ] - , [">= 1.0.0", [[">=1.0.0"]] ] - , [">= 1.0.0", [[">=1.0.0"]] ] - , ["> 1.0.0", [[">1.0.0"]] ] - , ["> 1.0.0", [[">1.0.0"]] ] - , ["<= 2.0.0", [["<=2.0.0"]] ] - , ["<= 2.0.0", [["<=2.0.0"]] ] - , ["<= 2.0.0", [["<=2.0.0"]] ] - , ["< 2.0.0", [["<2.0.0"]] ] - , ["<\t2.0.0", [["<2.0.0"]] ] - , [">=0.1.97", [[">=0.1.97"]] ] - , [">=0.1.97", [[">=0.1.97"]] ] - , ["0.1.20 || 1.2.4", [["0.1.20"], ["1.2.4"]] ] - , [">=0.2.3 || <0.0.1", [[">=0.2.3"], ["<0.0.1"]] ] - , [">=0.2.3 || <0.0.1", [[">=0.2.3"], ["<0.0.1"]] ] - , [">=0.2.3 || <0.0.1", [[">=0.2.3"], ["<0.0.1"]] ] - , ["||", [[""], [""]] ] - , ["2.x.x", [[">=2.0.0-", "<3.0.0-"]] ] - , ["1.2.x", [[">=1.2.0-", "<1.3.0-"]] ] - , ["1.2.x || 2.x", [[">=1.2.0-", "<1.3.0-"], [">=2.0.0-", "<3.0.0-"]] ] - , ["1.2.x || 2.x", [[">=1.2.0-", "<1.3.0-"], [">=2.0.0-", "<3.0.0-"]] ] - , ["x", [[""]] ] - , ["2.*.*", [[">=2.0.0-", "<3.0.0-"]] ] - , ["1.2.*", [[">=1.2.0-", "<1.3.0-"]] ] - , ["1.2.* || 2.*", [[">=1.2.0-", "<1.3.0-"], [">=2.0.0-", "<3.0.0-"]] ] - , ["1.2.* || 2.*", [[">=1.2.0-", "<1.3.0-"], [">=2.0.0-", "<3.0.0-"]] ] - , ["*", [[""]] ] - , ["2", [[">=2.0.0-", "<3.0.0-"]] ] - , ["2.3", [[">=2.3.0-", "<2.4.0-"]] ] - , ["~2.4", [[">=2.4.0-", "<2.5.0-"]] ] - , ["~2.4", [[">=2.4.0-", "<2.5.0-"]] ] - , ["~>3.2.1", [[">=3.2.1-", "<3.3.0-"]] ] - , ["~1", [[">=1.0.0-", "<2.0.0-"]] ] - , ["~>1", [[">=1.0.0-", "<2.0.0-"]] ] - , ["~> 1", [[">=1.0.0-", "<2.0.0-"]] ] - , ["~1.0", [[">=1.0.0-", "<1.1.0-"]] ] - , ["~ 1.0", [[">=1.0.0-", "<1.1.0-"]] ] - , ["<1", [["<1.0.0-"]] ] - , ["< 1", [["<1.0.0-"]] ] - , [">=1", [[">=1.0.0-"]] ] - , [">= 1", [[">=1.0.0-"]] ] - , ["<1.2", [["<1.2.0-"]] ] - , ["< 1.2", [["<1.2.0-"]] ] - , ["1", [[">=1.0.0-", "<2.0.0-"]] ] - ].forEach(function (v) { - t.equivalent(toComparators(v[0]), v[1], "toComparators("+v[0]+") === "+JSON.stringify(v[1])) - }) - - t.end() -})