From 3ca076926c31e50a42fe2a3985f761ffcbe8310d Mon Sep 17 00:00:00 2001 From: Raees Iqbal Date: Wed, 19 Feb 2020 17:17:42 +0500 Subject: [PATCH 1/4] Add support for .env files --- package-lock.json | 301 +++++++++++++++++- package.json | 2 + src/commands/dev/index.js | 9 +- .../netlify-lambda.js | 8 +- src/utils/serve-functions.js | 130 +++----- 5 files changed, 363 insertions(+), 87 deletions(-) diff --git a/package-lock.json b/package-lock.json index eca61d1b978..5b7c9345f86 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3010,6 +3010,39 @@ } } }, + "aws-sdk": { + "version": "2.621.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.621.0.tgz", + "integrity": "sha512-wf87zTPXx2cILc9kAKTXcSrAc+vCc7BxE7G8vPEWAreCDucLHbynachYQvwO5ql+I3Eq651/X2XjnY01niSTNw==", + "requires": { + "buffer": "4.9.1", + "events": "1.1.1", + "ieee754": "1.1.13", + "jmespath": "0.15.0", + "querystring": "0.2.0", + "sax": "1.2.1", + "url": "0.10.3", + "uuid": "3.3.2", + "xml2js": "0.4.19" + }, + "dependencies": { + "buffer": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + } + } + }, "aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", @@ -4066,6 +4099,30 @@ "object-visit": "^1.0.0" } }, + "color": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/color/-/color-3.0.0.tgz", + "integrity": "sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w==", + "requires": { + "color-convert": "^1.9.1", + "color-string": "^1.5.2" + }, + "dependencies": { + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + } + } + }, "color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -4079,11 +4136,34 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, + "color-string": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz", + "integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==", + "requires": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "colornames": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/colornames/-/colornames-1.1.1.tgz", + "integrity": "sha1-+IiQMGhcfE/54qVZ9Qd+t2qBb5Y=" + }, "colors": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" }, + "colorspace": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.2.tgz", + "integrity": "sha512-vt+OoIP2d76xLhjwbBaucYlNSpPsrJWPlBTtwCpQKIu6/CSMutyzX93O/Do0qzpH3YoHEes8YEFXyZ797rEhzQ==", + "requires": { + "color": "3.0.x", + "text-hex": "1.0.x" + } + }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -5339,6 +5419,16 @@ "integrity": "sha1-bfwP+dAQAKLt8oZTccrDFulJd68=", "dev": true }, + "diagnostics": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/diagnostics/-/diagnostics-1.1.1.tgz", + "integrity": "sha512-8wn1PmdunLJ9Tqbx+Fx/ZEuHfJf4NKSN2ZBj7SJC/OWRWha843+WsTjqMe1B5E3p28jqBlp+mJ2fPVxPyNgYKQ==", + "requires": { + "colorspace": "1.1.x", + "enabled": "1.0.x", + "kuler": "1.0.x" + } + }, "diff": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", @@ -5376,6 +5466,11 @@ "is-obj": "^2.0.0" } }, + "dotenv": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", + "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==" + }, "download": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/download/-/download-7.1.0.tgz", @@ -5518,6 +5613,14 @@ } } }, + "enabled": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-1.0.2.tgz", + "integrity": "sha1-ll9lE9LC0cX0ZStkouM5ZGf8L5M=", + "requires": { + "env-variable": "0.0.x" + } + }, "encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", @@ -5542,6 +5645,11 @@ "tapable": "^1.0.0" } }, + "env-variable": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/env-variable/-/env-variable-0.0.6.tgz", + "integrity": "sha512-bHz59NlBbtS0NhftmR8+ExBEekE7br0e01jw+kk0NDro7TtZzBYZ5ScGPs3OmwnpyfHTHOtr1Y6uedCdrIldtg==" + }, "envify": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/envify/-/envify-4.1.0.tgz", @@ -6285,8 +6393,7 @@ "events": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", - "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", - "dev": true + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=" }, "execa": { "version": "2.1.0", @@ -6704,6 +6811,11 @@ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" }, + "fast-safe-stringify": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz", + "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==" + }, "fast-stringify": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/fast-stringify/-/fast-stringify-1.1.2.tgz", @@ -6725,6 +6837,11 @@ "pend": "~1.2.0" } }, + "fecha": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-2.3.3.tgz", + "integrity": "sha512-lUGBnIamTAwk4znq5BcqsDaxSmZ9nDVJaij6NvRt/Tg4R69gERA+otPKbS86ROw9nxVMw2/mp1fnaiWqbs6Sdg==" + }, "figures": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.1.0.tgz", @@ -8930,6 +9047,11 @@ "pretty-format": "^24.9.0" } }, + "jmespath": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", + "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=" + }, "js-string-escape": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz", @@ -9054,6 +9176,32 @@ "graceful-fs": "^4.1.9" } }, + "kuler": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/kuler/-/kuler-1.0.1.tgz", + "integrity": "sha512-J9nVUucG1p/skKul6DU3PUZrhs0LPulNaeUOox0IyXDi8S4CztTHs1gQphhuZmzXG7VOQSf6NJfKuzteQLv9gQ==", + "requires": { + "colornames": "^1.1.1" + } + }, + "lambda-local": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/lambda-local/-/lambda-local-1.7.1.tgz", + "integrity": "sha512-2nRlgFSELc2YgLu1haa0jUgnAzlV5zPjYQKlsDkHUKFn73QlQsIqJZ5w8Hs54FyOT95qcJ29fc03x9f0+pf4ag==", + "requires": { + "aws-sdk": "^2.488.0", + "commander": "^4.1.0", + "dotenv": "^8.0.0", + "winston": "^3.2.1" + }, + "dependencies": { + "commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==" + } + } + }, "latest-version": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz", @@ -9746,6 +9894,25 @@ } } }, + "logform": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.1.2.tgz", + "integrity": "sha512-+lZh4OpERDBLqjiwDLpAWNQu6KMjnlXH2ByZwCuSqVPJletw0kTWJf5CgSNAUKn1KUkv3m2cUz/LK8zyEy7wzQ==", + "requires": { + "colors": "^1.2.1", + "fast-safe-stringify": "^2.0.4", + "fecha": "^2.3.3", + "ms": "^2.1.1", + "triple-beam": "^1.3.0" + }, + "dependencies": { + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, "loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -10937,7 +11104,7 @@ }, "resolve-from": { "version": "4.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, @@ -11163,6 +11330,11 @@ "wrappy": "1" } }, + "one-time": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/one-time/-/one-time-0.0.4.tgz", + "integrity": "sha1-+M33eISCb+Tf+T46nMN7HkSAdC4=" + }, "onetime": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz", @@ -12176,6 +12348,11 @@ "strict-uri-encode": "^1.0.0" } }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" + }, "querystring-es3": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", @@ -12809,6 +12986,11 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "sax": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", + "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=" + }, "seek-bzip": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.5.tgz", @@ -12999,6 +13181,21 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" }, + "simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", + "requires": { + "is-arrayish": "^0.3.1" + }, + "dependencies": { + "is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + } + } + }, "slash": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", @@ -13293,6 +13490,11 @@ "tweetnacl": "~0.14.0" } }, + "stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" + }, "stack-utils": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.2.tgz", @@ -13822,6 +14024,11 @@ } } }, + "text-hex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", + "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==" + }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -14043,6 +14250,11 @@ "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", "dev": true }, + "triple-beam": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", + "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==" + }, "ts-pnp": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/ts-pnp/-/ts-pnp-1.1.5.tgz", @@ -14573,6 +14785,22 @@ "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" }, + "url": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", + "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + } + } + }, "url-parse-lax": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", @@ -14845,6 +15073,59 @@ } } }, + "winston": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.2.1.tgz", + "integrity": "sha512-zU6vgnS9dAWCEKg/QYigd6cgMVVNwyTzKs81XZtTFuRwJOcDdBg7AU0mXVyNbs7O5RH2zdv+BdNZUlx7mXPuOw==", + "requires": { + "async": "^2.6.1", + "diagnostics": "^1.1.1", + "is-stream": "^1.1.0", + "logform": "^2.1.1", + "one-time": "0.0.4", + "readable-stream": "^3.1.1", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.3.0" + }, + "dependencies": { + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + } + } + }, + "winston-transport": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.3.0.tgz", + "integrity": "sha512-B2wPuwUi3vhzn/51Uukcao4dIduEiPOcOt9HJ3QeaXgkJ5Z7UwpBzxS4ZGNHtrxrUvTwemsQiSys0ihOf8Mp1A==", + "requires": { + "readable-stream": "^2.3.6", + "triple-beam": "^1.2.0" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, "word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", @@ -14945,6 +15226,20 @@ "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==" }, + "xml2js": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", + "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~9.0.1" + } + }, + "xmlbuilder": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=" + }, "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", diff --git a/package.json b/package.json index 526dae64e85..204c3a06fae 100644 --- a/package.json +++ b/package.json @@ -88,6 +88,7 @@ "copy-template-dir": "^1.4.0", "debug": "^4.1.1", "dot-prop": "^5.1.0", + "dotenv": "^8.2.0", "envinfo": "^7.3.1", "execa": "^2.0.3", "express": "^4.17.1", @@ -105,6 +106,7 @@ "inquirer-autocomplete-prompt": "^1.0.1", "is-docker": "^1.1.0", "jwt-decode": "^2.2.0", + "lambda-local": "^1.7.1", "lodash.get": "^4.4.2", "lodash.isempty": "^4.4.0", "lodash.isequal": "^4.5.0", diff --git a/src/commands/dev/index.js b/src/commands/dev/index.js index 360b75c592a..d3602df40f5 100644 --- a/src/commands/dev/index.js +++ b/src/commands/dev/index.js @@ -20,6 +20,7 @@ const Command = require('../../utils/command') const chalk = require('chalk') const jwtDecode = require('jwt-decode') const open = require('open') +const dotenv = require('dotenv') const { NETLIFYDEV, NETLIFYDEVLOG, @@ -313,10 +314,16 @@ function startDevServer(settings, log) { }) return } + + let envConfig = {} + if (fs.existsSync('.env')) { + envConfig = dotenv.parse(fs.readFileSync('.env')) + } + log(`${NETLIFYDEVLOG} Starting Netlify Dev with ${settings.type}`) const args = settings.command === 'npm' ? ['run', ...settings.args] : settings.args const ps = child_process.spawn(settings.command, args, { - env: { ...process.env, ...settings.env, FORCE_COLOR: 'true' }, + env: { ...process.env, ...settings.env, FORCE_COLOR: 'true', ...envConfig }, stdio: settings.stdio || 'inherit', detached: true, shell: true, diff --git a/src/function-builder-detectors/netlify-lambda.js b/src/function-builder-detectors/netlify-lambda.js index 51303dbb840..81914d9754b 100644 --- a/src/function-builder-detectors/netlify-lambda.js +++ b/src/function-builder-detectors/netlify-lambda.js @@ -1,5 +1,6 @@ const { existsSync, readFileSync } = require('fs') const execa = require('execa') +const dotenv = require('dotenv') module.exports = function() { if (!existsSync('package.json')) { @@ -25,8 +26,13 @@ module.exports = function() { } } + let envConfig = {} + if (existsSync('.env')) { + envConfig = dotenv.parse(readFileSync('.env')) + } + if (settings.npmScript) { - settings.build = () => execa(yarnExists ? 'yarn' : 'npm', ['run', settings.npmScript]) + settings.build = () => execa(yarnExists ? 'yarn' : 'npm', ['run', settings.npmScript], { env: { ...process.env, ...envConfig } }) settings.builderName = 'netlify-lambda' return settings } diff --git a/src/utils/serve-functions.js b/src/utils/serve-functions.js index badd6351c62..58cf29849b2 100644 --- a/src/utils/serve-functions.js +++ b/src/utils/serve-functions.js @@ -1,9 +1,12 @@ +const path = require('path') + const express = require('express') const bodyParser = require('body-parser') const expressLogging = require('express-logging') const queryString = require('querystring') const chokidar = require('chokidar') const jwtDecode = require('jwt-decode') +const lambdaLocal = require('lambda-local') const { NETLIFYDEVLOG, // NETLIFYDEVWARN, @@ -25,6 +28,43 @@ function handleErr(err, response) { // return path.join(functionPath, `${path.basename(functionPath)}.js`); // } +/** need to keep createCallback in scope so we can know if cb was called AND handler is async */ +function createCallback(response) { + return function(err, lambdaResponse) { + if (err) { + return handleErr(err, response) + } + if (lambdaResponse === undefined) { + return handleErr('lambda response was undefined. check your function code again.', response) + } + if (!Number(lambdaResponse.statusCode)) { + console.log( + `${NETLIFYDEVERR} Your function response must have a numerical statusCode. You gave: $`, + lambdaResponse.statusCode + ) + return handleErr('Incorrect function response statusCode', response) + } + if (typeof lambdaResponse.body !== 'string') { + console.log(`${NETLIFYDEVERR} Your function response must have a string body. You gave:`, lambdaResponse.body) + return handleErr('Incorrect function response body', response) + } + + response.statusCode = lambdaResponse.statusCode + // eslint-disable-line guard-for-in + for (const key in lambdaResponse.headers) { + response.setHeader(key, lambdaResponse.headers[key]) + } + for (const key in lambdaResponse.multiValueHeaders) { + const items = lambdaResponse.multiValueHeaders[key] + response.setHeader(key, items) + } + response.write( + lambdaResponse.isBase64Encoded ? Buffer.from(lambdaResponse.body, 'base64') : lambdaResponse.body + ) + response.end() + } +} + function buildClientContext(headers) { // inject a client context based on auth header, ported over from netlify-lambda (https://github.com/netlify/netlify-lambda/pull/57) if (!headers.authorization) return @@ -77,20 +117,6 @@ function createHandler(dir) { return } const { functionPath, moduleDir } = functions[func] - let handler - let before = module.paths - try { - module.paths = [moduleDir] - handler = require(functionPath) - if (typeof handler.handler !== 'function') { - throw new Error(`function ${functionPath} must export a function named handler`) - } - module.paths = before - } catch (error) { - module.paths = before - handleErr(error, response) - return - } const body = request.body.toString() var isBase64Encoded = Buffer.from(body, 'base64').toString('base64') === body @@ -102,7 +128,7 @@ function createHandler(dir) { .pop() .trim() - const lambdaRequest = { + const event = { path: request.path, httpMethod: request.method, queryStringParameters: queryString.parse(request.url.split(/\?(.+)/)[1]), @@ -111,79 +137,19 @@ function createHandler(dir) { isBase64Encoded: isBase64Encoded } - let callbackWasCalled = false const callback = createCallback(response) // we already checked that it exports a function named handler above - const promise = handler.handler( - lambdaRequest, - { clientContext: buildClientContext(request.headers) || {} }, - callback - ) - /** guard against using BOTH async and callback */ - if (callbackWasCalled && promise && typeof promise.then === 'function') { - throw new Error( - 'Error: your function seems to be using both a callback and returning a promise (aka async function). This is invalid, pick one. (Hint: async!)' - ) - } else { - // it is definitely an async function with no callback called, good. - promiseCallback(promise, callback) - } - /** need to keep createCallback in scope so we can know if cb was called AND handler is async */ - function createCallback(response) { - return function(err, lambdaResponse) { - callbackWasCalled = true - if (err) { - return handleErr(err, response) - } - if (lambdaResponse === undefined) { - return handleErr('lambda response was undefined. check your function code again.', response) - } - if (!Number(lambdaResponse.statusCode)) { - console.log( - `${NETLIFYDEVERR} Your function response must have a numerical statusCode. You gave: $`, - lambdaResponse.statusCode - ) - return handleErr('Incorrect function response statusCode', response) - } - if (typeof lambdaResponse.body !== 'string') { - console.log(`${NETLIFYDEVERR} Your function response must have a string body. You gave:`, lambdaResponse.body) - return handleErr('Incorrect function response body', response) - } - - response.statusCode = lambdaResponse.statusCode - // eslint-disable-line guard-for-in - for (const key in lambdaResponse.headers) { - response.setHeader(key, lambdaResponse.headers[key]) - } - for (const key in lambdaResponse.multiValueHeaders) { - const items = lambdaResponse.multiValueHeaders[key] - response.setHeader(key, items) - } - response.write( - lambdaResponse.isBase64Encoded ? Buffer.from(lambdaResponse.body, 'base64') : lambdaResponse.body - ) - response.end() - } - } + return lambdaLocal.execute({ + event: event, + lambdaPath: functionPath, + clientContext: JSON.stringify(buildClientContext(request.headers) || {}), + callback: callback, + envfile: path.resolve(moduleDir, '.env'), + }) } } -function promiseCallback(promise, callback) { - if (!promise) return // means no handler was written - if (typeof promise.then !== 'function') return - if (typeof callback !== 'function') return - - promise.then( - function(data) { - callback(null, data) - }, - function(err) { - callback(err, null) - } - ) -} - async function serveFunctions(settings) { const app = express() const dir = settings.functionsDir From 5d777e245cc403003ccf0e1029584ce88efac94b Mon Sep 17 00:00:00 2001 From: Raees Iqbal Date: Wed, 19 Feb 2020 18:02:07 +0500 Subject: [PATCH 2/4] Dev: Destroy added env vars after serving function --- src/utils/serve-functions.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/utils/serve-functions.js b/src/utils/serve-functions.js index 58cf29849b2..dbf36cb5482 100644 --- a/src/utils/serve-functions.js +++ b/src/utils/serve-functions.js @@ -146,6 +146,7 @@ function createHandler(dir) { clientContext: JSON.stringify(buildClientContext(request.headers) || {}), callback: callback, envfile: path.resolve(moduleDir, '.env'), + envdestroy: false, }) } } From dcf503b2e8eb241288d00e16cf0ccb0eae4e54aa Mon Sep 17 00:00:00 2001 From: Raees Iqbal Date: Wed, 19 Feb 2020 18:02:31 +0500 Subject: [PATCH 3/4] Dev: Reduce verbosity of lambdaLocal --- src/utils/serve-functions.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/utils/serve-functions.js b/src/utils/serve-functions.js index dbf36cb5482..cd14d775047 100644 --- a/src/utils/serve-functions.js +++ b/src/utils/serve-functions.js @@ -147,6 +147,7 @@ function createHandler(dir) { callback: callback, envfile: path.resolve(moduleDir, '.env'), envdestroy: false, + verboseLevel: 0, }) } } From 8f84d48f3aaf207a0523ed6649f036f26893108b Mon Sep 17 00:00:00 2001 From: Raees Iqbal Date: Wed, 19 Feb 2020 22:35:45 +0500 Subject: [PATCH 4/4] Add docs for Netlify Dev env vars --- docs/netlify-dev.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/netlify-dev.md b/docs/netlify-dev.md index c30454b33a5..39ab4ea88c3 100644 --- a/docs/netlify-dev.md +++ b/docs/netlify-dev.md @@ -173,6 +173,12 @@ The order of precedence for applying redirect rules is: See the [Redirects Documentation](https://www.netlify.com/docs/redirects/) for more information on Netlify's redirect and proxying capabilities. +## Environment Variables + +Netlify Dev supports local environment variables through `.env` files. +Netlify Dev will look in project root directory and each of your JavaScript based Netlify Functions directories for +`.env` file and will provide those variables to the spawned site generator/server and Netlify Functions. + ## Netlify Functions Netlify can also create serverless functions for you locally as part of Netlify Functions. The serverless functions can then be run by Netlify Dev in the same way that wold be when deployed to the cloud.