Compare commits

...

283 Commits

Author SHA1 Message Date
Nathan Rajlich
38928ab942 Publish
- @now/go@0.3.1-canary.1
 - @now/python@0.0.41-canary.4
2019-03-16 20:38:40 -07:00
Nathan Rajlich
bfb67d10ec [now-python] Run pip from within the installation directory (#295)
Otherwise the `setup.cfg` file is not respected (see #292).
2019-03-16 20:32:03 -07:00
Nathan Rajlich
616bad8a3d Fix packAndDeploy() for usage with @now/node (#293)
* Fix `packAndDeploy()` for usage with `@now/node`

Since the prepublish script for `@now/node` writes other stuff to
stdout, so relying on `npm pack` outputting the tarball name is not
reliable.

Instead, just `glob()` for a `*.tgz` file and expect that to be the
output package tarball.

Fixes error:

```
Error: ENOENT: no such file or directory, open '/home/circleci/repo/packages/now-node/> @now/node@0.5.2-canary.2 prepublish /home/circleci/repo/packages/now-node
> npm run build
> @now/node@0.5.2-canary.2 build /home/circleci/repo/packages/now-node
> ./build.sh
'/home/circleci/repo/packages/now-node-bridge/bridge.d.ts' -> 'src/bridge.d.ts'
now-node-0.5.2-canary.2.tgz'
```

* Make the `tgzPath` be absolute

* 'ignore' -> 'inherit'
2019-03-16 19:10:18 -07:00
Nathan Rajlich
e026ddf805 [now-go] Add missing await to getExportedFunctionName() (#285)
This fixes a subtle bug in the `getExportedFunctionName()` helper
function. It wasn't actually causing any issues in production, since the
`index.js` file also does `await` on the return value of this function
so it was still resolving the promise properly, but this is more correct
and fixes the associated `debug()` call.
2019-03-16 17:29:50 -07:00
Nathan Rajlich
bec9ea101f Publish
- @now/build-utils@0.4.37-canary.1
 - @now/node@0.5.2-canary.3
 - @now/python@0.0.41-canary.3
2019-03-16 16:44:26 -07:00
Nathan Rajlich
54f3f755fb [now-build-utils] Set npm_config_target env var when installing npm deps (#290) 2019-03-16 16:43:28 -07:00
Nathan Rajlich
5b03109ba7 [now-python] Add setup.cfg file before running pip install (#292)
* [now-python] Add `setup.cfg` file before running `pip install`

See: https://stackoverflow.com/a/44728772/376773

The `setup.cfg` is required for `now dev` on MacOS, where without
this file being present in the src dir then this error happens:

distutils.errors.DistutilsOptionError: must supply either home
or prefix/exec-prefix -- not both

* Only create the `seup.cfg` file once
2019-03-16 16:43:13 -07:00
Connor Davis
7ff9e810ff Add note about @now/next not supporting distDir (#289)
`now-builders` can't parse `next.config.js` because it can hold functions.

It expects `/.next` as the build output.

Closes: #288
2019-03-16 22:16:46 +01:00
Nathan Rajlich
3036aff45e [now-node] Add prepublish npm script
So that the TypeScript files are compiled before publishing.
2019-03-15 13:29:17 -07:00
Steven
c366aa69a4 Publish @now/node@0.5.2-canary.2 2019-03-15 16:18:46 -04:00
Steven
c8d225522d Publish
- @now/next@0.1.3-canary.0
 - @now/node-server@0.5.2-canary.1
 - @now/node@0.5.2-canary.1
2019-03-15 14:33:02 -04:00
Steven
8ee5063669 [now-node] Bump ncc to 0.16.0 (#283)
* [now-node] Bump ncc to 0.16.0

* [now-node] Bump ncc to 0.16.0
2019-03-15 11:14:33 -07:00
Nathan Rajlich
9372e70747 Publish
- @now/next@0.1.2
2019-03-14 20:59:14 -07:00
Nathan Rajlich
4a4bd550a1 Publish
- @now/bash@0.1.4-canary.0
 - @now/go@0.3.1-canary.0
 - @now/next@0.1.2-canary.0
 - @now/node-bridge@1.0.1-canary.0
 - @now/node-server@0.5.2-canary.0
 - @now/node@0.5.2-canary.0
 - @now/rust@0.1.2-canary.0
2019-03-14 20:39:34 -07:00
Connor Davis
f53343d547 Fix static files for latest now/next using target serverless (#282) 2019-03-14 21:52:06 -05:00
Nathan Rajlich
e4ed811b53 [now-bash] Only read the $event body once (#278)
In situations where the handler responds very quickly, the `$event` file
path gets deleted before the `_lambda_runtime_body` function can finish
its work. So instead, just read that file once and cache it to
a variable inside that function.

This fixes this issue when the `handler` responds very quickly, causing the
`$events` file to be deleted before the multiple `jq` invocations are able to
read it:

```
/var/task/.import-cache/runtime.sh: line 78: /tmp/T/tmp.DShzjeah: No such file or directory
/var/task/.import-cache/runtime.sh: line 82: /tmp/T/tmp.DShzjeah: No such file or directory
```
2019-03-14 19:27:39 -07:00
Nathan Rajlich
e9935dee31 [now-bash] Use the workPath directory (#279)
This is important for `now dev`, where the `workPath` is re-used and
thus leads to faster re-builds.
2019-03-14 14:13:16 -07:00
Nathan Rajlich
2e1e6bb131 Publish
- @now/next@0.1.1
2019-03-13 15:45:16 -07:00
Nathan Rajlich
4a01ac4bd0 [now-next] Update @now/node-bridge to v1.0.0 2019-03-13 15:44:32 -07:00
Nathan Rajlich
bd1a7c428f Publish
- @now/go@0.3.0
 - @now/next@0.1.0
2019-03-13 15:35:42 -07:00
Nathan Rajlich
9a4a3dac47 Publish
- @now/node@0.5.1
 - @now/node-server@0.5.1
2019-03-13 14:51:04 -07:00
Nathan Rajlich
4f2c35a0ee [now-node] Update @now/node-bridge to v1.0.0 2019-03-13 14:29:12 -07:00
Nathan Rajlich
672df5d026 [now-node-server] Update @now/node-bridge to v1.0.0 2019-03-13 14:28:37 -07:00
Nathan Rajlich
8cb648abc4 Publish
- @now/node@0.5.0
 - @now/node-server@0.5.0
2019-03-13 14:24:35 -07:00
Nathan Rajlich
74f658c634 Publish
- @now/node-bridge@1.0.0
2019-03-13 13:50:24 -07:00
Nathan Rajlich
efbb54a232 Publish
- @now/bash@0.1.3
2019-03-12 16:50:37 -07:00
Igor Klopov
3e2bd03e01 Publish
- @now/rust@0.1.1
2019-03-11 14:37:33 +03:00
Igor Klopov
8dc92b70b9 [now/rust] cleanup cache files a little + update def cache 2019-03-11 13:55:52 +03:00
Igor Klopov
4267be4e5a Publish
- @now/rust@0.1.0
2019-03-10 20:44:39 +03:00
Igor Klopov
43ba6459eb [now/rust] fixes 2019-03-10 20:40:38 +03:00
Igor Klopov
8c5638915d [now/rust] update default cache 2019-03-10 19:32:01 +03:00
Igor Klopov
3fab247c15 Publish
- @now/rust@0.0.9
2019-03-10 14:41:00 +03:00
Mike Engel
6ab0e2e9ab fix(now-rust): Fix how build.sh is detected and run (#267) 2019-03-10 14:34:10 +03:00
Igor Klopov
34369148d7 Publish
- @now/rust@0.0.8
2019-03-08 21:24:40 +03:00
Igor Klopov
662ad1ed3a [now/rust] remove gcc installation (#266)
* [now/rust] remove gcc

* update default cache to a blob, created without def.c.
2019-03-08 21:20:46 +03:00
Igor Klopov
890cd74ee5 Publish
- @now/rust@0.0.7
2019-03-08 20:03:18 +03:00
Igor Klopov
7ef616b31e lint fixes 2019-03-08 20:01:03 +03:00
Igor Klopov
bebcfa4bb5 Publish
- @now/rust@0.0.6
2019-03-08 19:57:34 +03:00
Igor Klopov
25100c53aa [now/rust] default cache (#265)
* [now/rust] default cache

* update default cache url
2019-03-08 19:55:04 +03:00
Sophearak Tha
fe20da87e7 add support go.mod (#258)
* add support go.mod

* add main__mod__.go

* add missing variable and fix import

* fix linter

* remove `gcc` and add `go mod tidy`

* let go build handle the getting the package
2019-03-08 05:02:44 +03:00
Igor Klopov
18cb147c86 Publish
- @now/rust@0.0.5
2019-03-07 20:25:25 +03:00
Mike Engel
9c9e18586f [now-rust]: Allow a build.sh to be run prior to compile (#253)
* fix(now-rust): Don't rely on encoding for parsing normal bodies

* feat(now-rust): Allow users to run a build.sh file
2019-03-07 20:11:20 +03:00
Igor Klopov
0cd7192740 Publish
- @now/rust@0.0.4
2019-03-07 19:40:17 +03:00
Juan Campa
a2d9c4fb4b Add headers to error when a deployment fails a probe (#257) 2019-03-07 09:35:56 -05:00
Nathan Rajlich
02fafd2ebc Publish
- @now/go@0.2.13-canary.2
 - @now/next@0.0.85-canary.10
 - @now/php-bridge@0.4.16-canary.0
 - @now/php@0.4.16-canary.0
 - @now/wordpress@0.4.16-canary.0
2019-03-04 15:53:34 -08:00
Daniel Rodríguez
42577c915c Update go to v1.12 (#247)
This might allow users to use `go.mod`, since on 1.12 they did the following:

> ... the go command now supports module-aware operations outside of a module directory, provided that those operations do not need to resolve import paths relative to the current directory or explicitly edit the go.mod file. ...

Perhaps after that, the users would be simply able to add this to their config files and make it work?

```
  "build": {    
    "env": {                                                              
      "GO111MODULE": "on"    
    }    
  },
```

Also related to #241.
2019-03-04 15:15:03 -08:00
Igor Klopov
73db9e11dd [now-php] improve routes test 2019-03-02 13:48:44 +03:00
Igor Klopov
3125125c16 Publish
- @now/php@0.4.15
 - @now/wordpress@0.4.15
2019-03-02 07:00:31 +03:00
Igor Klopov
5335291408 bump now-php to use new now-php-bridge 2019-03-02 06:01:33 +03:00
Igor Klopov
36620559f9 Publish
- @now/php-bridge@0.4.15
2019-03-02 03:53:48 +03:00
Igor Klopov
360ea3a609 [now-php] fix routing bug (#190) 2019-03-02 02:50:57 +03:00
Joe Haddad
1cd362126c Warn when .next is uploaded (#244)
* Add error document

* Check for a .next folder during deploy process

* Remove error and warn instead

* Check if path exists instead of globbing
2019-02-27 16:22:31 -05:00
Joe Haddad
ae19fe95f6 Publish
- @now/next@0.0.85-canary.9
2019-02-27 13:26:54 -05:00
Joe Haddad
3e34d402a2 Remove fs.promised dependency (#242)
* Remove fs.promised dependency

* Adjust import style per @dav-is

* Update names
2019-02-27 12:58:11 -05:00
Joe Haddad
cc7b97fbbb Dump next.config.js file on error (#243)
* Dump next.config.js file on error

* Relocate method to utilities

* Add tests for getNextConfig
2019-02-27 12:08:40 -05:00
Joe Haddad
c1049985af Publish
- @now/bash@0.1.3-canary.0
 - @now/build-utils@0.4.37-canary.0
 - @now/next@0.0.85-canary.8
2019-02-26 14:33:47 -05:00
Nathan Rajlich
214388ccf3 [now-bash] Use base64 --decode flag
Instead of `-d`. Seems the short flag BSD's `base64` is `-D`,
however the long option name is consistent between both versions.
2019-02-26 11:28:45 -08:00
Joe Haddad
b1d6b7bfc0 feat(@now/next): optional assets directory (#240)
* Make assets part of the build output

* Add console output for user
2019-02-26 14:18:03 -05:00
Nathan Rajlich
ece3564dfd [now-build-utils] Use os.tmpdir() for getWritableDirectory() (#238)
`os.tmpdir()` abstracts away platform differences related to retrieving
the writable temp directory, for example MacOS returns a user-specific
temp directory instead of `/tmp`.

On AWS Lambda, [it returns `/tmp`](https://nexec-v2.n8.io/api/node?arg=-p&arg=require(%27os%27).tmpdir()).

More importantly, it removes the `__dirname/tmp` special-case when not
running in prod. This was problematic for `now dev` because the module
directory is not always writable (i.e. for a `pkg` binary).
2019-02-25 16:56:41 -08:00
Igor Klopov
a88af1f077 Publish
- @now/build-utils@0.4.36
2019-02-24 23:26:14 +03:00
Igor Klopov
d92f7b26c0 lint fixes for build-utils 2019-02-24 23:08:09 +03:00
Igor Klopov
52198af750 Publish
- @now/build-utils@0.4.35-canary.3
2019-02-24 11:56:01 +03:00
Igor Klopov
d58bff2453 [build-utils] chmod +x before running user script 2019-02-24 11:50:07 +03:00
Joe Haddad
8c0a144ae4 Publish
- @now/next@0.0.85-canary.7
2019-02-22 17:13:46 -05:00
Joe Haddad
106e4d5f36 Cache Next.js node_modules for faster rebuilds (#235)
* Add `node_modules` caching for Next.js projects

* Use existing work directory instead of redownloading dependencies

* Reorder fns

* Add prettier configuration

* Move entry files to cache folder

* Correct glob base path

* Be sure to include .yarn-integrity

* Save `package.json` and `yarn.lock`, too

* Increase compatibility so Yarn can dedupe
2019-02-22 16:30:29 -05:00
Nathan Rajlich
66c28bd695 Publish
- @now/next@0.0.85-canary.6
 - @now/node-server@0.5.0-canary.3
 - @now/node@0.5.0-canary.5
2019-02-21 13:20:49 -08:00
Nathan Rajlich
55e75296ff [now-next] Update @now/node-bridge to v1.0.0-canary.2 (#232)
Update `@now/next` to use the latest `@now/node-bridge`, which removes the hard-coded port 3000 that was previously in-place, which was problematic for `now dev`. Now the `http.Server` instance listens on an ephemeral port which is detected by the Now node runtime.

(Similar to 6101ba9d95 and 8dc0c92c58)
2019-02-21 12:55:33 +01:00
Nathan Rajlich
36cbb36737 Add --tags flag when determining if commit it tagged
This fixes matching for "unannotated tags".

See: https://stackoverflow.com/questions/1474115/how-to-find-the-tag-associated-with-a-given-git-commit#comment9135284_1474161
2019-02-20 18:11:11 -08:00
Nathan Rajlich
978ca328ef Publish
- @now/node@0.5.0-canary.4
 - @now/node-server@0.5.0-canary.2
2019-02-20 16:49:58 -08:00
Nathan Rajlich
7b383e0f7c [now-node] Fix build.sh script 2019-02-20 16:40:52 -08:00
Nathan Rajlich
faa5ab36aa Publish
- @now/node@0.5.0-canary.3
2019-02-20 16:32:31 -08:00
Nathan Rajlich
c0a21969dd Regenerate yarn.lock file
Not really sure why this is happening, since `@now/node` and
`@now/node-server` both use this version, but without this commit, then
publish step on CircleCI fails due to a dirty working tree.

Go figure 🤷
2019-02-20 16:31:04 -08:00
Nathan Rajlich
73d0a1723f [now-node] Ensure that @now/node-bridge is installed for build 2019-02-20 14:59:24 -08:00
Nathan Rajlich
7c515544ae [now-node] Don't commit the bridge.d.ts file 2019-02-20 14:52:28 -08:00
Nathan Rajlich
b53c9a6299 Publish
- @now/node@0.5.0-canary.2
2019-02-20 14:51:02 -08:00
Nathan Rajlich
35ff11e6e4 Remove prepublish step for now
It's causing these kinds of failures:

https://circleci.com/gh/zeit/now-builders/839
2019-02-20 14:50:18 -08:00
Nathan Rajlich
64ee4905cd Publish
- @now/node-server@0.5.0-canary.1
 - @now/node@0.5.0-canary.1
2019-02-20 13:53:37 -08:00
Nathan Rajlich
e50dd7e50a Bump now/node and now/node-server to v0.5.0 canary 2019-02-20 13:53:00 -08:00
Nathan Rajlich
6101ba9d95 [now-node-server] Update @now/node-bridge to v1.0.0-canary.2 (#231)
Update `@now/node-server` to use the latest `@now/node-bridge`, which
removes the hard-coded port 3000 that was previously in-place,
which was problematic for `now dev`. Now the `http.Server`
instance listens on an ephemeral port which is detected by the
Now node runtime.
2019-02-20 13:47:17 -08:00
Nathan Rajlich
8dc0c92c58 [now-node] Migrate to TypeScript and use @now/node-bridge v1 (#212)
This moves `@now/node` to being implemented in TypeScript.

It also updates it to use the latest `@now/node-bridge`, which
removes the hard-coded port 3000 that was previously in-place,
which was problematic for `now dev`. Now the `http.Server`
instance listens on an ephemeral port which is detected by the
Now node runtime.
2019-02-20 12:33:21 -08:00
Nathan Rajlich
44c9f3765a Publish
- @now/node-bridge@1.0.0-canary.2
 - @now/node-server@0.4.27-canary.7
 - @now/node@0.4.29-canary.7
2019-02-19 20:49:58 -08:00
Nathan Rajlich
92c05ca338 Pin @now/node-bridge to v0.1.11-canary.0
To address: https://github.com/zeit/now-builders/pull/224#issuecomment-465410905
2019-02-19 20:26:38 -08:00
Nathan Rajlich
069b557906 Publish
- @now/node-bridge@1.0.0-canary.1
2019-02-19 17:26:04 -08:00
Nathan Rajlich
692a0df909 Publish
- @now/node-bridge@0.1.11-canary.1
 - @now/node-server@0.4.27-canary.6
 - @now/node@0.4.29-canary.6
2019-02-19 16:33:18 -08:00
Nathan Rajlich
aeafeb5441 [now-node-bridge] Refactor API to be http.Server focused (#224)
* [now-node-bridge] Refactor API to be `http.Server` focused

This commit refactors the `@now/node-bridge` helper module to work with
`http.Server` instances directly, instead of expecting the `port` to be
set.

The `Bridge` instance calls the `listen()` function on the server instance
which binds to an ephemeral port. This is especially important for
`now dev`, where using a hard-coded port will cause port conflicts for
multiple lambdas using the same builder.

Also converts to TypeScript and adds some basic unit tests.

Example usage:

```js
const server = new Server(() => {});
const bridge = new Bridge(server);
bridge.listen();

const info = await bridge.listening;
assert.equal(info.address, '127.0.0.1');
assert.equal(typeof info.port, 'number');
```

* Update `yarn.lock`

* Add `pretest` script

* Enable TypeScript `strict` mode

* Throw if a string is returned from `server.address()`

Defensive programming ftw

Co-Authored-By: TooTallNate <n@n8.io>

* Prettier

* Prettier

* Fixes

* Attempt to fix CI

* Add `files` array to package.json

* Check for the `Action` property to avoid type casting

Co-Authored-By: TooTallNate <n@n8.io>

* Split the normalizing functions into separate ones

Also adds additional unit tests.

* export the `NowProxyRequest` and `NowProxyResponse`

* Remove last `as` casting

* Move some up

* Debug CircleCI tests :/

* Fix "Invoke" check

* Attempt to fix CircleCI again

* Fix bad

* Convert tests to use `jest`
2019-02-19 16:17:58 -08:00
Nathan Rajlich
a09d5fb355 Add publish.sh script for CircleCI (#228)
* Add `publish.sh` script for CircleCI

Centralize the publishing logic for CircleCI to use.

There was a bug in the previous "Potentially publish stable release"
branch, such that it would be executed for non-tagged commits. The new
publish script checks if there are indeed any tags for the commit, and
bails if there are none.

As an additional bonus, there's now only one publish step in the
CircleCI config, because the publish script determines stable vs. canary
based on the tag name.

* Remove `echo`
2019-02-19 14:45:04 -08:00
Nathan Rajlich
d8017aa9aa Publish
- @now/python@0.0.41-canary.2
2019-02-19 12:14:49 -08:00
Honza Javorek
702f56b9b5 [now-python] Add missing base64 import and fix coding style (#226) 2019-02-19 12:11:12 -08:00
Nathan Rajlich
183b117152 Publish
- @now/python@0.0.41-canary.1
2019-02-19 11:29:26 -08:00
Nathaniel Hill
75b3fb4981 [now-python] Pass the request body to the HTTP request (#99)
* pass body to lambda

* reformat

* look for requirements.txt in lambda root

* single issue PR

* support base64 encoded request body

* support local requirements.txt

* formatting cleanup

* Update packages/now-python/now_handler.py

Co-Authored-By: NathanielHill <nata@goguna.com>

* Avoid error on empty POST body

Just realized I forgot to address the empty POST body error. This should do it

* quick formatting fix

remove double quotes for consistency
2019-02-19 11:28:21 -08:00
Steven
49e63de5fe Publish
- @now/next@0.0.85-canary.5
 - @now/node-server@0.4.27-canary.5
 - @now/node@0.4.29-canary.5
2019-02-17 19:09:27 -05:00
Steven
4742cd32f2 [now-node] add sourceMap flag to ncc (#222)
This adds a {sourceMap:true} flag to ncc builds
2019-02-17 19:08:19 -05:00
Steven
377b73105d [now-node] bump ncc to 0.15.2 (#221)
This has a couple fixes.

See release notes here https://github.com/zeit/ncc/releases/tag/0.15.2
2019-02-17 23:55:55 +01:00
Connor Davis
a5577efb3d Prepublish @now/next 2019-02-15 17:07:14 -06:00
Steven
2ec46dc5c9 Publish
- @now/node-server@0.4.27-canary.4
 - @now/node@0.4.29-canary.4
 - @now/rust@0.0.3-canary.2
2019-02-15 12:24:06 -05:00
Steven
42708ed93c [now-node] bump ncc to 0.15.1 (#219)
This fixes a regression introduced in ncc@0.13.2 and also prints the version of ncc used at build time.

See [release notes](https://github.com/zeit/ncc/releases/tag/0.15.1) for more info.
2019-02-15 17:48:58 +01:00
Antonio Nuno Monteiro
2fabe95f6e [now-rust] Build .rs entrypoints (#213) 2019-02-15 15:10:51 +00:00
Nathan Rajlich
ac1a3dab22 Publish
- @now/build-utils@0.4.35-canary.2
 - @now/go@0.2.13-canary.1
 - @now/rust@0.0.3-canary.1
2019-02-14 17:45:31 -08:00
Nathan Rajlich
ad4011512d [now-go] Refactor to be platform-aware for now dev (#216)
* [now-go] Refactor to be platform-aware for `now dev`

This is mostly to have `now dev` work, but also just a general cleanup
of the builder codebase.

Previously, the `get-exported-function-name` Go binary was being
compiled at publish-time for "linux x64" architecture, since that
is what AWS Lambda expects.

In order for `@now/go` to work on MacOS (or any other platform not
compatible with "linux x64") the helper program must be compiled by the
actual host machine, so that it builds a MacOS binary for example.
So building `get-exported-function-name` has been moved from the
"publish" step to the "postinstall" step.

Similarly, the `go` binary itself used to be downloaded explicitly by
the `build()` function during build-time. This step has been moved to
the "postinstall" script as well, so that said binary may be compiled.

This also makes sense because the `@now/go` builder will be downloaded
by `now dev` once, so this way the `go` binary only needs to be
downloaded once as well, rather than once per build.

Any assumptions about `GOOS` and `GOARCH` have also been removed.

* Don't lint the `go` tarball directory

* Use GitHub URL for the go bridge

* Tweak comments

* Use `glob()` instead of `FileFsRef`

`FileFsRef` appears to lose executable permissions on the file,
whereas `glob()` works as expected.
2019-02-14 17:36:33 -08:00
Nathan Rajlich
9ff1a25c8f [now-build-utils] Add FsFileRef.fromFsPath() helper function (#217)
* [now-build-utils] Add `FsFileRef.fromFile()` helper function

This helper function is very similar to the raw `FsFileRef` constructor,
however it stats the file to retrieve the proper `mode`, so that
settings like executable bits are not lost.

* Rename to `FileFsRef.fromFsPath()`
2019-02-14 17:09:01 -08:00
Antonio Nuno Monteiro
8039b3d377 [now-rust] Publish 0.1.2 to crates.io (#215) 2019-02-14 15:03:14 -08:00
Connor Davis
dd9017475c Publish
- @now/lambda@0.4.10-canary.1
 - @now/md@0.4.10-canary.1
 - @now/mdx-deck@0.4.19-canary.1
 - @now/next@0.0.85-canary.4
 - @now/node-server@0.4.27-canary.3
 - @now/node@0.4.29-canary.3
 - @now/php@0.4.14-canary.1
 - @now/static-build@0.4.19-canary.1
2019-02-12 21:41:52 -06:00
Connor Davis
031499014f Give tests 4 minutes instead of 2 2019-02-12 21:40:51 -06:00
Connor Davis
2a68d2a2ad Publish
- @now/build-utils@0.4.35-canary.1
 - @now/next@0.0.85-canary.3
 - @now/rust@0.0.3-canary.0
2019-02-12 21:00:19 -06:00
Connor Davis
31299fae6e Force canary bump in @now/next 2019-02-12 20:59:42 -06:00
Connor Davis
4bac0db379 fix @now/build-utils publishing tmp/ 2019-02-12 20:35:12 -06:00
Connor Davis
95e7d459d3 Increase timeout on now-build-utils 2019-02-12 19:39:15 -06:00
Antonio Nuno Monteiro
dd120b8d20 [now-rist] Implement simpler API for *.rs entrypoints (#210) 2019-02-12 13:21:03 -08:00
Mike Engel
b6975676e5 [now-rust] Import Deserialize traits behind de and ser (#203)
See https://github.com/serde-rs/serde/issues/1441
2019-02-12 13:16:14 -08:00
Igor Klopov
a7951dae81 [tests] produce public deployments 2019-02-12 22:07:10 +03:00
Connor Davis
b0c918f7fb Publish
- @now/next@0.0.85-canary.2
2019-02-11 20:28:52 -06:00
Connor Davis
df54dc7dc9 Download Entire Directory when Building now-next (#200) 2019-02-11 20:23:26 -06:00
paulogdm
0dd801ff6c Update now-next-legacy-mode.md (#208)
* Update now-next-legacy-mode.md

From `canary` to `latest`.

* Update now-next-no-serverless-pages-built.md

From `canary` to `latest`

* Apply suggestions from code review

Better words...

Co-Authored-By: paulogdm <paulogdemitri@gmail.com>
2019-02-11 14:41:42 +01:00
Connor Davis
398743ef95 Fix tests not completing 2019-02-08 20:03:32 -06:00
Nathan Rajlich
337c74b81b Publish
- @now/bash@0.1.2
2019-02-08 15:28:30 -08:00
Nathan Rajlich
680bb82ec3 [now-bash] Use mktemp dry run syntax that is compatible with BSD (#204)
For `now dev` running on a MacOS machine, some of our builders will need
to be adjusted to be "platform-aware".

In this case, `mktemp` is provided by BSD instead of GNU, which doesn't
support the long form `--dry-run` flag, however both support the `-u`
flag which does the same thing.
2019-02-08 15:25:51 -08:00
Nathan Rajlich
17ed5411e3 Publish
- @now/rust@0.0.2
2019-02-06 12:58:51 -08:00
Nathan Rajlich
d9bbcb6939 Publish
- @now/rust@0.0.2-canary.2
 - @now/static-build@0.4.19-canary.0
2019-02-05 12:06:03 -08:00
Igor Klopov
800e4de76f [tests] lint fixes 2019-02-05 22:35:18 +03:00
António Nuno Monteiro
864dd468d9 Place generated @now/rust lambdas in the location that matches their entrypoint (#198) 2019-02-05 11:31:41 -08:00
Igor Klopov
ba833871bb [tests] merge build.env from now.json 2019-02-05 22:15:02 +03:00
Arunoda Susiripal
e732bac78e @now/static-build@0.4.18 2019-02-05 02:27:26 +00:00
Arunoda Susiripal
28ea4015b4 Publish
- @now/static-build@0.4.18-canary.3
2019-02-05 02:12:15 +00:00
Arunoda Susiripal
a93d97cabd Use proper test code for now-static-build 2019-02-05 02:10:25 +00:00
Arunoda Susiripal
67f39f7c9b Publish
- @now/static-build@0.4.18-canary.2
2019-02-05 01:58:26 +00:00
Arunoda Susiripal
acd793b9e9 Fix a typo in a message of now-static-build 2019-02-05 01:57:27 +00:00
Arunoda Susiripal
f74d61279d Publish
- @now/static-build@0.4.18-canary.1
2019-02-05 01:50:45 +00:00
Arunoda Susiripala
fcb8eacec0 Check for distDir existence inside now-static-build (#197)
* Throw in case we don't see the distDir

* Add test cases.
2019-02-05 07:18:30 +05:30
Nathan Rajlich
c8fca2ba72 Publish
- @now/build-utils@0.4.35-canary.0
 - @now/rust@0.0.2-canary.1
2019-02-04 14:44:28 -08:00
António Nuno Monteiro
4feffa13eb Fix @now/rust for nested paths (#194)
* Fix `@now/rust` for nested paths

* fix bug

* fs-extra

* no need for mkdirp or rimraf anymore
2019-02-04 14:40:41 -08:00
Igor Klopov
3e330b25f4 Publish 2019-02-04 21:38:37 +03:00
Igor Klopov
9b2cae33af [build-utils] removed in-memory yarn cache 2019-02-04 19:45:46 +03:00
António Nuno Monteiro
4b6371530c Publish initial version to crates.io (#193) 2019-02-01 00:11:45 +01:00
Nathan Rajlich
9e1d577fc0 Publish
- @now/bash@0.1.2-canary.0
 - @now/build-utils@0.4.33-canary.2
 - @now/cgi@0.0.16-canary.0
 - @now/go@0.2.13-canary.0
 - @now/html-minifier@1.0.8-canary.0
 - @now/lambda@0.4.10-canary.0
 - @now/md@0.4.10-canary.0
 - @now/mdx-deck@0.4.19-canary.0
 - @now/next@0.0.85-canary.1
 - @now/node-bridge@0.1.11-canary.0
 - @now/node-server@0.4.27-canary.2
 - @now/node@0.4.29-canary.2
 - @now/optipng@0.4.9-canary.0
 - @now/php-bridge@0.4.14-canary.0
 - @now/php@0.4.14-canary.0
 - @now/python@0.0.41-canary.0
 - @now/rust@0.0.2-canary.0
 - @now/static-build@0.4.18-canary.0
 - @now/wordpress@0.4.15-canary.0
2019-01-31 14:32:48 -08:00
António Nuno Monteiro
cf2f542c71 Initial import of @now/rust (#191)
* Fix docstrings, remove unused rust dev dependency

* Add support for multiple binaries, prepareCache too

* Remove context from the handler signature, abstract over the AWS error

* Fix Rust tarball URL, caching and lint

* GCC URL
2019-01-31 22:29:50 +00:00
Igor Klopov
e608861e4e [now-node] bump ncc 2019-01-31 02:52:37 +03:00
Steven
a99b999209 Remove @now/build-utils peer dependency (#187)
* Remove peer dependencies

* Suppress eslint warning
2019-01-29 15:18:36 -05:00
Steven
fd9c6e7847 Add license to satisify warning (#186)
This solves the warning seen in `/_logs` all the time:

```
warning package.json: No license field
```
2019-01-29 12:59:25 -05:00
Steven
b2ad3a6147 Add repository key to package.json (#185) 2019-01-29 17:52:01 +01:00
Steven
997d3c2a30 Add link to builder docs (#184) 2019-01-29 17:24:54 +01:00
Igor Klopov
ca575bf0a6 Publish
- @now/next@0.0.85-canary.0
 - @now/node-server@0.4.27-canary.1
 - @now/node@0.4.29-canary.1
2019-01-29 19:09:01 +03:00
Igor Klopov
4c2e93ccef [now-node] bump ncc 2019-01-29 18:28:13 +03:00
paulogdm
4d6437d235 Fix broken error link (#175)
* Fix broken error link

* Added legacy mode error

Standard "Next.js" for all citations of Next.
Add "Legacy Mode" error.

* Update no serverless pages built doc

* Update doc on now/next legacy mode

* Add link after the error message
2019-01-28 19:05:02 +01:00
Igor Klopov
0d8058d062 Publish
- @now/node-server@0.4.27-canary.0
 - @now/node@0.4.29-canary.0
2019-01-27 21:58:47 +03:00
Igor Klopov
2b5cdfc0a7 [now-node] bump ncc 2019-01-27 15:27:00 +03:00
Igor Klopov
69a41f78fb Publish
- @now/build-utils@0.4.33-canary.1
2019-01-26 00:59:33 +03:00
Igor Klopov
a013d59d62 [build-utils] yarn in linux calls chown. mock it as well 2019-01-26 00:11:09 +03:00
Igor Klopov
173a29cfdb Publish
- @now/build-utils@0.4.33-canary.0
2019-01-25 02:51:46 +03:00
Igor Klopov
3f73451311 [build-utils] lint fixes 2019-01-25 00:55:32 +03:00
Igor Klopov
2fc706be43 [build-utils] make in-memory cache support git deps 2019-01-25 00:41:33 +03:00
Igor Klopov
0fb7eb6093 [build-utils] don't print download time of individual files 2019-01-24 18:44:10 +03:00
Igor Klopov
aa43c0bc87 [tests] consider now's 404 a case to retry 2019-01-23 18:43:55 +03:00
Igor Klopov
3c5925a6e3 [tests] print what failed page contains 2019-01-23 01:14:01 +03:00
Igor Klopov
9fc7b047f5 [tests] buildDelegate argument for testDeployment 2019-01-23 00:14:43 +03:00
Igor Klopov
ecae29457f Revert "[lerna] trying to set the order of package to publish"
This reverts commit 79251ad180.
2019-01-20 03:35:23 +03:00
Igor Klopov
77d445af71 Publish
- @now/bash@0.1.1
 - @now/build-utils@0.4.32
 - @now/cgi@0.0.15
 - @now/go@0.2.12
 - @now/html-minifier@1.0.7
 - @now/lambda@0.4.9
 - @now/md@0.4.9
 - @now/mdx-deck@0.4.18
 - @now/next@0.0.84
 - @now/node-bridge@0.1.10
 - @now/node-server@0.4.26
 - @now/node@0.4.28
 - @now/optipng@0.4.8
 - @now/php-bridge@0.4.13
 - @now/php@0.4.13
 - @now/static-build@0.4.17
 - @now/wordpress@0.4.14
2019-01-20 01:14:09 +03:00
Igor Klopov
79251ad180 [lerna] trying to set the order of package to publish 2019-01-20 00:01:16 +03:00
Igor Klopov
a215dc9103 [node-server] update tests for latest ncc 2019-01-19 23:23:44 +03:00
Nathan Rajlich
ea7d8f0f6c Update @zeit/ncc to v0.11.0 (#172) 2019-01-19 19:30:20 +03:00
Igor Klopov
2232efc984 fix misleading 'running npm install' messages in logs 2019-01-15 00:54:24 +03:00
Igor Klopov
b64ce0f3c0 [now-node] fix test for content-length 2019-01-14 03:27:15 +03:00
Igor Klopov
74233d50ad now/node: bump ncc 2019-01-12 05:20:37 +03:00
Nathan Rajlich
8aebec9fc3 Publish
- @now/bash@0.1.0
2019-01-10 12:27:59 -08:00
Igor Klopov
54584b7763 [tests] support NOW_TOKEN env var 2019-01-09 20:44:20 +03:00
Igor Klopov
d163fcbd71 [now-node-server] test for default content-type 2019-01-09 20:16:58 +03:00
Tim Neutkens
04c2996c76 [now-next] Add test for monorepo 2019-01-09 15:07:54 +01:00
Igor Klopov
2b69b898ed Publish
- @now/build-utils@0.4.32-canary.6
 - @now/node-bridge@0.1.10-canary.2
 - @now/node-server@0.4.26-canary.7
 - @now/node@0.4.28-canary.6
2019-01-08 01:42:13 +03:00
Igor Klopov
846aa11d6a now/node-bridge: postpone rejecting, let express print the error 2019-01-08 01:22:01 +03:00
Nathan Rajlich
a314a74479 Publish
- @now/bash@0.0.4-canary.2
2019-01-04 18:34:29 -08:00
Nathan Rajlich
40f029a72c [now-bash] Pipe response to jq stdin and use long options
Otherwise `jq` errors out with "arguments too long" when the response
body base64 is too large.

The long options are just for maintainability.
2019-01-04 18:33:56 -08:00
Nathan Rajlich
493d8a778f [now-bash] Update static-binaries to v1.0.0 2019-01-04 18:33:56 -08:00
Nathan Rajlich
cb5dcb658f [now-bash] Remove final build tree output
It's not necessary and can be too noisey if the lambda has a lot of files.
2019-01-04 18:33:56 -08:00
Nathan Rajlich
d77287d07b [now-bash] Add .editorconfig file 2019-01-04 18:33:56 -08:00
Igor Klopov
61d66bd957 Publish
- @now/build-utils@0.4.32-canary.5
 - @now/next@0.0.84-canary.0
2019-01-03 16:52:48 +03:00
Igor Klopov
ae73df9e3c build-utils: account google cloud functions 2019-01-03 16:29:55 +03:00
Tim Neutkens
cb09ae5bbf Publish
- @now/next@0.0.83
2019-01-03 11:56:29 +01:00
Tim Neutkens
a28eeacdaa Publish
- @now/build-utils@0.4.32-canary.4
 - @now/cgi@0.0.15-canary.0
 - @now/go@0.2.12-canary.0
 - @now/html-minifier@1.0.7-canary.0
 - @now/lambda@0.4.9-canary.0
 - @now/md@0.4.9-canary.0
 - @now/mdx-deck@0.4.18-canary.1
 - @now/next@0.0.83-canary.0
 - @now/node-bridge@0.1.10-canary.1
 - @now/node-server@0.4.26-canary.6
 - @now/node@0.4.28-canary.5
 - @now/optipng@0.4.8-canary.0
 - @now/php-bridge@0.4.13-canary.1
 - @now/php@0.4.13-canary.2
 - @now/static-build@0.4.17-canary.0
 - @now/wordpress@0.4.14-canary.1
2019-01-02 17:48:58 +01:00
Tim Neutkens
dd9d46d555 Add Next.js serverless target instead of lambdas build (#150)
* Give test more time

* Implement legacy flag

* Move tests

* Add test for new builder

* Add serverless target flow

* Remove prepareCache

* Add semver check

* Upgrade for latest Next.js canary
2019-01-02 17:48:01 +01:00
Igor Klopov
4472331ee0 tests: use token factory endpoint 2019-01-01 03:17:27 +03:00
Tim Neutkens
ac69836b44 Publish
- @now/next@0.0.82
2018-12-27 13:28:44 +01:00
Steven
15949a4ab4 Add missing license to package.json (#147) 2018-12-27 13:13:49 +01:00
Igor Klopov
697ada9d73 now-node: tests for content-length 2018-12-24 07:51:18 +03:00
Igor Klopov
cafbe30fa3 Publish
- @now/next@0.0.82-canary.1
 - @now/node-bridge@0.1.10-canary.0
 - @now/node-server@0.4.26-canary.5
 - @now/node@0.4.28-canary.4
2018-12-24 07:21:38 +03:00
Igor Klopov
583ebcc526 node-bridge: set content-length in response if user sets it 2018-12-24 06:57:17 +03:00
Connor Davis
52d1bd410c Lock Next.js Version (#145)
* Update utils.js

* Update utils.test.js

* Update utils.test.js

* Temp Commit

* Revert Temp Commit
2018-12-23 11:19:37 +01:00
Nathan Rajlich
11d0753bc1 Publish
- @now/bash@0.0.4-canary.1
 - @now/build-utils@0.4.32-canary.3
2018-12-21 13:46:41 -08:00
Nathan Rajlich
538710fe56 [now-bash] make the curl calls to AWS API silent (#142)
* [now-bash] make the `curl` calls to AWS API silent

Also log the exit status of the `handler` function.

* Remove `echo Request-Id`
2018-12-21 13:44:57 -08:00
Nathan Rajlich
2828c89e8d [now-bash] add stdio: inherit to builder.sh script (#143)
So that the build logs of the bash script are sent to the deployment
logs.
2018-12-21 13:44:42 -08:00
Igor Klopov
e40b45a939 tests: Accept = application/json for all api calls 2018-12-21 03:07:33 +03:00
Igor Klopov
38ba8a36fc Publish
- @now/build-utils@0.4.32-canary.2
 - @now/wordpress@0.4.14-canary.0
2018-12-21 00:59:08 +03:00
Igor Klopov
0323c505a3 now/build-utils: fix cross-install inssue in yarn in-memory cache 2018-12-20 09:03:52 +03:00
Igor Klopov
17ee07f4f6 now/build-utils: add cross-install test 2018-12-20 08:53:29 +03:00
Igor Klopov
0a6ada77ac now/wordpress: support non-root placement (monorepo) 2018-12-19 14:38:42 +03:00
Igor Klopov
4d817dd67d update yarn.lock file to avoid 'lerna ERR! EUNCOMMIT' 2018-12-19 01:55:54 +03:00
Igor Klopov
9682a7cc0b now/wordpress: release 0.4.13 manually 2018-12-18 10:25:24 +03:00
Igor Klopov
3456f23b3e now/wordpress: make latest.zip the default 2018-12-18 10:24:16 +03:00
Igor Klopov
800ca2cb0e Publish
- @now/php@0.4.13-canary.1
 - @now/wordpress@0.4.13-canary.1
2018-12-18 10:09:34 +03:00
Igor Klopov
ba54b4d706 now/wordpress: don't test it yet 2018-12-18 10:09:16 +03:00
Igor Klopov
e9482d66a9 now/php: dummy changes 2018-12-18 10:00:49 +03:00
Igor Klopov
401b669363 Publish
- @now/node-server@0.4.26-canary.4
 - @now/node@0.4.28-canary.3
 - @now/php-bridge@0.4.13-canary.0
 - @now/php@0.4.13-canary.0
 - @now/wordpress@0.4.13-canary.0
2018-12-18 09:51:38 +03:00
Igor Klopov
a2a0ede1f6 now/php-bridge: minor improvements 2018-12-18 09:49:19 +03:00
Igor Klopov
3c9fcff743 now/wordpress (#136)
* now/wordpress copied from new now/php

* download, decompress and merge release url

* static files

* require entrypoint be named 'wp-config.php'

* patch wp-db.php to use persistent connections

* "/wp-admin/index.php" rule is not needed

* emit lambda with name 'index.php'

* more staticRegexps

* make patchForPersistentConnections opt-in

* remove one more extra route

* update they way secrets are passed

* update route regexp a little
2018-12-18 09:47:07 +03:00
Igor Klopov
e5aa526583 now/php: update to use php-fpm 2018-12-18 04:24:08 +03:00
Igor Klopov
822b0ee3de now/node-server: yodasay.umd -> yodasay + pin 2018-12-18 03:21:45 +03:00
Igor Klopov
d612e46233 Publish
- @now/node-server@0.4.26-canary.3
 - @now/node@0.4.28-canary.2
2018-12-17 09:13:13 +03:00
Igor Klopov
77ee10cead now/node: bump ncc 2018-12-17 09:07:45 +03:00
Tim Neutkens
fb2029c464 Publish
- @now/build-utils@0.4.32-canary.1
 - @now/next@0.0.82-canary.0
 - @now/node-server@0.4.26-canary.2
 - @now/node@0.4.28-canary.1
 - @now/php@0.4.13-canary.1
2018-12-17 00:11:08 +01:00
Tim Neutkens
3b15755054 Add heap increase to now/next (#134) 2018-12-17 00:05:41 +01:00
Igor Klopov
4f65cc3aa8 now/build-utils: catch per-file stream errors 2018-12-16 03:17:04 +03:00
Igor Klopov
9936e35280 tests: retry on ETIMEDOUT 2018-12-15 21:55:55 +03:00
Igor Klopov
a04fd242b8 Revert "now/php: create php engine outside of request handling"
This reverts commit a7c2d9648a.
2018-12-12 01:09:12 +03:00
Igor Klopov
17bc6174a9 now/php: a regression test for engine reusage 2018-12-12 00:49:38 +03:00
Igor Klopov
a7c2d9648a now/php: create php engine outside of request handling 2018-12-11 23:04:47 +03:00
Igor Klopov
faa5ea9e21 now/php: fix $HTTP_RAW_POST_DATA 2018-12-11 08:49:45 +03:00
Igor Klopov
c52f30c898 now/php: fix $_SERVER['HTTP_HEADER'] 2018-12-11 07:53:46 +03:00
Igor Klopov
d675edf1dc this fixes several-values-per-header-name issue + test (#129) 2018-12-11 03:12:43 +03:00
Anthony Mittaz
f85c4f496f Bump ncc to v0.5.3 (#128)
* Bump `ncc` to v0.5.3

* Also bump `ncc` to v0.5.3 in now-node
2018-12-10 14:11:23 -08:00
Nathan Rajlich
d52d7904c2 Publish
- @now/bash@0.0.4-canary.0
2018-12-10 11:07:34 -08:00
Nathan Rajlich
79232024bd [now-bash] Rename serve function to handler (#125)
This is more consistent with what you would expect for a lambda
function, and we should maintain that convention.

For example: https://github.com/gkrizek/bash-lambda-layer
2018-12-10 10:55:38 -08:00
Igor Klopov
660b787bc3 tests: print headers in deploymentPost too 2018-12-10 06:34:21 +03:00
Igor Klopov
2dbf983ddb tests: account API_HOST in fetchApi, not in fetchWithAuth 2018-12-10 06:19:42 +03:00
Igor Klopov
0866ba9391 tests: export fetchApi and fetchWithAuth 2018-12-10 05:45:46 +03:00
Igor Klopov
d259a722a0 [test] print resp.headers on filePost failure 2018-12-10 05:10:32 +03:00
Igor Klopov
bf77c51f64 tests: retry on some network failures 2018-12-10 03:59:13 +03:00
Igor Klopov
062b78130c Publish
- @now/build-utils@0.4.32-canary.0
 - @now/mdx-deck@0.4.18-canary.0
 - @now/node-server@0.4.26-canary.1
 - @now/php@0.4.13-canary.0
2018-12-10 02:38:22 +03:00
Igor Klopov
fa70bc50cb sema around await streamToBuffer(zipFile.outputStream) (#124)
* sema around await streamToBuffer(zipFile.outputStream)

* lint fixes

* fix looking for 'undefined' scriptName
2018-12-10 02:30:16 +03:00
Igor Klopov
08e22b35d1 now/node-server: an improvement for 09-no-bundle 2018-12-09 00:32:15 +03:00
Igor Klopov
9d8f3315a1 now/php: partially revert set-cookie commit 2018-12-09 00:31:29 +03:00
Igor Klopov
a737a99a9d now/php: new test for setcookie + fix for bridge.go 2018-12-09 00:08:54 +03:00
Igor Klopov
ee92d92c9f now/php: fixed $_REQUEST 2018-12-08 07:58:08 +03:00
Igor Klopov
34d3ebd289 now/php: fix $_SERVER['SERVER_PROTOCOL'] 2018-12-08 06:35:46 +03:00
Igor Klopov
785f187e5d now/php: unescape cookie values 2018-12-08 06:25:39 +03:00
Igor Klopov
44449f474e now/php: fixed $_COOKIE 2018-12-08 01:03:18 +03:00
Igor Klopov
f44dae7f39 now/php: lint fixes 2018-12-07 23:06:45 +03:00
Igor Klopov
06f973f641 now/php: fixed $_SERVER['REQUEST_METHOD'] 2018-12-07 23:04:47 +03:00
Igor Klopov
47bb47804e now/php: fixed $_POST 2018-12-07 22:52:11 +03:00
António Nuno Monteiro
5df692979a Provide a complete implementation for @now/mdx-deck's analyze function (#97)
* Provide a complete implementation for `@now/mdx-deck`'s analyze function

Fixes #93

* Delete the analyze step
2018-12-07 03:44:56 +03:00
Igor Klopov
cd02d5390f now/php: simplify test.go and test.php 2018-12-07 03:37:25 +03:00
Igor Klopov
c93fd416c4 tests: pass 'env' from now.json to nowDeploy 2018-12-07 02:45:12 +03:00
Igor Klopov
431db7a62d bridge.go: remove duplicating 'host' header check 2018-12-07 02:40:09 +03:00
Igor Klopov
6f86c70313 now/php: use v[len(v) - 1] instead of iterating 2018-12-07 02:13:28 +03:00
Igor Klopov
0923fc9200 now/php: better parsing of _GET 2018-12-07 02:05:25 +03:00
Igor Klopov
787675f462 probe.js for more complex tests. probe.js for now/php globals 2018-12-06 20:53:41 +03:00
Igor Klopov
977615720a improvements and a test for now/php 2018-12-06 08:23:12 +03:00
Igor Klopov
1a4e64cd27 Publish
- @now/node-server@0.4.26-canary.0
 - @now/node@0.4.28-canary.0
2018-12-06 04:16:39 +03:00
Igor Klopov
c9fc255002 don't force set NODE_ENV=production. default instead (#120) 2018-12-06 03:03:02 +03:00
Igor Klopov
e83d4d4249 Publish
- @now/bash@0.0.3
 - @now/build-utils@0.4.31
 - @now/cgi@0.0.14
 - @now/go@0.2.11
 - @now/lambda@0.4.8
 - @now/md@0.4.8
 - @now/mdx-deck@0.4.17
 - @now/next@0.0.81
 - @now/node-server@0.4.25
 - @now/node@0.4.27
 - @now/php@0.4.12
 - @now/static-build@0.4.16
2018-12-06 01:54:09 +03:00
Igor Klopov
d2ca763079 update yarn.lock 2018-12-06 01:52:54 +03:00
Nathan Rajlich
2a95388f89 Publish
- @now/bash@0.0.3-canary.0
 - @now/build-utils@0.4.31-canary.2
 - @now/cgi@0.0.14-canary.0
 - @now/go@0.2.11-canary.1
 - @now/lambda@0.4.8-canary.1
 - @now/md@0.4.8-canary.2
 - @now/mdx-deck@0.4.17-canary.3
 - @now/node-server@0.4.25-canary.3
 - @now/node@0.4.27-canary.3
 - @now/php@0.4.12-canary.3
 - @now/static-build@0.4.16-canary.2
2018-12-04 17:40:38 -08:00
Nathan Rajlich
be9fedfdc4 Bump ncc to v0.4.1 (#117) 2018-12-04 17:38:41 -08:00
Igor Klopov
f0dee65f69 fixes for now/php 2018-12-05 00:46:59 +03:00
Daniel Levine
5514753c07 Update index.js (#115)
quick typo fix
2018-12-04 13:12:58 -08:00
Nathan Rajlich
7028556919 Add @now/bash builder (#114)
This builder expects a `.sh` shell script entrypoint file, and implements
a custom Lambda runtime written in bash.

* The entrypoint must define a `serve()` function which is executed for every
  HTTP request.
* The entrypoint _may_ define a `build()` function only gets executed
  during the build, to retreive any additional artifacts that the lambda
  depends on.
* `jq` is available implicitly, since the runtime depends on it to parse the
  event and generate the response.
* Stdin is the HTTP request body
* Stdout is the HTTP response body
* Invoke `http_response_code` to set the response status code
* Invoke `http_response_header` to set a HTTP response header
* Parse the `$REQUEST` variable with `jq` to get context about the request
  (path, method, etc.)
* [`import`](https://import.pw) is available by default, and `import`
  calls at the top-level of your file will be cached inside the lambda at
  build-time
* Since the runtime itself is written in bash, every time `serve` is
  invoked, _it is the same process_. This means that you can use global
  state in your script, for example:

```bash
COUNT=0

serve() {
  COUNT="$(( COUNT + 1 ))"
  echo "Invoke count: $COUNT"
}
```
2018-12-04 22:50:11 +03:00
Nathan Rajlich
a1f24853fc Create go/bridge common logic package for Go lambda builders (#96)
* Create `go/bridge` common logic package for Go lambda builders

* gofmt

* Fill out more properties on the `http.Request`
2018-12-04 22:47:09 +03:00
Igor Klopov
9804e82f8f add top-level package.json dummy 'version' entry 2018-12-04 07:28:00 +03:00
Igor Klopov
e96596634b specify '@canary' explicitly as builderUrl or buildUtilsUrl 2018-12-04 02:52:05 +03:00
Igor Klopov
495c193a40 Publish
- @now/build-utils@0.4.31-canary.1
 - @now/lambda@0.4.8-canary.0
 - @now/md@0.4.8-canary.1
 - @now/mdx-deck@0.4.17-canary.2
 - @now/node-server@0.4.25-canary.2
 - @now/node@0.4.27-canary.2
 - @now/php@0.4.12-canary.2
 - @now/static-build@0.4.16-canary.1
2018-12-04 02:03:45 +03:00
Igor Klopov
9d77d89513 bump ncc to 0.3.0 (#113) 2018-12-04 02:00:33 +03:00
Igor Klopov
bcffe0db91 take random token from pool if CIRCLE_BUILD_NUM is absent 2018-12-04 01:02:21 +03:00
Igor Klopov
228892fe9f pass API_HOST from process.env, don't write auth.json 2018-12-04 00:29:46 +03:00
Igor Klopov
c7d434c81d More tests 4 (#112)
* replace RANDOMNESS_PLACEHOLDER in all files

* [wip] test for now/lambda

* fix for lambda test

* testDeployment to return { deploymentId, deploymentUrl }
2018-12-04 00:03:25 +03:00
Igor Klopov
66bf4aa25a Publish
- @now/md@0.4.8-canary.0
 - @now/mdx-deck@0.4.17-canary.1
 - @now/next@0.0.81-canary.1
 - @now/node-server@0.4.25-canary.1
 - @now/node@0.4.27-canary.1
 - @now/php@0.4.12-canary.1
 - @now/static-build@0.4.16-canary.0
2018-12-03 04:54:10 +03:00
Igor Klopov
f328a53a3f bump ncc to 0.2.0 (#110) 2018-12-03 04:51:20 +03:00
Tim Neutkens
168b4cf2bb Include /static directory for now/next (#109) 2018-12-02 18:40:13 +01:00
Thomas Lindstrøm
a91e3da7d8 Support default export from import/export syntax (#30)
Fix issue where files using new `import/export` syntax ran into 502 when also exporting other named exports.
https://spectrum.chat/thread/4322e805-b8ba-43d2-96e2-98b2497724e3

```
const data = {};

export default function handler(request, response) {
  response.end('hello');
}

export {data};
```
2018-11-30 08:17:07 +03:00
Igor Klopov
756c452203 bump ncc in node-server and node 2018-11-30 07:59:11 +03:00
Igor Klopov
80db1937f8 take pool position from CIRCLE_BUILD_NUM 2018-11-29 05:35:45 +03:00
Igor Klopov
d9df4b0929 pick auth token from pool 2018-11-29 05:10:47 +03:00
Igor Klopov
08c52ebbf2 More tests 3 (#101)
* test for now/md

* yarn.lock is not needed in apollo anymore

* test for now/mdx
2018-11-29 04:39:29 +03:00
Tim Neutkens
fe8ead391a Publish
- @now/next@0.0.81-canary.0
2018-11-28 19:21:44 +01:00
Tim Neutkens
5d45f2df31 @now/next Fix prepareCache (#98) 2018-11-28 19:19:01 +01:00
Nathan Rajlich
1385c1ca48 Add yarn.lock file to root 2018-11-27 16:10:36 -08:00
Nathan Rajlich
4c63009123 Add manual publish instructions to README 2018-11-27 16:10:18 -08:00
Nathan Rajlich
389c85cef5 Publish
- @now/go@0.2.11-canary.0
 - @now/mdx-deck@0.4.17-canary.0
2018-11-27 16:06:37 -08:00
Vince Picone
227c239bbc [now/mdx-deck] update mdx-deck to v1.7.15 (#86)
* Update mdx-deck dependancy

Builds failing due to a breaking change in babel-plugin-styled-components 1.9.0. Updates mdx-deck to a version with babel-plugin-styled-components pinned to 1.8.0.

https://github.com/jxnblk/mdx-deck/issues/228

Related: https://github.com/styled-components/babel-plugin-styled-components/issues/182

* Only changed version in one place.
2018-11-27 15:58:10 -08:00
Nathan Rajlich
b93736132a [now-go] always send the response as base64 (#85)
This is in-line with the CGI and PHP (#83) builders.

(Side note: we really need to make a common go import for this logic…)
2018-11-27 15:51:05 -08:00
Igor Klopov
26849422ff Publish
- @now/build-utils@0.4.31-canary.0
 - @now/node-server@0.4.25-canary.0
 - @now/node@0.4.27-canary.0
2018-11-28 02:18:45 +03:00
Igor Klopov
31dd1ca491 build-utils: inject memory-fs for yarn cache (#91)
* build-utils: inject memory-fs for yarn cache

* ditch shelljs dependency

* try to cover circle ci odd yarn installation

* Revert "try to cover circle ci odd yarn installation"

This reverts commit 751949a5dd209bab34934042eba3be1904a86ac9.

* use in-memory cache for aws only

* separate isInsideCachePath function

* print 'using memory-fs for yarn cache'

* wrong name. isInsideCachePath -> isOutsideCachePath
2018-11-27 22:12:37 +03:00
Igor Klopov
04a1ce89b3 bump ncc in node-server and node 2018-11-27 22:00:56 +03:00
Igor Klopov
3e247fd16d Tests for ncc assets (#82)
* [wip] added a test for ncc assets

* bump ncc, add 08-assets test to node-server as well

* builder-utils: don't run all fixtures, just some
2018-11-27 05:58:26 +03:00
Nathan Rajlich
9e127421ad Publish
- @now/php@0.4.12-canary.0
2018-11-26 16:51:13 -08:00
Nathan Rajlich
337d0cb1ed [now-php] set the proper response status code (#84)
1. The initial status code should be 200 (so that the first PHP call to `http_status_code` returns 200, as per the PHP documentation).
1. Extract the resulting status code and return it in the response.
2018-11-26 16:47:44 -08:00
Nathan Rajlich
ad3cdf46f4 [now-php] always send the response as base64 (#83)
This should address https://spectrum.chat/zeit/general/corrupted-image-using-php~9fbb8cc5-b210-49d1-8934-b393a628219f
2018-11-26 16:34:21 -08:00
250 changed files with 15968 additions and 3754 deletions

12
.circleci/build.sh Executable file
View File

@@ -0,0 +1,12 @@
#!/bin/bash
set -euo pipefail
circleci_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
needs_build="$(grep -rn '"build"' packages/*/package.json | cut -d: -f1)"
for pkg in $needs_build; do
dir="$(dirname "$pkg")"
cd "$circleci_dir/../$dir"
echo "Building \`$dir\`"
yarn build
done

View File

@@ -23,6 +23,9 @@ jobs:
- run:
name: Linting
command: yarn lint
- run:
name: Building
command: ./.circleci/build.sh
- run:
name: Tests
command: yarn test
@@ -30,11 +33,8 @@ jobs:
name: Potentially save npm token
command: "([[ ! -z $NPM_TOKEN ]] && echo \"//registry.npmjs.org/:_authToken=$NPM_TOKEN\" >> ~/.npmrc) || echo \"Did not write npm token\""
- run:
name: Potentially publish canary release
command: "if ls ~/.npmrc >/dev/null 2>&1 && [[ $(git describe --exact-match 2> /dev/null || :) =~ -canary ]]; then yarn run lerna publish from-git --npm-tag canary --yes; else echo \"Did not publish\"; fi"
- run:
name: Potentially publish stable release
command: "if ls ~/.npmrc >/dev/null 2>&1 && [[ ! $(git describe --exact-match 2> /dev/null || :) =~ -canary ]]; then yarn run lerna publish from-git --yes; else echo \"Did not publish\"; fi"
name: Potentially publish releases to npm
command: ./.circleci/publish.sh
workflows:
version: 2
build-and-deploy:

24
.circleci/publish.sh Executable file
View File

@@ -0,0 +1,24 @@
#!/bin/bash
set -euo pipefail
if [ ! -e ~/.npmrc ]; then
echo "~/.npmrc file does not exist, skipping publish"
exit 0
fi
npm_tag=""
tag="$(git describe --tags --exact-match 2> /dev/null || :)"
if [ -z "$tag" ]; then
echo "Not a tagged commit, skipping publish"
exit 0
fi
if [[ "$tag" =~ -canary ]]; then
echo "Publishing canary release"
npm_tag="--npm-tag canary"
else
echo "Publishing stable release"
fi
yarn run lerna publish from-git $npm_tag --yes

View File

@@ -1,3 +1,4 @@
/tmp/*
/node_modules/*
/**/node_modules/*
/packages/now-go/go/*

2
.gitignore vendored
View File

@@ -1,2 +1,4 @@
node_modules
tmp
target/
.next

3
.prettierrc.json Normal file
View File

@@ -0,0 +1,3 @@
{
"singleQuote": true
}

View File

@@ -2,7 +2,7 @@
This is the full list of official Builders provided by the ZEIT team.
More details here: http://zeit.co/docs
More details here: https://zeit.co/docs/v2/deployments/builders/overview/
### Publishing to npm
@@ -19,3 +19,9 @@ For the canary channel use:
```
yarn publish-canary
```
CircleCI will take care of publishing the updated packages to npm from there.
If for some reason CircleCI fails to publish the npm package, you may do so
manually by running `npm publish` from the package directory. Make sure to
include the `--tag canary` parameter if you are publishing a canary release!

View File

@@ -0,0 +1,73 @@
# `@now/next` Legacy Mode
#### Why This Warning Occurred
`@now/next` has two modes: `legacy` and `serverless`. You will always want to use the `serverless` mode. `legacy` is to provide backwards compatibility with previous `@now/next` versions.
The differences:
Legacy:
- Minimal lambda size of `2.2Mb` (approximately)
- Forces `next@v7.0.2-canary.49` and `next-server@v7.0.2-canary.49`
- Forces all `dependencies` to be `devDependencies`
- Loads `next.config.js` on bootup, breaking sometimes when users didn't use `phases` to load files
- Used `next-server` which is the full Next.js server with routing etc.
- Runs `npm install`
- Runs `npm run now-build`
- Runs `npm install --production` after build
Serverless:
- Minimal lambda size of `49Kb` (approximately)
- Uses Next.js build targets (`target: 'serverless'`) in `next.config.js`. [documentation](https://github.com/zeit/next.js#summary)
- Does not make changes to your application dependencies
- Does not load `next.config.js` ([as per the serverless target documentation](https://github.com/zeit/next.js#summary))
- Runs `npm install`
- Runs `npm run now-build`
- Does not run `npm install --production` as the output from the build is all that's needed to bundle lambdas.
- No runtime dependencies, meaning smaller lambda functions
- Optimized for fast [cold start](https://zeit.co/blog/serverless-ssr#cold-start)
#### Possible Ways to Fix It
In order to create the smallest possible lambdas Next.js has to be configured to build for the `serverless` target.
1. Serverless Next.js requires Next.js 8 or later, to upgrade you can install the `latest` version:
```
npm install next --save
```
2. Add the `now-build` script to your `package.json`
```json
{
"scripts": {
"now-build": "next build"
},
}
```
3. Add `target: 'serverless'` to `next.config.js`
```js
module.exports = {
target: 'serverless'
// Other options are still valid
}
```
4. Optionally make sure the `"src"` in `"builds"` points to your application `package.json`
```js
{
"version": 2,
"builds": [{ "src": "package.json", "use": "@now/next" }]
}
```
### Useful Links
- [Serverless target implementation](https://github.com/zeit/now-builders/pull/150)

View File

@@ -0,0 +1,45 @@
# `@now/next` No Serverless Pages Built
#### Why This Error Occurred
This error occurs when you have your application is not configured for Serverless Next.js build output.
#### Possible Ways to Fix It
In order to create the smallest possible lambdas Next.js has to be configured to build for the `serverless` target.
1. Serverless Next.js requires Next.js 8 or later, to upgrade you can install the `latest` version:
```
npm install next --save
```
2. Add the `now-build` script to your `package.json`
```json
{
"scripts": {
"now-build": "next build"
},
}
```
3. Add `target: 'serverless'` to `next.config.js`
```js
module.exports = {
target: 'serverless'
// Other options
}
```
4. Remove `distDir` from `next.config.js` as `@now/next` can't parse this file and expects your build output at `/.next`
5. Optionally make sure the `"src"` in `"builds"` points to your application `package.json`
```js
{
"version": 2,
"builds": [{ "src": "package.json", "use": "@now/next" }]
}
```

View File

@@ -1,5 +1,6 @@
{
"name": "now-builders",
"version": "0.0.0",
"private": true,
"license": "MIT",
"dependencies": {
@@ -14,13 +15,13 @@
"publish-stable": "lerna version",
"publish-canary": "lerna version prerelease --preid canary",
"lint": "tsc && eslint .",
"test": "jest --runInBand",
"test": "jest --runInBand --verbose",
"lint-staged": "lint-staged"
},
"pre-commit": "lint-staged",
"lint-staged": {
"*.js": [
"prettier --write --single-quote",
"prettier --write",
"eslint --fix",
"git add"
]
@@ -30,6 +31,8 @@
"@types/glob": "^7.1.1",
"@types/multistream": "^2.1.1",
"@types/node": "^10.12.8",
"async-retry": "1.2.3",
"buffer-replace": "^1.0.0",
"eslint": "^5.9.0",
"eslint-config-airbnb-base": "^13.1.0",
"eslint-config-prettier": "^3.1.0",

View File

@@ -0,0 +1,32 @@
root = true
[*]
indent_style = tab
indent_size = 4
tab_width = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[{*.json,*.json.example,*.gyp,*.yml}]
indent_style = space
indent_size = 2
[*.py]
indent_style = space
indent_size = 4
[*.md]
trim_trailing_whitespace = false
# Ideal settings - some plugins might support these.
[*.js]
quote_type = single
[{*.c,*.cc,*.h,*.hh,*.cpp,*.hpp,*.m,*.mm,*.mpp,*.js,*.java,*.go,*.rs,*.php,*.ng,*.jsx,*.ts,*.d,*.cs,*.swift}]
curly_bracket_next_line = false
spaces_around_operators = true
spaces_around_brackets = outside
# close enough to 1TB
indent_brace_style = K&R

2
packages/now-bash/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
node_modules
handler

14
packages/now-bash/bootstrap Executable file
View File

@@ -0,0 +1,14 @@
#!/bin/bash
set -euo pipefail
cd "$LAMBDA_TASK_ROOT"
# Configure `import`
export IMPORT_CACHE="$LAMBDA_TASK_ROOT/.import-cache"
export PATH="$IMPORT_CACHE/bin:$PATH"
# Load `import` and runtime
. "$(which import)"
. "$IMPORT_CACHE/runtime.sh"
# Load user code and process events in a loop forever
_lambda_runtime_init

40
packages/now-bash/builder.sh Executable file
View File

@@ -0,0 +1,40 @@
#!/bin/bash
set -euo pipefail
# `import` debug logs are always enabled during build
export IMPORT_DEBUG=1
# Install `import`
IMPORT_BIN="$IMPORT_CACHE/bin/import"
mkdir -p "$(dirname "$IMPORT_BIN")"
curl -sfLS https://import.pw > "$IMPORT_BIN"
chmod +x "$IMPORT_BIN"
# For now only the entrypoint file is copied into the lambda
mkdir -p "$(dirname "$ENTRYPOINT")"
cp "$SRC/$ENTRYPOINT" "$ENTRYPOINT"
# Copy in the runtime
cp "$BUILDER/runtime.sh" "$IMPORT_CACHE"
cp "$BUILDER/bootstrap" .
# Load `import`
. "$(which import)"
# Cache runtime and user dependencies
echo "Caching imports in \"$ENTRYPOINT\"…"
. "$IMPORT_CACHE/runtime.sh"
. "$ENTRYPOINT"
echo "Done caching imports"
# Run user build script
if declare -f build > /dev/null; then
echo "Running \`build\` function in \"$ENTRYPOINT\"…"
build "$@"
fi
# Ensure the entrypoint defined a `handler` function
if ! declare -f handler > /dev/null; then
echo "ERROR: A \`handler\` function must be defined in \"$ENTRYPOINT\"!" >&2
exit 1
fi

View File

@@ -0,0 +1,57 @@
const execa = require('execa');
const { join } = require('path');
const snakeCase = require('snake-case');
const glob = require('@now/build-utils/fs/glob'); // eslint-disable-line import/no-extraneous-dependencies
const download = require('@now/build-utils/fs/download'); // eslint-disable-line import/no-extraneous-dependencies
const { createLambda } = require('@now/build-utils/lambda'); // eslint-disable-line import/no-extraneous-dependencies
const getWritableDirectory = require('@now/build-utils/fs/get-writable-directory'); // eslint-disable-line import/no-extraneous-dependencies
exports.config = {
maxLambdaSize: '10mb',
};
exports.analyze = ({ files, entrypoint }) => files[entrypoint].digest;
exports.build = async ({
workPath, files, entrypoint, config,
}) => {
const srcDir = await getWritableDirectory();
console.log('downloading files...');
await download(files, srcDir);
const configEnv = Object.keys(config).reduce((o, v) => {
o[`IMPORT_${snakeCase(v).toUpperCase()}`] = config[v]; // eslint-disable-line no-param-reassign
return o;
}, {});
const IMPORT_CACHE = `${workPath}/.import-cache`;
const env = Object.assign({}, process.env, configEnv, {
PATH: `${IMPORT_CACHE}/bin:${process.env.PATH}`,
IMPORT_CACHE,
SRC: srcDir,
BUILDER: __dirname,
ENTRYPOINT: entrypoint,
});
const builderPath = join(__dirname, 'builder.sh');
await execa(builderPath, [entrypoint], {
env,
cwd: workPath,
stdio: 'inherit',
});
const lambda = await createLambda({
files: await glob('**', workPath),
handler: entrypoint, // not actually used in `bootstrap`
runtime: 'provided',
environment: Object.assign({}, configEnv, {
SCRIPT_FILENAME: entrypoint,
}),
});
return {
[entrypoint]: lambda,
};
};

View File

@@ -0,0 +1,24 @@
{
"name": "@now/bash",
"version": "0.1.4-canary.0",
"description": "Now 2.0 builder for HTTP endpoints written in Bash",
"main": "index.js",
"author": "Nathan Rajlich <nate@zeit.co>",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/zeit/now-builders.git",
"directory": "packages/now-bash"
},
"files": [
"builder.sh",
"runtime.sh",
"bootstrap",
"index.js",
"package.json"
],
"dependencies": {
"execa": "^1.0.0",
"snake-case": "^2.1.0"
}
}

View File

@@ -0,0 +1,114 @@
import "static-binaries@1.0.0"
static_binaries jq
# These get reset upon each request
_STATUS_CODE="$(mktemp)"
_HEADERS="$(mktemp)"
_lambda_runtime_api() {
local endpoint="$1"
shift
curl -sfLS "http://$AWS_LAMBDA_RUNTIME_API/2018-06-01/runtime/$endpoint" "$@"
}
_lambda_runtime_init() {
# Initialize user code
. "$SCRIPT_FILENAME" || {
local exit_code="$?"
local error
error='{"exitCode":'"$exit_code"'}'
_lambda_runtime_api "init/error" -X POST -d "$error"
exit "$EXIT_CODE"
}
# Process events
while true; do _lambda_runtime_next; done
}
_lambda_runtime_next() {
echo 200 > "$_STATUS_CODE"
echo '{"content-type":"text/plain; charset=utf8"}' > "$_HEADERS"
local headers
headers="$(mktemp)"
# Get an event
local event
event="$(mktemp)"
_lambda_runtime_api invocation/next -D "$headers" | jq --raw-output --monochrome-output '.body' > "$event"
local request_id
request_id="$(grep -Fi Lambda-Runtime-Aws-Request-Id "$headers" | tr -d '[:space:]' | cut -d: -f2)"
rm -f "$headers"
# Execute the handler function from the script
local body
body="$(mktemp)"
local exit_code=0
REQUEST="$event"
# Stdin of the `handler` function is the HTTP request body.
# Need to use a fifo here instead of bash <() because Lambda
# errors with "/dev/fd/63 not found" for some reason :/
local stdin
stdin="$(mktemp -u)"
mkfifo "$stdin"
_lambda_runtime_body < "$event" > "$stdin" &
handler "$event" < "$stdin" > "$body" || exit_code="$?"
rm -f "$event" "$stdin"
if [ "$exit_code" -eq 0 ]; then
# Send the response
jq --raw-input --raw-output --compact-output --slurp --monochrome-output \
--arg statusCode "$(cat "$_STATUS_CODE")" \
--argjson headers "$(cat "$_HEADERS")" \
'{statusCode:$statusCode|tonumber, headers:$headers, encoding:"base64", body:.|@base64}' < "$body" \
| _lambda_runtime_api "invocation/$request_id/response" -X POST -d @- > /dev/null
rm -f "$body" "$_HEADERS"
else
echo "\`handler\` function return code: $exit_code"
_lambda_runtime_api "invocation/$request_id/error" -X POST -d @- > /dev/null <<< '{"exitCode":'"$exit_code"'}'
fi
}
_lambda_runtime_body() {
local event
event="$(cat)"
if [ "$(jq --raw-output '.body | type' <<< "$event")" = "string" ]; then
if [ "$(jq --raw-output '.encoding' <<< "$event")" = "base64" ]; then
jq --raw-output '.body' <<< "$event" | base64 --decode
else
# assume plain-text body
jq --raw-output '.body' <<< "$event"
fi
fi
}
# Set the response status code.
http_response_code() {
echo "$1" > "$_STATUS_CODE"
}
# Sets a response header.
# Overrides existing header if it has already been set.
http_response_header() {
local name="$1"
local value="$2"
local tmp
tmp="$(mktemp)"
jq --arg name "$name" --arg value "$value" '.[$name] = $value' < "$_HEADERS" > "$tmp"
mv -f "$tmp" "$_HEADERS"
}
http_response_redirect() {
http_response_code "${2:-302}"
http_response_header "location" "$1"
}
http_response_json() {
http_response_header "content-type" "application/json; charset=utf8"
}

146
packages/now-bash/yarn.lock Normal file
View File

@@ -0,0 +1,146 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
cross-spawn@^6.0.0:
version "6.0.5"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==
dependencies:
nice-try "^1.0.4"
path-key "^2.0.1"
semver "^5.5.0"
shebang-command "^1.2.0"
which "^1.2.9"
end-of-stream@^1.1.0:
version "1.4.1"
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43"
integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==
dependencies:
once "^1.4.0"
execa@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8"
integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==
dependencies:
cross-spawn "^6.0.0"
get-stream "^4.0.0"
is-stream "^1.1.0"
npm-run-path "^2.0.0"
p-finally "^1.0.0"
signal-exit "^3.0.0"
strip-eof "^1.0.0"
get-stream@^4.0.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5"
integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==
dependencies:
pump "^3.0.0"
is-stream@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ=
isexe@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=
lower-case@^1.1.1:
version "1.1.4"
resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac"
integrity sha1-miyr0bno4K6ZOkv31YdcOcQujqw=
nice-try@^1.0.4:
version "1.0.5"
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
no-case@^2.2.0:
version "2.3.2"
resolved "https://registry.yarnpkg.com/no-case/-/no-case-2.3.2.tgz#60b813396be39b3f1288a4c1ed5d1e7d28b464ac"
integrity sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==
dependencies:
lower-case "^1.1.1"
npm-run-path@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f"
integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=
dependencies:
path-key "^2.0.0"
once@^1.3.1, once@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
dependencies:
wrappy "1"
p-finally@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=
path-key@^2.0.0, path-key@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=
pump@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64"
integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==
dependencies:
end-of-stream "^1.1.0"
once "^1.3.1"
semver@^5.5.0:
version "5.6.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004"
integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==
shebang-command@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=
dependencies:
shebang-regex "^1.0.0"
shebang-regex@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=
signal-exit@^3.0.0:
version "3.0.2"
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=
snake-case@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/snake-case/-/snake-case-2.1.0.tgz#41bdb1b73f30ec66a04d4e2cad1b76387d4d6d9f"
integrity sha1-Qb2xtz8w7GagTU4srRt2OH1NbZ8=
dependencies:
no-case "^2.2.0"
strip-eof@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=
which@^1.2.9:
version "1.3.1"
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==
dependencies:
isexe "^2.0.0"
wrappy@1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=

View File

@@ -1 +1,2 @@
/test
tmp

View File

@@ -26,6 +26,18 @@ class FileFsRef {
this.fsPath = fsPath;
}
/**
* Creates a `FileFsRef` with the correct `mode` from the file system.
*
* @argument {Object} options
* @argument {string} options.fsPath
* @returns {Promise<FileFsRef>}
*/
static async fromFsPath({ fsPath }) {
const { mode } = await fs.lstat(fsPath);
return new FileFsRef({ mode, fsPath });
}
/**
* @argument {Object} options
* @argument {number} [options.mode=0o100644]

View File

@@ -49,14 +49,14 @@ class FileRef {
assert(url);
await semaToDownloadFromS3.acquire();
console.time(`downloading ${url}`);
// console.time(`downloading ${url}`);
try {
return await retry(
async () => {
const resp = await fetch(url);
if (!resp.ok) {
const error = new BailableError(
`${resp.status} ${resp.statusText}`,
`download: ${resp.status} ${resp.statusText} for ${url}`,
);
if (resp.status === 403) error.bail = true;
throw error;
@@ -66,7 +66,7 @@ class FileRef {
{ factor: 1, retries: 3 },
);
} finally {
console.timeEnd(`downloading ${url}`);
// console.timeEnd(`downloading ${url}`);
semaToDownloadFromS3.release();
}
}

View File

@@ -1,12 +1,10 @@
const path = require('path');
const fs = require('fs-extra');
const dev = !process.env.AWS_EXECUTION_ENV;
const TMP_PATH = dev ? path.join(process.cwd(), 'tmp') : '/tmp';
const { join } = require('path');
const { tmpdir } = require('os');
const { mkdirp } = require('fs-extra');
module.exports = async function getWritableDirectory() {
const name = Math.floor(Math.random() * 0x7fffffff).toString(16);
const directory = path.join(TMP_PATH, name);
await fs.mkdirp(directory);
const directory = join(tmpdir(), name);
await mkdirp(directory);
return directory;
};

View File

@@ -3,9 +3,9 @@ const fs = require('fs-extra');
const path = require('path');
const { spawn } = require('child_process');
function spawnAsync(command, args, cwd) {
function spawnAsync(command, args, cwd, opts = {}) {
return new Promise((resolve, reject) => {
const child = spawn(command, args, { stdio: 'inherit', cwd });
const child = spawn(command, args, { stdio: 'inherit', cwd, ...opts });
child.on('error', reject);
child.on('close', (code, signal) => (code !== 0
? reject(new Error(`Exited with ${code || signal}`))
@@ -13,9 +13,18 @@ function spawnAsync(command, args, cwd) {
});
}
async function chmodPlusX(fsPath) {
const s = await fs.stat(fsPath);
const newMode = s.mode | 64 | 8 | 1; // eslint-disable-line no-bitwise
if (s.mode === newMode) return;
const base8 = newMode.toString(8).slice(-3);
await fs.chmod(fsPath, base8);
}
async function runShellScript(fsPath) {
assert(path.isAbsolute(fsPath));
const destPath = path.dirname(fsPath);
await chmodPlusX(fsPath);
await spawnAsync(`./${path.basename(fsPath)}`, [], destPath);
return true;
}
@@ -35,7 +44,7 @@ async function scanParentDirs(destPath, scriptName) {
// eslint-disable-next-line no-await-in-loop
const packageJson = JSON.parse(await fs.readFile(packageJsonPath));
hasScript = Boolean(
packageJson.scripts && packageJson.scripts[scriptName],
packageJson.scripts && scriptName && packageJson.scripts[scriptName],
);
// eslint-disable-next-line no-await-in-loop
hasPackageLockJson = await fs.exists(
@@ -52,20 +61,34 @@ async function scanParentDirs(destPath, scriptName) {
return { hasScript, hasPackageLockJson };
}
async function runNpmInstall(destPath, args = []) {
async function installDependencies(destPath, args = []) {
assert(path.isAbsolute(destPath));
let commandArgs = args;
console.log(`installing to ${destPath}`);
const { hasPackageLockJson } = await scanParentDirs(destPath);
const opts = {
env: {
...process.env,
// This is a little hack to force `node-gyp` to build for the
// Node.js version that `@now/node` and `@now/node-server` use
npm_config_target: '8.10.0',
},
};
if (hasPackageLockJson) {
commandArgs = args.filter(a => a !== '--prefer-offline');
await spawnAsync('npm', ['install'].concat(commandArgs), destPath);
await spawnAsync('npm', ['cache', 'clean', '--force'], destPath);
await spawnAsync('npm', ['install'].concat(commandArgs), destPath, opts);
await spawnAsync('npm', ['cache', 'clean', '--force'], destPath, opts);
} else {
await spawnAsync('yarn', ['--cwd', destPath].concat(commandArgs), destPath);
await spawnAsync('yarn', ['cache', 'clean'], destPath);
await spawnAsync(
'yarn',
['--cwd', destPath].concat(commandArgs),
destPath,
opts,
);
await spawnAsync('yarn', ['cache', 'clean'], destPath, opts);
}
}
@@ -90,6 +113,7 @@ async function runPackageJsonScript(destPath, scriptName) {
module.exports = {
runShellScript,
runNpmInstall,
installDependencies,
runNpmInstall: installDependencies,
runPackageJsonScript,
};

View File

@@ -1,4 +1,5 @@
const assert = require('assert');
const Sema = require('async-sema');
const { ZipFile } = require('yazl');
const streamToBuffer = require('./fs/stream-to-buffer.js');
@@ -14,6 +15,7 @@ class Lambda {
}
}
const sema = new Sema(10);
const mtime = new Date(1540000000000);
async function createLambda({
@@ -23,24 +25,33 @@ async function createLambda({
assert(typeof handler === 'string', '"handler" is not a string');
assert(typeof runtime === 'string', '"runtime" is not a string');
assert(typeof environment === 'object', '"environment" is not an object');
const zipFile = new ZipFile();
Object.keys(files)
.sort()
.forEach((name) => {
const file = files[name];
const stream = file.toStream();
zipFile.addReadStream(stream, name, { mode: file.mode, mtime });
await sema.acquire();
try {
const zipFile = new ZipFile();
const zipBuffer = await new Promise((resolve, reject) => {
Object.keys(files)
.sort()
.forEach((name) => {
const file = files[name];
const stream = file.toStream();
stream.on('error', reject);
zipFile.addReadStream(stream, name, { mode: file.mode, mtime });
});
zipFile.end();
streamToBuffer(zipFile.outputStream).then(resolve).catch(reject);
});
zipFile.end();
const zipBuffer = await streamToBuffer(zipFile.outputStream);
return new Lambda({
zipBuffer,
handler,
runtime,
environment,
});
return new Lambda({
zipBuffer,
handler,
runtime,
environment,
});
} finally {
sema.release();
}
}
module.exports = {

View File

@@ -1,6 +1,12 @@
{
"name": "@now/build-utils",
"version": "0.4.30",
"version": "0.4.37-canary.1",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/zeit/now-builders.git",
"directory": "packages/now-build-utils"
},
"dependencies": {
"async-retry": "1.2.3",
"async-sema": "2.1.4",
@@ -8,6 +14,7 @@
"fs-extra": "7.0.0",
"glob": "7.1.3",
"into-stream": "4.0.0",
"memory-fs": "0.4.1",
"multistream": "2.1.1",
"node-fetch": "2.2.0",
"yazl": "2.4.3"

View File

@@ -0,0 +1,5 @@
const cowsay = require('cowsay').say;
module.exports = (req, resp) => {
resp.end(cowsay({ text: 'cross-cow:RANDOMNESS_PLACEHOLDER' }));
};

View File

@@ -0,0 +1,5 @@
{
"dependencies": {
"lib": "../lib"
}
}

View File

@@ -0,0 +1,7 @@
{
"name": "lib",
"version": "0.0.1",
"dependencies": {
"cowsay": "*"
}
}

View File

@@ -0,0 +1,9 @@
{
"version": 2,
"builds": [
{ "src": "api/index.js", "use": "@now/node" }
],
"probes": [
{ "path": "/api/index.js", "mustContain": "cross-cow:RANDOMNESS_PLACEHOLDER" }
]
}

View File

@@ -7,7 +7,8 @@ const {
testDeployment,
} = require('../../../test/lib/deployment/test-deployment.js');
jest.setTimeout(2 * 60 * 1000);
jest.setTimeout(4 * 60 * 1000);
const builderUrl = '@canary';
let buildUtilsUrl;
beforeAll(async () => {
@@ -25,8 +26,11 @@ for (const fixture of fs.readdirSync(fixturesPath)) {
// eslint-disable-next-line no-loop-func
it(`should build ${fixture}`, async () => {
await expect(
testDeployment({ buildUtilsUrl }, path.join(fixturesPath, fixture)),
).resolves.toBe(undefined);
testDeployment(
{ builderUrl, buildUtilsUrl },
path.join(fixturesPath, fixture),
),
).resolves.toBeDefined();
});
}
@@ -43,11 +47,17 @@ for (const builder of buildersToTestWith) {
// eslint-disable-next-line no-restricted-syntax
for (const fixture of fs.readdirSync(fixturesPath2)) {
// eslint-disable-next-line no-loop-func
it(`should build ${builder}/${fixture}`, async () => {
await expect(
testDeployment({ buildUtilsUrl }, path.join(fixturesPath2, fixture)),
).resolves.toBe(undefined);
});
// don't run all foreign fixtures, just some
if (['01-cowsay', '03-env-vars'].includes(fixture)) {
// eslint-disable-next-line no-loop-func
it(`should build ${builder}/${fixture}`, async () => {
await expect(
testDeployment(
{ builderUrl, buildUtilsUrl },
path.join(fixturesPath2, fixture),
),
).resolves.toBeDefined();
});
}
}
}

View File

@@ -1,10 +1,10 @@
const path = require('path');
const { mkdirp, copyFile } = require('fs-extra');
const glob = require('@now/build-utils/fs/glob');
const download = require('@now/build-utils/fs/download');
const { createLambda } = require('@now/build-utils/lambda');
const getWritableDirectory = require('@now/build-utils/fs/get-writable-directory');
const glob = require('@now/build-utils/fs/glob'); // eslint-disable-line import/no-extraneous-dependencies
const download = require('@now/build-utils/fs/download'); // eslint-disable-line import/no-extraneous-dependencies
const { createLambda } = require('@now/build-utils/lambda'); // eslint-disable-line import/no-extraneous-dependencies
const getWritableDirectory = require('@now/build-utils/fs/get-writable-directory'); // eslint-disable-line import/no-extraneous-dependencies
exports.analyze = ({ files, entrypoint }) => files[entrypoint].digest;

View File

@@ -1,152 +1,36 @@
package main
import (
"os"
"fmt"
"net"
"strings"
"io/ioutil"
now "../../utils/go/bridge"
"net/http"
"net/http/cgi"
"os"
"path/filepath"
"encoding/json"
b64 "encoding/base64"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
)
type Request struct {
Host string `json:"host"`
Path string `json:"path"`
Method string `json:"method"`
Headers map[string]string `json:"headers"`
Encoding string `json:"encoding,omitempty"`
Body string `json:"body"`
}
type Response struct {
StatusCode int `json:"statusCode"`
Headers map[string]string `json:"headers"`
Encoding string `json:"encoding,omitemtpy"`
Body string `json:"body"`
}
type ResponseError struct {
Code string `json:"code"`
Message string `json:"message"`
}
type ResponseErrorWrapper struct {
Error ResponseError `json:"error"`
}
type CgiHandler struct {
http.Handler
Dir string
Script string
}
func createErrorResponse(message string, code string, statusCode int) (Response, error) {
obj := ResponseErrorWrapper{
Error: ResponseError{
Code: code,
Message: message,
},
}
body, _ := json.Marshal(obj)
return Response{
StatusCode: statusCode,
Headers: map[string]string{
"Content-Type": "application/json",
},
Body: string(body),
}, nil
}
func (h *CgiHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
cgih := cgi.Handler{
handler := cgi.Handler{
Path: h.Script,
Root: "/" + h.Script,
Dir: h.Dir,
Env: []string{"SERVER_PORT=443", "HTTPS=on", "SERVER_SOFTWARE=@now/cgi"},
Dir: h.Dir,
Env: []string{
"HTTPS=on",
"SERVER_PORT=443",
"SERVER_SOFTWARE=@now/cgi",
},
}
cgih.ServeHTTP(w, r)
handler.ServeHTTP(w, r)
}
func main() {
l, err := net.Listen("tcp", ":0")
if err != nil {
panic(err)
}
workdir, _ := filepath.Abs(".")
script := os.Getenv("SCRIPT_FILENAME")
h := &CgiHandler{nil, workdir, script}
http.Handle("/", h)
go http.Serve(l, nil)
handler := func(_req events.APIGatewayProxyRequest) (Response, error) {
var req Request
err := json.Unmarshal([]byte(_req.Body), &req)
if err != nil {
fmt.Println(err)
return createErrorResponse("Invalid payload", "bad_request", 400)
}
if req.Encoding == "base64" {
decoded, _ := b64.StdEncoding.DecodeString(req.Body)
req.Body = string(decoded)
}
url := "http://" + l.Addr().String() + req.Path
internalReq, err := http.NewRequest(req.Method, url, strings.NewReader(req.Body))
if err != nil {
fmt.Println(err)
return createErrorResponse("Bad gateway internal req failed", "bad_gateway", 502)
}
for k, v := range req.Headers {
internalReq.Header.Add(k, v)
if strings.ToLower(k) == "host" {
internalReq.Host = v
}
}
client := &http.Client{}
internalRes, err := client.Do(internalReq)
if err != nil {
fmt.Println(err)
return createErrorResponse("Bad gateway internal req Do failed", "bad_gateway", 502)
}
defer internalRes.Body.Close()
resHeaders := make(map[string]string, len(internalRes.Header))
for k, v := range internalRes.Header {
// FIXME: support multiple values via concatenating with ','
// see RFC 7230, section 3.2.2
resHeaders[k] = v[0]
}
bodyBytes, err := ioutil.ReadAll(internalRes.Body)
if err != nil {
return createErrorResponse("Bad gateway ReadAll bytes from response failed", "bad_gateway", 502)
}
resBody := b64.StdEncoding.EncodeToString(bodyBytes)
return Response{
StatusCode: internalRes.StatusCode,
Headers: resHeaders,
Encoding: "base64",
Body: resBody,
}, nil
}
lambda.Start(handler)
handler := &CgiHandler{nil, workdir, script}
now.Start(handler)
}

View File

@@ -1,6 +1,12 @@
{
"name": "@now/cgi",
"version": "0.0.13",
"version": "0.0.16-canary.0",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/zeit/now-builders.git",
"directory": "packages/now-cgi"
},
"scripts": {
"test": "best -I test/*.js",
"prepublish": "./build.sh"
@@ -15,8 +21,5 @@
"devDependencies": {
"@zeit/best": "0.4.3",
"rmfr": "2.0.0"
},
"peerDependencies": {
"@now/build-utils": ">=0.0.1"
}
}

View File

@@ -1,3 +1,5 @@
node_modules
*.log
bin
/?.js
/go
/get-exported-function-name

View File

@@ -1,7 +0,0 @@
#!/usr/bin/env bash
mkdir -p bin
cd util
GOOS=linux GOARCH=amd64 go build get-exported-function-name.go
mv get-exported-function-name ../bin/

View File

@@ -1,23 +0,0 @@
const path = require('path');
const fetch = require('node-fetch');
const tar = require('tar');
const getWritableDirectory = require('@now/build-utils/fs/get-writable-directory.js');
const url = 'https://dl.google.com/go/go1.11.1.linux-amd64.tar.gz';
module.exports = async () => {
const res = await fetch(url);
const dir = await getWritableDirectory();
if (!res.ok) {
throw new Error(`Failed to download: ${url}`);
}
return new Promise((resolve, reject) => {
res.body
.on('error', reject)
.pipe(tar.extract({ cwd: dir, strip: 1 }))
.on('finish', () => resolve(path.join(dir, 'bin', 'go')));
});
};

View File

@@ -0,0 +1,129 @@
const tar = require('tar');
const execa = require('execa');
const fetch = require('node-fetch');
const { mkdirp } = require('fs-extra');
const { dirname, join } = require('path');
const debug = require('debug')('@now/go:go-helpers');
const archMap = new Map([['x64', 'amd64'], ['x86', '386']]);
const platformMap = new Map([['win32', 'windows']]);
// Location where the `go` binary will be installed after `postinstall`
const GO_DIR = join(__dirname, 'go');
const GO_BIN = join(GO_DIR, 'bin/go');
const getPlatform = p => platformMap.get(p) || p;
const getArch = a => archMap.get(a) || a;
const getGoUrl = (version, platform, arch) => {
const goArch = getArch(arch);
const goPlatform = getPlatform(platform);
const ext = platform === 'win32' ? 'zip' : 'tar.gz';
return `https://dl.google.com/go/go${version}.${goPlatform}-${goArch}.${ext}`;
};
async function getExportedFunctionName(filePath) {
debug('Detecting handler name for %o', filePath);
const bin = join(__dirname, 'get-exported-function-name');
const args = [filePath];
const name = await execa.stdout(bin, args);
debug('Detected exported name %o', name);
return name;
}
// Creates a `$GOPATH` directory tree, as per `go help gopath` instructions.
// Without this, `go` won't recognize the `$GOPATH`.
function createGoPathTree(goPath, platform, arch) {
const tuple = `${getPlatform(platform)}_${getArch(arch)}`;
debug('Creating GOPATH directory structure for %o (%s)', goPath, tuple);
return Promise.all([
mkdirp(join(goPath, 'bin')),
mkdirp(join(goPath, 'pkg', tuple)),
]);
}
async function get({ src } = {}) {
const args = ['get'];
if (src) {
debug('Fetching `go` dependencies for file %o', src);
args.push(src);
} else {
debug('Fetching `go` dependencies for cwd %o', this.cwd);
}
await this(...args);
}
async function build({ src, dest }) {
debug('Building `go` binary %o -> %o', src, dest);
let sources;
if (Array.isArray(src)) {
sources = src;
} else {
sources = [src];
}
await this('build', '-o', dest, ...sources);
}
async function createGo(
goPath,
platform = process.platform,
arch = process.arch,
opts = {},
goMod = false,
) {
const env = {
...process.env,
PATH: `${dirname(GO_BIN)}:${process.env.PATH}`,
GOPATH: goPath,
...opts.env,
};
if (goMod) {
env.GO111MODULE = 'on';
}
function go(...args) {
debug('Exec %o', `go ${args.join(' ')}`);
return execa('go', args, { stdio: 'inherit', ...opts, env });
}
go.cwd = opts.cwd || process.cwd();
go.get = get;
go.build = build;
go.goPath = goPath;
await createGoPathTree(goPath, platform, arch);
return go;
}
async function downloadGo(
dir = GO_DIR,
version = '1.12',
platform = process.platform,
arch = process.arch,
) {
debug('Installing `go` v%s to %o for %s %s', version, dir, platform, arch);
const url = getGoUrl(version, platform, arch);
debug('Downloading `go` URL: %o', url);
const res = await fetch(url);
if (!res.ok) {
throw new Error(`Failed to download: ${url} (${res.status})`);
}
// TODO: use a zip extractor when `ext === "zip"`
await mkdirp(dir);
await new Promise((resolve, reject) => {
res.body
.on('error', reject)
.pipe(tar.extract({ cwd: dir, strip: 1 }))
.on('error', reject)
.on('finish', resolve);
});
return createGo(dir, platform, arch);
}
module.exports = {
createGo,
downloadGo,
getExportedFunctionName,
};

View File

@@ -1,126 +1,186 @@
const path = require('path');
const { mkdirp, readFile, writeFile } = require('fs-extra');
const { join, dirname } = require('path');
const {
readFile, writeFile, pathExists, move,
} = require('fs-extra');
const execa = require('execa');
const { createLambda } = require('@now/build-utils/lambda.js');
const getWritableDirectory = require('@now/build-utils/fs/get-writable-directory.js');
const download = require('@now/build-utils/fs/download.js');
const downloadGit = require('lambda-git');
const glob = require('@now/build-utils/fs/glob.js');
const downloadGoBin = require('./download-go-bin');
const glob = require('@now/build-utils/fs/glob.js'); // eslint-disable-line import/no-extraneous-dependencies
const download = require('@now/build-utils/fs/download.js'); // eslint-disable-line import/no-extraneous-dependencies
const { createLambda } = require('@now/build-utils/lambda.js'); // eslint-disable-line import/no-extraneous-dependencies
const getWritableDirectory = require('@now/build-utils/fs/get-writable-directory.js'); // eslint-disable-line import/no-extraneous-dependencies
const { createGo, getExportedFunctionName } = require('./go-helpers');
// creates a `$GOPATH` direcotry tree, as per
// `go help gopath`'s instructions.
// without this, Go won't recognize the `$GOPATH`
async function createGoPathTree(goPath) {
await mkdirp(path.join(goPath, 'bin'));
await mkdirp(path.join(goPath, 'pkg', 'linux_amd64'));
}
exports.config = {
const config = {
maxLambdaSize: '10mb',
};
exports.build = async ({ files, entrypoint }) => {
console.log('downloading files...');
async function build({ files, entrypoint }) {
console.log('Downloading user files...');
const gitPath = await getWritableDirectory();
const goPath = await getWritableDirectory();
const srcPath = path.join(goPath, 'src', 'lambda');
const outDir = await getWritableDirectory();
await createGoPathTree(goPath);
const [goPath, outDir] = await Promise.all([
getWritableDirectory(),
getWritableDirectory(),
]);
const srcPath = join(goPath, 'src', 'lambda');
const downloadedFiles = await download(files, srcPath);
console.log('downloading go binary...');
const goBin = await downloadGoBin();
console.log('downloading git binary...');
// downloads a git binary that works on Amazon Linux and sets
// `process.env.GIT_EXEC_PATH` so `go(1)` can see it
await downloadGit({ targetDirectory: gitPath });
const goEnv = {
...process.env,
GOOS: 'linux',
GOARCH: 'amd64',
GOPATH: goPath,
};
console.log(`parsing AST for "${entrypoint}"`);
let handlerFunctionName = '';
console.log(`Parsing AST for "${entrypoint}"`);
let parseFunctionName;
try {
handlerFunctionName = await execa.stdout(
path.join(__dirname, 'bin', 'get-exported-function-name'),
[downloadedFiles[entrypoint].fsPath],
parseFunctionName = await getExportedFunctionName(
downloadedFiles[entrypoint].fsPath,
);
} catch (err) {
console.log(`failed to parse AST for "${entrypoint}"`);
console.log(`Failed to parse AST for "${entrypoint}"`);
throw err;
}
if (handlerFunctionName === '') {
const e = new Error(
`Could not find an exported function on "${entrypoint}"`,
if (!parseFunctionName) {
const err = new Error(
`Could not find an exported function in "${entrypoint}"`,
);
console.log(e.message);
throw e;
console.log(err.message);
throw err;
}
console.log(
`Found exported function "${handlerFunctionName}" on "${entrypoint}"`,
);
const handlerFunctionName = parseFunctionName.split(',')[0];
const origianlMainGoContents = await readFile(
path.join(__dirname, 'main.go'),
'utf8',
console.log(
`Found exported function "${handlerFunctionName}" in "${entrypoint}"`,
);
const mainGoContents = origianlMainGoContents.replace(
'__NOW_HANDLER_FUNC_NAME',
handlerFunctionName,
);
// in order to allow the user to have `main.go`, we need our `main.go` to be called something else
const mainGoFileName = 'main__now__go__.go';
// we need `main.go` in the same dir as the entrypoint,
// otherwise `go build` will refuse to build
const entrypointDirname = path.dirname(downloadedFiles[entrypoint].fsPath);
const entrypointDirname = dirname(downloadedFiles[entrypoint].fsPath);
// Go doesn't like to build files in different directories,
// so now we place `main.go` together with the user code
await writeFile(path.join(entrypointDirname, mainGoFileName), mainGoContents);
console.log('installing dependencies');
// `go get` will look at `*.go` (note we set `cwd`), parse
// the `import`s and download any packages that aren't part of the stdlib
try {
await execa(goBin, ['get'], {
env: goEnv,
cwd: entrypointDirname,
stdio: 'inherit',
});
} catch (err) {
console.log('failed to `go get`');
throw err;
}
console.log('running go build...');
try {
await execa(
goBin,
[
'build',
'-o',
path.join(outDir, 'handler'),
path.join(entrypointDirname, mainGoFileName),
downloadedFiles[entrypoint].fsPath,
],
{ env: goEnv, cwd: entrypointDirname, stdio: 'inherit' },
// check if package name other than main
const packageName = parseFunctionName.split(',')[1];
const isGoModExist = await pathExists(`${entrypointDirname}/go.mod`);
if (packageName !== 'main') {
const go = await createGo(
goPath,
process.platform,
process.arch,
{
cwd: entrypointDirname,
},
true,
);
} catch (err) {
console.log('failed to `go build`');
throw err;
if (!isGoModExist) {
try {
go('mod', 'init', packageName);
} catch (err) {
console.log(`failed to \`go mod init ${packageName}\``);
throw err;
}
}
const mainModGoFileName = 'main__mod__.go';
const modMainGoContents = await readFile(
join(__dirname, mainModGoFileName),
'utf8',
);
let goPackageName = `${packageName}/${packageName}`;
const goFuncName = `${packageName}.${handlerFunctionName}`;
if (isGoModExist) {
const goModContents = await readFile(
`${entrypointDirname}/go.mod`,
'utf8',
);
goPackageName = `${
goModContents.split('\n')[0].split(' ')[1]
}/${packageName}`;
}
const mainModGoContents = modMainGoContents
.replace('__NOW_HANDLER_PACKAGE_NAME', goPackageName)
.replace('__NOW_HANDLER_FUNC_NAME', goFuncName);
// write main__mod__.go
await writeFile(
join(entrypointDirname, mainModGoFileName),
mainModGoContents,
);
// move user go file to folder
try {
await move(
downloadedFiles[entrypoint].fsPath,
`${join(entrypointDirname, packageName, entrypoint)}`,
);
} catch (err) {
console.log('failed to move entry to package folder');
throw err;
}
console.log('tidy go.mod file');
try {
// ensure go.mod up-to-date
await go('mod', 'tidy');
} catch (err) {
console.log('failed to `go mod tidy`');
throw err;
}
console.log('Running `go build`...');
const destPath = join(outDir, 'handler');
try {
const src = [join(entrypointDirname, mainModGoFileName)];
await go.build({ src, dest: destPath });
} catch (err) {
console.log('failed to `go build`');
throw err;
}
} else {
const go = await createGo(
goPath,
process.platform,
process.arch,
{
cwd: entrypointDirname,
},
false,
);
const origianlMainGoContents = await readFile(
join(__dirname, 'main.go'),
'utf8',
);
const mainGoContents = origianlMainGoContents.replace(
'__NOW_HANDLER_FUNC_NAME',
handlerFunctionName,
);
// in order to allow the user to have `main.go`,
// we need our `main.go` to be called something else
const mainGoFileName = 'main__now__go__.go';
// Go doesn't like to build files in different directories,
// so now we place `main.go` together with the user code
await writeFile(join(entrypointDirname, mainGoFileName), mainGoContents);
// `go get` will look at `*.go` (note we set `cwd`), parse the `import`s
// and download any packages that aren't part of the stdlib
try {
await go.get();
} catch (err) {
console.log('failed to `go get`');
throw err;
}
console.log('Running `go build`...');
const destPath = join(outDir, 'handler');
try {
const src = [
join(entrypointDirname, mainGoFileName),
downloadedFiles[entrypoint].fsPath,
];
await go.build({ src, dest: destPath });
} catch (err) {
console.log('failed to `go build`');
throw err;
}
}
const lambda = await createLambda({
@@ -133,4 +193,6 @@ exports.build = async ({ files, entrypoint }) => {
return {
[entrypoint]: lambda,
};
};
}
module.exports = { config, build };

View File

@@ -1,143 +1,10 @@
package main
import (
b64 "encoding/base64"
"encoding/json"
"fmt"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
"io/ioutil"
"net"
"net/http"
"strings"
now "github.com/zeit/now-builders/utils/go/bridge"
)
type Request struct {
Host string `json:"host"`
Path string `json:"path"`
Method string `json`
Headers map[string]string `json:"headers"`
Encoding string `json"encoding,omitempty"`
Body string `json:"body"`
}
type Response struct {
StatusCode int `json:"statusCode"`
Headers map[string]string `json:"headers"`
Encoding string `json:"encoding,omitemtpy"`
Body string `json:"body"`
}
type ResponseError struct {
Code string `json:"code"`
Message string `json:"message"`
}
type ResponseErrorWrapper struct {
Error ResponseError `json:"error"`
}
func createErrorResponse(message string, code string, statusCode int) (Response, error) {
obj := ResponseErrorWrapper{
Error: ResponseError{
Code: code,
Message: message,
},
}
body, _ := json.Marshal(obj)
return Response{
StatusCode: statusCode,
Headers: map[string]string{
"Content-Type": "application/json",
},
Body: string(body),
}, nil
}
func main() {
l, err := net.Listen("tcp", ":0")
if err != nil {
panic(err)
}
http.HandleFunc("/", __NOW_HANDLER_FUNC_NAME)
go http.Serve(l, nil)
handler := func(_req events.APIGatewayProxyRequest) (Response, error) {
var req Request
err := json.Unmarshal([]byte(_req.Body), &req)
if err != nil {
fmt.Println(err)
return createErrorResponse("Invalid payload", "bad_request", 400)
}
if req.Encoding == "base64" {
decoded, _ := b64.StdEncoding.DecodeString(req.Body)
req.Body = string(decoded)
}
url := "http://" + l.Addr().String() + req.Path
internalReq, err := http.NewRequest(req.Method, url, strings.NewReader(req.Body))
if err != nil {
fmt.Println(err)
return createErrorResponse("Bad gateway", "bad_gateway", 502)
}
for k, v := range req.Headers {
internalReq.Header.Add(k, v)
if strings.ToLower(k) == "host" {
// we need to set `Host` in the request
// because Go likes to ignore the `Host` header
// see https://github.com/golang/go/issues/7682
internalReq.Host = v
}
}
client := &http.Client{}
internalRes, err := client.Do(internalReq)
if err != nil {
fmt.Println(err)
return createErrorResponse("Bad gateway", "bad_gateway", 502)
}
defer internalRes.Body.Close()
resHeaders := make(map[string]string, len(internalRes.Header))
var resEncoding string
for k, v := range internalRes.Header {
// FIXME: support multiple values via concatenating with ','
// see RFC 7230, section 3.2.2
if strings.ToLower(k) == "x-now-response-encoding" {
// we don't want to send this header down
resEncoding = v[0]
} else {
resHeaders[k] = v[0]
}
}
bodyBytes, err := ioutil.ReadAll(internalRes.Body)
if err != nil {
return createErrorResponse("Bad gateway", "bad_gateway", 502)
}
var resBody string
if resEncoding == "base64" {
resBody = b64.StdEncoding.EncodeToString(bodyBytes)
} else {
resBody = string(bodyBytes)
}
return Response{
StatusCode: internalRes.StatusCode,
Headers: resHeaders,
Encoding: resEncoding,
Body: resBody,
}, nil
}
lambda.Start(handler)
now.Start(http.HandlerFunc(__NOW_HANDLER_FUNC_NAME))
}

View File

@@ -0,0 +1,12 @@
package main
import (
"net/http"
"__NOW_HANDLER_PACKAGE_NAME"
now "github.com/zeit/now-builders/utils/go/bridge"
)
func main() {
now.Start(http.HandlerFunc(__NOW_HANDLER_FUNC_NAME))
}

View File

@@ -1,29 +1,27 @@
{
"name": "@now/go",
"version": "0.2.10",
"version": "0.3.1-canary.1",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/zeit/now-builders.git",
"directory": "packages/now-go"
},
"scripts": {
"test": "best -I test/*.js",
"prepublish": "./build.sh"
"postinstall": "node ./util/install"
},
"files": [
"bin",
"download-go-bin.js",
"index.js",
"main.go"
"*.js",
"main.go",
"main__mod__.go",
"util"
],
"dependencies": {
"debug": "^4.1.1",
"execa": "^1.0.0",
"fs-extra": "^7.0.0",
"lambda-git": "^0.1.2",
"mkdirp-promise": "5.0.1",
"node-fetch": "^2.2.1",
"tar": "4.4.6"
},
"devDependencies": {
"@zeit/best": "0.4.3",
"rmfr": "2.0.0"
},
"peerDependencies": {
"@now/build-utils": ">=0.0.1"
}
}

View File

@@ -34,7 +34,7 @@ func main() {
if fn.Name.IsExported() == true {
// we found the first exported function
// we're done!
fmt.Print(fn.Name.Name)
fmt.Print(fn.Name.Name, ",", parsed.Name.Name)
os.Exit(0)
}
}

View File

@@ -0,0 +1,18 @@
const { join } = require('path');
const { downloadGo } = require('../go-helpers');
async function main() {
// First download the `go` binary for this platform/arch.
const go = await downloadGo();
// Build the `get-exported-function-name` helper program.
// `go get` is not necessary because the program has no external deps.
const src = join(__dirname, 'get-exported-function-name.go');
const dest = join(__dirname, '../get-exported-function-name');
await go.build({ src, dest });
}
main().catch((err) => {
console.error(err);
process.exit(1);
});

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
const FileBlob = require('@now/build-utils/file-blob.js');
const FileBlob = require('@now/build-utils/file-blob.js'); // eslint-disable-line import/no-extraneous-dependencies
const { minify } = require('html-minifier');
const defaultOptions = {

View File

@@ -1,10 +1,13 @@
{
"name": "@now/html-minifier",
"version": "1.0.6",
"version": "1.0.8-canary.0",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/zeit/now-builders.git",
"directory": "packages/now-html-minifier"
},
"dependencies": {
"html-minifier": "3.5.21"
},
"peerDependencies": {
"@now/build-utils": ">=0.0.1"
}
}

View File

@@ -1,5 +1,5 @@
const { Lambda } = require('@now/build-utils/lambda.js');
const streamToBuffer = require('@now/build-utils/fs/stream-to-buffer.js');
const { Lambda } = require('@now/build-utils/lambda.js'); // eslint-disable-line import/no-extraneous-dependencies
const streamToBuffer = require('@now/build-utils/fs/stream-to-buffer.js'); // eslint-disable-line import/no-extraneous-dependencies
exports.build = async ({ files, entrypoint, config }) => {
if (!files[entrypoint]) throw new Error('Entrypoint not found in files');

View File

@@ -1,7 +1,13 @@
{
"name": "@now/lambda",
"version": "0.4.7",
"peerDependencies": {
"@now/build-utils": ">=0.0.1"
"version": "0.4.10-canary.1",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/zeit/now-builders.git",
"directory": "packages/now-lambda"
},
"scripts": {
"test": "jest"
}
}

Binary file not shown.

View File

@@ -0,0 +1,11 @@
{
"version": 2,
"builds": [
{ "src": "index.zip", "use": "@now/lambda", "config": { "handler": "index.handler", "runtime": "nodejs8.10" } },
{ "src": "subdirectory/index.zip", "use": "@now/lambda", "config": { "handler": "index.handler", "runtime": "nodejs8.10" } }
],
"probes": [
{ "path": "/", "mustContain": "cow:NO_REPLACE_TO_AVOID_CRC_MISMATCH" },
{ "path": "/subdirectory/", "mustContain": "yoda:NO_REPLACE_TO_AVOID_CRC_MISMATCH" }
]
}

Binary file not shown.

View File

@@ -0,0 +1,33 @@
/* global beforeAll, expect, it, jest */
const fs = require('fs');
const path = require('path');
const {
packAndDeploy,
testDeployment,
} = require('../../../test/lib/deployment/test-deployment.js');
jest.setTimeout(4 * 60 * 1000);
const buildUtilsUrl = '@canary';
let builderUrl;
beforeAll(async () => {
const builderPath = path.resolve(__dirname, '..');
builderUrl = await packAndDeploy(builderPath);
console.log('builderUrl', builderUrl);
});
const fixturesPath = path.resolve(__dirname, 'fixtures');
// eslint-disable-next-line no-restricted-syntax
for (const fixture of fs.readdirSync(fixturesPath)) {
// eslint-disable-next-line no-loop-func
it(`should build ${fixture}`, async () => {
await expect(
testDeployment(
{ builderUrl, buildUtilsUrl },
path.join(fixturesPath, fixture),
),
).resolves.toBeDefined();
});
}

View File

@@ -0,0 +1 @@
/test

View File

@@ -1,4 +1,4 @@
const FileBlob = require('@now/build-utils/file-blob.js');
const FileBlob = require('@now/build-utils/file-blob.js'); // eslint-disable-line import/no-extraneous-dependencies
const unified = require('unified');
const unifiedStream = require('unified-stream');
const markdown = require('remark-parse');

View File

@@ -1,6 +1,12 @@
{
"name": "@now/md",
"version": "0.4.7",
"version": "0.4.10-canary.1",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/zeit/now-builders.git",
"directory": "packages/now-md"
},
"dependencies": {
"rehype-document": "^2.2.0",
"rehype-format": "^2.3.0",
@@ -10,7 +16,7 @@
"unified": "^7.0.0",
"unified-stream": "^1.0.2"
},
"peerDependencies": {
"@now/build-utils": ">=0.0.1"
"scripts": {
"test": "jest"
}
}

View File

@@ -0,0 +1,5 @@
# Testing Markdown
cow:RANDOMNESS_PLACEHOLDER
[Wow a link!](https://zeit.co)

View File

@@ -0,0 +1,11 @@
{
"version": 2,
"builds": [
{ "src": "index.md", "use": "@now/md" },
{ "src": "subdirectory/index.md", "use": "@now/md" }
],
"probes": [
{ "path": "/", "mustContain": "cow:RANDOMNESS_PLACEHOLDER" },
{ "path": "/subdirectory/", "mustContain": "yoda:RANDOMNESS_PLACEHOLDER" }
]
}

View File

@@ -0,0 +1,5 @@
# Testing Markdown
yoda:RANDOMNESS_PLACEHOLDER
[Wow a link!](https://zeit.co)

View File

@@ -0,0 +1,33 @@
/* global beforeAll, expect, it, jest */
const fs = require('fs');
const path = require('path');
const {
packAndDeploy,
testDeployment,
} = require('../../../test/lib/deployment/test-deployment.js');
jest.setTimeout(4 * 60 * 1000);
const buildUtilsUrl = '@canary';
let builderUrl;
beforeAll(async () => {
const builderPath = path.resolve(__dirname, '..');
builderUrl = await packAndDeploy(builderPath);
console.log('builderUrl', builderUrl);
});
const fixturesPath = path.resolve(__dirname, 'fixtures');
// eslint-disable-next-line no-restricted-syntax
for (const fixture of fs.readdirSync(fixturesPath)) {
// eslint-disable-next-line no-loop-func
it(`should build ${fixture}`, async () => {
await expect(
testDeployment(
{ builderUrl, buildUtilsUrl },
path.join(fixturesPath, fixture),
),
).resolves.toBeDefined();
});
}

View File

@@ -0,0 +1 @@
/test

View File

@@ -1,12 +1,10 @@
const download = require('@now/build-utils/fs/download.js');
const download = require('@now/build-utils/fs/download.js'); // eslint-disable-line import/no-extraneous-dependencies
const fs = require('fs');
const { promisify } = require('util');
const getWritableDirectory = require('@now/build-utils/fs/get-writable-directory.js');
const glob = require('@now/build-utils/fs/glob.js');
const getWritableDirectory = require('@now/build-utils/fs/get-writable-directory.js'); // eslint-disable-line import/no-extraneous-dependencies
const glob = require('@now/build-utils/fs/glob.js'); // eslint-disable-line import/no-extraneous-dependencies
const path = require('path');
const { runNpmInstall } = require('@now/build-utils/fs/run-user-scripts.js');
exports.analyze = ({ files, entrypoint }) => files[entrypoint].digest;
const { runNpmInstall } = require('@now/build-utils/fs/run-user-scripts.js'); // eslint-disable-line import/no-extraneous-dependencies
const writeFile = promisify(fs.writeFile);
@@ -14,10 +12,10 @@ exports.build = async ({ files, entrypoint, workPath }) => {
console.log('downloading user files...');
const downloadedFiles = await download(files, workPath);
console.log('writing package.json...');
const packageJson = { dependencies: { 'mdx-deck': '1.7.7' } };
const packageJson = { dependencies: { 'mdx-deck': '1.7.15' } };
const packageJsonPath = path.join(workPath, 'package.json');
await writeFile(packageJsonPath, JSON.stringify(packageJson));
console.log('running npm install...');
console.log('installing dependencies...');
process.env.PUPPETEER_SKIP_CHROMIUM_DOWNLOAD = '1'; // TODO opts argument for runNpmInstall
await runNpmInstall(path.dirname(packageJsonPath), [
'--prod',
@@ -47,7 +45,7 @@ exports.build = async ({ files, entrypoint, workPath }) => {
exports.prepareCache = async ({ cachePath }) => {
console.log('writing package.json...');
const packageJson = { dependencies: { 'mdx-deck': '1.7.7' } };
const packageJson = { dependencies: { 'mdx-deck': '1.7.15' } };
const packageJsonPath = path.join(cachePath, 'package.json');
await writeFile(packageJsonPath, JSON.stringify(packageJson));
console.log('running npm install...');

View File

@@ -1,7 +1,13 @@
{
"name": "@now/mdx-deck",
"version": "0.4.16",
"peerDependencies": {
"@now/build-utils": ">=0.0.1"
"version": "0.4.19-canary.1",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/zeit/now-builders.git",
"directory": "packages/now-mdx-deck"
},
"scripts": {
"test": "jest"
}
}

View File

@@ -0,0 +1,5 @@
# Testing Markdown
---
cow:RANDOMNESS_PLACEHOLDER
---
[Wow a link!](https://zeit.co)

View File

@@ -0,0 +1,11 @@
{
"version": 2,
"builds": [
{ "src": "index.mdx", "use": "@now/mdx-deck" },
{ "src": "subdirectory/index.mdx", "use": "@now/mdx-deck" }
],
"probes": [
{ "path": "/", "mustContain": "cow:RANDOMNESS_PLACEHOLDER" },
{ "path": "/subdirectory/", "mustContain": "yoda:RANDOMNESS_PLACEHOLDER" }
]
}

View File

@@ -0,0 +1,5 @@
# Testing Markdown
---
yoda:RANDOMNESS_PLACEHOLDER
---
[Wow a link!](https://zeit.co)

View File

@@ -0,0 +1,33 @@
/* global beforeAll, expect, it, jest */
const fs = require('fs');
const path = require('path');
const {
packAndDeploy,
testDeployment,
} = require('../../../test/lib/deployment/test-deployment.js');
jest.setTimeout(4 * 60 * 1000);
const buildUtilsUrl = '@canary';
let builderUrl;
beforeAll(async () => {
const builderPath = path.resolve(__dirname, '..');
builderUrl = await packAndDeploy(builderPath);
console.log('builderUrl', builderUrl);
});
const fixturesPath = path.resolve(__dirname, 'fixtures');
// eslint-disable-next-line no-restricted-syntax
for (const fixture of fs.readdirSync(fixturesPath)) {
// eslint-disable-next-line no-loop-func
it(`should build ${fixture}`, async () => {
await expect(
testDeployment(
{ builderUrl, buildUtilsUrl },
path.join(fixturesPath, fixture),
),
).resolves.toBeDefined();
});
}

View File

@@ -1,22 +1,31 @@
const { createLambda } = require('@now/build-utils/lambda.js');
const download = require('@now/build-utils/fs/download.js');
const FileFsRef = require('@now/build-utils/file-fs-ref.js');
const FileBlob = require('@now/build-utils/file-blob');
const { createLambda } = require('@now/build-utils/lambda.js'); // eslint-disable-line import/no-extraneous-dependencies
const download = require('@now/build-utils/fs/download.js'); // eslint-disable-line import/no-extraneous-dependencies
const FileFsRef = require('@now/build-utils/file-fs-ref.js'); // eslint-disable-line import/no-extraneous-dependencies
const FileBlob = require('@now/build-utils/file-blob'); // eslint-disable-line import/no-extraneous-dependencies
const path = require('path');
const { readFile, writeFile, unlink } = require('fs.promised');
const {
runNpmInstall,
runPackageJsonScript,
} = require('@now/build-utils/fs/run-user-scripts.js');
const glob = require('@now/build-utils/fs/glob.js');
} = require('@now/build-utils/fs/run-user-scripts.js'); // eslint-disable-line import/no-extraneous-dependencies
const glob = require('@now/build-utils/fs/glob.js'); // eslint-disable-line import/no-extraneous-dependencies
const {
readFile,
writeFile,
unlink: unlinkFile,
remove: removePath,
mkdirp,
rename: renamePath,
pathExists,
} = require('fs-extra');
const semver = require('semver');
const nextLegacyVersions = require('./legacy-versions');
const {
excludeFiles,
validateEntrypoint,
includeOnlyEntryDirectory,
moveEntryDirectoryToRoot,
excludeLockFiles,
normalizePackageJson,
excludeStaticDirectory,
onlyStaticDirectory,
getNextConfig,
} = require('./utils');
/** @typedef { import('@now/build-utils/file-ref').Files } Files */
@@ -31,15 +40,17 @@ const {
/**
* Read package.json from files
* @param {DownloadedFiles} files
* @param {string} entryPath
*/
async function readPackageJson(files) {
if (!files['package.json']) {
async function readPackageJson(entryPath) {
const packagePath = path.join(entryPath, 'package.json');
try {
return JSON.parse(await readFile(packagePath, 'utf8'));
} catch (err) {
console.log('package.json not found in entry');
return {};
}
const packageJsonPath = files['package.json'].fsPath;
return JSON.parse(await readFile(packageJsonPath, 'utf8'));
}
/**
@@ -66,6 +77,36 @@ async function writeNpmRc(workPath, token) {
);
}
function getNextVersion(packageJson) {
let nextVersion;
if (packageJson.dependencies && packageJson.dependencies.next) {
nextVersion = packageJson.dependencies.next;
} else if (packageJson.devDependencies && packageJson.devDependencies.next) {
nextVersion = packageJson.devDependencies.next;
}
return nextVersion;
}
function isLegacyNext(nextVersion) {
// If version is using the dist-tag instead of a version range
if (nextVersion === 'canary' || nextVersion === 'latest') {
return false;
}
// If the version is an exact match with the legacy versions
if (nextLegacyVersions.indexOf(nextVersion) !== -1) {
return true;
}
const maxSatisfying = semver.maxSatisfying(nextLegacyVersions, nextVersion);
// When the version can't be matched with legacy versions, so it must be a newer version
if (maxSatisfying === null) {
return false;
}
return true;
}
exports.config = {
maxLambdaSize: '5mb',
};
@@ -79,127 +120,232 @@ exports.build = async ({ files, workPath, entrypoint }) => {
console.log('downloading user files...');
const entryDirectory = path.dirname(entrypoint);
const filesOnlyEntryDirectory = includeOnlyEntryDirectory(
files,
entryDirectory,
);
const filesWithEntryDirectoryRoot = moveEntryDirectoryToRoot(
filesOnlyEntryDirectory,
entryDirectory,
);
const filesWithoutLockfiles = excludeLockFiles(filesWithEntryDirectoryRoot);
const filesWithoutStaticDirectory = excludeStaticDirectory(
filesWithoutLockfiles,
);
let downloadedFiles = await download(filesWithoutStaticDirectory, workPath);
await download(files, workPath);
const entryPath = path.join(workPath, entryDirectory);
console.log('normalizing package.json');
const packageJson = normalizePackageJson(
await readPackageJson(downloadedFiles),
);
console.log('normalized package.json result: ', packageJson);
await writePackageJson(workPath, packageJson);
if (await pathExists(path.join(entryPath, '.next'))) {
console.warn(
'WARNING: You should probably not upload the `.next` directory. See https://zeit.co/docs/v2/deployments/official-builders/next-js-now-next/ for more information.',
);
}
const pkg = await readPackageJson(entryPath);
const nextVersion = getNextVersion(pkg);
if (!nextVersion) {
throw new Error(
'No Next.js version could be detected in "package.json". Make sure `"next"` is installed in "dependencies" or "devDependencies"',
);
}
const isLegacy = isLegacyNext(nextVersion);
console.log(`MODE: ${isLegacy ? 'legacy' : 'serverless'}`);
if (isLegacy) {
try {
await unlinkFile(path.join(entryPath, 'yarn.lock'));
} catch (err) {
console.log('no yarn.lock removed');
}
try {
await unlinkFile(path.join(entryPath, 'package-lock.json'));
} catch (err) {
console.log('no package-lock.json removed');
}
console.warn(
"WARNING: your application is being deployed in @now/next's legacy mode. http://err.sh/zeit/now-builders/now-next-legacy-mode",
);
console.log('normalizing package.json');
const packageJson = normalizePackageJson(pkg);
console.log('normalized package.json result: ', packageJson);
await writePackageJson(entryPath, packageJson);
} else if (!pkg.scripts || !pkg.scripts['now-build']) {
console.warn(
'WARNING: "now-build" script not found. Adding \'"now-build": "next build"\' to "package.json" automatically',
);
pkg.scripts = {
'now-build': 'next build',
...(pkg.scripts || {}),
};
console.log('normalized package.json result: ', pkg);
await writePackageJson(entryPath, pkg);
}
if (process.env.NPM_AUTH_TOKEN) {
console.log('found NPM_AUTH_TOKEN in environment, creating .npmrc');
await writeNpmRc(workPath, process.env.NPM_AUTH_TOKEN);
await writeNpmRc(entryPath, process.env.NPM_AUTH_TOKEN);
}
downloadedFiles = await glob('**', workPath);
console.log('running npm install...');
await runNpmInstall(workPath, ['--prefer-offline']);
console.log('installing dependencies...');
await runNpmInstall(entryPath, ['--prefer-offline']);
console.log('running user script...');
await runPackageJsonScript(workPath, 'now-build');
console.log('running npm install --production...');
await runNpmInstall(workPath, ['--prefer-offline', '--production']);
await runPackageJsonScript(entryPath, 'now-build');
if (isLegacy) {
console.log('running npm install --production...');
await runNpmInstall(entryPath, ['--prefer-offline', '--production']);
}
if (process.env.NPM_AUTH_TOKEN) {
await unlink(path.join(workPath, '.npmrc'));
await unlinkFile(path.join(entryPath, '.npmrc'));
}
downloadedFiles = await glob('**', workPath);
console.log('preparing lambda files...');
let buildId;
try {
buildId = await readFile(path.join(workPath, '.next', 'BUILD_ID'), 'utf8');
} catch (err) {
console.error(
'BUILD_ID not found in ".next". The "package.json" "build" script did not run "next build"',
);
throw new Error('Missing BUILD_ID');
}
const dotNextRootFiles = await glob('.next/*', workPath);
const dotNextServerRootFiles = await glob('.next/server/*', workPath);
const nodeModules = excludeFiles(
await glob('node_modules/**', workPath),
file => file.startsWith('node_modules/.cache'),
);
const launcherFiles = {
'now__bridge.js': new FileFsRef({ fsPath: require('@now/node-bridge') }),
};
const nextFiles = {
...nodeModules,
...dotNextRootFiles,
...dotNextServerRootFiles,
...launcherFiles,
};
if (downloadedFiles['next.config.js']) {
nextFiles['next.config.js'] = downloadedFiles['next.config.js'];
}
const pages = await glob(
'**/*.js',
path.join(workPath, '.next', 'server', 'static', buildId, 'pages'),
);
const launcherPath = path.join(__dirname, 'launcher.js');
const launcherData = await readFile(launcherPath, 'utf8');
const lambdas = {};
await Promise.all(
Object.keys(pages).map(async (page) => {
// These default pages don't have to be handled as they'd always 404
if (['_app.js', '_error.js', '_document.js'].includes(page)) {
return;
if (isLegacy) {
const filesAfterBuild = await glob('**', entryPath);
console.log('preparing lambda files...');
let buildId;
try {
buildId = await readFile(
path.join(entryPath, '.next', 'BUILD_ID'),
'utf8',
);
} catch (err) {
console.error(
'BUILD_ID not found in ".next". The "package.json" "build" script did not run "next build"',
);
throw new Error('Missing BUILD_ID');
}
const dotNextRootFiles = await glob('.next/*', entryPath);
const dotNextServerRootFiles = await glob('.next/server/*', entryPath);
const nodeModules = excludeFiles(
await glob('node_modules/**', entryPath),
file => file.startsWith('node_modules/.cache'),
);
const launcherFiles = {
'now__bridge.js': new FileFsRef({ fsPath: require('@now/node-bridge') }),
};
const nextFiles = {
...nodeModules,
...dotNextRootFiles,
...dotNextServerRootFiles,
...launcherFiles,
};
if (filesAfterBuild['next.config.js']) {
nextFiles['next.config.js'] = filesAfterBuild['next.config.js'];
}
const pages = await glob(
'**/*.js',
path.join(entryPath, '.next', 'server', 'static', buildId, 'pages'),
);
const launcherPath = path.join(__dirname, 'legacy-launcher.js');
const launcherData = await readFile(launcherPath, 'utf8');
await Promise.all(
Object.keys(pages).map(async (page) => {
// These default pages don't have to be handled as they'd always 404
if (['_app.js', '_error.js', '_document.js'].includes(page)) {
return;
}
const pathname = page.replace(/\.js$/, '');
const launcher = launcherData.replace(
'PATHNAME_PLACEHOLDER',
`/${pathname.replace(/(^|\/)index$/, '')}`,
);
const pageFiles = {
[`.next/server/static/${buildId}/pages/_document.js`]: filesAfterBuild[
`.next/server/static/${buildId}/pages/_document.js`
],
[`.next/server/static/${buildId}/pages/_app.js`]: filesAfterBuild[
`.next/server/static/${buildId}/pages/_app.js`
],
[`.next/server/static/${buildId}/pages/_error.js`]: filesAfterBuild[
`.next/server/static/${buildId}/pages/_error.js`
],
[`.next/server/static/${buildId}/pages/${page}`]: filesAfterBuild[
`.next/server/static/${buildId}/pages/${page}`
],
};
console.log(`Creating lambda for page: "${page}"...`);
lambdas[path.join(entryDirectory, pathname)] = await createLambda({
files: {
...nextFiles,
...pageFiles,
'now__launcher.js': new FileBlob({ data: launcher }),
},
handler: 'now__launcher.launcher',
runtime: 'nodejs8.10',
});
console.log(`Created lambda for page: "${page}"`);
}),
);
} else {
console.log('preparing lambda files...');
const launcherFiles = {
'now__bridge.js': new FileFsRef({ fsPath: require('@now/node-bridge') }),
'now__launcher.js': new FileFsRef({
fsPath: path.join(__dirname, 'launcher.js'),
}),
};
const pages = await glob(
'**/*.js',
path.join(entryPath, '.next', 'serverless', 'pages'),
);
const pageKeys = Object.keys(pages);
if (pageKeys.length === 0) {
const nextConfig = await getNextConfig(workPath, entryPath);
if (nextConfig != null) {
console.info('Found next.config.js:');
console.info(nextConfig);
console.info();
}
const pathname = page.replace(/\.js$/, '');
const launcher = launcherData.replace(
'PATHNAME_PLACEHOLDER',
`/${pathname.replace(/(^|\/)index$/, '')}`,
throw new Error(
'No serverless pages were built. https://err.sh/zeit/now-builders/now-next-no-serverless-pages-built',
);
}
const pageFiles = {
[`.next/server/static/${buildId}/pages/_document.js`]: downloadedFiles[
`.next/server/static/${buildId}/pages/_document.js`
],
[`.next/server/static/${buildId}/pages/_app.js`]: downloadedFiles[
`.next/server/static/${buildId}/pages/_app.js`
],
[`.next/server/static/${buildId}/pages/_error.js`]: downloadedFiles[
`.next/server/static/${buildId}/pages/_error.js`
],
[`.next/server/static/${buildId}/pages/${page}`]: downloadedFiles[
`.next/server/static/${buildId}/pages/${page}`
],
};
// An optional assets folder that is placed alongside every page entrypoint
const assets = await glob(
'assets/**',
path.join(entryPath, '.next', 'serverless'),
);
console.log(`Creating lambda for page: "${page}"...`);
lambdas[path.join(entryDirectory, pathname)] = await createLambda({
files: {
...nextFiles,
...pageFiles,
'now__launcher.js': new FileBlob({ data: launcher }),
},
handler: 'now__launcher.launcher',
runtime: 'nodejs8.10',
});
console.log(`Created lambda for page: "${page}"`);
}),
);
const assetKeys = Object.keys(assets);
if (assetKeys.length > 0) {
console.log('detected assets to be bundled with lambda:');
assetKeys.forEach(assetFile => console.log(`\t${assetFile}`));
}
await Promise.all(
pageKeys.map(async (page) => {
// These default pages don't have to be handled as they'd always 404
if (['_app.js', '_error.js', '_document.js'].includes(page)) {
return;
}
const pathname = page.replace(/\.js$/, '');
console.log(`Creating lambda for page: "${page}"...`);
lambdas[path.join(entryDirectory, pathname)] = await createLambda({
files: {
...launcherFiles,
...assets,
'page.js': pages[page],
},
handler: 'now__launcher.launcher',
runtime: 'nodejs8.10',
});
console.log(`Created lambda for page: "${page}"`);
}),
);
}
const nextStaticFiles = await glob(
'**',
path.join(workPath, '.next', 'static'),
path.join(entryPath, '.next', 'static'),
);
const staticFiles = Object.keys(nextStaticFiles).reduce(
(mappedFiles, file) => ({
@@ -209,28 +355,46 @@ exports.build = async ({ files, workPath, entrypoint }) => {
{},
);
return { ...lambdas, ...staticFiles };
};
exports.prepareCache = async ({ files, cachePath, workPath }) => {
console.log('downloading user files...');
await download(files, cachePath);
await download(await glob('.next/**', workPath), cachePath);
await download(await glob('node_modules/**', workPath), cachePath);
console.log('.next folder contents', await glob('.next/**', cachePath));
console.log(
'.cache folder contents',
await glob('node_modules/.cache/**', cachePath),
const staticDirectoryFiles = onlyStaticDirectory(
includeOnlyEntryDirectory(files, entryDirectory),
entryDirectory,
);
console.log('running npm install...');
await runNpmInstall(cachePath);
return { ...lambdas, ...staticFiles, ...staticDirectoryFiles };
};
exports.prepareCache = async ({ cachePath, workPath, entrypoint }) => {
console.log('preparing cache ...');
const entryDirectory = path.dirname(entrypoint);
const entryPath = path.join(workPath, entryDirectory);
const cacheEntryPath = path.join(cachePath, entryDirectory);
const pkg = await readPackageJson(entryPath);
const nextVersion = getNextVersion(pkg);
const isLegacy = isLegacyNext(nextVersion);
if (isLegacy) {
// skip caching legacy mode (swapping deps between all and production can get bug-prone)
return {};
}
console.log('clearing old cache ...');
await removePath(cacheEntryPath);
await mkdirp(cacheEntryPath);
console.log('copying build files for cache ...');
await renamePath(entryPath, cacheEntryPath);
console.log('producing cache file manifest ...');
const cacheEntrypoint = path.relative(cachePath, cacheEntryPath);
return {
...(await glob('.next/records.json', cachePath)),
...(await glob('.next/server/records.json', cachePath)),
...(await glob('node_modules/**', cachePath)),
...(await glob('yarn.lock', cachePath)),
...(await glob(
path.join(cacheEntrypoint, 'node_modules/{**,!.*,.yarn*}'),
cachePath,
)),
...(await glob(path.join(cacheEntrypoint, 'package-lock.json'), cachePath)),
...(await glob(path.join(cacheEntrypoint, 'yarn.lock'), cachePath)),
};
};

View File

@@ -1,19 +1,11 @@
const { Server } = require('http');
const next = require('next-server');
const url = require('url');
const { Bridge } = require('./now__bridge.js');
const bridge = new Bridge();
bridge.port = 3000;
process.env.NODE_ENV = 'production';
const app = next({});
const { Server } = require('http');
const { Bridge } = require('./now__bridge.js');
const page = require('./page.js');
const server = new Server((req, res) => {
const parsedUrl = url.parse(req.url, true);
app.render(req, res, 'PATHNAME_PLACEHOLDER', parsedUrl.query, parsedUrl);
});
server.listen(bridge.port);
const server = new Server(page.render);
const bridge = new Bridge(server);
bridge.listen();
exports.launcher = bridge.launcher;

View File

@@ -0,0 +1,18 @@
const { Server } = require('http');
const next = require('next-server');
const url = require('url');
const { Bridge } = require('./now__bridge.js');
process.env.NODE_ENV = 'production';
const app = next({});
const server = new Server((req, res) => {
const parsedUrl = url.parse(req.url, true);
app.render(req, res, 'PATHNAME_PLACEHOLDER', parsedUrl.query, parsedUrl);
});
const bridge = new Bridge(server);
bridge.listen();
exports.launcher = bridge.launcher;

View File

@@ -0,0 +1,336 @@
module.exports = [
'0.1.0',
'0.1.1',
'0.2.0',
'0.2.1',
'0.2.2',
'0.2.3',
'0.2.4',
'0.2.5',
'0.2.6',
'0.2.7',
'0.2.8',
'0.2.9',
'0.2.10',
'0.2.11',
'0.2.12',
'0.2.13',
'0.2.14',
'0.3.0',
'0.3.1',
'0.3.2',
'0.3.3',
'0.4.0',
'0.4.1',
'0.9.9',
'0.9.10',
'0.9.11',
'1.0.0',
'1.0.1',
'1.0.2',
'1.1.0',
'1.1.1',
'1.1.2',
'1.2.0',
'1.2.1',
'1.2.2',
'1.2.3',
'2.0.0-beta.0',
'2.0.0-beta.1',
'2.0.0-beta.2',
'2.0.0-beta.3',
'2.0.0-beta.4',
'2.0.0-beta.5',
'2.0.0-beta.6',
'2.0.0-beta.7',
'2.0.0-beta.8',
'2.0.0-beta.9',
'2.0.0-beta.10',
'2.0.0-beta.11',
'2.0.0-beta.12',
'2.0.0-beta.13',
'2.0.0-beta.14',
'2.0.0-beta.15',
'2.0.0-beta.16',
'2.0.0-beta.17',
'2.0.0-beta.18',
'2.0.0-beta.19',
'2.0.0-beta.20',
'2.0.0-beta.21',
'2.0.0-beta.22',
'2.0.0-beta.23',
'2.0.0-beta.24',
'2.0.0-beta.25',
'2.0.0-beta.26',
'2.0.0-beta.27',
'2.0.0-beta.28',
'2.0.0-beta.29',
'2.0.0-beta.30',
'2.0.0-beta.31',
'2.0.0-beta.32',
'2.0.0-beta.33',
'2.0.0-beta.34',
'2.0.0-beta.35',
'2.0.0-beta.36',
'2.0.0-beta.37',
'2.0.0-beta.38',
'2.0.0-beta.39',
'2.0.0-beta.40',
'2.0.0-beta.41',
'2.0.0-beta.42',
'2.0.0',
'2.0.1',
'2.1.0',
'2.1.1',
'2.2.0',
'2.3.0-alpha1',
'2.3.0',
'2.3.1',
'2.4.0',
'2.4.1',
'2.4.2',
'2.4.3',
'2.4.4',
'2.4.5',
'2.4.6',
'2.4.7',
'2.4.8',
'2.4.9',
'3.0.0-beta1',
'3.0.0-beta10',
'3.0.0-beta11',
'3.0.0-beta12',
'3.0.0-beta13',
'3.0.0-beta14',
'3.0.0-beta15',
'3.0.0-beta16',
'3.0.0-beta2',
'3.0.0-beta3',
'3.0.0-beta4',
'3.0.0-beta5',
'3.0.0-beta6',
'3.0.0-beta7',
'3.0.0-beta8',
'3.0.0-beta9',
'3.0.1-beta.1',
'3.0.1-beta.2',
'3.0.1-beta.3',
'3.0.1-beta.4',
'3.0.1-beta.5',
'3.0.1-beta.6',
'3.0.1-beta.7',
'3.0.1-beta.8',
'3.0.1-beta.9',
'3.0.1-beta.10',
'3.0.1-beta.11',
'3.0.1-beta.12',
'3.0.1-beta.13',
'3.0.1-beta.14',
'3.0.1-beta.15',
'3.0.1-beta.16',
'3.0.1-beta.17',
'3.0.1-beta.18',
'3.0.1-beta.19',
'3.0.1-beta.20',
'3.0.1-beta.21',
'3.0.1',
'3.0.2',
'3.0.3',
'3.0.4',
'3.0.5',
'3.0.6',
'3.1.0',
'3.2.0',
'3.2.1',
'3.2.2',
'3.2.3',
'4.0.0-beta.1',
'4.0.0-beta.2',
'4.0.0-beta.3',
'4.0.0-beta.4',
'4.0.0-beta.5',
'4.0.0-beta.6',
'4.0.0',
'4.0.1',
'4.0.2',
'4.0.3',
'4.0.4',
'4.0.5',
'4.1.0',
'4.1.1',
'4.1.2',
'4.1.3',
'4.1.4-canary.1',
'4.1.4-canary.2',
'4.1.4',
'4.2.0-canary.1',
'4.2.0-zones.2',
'4.2.0',
'4.2.1',
'4.2.2',
'4.2.3',
'4.3.0-canary.1',
'4.3.0-universal-alpha.1',
'4.3.0-universal-alpha.2',
'4.3.0-universal-alpha.3',
'4.3.0-universal-alpha.4',
'4.3.0-zones.1',
'4.4.0-canary.2',
'4.4.0-canary.3',
'5.0.0-universal-alpha.1',
'5.0.0-universal-alpha.2',
'5.0.0-universal-alpha.3',
'5.0.0-universal-alpha.4',
'5.0.0-universal-alpha.5',
'5.0.0-universal-alpha.6',
'5.0.0-universal-alpha.7',
'5.0.0-universal-alpha.8',
'5.0.0-universal-alpha.9',
'5.0.0-universal-alpha.10',
'5.0.0-universal-alpha.11',
'5.0.0-universal-alpha.12',
'5.0.0-universal-alpha.13',
'5.0.0-universal-alpha.14',
'5.0.0-universal-alpha.15',
'5.0.0-universal-alpha.16',
'5.0.0-universal-alpha.17',
'5.0.0-universal-alpha.18',
'5.0.0-universal-alpha.19',
'5.0.0-universal-alpha.20',
'5.0.0-universal-alpha.21',
'5.0.0-universal-alpha.22',
'5.0.0-universal-alpha.23',
'5.0.0-zones.1',
'5.0.0',
'5.0.1-canary.1',
'5.0.1-canary.2',
'5.0.1-canary.3',
'5.0.1-canary.4',
'5.0.1-canary.5',
'5.0.1-canary.6',
'5.0.1-canary.7',
'5.0.1-canary.8',
'5.0.1-canary.9',
'5.0.1-canary.10',
'5.0.1-canary.11',
'5.0.1-canary.12',
'5.0.1-canary.13',
'5.0.1-canary.14',
'5.0.1-canary.15',
'5.0.1-canary.16',
'5.0.1-canary.17',
'5.1.0',
'6.0.0-canary.1',
'6.0.0-canary.2',
'6.0.0-canary.3',
'6.0.0-canary.4',
'6.0.0-canary.5',
'6.0.0-canary.6',
'6.0.0-canary.7',
'6.0.0',
'6.0.1-canary.0',
'6.0.1-canary.1',
'6.0.1-canary.2',
'6.0.1',
'6.0.2-canary.0',
'6.0.2',
'6.0.3-canary.0',
'6.0.3-canary.1',
'6.0.3',
'6.0.4-canary.0',
'6.0.4-canary.1',
'6.0.4-canary.2',
'6.0.4-canary.3',
'6.0.4-canary.4',
'6.0.4-canary.5',
'6.0.4-canary.6',
'6.0.4-canary.7',
'6.0.4-canary.8',
'6.0.4-canary.9',
'6.1.0-canary.0',
'6.1.0',
'6.1.1-canary.0',
'6.1.1-canary.1',
'6.1.1-canary.2',
'6.1.1-canary.3',
'6.1.1-canary.4',
'6.1.1-canary.5',
'6.1.1',
'6.1.2',
'7.0.0-canary.0',
'7.0.0-canary.1',
'7.0.0-canary.2',
'7.0.0-canary.3',
'7.0.0-canary.4',
'7.0.0-canary.5',
'7.0.0-canary.6',
'7.0.0-canary.7',
'7.0.0-canary.8',
'7.0.0-canary.9',
'7.0.0-canary.10',
'7.0.0-canary.11',
'7.0.0-canary.12',
'7.0.0-canary.13',
'7.0.0-canary.14',
'7.0.0-canary.15',
'7.0.0-canary.16',
'7.0.0-canary.18',
'7.0.0-canary.19',
'7.0.0-canary.20',
'7.0.0',
'7.0.1-canary.0',
'7.0.1-canary.1',
'7.0.1-canary.2',
'7.0.1-canary.3',
'7.0.1-canary.4',
'7.0.1-canary.5',
'7.0.1-canary.6',
'7.0.1',
'7.0.2-alpha.1',
'7.0.2-alpha.3',
'7.0.2-canary.5',
'7.0.2-canary.6',
'7.0.2-canary.7',
'7.0.2-canary.8',
'7.0.2-canary.9',
'7.0.2-canary.10',
'7.0.2-canary.11',
'7.0.2-canary.12',
'7.0.2-canary.13',
'7.0.2-canary.14',
'7.0.2-canary.15',
'7.0.2-canary.16',
'7.0.2-canary.17',
'7.0.2-canary.18',
'7.0.2-canary.19',
'7.0.2-canary.20',
'7.0.2-canary.21',
'7.0.2-canary.22',
'7.0.2-canary.23',
'7.0.2-canary.24',
'7.0.2-canary.25',
'7.0.2-canary.26',
'7.0.2-canary.27',
'7.0.2-canary.28',
'7.0.2-canary.29',
'7.0.2-canary.31',
'7.0.2-canary.33',
'7.0.2-canary.34',
'7.0.2-canary.35',
'7.0.2-canary.36',
'7.0.2-canary.37',
'7.0.2-canary.38',
'7.0.2-canary.39',
'7.0.2-canary.40',
'7.0.2-canary.41',
'7.0.2-canary.42',
'7.0.2-canary.43',
'7.0.2-canary.44',
'7.0.2-canary.45',
'7.0.2-canary.46',
'7.0.2-canary.47',
'7.0.2-canary.48',
'7.0.2-canary.49',
'7.0.2-canary.50',
'7.0.2',
];

View File

@@ -1,12 +1,16 @@
{
"name": "@now/next",
"version": "0.0.80",
"dependencies": {
"@now/node-bridge": "0.1.4",
"execa": "^1.0.0",
"fs.promised": "^3.0.0"
"version": "0.1.3-canary.0",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/zeit/now-builders.git",
"directory": "packages/now-next"
},
"peerDependencies": {
"@now/build-utils": ">=0.0.1"
"dependencies": {
"@now/node-bridge": "^1.0.0",
"execa": "^1.0.0",
"fs-extra": "^7.0.0",
"semver": "^5.6.0"
}
}

View File

@@ -1,4 +1,5 @@
const rename = require('@now/build-utils/fs/rename.js');
const fs = require('fs-extra');
const path = require('path');
/** @typedef { import('@now/build-utils/file-ref') } FileRef */
/** @typedef { import('@now/build-utils/file-fs-ref') } FileFsRef */
@@ -64,24 +65,6 @@ function includeOnlyEntryDirectory(files, entryDirectory) {
return excludeFiles(files, matcher);
}
/**
* Moves all files under the entry directory to the root directory
* @param {Files} files
* @param {string} entryDirectory
* @returns {Files}
*/
function moveEntryDirectoryToRoot(files, entryDirectory) {
if (entryDirectory === '.') {
return files;
}
function delegate(filePath) {
return filePath.replace(new RegExp(`^${entryDirectory}/`), '');
}
return rename(files, delegate);
}
/**
* Exclude package manager lockfiles from files
* @param {Files} files
@@ -99,13 +82,13 @@ function excludeLockFiles(files) {
}
/**
* Exclude the static directory from files
* Include the static directory from files
* @param {Files} files
* @returns {Files}
*/
function excludeStaticDirectory(files) {
function onlyStaticDirectory(files, entryDir) {
function matcher(filePath) {
return filePath.startsWith('static');
return !filePath.startsWith(path.join(entryDir, 'static'));
}
return excludeFiles(files, matcher);
@@ -140,28 +123,42 @@ function normalizePackageJson(defaultPackageJson = {}) {
'react-dom': 'latest',
...dependencies, // override react if user provided it
// next-server is forced to canary
'next-server': 'canary',
'next-server': 'v7.0.2-canary.49',
},
devDependencies: {
...devDependencies,
// next is forced to canary
next: 'canary',
next: 'v7.0.2-canary.49',
// next-server is a dependency here
'next-server': undefined,
},
scripts: {
...defaultPackageJson.scripts,
'now-build': 'next build --lambdas',
'now-build': 'NODE_OPTIONS=--max_old_space_size=3000 next build --lambdas',
},
};
}
async function getNextConfig(workPath, entryPath) {
const entryConfig = path.join(entryPath, './next.config.js');
if (await fs.pathExists(entryConfig)) {
return fs.readFile(entryConfig, 'utf8');
}
const workConfig = path.join(workPath, './next.config.js');
if (await fs.pathExists(workConfig)) {
return fs.readFile(workConfig, 'utf8');
}
return null;
}
module.exports = {
excludeFiles,
validateEntrypoint,
includeOnlyEntryDirectory,
moveEntryDirectoryToRoot,
excludeLockFiles,
normalizePackageJson,
excludeStaticDirectory,
onlyStaticDirectory,
getNextConfig,
};

View File

@@ -0,0 +1,24 @@
{
"extends": ["prettier", "airbnb-base"],
"rules": {
"no-console": 0,
"import/no-unresolved": 0,
"import/no-dynamic-require": 0,
"global-require": 0
},
"overrides": [
{
"files": ["test/**"],
"rules": {
"import/no-extraneous-dependencies": 0
},
"globals": {
"describe": true,
"it": true,
"test": true,
"expect": true
}
}
]
}

1
packages/now-node-bridge/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/bridge.*

View File

@@ -1,98 +0,0 @@
const http = require('http');
function normalizeEvent(event) {
if (event.Action === 'Invoke') {
const invokeEvent = JSON.parse(event.body);
const {
method, path, headers, encoding,
} = invokeEvent;
let { body } = invokeEvent;
if (body) {
if (encoding === 'base64') {
body = Buffer.from(body, encoding);
} else if (encoding === undefined) {
body = Buffer.from(body);
} else {
throw new Error(`Unsupported encoding: ${encoding}`);
}
}
return {
method,
path,
headers,
body,
};
}
const {
httpMethod: method, path, headers, body,
} = event;
return {
method,
path,
headers,
body,
};
}
class Bridge {
constructor() {
this.launcher = this.launcher.bind(this);
}
launcher(event) {
// eslint-disable-next-line consistent-return
return new Promise((resolve, reject) => {
if (this.userError) {
console.error('Error while initializing entrypoint:', this.userError);
return resolve({ statusCode: 500, body: '' });
}
if (!this.port) {
return resolve({ statusCode: 504, body: '' });
}
const {
method, path, headers, body,
} = normalizeEvent(event);
const opts = {
hostname: '127.0.0.1',
port: this.port,
path,
method,
headers,
};
const req = http.request(opts, (res) => {
const response = res;
const respBodyChunks = [];
response.on('data', chunk => respBodyChunks.push(Buffer.from(chunk)));
response.on('error', error => reject(error));
response.on('end', () => {
delete response.headers.connection;
delete response.headers['content-length'];
resolve({
statusCode: response.statusCode,
headers: response.headers,
body: Buffer.concat(respBodyChunks).toString('base64'),
encoding: 'base64',
});
});
});
if (body) req.write(body);
req.end();
});
}
}
module.exports = {
Bridge,
};

View File

@@ -1,7 +1,26 @@
{
"name": "@now/node-bridge",
"version": "0.1.9",
"peerDependencies": {
"@now/build-utils": ">=0.0.1"
"version": "1.0.1-canary.0",
"license": "MIT",
"main": "./index.js",
"repository": {
"type": "git",
"url": "https://github.com/zeit/now-builders.git",
"directory": "packages/now-node-bridge"
},
"files": [
"bridge.*",
"index.js"
],
"scripts": {
"build": "tsc",
"test": "npm run build && jest",
"prepublish": "npm run build"
},
"devDependencies": {
"@types/aws-lambda": "8.10.19",
"@types/node": "11.9.4",
"jest": "24.1.0",
"typescript": "3.3.3"
}
}

View File

@@ -0,0 +1,183 @@
import { AddressInfo } from 'net';
import { APIGatewayProxyEvent } from 'aws-lambda';
import {
Server,
IncomingHttpHeaders,
OutgoingHttpHeaders,
request
} from 'http';
interface NowProxyEvent {
Action: string;
body: string;
}
export interface NowProxyRequest {
isApiGateway?: boolean;
method: string;
path: string;
headers: IncomingHttpHeaders;
body: Buffer;
}
export interface NowProxyResponse {
statusCode: number;
headers: OutgoingHttpHeaders;
body: string;
encoding: string;
}
function normalizeNowProxyEvent(event: NowProxyEvent): NowProxyRequest {
let bodyBuffer: Buffer | null;
const { method, path, headers, encoding, body } = JSON.parse(event.body);
if (body) {
if (encoding === 'base64') {
bodyBuffer = Buffer.from(body, encoding);
} else if (encoding === undefined) {
bodyBuffer = Buffer.from(body);
} else {
throw new Error(`Unsupported encoding: ${encoding}`);
}
} else {
bodyBuffer = Buffer.alloc(0);
}
return { isApiGateway: false, method, path, headers, body: bodyBuffer };
}
function normalizeAPIGatewayProxyEvent(
event: APIGatewayProxyEvent
): NowProxyRequest {
let bodyBuffer: Buffer | null;
const { httpMethod: method, path, headers, body } = event;
if (body) {
if (event.isBase64Encoded) {
bodyBuffer = Buffer.from(body, 'base64');
} else {
bodyBuffer = Buffer.from(body);
}
} else {
bodyBuffer = Buffer.alloc(0);
}
return { isApiGateway: true, method, path, headers, body: bodyBuffer };
}
function normalizeEvent(
event: NowProxyEvent | APIGatewayProxyEvent
): NowProxyRequest {
if ('Action' in event) {
if (event.Action === 'Invoke') {
return normalizeNowProxyEvent(event);
} else {
throw new Error(`Unexpected event.Action: ${event.Action}`);
}
} else {
return normalizeAPIGatewayProxyEvent(event);
}
}
export class Bridge {
private server: Server | null;
private listening: Promise<AddressInfo>;
private resolveListening: (info: AddressInfo) => void;
constructor(server?: Server) {
this.server = null;
if (server) {
this.setServer(server);
}
this.launcher = this.launcher.bind(this);
// This is just to appease TypeScript strict mode, since it doesn't
// understand that the Promise constructor is synchronous
this.resolveListening = (info: AddressInfo) => {};
this.listening = new Promise(resolve => {
this.resolveListening = resolve;
});
}
setServer(server: Server) {
this.server = server;
server.once('listening', () => {
const addr = server.address();
if (typeof addr === 'string') {
throw new Error(`Unexpected string for \`server.address()\`: ${addr}`);
} else if (!addr) {
throw new Error('`server.address()` returned `null`');
} else {
this.resolveListening(addr);
}
});
}
listen() {
if (!this.server) {
throw new Error('Server has not been set!');
}
return this.server.listen({
host: '127.0.0.1',
port: 0
});
}
async launcher(
event: NowProxyEvent | APIGatewayProxyEvent
): Promise<NowProxyResponse> {
const { port } = await this.listening;
const { isApiGateway, method, path, headers, body } = normalizeEvent(
event
);
const opts = {
hostname: '127.0.0.1',
port,
path,
method,
headers
};
// eslint-disable-next-line consistent-return
return new Promise((resolve, reject) => {
const req = request(opts, res => {
const response = res;
const respBodyChunks: Buffer[] = [];
response.on('data', chunk => respBodyChunks.push(Buffer.from(chunk)));
response.on('error', reject);
response.on('end', () => {
const bodyBuffer = Buffer.concat(respBodyChunks);
delete response.headers.connection;
if (isApiGateway) {
delete response.headers['content-length'];
} else if (response.headers['content-length']) {
response.headers['content-length'] = String(bodyBuffer.length);
}
resolve({
statusCode: response.statusCode || 200,
headers: response.headers,
body: bodyBuffer.toString('base64'),
encoding: 'base64'
});
});
});
req.on('error', error => {
setTimeout(() => {
// this lets express print the true error of why the connection was closed.
// it is probably 'Cannot set headers after they are sent to the client'
reject(error);
}, 2);
});
if (body) req.write(body);
req.end();
});
}
}

View File

@@ -0,0 +1,71 @@
const assert = require('assert');
const { Server } = require('http');
const { Bridge } = require('../bridge');
test('port binding', async () => {
const server = new Server();
const bridge = new Bridge(server);
bridge.listen();
// Test port binding
const info = await bridge.listening;
assert.equal(info.address, '127.0.0.1');
assert.equal(typeof info.port, 'number');
server.close();
});
test('`APIGatewayProxyEvent` normalizing', async () => {
const server = new Server((req, res) => res.end(
JSON.stringify({
method: req.method,
path: req.url,
headers: req.headers,
}),
));
const bridge = new Bridge(server);
bridge.listen();
const result = await bridge.launcher({
httpMethod: 'GET',
headers: { foo: 'bar' },
path: '/apigateway',
body: null,
});
assert.equal(result.encoding, 'base64');
assert.equal(result.statusCode, 200);
const body = JSON.parse(Buffer.from(result.body, 'base64').toString());
assert.equal(body.method, 'GET');
assert.equal(body.path, '/apigateway');
assert.equal(body.headers.foo, 'bar');
server.close();
});
test('`NowProxyEvent` normalizing', async () => {
const server = new Server((req, res) => res.end(
JSON.stringify({
method: req.method,
path: req.url,
headers: req.headers,
}),
));
const bridge = new Bridge(server);
bridge.listen();
const result = await bridge.launcher({
Action: 'Invoke',
body: JSON.stringify({
method: 'POST',
headers: { foo: 'baz' },
path: '/nowproxy',
body: 'body=1',
}),
});
assert.equal(result.encoding, 'base64');
assert.equal(result.statusCode, 200);
const body = JSON.parse(Buffer.from(result.body, 'base64').toString());
assert.equal(body.method, 'POST');
assert.equal(body.path, '/nowproxy');
assert.equal(body.headers.foo, 'baz');
server.close();
});

View File

@@ -0,0 +1,16 @@
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"outDir": ".",
"strict": true,
"sourceMap": true,
"declaration": true
},
"include": [
"src/**/*"
],
"exclude": [
"node_modules"
]
}

View File

@@ -1,15 +1,15 @@
const { createLambda } = require('@now/build-utils/lambda.js');
const download = require('@now/build-utils/fs/download.js');
const FileBlob = require('@now/build-utils/file-blob.js');
const FileFsRef = require('@now/build-utils/file-fs-ref.js');
const { createLambda } = require('@now/build-utils/lambda.js'); // eslint-disable-line import/no-extraneous-dependencies
const download = require('@now/build-utils/fs/download.js'); // eslint-disable-line import/no-extraneous-dependencies
const FileBlob = require('@now/build-utils/file-blob.js'); // eslint-disable-line import/no-extraneous-dependencies
const FileFsRef = require('@now/build-utils/file-fs-ref.js'); // eslint-disable-line import/no-extraneous-dependencies
const fs = require('fs-extra');
const glob = require('@now/build-utils/fs/glob.js');
const glob = require('@now/build-utils/fs/glob.js'); // eslint-disable-line import/no-extraneous-dependencies
const path = require('path');
const rename = require('@now/build-utils/fs/rename.js');
const rename = require('@now/build-utils/fs/rename.js'); // eslint-disable-line import/no-extraneous-dependencies
const {
runNpmInstall,
runPackageJsonScript,
} = require('@now/build-utils/fs/run-user-scripts.js');
} = require('@now/build-utils/fs/run-user-scripts.js'); // eslint-disable-line import/no-extraneous-dependencies
/** @typedef { import('@now/build-utils/file-ref') } FileRef */
/** @typedef {{[filePath: string]: FileRef}} Files */
@@ -37,7 +37,7 @@ async function downloadInstallAndBundle(
console.log('downloading user files...');
const downloadedFiles = await download(files, userPath);
console.log('running npm install for user...');
console.log("installing dependencies for user's code...");
const entrypointFsDirname = path.join(userPath, path.dirname(entrypoint));
await runNpmInstall(entrypointFsDirname, npmArguments);
@@ -46,8 +46,9 @@ async function downloadInstallAndBundle(
{
'package.json': new FileBlob({
data: JSON.stringify({
license: 'UNLICENSED',
dependencies: {
'@zeit/ncc': '0.1.12',
'@zeit/ncc': '0.16.0',
},
}),
}),
@@ -55,7 +56,7 @@ async function downloadInstallAndBundle(
nccPath,
);
console.log('running npm install for ncc...');
console.log('installing dependencies for ncc...');
await runNpmInstall(nccPath, npmArguments);
return [downloadedFiles, userPath, nccPath, entrypointFsDirname];
}
@@ -63,7 +64,7 @@ async function downloadInstallAndBundle(
async function compile(workNccPath, downloadedFiles, entrypoint) {
const input = downloadedFiles[entrypoint].fsPath;
const ncc = require(path.join(workNccPath, 'node_modules/@zeit/ncc'));
const { code, assets } = await ncc(input);
const { code, assets } = await ncc(input, { sourceMap: true });
const preparedFiles = {};
const blob = new FileBlob({ data: code });
@@ -71,7 +72,8 @@ async function compile(workNccPath, downloadedFiles, entrypoint) {
preparedFiles[path.join('user', entrypoint)] = blob;
// eslint-disable-next-line no-restricted-syntax
for (const assetName of Object.keys(assets)) {
const blob2 = new FileBlob({ data: assets[assetName] });
const { source: data, permissions: mode } = assets[assetName];
const blob2 = new FileBlob({ data, mode });
preparedFiles[
path.join('user', path.dirname(entrypoint), assetName)
] = blob2;

View File

@@ -4,19 +4,16 @@ const { Bridge } = require('./bridge.js');
const bridge = new Bridge();
const saveListen = Server.prototype.listen;
Server.prototype.listen = function listen(...args) {
this.on('listening', function listening() {
bridge.port = this.address().port;
});
saveListen.apply(this, args);
Server.prototype.listen = function listen() {
bridge.setServer(this);
Server.prototype.listen = saveListen;
return bridge.listen();
};
try {
if (!process.env.NODE_ENV) {
process.env.NODE_ENV = 'production';
// PLACEHOLDER
} catch (error) {
console.error(error);
bridge.userError = error;
}
// PLACEHOLDER
exports.launcher = bridge.launcher;

View File

@@ -1,12 +1,15 @@
{
"name": "@now/node-server",
"version": "0.4.24",
"dependencies": {
"@now/node-bridge": "^0.1.9",
"fs-extra": "7.0.1"
"version": "0.5.2-canary.1",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/zeit/now-builders.git",
"directory": "packages/now-node-server"
},
"peerDependencies": {
"@now/build-utils": ">=0.0.1"
"dependencies": {
"@now/node-bridge": "^1.0.1-canary.0",
"fs-extra": "7.0.1"
},
"scripts": {
"test": "jest"

View File

@@ -1,4 +1,4 @@
const cowsay = require('cowsay/build/cowsay.umd.js').say;
const cowsay = require('cowsay').say;
const http = require('http');
// test that process.env is not replaced by webpack

View File

@@ -6,6 +6,6 @@
],
"probes": [
{ "path": "/", "mustContain": "cow:RANDOMNESS_PLACEHOLDER" },
{ "path": "/subdirectory", "mustContain": "yoda:RANDOMNESS_PLACEHOLDER" }
{ "path": "/subdirectory/", "mustContain": "yoda:RANDOMNESS_PLACEHOLDER" }
]
}

View File

@@ -1,5 +1,5 @@
{
"dependencies": {
"cowsay": "^1.3.1"
"cowsay": "1.3.1"
}
}

View File

@@ -1,4 +1,4 @@
const yodasay = require('yodasay/build/yodasay.umd.js').say;
const yodasay = require('yodasay').say;
const http = require('http');
// test that process.env is not replaced by webpack

View File

@@ -1,5 +1,5 @@
{
"dependencies": {
"yodasay": "^1.1.6"
"yodasay": "1.1.9"
}
}

View File

@@ -0,0 +1,7 @@
const http = require('http');
const server = http.createServer((req, resp) => {
resp.end('RANDOMNESS_PLACEHOLDER');
});
server.listen();

View File

@@ -0,0 +1,6 @@
{
"version": 2,
"builds": [
{ "src": "index.js", "use": "@now/node-server" }
]
}

View File

@@ -0,0 +1,7 @@
const assert = require('assert');
module.exports = async ({ deploymentUrl, fetch, randomness }) => {
const resp = await fetch(`https://${deploymentUrl}/`);
assert.equal(resp.headers.get('content-type'), null);
assert.equal(await resp.text(), randomness);
};

View File

@@ -0,0 +1,15 @@
const fs = require('fs');
const http = require('http');
const path = require('path');
const server = http.createServer((req, resp) => {
const asset1 = fs.readFileSync(
path.join(__dirname, 'subdirectory1/asset.txt'),
);
const asset2 = fs.readFileSync(
path.join(__dirname, 'subdirectory2/asset.txt'),
);
resp.end(`${asset1},${asset2}`);
});
server.listen();

View File

@@ -0,0 +1,9 @@
{
"version": 2,
"builds": [
{ "src": "index.js", "use": "@now/node-server" }
],
"probes": [
{ "path": "/", "mustContain": "asset1:RANDOMNESS_PLACEHOLDER,asset2:RANDOMNESS_PLACEHOLDER" }
]
}

View File

@@ -0,0 +1 @@
asset1:RANDOMNESS_PLACEHOLDER

View File

@@ -0,0 +1 @@
asset2:RANDOMNESS_PLACEHOLDER

View File

@@ -5,7 +5,7 @@
{ "src": "without-bundle/index.js", "use": "@now/node-server", "config": { "bundle": false } }
],
"probes": [
{ "path": "/with-bundle", "mustContain": "RANDOMNESS_PLACEHOLDER" },
{ "path": "/without-bundle", "mustContain": "RANDOMNESS_PLACEHOLDER" }
{ "path": "/with-bundle", "mustContain": "RANDOMNESS_PLACEHOLDER:with-bundle" },
{ "path": "/without-bundle", "mustContain": "RANDOMNESS_PLACEHOLDER:without-bundle" }
]
}

View File

@@ -2,7 +2,7 @@ const http = require('http');
const isBundled = require('./is-bundled.js');
const server = http.createServer((req, resp) => {
resp.end(isBundled() ? 'RANDOMNESS_PLACEHOLDER' : '');
resp.end(isBundled() ? 'RANDOMNESS_PLACEHOLDER:with-bundle' : 'WITHOUT-BUNDLE-THAT-IS-WRONG');
});
server.listen();

View File

@@ -1,3 +1,4 @@
const path = require('path');
module.exports = () => path.basename(__filename) === 'index.js';
// eslint-disable-next-line no-eval
module.exports = () => path.basename(eval('__filename')) === 'index.js';

View File

@@ -2,7 +2,7 @@ const http = require('http');
const isBundled = require('./is-bundled.js');
const server = http.createServer((req, resp) => {
resp.end(isBundled() ? '' : 'RANDOMNESS_PLACEHOLDER');
resp.end(isBundled() ? 'WITH-BUNDLE-THAT-IS-WRONG' : 'RANDOMNESS_PLACEHOLDER:without-bundle');
});
server.listen();

View File

@@ -1,3 +1,4 @@
const path = require('path');
module.exports = () => path.basename(__filename) === 'index.js';
// eslint-disable-next-line no-eval
module.exports = () => path.basename(eval('__filename')) === 'index.js';

Some files were not shown because too many files have changed in this diff Show More