Compare commits

...

22 Commits

Author SHA1 Message Date
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
60 changed files with 2764 additions and 244 deletions

1
.gitignore vendored
View File

@@ -1,2 +1,3 @@
node_modules
tmp
target/

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

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, currently this version is out on the `canary` release channel:
```
npm install next@canary
```
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,43 @@
# `@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, currently this version is out on the `canary` release channel:
```
npm install next@canary
```
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" }]
}
```

View File

@@ -2,24 +2,7 @@
"npmClient": "yarn",
"useWorkspaces": true,
"packages": [
"packages/now-build-utils",
"packages/now-node-bridge",
"packages/now-php-bridge",
"packages/now-bash",
"packages/now-cgi",
"packages/now-go",
"packages/now-html-minifier",
"packages/now-lambda",
"packages/now-md",
"packages/now-mdx-deck",
"packages/now-next",
"packages/now-node",
"packages/now-node-server",
"packages/now-optipng",
"packages/now-php",
"packages/now-python",
"packages/now-static-build",
"packages/now-wordpress"
"packages/*"
],
"command": {
"publish": {

View File

@@ -1,10 +1,10 @@
const execa = require('execa');
const { join } = require('path');
const snakeCase = require('snake-case');
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.config = {
maxLambdaSize: '10mb',

View File

@@ -1,10 +1,15 @@
{
"name": "@now/bash",
"version": "0.1.1",
"version": "0.1.2-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",
@@ -15,8 +20,5 @@
"dependencies": {
"execa": "^1.0.0",
"snake-case": "^2.1.0"
},
"peerDependencies": {
"@now/build-utils": ">=0.0.1"
}
}

View File

@@ -49,7 +49,7 @@ class FileRef {
assert(url);
await semaToDownloadFromS3.acquire();
console.time(`downloading ${url}`);
// console.time(`downloading ${url}`);
try {
return await retry(
async () => {
@@ -66,7 +66,7 @@ class FileRef {
{ factor: 1, retries: 3 },
);
} finally {
console.timeEnd(`downloading ${url}`);
// console.timeEnd(`downloading ${url}`);
semaToDownloadFromS3.release();
}
}

View File

@@ -1,3 +1,5 @@
/* eslint-disable arrow-body-style,no-multi-assign,no-param-reassign */
const MemoryFileSystem = require('memory-fs');
const fs = require('fs');
const path = require('path');
@@ -19,76 +21,222 @@ function isInsideCachePath(filename) {
return !relative.startsWith('..');
}
const saveCreateWriteStream = fs.createWriteStream;
fs.createWriteStream = (...args) => {
const filename = args[0];
if (!isInsideCachePath(filename)) {
return saveCreateWriteStream.call(fs, ...args);
}
function replaceFn(name, newFnFactory) {
const prevFn = fs[name];
fs[name] = newFnFactory(prevFn);
}
vfs.mkdirpSync(path.dirname(filename));
fs.writeFileSync(filename, Buffer.alloc(0));
const stream = vfs.createWriteStream(...args);
stream.on('finish', () => {
setTimeout(() => {
stream.emit('close');
});
});
return stream;
};
const saveReadFile = fs.readFile;
fs.readFile = (...args) => {
const filename = args[0];
if (!isInsideCachePath(filename)) {
return saveReadFile.call(fs, ...args);
}
const callback = args[args.length - 1];
return vfs.readFile(...args.slice(0, -1), (error, result) => {
if (error) {
saveReadFile.call(fs, ...args);
return;
replaceFn('createWriteStream', (prevFn) => {
return (...args) => {
const filename = args[0];
if (!isInsideCachePath(filename)) {
return prevFn.call(fs, ...args);
}
callback(error, result);
});
};
const stream = vfs.createWriteStream(...args);
const saveCopyFile = fs.copyFile;
fs.copyFile = (...args) => {
const src = args[0];
const dest = args[1];
const callback = args[args.length - 1];
stream.on('finish', () => {
setTimeout(() => {
stream.emit('close');
});
});
if (isInsideCachePath(src) && !isInsideCachePath(dest)) {
const buffer = vfs.readFileSync(src);
return fs.writeFile(dest, buffer, callback);
}
setTimeout(() => {
stream.emit('open');
});
if (!isInsideCachePath(src) && isInsideCachePath(dest)) {
const buffer = fs.readFileSync(src);
return stream;
};
});
vfs.mkdirpSync(path.dirname(dest));
fs.writeFileSync(dest, Buffer.alloc(0));
return vfs.writeFile(dest, buffer, callback);
}
replaceFn('readFile', (prevFn) => {
return (...args) => {
const filename = args[0];
if (!isInsideCachePath(filename)) {
return prevFn.call(fs, ...args);
}
return saveCopyFile.call(fs, ...args);
};
const callback = args[args.length - 1];
return vfs.readFile(...args.slice(0, -1), (error, result) => {
if (error) {
return prevFn.call(fs, ...args);
}
const saveWriteFile = fs.writeFile;
fs.writeFile = (...args) => {
const filename = args[0];
if (!isInsideCachePath(filename)) {
return saveWriteFile.call(fs, ...args);
}
return callback(error, result);
});
};
});
vfs.mkdirpSync(path.dirname(filename));
fs.writeFileSync(filename, Buffer.alloc(0));
return vfs.writeFile(...args);
};
replaceFn('readdir', (prevFn) => {
return (...args) => {
const dirname = args[0];
if (!isInsideCachePath(dirname)) {
return prevFn.call(fs, ...args);
}
const callback = args[args.length - 1];
return prevFn.call(fs, dirname, (error, results) => {
if (error) {
results = [];
}
return vfs.readdir(dirname, (error2, results2) => {
if (error2) {
return callback(error2);
}
// eslint-disable-next-line no-restricted-syntax
for (const result2 of results2) {
if (!results.includes(result2)) {
results.push(result2);
}
}
return callback(error2, results);
});
});
};
});
replaceFn('stat', (prevFn) => {
return (...args) => {
const filename = args[0];
if (!isInsideCachePath(filename)) {
return prevFn.call(fs, ...args);
}
const callback = args[args.length - 1];
return vfs.stat(...args.slice(0, -1), (error, result) => {
if (error) {
return prevFn.call(fs, ...args);
}
result.atime = result.mtime = new Date();
return callback(error, result);
});
};
});
replaceFn('lstat', (prevFn) => {
return (...args) => {
const filename = args[0];
if (!isInsideCachePath(filename)) {
return prevFn.call(fs, ...args);
}
const callback = args[args.length - 1];
return vfs.stat(...args.slice(0, -1), (error, result) => {
if (error) {
return prevFn.call(fs, ...args);
}
result.atime = result.mtime = new Date();
return callback(error, result);
});
};
});
replaceFn('exists', (prevFn) => {
return (...args) => {
const filename = args[0];
if (!isInsideCachePath(filename)) {
return prevFn.call(fs, ...args);
}
const callback = args[args.length - 1];
return vfs.exists(...args.slice(0, -1), (result) => {
if (!result) {
return prevFn.call(fs, ...args);
}
return callback(result);
});
};
});
replaceFn('copyFile', (prevFn) => {
return (...args) => {
const src = args[0];
const dest = args[1];
const callback = args[args.length - 1];
if (isInsideCachePath(src) && !isInsideCachePath(dest)) {
const buffer = vfs.readFileSync(src);
return fs.writeFile(dest, buffer, callback);
}
if (!isInsideCachePath(src) && isInsideCachePath(dest)) {
const buffer = fs.readFileSync(src);
return vfs.writeFile(dest, buffer, callback);
}
return prevFn.call(fs, ...args);
};
});
replaceFn('writeFile', (prevFn) => {
return (...args) => {
const filename = args[0];
if (!isInsideCachePath(filename)) {
return prevFn.call(fs, ...args);
}
return vfs.writeFile(...args);
};
});
replaceFn('mkdir', (prevFn) => {
return (...args) => {
const dirname = args[0];
if (!isInsideCachePath(dirname)) {
return prevFn.call(fs, ...args);
}
const callback = args[args.length - 1];
return prevFn.call(fs, dirname, (error) => {
if (error) {
return callback(error);
}
return vfs.mkdirp(dirname, callback);
});
};
});
replaceFn('utimes', (prevFn) => {
return (...args) => {
const filename = args[0];
if (!isInsideCachePath(filename)) {
return prevFn.call(fs, ...args);
}
const callback = args[args.length - 1];
return setTimeout(callback, 0);
};
});
replaceFn('chmod', (prevFn) => {
return (...args) => {
const filename = args[0];
if (!isInsideCachePath(filename)) {
return prevFn.call(fs, ...args);
}
const callback = args[args.length - 1];
return setTimeout(callback, 0);
};
});
replaceFn('chown', (prevFn) => {
return (...args) => {
const filename = args[0];
if (!isInsideCachePath(filename)) {
return prevFn.call(fs, ...args);
}
const callback = args[args.length - 1];
return setTimeout(callback, 0);
};
});
require(yarnPath);

View File

@@ -1,7 +1,12 @@
{
"name": "@now/build-utils",
"version": "0.4.32",
"version": "0.4.33-canary.2",
"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",

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,7 +1,12 @@
{
"name": "@now/cgi",
"version": "0.0.15",
"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"
@@ -16,8 +21,5 @@
"devDependencies": {
"@zeit/best": "0.4.3",
"rmfr": "2.0.0"
},
"peerDependencies": {
"@now/build-utils": ">=0.0.1"
}
}

View File

@@ -2,7 +2,7 @@ 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 getWritableDirectory = require('@now/build-utils/fs/get-writable-directory.js'); // eslint-disable-line import/no-extraneous-dependencies
const url = 'https://dl.google.com/go/go1.11.1.linux-amd64.tar.gz';

View File

@@ -2,11 +2,11 @@ const path = require('path');
const { mkdirp, readFile, writeFile } = 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 { 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 download = require('@now/build-utils/fs/download.js'); // eslint-disable-line import/no-extraneous-dependencies
const downloadGit = require('lambda-git');
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 downloadGoBin = require('./download-go-bin');
// creates a `$GOPATH` directory tree, as per

View File

@@ -1,7 +1,12 @@
{
"name": "@now/go",
"version": "0.2.12",
"version": "0.2.13-canary.0",
"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"
@@ -23,8 +28,5 @@
"devDependencies": {
"@zeit/best": "0.4.3",
"rmfr": "2.0.0"
},
"peerDependencies": {
"@now/build-utils": ">=0.0.1"
}
}

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,11 +1,13 @@
{
"name": "@now/html-minifier",
"version": "1.0.7",
"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,9 +1,11 @@
{
"name": "@now/lambda",
"version": "0.4.9",
"version": "0.4.10-canary.0",
"license": "MIT",
"peerDependencies": {
"@now/build-utils": ">=0.0.1"
"repository": {
"type": "git",
"url": "https://github.com/zeit/now-builders.git",
"directory": "packages/now-lambda"
},
"scripts": {
"test": "jest"

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,7 +1,12 @@
{
"name": "@now/md",
"version": "0.4.9",
"version": "0.4.10-canary.0",
"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",
@@ -11,9 +16,6 @@
"unified": "^7.0.0",
"unified-stream": "^1.0.2"
},
"peerDependencies": {
"@now/build-utils": ">=0.0.1"
},
"scripts": {
"test": "jest"
}

View File

@@ -1,10 +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');
const { runNpmInstall } = require('@now/build-utils/fs/run-user-scripts.js'); // eslint-disable-line import/no-extraneous-dependencies
const writeFile = promisify(fs.writeFile);

View File

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

View File

@@ -1,14 +1,14 @@
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 semver = require('semver');
const nextLegacyVersions = require('./legacy-versions');
const {
@@ -145,8 +145,9 @@ exports.build = async ({ files, workPath, entrypoint }) => {
}
console.warn(
"WARNING: your application is being deployed in @now/next's legacy mode.",
"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);

View File

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

View File

@@ -1,4 +1,4 @@
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
/** @typedef { import('@now/build-utils/file-ref') } FileRef */
/** @typedef { import('@now/build-utils/file-fs-ref') } FileFsRef */

View File

@@ -1,8 +1,10 @@
{
"name": "@now/node-bridge",
"version": "0.1.10",
"version": "0.1.11-canary.0",
"license": "MIT",
"peerDependencies": {
"@now/build-utils": ">=0.0.1"
"repository": {
"type": "git",
"url": "https://github.com/zeit/now-builders.git",
"directory": "packages/now-node-bridge"
}
}

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('installing dependencies for user\'s code...');
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.11.0',
'@zeit/ncc': '0.13.2',
},
}),
}),

View File

@@ -1,13 +1,15 @@
{
"name": "@now/node-server",
"version": "0.4.26",
"version": "0.4.27-canary.2",
"license": "MIT",
"dependencies": {
"@now/node-bridge": "^0.1.10",
"fs-extra": "7.0.1"
"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": "^0.1.11-canary.0",
"fs-extra": "7.0.1"
},
"scripts": {
"test": "jest"

View File

@@ -1,14 +1,14 @@
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 {
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 */
@@ -35,7 +35,7 @@ async function downloadInstallAndBundle(
console.log('downloading user files...');
const downloadedFiles = await download(files, userPath);
console.log('installing dependencies for user\'s code...');
console.log("installing dependencies for user's code...");
const entrypointFsDirname = path.join(userPath, path.dirname(entrypoint));
await runNpmInstall(entrypointFsDirname, npmArguments);
@@ -44,8 +44,9 @@ async function downloadInstallAndBundle(
{
'package.json': new FileBlob({
data: JSON.stringify({
license: 'UNLICENSED',
dependencies: {
'@zeit/ncc': '0.11.0',
'@zeit/ncc': '0.13.2',
},
}),
}),

View File

@@ -1,13 +1,15 @@
{
"name": "@now/node",
"version": "0.4.28",
"version": "0.4.29-canary.2",
"license": "MIT",
"dependencies": {
"@now/node-bridge": "^0.1.10",
"fs-extra": "7.0.1"
"repository": {
"type": "git",
"url": "https://github.com/zeit/now-builders.git",
"directory": "packages/now-node"
},
"peerDependencies": {
"@now/build-utils": ">=0.0.1"
"dependencies": {
"@now/node-bridge": "^0.1.11-canary.0",
"fs-extra": "7.0.1"
},
"scripts": {
"test": "jest"

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 OptiPng = require('optipng');
const pipe = require('multipipe');

View File

@@ -1,12 +1,14 @@
{
"name": "@now/optipng",
"version": "0.4.8",
"version": "0.4.9-canary.0",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/zeit/now-builders.git",
"directory": "packages/now-optipng"
},
"dependencies": {
"multipipe": "2.0.3",
"optipng": "1.1.0"
},
"peerDependencies": {
"@now/build-utils": ">=0.0.1"
}
}

View File

@@ -1,23 +1,38 @@
const FileBlob = require('@now/build-utils/file-blob.js');
const FileFsRef = require('@now/build-utils/file-fs-ref.js');
const glob = require('@now/build-utils/fs/glob.js');
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 glob = require('@now/build-utils/fs/glob.js'); // eslint-disable-line import/no-extraneous-dependencies
const path = require('path');
async function getFiles() {
const files = await glob('native/**', __dirname);
const phpConfig = await FileBlob.fromStream({ stream: files['native/php.ini'].toStream() });
phpConfig.data = phpConfig.data.toString()
const phpConfig = await FileBlob.fromStream({
stream: files['native/php.ini'].toStream(),
});
phpConfig.data = phpConfig.data
.toString()
.replace(/\/root\/app\/modules/g, '/var/task/native/modules');
files['native/php.ini'] = phpConfig;
Object.assign(files, {
'fastcgi/connection.js': new FileFsRef({ fsPath: require.resolve('fastcgi-client/lib/connection.js') }),
'fastcgi/consts.js': new FileFsRef({ fsPath: require.resolve('fastcgi-client/lib/consts.js') }),
'fastcgi/stringifykv.js': new FileFsRef({ fsPath: require.resolve('fastcgi-client/lib/stringifykv.js') }),
'fastcgi/index.js': new FileFsRef({ fsPath: path.join(__dirname, 'fastcgi/index.js') }),
'fastcgi/port.js': new FileFsRef({ fsPath: path.join(__dirname, 'fastcgi/port.js') }),
'launcher.js': new FileFsRef({ fsPath: path.join(__dirname, 'launcher.js') }),
'fastcgi/connection.js': new FileFsRef({
fsPath: require.resolve('fastcgi-client/lib/connection.js'),
}),
'fastcgi/consts.js': new FileFsRef({
fsPath: require.resolve('fastcgi-client/lib/consts.js'),
}),
'fastcgi/stringifykv.js': new FileFsRef({
fsPath: require.resolve('fastcgi-client/lib/stringifykv.js'),
}),
'fastcgi/index.js': new FileFsRef({
fsPath: path.join(__dirname, 'fastcgi/index.js'),
}),
'fastcgi/port.js': new FileFsRef({
fsPath: path.join(__dirname, 'fastcgi/port.js'),
}),
'launcher.js': new FileFsRef({
fsPath: path.join(__dirname, 'launcher.js'),
}),
});
return files;

View File

@@ -1,11 +1,13 @@
{
"name": "@now/php-bridge",
"version": "0.4.13",
"version": "0.4.14-canary.0",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/zeit/now-builders.git",
"directory": "packages/now-php-bridge"
},
"dependencies": {
"fastcgi-client": "0.0.1"
},
"peerDependencies": {
"@now/build-utils": ">=0.0.1"
}
}

View File

@@ -1,6 +1,6 @@
const { createLambda } = require('@now/build-utils/lambda.js');
const { createLambda } = require('@now/build-utils/lambda.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 { getFiles } = require('@now/php-bridge');
exports.config = {

View File

@@ -1,12 +1,14 @@
{
"name": "@now/php",
"version": "0.4.13",
"version": "0.4.14-canary.0",
"license": "MIT",
"dependencies": {
"@now/php-bridge": "^0.4.13"
"repository": {
"type": "git",
"url": "https://github.com/zeit/now-builders.git",
"directory": "packages/now-php"
},
"peerDependencies": {
"@now/build-utils": ">=0.0.1"
"dependencies": {
"@now/php-bridge": "^0.4.14-canary.0"
},
"scripts": {
"test": "jest"

View File

@@ -3,7 +3,7 @@ const fetch = require('node-fetch');
const execa = require('execa');
const { createWriteStream } = require('fs');
const getWritableDirectory = require('@now/build-utils/fs/get-writable-directory.js');
const getWritableDirectory = require('@now/build-utils/fs/get-writable-directory.js'); // eslint-disable-line import/no-extraneous-dependencies
const url = 'https://bootstrap.pypa.io/get-pip.py';

View File

@@ -1,10 +1,10 @@
const path = require('path');
const execa = require('execa');
const { readFile, writeFile } = require('fs.promised');
const getWritableDirectory = require('@now/build-utils/fs/get-writable-directory.js');
const download = require('@now/build-utils/fs/download.js');
const glob = require('@now/build-utils/fs/glob.js');
const { createLambda } = require('@now/build-utils/lambda.js');
const getWritableDirectory = require('@now/build-utils/fs/get-writable-directory.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 glob = require('@now/build-utils/fs/glob.js'); // eslint-disable-line import/no-extraneous-dependencies
const { createLambda } = require('@now/build-utils/lambda.js'); // eslint-disable-line import/no-extraneous-dependencies
const downloadAndInstallPip = require('./download-and-install-pip');
async function pipInstall(pipPath, srcDir, ...args) {

View File

@@ -1,14 +1,16 @@
{
"name": "@now/python",
"version": "0.0.40",
"version": "0.0.41-canary.0",
"main": "index.js",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/zeit/now-builders.git",
"directory": "packages/now-python"
},
"dependencies": {
"execa": "^1.0.0",
"fs.promised": "^3.0.0",
"node-fetch": "^2.2.0"
},
"peerDependencies": {
"@now/build-utils": ">=0.0.1"
}
}

1101
packages/now-rust/Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,15 @@
[package]
name = "now_lambda"
version = "0.1.0"
authors = ["Antonio Nuno Monteiro <anmonteiro@gmail.com>"]
edition = "2018"
[dependencies]
serde = "^1"
serde_json = "^1"
serde_derive = "^1"
http = "0.1"
tokio = "^0.1"
base64 = "0.10"
log = "^0.4"
lambda_runtime = "0.2.0"

View File

@@ -0,0 +1,62 @@
const tar = require('tar');
const fetch = require('node-fetch');
const rustUrl = 'https://dmmcy0pwk6bqi.cloudfront.net/rust.tar.gz';
const ccUrl = 'https://dmmcy0pwk6bqi.cloudfront.net/gcc-4.8.5.tgz';
async function downloadRustToolchain() {
console.log('downloading the rust toolchain');
const res = await fetch(rustUrl);
if (!res.ok) {
throw new Error(`Failed to download: ${rustUrl}`);
}
const { HOME } = process.env;
return new Promise((resolve, reject) => {
res.body
.on('error', reject)
.pipe(tar.extract({ gzip: true, cwd: HOME }))
.on('finish', () => resolve());
});
}
async function downloadGCC() {
console.log('downloading GCC');
const res = await fetch(ccUrl);
if (!res.ok) {
throw new Error(`Failed to download: ${ccUrl}`);
}
return new Promise((resolve, reject) => {
res.body
.on('error', reject)
// NOTE(anmonteiro): We pipe GCC into `/tmp` instead of getting a writable
// directory from `@now/build-utils` because the GCC distribution that we
// use is specifically packaged for AWS Lambda (where `/tmp` is writable)
// and contains several hardcoded symlinks to paths in `/tmp`.
.pipe(tar.extract({ gzip: true, cwd: '/tmp' }))
.on('finish', async () => {
const { LD_LIBRARY_PATH } = process.env;
// Set the environment variables as per
// https://github.com/lambci/lambci/blob/e6c9c7/home/init/gcc#L14-L17
const newEnv = {
PATH: '/tmp/bin:/tmp/sbin',
LD_LIBRARY_PATH: `/tmp/lib:/tmp/lib64:${LD_LIBRARY_PATH}`,
CPATH: '/tmp/include',
LIBRARY_PATH: '/tmp/lib',
};
return resolve(newEnv);
});
});
}
module.exports = async () => {
await downloadRustToolchain();
const newEnv = await downloadGCC();
return newEnv;
};

View File

@@ -0,0 +1,90 @@
const fs = require('fs');
const path = require('path');
const concat = require('concat-stream');
const execa = require('execa');
const toml = require('toml');
const rimraf = require('rimraf');
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 glob = require('@now/build-utils/fs/glob.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 installRustAndGCC = require('./download-install-rust-toolchain.js');
const inferCargoBinaries = require('./inferCargoBinaries.js');
exports.config = {
maxLambdaSize: '25mb',
};
async function parseTOMLStream(stream) {
return new Promise((resolve) => {
stream.pipe(concat(data => resolve(toml.parse(data))));
});
}
exports.build = async ({ files, entrypoint, workPath }) => {
console.log('downloading files');
const downloadedFiles = await download(files, workPath);
const { PATH: toolchainPath, ...otherEnv } = await installRustAndGCC();
const { PATH, HOME } = process.env;
const rustEnv = {
...process.env,
...otherEnv,
PATH: `${path.join(HOME, '.cargo/bin')}:${toolchainPath}:${PATH}`,
};
let cargoToml;
try {
cargoToml = await parseTOMLStream(files[entrypoint].toStream());
} catch (err) {
console.error('Failed to parse TOML from entrypoint:', entrypoint);
throw err;
}
const entrypointDirname = path.dirname(downloadedFiles[entrypoint].fsPath);
console.log('running `cargo build --release`...');
try {
await execa('cargo', ['build', '--release'], {
env: rustEnv,
cwd: entrypointDirname,
stdio: 'inherit',
});
} catch (err) {
console.error('failed to `cargo build --release`');
throw err;
}
const targetPath = path.join(workPath, 'target', 'release');
const binaries = await inferCargoBinaries(
cargoToml,
path.join(workPath, 'src'),
);
const lambdas = {};
await Promise.all(
binaries.map(async (binary) => {
const fsPath = path.join(targetPath, binary);
const lambda = await createLambda({
files: {
bootstrap: new FileFsRef({ mode: 0o755, fsPath }),
},
handler: 'bootstrap',
runtime: 'provided',
});
lambdas[binary] = lambda;
}),
);
return lambdas;
};
exports.prepareCache = async ({ cachePath, workPath }) => {
console.log('preparing cache...');
rimraf.sync(path.join(cachePath, 'target'));
fs.renameSync(path.join(workPath, 'target'), path.join(cachePath, 'target'));
return {
...(await glob('target/**', path.join(cachePath))),
};
};

View File

@@ -0,0 +1,73 @@
const fs = require('fs');
const path = require('path');
function readdir(dir) {
return new Promise((resolve, reject) => {
fs.readdir(dir, (err, files) => {
if (err != null) {
return reject(err);
}
return resolve(files);
});
});
}
function exists(p) {
return new Promise((resolve, reject) => {
fs.exists(p, (err, res) => {
if (err != null) {
return reject(err);
}
return resolve(res);
});
});
}
function stat(p) {
return new Promise((resolve, reject) => {
fs.stat(p, (err, stats) => {
if (err != null) {
return reject(err);
}
return resolve(stats);
});
});
}
async function inferCargoBinaries(cargoToml, srcDir) {
const { package: pkg, bin } = cargoToml;
const binaries = [];
const hasMain = (await readdir(srcDir)).includes('main.rs');
if (hasMain) {
binaries.push(pkg.name);
}
// From: https://doc.rust-lang.org/cargo/reference/manifest.html#the-project-layout
// Do note, however, once you add a [[bin]] section (see below), Cargo will
// no longer automatically build files located in src/bin/*.rs. Instead you
// must create a [[bin]] section for each file you want to build.
if (Array.isArray(bin)) {
bin.forEach((binary) => {
binaries.push(binary.name);
});
} else {
const binDir = path.join(srcDir, 'bin');
const filesInSrcBin = (await exists(binDir)) && (await stat(binDir)).isDirectory()
? await readdir(binDir)
: [];
filesInSrcBin.forEach((file) => {
if (file.endsWith('.rs')) {
binaries.push(file.slice(0, -3));
}
});
}
return binaries;
}
module.exports = inferCargoBinaries;

View File

@@ -0,0 +1,23 @@
{
"name": "@now/rust",
"version": "0.0.2-canary.0",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/zeit/now-builders.git",
"directory": "packages/now-rust"
},
"files": [
"index.js",
"download-install-rust-toolchain.js",
"inferCargoBinaries.js"
],
"dependencies": {
"concat-stream": "^2.0.0",
"execa": "^1.0.0",
"node-fetch": "^2.3.0",
"rimraf": "^2.6.3",
"tar": "^4.4.8",
"toml": "^2.3.3"
}
}

View File

@@ -0,0 +1,157 @@
//! Provides a Now Lambda oriented request and response body entity interface
use std::{borrow::Cow, ops::Deref};
use base64::display::Base64Display;
use serde::ser::{Error as SerError, Serialize, Serializer};
/// Representation of http request and response bodies as supported
/// by Zeit Now v2.
///
/// These come in three flavors
/// * `Empty` ( no body )
/// * `Text` ( text data )
/// * `Binary` ( binary data )
///
/// Body types can be `Deref` and `AsRef`'d into `[u8]` types much like the `hyper` crate
///
/// # Examples
///
/// Body types are inferred with `From` implementations.
///
/// ## Text
///
/// Types like `String`, `str` whose type reflects
/// text produce `Body::Text` variants
///
/// ```
/// assert!(match now_lambda::Body::from("text") {
/// now_lambda::Body::Text(_) => true,
/// _ => false
/// })
/// ```
///
/// ## Binary
///
/// Types like `Vec<u8>` and `&[u8]` whose types reflect raw bytes produce `Body::Binary` variants
///
/// ```
/// assert!(match now_lambda::Body::from("text".as_bytes()) {
/// now_lambda::Body::Binary(_) => true,
/// _ => false
/// })
/// ```
///
/// `Binary` responses bodies will automatically get base64 encoded.
///
/// ## Empty
///
/// The unit type ( `()` ) whose type represents an empty value produces `Body::Empty` variants
///
/// ```
/// assert!(match now_lambda::Body::from(()) {
/// now_lambda::Body::Empty => true,
/// _ => false
/// })
/// ```
#[derive(Debug, PartialEq)]
pub enum Body {
/// An empty body
Empty,
/// A body containing string data
Text(String),
/// A body containing binary data
Binary(Vec<u8>),
}
impl Default for Body {
fn default() -> Self {
Body::Empty
}
}
impl From<()> for Body {
fn from(_: ()) -> Self {
Body::Empty
}
}
impl<'a> From<&'a str> for Body {
fn from(s: &'a str) -> Self {
Body::Text(s.into())
}
}
impl From<String> for Body {
fn from(b: String) -> Self {
Body::Text(b)
}
}
impl From<Cow<'static, str>> for Body {
#[inline]
fn from(cow: Cow<'static, str>) -> Body {
match cow {
Cow::Borrowed(b) => Body::from(b.to_owned()),
Cow::Owned(o) => Body::from(o),
}
}
}
impl From<Cow<'static, [u8]>> for Body {
#[inline]
fn from(cow: Cow<'static, [u8]>) -> Body {
match cow {
Cow::Borrowed(b) => Body::from(b),
Cow::Owned(o) => Body::from(o),
}
}
}
impl From<Vec<u8>> for Body {
fn from(b: Vec<u8>) -> Self {
Body::Binary(b)
}
}
impl<'a> From<&'a [u8]> for Body {
fn from(b: &'a [u8]) -> Self {
Body::Binary(b.to_vec())
}
}
impl Deref for Body {
type Target = [u8];
#[inline]
fn deref(&self) -> &Self::Target {
self.as_ref()
}
}
impl AsRef<[u8]> for Body {
#[inline]
fn as_ref(&self) -> &[u8] {
match self {
Body::Empty => &[],
Body::Text(ref bytes) => bytes.as_ref(),
Body::Binary(ref bytes) => bytes.as_ref(),
}
}
}
impl<'a> Serialize for Body {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match self {
Body::Text(data) => serializer
.serialize_str(::std::str::from_utf8(data.as_ref()).map_err(S::Error::custom)?),
Body::Binary(data) => {
serializer.collect_str(&Base64Display::with_config(data, base64::STANDARD))
}
Body::Empty => serializer.serialize_unit(),
}
}
}

View File

@@ -0,0 +1,35 @@
use lambda_runtime::error::LambdaErrorExt;
use std::{error::Error, fmt};
/// This module implements a custom error currently over the AWS Lambda runtime,
/// which can be extended later to support more service providers.
#[derive(Debug)]
pub struct NowError {
msg: String,
}
impl NowError {
pub fn new(message: &str) -> NowError {
NowError {
msg: message.to_owned(),
}
}
}
impl fmt::Display for NowError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.msg)
}
}
impl Error for NowError {}
impl From<std::num::ParseIntError> for NowError {
fn from(i: std::num::ParseIntError) -> Self {
NowError::new(&format!("{}", i))
}
}
// the value returned by the error_type function is included as the
// `errorType` in the AWS Lambda response
impl LambdaErrorExt for NowError {
fn error_type(&self) -> &str {
"NowError"
}
}

View File

@@ -0,0 +1,87 @@
pub use http::{self, Response};
use lambda_runtime::{self as lambda, Context};
use log::{self, debug, error};
use serde_json::Error;
use tokio::runtime::Runtime as TokioRuntime;
mod body;
pub mod error;
pub mod request;
mod response;
mod strmap;
pub use crate::{body::Body, response::IntoResponse, strmap::StrMap};
use crate::{
error::NowError,
request::{NowEvent, NowRequest},
response::NowResponse,
};
/// Type alias for `http::Request`s with a fixed `now_lambda::Body` body
pub type Request = http::Request<Body>;
/// Functions acting as Now Lambda handlers must conform to this type.
pub trait Handler<R> {
/// Method to execute the handler function
fn run(&mut self, event: Request) -> Result<R, NowError>;
}
impl<Function, R> Handler<R> for Function
where
Function: FnMut(Request) -> Result<R, NowError>,
{
fn run(&mut self, event: Request) -> Result<R, NowError> {
(*self)(event)
}
}
/// Creates a new `lambda_runtime::Runtime` and begins polling for Now Lambda events
///
/// # Arguments
///
/// * `f` A type that conforms to the `Handler` interface.
///
/// # Panics
/// The function panics if the Lambda environment variables are not set.
pub fn start<R>(f: impl Handler<R>, runtime: Option<TokioRuntime>)
where
R: IntoResponse,
{
// handler requires a mutable ref
let mut func = f;
lambda::start(
|e: NowEvent, _ctx: Context| {
let req_str = e.body;
let parse_result: Result<NowRequest, Error> = serde_json::from_str(&req_str);
match parse_result {
Ok(req) => {
debug!("Deserialized Now proxy request successfully");
func.run(req.into())
.map(|resp| NowResponse::from(resp.into_response()))
}
Err(e) => {
error!("Could not deserialize event body to NowRequest {}", e);
panic!("Could not deserialize event body to NowRequest {}", e);
}
}
},
runtime,
)
}
/// A macro for starting new handler's poll for Now Lambda events
#[macro_export]
macro_rules! lambda {
($handler:expr) => {
$crate::start($handler, None)
};
($handler:expr, $runtime:expr) => {
$crate::start($handler, Some($runtime))
};
($handler:ident) => {
$crate::start($handler, None)
};
($handler:ident, $runtime:expr) => {
$crate::start($handler, Some($runtime))
};
}

View File

@@ -0,0 +1,139 @@
use std::{borrow::Cow, fmt, mem};
use http::{self, header::HeaderValue, HeaderMap, Method, Request as HttpRequest};
use serde::{
de::{Error as DeError, MapAccess, Visitor},
Deserialize, Deserializer,
};
use serde_derive::Deserialize;
#[allow(unused_imports)]
use serde_json::Value;
use crate::body::Body;
/// Representation of a Now Lambda proxy event data
#[doc(hidden)]
#[derive(Deserialize, Debug, Default)]
#[serde(rename_all = "camelCase")]
pub(crate) struct NowRequest<'a> {
pub(crate) host: Cow<'a, str>,
pub(crate) path: Cow<'a, str>,
#[serde(deserialize_with = "deserialize_method")]
pub(crate) method: Method,
#[serde(deserialize_with = "deserialize_headers")]
pub(crate) headers: HeaderMap<HeaderValue>,
pub(crate) body: Option<Cow<'a, str>>,
pub(crate) encoding: Option<String>,
}
#[doc(hidden)]
#[derive(Deserialize, Debug, Default)]
pub(crate) struct NowEvent<'a> {
#[serde(rename = "Action")]
action: Cow<'a, str>,
pub(crate) body: Cow<'a, str>,
}
fn deserialize_method<'de, D>(deserializer: D) -> Result<Method, D::Error>
where
D: Deserializer<'de>,
{
struct MethodVisitor;
impl<'de> Visitor<'de> for MethodVisitor {
type Value = Method;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(formatter, "a Method")
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: DeError,
{
v.parse().map_err(E::custom)
}
}
deserializer.deserialize_str(MethodVisitor)
}
fn deserialize_headers<'de, D>(deserializer: D) -> Result<HeaderMap<HeaderValue>, D::Error>
where
D: Deserializer<'de>,
{
struct HeaderVisitor;
impl<'de> Visitor<'de> for HeaderVisitor {
type Value = HeaderMap<HeaderValue>;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(formatter, "a HeaderMap<HeaderValue>")
}
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: MapAccess<'de>,
{
let mut headers = http::HeaderMap::new();
while let Some((key, value)) = map.next_entry::<Cow<'_, str>, Cow<'_, str>>()? {
let header_name = key
.parse::<http::header::HeaderName>()
.map_err(A::Error::custom)?;
let header_value =
http::header::HeaderValue::from_shared(value.into_owned().into())
.map_err(A::Error::custom)?;
headers.append(header_name, header_value);
}
Ok(headers)
}
}
deserializer.deserialize_map(HeaderVisitor)
}
/// deserializes (json) null values to their default values
// https://github.com/serde-rs/serde/issues/1098
#[allow(dead_code)]
fn nullable_default<'de, T, D>(deserializer: D) -> Result<T, D::Error>
where
D: Deserializer<'de>,
T: Default + Deserialize<'de>,
{
let opt = Option::deserialize(deserializer)?;
Ok(opt.unwrap_or_else(T::default))
}
impl<'a> From<NowRequest<'a>> for HttpRequest<Body> {
fn from(value: NowRequest<'_>) -> Self {
let NowRequest {
host,
path,
method,
headers,
body,
encoding,
} = value;
// build an http::Request<now_lambda::Body> from a now_lambda::NowRequest
let mut builder = HttpRequest::builder();
builder.method(method);
builder.uri({ format!("https://{}{}", host, path) });
let mut req = builder
.body(match (body, encoding) {
(Some(ref b), Some(ref encoding)) if encoding == "base64" => {
// todo: document failure behavior
Body::from(::base64::decode(b.as_ref()).unwrap_or_default())
}
(Some(b), Some(_)) => Body::from(b.into_owned()),
_ => Body::from(()),
})
.expect("failed to build request");
// no builder method that sets headers in batch
mem::replace(req.headers_mut(), headers);
req
}
}

View File

@@ -0,0 +1,125 @@
//! Response types
use http::{
header::{HeaderMap, HeaderValue},
Response,
};
use serde::{
ser::{Error as SerError, SerializeMap},
Serializer,
};
use serde_derive::Serialize;
use crate::body::Body;
/// Representation of a Now Lambda response
#[derive(Serialize, Debug)]
#[serde(rename_all = "camelCase")]
pub(crate) struct NowResponse {
pub status_code: u16,
#[serde(
skip_serializing_if = "HeaderMap::is_empty",
serialize_with = "serialize_headers"
)]
pub headers: HeaderMap<HeaderValue>,
#[serde(skip_serializing_if = "Option::is_none")]
pub body: Option<Body>,
#[serde(skip_serializing_if = "Option::is_none")]
pub encoding: Option<String>,
}
impl Default for NowResponse {
fn default() -> Self {
Self {
status_code: 200,
headers: Default::default(),
body: Default::default(),
encoding: Default::default(),
}
}
}
fn serialize_headers<S>(headers: &HeaderMap<HeaderValue>, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut map = serializer.serialize_map(Some(headers.keys_len()))?;
for key in headers.keys() {
let map_value = headers[key].to_str().map_err(S::Error::custom)?;
map.serialize_entry(key.as_str(), map_value)?;
}
map.end()
}
impl<T> From<Response<T>> for NowResponse
where
T: Into<Body>,
{
fn from(value: Response<T>) -> Self {
let (parts, bod) = value.into_parts();
let (encoding, body) = match bod.into() {
Body::Empty => (None, None),
b @ Body::Text(_) => (None, Some(b)),
b @ Body::Binary(_) => (Some("base64".to_string()), Some(b)),
};
NowResponse {
status_code: parts.status.as_u16(),
body,
headers: parts.headers,
encoding,
}
}
}
/// A conversion of self into a `Response`
///
/// Implementations for `Response<B> where B: Into<Body>`,
/// `B where B: Into<Body>` and `serde_json::Value` are provided
/// by default
///
/// # example
///
/// ```rust
/// use now_lambda::{Body, IntoResponse, Response};
///
/// assert_eq!(
/// "hello".into_response().body(),
/// Response::new(Body::from("hello")).body()
/// );
/// ```
pub trait IntoResponse {
/// Return a translation of `self` into a `Response<Body>`
fn into_response(self) -> Response<Body>;
}
impl<B> IntoResponse for Response<B>
where
B: Into<Body>,
{
fn into_response(self) -> Response<Body> {
let (parts, body) = self.into_parts();
Response::from_parts(parts, body.into())
}
}
impl<B> IntoResponse for B
where
B: Into<Body>,
{
fn into_response(self) -> Response<Body> {
Response::new(self.into())
}
}
impl IntoResponse for serde_json::Value {
fn into_response(self) -> Response<Body> {
Response::builder()
.header(http::header::CONTENT_TYPE, "application/json")
.body(
serde_json::to_string(&self)
.expect("unable to serialize serde_json::Value")
.into(),
)
.expect("unable to build http::Response")
}
}

View File

@@ -0,0 +1,93 @@
use std::{
collections::{hash_map::Keys, HashMap},
fmt,
sync::Arc,
};
use serde::{
de::{MapAccess, Visitor},
Deserialize, Deserializer,
};
/// A read-only view into a map of string data
#[derive(Default, Debug, PartialEq)]
pub struct StrMap(pub(crate) Arc<HashMap<String, String>>);
impl StrMap {
/// Return a named value where available
pub fn get(&self, key: &str) -> Option<&str> {
self.0.get(key).map(|value| value.as_ref())
}
/// Return true if the underlying map is empty
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
/// Return an iterator over keys and values
pub fn iter(&self) -> StrMapIter<'_> {
StrMapIter {
data: self,
keys: self.0.keys(),
}
}
}
impl Clone for StrMap {
fn clone(&self) -> Self {
// only clone the inner data
StrMap(self.0.clone())
}
}
impl From<HashMap<String, String>> for StrMap {
fn from(inner: HashMap<String, String>) -> Self {
StrMap(Arc::new(inner))
}
}
/// A read only reference to `StrMap` key and value slice pairings
pub struct StrMapIter<'a> {
data: &'a StrMap,
keys: Keys<'a, String, String>,
}
impl<'a> Iterator for StrMapIter<'a> {
type Item = (&'a str, &'a str);
#[inline]
fn next(&mut self) -> Option<(&'a str, &'a str)> {
self.keys
.next()
.and_then(|k| self.data.get(k).map(|v| (k.as_str(), v)))
}
}
impl<'de> Deserialize<'de> for StrMap {
fn deserialize<D>(deserializer: D) -> Result<StrMap, D::Error>
where
D: Deserializer<'de>,
{
struct StrMapVisitor;
impl<'de> Visitor<'de> for StrMapVisitor {
type Value = StrMap;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(formatter, "a StrMap")
}
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: MapAccess<'de>,
{
let mut inner = HashMap::new();
while let Some((key, value)) = map.next_entry()? {
inner.insert(key, value);
}
Ok(StrMap(Arc::new(inner)))
}
}
deserializer.deserialize_map(StrMapVisitor)
}
}

View File

@@ -0,0 +1,154 @@
/* global afterAll, beforeAll, describe, expect, it, jest */
const fs = require('fs');
const inferCargoBinaries = require('../inferCargoBinaries');
const { exists, readdir, stat } = fs;
const isDir = fs.Stats.prototype.isDirectory;
beforeAll(() => {
fs.exists = jest.fn((p, cb) => cb(null, false));
});
afterAll(() => {
fs.readdir = readdir;
fs.stat = stat;
fs.Stats.prototype.isDirectory = isDir;
fs.exists = exists;
});
// src/
// |- main.rs
describe('one binary, src/main.rs', async () => {
beforeAll(() => {
fs.readdir = jest.fn((p, cb) => cb(null, ['main.rs']));
});
it('infers only one binary', async () => {
const toml = {
package: {
name: 'foo',
},
};
expect(inferCargoBinaries(toml, '/path/to/src')).resolves.toEqual(['foo']);
});
});
// [[bin]] sections in `Cargo.toml`
// `main.rs` -> `package.name`
// `bar.rs` -> `bin.name`
// src/
// |- bar.rs
// |- main.rs
describe('two binaries, src/main.rs, src/bar.rs', async () => {
beforeAll(() => {
fs.readdir = jest.fn((p, cb) => cb(null, ['main.rs', 'bar.rs']));
});
it('infers two binaries', async () => {
const toml = {
package: {
name: 'foo',
},
bin: [{ name: 'bar', path: 'src/bar.rs' }],
};
expect((await inferCargoBinaries(toml, '/path/to/src')).sort()).toEqual([
'bar',
'foo',
]);
});
});
// no main.rs
// src/
// |- foo.rs
describe('one named binary, no main.rs', async () => {
beforeAll(() => {
fs.readdir = jest.fn((p, cb) => cb(null, ['bar.rs']));
});
it('infers only one binary', async () => {
const toml = {
package: {
name: 'foo',
},
bin: [{ name: 'bar', path: 'src/bar.rs' }],
};
expect((await inferCargoBinaries(toml, '/path/to/src')).sort()).toEqual([
'bar',
]);
});
});
// `src/bin` folder
// src/
// |- bin/
// | |- bar.rs
// | |- baz.rs
// |- main.rs
describe('multiple binaries in bin/, no [[bin]] section', async () => {
beforeAll(() => {
fs.readdir = jest.fn((p, cb) => {
if (p === '/path/to/src') {
return cb(null, ['bin', 'main.rs']);
}
if (p === '/path/to/src/bin') {
return cb(null, ['bar.rs', 'baz.rs']);
}
return cb('some error');
});
fs.exists = jest.fn((p, cb) => cb(null, p.endsWith('bin')));
fs.stat = jest.fn((_, cb) => cb(null, new fs.Stats()));
fs.Stats.prototype.isDirectory = jest.fn(() => true);
});
it('infers three binaries', async () => {
const toml = {
package: {
name: 'foo',
},
};
expect((await inferCargoBinaries(toml, '/path/to/src')).sort()).toEqual([
'bar',
'baz',
'foo',
]);
});
});
// `src/bin` folder, bin sections ignore baz.rs
// src/
// |- bin/
// | |- bar.rs
// | |- baz.rs
// |- main.rs
describe('src/bin exists but one binary is ignored', async () => {
beforeAll(() => {
fs.readdir = jest.fn((p, cb) => {
if (p === '/path/to/src') {
return cb(null, ['bin', 'main.rs']);
}
if (p === '/path/to/src/bin') {
return cb(null, ['bar.rs', 'baz.rs']);
}
return cb('some error');
});
fs.exists = jest.fn((p, cb) => cb(null, p.endsWith('bin')));
fs.stat = jest.fn((_, cb) => cb(null, new fs.Stats()));
fs.Stats.prototype.isDirectory = jest.fn(() => true);
});
it('infers only one binary', async () => {
const toml = {
package: {
name: 'foo',
},
bin: [{ name: 'bar', path: 'src/bar.rs' }],
};
expect((await inferCargoBinaries(toml, '/path/to/src')).sort()).toEqual([
'bar',
'foo',
]);
});
});

View File

@@ -1,11 +1,11 @@
const download = require('@now/build-utils/fs/download.js');
const glob = require('@now/build-utils/fs/glob.js');
const download = require('@now/build-utils/fs/download.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,
runPackageJsonScript,
runShellScript,
} = 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
exports.build = async ({
files, entrypoint, workPath, config,

View File

@@ -1,9 +1,11 @@
{
"name": "@now/static-build",
"version": "0.4.17",
"version": "0.4.18-canary.0",
"license": "MIT",
"peerDependencies": {
"@now/build-utils": ">=0.0.1"
"repository": {
"type": "git",
"url": "https://github.com/zeit/now-builders.git",
"directory": "packages/now-static-build"
},
"scripts": {
"test": "jest"

View File

@@ -1,11 +1,11 @@
const assert = require('assert');
const { createLambda } = require('@now/build-utils/lambda.js');
const { createLambda } = require('@now/build-utils/lambda.js'); // eslint-disable-line import/no-extraneous-dependencies
const fetch = require('node-fetch');
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 { getFiles } = require('@now/php-bridge');
const path = require('path');
const rename = require('@now/build-utils/fs/rename.js');
const streamToBuffer = require('@now/build-utils/fs/stream-to-buffer.js');
const rename = require('@now/build-utils/fs/rename.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
const yauzl = require('yauzl');
exports.config = {
@@ -16,7 +16,9 @@ async function readReleaseUrl(releaseUrl) {
const resp = await fetch(releaseUrl);
if (!resp.ok) {
throw new Error(`Failed to download ${releaseUrl}. Status code is ${resp.status}`);
throw new Error(
`Failed to download ${releaseUrl}. Status code is ${resp.status}`,
);
}
return resp.buffer();
@@ -49,13 +51,15 @@ function decompressBuffer(buffer, mountpoint) {
return;
}
streamToBuffer(readStream).then((data) => {
assert(prefixRegexp.test(fileName), fileName);
const fileName2 = fileName.replace(prefixRegexp, '');
const fileName3 = path.join(mountpoint, fileName2);
files[fileName3] = new FileBlob({ data });
zipfile.readEntry();
}).catch(reject);
streamToBuffer(readStream)
.then((data) => {
assert(prefixRegexp.test(fileName), fileName);
const fileName2 = fileName.replace(prefixRegexp, '');
const fileName3 = path.join(mountpoint, fileName2);
files[fileName3] = new FileBlob({ data });
zipfile.readEntry();
})
.catch(reject);
});
});
@@ -65,12 +69,22 @@ function decompressBuffer(buffer, mountpoint) {
}
const staticRegexps = [
/\.css$/, /\.gif$/, /\.ico$/, /\.js$/, /\.jpg$/, /\.png$/, /\.svg$/, /\.woff$/, /\.woff2$/,
/\.css$/,
/\.gif$/,
/\.ico$/,
/\.js$/,
/\.jpg$/,
/\.png$/,
/\.svg$/,
/\.woff$/,
/\.woff2$/,
];
exports.build = async ({ files, entrypoint, config }) => {
if (path.basename(entrypoint) !== 'wp-config.php') {
throw new Error(`Entrypoint file name must be "wp-config.php". Currently it is ${entrypoint}`);
throw new Error(
`Entrypoint file name must be "wp-config.php". Currently it is ${entrypoint}`,
);
}
const { releaseUrl = 'https://wordpress.org/latest.zip' } = config;
@@ -84,9 +98,12 @@ exports.build = async ({ files, entrypoint, config }) => {
if (config.patchForPersistentConnections) {
const wpDbPhp = path.join(mountpoint, 'wp-includes/wp-db.php');
const wpDbPhpBlob = mergedFiles[wpDbPhp];
wpDbPhpBlob.data = wpDbPhpBlob.data.toString()
.replace(/mysqli_real_connect\( \$this->dbh, \$host,/g,
'mysqli_real_connect( $this->dbh, \'p:\' . $host,');
wpDbPhpBlob.data = wpDbPhpBlob.data
.toString()
.replace(
/mysqli_real_connect\( \$this->dbh, \$host,/g,
"mysqli_real_connect( $this->dbh, 'p:' . $host,",
);
}
const staticFiles = {};

View File

@@ -1,15 +1,17 @@
{
"name": "@now/wordpress",
"version": "0.4.14",
"version": "0.4.15-canary.0",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/zeit/now-builders.git",
"directory": "packages/now-wordpress"
},
"dependencies": {
"@now/php-bridge": "^0.4.13",
"@now/php-bridge": "^0.4.14-canary.0",
"node-fetch": "2.3.0",
"yauzl": "2.10.0"
},
"peerDependencies": {
"@now/build-utils": ">=0.0.1"
},
"scripts": {
"test": "jest"
}

View File

@@ -22,7 +22,7 @@ async function packAndDeploy (builderPath) {
const RANDOMNESS_PLACEHOLDER_STRING = 'RANDOMNESS_PLACEHOLDER';
async function testDeployment ({ builderUrl, buildUtilsUrl }, fixturePath) {
async function testDeployment ({ builderUrl, buildUtilsUrl }, fixturePath, buildDelegate) {
console.log('testDeployment', fixturePath);
const globResult = await glob(`${fixturePath}/**`, { nodir: true });
const bodies = globResult.reduce((b, f) => {
@@ -63,6 +63,10 @@ async function testDeployment ({ builderUrl, buildUtilsUrl }, fixturePath) {
config.useBuildUtils = `https://${buildUtilsUrl}`;
}
}
if (buildDelegate) {
buildDelegate(build);
}
}
bodies['now.json'] = Buffer.from(JSON.stringify(nowJson));
@@ -84,7 +88,8 @@ async function testDeployment ({ builderUrl, buildUtilsUrl }, fixturePath) {
if (!text.includes(probe.mustContain)) {
await fs.writeFile(path.join(__dirname, 'failed-page.txt'), text);
throw new Error(
`Fetched page ${probeUrl} does not contain ${probe.mustContain}`
`Fetched page ${probeUrl} does not contain ${probe.mustContain}.`
+ ` Instead it contains ${text.slice(0, 60)}`
);
}
} else {
@@ -113,7 +118,8 @@ async function fetchDeploymentUrl (url, opts) {
for (let i = 0; i < 500; i += 1) {
const resp = await fetch(url, opts);
const text = await resp.text();
if (text && !text.includes('Join Free')) {
if (text && !text.includes('Join Free')
&& !text.includes('The page could not be found')) {
return text;
}

View File

@@ -8,7 +8,7 @@ const {
excludeStaticDirectory,
onlyStaticDirectory,
} = require('@now/next/utils');
const FileRef = require('@now/build-utils/file-ref');
const FileRef = require('@now/build-utils/file-ref'); // eslint-disable-line import/no-extraneous-dependencies
describe('excludeFiles', () => {
it('should exclude files', () => {

View File

@@ -1780,6 +1780,16 @@ concat-stream@^1.4.6, concat-stream@^1.4.7, concat-stream@^1.5.0, concat-stream@
readable-stream "^2.2.2"
typedarray "^0.0.6"
concat-stream@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-2.0.0.tgz#414cf5af790a48c60ab9be4527d56d5e41133cb1"
integrity sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==
dependencies:
buffer-from "^1.0.0"
inherits "^2.0.3"
readable-stream "^3.0.2"
typedarray "^0.0.6"
config-chain@^1.1.11:
version "1.1.12"
resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.12.tgz#0fde8d091200eb5e808caf25fe618c02f48e4efa"
@@ -6741,6 +6751,15 @@ read@1, read@~1.0.1:
isarray "0.0.1"
string_decoder "~0.10.x"
readable-stream@^3.0.2:
version "3.1.1"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.1.1.tgz#ed6bbc6c5ba58b090039ff18ce670515795aeb06"
integrity sha512-DkN66hPyqDhnIQ6Jcsvx9bFjhw214O4poMBcIMgPVpQvNy9a0e0Uhg5SqySyDKAmUlwt8LonTBz1ezOnM8pUdA==
dependencies:
inherits "^2.0.3"
string_decoder "^1.1.1"
util-deprecate "^1.0.1"
readable-stream@~1.1.9:
version "1.1.14"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9"
@@ -7046,6 +7065,13 @@ rimraf@2, rimraf@^2.2.6, rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.
dependencies:
glob "^7.0.5"
rimraf@^2.6.3:
version "2.6.3"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab"
integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==
dependencies:
glob "^7.1.3"
rmfr@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/rmfr/-/rmfr-2.0.0.tgz#8a42e81332550b3f0019b8fb8ab245bea81b6d1c"
@@ -7539,6 +7565,13 @@ string-width@^1.0.1:
is-fullwidth-code-point "^2.0.0"
strip-ansi "^4.0.0"
string_decoder@^1.1.1:
version "1.2.0"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.2.0.tgz#fe86e738b19544afe70469243b2a1ee9240eae8d"
integrity sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w==
dependencies:
safe-buffer "~5.1.0"
string_decoder@~0.10.x:
version "0.10.31"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
@@ -7746,7 +7779,7 @@ tar@^2.0.0:
fstream "^1.0.2"
inherits "2"
tar@^4, tar@^4.4.6:
tar@^4, tar@^4.4.6, tar@^4.4.8:
version "4.4.8"
resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.8.tgz#b19eec3fde2a96e64666df9fdb40c5ca1bc3747d"
integrity sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ==
@@ -7903,6 +7936,11 @@ to-regex@^3.0.1, to-regex@^3.0.2:
regex-not "^1.0.2"
safe-regex "^1.1.0"
toml@^2.3.3:
version "2.3.6"
resolved "https://registry.yarnpkg.com/toml/-/toml-2.3.6.tgz#25b0866483a9722474895559088b436fd11f861b"
integrity sha512-gVweAectJU3ebq//Ferr2JUY4WKSDe5N+z0FvjDncLGyHmIDoxgY/2Ie4qfEIDm4IS7OA6Rmdm7pdEEdMcV/xQ==
tough-cookie@>=2.3.3, tough-cookie@^2.3.4:
version "2.5.0"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
@@ -8198,7 +8236,7 @@ use@^3.1.0:
resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f"
integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==
util-deprecate@~1.0.1:
util-deprecate@^1.0.1, util-deprecate@~1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=