mirror of
https://github.com/LukeHagar/vercel.git
synced 2025-12-11 04:22:13 +00:00
Compare commits
27 Commits
@now/build
...
@now/php@0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e2f91094bc | ||
|
|
38dba57378 | ||
|
|
be6a6ba1d7 | ||
|
|
31fb5d9ec8 | ||
|
|
6c8f946a48 | ||
|
|
d59e1b9789 | ||
|
|
2852d3fbc3 | ||
|
|
d0292eb751 | ||
|
|
17bbf69346 | ||
|
|
4fb4229c90 | ||
|
|
03b7586b50 | ||
|
|
a1427866ca | ||
|
|
5f787b8146 | ||
|
|
b03405a665 | ||
|
|
4393dad15a | ||
|
|
b4d604b2e9 | ||
|
|
5fb6e5c0ba | ||
|
|
9d7dd3a713 | ||
|
|
4f867b320d | ||
|
|
c153690104 | ||
|
|
8c1b96edf7 | ||
|
|
15c83a69f7 | ||
|
|
0986de85ee | ||
|
|
94c5d83ccc | ||
|
|
ff49b9d32d | ||
|
|
ec5290dab1 | ||
|
|
4f758ec84e |
74
CODE_OF_CONDUCT.md
Normal file
74
CODE_OF_CONDUCT.md
Normal file
@@ -0,0 +1,74 @@
|
||||
## Code of Conduct
|
||||
|
||||
### Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as
|
||||
contributors and maintainers pledge to making participation in our project and
|
||||
our community a harassment-free experience for everyone, regardless of age, body
|
||||
size, disability, ethnicity, gender identity and expression, level of experience,
|
||||
nationality, personal appearance, race, religion, or sexual identity and
|
||||
orientation.
|
||||
|
||||
### Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment
|
||||
include:
|
||||
|
||||
- Using welcoming and inclusive language
|
||||
- Being respectful of differing viewpoints and experiences
|
||||
- Gracefully accepting constructive criticism
|
||||
- Focusing on what is best for the community
|
||||
- Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
- The use of sexualized language or imagery and unwelcome sexual attention or
|
||||
advances
|
||||
- Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
- Public or private harassment
|
||||
- Publishing others' private information, such as a physical or electronic
|
||||
address, without explicit permission
|
||||
- Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
### Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable
|
||||
behavior and are expected to take appropriate and fair corrective action in
|
||||
response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or
|
||||
reject comments, commits, code, wiki edits, issues, and other contributions
|
||||
that are not aligned to this Code of Conduct, or to ban temporarily or
|
||||
permanently any contributor for other behaviors that they deem inappropriate,
|
||||
threatening, offensive, or harmful.
|
||||
|
||||
### Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces
|
||||
when an individual is representing the project or its community. Examples of
|
||||
representing a project or community include using an official project e-mail
|
||||
address, posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event. Representation of a project may be
|
||||
further defined and clarified by project maintainers.
|
||||
|
||||
### Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported by contacting the project team at [abuse@zeit.co](mailto:abuse@zeit.co). All
|
||||
complaints will be reviewed and investigated and will result in a response that
|
||||
is deemed necessary and appropriate to the circumstances. The project team is
|
||||
obligated to maintain confidentiality with regard to the reporter of an incident.
|
||||
Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good
|
||||
faith may face temporary or permanent repercussions as determined by other
|
||||
members of the project's leadership.
|
||||
|
||||
### Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
||||
available at [http://contributor-covenant.org/version/1/4][version]
|
||||
|
||||
[homepage]: http://contributor-covenant.org
|
||||
[version]: http://contributor-covenant.org/version/1/4/
|
||||
@@ -1,10 +1,13 @@
|
||||
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
|
||||
const {
|
||||
glob,
|
||||
download,
|
||||
createLambda,
|
||||
getWriteableDirectory,
|
||||
shouldServe,
|
||||
} = require('@now/build-utils'); // eslint-disable-line import/no-extraneous-dependencies
|
||||
|
||||
exports.config = {
|
||||
maxLambdaSize: '10mb',
|
||||
@@ -15,7 +18,7 @@ exports.analyze = ({ files, entrypoint }) => files[entrypoint].digest;
|
||||
exports.build = async ({
|
||||
workPath, files, entrypoint, config,
|
||||
}) => {
|
||||
const srcDir = await getWritableDirectory();
|
||||
const srcDir = await getWriteableDirectory();
|
||||
|
||||
console.log('downloading files...');
|
||||
await download(files, srcDir);
|
||||
@@ -55,3 +58,5 @@ exports.build = async ({
|
||||
[entrypoint]: lambda,
|
||||
};
|
||||
};
|
||||
|
||||
exports.shouldServe = shouldServe;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@now/bash",
|
||||
"version": "0.2.0",
|
||||
"version": "0.2.3",
|
||||
"description": "Now 2.0 builder for HTTP endpoints written in Bash",
|
||||
"main": "index.js",
|
||||
"author": "Nathan Rajlich <nate@zeit.co>",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@now/build-utils",
|
||||
"version": "0.5.1",
|
||||
"version": "0.5.4",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.js",
|
||||
@@ -10,8 +10,10 @@
|
||||
"directory": "packages/now-build-utils"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/cross-spawn": "6.0.0",
|
||||
"async-retry": "1.2.3",
|
||||
"async-sema": "2.1.4",
|
||||
"cross-spawn": "6.0.5",
|
||||
"end-of-stream": "1.4.1",
|
||||
"fs-extra": "7.0.0",
|
||||
"glob": "7.1.3",
|
||||
|
||||
@@ -8,7 +8,6 @@ import { File } from './types';
|
||||
interface FileRefOptions {
|
||||
mode?: number;
|
||||
digest: string;
|
||||
mutable?: boolean;
|
||||
}
|
||||
|
||||
const semaToDownloadFromS3 = new Sema(5);
|
||||
@@ -26,26 +25,29 @@ export default class FileRef implements File {
|
||||
public type: 'FileRef';
|
||||
public mode: number;
|
||||
public digest: string;
|
||||
public mutable: boolean;
|
||||
|
||||
constructor({ mode = 0o100644, digest, mutable = false }: FileRefOptions) {
|
||||
constructor({ mode = 0o100644, digest }: FileRefOptions) {
|
||||
assert(typeof mode === 'number');
|
||||
assert(typeof digest === 'string');
|
||||
assert(typeof mutable === 'boolean');
|
||||
this.type = 'FileRef';
|
||||
this.mode = mode;
|
||||
this.digest = digest;
|
||||
this.mutable = mutable;
|
||||
}
|
||||
|
||||
async toStreamAsync(): Promise<NodeJS.ReadableStream> {
|
||||
let url = '';
|
||||
// sha:24be087eef9fac01d61b30a725c1a10d7b45a256
|
||||
const digestParts = this.digest.split(':');
|
||||
if (digestParts[0] === 'sha') {
|
||||
url = this.mutable
|
||||
? `https://s3.amazonaws.com/now-files/${digestParts[1]}`
|
||||
: `https://dmmcy0pwk6bqi.cloudfront.net/${digestParts[1]}`;
|
||||
const [digestType, digestHash] = this.digest.split(':');
|
||||
if (digestType === 'sha') {
|
||||
// This CloudFront URL edge caches the `now-files` S3 bucket to prevent
|
||||
// overloading it
|
||||
// `https://now-files.s3.amazonaws.com/${digestHash}`
|
||||
url = `https://dmmcy0pwk6bqi.cloudfront.net/${digestHash}`;
|
||||
} else if (digestType === 'sha+ephemeral') {
|
||||
// This URL is currently only used for cache files that constantly
|
||||
// change. We shouldn't cache it on CloudFront because it'd always be a
|
||||
// MISS.
|
||||
url = `https://now-ephemeral-files.s3.amazonaws.com/${digestHash}`;
|
||||
} else {
|
||||
throw new Error('Expected digest to be sha');
|
||||
}
|
||||
@@ -58,14 +60,14 @@ export default class FileRef implements File {
|
||||
const resp = await fetch(url);
|
||||
if (!resp.ok) {
|
||||
const error = new BailableError(
|
||||
`download: ${resp.status} ${resp.statusText} for ${url}`,
|
||||
`download: ${resp.status} ${resp.statusText} for ${url}`
|
||||
);
|
||||
if (resp.status === 403) error.bail = true;
|
||||
throw error;
|
||||
}
|
||||
return resp.body;
|
||||
},
|
||||
{ factor: 1, retries: 3 },
|
||||
{ factor: 1, retries: 3 }
|
||||
);
|
||||
} finally {
|
||||
// console.timeEnd(`downloading ${url}`);
|
||||
@@ -77,15 +79,15 @@ export default class FileRef implements File {
|
||||
let flag = false;
|
||||
|
||||
// eslint-disable-next-line consistent-return
|
||||
return multiStream((cb) => {
|
||||
return multiStream(cb => {
|
||||
if (flag) return cb(null, null);
|
||||
flag = true;
|
||||
|
||||
this.toStreamAsync()
|
||||
.then((stream) => {
|
||||
.then(stream => {
|
||||
cb(null, stream);
|
||||
})
|
||||
.catch((error) => {
|
||||
.catch(error => {
|
||||
cb(error, null);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,22 +1,28 @@
|
||||
import assert from 'assert';
|
||||
import fs from 'fs-extra';
|
||||
import path from 'path';
|
||||
import { spawn, SpawnOptions } from 'child_process';
|
||||
import spawn from 'cross-spawn';
|
||||
import { SpawnOptions } from 'child_process';
|
||||
|
||||
function spawnAsync(command: string, args: string[], cwd: string, opts: SpawnOptions = {}) {
|
||||
function spawnAsync(
|
||||
command: string,
|
||||
args: string[],
|
||||
cwd: string,
|
||||
opts: SpawnOptions = {}
|
||||
) {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
const stderrLogs: Buffer[] = []
|
||||
const stderrLogs: Buffer[] = [];
|
||||
opts = { stdio: 'inherit', cwd, ...opts };
|
||||
const child = spawn(command, args, opts);
|
||||
|
||||
if (opts.stdio === 'pipe'){
|
||||
if (opts.stdio === 'pipe') {
|
||||
child.stderr.on('data', data => stderrLogs.push(data));
|
||||
}
|
||||
|
||||
child.on('error', reject);
|
||||
child.on('close', (code, signal) => {
|
||||
if (code === 0) {
|
||||
return resolve()
|
||||
return resolve();
|
||||
}
|
||||
|
||||
const errorLogs = stderrLogs.map(line => line.toString()).join('');
|
||||
@@ -58,13 +64,15 @@ async function scanParentDirs(destPath: string, scriptName?: string) {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
if (await fs.pathExists(packageJsonPath)) {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf8'));
|
||||
const packageJson = JSON.parse(
|
||||
await fs.readFile(packageJsonPath, 'utf8')
|
||||
);
|
||||
hasScript = Boolean(
|
||||
packageJson.scripts && scriptName && packageJson.scripts[scriptName],
|
||||
packageJson.scripts && scriptName && packageJson.scripts[scriptName]
|
||||
);
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
hasPackageLockJson = await fs.pathExists(
|
||||
path.join(currentDestPath, 'package-lock.json'),
|
||||
path.join(currentDestPath, 'package-lock.json')
|
||||
);
|
||||
break;
|
||||
}
|
||||
@@ -77,7 +85,10 @@ async function scanParentDirs(destPath: string, scriptName?: string) {
|
||||
return { hasScript, hasPackageLockJson };
|
||||
}
|
||||
|
||||
export async function installDependencies(destPath: string, args: string[] = []) {
|
||||
export async function installDependencies(
|
||||
destPath: string,
|
||||
args: string[] = []
|
||||
) {
|
||||
assert(path.isAbsolute(destPath));
|
||||
|
||||
let commandArgs = args;
|
||||
@@ -91,7 +102,7 @@ export async function installDependencies(destPath: string, args: string[] = [])
|
||||
// Node.js version that `@now/node` and `@now/node-server` use
|
||||
npm_config_target: '8.10.0',
|
||||
},
|
||||
stdio: 'pipe'
|
||||
stdio: 'pipe',
|
||||
};
|
||||
|
||||
if (hasPackageLockJson) {
|
||||
@@ -105,9 +116,9 @@ export async function installDependencies(destPath: string, args: string[] = [])
|
||||
} else {
|
||||
await spawnAsync(
|
||||
'yarn',
|
||||
['--cwd', destPath].concat(commandArgs),
|
||||
['--ignore-engines', '--cwd', destPath].concat(commandArgs),
|
||||
destPath,
|
||||
opts as SpawnOptions,
|
||||
opts as SpawnOptions
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -120,7 +131,7 @@ export async function runPackageJsonScript(
|
||||
assert(path.isAbsolute(destPath));
|
||||
const { hasScript, hasPackageLockJson } = await scanParentDirs(
|
||||
destPath,
|
||||
scriptName,
|
||||
scriptName
|
||||
);
|
||||
if (!hasScript) return false;
|
||||
|
||||
@@ -129,7 +140,12 @@ export async function runPackageJsonScript(
|
||||
await spawnAsync('npm', ['run', scriptName], destPath, opts);
|
||||
} else {
|
||||
console.log(`running "yarn run ${scriptName}"`);
|
||||
await spawnAsync('yarn', ['--cwd', destPath, 'run', scriptName], destPath, opts);
|
||||
await spawnAsync(
|
||||
'yarn',
|
||||
['--cwd', destPath, 'run', scriptName],
|
||||
destPath,
|
||||
opts
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
9
packages/now-build-utils/test/fixtures/15-yarn-ignore-engines/index.js
vendored
Normal file
9
packages/now-build-utils/test/fixtures/15-yarn-ignore-engines/index.js
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
const scheduler = require('@google-cloud/scheduler');
|
||||
|
||||
module.exports = (_, res) => {
|
||||
if (scheduler) {
|
||||
res.end('found:RANDOMNESS_PLACEHOLDER');
|
||||
} else {
|
||||
res.end('nope:RANDOMNESS_PLACEHOLDER');
|
||||
}
|
||||
};
|
||||
10
packages/now-build-utils/test/fixtures/15-yarn-ignore-engines/now.json
vendored
Normal file
10
packages/now-build-utils/test/fixtures/15-yarn-ignore-engines/now.json
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"version": 2,
|
||||
"builds": [
|
||||
{ "src": "index.js", "use": "@now/node", "config": { "maxLambdaSize": "15mb" } }
|
||||
],
|
||||
"probes": [
|
||||
{ "path": "/", "mustContain": "found:RANDOMNESS_PLACEHOLDER" }
|
||||
]
|
||||
}
|
||||
|
||||
8
packages/now-build-utils/test/fixtures/15-yarn-ignore-engines/package.json
vendored
Normal file
8
packages/now-build-utils/test/fixtures/15-yarn-ignore-engines/package.json
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "15-yarn-ignore-engines",
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"dependencies": {
|
||||
"@google-cloud/scheduler": "0.3.0"
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ const glob = require('@now/build-utils/fs/glob'); // eslint-disable-line import/
|
||||
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
|
||||
const { shouldServe } = require('@now/build-utils'); // eslint-disable-line import/no-extraneous-dependencies
|
||||
|
||||
exports.analyze = ({ files, entrypoint }) => files[entrypoint].digest;
|
||||
|
||||
@@ -40,3 +41,5 @@ exports.build = async ({ files, entrypoint }) => {
|
||||
[entrypoint]: lambda,
|
||||
};
|
||||
};
|
||||
|
||||
exports.shouldServe = shouldServe;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@now/cgi",
|
||||
"version": "0.1.0",
|
||||
"version": "0.1.3",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -3,6 +3,7 @@ import execa from 'execa';
|
||||
import fetch from 'node-fetch';
|
||||
import { mkdirp, pathExists } from 'fs-extra';
|
||||
import { dirname, join } from 'path';
|
||||
import { homedir } from 'os';
|
||||
import Debug from 'debug';
|
||||
|
||||
const debug = Debug('@now/go:go-helpers');
|
||||
@@ -118,16 +119,25 @@ export async function downloadGo(
|
||||
platform = process.platform,
|
||||
arch = process.arch
|
||||
) {
|
||||
debug('Installing `go` v%s to %o for %s %s', version, dir, platform, arch);
|
||||
// Check default `Go` in user machine
|
||||
const isUserGo = await pathExists(join(homedir(), 'go'));
|
||||
|
||||
const url = getGoUrl(version, platform, arch);
|
||||
|
||||
// if we found GOPATH in ENV, use it
|
||||
if (process.env.GOPATH !== undefined) {
|
||||
// If we found GOPATH in ENV, or default `Go` path exists
|
||||
// asssume that user have `Go` installed
|
||||
if (isUserGo || process.env.GOPATH !== undefined) {
|
||||
return createGo(dir, platform, arch);
|
||||
} else {
|
||||
// Check `Go` bin in builder CWD
|
||||
const isGoExist = await pathExists(join(dir, 'bin'));
|
||||
if (!isGoExist) {
|
||||
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);
|
||||
console.log('Downloading Go ...');
|
||||
const res = await fetch(url);
|
||||
|
||||
@@ -47,6 +47,7 @@ export async function build({
|
||||
getWriteableDirectory(),
|
||||
getWriteableDirectory(),
|
||||
]);
|
||||
|
||||
if (meta.isDev) {
|
||||
const devGoPath = `dev${entrypointArr[entrypointArr.length - 1]}`;
|
||||
const goPathArr = goPath.split(sep);
|
||||
@@ -57,6 +58,17 @@ export async function build({
|
||||
|
||||
const srcPath = join(goPath, 'src', 'lambda');
|
||||
const downloadedFiles = await download(files, srcPath);
|
||||
const input = dirname(downloadedFiles[entrypoint].fsPath);
|
||||
var includedFiles: Files = {};
|
||||
|
||||
if (config && config.includeFiles) {
|
||||
for (const pattern of config.includeFiles) {
|
||||
const files = await glob(pattern, input);
|
||||
for (const assetName of Object.keys(files)) {
|
||||
includedFiles[assetName] = files[assetName];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`Parsing AST for "${entrypoint}"`);
|
||||
let analyzed: string;
|
||||
@@ -264,7 +276,7 @@ export async function build({
|
||||
}
|
||||
|
||||
const lambda = await createLambda({
|
||||
files: await glob('**', outDir),
|
||||
files: { ...(await glob('**', outDir)), ...includedFiles },
|
||||
handler: 'handler',
|
||||
runtime: 'go1.x',
|
||||
environment: {},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@now/go",
|
||||
"version": "0.4.2",
|
||||
"version": "0.4.5",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
16
packages/now-go/test/fixtures/08-include-files/index.go
vendored
Normal file
16
packages/now-go/test/fixtures/08-include-files/index.go
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
package cowsay
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// Handler function
|
||||
func Handler(w http.ResponseWriter, r *http.Request) {
|
||||
bts, err := ioutil.ReadFile("templates/foo.txt")
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
fmt.Fprintf(w, string(bts))
|
||||
}
|
||||
20
packages/now-go/test/fixtures/08-include-files/now.json
vendored
Normal file
20
packages/now-go/test/fixtures/08-include-files/now.json
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"version": 2,
|
||||
"builds": [
|
||||
{
|
||||
"src": "index.go",
|
||||
"use": "@now/go",
|
||||
"config": {
|
||||
"includeFiles": [
|
||||
"templates/**"
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"probes": [
|
||||
{
|
||||
"path": "/",
|
||||
"mustContain": "foobar from file"
|
||||
}
|
||||
]
|
||||
}
|
||||
1
packages/now-go/test/fixtures/08-include-files/templates/foo.txt
vendored
Normal file
1
packages/now-go/test/fixtures/08-include-files/templates/foo.txt
vendored
Normal file
@@ -0,0 +1 @@
|
||||
foobar from file
|
||||
@@ -1,4 +1,4 @@
|
||||
const FileBlob = require('@now/build-utils/file-blob.js'); // eslint-disable-line import/no-extraneous-dependencies
|
||||
const { FileBlob, shouldServe } = require('@now/build-utils'); // eslint-disable-line import/no-extraneous-dependencies
|
||||
const { minify } = require('html-minifier');
|
||||
|
||||
const defaultOptions = {
|
||||
@@ -28,3 +28,5 @@ exports.build = async ({ files, entrypoint, config }) => {
|
||||
|
||||
return { [entrypoint]: result };
|
||||
};
|
||||
|
||||
exports.shouldServe = shouldServe;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@now/html-minifier",
|
||||
"version": "1.1.0",
|
||||
"version": "1.1.3",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
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
|
||||
const { shouldServe } = require('@now/build-utils'); // eslint-disable-line import/no-extraneous-dependencies
|
||||
|
||||
exports.build = async ({ files, entrypoint, config }) => {
|
||||
if (!files[entrypoint]) throw new Error('Entrypoint not found in files');
|
||||
@@ -10,3 +11,5 @@ exports.build = async ({ files, entrypoint, config }) => {
|
||||
const lambda = new Lambda({ zipBuffer, handler, runtime });
|
||||
return { [entrypoint]: lambda };
|
||||
};
|
||||
|
||||
exports.shouldServe = shouldServe;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@now/lambda",
|
||||
"version": "0.5.0",
|
||||
"version": "0.5.3",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const FileBlob = require('@now/build-utils/file-blob.js'); // eslint-disable-line import/no-extraneous-dependencies
|
||||
const { FileBlob, shouldServe } = require('@now/build-utils'); // eslint-disable-line import/no-extraneous-dependencies
|
||||
const unified = require('unified');
|
||||
const unifiedStream = require('unified-stream');
|
||||
const markdown = require('remark-parse');
|
||||
@@ -38,3 +38,5 @@ exports.build = async ({ files, entrypoint, config }) => {
|
||||
|
||||
return { [replacedEntrypoint]: result };
|
||||
};
|
||||
|
||||
exports.shouldServe = shouldServe;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@now/md",
|
||||
"version": "0.5.0",
|
||||
"version": "0.5.3",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@now/mdx-deck",
|
||||
"version": "0.5.0",
|
||||
"version": "0.5.3",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@now/next",
|
||||
"version": "0.2.0",
|
||||
"version": "0.3.1",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index",
|
||||
"scripts": {
|
||||
@@ -14,7 +14,7 @@
|
||||
"directory": "packages/now-next"
|
||||
},
|
||||
"dependencies": {
|
||||
"@now/node-bridge": "^1.1.0",
|
||||
"@now/node-bridge": "^1.1.2",
|
||||
"fs-extra": "^7.0.0",
|
||||
"get-port": "^5.0.0",
|
||||
"resolve-from": "^5.0.0",
|
||||
|
||||
@@ -2,18 +2,21 @@ import resolveFrom from 'resolve-from';
|
||||
import { parse } from 'url';
|
||||
import getPort from 'get-port';
|
||||
import { createServer } from 'http';
|
||||
import { syncEnvVars } from './utils';
|
||||
|
||||
export interface ProcessEnv {
|
||||
[key: string]: string;
|
||||
}
|
||||
process.on('unhandledRejection', err => {
|
||||
console.error('Exiting builder due to build error:');
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
async function main(env: ProcessEnv, cwd: string) {
|
||||
async function main(cwd: string) {
|
||||
const next = require(resolveFrom(cwd, 'next'));
|
||||
const app = next({ dev: true, dir: cwd });
|
||||
const handler = app.getRequestHandler();
|
||||
|
||||
const openPort = await getPort({
|
||||
port: [ 5000, 4000 ]
|
||||
port: [5000, 4000],
|
||||
});
|
||||
|
||||
const url = `http://localhost:${openPort}`;
|
||||
@@ -21,21 +24,21 @@ async function main(env: ProcessEnv, cwd: string) {
|
||||
// Prepare for incoming requests
|
||||
await app.prepare();
|
||||
|
||||
// The runtime env vars are passed in to `argv[2]`
|
||||
// as a base64-encoded JSON string
|
||||
const runtimeEnv = JSON.parse(
|
||||
Buffer.from(process.argv[2], 'base64').toString()
|
||||
);
|
||||
syncEnvVars(process.env, process.env, runtimeEnv);
|
||||
|
||||
createServer((req, res) => {
|
||||
const parsedUrl = parse(req.url || '', true);
|
||||
handler(req, res, parsedUrl);
|
||||
}).listen(openPort, (error: NodeJS.ErrnoException) => {
|
||||
if (error) {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
}).listen(openPort, () => {
|
||||
if (process.send) {
|
||||
process.send(url);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
main(process.env as ProcessEnv, process.cwd());
|
||||
main(process.cwd());
|
||||
|
||||
@@ -25,6 +25,7 @@ import {
|
||||
|
||||
import nextLegacyVersions from './legacy-versions';
|
||||
import {
|
||||
EnvConfig,
|
||||
excludeFiles,
|
||||
getNextConfig,
|
||||
getPathsInside,
|
||||
@@ -33,11 +34,14 @@ import {
|
||||
normalizePackageJson,
|
||||
onlyStaticDirectory,
|
||||
stringMap,
|
||||
syncEnvVars,
|
||||
validateEntrypoint,
|
||||
} from './utils';
|
||||
|
||||
interface BuildParamsMeta {
|
||||
isDev: boolean | undefined;
|
||||
env?: EnvConfig;
|
||||
buildEnv?: EnvConfig;
|
||||
}
|
||||
|
||||
interface BuildParamsType extends BuildOptions {
|
||||
@@ -119,13 +123,17 @@ function isLegacyNext(nextVersion: string) {
|
||||
const name = '[@now/next]';
|
||||
const urls: stringMap = {};
|
||||
|
||||
function startDevServer(entryPath: string) {
|
||||
const forked = fork(path.join(__dirname, 'dev-server.js'), [], {
|
||||
function startDevServer(entryPath: string, runtimeEnv: EnvConfig) {
|
||||
// The runtime env vars are encoded and passed in as `argv[2]`, so that the
|
||||
// dev-server process can replace them onto `process.env` after the Next.js
|
||||
// "prepare" step
|
||||
const encodedEnv = Buffer.from(JSON.stringify(runtimeEnv)).toString('base64');
|
||||
|
||||
// `env` is omitted since that
|
||||
// makes it default to `process.env`
|
||||
const forked = fork(path.join(__dirname, 'dev-server.js'), [encodedEnv], {
|
||||
cwd: entryPath,
|
||||
execArgv: [],
|
||||
env: {
|
||||
NOW_REGION: 'dev1',
|
||||
},
|
||||
});
|
||||
|
||||
const getUrl = () =>
|
||||
@@ -182,7 +190,13 @@ export const build = async ({
|
||||
if (!urls[entrypoint]) {
|
||||
console.log(`${name} Installing dependencies...`);
|
||||
await runNpmInstall(entryPath, ['--prefer-offline']);
|
||||
const { forked, getUrl } = startDevServer(entryPath);
|
||||
|
||||
// The runtime env vars consist of the base `process.env` vars, but with the
|
||||
// build env vars removed, and the runtime env vars mixed in afterwards
|
||||
const runtimeEnv: EnvConfig = Object.assign({}, process.env);
|
||||
syncEnvVars(runtimeEnv, meta.buildEnv || {}, meta.env || {});
|
||||
|
||||
const { forked, getUrl } = startDevServer(entryPath, runtimeEnv);
|
||||
urls[entrypoint] = await getUrl();
|
||||
childProcess = forked;
|
||||
console.log(
|
||||
|
||||
@@ -2,18 +2,22 @@ import fs from 'fs-extra';
|
||||
import path from 'path';
|
||||
import { Files } from '@now/build-utils';
|
||||
|
||||
type stringMap = {[key: string]: string};
|
||||
type stringMap = { [key: string]: string };
|
||||
|
||||
export interface EnvConfig {
|
||||
[name: string]: string | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate if the entrypoint is allowed to be used
|
||||
*/
|
||||
function validateEntrypoint(entrypoint: string) {
|
||||
if (
|
||||
!/package\.json$/.exec(entrypoint)
|
||||
&& !/next\.config\.js$/.exec(entrypoint)
|
||||
!/package\.json$/.exec(entrypoint) &&
|
||||
!/next\.config\.js$/.exec(entrypoint)
|
||||
) {
|
||||
throw new Error(
|
||||
'Specified "src" for "@now/next" has to be "package.json" or "next.config.js"',
|
||||
'Specified "src" for "@now/next" has to be "package.json" or "next.config.js"'
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -21,7 +25,10 @@ function validateEntrypoint(entrypoint: string) {
|
||||
/**
|
||||
* Exclude certain files from the files object
|
||||
*/
|
||||
function excludeFiles(files: Files, matcher: (filePath: string) => boolean): Files {
|
||||
function excludeFiles(
|
||||
files: Files,
|
||||
matcher: (filePath: string) => boolean
|
||||
): Files {
|
||||
return Object.keys(files).reduce((newFiles, filePath) => {
|
||||
if (matcher(filePath)) {
|
||||
return newFiles;
|
||||
@@ -36,7 +43,10 @@ function excludeFiles(files: Files, matcher: (filePath: string) => boolean): Fil
|
||||
/**
|
||||
* Creates a new Files object holding only the entrypoint files
|
||||
*/
|
||||
function includeOnlyEntryDirectory(files: Files, entryDirectory: string): Files {
|
||||
function includeOnlyEntryDirectory(
|
||||
files: Files,
|
||||
entryDirectory: string
|
||||
): Files {
|
||||
if (entryDirectory === '.') {
|
||||
return files;
|
||||
}
|
||||
@@ -76,7 +86,13 @@ function onlyStaticDirectory(files: Files, entryDir: string): Files {
|
||||
/**
|
||||
* Enforce specific package.json configuration for smallest possible lambda
|
||||
*/
|
||||
function normalizePackageJson(defaultPackageJson: {dependencies?: stringMap, devDependencies?: stringMap, scripts?: stringMap} = {}) {
|
||||
function normalizePackageJson(
|
||||
defaultPackageJson: {
|
||||
dependencies?: stringMap;
|
||||
devDependencies?: stringMap;
|
||||
scripts?: stringMap;
|
||||
} = {}
|
||||
) {
|
||||
const dependencies: stringMap = {};
|
||||
const devDependencies: stringMap = {
|
||||
...defaultPackageJson.dependencies,
|
||||
@@ -112,7 +128,8 @@ function normalizePackageJson(defaultPackageJson: {dependencies?: stringMap, dev
|
||||
},
|
||||
scripts: {
|
||||
...defaultPackageJson.scripts,
|
||||
'now-build': 'NODE_OPTIONS=--max_old_space_size=3000 next build --lambdas',
|
||||
'now-build':
|
||||
'NODE_OPTIONS=--max_old_space_size=3000 next build --lambdas',
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -151,7 +168,12 @@ function getPathsInside(entryDirectory: string, files: Files) {
|
||||
return watch;
|
||||
}
|
||||
|
||||
function getRoutes(entryDirectory: string, pathsInside: string[], files: Files, url: string): any[] {
|
||||
function getRoutes(
|
||||
entryDirectory: string,
|
||||
pathsInside: string[],
|
||||
files: Files,
|
||||
url: string
|
||||
): any[] {
|
||||
const filesInside: Files = {};
|
||||
const prefix = entryDirectory === `.` ? `/` : `/${entryDirectory}/`;
|
||||
|
||||
@@ -166,12 +188,12 @@ function getRoutes(entryDirectory: string, pathsInside: string[], files: Files,
|
||||
const routes: any[] = [
|
||||
{
|
||||
src: `${prefix}_next/(.*)`,
|
||||
dest: `${url}/_next/$1`
|
||||
dest: `${url}/_next/$1`,
|
||||
},
|
||||
{
|
||||
src: `${prefix}static/(.*)`,
|
||||
dest: `${url}/static/$1`
|
||||
}
|
||||
dest: `${url}/static/$1`,
|
||||
},
|
||||
];
|
||||
|
||||
for (const file of Object.keys(filesInside)) {
|
||||
@@ -192,7 +214,7 @@ function getRoutes(entryDirectory: string, pathsInside: string[], files: Files,
|
||||
|
||||
routes.push({
|
||||
src: `${prefix}${pageName}`,
|
||||
dest: `${url}/${pageName}`
|
||||
dest: `${url}/${pageName}`,
|
||||
});
|
||||
|
||||
if (pageName.endsWith('index')) {
|
||||
@@ -200,7 +222,7 @@ function getRoutes(entryDirectory: string, pathsInside: string[], files: Files,
|
||||
|
||||
routes.push({
|
||||
src: `${prefix}${resolvedIndex}`,
|
||||
dest: `${url}/${resolvedIndex}`
|
||||
dest: `${url}/${resolvedIndex}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -208,6 +230,20 @@ function getRoutes(entryDirectory: string, pathsInside: string[], files: Files,
|
||||
return routes;
|
||||
}
|
||||
|
||||
function syncEnvVars(base: EnvConfig, removeEnv: EnvConfig, addEnv: EnvConfig) {
|
||||
// Remove any env vars from `removeEnv`
|
||||
// that are not present in the `addEnv`
|
||||
const addKeys = new Set(Object.keys(addEnv));
|
||||
for (const name of Object.keys(removeEnv)) {
|
||||
if (!addKeys.has(name)) {
|
||||
delete base[name];
|
||||
}
|
||||
}
|
||||
|
||||
// Add in the keys from `addEnv`
|
||||
Object.assign(base, addEnv);
|
||||
}
|
||||
|
||||
export {
|
||||
excludeFiles,
|
||||
validateEntrypoint,
|
||||
@@ -219,4 +255,5 @@ export {
|
||||
getPathsInside,
|
||||
getRoutes,
|
||||
stringMap,
|
||||
syncEnvVars,
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@now/node-bridge",
|
||||
"version": "1.1.0",
|
||||
"version": "1.1.2",
|
||||
"license": "MIT",
|
||||
"main": "./index.js",
|
||||
"repository": {
|
||||
|
||||
@@ -9,6 +9,7 @@ const {
|
||||
runNpmInstall,
|
||||
runPackageJsonScript,
|
||||
} = require('@now/build-utils/fs/run-user-scripts.js'); // eslint-disable-line import/no-extraneous-dependencies
|
||||
const { shouldServe } = require('@now/build-utils'); // eslint-disable-line import/no-extraneous-dependencies
|
||||
|
||||
/** @typedef { import('@now/build-utils/file-ref') } FileRef */
|
||||
/** @typedef {{[filePath: string]: FileRef}} Files */
|
||||
@@ -49,8 +50,12 @@ async function compile(workPath, downloadedFiles, entrypoint, config) {
|
||||
});
|
||||
|
||||
if (config && config.includeFiles) {
|
||||
const includeFiles = typeof config.includeFiles === 'string'
|
||||
? [config.includeFiles]
|
||||
: config.includeFiles;
|
||||
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const pattern of config.includeFiles) {
|
||||
for (const pattern of includeFiles) {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
const files = await glob(pattern, inputDir);
|
||||
|
||||
@@ -145,3 +150,5 @@ exports.prepareCache = async ({ workPath }) => ({
|
||||
...(await glob('package-lock.json', workPath)),
|
||||
...(await glob('yarn.lock', workPath)),
|
||||
});
|
||||
|
||||
exports.shouldServe = shouldServe;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@now/node-server",
|
||||
"version": "0.6.0",
|
||||
"version": "0.7.1",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -8,8 +8,8 @@
|
||||
"directory": "packages/now-node-server"
|
||||
},
|
||||
"dependencies": {
|
||||
"@now/node-bridge": "^1.1.0",
|
||||
"@zeit/ncc": "0.18.1",
|
||||
"@now/node-bridge": "^1.1.2",
|
||||
"@zeit/ncc": "0.18.2",
|
||||
"fs-extra": "7.0.1"
|
||||
},
|
||||
"scripts": {
|
||||
|
||||
5
packages/now-node-server/test/fixtures/11-include-files/accepts-string/index.js
vendored
Normal file
5
packages/now-node-server/test/fixtures/11-include-files/accepts-string/index.js
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
const express = require('express');
|
||||
|
||||
const app = express();
|
||||
|
||||
app.listen();
|
||||
@@ -9,6 +9,13 @@
|
||||
"templates/**"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"src": "accepts-string/index.js",
|
||||
"use": "@now/node-server",
|
||||
"config": {
|
||||
"includeFiles": "templates/**"
|
||||
}
|
||||
}
|
||||
],
|
||||
"probes": [
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@now/node",
|
||||
"version": "0.6.0",
|
||||
"version": "0.7.1",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index",
|
||||
"repository": {
|
||||
@@ -9,8 +9,8 @@
|
||||
"directory": "packages/now-node"
|
||||
},
|
||||
"dependencies": {
|
||||
"@now/node-bridge": "^1.1.0",
|
||||
"@zeit/ncc": "0.18.1",
|
||||
"@now/node-bridge": "^1.1.2",
|
||||
"@zeit/ncc": "0.18.2",
|
||||
"fs-extra": "7.0.1"
|
||||
},
|
||||
"scripts": {
|
||||
|
||||
@@ -11,14 +11,15 @@ import {
|
||||
runPackageJsonScript,
|
||||
PrepareCacheOptions,
|
||||
BuildOptions,
|
||||
shouldServe,
|
||||
} from '@now/build-utils';
|
||||
|
||||
interface CompilerConfig {
|
||||
includeFiles?: string[]
|
||||
includeFiles?: string | string[];
|
||||
}
|
||||
|
||||
interface DownloadOptions {
|
||||
files: Files,
|
||||
files: Files;
|
||||
entrypoint: string;
|
||||
workPath: string;
|
||||
npmArguments?: string[];
|
||||
@@ -28,7 +29,7 @@ async function downloadInstallAndBundle({
|
||||
files,
|
||||
entrypoint,
|
||||
workPath,
|
||||
npmArguments = []
|
||||
npmArguments = [],
|
||||
}: DownloadOptions) {
|
||||
console.log('downloading user files...');
|
||||
const downloadedFiles = await download(files, workPath);
|
||||
@@ -41,15 +42,27 @@ async function downloadInstallAndBundle({
|
||||
return { entrypointPath, entrypointFsDirname };
|
||||
}
|
||||
|
||||
async function compile(entrypointPath: string, entrypoint: string, config: CompilerConfig): Promise<Files> {
|
||||
async function compile(
|
||||
entrypointPath: string,
|
||||
entrypoint: string,
|
||||
config: CompilerConfig
|
||||
): Promise<Files> {
|
||||
const input = entrypointPath;
|
||||
const inputDir = dirname(input);
|
||||
const rootIncludeFiles = inputDir.split(sep).pop() || '';
|
||||
const ncc = require('@zeit/ncc');
|
||||
const { code, map, assets } = await ncc(input, { sourceMap: true, sourceMapRegister: true });
|
||||
const { code, map, assets } = await ncc(input, {
|
||||
sourceMap: true,
|
||||
sourceMapRegister: true,
|
||||
});
|
||||
|
||||
if (config && config.includeFiles) {
|
||||
for (const pattern of config.includeFiles) {
|
||||
const includeFiles =
|
||||
typeof config.includeFiles === 'string'
|
||||
? [config.includeFiles]
|
||||
: config.includeFiles;
|
||||
|
||||
for (const pattern of includeFiles) {
|
||||
const files = await glob(pattern, inputDir);
|
||||
|
||||
for (const assetName of Object.keys(files)) {
|
||||
@@ -61,12 +74,12 @@ async function compile(entrypointPath: string, entrypoint: string, config: Compi
|
||||
// if asset contain directory
|
||||
// no need to use `rootIncludeFiles`
|
||||
if (assetName.includes(sep)) {
|
||||
fullPath = assetName
|
||||
fullPath = assetName;
|
||||
}
|
||||
|
||||
assets[fullPath] = {
|
||||
'source': data,
|
||||
'permissions': mode
|
||||
source: data,
|
||||
permissions: mode,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -75,7 +88,9 @@ async function compile(entrypointPath: string, entrypoint: string, config: Compi
|
||||
const preparedFiles: Files = {};
|
||||
// move all user code to 'user' subdirectory
|
||||
preparedFiles[entrypoint] = new FileBlob({ data: code });
|
||||
preparedFiles[`${entrypoint.replace('.ts', '.js')}.map`] = new FileBlob({ data: map });
|
||||
preparedFiles[`${entrypoint.replace('.ts', '.js')}.map`] = new FileBlob({
|
||||
data: map,
|
||||
});
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const assetName of Object.keys(assets)) {
|
||||
const { source: data, permissions: mode } = assets[assetName];
|
||||
@@ -87,16 +102,24 @@ async function compile(entrypointPath: string, entrypoint: string, config: Compi
|
||||
}
|
||||
|
||||
export const config = {
|
||||
maxLambdaSize: '5mb'
|
||||
maxLambdaSize: '5mb',
|
||||
};
|
||||
|
||||
export async function build({ files, entrypoint, workPath, config }: BuildOptions) {
|
||||
export async function build({
|
||||
files,
|
||||
entrypoint,
|
||||
workPath,
|
||||
config,
|
||||
}: BuildOptions) {
|
||||
const {
|
||||
entrypointPath,
|
||||
entrypointFsDirname
|
||||
} = await downloadInstallAndBundle(
|
||||
{ files, entrypoint, workPath, npmArguments: ['--prefer-offline'] }
|
||||
);
|
||||
entrypointFsDirname,
|
||||
} = await downloadInstallAndBundle({
|
||||
files,
|
||||
entrypoint,
|
||||
workPath,
|
||||
npmArguments: ['--prefer-offline'],
|
||||
});
|
||||
|
||||
console.log('running user script...');
|
||||
await runPackageJsonScript(entrypointFsDirname, 'now-build');
|
||||
@@ -110,19 +133,19 @@ export async function build({ files, entrypoint, workPath, config }: BuildOption
|
||||
'// PLACEHOLDER',
|
||||
[
|
||||
`listener = require("./${entrypoint}");`,
|
||||
'if (listener.default) listener = listener.default;'
|
||||
'if (listener.default) listener = listener.default;',
|
||||
].join(' ')
|
||||
);
|
||||
|
||||
const launcherFiles = {
|
||||
'launcher.js': new FileBlob({ data: launcherData }),
|
||||
'bridge.js': new FileFsRef({ fsPath: require('@now/node-bridge') })
|
||||
'bridge.js': new FileFsRef({ fsPath: require('@now/node-bridge') }),
|
||||
};
|
||||
|
||||
const lambda = await createLambda({
|
||||
files: { ...preparedFiles, ...launcherFiles },
|
||||
handler: 'launcher.launcher',
|
||||
runtime: 'nodejs8.10'
|
||||
runtime: 'nodejs8.10',
|
||||
});
|
||||
|
||||
return { [entrypoint]: lambda };
|
||||
@@ -132,6 +155,8 @@ export async function prepareCache({ workPath }: PrepareCacheOptions) {
|
||||
return {
|
||||
...(await glob('node_modules/**', workPath)),
|
||||
...(await glob('package-lock.json', workPath)),
|
||||
...(await glob('yarn.lock', workPath))
|
||||
...(await glob('yarn.lock', workPath)),
|
||||
};
|
||||
}
|
||||
|
||||
export { shouldServe };
|
||||
|
||||
7
packages/now-node/test/fixtures/09-include-files/accepts-string.js
vendored
Normal file
7
packages/now-node/test/fixtures/09-include-files/accepts-string.js
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
const edge = require('edge.js');
|
||||
|
||||
module.exports = (req, resp) => {
|
||||
edge.registerViews('templates');
|
||||
|
||||
resp.end(edge.render('accepts-string', { name: 'String!' }));
|
||||
};
|
||||
@@ -18,6 +18,13 @@
|
||||
"root.edge"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"src": "accepts-string.js",
|
||||
"use": "@now/node",
|
||||
"config": {
|
||||
"includeFiles": "templates/accepts-string.edge"
|
||||
}
|
||||
}
|
||||
],
|
||||
"probes": [
|
||||
@@ -25,6 +32,10 @@
|
||||
"path": "/",
|
||||
"mustContain": "hello Now!"
|
||||
},
|
||||
{
|
||||
"path": "/accepts-string.js",
|
||||
"mustContain": "hello String!"
|
||||
},
|
||||
{
|
||||
"path": "/root.js",
|
||||
"mustContain": "hello Root!"
|
||||
|
||||
1
packages/now-node/test/fixtures/09-include-files/templates/accepts-string.edge
vendored
Normal file
1
packages/now-node/test/fixtures/09-include-files/templates/accepts-string.edge
vendored
Normal file
@@ -0,0 +1 @@
|
||||
hello {{ name }}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@now/optipng",
|
||||
"version": "0.5.0",
|
||||
"version": "0.6.1",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index",
|
||||
"files": [
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
// eslint-disable-line import/no-extraneous-dependencies
|
||||
import {
|
||||
import {
|
||||
FileBlob,
|
||||
BuildOptions,
|
||||
AnalyzeOptions
|
||||
} from '@now/build-utils'
|
||||
import OptiPng from 'optipng'
|
||||
import pipe from 'multipipe'
|
||||
AnalyzeOptions,
|
||||
shouldServe,
|
||||
} from '@now/build-utils';
|
||||
import OptiPng from 'optipng';
|
||||
import pipe from 'multipipe';
|
||||
|
||||
export function analyze({ files, entrypoint }: AnalyzeOptions) {
|
||||
export function analyze({ files, entrypoint }: AnalyzeOptions) {
|
||||
return files[entrypoint].digest;
|
||||
}
|
||||
|
||||
@@ -20,3 +21,5 @@ export async function build({ files, entrypoint }: BuildOptions) {
|
||||
const result = await FileBlob.fromStream({ stream });
|
||||
return { [entrypoint]: result };
|
||||
}
|
||||
|
||||
export { shouldServe };
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@now/php-bridge",
|
||||
"version": "0.5.0",
|
||||
"version": "0.5.2",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
const {
|
||||
createLambda, rename, glob, download,
|
||||
createLambda,
|
||||
rename,
|
||||
glob,
|
||||
download,
|
||||
shouldServe,
|
||||
} = require('@now/build-utils'); // eslint-disable-line import/no-extraneous-dependencies
|
||||
const path = require('path');
|
||||
const { getFiles } = require('@now/php-bridge');
|
||||
@@ -52,3 +56,5 @@ exports.build = async ({
|
||||
|
||||
return { [entrypoint]: lambda };
|
||||
};
|
||||
|
||||
exports.shouldServe = shouldServe;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@now/php",
|
||||
"version": "0.5.0",
|
||||
"version": "0.5.3",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -8,7 +8,7 @@
|
||||
"directory": "packages/now-php"
|
||||
},
|
||||
"dependencies": {
|
||||
"@now/php-bridge": "^0.5.0"
|
||||
"@now/php-bridge": "^0.5.2"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "jest"
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
import { join } from 'path';
|
||||
import fetch from 'node-fetch';
|
||||
import execa from 'execa';
|
||||
import { createWriteStream } from 'fs';
|
||||
import { getWriteableDirectory } from '@now/build-utils';
|
||||
|
||||
const url = 'https://bootstrap.pypa.io/get-pip.py';
|
||||
|
||||
// downloads `get-pip.py` and returns its absolute path
|
||||
async function downloadGetPipScript() {
|
||||
console.log('downloading "get-pip.py"...');
|
||||
const res = await fetch(url);
|
||||
|
||||
if (!res.ok || res.status !== 200) {
|
||||
throw new Error(`Could not download "get-pip.py" from "${url}"`);
|
||||
}
|
||||
|
||||
const dir = await getWriteableDirectory();
|
||||
const filePath = join(dir, 'get-pip.py');
|
||||
const writeStream = createWriteStream(filePath);
|
||||
|
||||
return new Promise<string>((resolve, reject) => {
|
||||
res.body
|
||||
.on('error', reject)
|
||||
.pipe(writeStream)
|
||||
.on('finish', () => resolve(filePath));
|
||||
});
|
||||
}
|
||||
|
||||
// downloads and installs `pip` (respecting
|
||||
// process.env.PYTHONUSERBASE), and returns
|
||||
// the absolute path to it
|
||||
export async function downloadAndInstallPip() {
|
||||
const { PYTHONUSERBASE } = process.env;
|
||||
if (!PYTHONUSERBASE) {
|
||||
// this is the directory in which `pip` will be
|
||||
// installed to. `--user` will assume `~` if this
|
||||
// is not set, and `~` is not writeable on AWS Lambda.
|
||||
// let's refuse to proceed
|
||||
throw new Error(
|
||||
'Could not install "pip": "PYTHONUSERBASE" env var is not set',
|
||||
);
|
||||
}
|
||||
const getPipFilePath = await downloadGetPipScript();
|
||||
|
||||
console.log('running "python get-pip.py"...');
|
||||
try {
|
||||
await execa('python3', [getPipFilePath, '--user'], { stdio: 'inherit' });
|
||||
} catch (err) {
|
||||
console.log('could not install pip');
|
||||
throw err;
|
||||
}
|
||||
|
||||
return join(PYTHONUSERBASE, 'bin', 'pip');
|
||||
}
|
||||
|
||||
@@ -9,20 +9,30 @@ import {
|
||||
download,
|
||||
glob,
|
||||
createLambda,
|
||||
shouldServe,
|
||||
BuildOptions,
|
||||
} from '@now/build-utils';
|
||||
import { downloadAndInstallPip } from './download-and-install-pip';
|
||||
|
||||
async function pipInstall(pipPath: string, workDir: string, ...args: string[]) {
|
||||
const target = '.';
|
||||
console.log(`running "pip install --target ${target} --upgrade ${args.join(' ')}"...`);
|
||||
console.log(
|
||||
`running "pip install --target ${target} --upgrade ${args.join(' ')}"...`
|
||||
);
|
||||
try {
|
||||
await execa(pipPath, ['install', '--target', target, '--upgrade', ...args], {
|
||||
cwd: workDir,
|
||||
stdio: 'inherit',
|
||||
});
|
||||
await execa(
|
||||
pipPath,
|
||||
['install', '--target', target, '--upgrade', ...args],
|
||||
{
|
||||
cwd: workDir,
|
||||
stdio: 'inherit',
|
||||
}
|
||||
);
|
||||
} catch (err) {
|
||||
console.log(`failed to run "pip install --target ${target} --upgrade ${args.join(' ')}"...`);
|
||||
console.log(
|
||||
`failed to run "pip install --target ${target} --upgrade ${args.join(
|
||||
' '
|
||||
)}"...`
|
||||
);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
@@ -42,11 +52,10 @@ async function pipInstallUser(pipPath: string, ...args: string[]) {
|
||||
async function pipenvInstall(pyUserBase: string, srcDir: string) {
|
||||
console.log('running "pipenv_to_requirements -f');
|
||||
try {
|
||||
await execa(
|
||||
join(pyUserBase, 'bin', 'pipenv_to_requirements'),
|
||||
['-f'],
|
||||
{ cwd: srcDir, stdio: 'inherit' },
|
||||
);
|
||||
await execa(join(pyUserBase, 'bin', 'pipenv_to_requirements'), ['-f'], {
|
||||
cwd: srcDir,
|
||||
stdio: 'inherit',
|
||||
});
|
||||
} catch (err) {
|
||||
console.log('failed to run "pipenv_to_requirements -f"');
|
||||
throw err;
|
||||
@@ -57,17 +66,18 @@ export const config = {
|
||||
maxLambdaSize: '5mb',
|
||||
};
|
||||
|
||||
export const build = async ({ workPath, files, entrypoint }: BuildOptions) => {
|
||||
export const build = async ({
|
||||
workPath,
|
||||
files: originalFiles,
|
||||
entrypoint,
|
||||
meta = {},
|
||||
}: BuildOptions) => {
|
||||
console.log('downloading files...');
|
||||
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
files = await download(files, workPath);
|
||||
|
||||
// this is where `pip` will be installed to
|
||||
// we need it to be under `/tmp`
|
||||
const downloadedFiles = await download(originalFiles, workPath);
|
||||
const foundLockFile = 'Pipfile.lock' in downloadedFiles;
|
||||
const pyUserBase = await getWriteableDirectory();
|
||||
process.env.PYTHONUSERBASE = pyUserBase;
|
||||
const pipPath = await downloadAndInstallPip();
|
||||
const pipPath = 'pip3';
|
||||
|
||||
try {
|
||||
// See: https://stackoverflow.com/a/44728772/376773
|
||||
@@ -77,8 +87,10 @@ export const build = async ({ workPath, files, entrypoint }: BuildOptions) => {
|
||||
//
|
||||
// distutils.errors.DistutilsOptionError: must supply either home
|
||||
// or prefix/exec-prefix -- not both
|
||||
const setupCfg = join(workPath, 'setup.cfg');
|
||||
await writeFile(setupCfg, '[install]\nprefix=\n');
|
||||
if (meta.isDev) {
|
||||
const setupCfg = join(workPath, 'setup.cfg');
|
||||
await writeFile(setupCfg, '[install]\nprefix=\n');
|
||||
}
|
||||
} catch (err) {
|
||||
console.log('failed to create "setup.cfg" file');
|
||||
throw err;
|
||||
@@ -87,10 +99,7 @@ export const build = async ({ workPath, files, entrypoint }: BuildOptions) => {
|
||||
await pipInstall(pipPath, workPath, 'werkzeug');
|
||||
await pipInstall(pipPath, workPath, 'requests');
|
||||
|
||||
const entryDirectory = dirname(entrypoint);
|
||||
const requirementsTxt = join(entryDirectory, 'requirements.txt');
|
||||
|
||||
if (files['Pipfile.lock']) {
|
||||
if (foundLockFile) {
|
||||
console.log('found "Pipfile.lock"');
|
||||
|
||||
// Install pipenv.
|
||||
@@ -100,6 +109,8 @@ export const build = async ({ workPath, files, entrypoint }: BuildOptions) => {
|
||||
}
|
||||
|
||||
const fsFiles = await glob('**', workPath);
|
||||
const entryDirectory = dirname(entrypoint);
|
||||
const requirementsTxt = join(entryDirectory, 'requirements.txt');
|
||||
|
||||
if (fsFiles[requirementsTxt]) {
|
||||
console.log('found local "requirements.txt"');
|
||||
@@ -122,7 +133,7 @@ export const build = async ({ workPath, files, entrypoint }: BuildOptions) => {
|
||||
.replace(/\.py$/, '');
|
||||
const nowHandlerPyContents = originalNowHandlerPyContents.replace(
|
||||
/__NOW_HANDLER_FILENAME/g,
|
||||
userHandlerFilePath,
|
||||
userHandlerFilePath
|
||||
);
|
||||
|
||||
// in order to allow the user to have `server.py`, we need our `server.py` to be called
|
||||
@@ -131,7 +142,7 @@ export const build = async ({ workPath, files, entrypoint }: BuildOptions) => {
|
||||
|
||||
await writeFile(
|
||||
join(workPath, `${nowHandlerPyFilename}.py`),
|
||||
nowHandlerPyContents,
|
||||
nowHandlerPyContents
|
||||
);
|
||||
|
||||
const lambda = await createLambda({
|
||||
@@ -145,3 +156,5 @@ export const build = async ({ workPath, files, entrypoint }: BuildOptions) => {
|
||||
[entrypoint]: lambda,
|
||||
};
|
||||
};
|
||||
|
||||
export { shouldServe };
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@now/python",
|
||||
"version": "0.1.0",
|
||||
"version": "0.2.1",
|
||||
"main": "index.js",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -8,6 +8,7 @@ const glob = require('@now/build-utils/fs/glob.js'); // eslint-disable-line impo
|
||||
const { runShellScript } = require('@now/build-utils/fs/run-user-scripts.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 FileRef = require('@now/build-utils/file-ref.js'); // eslint-disable-line import/no-extraneous-dependencies
|
||||
const { shouldServe } = require('@now/build-utils'); // eslint-disable-line import/no-extraneous-dependencies
|
||||
const installRust = require('./install-rust.js');
|
||||
|
||||
exports.config = {
|
||||
@@ -367,3 +368,5 @@ exports.getDefaultCache = ({ files, entrypoint }) => {
|
||||
});
|
||||
return { [targetFolderDir]: defaultCacheRef };
|
||||
};
|
||||
|
||||
exports.shouldServe = shouldServe;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@now/rust",
|
||||
"version": "0.2.0",
|
||||
"version": "0.2.3",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -15,7 +15,7 @@ function validateDistDir(distDir) {
|
||||
const distDirName = path.basename(distDir);
|
||||
if (!existsSync(distDir)) {
|
||||
const message = `Build was unable to create the distDir: ${distDirName}.`
|
||||
+ '\nMake sure you mentioned the correct dist directory: https://zeit.co/docs/v2/deployments/official-builders/static-build-now-static-build/#configuring-the-build-output-directory';
|
||||
+ '\nMake sure you mentioned the correct dist directory: https://zeit.co/docs/v2/deployments/official-builders/static-build-now-static-build/#local-development';
|
||||
throw new Error(message);
|
||||
}
|
||||
}
|
||||
@@ -58,6 +58,7 @@ exports.build = async ({
|
||||
devPort = await getPort();
|
||||
nowDevScriptPorts.set(entrypoint, devPort);
|
||||
const opts = {
|
||||
cwd: entrypointFsDirname,
|
||||
env: { ...process.env, PORT: String(devPort) },
|
||||
};
|
||||
const child = spawn('yarn', ['run', 'now-dev'], opts);
|
||||
@@ -103,6 +104,12 @@ exports.build = async ({
|
||||
dest: `http://localhost:${devPort}${srcBase}/$1`,
|
||||
});
|
||||
} else {
|
||||
if (meta.isDev) {
|
||||
console.log('WARN: "now-dev" script is missing from package.json');
|
||||
console.log(
|
||||
'See the local development docs: http://zeit.co/docs/v2/deployments/official-builders/static-now-static#local-development',
|
||||
);
|
||||
}
|
||||
// Run the `now-build` script and wait for completion to collect the build
|
||||
// outputs
|
||||
console.log('running user "now-build" script from `package.json`...');
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@now/static-build",
|
||||
"version": "0.5.2",
|
||||
"version": "0.5.5",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@now/wordpress",
|
||||
"version": "0.5.0",
|
||||
"version": "0.5.2",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -8,7 +8,7 @@
|
||||
"directory": "packages/now-wordpress"
|
||||
},
|
||||
"dependencies": {
|
||||
"@now/php-bridge": "^0.5.0",
|
||||
"@now/php-bridge": "^0.5.2",
|
||||
"node-fetch": "2.3.0",
|
||||
"yauzl": "2.10.0"
|
||||
},
|
||||
|
||||
35
yarn.lock
35
yarn.lock
@@ -940,6 +940,13 @@
|
||||
dependencies:
|
||||
"@babel/types" "^7.3.0"
|
||||
|
||||
"@types/cross-spawn@6.0.0":
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/cross-spawn/-/cross-spawn-6.0.0.tgz#320aaf1d1a12979f1b84fe7a5590a7e860bf3a80"
|
||||
integrity sha512-evp2ZGsFw9YKprDbg8ySgC9NA15g3YgiI8ANkGmKKvvi0P2aDGYLPxQIC5qfeKNUOe3TjABVGuah6omPRpIYhg==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/debug@^4.1.3":
|
||||
version "4.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.4.tgz#56eec47706f0fd0b7c694eae2f3172e6b0b769da"
|
||||
@@ -1128,10 +1135,10 @@
|
||||
globby "8.0.0"
|
||||
signal-exit "3.0.2"
|
||||
|
||||
"@zeit/ncc@0.18.1":
|
||||
version "0.18.1"
|
||||
resolved "https://registry.yarnpkg.com/@zeit/ncc/-/ncc-0.18.1.tgz#1723884210c792ba702ec6dccb390f387f0a3ba6"
|
||||
integrity sha512-Tq13BzK+hAWBZY+VvncRZzpE5PHGks3kn2XJ+bcWSXgTZb4rTR/CTV1YYXilNNkX//jC1sziuM167FhLzFu2XA==
|
||||
"@zeit/ncc@0.18.2":
|
||||
version "0.18.2"
|
||||
resolved "https://registry.yarnpkg.com/@zeit/ncc/-/ncc-0.18.2.tgz#b5f721ec1d23bfe531f3568633689ddab7c05638"
|
||||
integrity sha512-liiuVTcxLaOIGQDftpZ2qhSS/vdEbuvmi2tkBWMfIwIyeKd/sh/jw+l8yONT3/unx/sSmfMTDnwfwUlY+saKiw==
|
||||
|
||||
JSONStream@^1.0.4, JSONStream@^1.3.4:
|
||||
version "1.3.5"
|
||||
@@ -2534,16 +2541,7 @@ create-error-class@^3.0.1:
|
||||
dependencies:
|
||||
capture-stack-trace "^1.0.0"
|
||||
|
||||
cross-spawn@^5.0.1:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449"
|
||||
integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=
|
||||
dependencies:
|
||||
lru-cache "^4.0.1"
|
||||
shebang-command "^1.2.0"
|
||||
which "^1.2.9"
|
||||
|
||||
cross-spawn@^6.0.0, cross-spawn@^6.0.5:
|
||||
cross-spawn@6.0.5, cross-spawn@^6.0.0, cross-spawn@^6.0.5:
|
||||
version "6.0.5"
|
||||
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
|
||||
integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==
|
||||
@@ -2554,6 +2552,15 @@ cross-spawn@^6.0.0, cross-spawn@^6.0.5:
|
||||
shebang-command "^1.2.0"
|
||||
which "^1.2.9"
|
||||
|
||||
cross-spawn@^5.0.1:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449"
|
||||
integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=
|
||||
dependencies:
|
||||
lru-cache "^4.0.1"
|
||||
shebang-command "^1.2.0"
|
||||
which "^1.2.9"
|
||||
|
||||
cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0":
|
||||
version "0.3.4"
|
||||
resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.4.tgz#8cd52e8a3acfd68d3aed38ee0a640177d2f9d797"
|
||||
|
||||
Reference in New Issue
Block a user