Commit 0b761f14 authored by Hunter Loftis's avatar Hunter Loftis

Merge pull request #155 from heroku/master-merge-yoga

Merge yoga
parents f4798c6c 6163a226
Heroku Buildpack for Node.js # Heroku Buildpack for Node.js
============================
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. 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.
How it Works ## How it Works
------------
Here's an overview of what this buildpack does: Apps are built via one of four paths:
- Uses the [semver.io](https://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. 1. A regular `npm install` (default scenario)
- Allows any recent version of node to be used, including [pre-release versions](https://semver.io/node.json). 2. Copy existing `node_modules` from cache, then `npm prune`, then `npm install` (subsequent builds)
- Uses an [S3 caching proxy](https://github.com/heroku/s3pository#readme) of nodejs.org for faster downloads of the node binary. 3. No build (if package.json doesn't exist but server.js does)
- Discourages use of dangerous semver ranges like `*` and `>0.10`. 4. Run `npm run preinstall`, `npm rebuild`, `npm run postinstall` (`node_modules` are checked into source control)
- 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). You should only use #3 (omitting package.json) for quick tests or experiments.
You should never use #4 - it's included for backwards-compatibility and will generate warnings.
Checking in `node_modules` is an antipattern.
For more information, see [the npm docs](https://docs.npmjs.com/misc/faq#should-i-check-my-node_modules-folder-into-git-)
Documentation For technical details, check out the [heavily-commented compile script](https://github.com/heroku/heroku-buildpack-nodejs/blob/master/bin/compile).
-------------
## Documentation
For more information about using Node.js and buildpacks on Heroku, see these Dev Center articles: For more information about using Node.js and buildpacks on Heroku, see these Dev Center articles:
...@@ -36,36 +31,128 @@ For more information about using Node.js and buildpacks on Heroku, see these Dev ...@@ -36,36 +31,128 @@ For more information about using Node.js and buildpacks on Heroku, see these Dev
- [Buildpack API](https://devcenter.heroku.com/articles/buildpack-api) - [Buildpack API](https://devcenter.heroku.com/articles/buildpack-api)
Try npm@next ## Legacy Compatibility
------------
Use [the preview](https://github.com/heroku/heroku-buildpack-nodejs/tree/yoga) For most Node.js apps this buildpack should work just fine.
of the upcoming Node buildpack release, which lets you specify a version of If, however, you're unable to deploy using this new version of the buildpack, you can get your app working again by locking it to the previous version:
npm just like you already specify a version of node:
``` ```
heroku config:set BUILDPACK_URL=https://github.com/heroku/heroku-buildpack-nodejs#v63 -a my-app
git commit -am "empty" --allow-empty
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.
## Options
### Specify a node version
Set engines.node in package.json to the semver range
(or specific version) of node you'd like to use.
(It's a good idea to make this the same version you use during development)
```json
"engines": { "engines": {
"node": "0.10.x", "node": "0.11.x"
"npm": "2.x" }
```
```json
"engines": {
"node": "0.10.33"
} }
``` ```
Default: the
[latest stable version.](http://semver.io/node)
### Specify an npm version
Legacy Compatibility Set engines.npm in package.json to the semver range
-------------------- (or specific version) of npm you'd like to use.
(It's a good idea to make this the same version you use during development)
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: Since 'npm 2' shipped several major bugfixes, you might try:
```json
"engines": {
"npm": "2.x"
}
```
```json
"engines": {
"npm": "^2.1.0"
}
``` ```
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 Default: the version of npm bundled with your node install (varies).
### Enable or disable node_modules caching
For a 'clean' build without using any cached node modules:
```shell
heroku config:set NODE_MODULES_CACHE=false
git commit -am 'rebuild' --allow-empty
git push heroku master git push heroku master
heroku config:unset NODE_MODULES_CACHE
``` ```
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. Caching node_modules between builds dramatically speeds up build times.
However, `npm install` doesn't automatically update already-installed modules
as long as they fall within acceptable semver ranges,
which can lead to outdated modules.
Default: `NODE_MODULES_CACHE` defaults to true
### Enable or disable devDependencies installation
During local development, `npm install` installs all dependencies
and all devDependencies (test frameworks, build tools, etc).
This is usually something you want to avoid in production, so
npm has a 'production' config that can be set through the environment:
To install *dependencies only:*
```shell
heroku config:set NPM_CONFIG_PRODUCTION=true
```
To install *dependencies and devDependencies:*
```shell
heroku config:set NPM_CONFIG_PRODUCTION=false
```
Hacking Default: `NPM_CONFIG_PRODUCTION` defaults to true on Heroku
-------
### Configure npm with .npmrc
Sometimes, a project needs custom npm behavior to set up proxies,
use a different registry, etc. For such behavior,
just include an `.npmrc` file in the root of your project:
```
# .npmrc
registry = 'https://custom-registry.com/'
```
### Chain Node with multiple buildpacks
This buildpack automatically exports node, npm, and any node_modules binaries
into the `$PATH` for easy use in subsequent buildpacks.
## Feedback
Having trouble? Dig it? Feature request?
- [help.heroku.com](https://help.heroku.com/)
- [@hunterloftis](http://twitter.com/hunterloftis)
- [github issues](https://github.com/heroku/heroku-buildpack-nodejs/issues)
## 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: 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:
...@@ -80,9 +167,7 @@ heroku config:set BUILDPACK_URL=<your-github-url> ...@@ -80,9 +167,7 @@ heroku config:set BUILDPACK_URL=<your-github-url>
heroku config:set BUILDPACK_URL=<your-github-url>#your-branch heroku config:set BUILDPACK_URL=<your-github-url>#your-branch
``` ```
## Testing
Testing
-------
[Anvil](https://github.com/ddollar/anvil) is a generic build server for Heroku. [Anvil](https://github.com/ddollar/anvil) is a generic build server for Heroku.
......
...@@ -3,15 +3,45 @@ error() { ...@@ -3,15 +3,45 @@ error() {
exit 1 exit 1
} }
status() { head() {
echo ""
echo "-----> $*" echo "-----> $*"
} }
info() {
#echo "`date +\"%M:%S\"` $*"
echo " $*"
}
build_failed() {
head "Build failed"
}
protip() { protip() {
tip=$1
url=$2
echo echo
echo "PRO TIP: $*" | indent echo "PRO TIP: $tip" | indent
echo "See https://devcenter.heroku.com/articles/nodejs-support" | indent echo "See ${url:-https://devcenter.heroku.com/articles/nodejs-support}" | indent
echo }
file_contents() {
if test -f $1; then
echo "$(cat $1)"
else
echo ""
fi
}
package_json() {
if test -f $build_dir/package.json; then
local result="$(cat $build_dir/package.json | $bp_dir/vendor/jq -r $1)"
if [ "$result" == "null" ]; then echo ""
else echo "$result"
fi
else
echo ""
fi
} }
# sed -l basically makes sed replace and buffer through stdin to stdout # sed -l basically makes sed replace and buffer through stdin to stdout
...@@ -31,13 +61,15 @@ cat_npm_debug_log() { ...@@ -31,13 +61,15 @@ cat_npm_debug_log() {
export_env_dir() { export_env_dir() {
env_dir=$1 env_dir=$1
whitelist_regex=${2:-''}
blacklist_regex=${3:-'^(PATH|GIT_DIR|CPATH|CPPATH|LD_PRELOAD|LIBRARY_PATH)$'}
if [ -d "$env_dir" ]; then if [ -d "$env_dir" ]; then
for e in $(ls $env_dir); do whitelist_regex=${2:-''}
echo "$e" | grep -E "$whitelist_regex" | grep -qvE "$blacklist_regex" && blacklist_regex=${3:-'^(PATH|GIT_DIR|CPATH|CPPATH|LD_PRELOAD|LIBRARY_PATH)$'}
export "$e=$(cat $env_dir/$e)" if [ -d "$env_dir" ]; then
: for e in $(ls $env_dir); do
done echo "$e" | grep -E "$whitelist_regex" | grep -qvE "$blacklist_regex" &&
export "$e=$(cat $env_dir/$e)"
:
done
fi
fi fi
} }
This diff is collapsed.
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
if [ -f $1/package.json ]; then if [ -f $1/package.json ]; then
echo "Node.js" && exit 0 echo "Node.js" && exit 0
elif [ -f $1/server.js ]; then
echo "Node.js" && exit 0
else else
echo "no" && exit 1 echo "no" && exit 1
fi fi
...@@ -14,118 +14,278 @@ testDetectWithoutPackageJson() { ...@@ -14,118 +14,278 @@ testDetectWithoutPackageJson() {
testNoVersion() { testNoVersion() {
compile "no-version" compile "no-version"
assertCaptured "Node engine: unspecified"
assertCaptured "PRO TIP: Specify a node version in package.json" assertCaptured "PRO TIP: Specify a node version in package.json"
assertCaptured "Defaulting to latest stable node" assertCaptured "Resolving node version (latest stable) via semver.io"
assertCaptured "Downloading and installing node 0.10"
assertCapturedSuccess assertCapturedSuccess
} }
testDangerousRangeStar() { testSpecificVersion() {
compile "dangerous-range-star" compile "specific-version"
assertCaptured "PRO TIP: Avoid using semver ranges like '*'" assertNotCaptured "Resolving node version"
assertCaptured "Requested node range: *" assertCaptured "Downloading and installing node 0.10.29"
assertCaptured "Resolved node version: 0.10"
assertCapturedSuccess assertCapturedSuccess
} }
testDangerousRangeGreaterThan() { testStableVersion() {
compile "dangerous-range-greater-than" compile "stable-node"
assertCaptured "PRO TIP: Avoid using semver ranges starting with '>'" assertCaptured "Downloading and installing node 0.10"
assertCaptured "Requested node range: >" assertNotCaptured "PRO TIP"
assertCaptured "Resolved node version: 0.10."
assertCapturedSuccess assertCapturedSuccess
} }
testRangeWithSpace() { testUnstableVersion() {
compile "range-with-space" compile "unstable-version"
assertCaptured "Requested node range: >= 0.8.x" assertCaptured "Resolving node version >0.11.0 via semver.io"
assertCaptured "Resolved node version: 0.10." assertCaptured "Downloading and installing node 0.11"
assertCapturedSuccess assertCapturedSuccess
} }
testStableVersion() { testInfoEmpty() {
compile "stable-node" compile "info-empty"
assertNotCaptured "PRO TIP: Avoid using semver" assertCaptured "Node engine: unspecified"
assertNotCaptured "PRO TIP: Specify" assertCaptured "Npm engine: unspecified"
assertCaptured "Resolved node version" assertCaptured "Start mechanism: none"
assertCaptured "node_modules source: package.json"
assertCaptured "node_modules cached: false"
assertCapturedSuccess assertCapturedSuccess
} }
testUnstableVersion() { testDangerousRangeStar() {
compile "unstable-version" compile "dangerous-range-star"
assertCaptured "Requested node range: >0.11.0" assertCaptured "PRO TIP: Avoid semver ranges like '*'"
assertCaptured "Resolved node version: 0.11." assertCaptured "Node engine: *"
assertCaptured "Resolving node version * via semver.io"
assertCaptured "Downloading and installing node 0.10"
assertCapturedSuccess assertCapturedSuccess
} }
testProfileCreated() { testDangerousRangeGreaterThan() {
compile "stable-node" compile "dangerous-range-greater-than"
assertCaptured "Building runtime environment" assertCaptured "PRO TIP: Avoid semver ranges starting with '>'"
assertFile "export PATH=\"\$HOME/vendor/node/bin:\$HOME/bin:\$HOME/node_modules/.bin:\$PATH\";" ".profile.d/nodejs.sh" assertCaptured "Resolving node version >0.4 via semver.io"
assertCaptured "Downloading and installing node 0.10"
assertCapturedSuccess
}
testRangeWithSpace() {
compile "range-with-space"
assertCaptured "Resolving node version >= 0.8.x via semver.io"
assertCaptured "Downloading and installing node 0.10"
assertCapturedSuccess assertCapturedSuccess
} }
testInvalidDependency() { testInvalidDependency() {
compile "invalid-dependency" compile "invalid-dependency"
assertCaptured "not in the npm registry" assertCaptured "npm ERR! 404"
assertCapturedError 1 "" assertCapturedError 1 ""
} }
testNodeModulesCached() { testNodeModulesCached() {
cache=$(mktmpdir) cache=$(mktmpdir)
compile "caching" $cache compile "caching" $cache
assertCaptured "Caching node" assertCaptured "Caching node_modules for future builds"
assertEquals "1" "$(ls -1 $cache/ | wc -l)" assertEquals "1" "$(ls -1 $cache/ | wc -l)"
} }
testBuildWithCache() {
cache=$(mktmpdir)
compile "stable-node" $cache
assertCaptured "node_modules cached: false"
assertCaptured "Caching node_modules for future builds"
assertCapturedSuccess
compile "stable-node" $cache
assertCaptured "node_modules cached: true"
assertCaptured "Restoring node modules from cache"
assertCapturedSuccess
}
testModulesCheckedIn() { testModulesCheckedIn() {
compile "modules-checked-in" compile "modules-checked-in"
assertCaptured "Found existing node_modules directory; skipping cache" assertCaptured "node_modules source: prebuilt"
assertCaptured "Rebuilding any native dependencies" assertCaptured "(preinstall script)"
assertCaptured "Rebuilding any native modules for this architecture"
assertCaptured "(postinstall script)"
assertNotCaptured "Restoring node modules"
assertNotCaptured "Pruning unused dependencies"
assertNotCaptured "Installing any new modules"
assertNotCaptured "Installing node modules"
assertNotCaptured "Deduping dependency tree"
assertCapturedSuccess assertCapturedSuccess
} }
testUserConfig() { testUserConfig() {
compile "userconfig" compile "userconfig"
assertCaptured "https://www.google.com/" assertCaptured "www.google.com"
assertCaptured "registry error" assertCaptured "registry error"
assertCapturedError 1 "" assertCapturedError 1 ""
} }
testProcfile() {
compile "procfile-present-only"
assertCaptured "Start mechanism: Procfile"
assertNotCaptured "new Procfile"
assertCapturedSuccess
}
testProcfileAbsentNpmStartPresent() { testProcfileAbsentNpmStartPresent() {
compile "procfile-absent-npm-start-present" compile "procfile-absent-npm-start-present"
assertCaptured "No Procfile found; Adding npm start to new Procfile" assertCaptured "Start mechanism: npm start"
assertCaptured "Adding 'web: npm start' to new Procfile"
assertFile "web: npm start" "Procfile" assertFile "web: npm start" "Procfile"
assertCapturedSuccess assertCapturedSuccess
} }
testProcfileAbsentNpmStartAbsent() { testProcfileAbsentNpmStartAbsent() {
compile "procfile-absent-npm-start-absent" compile "procfile-absent-npm-start-absent"
assertCaptured "Create a Procfile or specify a start script in package.json" assertCaptured "Start mechanism: none"
assertNotCaptured "new Procfile"
assertCapturedSuccess assertCapturedSuccess
} }
testProcfileAbsentNpmStartPresent() { testProcfileAbsentServerPresent() {
compile "procfile-absent-npm-start-present" compile "procfile-absent-server-present"
assertCaptured "No Procfile found; Adding npm start to new Procfile" assertCaptured "Start mechanism: server.js"
assertFile "web: npm start" "Procfile" assertCaptured "'web: node server.js' to new Procfile"
assertFile "web: node server.js" "Procfile"
assertCapturedSuccess assertCapturedSuccess
} }
testEnvDirNotImported() { testServerPresentOnly() {
compile "stable-node" compile "server-present-only"
assertNotCaptured "Exporting config vars to environment" assertCaptured "PRO TIP: Use 'npm init'"
assertCaptured "Skipping dependencies"
assertCaptured "'web: node server.js' to new Procfile"
assertFile "web: node server.js" "Procfile"
assertCapturedSuccess assertCapturedSuccess
} }
testEnvDirExported() { testEnvVars() {
env_dir=$(mktmpdir) env_dir=$(mktmpdir)
echo "chicken" > $env_dir/birds echo "false" > $env_dir/NPM_CONFIG_PRODUCTION
echo "koi" > $env_dir/fish
compile "stable-node" "$(mktmpdir)" $env_dir compile "stable-node" "$(mktmpdir)" $env_dir
assertCaptured "Exporting config vars to environment" assertCaptured "NPM_CONFIG_PRODUCTION=false"
assertCapturedSuccess
}
testNoEnvVars() {
env_dir=$(mktmpdir)
compile "stable-node" "$(mktmpdir)" $env_dir
assertCaptured "NPM_CONFIG_PRODUCTION=true"
assertCapturedSuccess
}
testNoDevDependencies() {
compile "dev-dependencies"
assertNotCaptured "lodash"
assertCapturedSuccess assertCapturedSuccess
} }
testDevDependencies() {
env_dir=$(mktmpdir)
echo "false" > $env_dir/NPM_CONFIG_PRODUCTION
compile "dev-dependencies" "$(mktmpdir)" $env_dir
assertCaptured "lodash"
assertCapturedSuccess
}
testOptionalDependencies() {
env_dir=$(mktmpdir)
#echo "true" > $env_dir/NPM_CONFIG_OPTIONAL
compile "optional-dependencies" "$(mktmpdir)" $env_dir
assertNotCaptured "NPM_CONFIG_OPTIONAL"
assertCaptured "less"
assertCaptured "mime"
assertCaptured "mkdirp"
assertCaptured "clean-css"
assertCaptured "request"
assertCapturedSuccess
}
testNoOptionalDependencies() {
env_dir=$(mktmpdir)
echo "false" > $env_dir/NPM_CONFIG_OPTIONAL
compile "optional-dependencies" "$(mktmpdir)" $env_dir
assertCaptured "NPM_CONFIG_OPTIONAL=false"
assertCaptured "less"
assertNotCaptured "mime"
assertNotCaptured "mkdirp"
assertNotCaptured "clean-css"
assertNotCaptured "request"
assertCapturedSuccess
}
testDisableCache() {
cache=$(mktmpdir)
env_dir=$(mktmpdir)
compile "node-modules-cache-1" $cache
assertCaptured "lodash@1.0.0"
assertCapturedSuccess
compile "node-modules-cache-2" $cache
assertCaptured "lodash@1.0.0"
assertCapturedSuccess
echo "false" > $env_dir/NODE_MODULES_CACHE
compile "node-modules-cache-2" $cache $env_dir
assertCaptured "lodash@1.3.1"
assertCapturedSuccess
}
testNpmrc() {
compile "dev-dependencies"
assertNotCaptured "lodash"
assertCapturedSuccess
compile "dev-dependencies-npmrc"
assertCaptured "lodash"
assertCapturedSuccess
}
testShrinkwrap() {
compile "shrinkwrap"
assertCaptured "express@4.10.4"
assertCaptured "lodash@2.4.0"
assertNotCaptured "mocha"
assertCapturedSuccess
}
testNpmVersionRange() {
compile "npm-version-range"
assertCaptured "Resolving npm version"
assertCaptured "installing npm 1.4."
assertCapturedSuccess
}
testNpmVersionSpecific() {
compile "npm-version-specific"
assertCaptured "installing npm 2.1.11"
assertNotCaptured "Resolving npm version"
assertCapturedSuccess
}
testProfileExport() {
compile "stable-node"
assertCaptured "Creating runtime environment"
assertFileContains "export PATH=\"\$HOME/.heroku/node/bin:\$HOME/bin:\$HOME/node_modules/.bin:\$PATH\"" "${compile_dir}/.profile.d/nodejs.sh"
assertFileContains "export NODE_HOME=\"\$HOME/.heroku/node\"" "${compile_dir}/.profile.d/nodejs.sh"
assertCapturedSuccess
}
testMultiExport() {
compile "stable-node"
assertFileContains "export PATH=" "${bp_dir}/export"
assertFileContains "/.heroku/node/bin:" "${bp_dir}/export"
assertFileContains "/node_modules/.bin:\$PATH" "${bp_dir}/export"
assertFileContains "export NODE_HOME=" "${bp_dir}/export"
assertFileContains "/.heroku/node\"" "${bp_dir}/export"
assertCapturedSuccess
}
# Utils # Utils
pushd $(dirname 0) >/dev/null pushd $(dirname 0) >/dev/null
......
if [ "$node_engine" == "" ]; then
protip "Specify a node version in package.json" "https://devcenter.heroku.com/articles/nodejs-support#specifying-a-node-js-version"
elif [ "$node_engine" == "*" ]; then
protip "Avoid semver ranges like '*' in engines.node" "https://devcenter.heroku.com/articles/nodejs-support#specifying-a-node-js-version"
elif [ ${node_engine:0:1} == ">" ]; then
protip "Avoid semver ranges starting with '>' in engines.node" "https://devcenter.heroku.com/articles/nodejs-support#specifying-a-node-js-version"
fi
if [ "$modules_source" == "prebuilt" ]; then
protip "Avoid checking node_modules into source control" "https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git-"
elif [ "$modules_source" == "" ]; then
protip "Use 'npm init' and 'npm install --save' to define dependencies"
fi
if [ "$start_method" == "" ]; then
protip "Include a Procfile, package.json start script, or server.js file to start your app" "https://devcenter.heroku.com/articles/nodejs-support#runtime-behavior"
fi
A fake README, to keep npm from polluting stderr.
\ No newline at end of file
{
"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": {
},
"engines": {
"node": "~0.10.0"
},
"devDependencies": {
"lodash": "^2.4.1"
}
}
A fake README, to keep npm from polluting stderr.
\ No newline at end of file
{
"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"
},
"devDependencies": {
"lodash": "^2.4.1"
}
}
A fake README, to keep npm from polluting stderr.
\ No newline at end of file
{
"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": {
}
}
...@@ -6,6 +6,10 @@ ...@@ -6,6 +6,10 @@
"type" : "git", "type" : "git",
"url" : "http://github.com/example/example.git" "url" : "http://github.com/example/example.git"
}, },
"scripts": {
"preinstall": "echo '(preinstall script)'",
"postinstall": "echo '(postinstall script)'"
},
"dependencies": { "dependencies": {
"hashish": "*" "hashish": "*"
}, },
......
A fake README, to keep npm from polluting stderr.
\ No newline at end of file
{
"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": {
"lodash": "1.0.0"
},
"engines": {
"node": "~0.10.0"
}
}
A fake README, to keep npm from polluting stderr.
\ No newline at end of file
{
"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": {
"lodash": "^1.0.0"
},
"engines": {
"node": "~0.10.0"
}
}
A fake README, to keep npm from polluting stderr.
\ No newline at end of file
{
"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.33",
"npm": "1.4.x"
}
}
A fake README, to keep npm from polluting stderr.
\ No newline at end of file
{
"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",
"npm": "2.1.11"
}
}
A fake README, to keep npm from polluting stderr.
\ No newline at end of file
{
"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": {
"less": "1.7.0"
},
"engines": {
"node": "0.10.x"
},
"scripts": {
"start": "node foo.js"
}
}
A fake README, to keep npm from polluting stderr.
\ No newline at end of file
{
"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"
}
}
A fake README, to keep npm from polluting stderr.
\ No newline at end of file
A fake README, to keep npm from polluting stderr.
\ No newline at end of file
A fake README, to keep npm from polluting stderr.
\ No newline at end of file
{
"name": "node-buildpack-test-app",
"version": "0.0.1",
"dependencies": {
"express": {
"version": "4.10.4",
"from": "express@4.10.4",
"resolved": "https://registry.npmjs.org/express/-/express-4.10.4.tgz",
"dependencies": {
"accepts": {
"version": "1.1.3",
"from": "accepts@~1.1.3",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.1.3.tgz",
"dependencies": {
"mime-types": {
"version": "2.0.3",
"from": "mime-types@~2.0.3",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.3.tgz",
"dependencies": {
"mime-db": {
"version": "1.2.0",
"from": "mime-db@~1.2.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.2.0.tgz"
}
}
},
"negotiator": {
"version": "0.4.9",
"from": "negotiator@0.4.9",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.4.9.tgz"
}
}
},
"content-disposition": {
"version": "0.5.0",
"from": "content-disposition@0.5.0",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.0.tgz"
},
"cookie-signature": {
"version": "1.0.5",
"from": "cookie-signature@1.0.5",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.5.tgz"
},
"debug": {
"version": "2.1.0",
"from": "debug@~2.1.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.1.0.tgz",
"dependencies": {
"ms": {
"version": "0.6.2",
"from": "ms@0.6.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz"
}
}
},
"depd": {
"version": "1.0.0",
"from": "depd@~1.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-1.0.0.tgz"
},
"escape-html": {
"version": "1.0.1",
"from": "escape-html@1.0.1",
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.1.tgz"
},
"etag": {
"version": "1.5.1",
"from": "etag@~1.5.1",
"resolved": "https://registry.npmjs.org/etag/-/etag-1.5.1.tgz",
"dependencies": {
"crc": {
"version": "3.2.1",
"from": "crc@3.2.1",
"resolved": "https://registry.npmjs.org/crc/-/crc-3.2.1.tgz"
}
}
},
"finalhandler": {
"version": "0.3.2",
"from": "finalhandler@0.3.2",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.3.2.tgz"
},
"fresh": {
"version": "0.2.4",
"from": "fresh@0.2.4",
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.2.4.tgz"
},
"media-typer": {
"version": "0.3.0",
"from": "media-typer@0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz"
},
"methods": {
"version": "1.1.0",
"from": "methods@1.1.0",
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.0.tgz"
},
"on-finished": {
"version": "2.1.1",
"from": "on-finished@~2.1.1",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.1.1.tgz",
"dependencies": {
"ee-first": {
"version": "1.1.0",
"from": "ee-first@1.1.0",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.0.tgz"
}
}
},
"parseurl": {
"version": "1.3.0",
"from": "parseurl@~1.3.0",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.0.tgz"
},
"path-to-regexp": {
"version": "0.1.3",
"from": "path-to-regexp@0.1.3",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.3.tgz"
},
"proxy-addr": {
"version": "1.0.4",
"from": "proxy-addr@~1.0.4",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.0.4.tgz",
"dependencies": {
"forwarded": {
"version": "0.1.0",
"from": "forwarded@~0.1.0",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.0.tgz"
},
"ipaddr.js": {
"version": "0.1.5",
"from": "ipaddr.js@0.1.5",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-0.1.5.tgz"
}
}
},
"qs": {
"version": "2.3.3",
"from": "qs@2.3.3",
"resolved": "https://registry.npmjs.org/qs/-/qs-2.3.3.tgz"
},
"range-parser": {
"version": "1.0.2",
"from": "range-parser@~1.0.2",
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.0.2.tgz"
},
"send": {
"version": "0.10.1",
"from": "send@0.10.1",
"resolved": "https://registry.npmjs.org/send/-/send-0.10.1.tgz",
"dependencies": {
"destroy": {
"version": "1.0.3",
"from": "destroy@1.0.3",
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.3.tgz"
},
"mime": {
"version": "1.2.11",
"from": "mime@1.2.11",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz"
},
"ms": {
"version": "0.6.2",
"from": "ms@0.6.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz"
}
}
},
"serve-static": {
"version": "1.7.1",
"from": "serve-static@~1.7.1",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.7.1.tgz"
},
"type-is": {
"version": "1.5.3",
"from": "type-is@~1.5.3",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.5.3.tgz",
"dependencies": {
"mime-types": {
"version": "2.0.3",
"from": "mime-types@~2.0.3",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.3.tgz",
"dependencies": {
"mime-db": {
"version": "1.2.0",
"from": "mime-db@~1.2.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.2.0.tgz"
}
}
}
}
},
"vary": {
"version": "1.0.0",
"from": "vary@~1.0.0",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.0.0.tgz"
},
"cookie": {
"version": "0.1.2",
"from": "cookie@0.1.2",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.1.2.tgz"
},
"merge-descriptors": {
"version": "0.0.2",
"from": "merge-descriptors@0.0.2",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-0.0.2.tgz"
},
"utils-merge": {
"version": "1.0.0",
"from": "utils-merge@1.0.0",
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz"
}
}
},
"lodash": {
"version": "2.4.0",
"from": "lodash@2.4.0",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.0.tgz"
}
}
}
{
"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": {
"express": "4.10.4",
"lodash": "^2.4.0"
},
"engines": {
"node": "~0.10.0"
},
"devDependencies": {
"mocha": "2.0.1"
}
}
A fake README, to keep npm from polluting stderr.
\ No newline at end of file
{
"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.29"
}
}
...@@ -11,5 +11,8 @@ ...@@ -11,5 +11,8 @@
}, },
"engines": { "engines": {
"node": "~0.10.0" "node": "~0.10.0"
},
"scripts": {
"start": "node foo.js"
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment