Compare commits

...

36 Commits

Author SHA1 Message Date
Steven
08641ab804 Publish
- @now/bash@1.0.2
 - @now/build-utils@0.8.9
 - @now/go@0.5.6
 - @now/next@0.5.5
 - @now/node-bridge@1.2.3
 - @now/node@0.12.0
 - @now/php@0.5.7
 - @now/python@0.2.12
 - @now/ruby@0.1.3
 - @now/rust@0.2.9
 - @now/static-build@0.7.3
2019-07-18 07:25:24 -04:00
Steven
e7f87ceba7 [now-node] Fix order devDependencies (master only) 2019-07-17 17:21:44 -04:00
Steven
e9632699e1 Regenerate yarn.lock and pin dependencies (#780)
* Regenerate yarn.lock

* Fix typings for bridge and helpers

* Remove top level dependencies and pin version

* Add missing @types/multistream

* Add @types/node

* Add @types/node

* Fix child.stdout null check

* Add global types

* Move types to root, generate lock file

* Remove unused tests inside the integration tests
2019-07-17 17:18:02 -04:00
Steven
a9427bbe76 [now-node] Use ncc before publishing to npm (#755)
* [now-node] Use ncc before publishing

* Copy entire bridge source file

* Remove node-bridge dependency

* add typescript to build

* ensure typescript reference is not analyzed

* remove duplicate build

* typescript as a compiler

* Revert "typescript as a compiler"

This reverts commit f51178e641b09ea6aff0dc98185c86e8d27de2cc.

* exclude langs

* fixup mkdir

* fixup mv command

* fixup typescript reference

* Change require to use bridge

* Remove copy step for bridge defs

* Change back to require

* Copy bridge again

* Remove dependency on @now/node-bridge
2019-07-17 13:30:42 -04:00
ywg-jean
cd700b01cc [now-node] Yarn workspaces transpilation & typescript dependenci… (#765)
* tests transpilation of yarn workspaces

up until @now/node@0.7.4-canary.28 this used to work out of the box

* tests that typescript workspaces are properly compiled

* update node-file-trace, symlink handling

* update node-file-trace, use index.ts in package.json main

* remove logging!
2019-07-17 13:30:30 -04:00
Guy Bedford
12244133f8 Use typescript esnext target (#756) 2019-07-17 13:30:17 -04:00
Steven
55acea648c Revert "[now-node-bridge] Increase timeout to 10 minutes" (#768)
This reverts commit 1658a84795b1dbd3ae240b2443476fdcf3af38f7.
2019-07-17 13:30:01 -04:00
Steven
48a6b77fed [now-node-bridge] Increase timeout to 10 minutes (#766) 2019-07-17 13:29:54 -04:00
dependabot[bot]
b0e20c043c Bump lodash from 4.17.11 to 4.17.14 in /test/integration/now-nod… (#761)
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.11 to 4.17.14.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.11...4.17.14)

Signed-off-by: dependabot[bot] <support@github.com>
2019-07-17 13:29:38 -04:00
Sophearak Tha
88ceaf12d0 Improve support for zero-config in now dev (#764) 2019-07-17 13:29:16 -04:00
Guy Bedford
0f94a523a6 [now-node] Fix .tsx resolution (#760)
* tsx resolution test

* .tsx support

* add logging, extension rewrite fix

* remove logging
2019-07-17 13:28:47 -04:00
Steven
0b3a01d07b [now-node] Bump @zeit/node-file-trace to 0.1.7 (#759)
* adds failing test to prevent future regression with yarn workspaces

* [now-node] Bump  @zeit/node-file-trace to 0.1.7
2019-07-17 13:28:34 -04:00
Nathan Rajlich
c03d9479e1 [now-static-build] Use yarn when invoking now-dev script (#747)
`yarn` used to be used, but was switched over to `npm` in #636.

The problem with `npm` is that when the `ignoreScripts` config option
is enabled in the user's `.npmrc` file, then `npm run …` does not get
invoked. This makes sense for `npm i`, but doesn't really make sense if
you're explicitly _trying_ to run a package script via `npm run`, and in
fact breaks `now dev`.

`yarn` has a similar option to ignore scripts, however it has the more
understandable behavior that when you do `yarn run` then the script is
actually run.

There isn't a concern about if the user does not have `yarn` installed
since `now dev` bundles its own copy of yarn and uses that version.
2019-07-17 13:28:09 -04:00
JJ Kasper
8d987243c6 Remove extra pre-fixing for dynamic routes (#751) 2019-07-17 13:27:45 -04:00
JJ Kasper
23d877de75 [now-next] Add subdir prefix to "src" for dynamic routes (#745)
* Update dynamic routes to have prefix in src
and not in dest for dev

* Make sure prefix isn't inside of capture
group for dynamic routes

* Prevent double slashes in src regexp

* Make sure leading slash is outside capture group

* Move up removing of leading slash from capture group

Fixes #729.
2019-07-17 13:27:26 -04:00
Guy Bedford
8855813697 [now-node] Support symlink outputs (#728)
* support symlink outputs

* create symlink in build file

* ensure build script idempotency

* Add isSymbolicLink and fix test
2019-07-17 13:26:53 -04:00
Sophearak Tha
5ca59332ed Remove maxLambdaSize config from all builders (#741)
* remove maxLambdaSize config

* remove maxLambdaSize config from `now-bash`, `now-php` and from tests
2019-07-17 13:26:30 -04:00
Luc
860a678b74 Update node-file-trace to 0.1.6 (#748) 2019-07-17 13:26:13 -04:00
Steven
ecb3fd25da [now-lambda] Remove package source code (#744)
* [now-lambda] Remove package source code

* Rename variable
2019-07-17 13:25:18 -04:00
Steven
5cb95bd226 [now-node] Add support for AWS Lambda API usage (#742)
* Add support for direct AWS usage

* Add test case using callback
2019-07-17 13:24:00 -04:00
Guy Bedford
47bc8c04ad update to node-file-trace@0.1.5 (#735) 2019-07-17 13:20:53 -04:00
Steven
2879041a65 Remove deprecated builders (#733)
* Remove deprecated builders

* Update comment so that tests  run
2019-07-17 13:20:35 -04:00
Steven
2e7e403725 [now-node] Add puppeteer / lighthouse tests (#731)
* [now-node] Add puppeteer tests

* Rename puppeteer tests

* Fix tests
2019-07-17 13:18:21 -04:00
Steven
30eede64ec [now-node] Add integration test for sharp (#730)
* [now-node] Add integration test for `sharp`

* Add monkey image in test
2019-07-17 13:18:05 -04:00
Guy Bedford
70f3d6f7de Nested tsconfig.json lookup support (#726)
* lookup nested tsconfig.json for each ts compilation

* [now-node] Nested tsconfig.json

* fixes
2019-07-17 13:17:25 -04:00
Guy Bedford
e1f7191f67 [now-node] Use node-file-trace approach as ncc alternative (#712)
* WIP: filter approach

* typing fixes

* reinclude ncc for helpers build

* include node-file-trace

* get integration tests working

* add node-file-trace to files

* fixup nested package.json files

* add node-file-trace dependencies

* add trace logging

* fixup inputFiles glob

* Revert "add node-file-trace dependencies"

This reverts commit ef0d3f60c9ec9ee78047a3f85f836fab21655bee.

* use external @zeit/node-file-trace

* inputFiles logging

* add missing Promise.all

* remove node-file-trace in files, ncc as devDependency

* disable typescript tests

* feedback from @styfle

* babel support

* add babel commonjs transform

* sourcemaps support

* fix faulty build config

* separate babel compilation file

* typescript attempt

* reenable typescript tests

* typescript support

* fixup typescript source maps

* remove Babel error wrapper

* set typescript errors to logging

* mode support

* formatting

* add back prepareCache

* fixup binary emission

* support typescript compiler fallback

* remove logging

* update yarn lock

* Update packages/now-node/test/fixtures/12-stack-trace-esm/index.js

Co-Authored-By: Steven <steven@ceriously.com>

* formatting

* guard log statements

* update probe line number for eslint ignore line

* fixup default config handling
2019-07-17 13:16:22 -04:00
Steven
a8f4b67aa2 [now-node-server] Remove package source code (#721)
* [now-node-server] Remove package

* Update comment so tests run
2019-07-17 13:15:54 -04:00
Simon Willison
d64a53cbb1 [now-python] Support ASGI functions as well as classes (#711)
* [now-python] Support ASGI functions as well as classes

Refs #710

* Fixed incorrect indentation
2019-07-17 13:12:08 -04:00
Andy Bitz
4300882d12 Publish
- @now/build-utils@0.8.8
2019-07-16 19:30:24 +02:00
Andy
0711e094f3 [now-build-utils] Fix file order (#772)
* [now-build-utils] Fix file order

* Use localeCompare
2019-07-16 19:30:08 +02:00
Andy Bitz
4ec1883262 Publish
- @now/build-utils@0.8.7
2019-07-16 17:25:37 +02:00
Andy
cb53db4157 [now-build-utils] Ignore more default routes and builds (#771)
* [now-build-utils] Ignore more default routes

* Don't export

* Update packages/now-build-utils/src/detect-builder.ts

Co-Authored-By: Steven <steven@ceriously.com>

* Update packages/now-build-utils/src/detect-builder.ts

Co-Authored-By: Steven <steven@ceriously.com>
2019-07-16 17:25:15 +02:00
Andy Bitz
49aea85638 Publish
- @now/build-utils@0.8.6
 - @now/static-build@0.7.2
2019-07-16 11:43:43 +02:00
Andy
3971b5a8cf [now-static-build] Remove default routes for now dev (#769)
* [now-static-build] Remove default routes for now dev

* Update packages/now-static-build/src/index.ts

Co-Authored-By: Leo Lamprecht <mindrun@icloud.com>
2019-07-16 11:41:41 +02:00
Igor Klopov
958946d01a Publish
- @now/build-utils@0.8.5
2019-07-13 22:01:47 +03:00
Igor Klopov
f3d284476f remove mutex because it is not reentrant and hangs on sub-invocation (#758) 2019-07-13 22:00:17 +03:00
182 changed files with 3691 additions and 6889 deletions

View File

@@ -43,23 +43,19 @@
]
},
"devDependencies": {
"@types/fs-extra": "^5.0.4",
"@types/glob": "^7.1.1",
"@types/multistream": "^2.1.1",
"@types/node": "^10.12.8",
"@types/node": "*",
"async-retry": "1.2.3",
"buffer-replace": "^1.0.0",
"codecov": "^3.2.0",
"eslint": "^5.9.0",
"eslint-config-airbnb-base": "^13.1.0",
"eslint-config-prettier": "^3.1.0",
"eslint-plugin-import": "^2.14.0",
"buffer-replace": "1.0.0",
"codecov": "3.2.0",
"eslint": "5.9.0",
"eslint-config-airbnb-base": "13.1.0",
"eslint-config-prettier": "3.3.0",
"eslint-plugin-import": "2.14.0",
"fs-extra": "^7.0.1",
"glob": "^7.1.3",
"jest": "^23.6.0",
"lint-staged": "^8.0.4",
"node-fetch": "^2.3.0",
"pre-commit": "^1.2.2",
"jest": "24.7.1",
"lint-staged": "8.1.0",
"node-fetch": "2.6.0",
"pre-commit": "1.2.2",
"prettier": "1.17.1"
},
"prettier": {

View File

@@ -9,10 +9,6 @@ const {
shouldServe,
} = require('@now/build-utils'); // eslint-disable-line import/no-extraneous-dependencies
exports.config = {
maxLambdaSize: '30mb',
};
// From this list: https://import.pw/importpw/import/docs/config.md
const allowedConfigImports = new Set([
'CACHE',

View File

@@ -1,6 +1,6 @@
{
"name": "@now/bash",
"version": "1.0.1",
"version": "1.0.2",
"description": "Now 2.0 builder for HTTP endpoints written in Bash",
"main": "index.js",
"author": "Nathan Rajlich <nate@zeit.co>",

View File

@@ -1,6 +1,6 @@
{
"name": "@now/build-utils",
"version": "0.8.4",
"version": "0.8.9",
"license": "MIT",
"main": "./dist/index.js",
"types": "./dist/index.d.js",
@@ -35,6 +35,7 @@
"@types/end-of-stream": "^1.4.0",
"@types/fs-extra": "^5.0.5",
"@types/glob": "^7.1.1",
"@types/multistream": "2.1.1",
"@types/node-fetch": "^2.1.6",
"@types/semver": "6.0.0",
"@types/yazl": "^2.4.1",

View File

@@ -76,19 +76,34 @@ export function ignoreApiFilter(file: string) {
return false;
}
// If the file does not match any builder we also
// don't want to create a route e.g. `package.json`
if (API_BUILDERS.every(({ src }) => !minimatch(file, src))) {
return false;
}
return true;
}
// We need to sort the file paths by alphabet to make
// sure the routes stay in the same order e.g. for deduping
export function sortFiles(fileA: string, fileB: string) {
return fileA.localeCompare(fileB);
}
export async function detectApiBuilders(
files: string[]
): Promise<Builder[] | null> {
const builds = files.filter(ignoreApiFilter).map(file => {
const result = API_BUILDERS.find(
({ src }): boolean => minimatch(file, src)
);
const builds = files
.sort(sortFiles)
.filter(ignoreApiFilter)
.map(file => {
const result = API_BUILDERS.find(
({ src }): boolean => minimatch(file, src)
);
return result ? { ...result, src: file } : null;
});
return result ? { ...result, src: file } : null;
});
const finishedBuilds = builds.filter(Boolean);
return finishedBuilds.length > 0 ? (finishedBuilds as Builder[]) : null;

View File

@@ -1,6 +1,6 @@
import { Route } from './types';
import { parse as parsePath } from 'path';
import { ignoreApiFilter } from './detect-builder';
import { ignoreApiFilter, sortFiles } from './detect-builder';
function joinPath(...segments: string[]) {
const joinedPath = segments.join('/');
@@ -55,7 +55,7 @@ function createRouteFromPath(filePath: string): Route {
);
const src = `^/${srcParts.join('/')}$`;
const dest = `/${filePath}?${query.join('&')}`;
const dest = `/${filePath}${query.length ? '?' : ''}${query.join('&')}`;
return { src, dest };
}
@@ -181,6 +181,7 @@ export async function detectApiRoutes(
// the first ones to get handled
const sortedFiles = files
.filter(ignoreApiFilter)
.sort(sortFiles)
.sort(sortFilesBySegmentCount);
const defaultRoutes: Route[] = [];

View File

@@ -18,7 +18,7 @@ function spawnAsync(
opts = { stdio: 'inherit', cwd, ...opts };
const child = spawn(command, args, opts);
if (opts.stdio === 'pipe') {
if (opts.stdio === 'pipe' && child.stderr) {
child.stderr.on('data', data => stderrLogs.push(data));
}
@@ -139,13 +139,7 @@ export async function runNpmInstall(
} else {
await spawnAsync(
'yarn',
commandArgs.concat([
'--ignore-engines',
'--mutex',
'network',
'--cwd',
destPath,
]),
commandArgs.concat(['--ignore-engines', '--cwd', destPath]),
destPath,
opts
);

View File

@@ -3,8 +3,7 @@
"builds": [
{
"src": "index.js",
"use": "@now/node",
"config": { "maxLambdaSize": "18mb" }
"use": "@now/node"
}
],
"probes": [{ "path": "/", "mustContain": "found:RANDOMNESS_PLACEHOLDER" }]

View File

@@ -224,10 +224,12 @@ it('Test `detectApiBuilders`', async () => {
it('Test `detectApiRoutes`', async () => {
{
const files = ['api/user.go', 'api/team.js'];
const files = ['api/user.go', 'api/team.js', 'api/package.json'];
const { defaultRoutes } = await detectApiRoutes(files);
expect(defaultRoutes.length).toBe(2);
expect(defaultRoutes[0].dest).toBe('/api/team.js');
expect(defaultRoutes[1].dest).toBe('/api/user.go');
}
{

View File

@@ -45,10 +45,6 @@ async function initPrivateGit(credentials: string) {
export const version = 2;
export const config = {
maxLambdaSize: '10mb',
};
export async function build({
files,
entrypoint,
@@ -241,7 +237,7 @@ Learn more: https://zeit.co/docs/v2/deployments/official-builders/go-now-go/#ent
if (meta.isDev && isGoModExist && isGoModInRootDir) {
await writeFile(
join(dirname(downloadedFiles['now.json'].fsPath), mainModGoFileName),
join(dirname(downloadedFiles['go.mod'].fsPath), mainModGoFileName),
mainModGoContents
);
} else if (isGoModExist && isGoModInRootDir) {
@@ -291,7 +287,7 @@ Learn more: https://zeit.co/docs/v2/deployments/official-builders/go-now-go/#ent
let baseGoModPath = '';
if (meta.isDev && isGoModExist && isGoModInRootDir) {
baseGoModPath = dirname(downloadedFiles['now.json'].fsPath);
baseGoModPath = dirname(downloadedFiles['go.mod'].fsPath);
} else if (isGoModExist && isGoModInRootDir) {
baseGoModPath = srcPath;
} else if (isGoModExist && !isGoModInRootDir) {

View File

@@ -1,6 +1,6 @@
{
"name": "@now/go",
"version": "0.5.5",
"version": "0.5.6",
"license": "MIT",
"homepage": "https://zeit.co/docs/v2/deployments/official-builders/go-now-go",
"repository": {

View File

@@ -1 +0,0 @@
save-prefix ""

View File

@@ -1,32 +0,0 @@
const { FileBlob, shouldServe } = require('@now/build-utils'); // eslint-disable-line import/no-extraneous-dependencies
const { minify } = require('html-minifier');
const defaultOptions = {
minifyCSS: true,
minifyJS: true,
removeComments: true,
removeAttributeQuotes: true,
removeEmptyAttributes: true,
removeOptionalTags: true,
removeRedundantAttributes: true,
useShortDoctype: true,
collapseWhitespace: true,
collapseBooleanAttributes: true,
caseSensitive: true,
};
exports.analyze = ({ files, entrypoint }) => files[entrypoint].digest;
exports.build = async ({ files, entrypoint, config }) => {
const stream = files[entrypoint].toStream();
const options = Object.assign({}, defaultOptions, config || {});
const { data } = await FileBlob.fromStream({ stream });
const content = data.toString();
const minified = minify(content, options);
const result = new FileBlob({ data: minified });
return { [entrypoint]: result };
};
exports.shouldServe = shouldServe;

View File

@@ -1,14 +0,0 @@
{
"name": "@now/html-minifier",
"version": "1.1.4",
"license": "MIT",
"homepage": "https://zeit.co/docs/v2/deployments/official-builders/html-minifier-now-html-minifier",
"repository": {
"type": "git",
"url": "https://github.com/zeit/now-builders.git",
"directory": "packages/now-html-minifier"
},
"dependencies": {
"html-minifier": "3.5.21"
}
}

View File

@@ -1,83 +0,0 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
camel-case@3.0.x:
version "3.0.0"
resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-3.0.0.tgz#ca3c3688a4e9cf3a4cda777dc4dcbc713249cf73"
integrity sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=
dependencies:
no-case "^2.2.0"
upper-case "^1.1.1"
clean-css@4.2.x:
version "4.2.1"
resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.1.tgz#2d411ef76b8569b6d0c84068dabe85b0aa5e5c17"
integrity sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g==
dependencies:
source-map "~0.6.0"
commander@2.17.x, commander@~2.17.1:
version "2.17.1"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf"
integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==
he@1.2.x:
version "1.2.0"
resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
html-minifier@3.5.21:
version "3.5.21"
resolved "https://registry.yarnpkg.com/html-minifier/-/html-minifier-3.5.21.tgz#d0040e054730e354db008463593194015212d20c"
integrity sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA==
dependencies:
camel-case "3.0.x"
clean-css "4.2.x"
commander "2.17.x"
he "1.2.x"
param-case "2.1.x"
relateurl "0.2.x"
uglify-js "3.4.x"
lower-case@^1.1.1:
version "1.1.4"
resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac"
integrity sha1-miyr0bno4K6ZOkv31YdcOcQujqw=
no-case@^2.2.0:
version "2.3.2"
resolved "https://registry.yarnpkg.com/no-case/-/no-case-2.3.2.tgz#60b813396be39b3f1288a4c1ed5d1e7d28b464ac"
integrity sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==
dependencies:
lower-case "^1.1.1"
param-case@2.1.x:
version "2.1.1"
resolved "https://registry.yarnpkg.com/param-case/-/param-case-2.1.1.tgz#df94fd8cf6531ecf75e6bef9a0858fbc72be2247"
integrity sha1-35T9jPZTHs915r75oIWPvHK+Ikc=
dependencies:
no-case "^2.2.0"
relateurl@0.2.x:
version "0.2.7"
resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9"
integrity sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=
source-map@~0.6.0, source-map@~0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
uglify-js@3.4.x:
version "3.4.9"
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.9.tgz#af02f180c1207d76432e473ed24a28f4a782bae3"
integrity sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q==
dependencies:
commander "~2.17.1"
source-map "~0.6.1"
upper-case@^1.1.1:
version "1.1.3"
resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-1.1.3.tgz#f6b4501c2ec4cdd26ba78be7222961de77621598"
integrity sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=

View File

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

View File

@@ -1,15 +0,0 @@
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');
const { handler, runtime } = config;
if (!handler) throw new Error('Handler not found in config');
if (!runtime) throw new Error('Runtime not found in config');
const zipBuffer = await streamToBuffer(files[entrypoint].toStream());
const lambda = new Lambda({ zipBuffer, handler, runtime });
return { [entrypoint]: lambda };
};
exports.shouldServe = shouldServe;

View File

@@ -1,13 +0,0 @@
{
"name": "@now/lambda",
"version": "0.5.4",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/zeit/now-builders.git",
"directory": "packages/now-lambda"
},
"scripts": {
"test": "jest"
}
}

View File

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

View File

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

View File

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

View File

@@ -1,45 +0,0 @@
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');
const remark2rehype = require('remark-rehype');
const doc = require('rehype-document');
const format = require('rehype-format');
const html = require('rehype-stringify');
exports.analyze = ({ files, entrypoint }) => files[entrypoint].digest;
exports.build = async ({ files, entrypoint, config }) => {
const stream = files[entrypoint].toStream();
const options = config || {};
const title = options.title || null;
const language = options.language || 'en';
const meta = options.meta || null;
const css = options.css || null;
const processor = unified()
.use(markdown)
.use(remark2rehype)
.use(doc, {
title,
language,
meta,
css,
})
.use(format)
.use(html);
const result = await FileBlob.fromStream({
stream: stream.pipe(unifiedStream(processor)),
});
const replacedEntrypoint = entrypoint.replace(/\.[^.]+$/, '.html');
return { [replacedEntrypoint]: result };
};
exports.shouldServe = (options) => {
const requestPath = options.requestPath.replace(/\.html$/, '.md');
return shouldServe({ ...options, requestPath });
};

View File

@@ -1,23 +0,0 @@
{
"name": "@now/md",
"version": "0.5.5",
"license": "MIT",
"homepage": "https://zeit.co/docs/v2/deployments/official-builders/markdown-now-md",
"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",
"rehype-stringify": "^4.0.0",
"remark-parse": "^6.0.1",
"remark-rehype": "^3.0.1",
"unified": "^7.0.0",
"unified-stream": "^1.0.2"
},
"scripts": {
"test": "jest"
}
}

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,508 +0,0 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
array-iterate@^1.0.0:
version "1.1.2"
resolved "https://registry.npmjs.org/array-iterate/-/array-iterate-1.1.2.tgz#f66a57e84426f8097f4197fbb6c051b8e5cdf7d8"
integrity sha512-1hWSHTIlG/8wtYD+PPX5AOBtKWngpDFjrsrHgZpe+JdgNGz0udYu6ZIkAa/xuenIUEqFv7DvE2Yr60jxweJSrQ==
bail@^1.0.0:
version "1.0.3"
resolved "https://registry.npmjs.org/bail/-/bail-1.0.3.tgz#63cfb9ddbac829b02a3128cd53224be78e6c21a3"
integrity sha512-1X8CnjFVQ+a+KW36uBNMTU5s8+v5FzeqrP7hTG5aTb4aPreSbZJlhwPon9VKMuEVgV++JM+SQrALY3kr7eswdg==
ccount@^1.0.0:
version "1.0.3"
resolved "https://registry.npmjs.org/ccount/-/ccount-1.0.3.tgz#f1cec43f332e2ea5a569fd46f9f5bde4e6102aff"
integrity sha512-Jt9tIBkRc9POUof7QA/VwWd+58fKkEEfI+/t1/eOlxKM7ZhrczNzMFefge7Ai+39y1pR/pP6cI19guHy3FSLmw==
character-entities-html4@^1.0.0:
version "1.1.2"
resolved "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-1.1.2.tgz#c44fdde3ce66b52e8d321d6c1bf46101f0150610"
integrity sha512-sIrXwyna2+5b0eB9W149izTPJk/KkJTg6mEzDGibwBUkyH1SbDa+nf515Ppdi3MaH35lW0JFJDWeq9Luzes1Iw==
character-entities-legacy@^1.0.0:
version "1.1.2"
resolved "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.2.tgz#7c6defb81648498222c9855309953d05f4d63a9c"
integrity sha512-9NB2VbXtXYWdXzqrvAHykE/f0QJxzaKIpZ5QzNZrrgQ7Iyxr2vnfS8fCBNVW9nUEZE0lo57nxKRqnzY/dKrwlA==
character-entities@^1.0.0:
version "1.2.2"
resolved "https://registry.npmjs.org/character-entities/-/character-entities-1.2.2.tgz#58c8f371c0774ef0ba9b2aca5f00d8f100e6e363"
integrity sha512-sMoHX6/nBiy3KKfC78dnEalnpn0Az0oSNvqUWYTtYrhRI5iUIYsROU48G+E+kMFQzqXaJ8kHJZ85n7y6/PHgwQ==
character-reference-invalid@^1.0.0:
version "1.1.2"
resolved "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.2.tgz#21e421ad3d84055952dab4a43a04e73cd425d3ed"
integrity sha512-7I/xceXfKyUJmSAn/jw8ve/9DyOP7XxufNYLI9Px7CmsKgEUaZLUTax6nZxGQtaoiZCjpu6cHPj20xC/vqRReQ==
collapse-white-space@^1.0.0, collapse-white-space@^1.0.2:
version "1.0.4"
resolved "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.4.tgz#ce05cf49e54c3277ae573036a26851ba430a0091"
integrity sha512-YfQ1tAUZm561vpYD+5eyWN8+UsceQbSrqqlc/6zDY2gtAE+uZLSdkkovhnGpmCThsvKBFakq4EdY/FF93E8XIw==
comma-separated-tokens@^1.0.0, comma-separated-tokens@^1.0.1:
version "1.0.5"
resolved "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.5.tgz#b13793131d9ea2d2431cf5b507ddec258f0ce0db"
integrity sha512-Cg90/fcK93n0ecgYTAz1jaA3zvnQ0ExlmKY1rdbyHqAx6BHxwoJc+J7HDu0iuQ7ixEs1qaa+WyQ6oeuBpYP1iA==
dependencies:
trim "0.0.1"
detab@^2.0.0:
version "2.0.1"
resolved "https://registry.npmjs.org/detab/-/detab-2.0.1.tgz#531f5e326620e2fd4f03264a905fb3bcc8af4df4"
integrity sha512-/hhdqdQc5thGrqzjyO/pz76lDZ5GSuAs6goxOaKTsvPk7HNnzAyFN5lyHgqpX4/s1i66K8qMGj+VhA9504x7DQ==
dependencies:
repeat-string "^1.5.4"
doctype@^2.0.0:
version "2.0.2"
resolved "https://registry.npmjs.org/doctype/-/doctype-2.0.2.tgz#b791fb52f57f300a3e81d1b2816517c044ff1432"
integrity sha512-RuESV/brHB7HGyUWzlHvFaaHQspzld15CC0RG+nzbuD+KQNDvxWmbubGrhqwF0SJqbbEGt8lncSTtghI/vNb6Q==
extend@^3.0.0:
version "3.0.2"
resolved "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
hast-util-embedded@^1.0.0, hast-util-embedded@^1.0.1:
version "1.0.1"
resolved "https://registry.npmjs.org/hast-util-embedded/-/hast-util-embedded-1.0.1.tgz#2889896b4fd1d485a51cb9ce4f5bd17b47049eba"
integrity sha512-VreBCMxmSRCT7OjZihrth3ByA9GtLKbRyoDJafP/1vxAxx+VNdhHKKADCSIyMGvrvTExVRqU/BnVq51dxMLAeQ==
dependencies:
hast-util-is-element "^1.0.0"
hast-util-has-property@^1.0.0:
version "1.0.1"
resolved "https://registry.npmjs.org/hast-util-has-property/-/hast-util-has-property-1.0.1.tgz#ac08c40bcbf27b80a85aaae91e4f6250a53e802f"
integrity sha512-DUck5lp8ku3o8n9GIA1Nghdz8UQyis2/b/ro0O4z5HP/y82uzZL6CXehuQmY5re+rLgTP4MVF/YpYDj9YqD0wA==
hast-util-is-body-ok-link@^1.0.0:
version "1.0.1"
resolved "https://registry.npmjs.org/hast-util-is-body-ok-link/-/hast-util-is-body-ok-link-1.0.1.tgz#f5d8893f4f21fa1ae51c059ac29abdbc8e6e6046"
integrity sha512-qFDY0oz0lbc0DOcy61BSgJo+wi/ykFs4p95YjrtRP81eNfmBPs/Z0j4WLFmepJ6znfxLlRcPpic8FOdzCD5aKw==
dependencies:
hast-util-has-property "^1.0.0"
hast-util-is-element "^1.0.0"
hast-util-is-element@^1.0.0:
version "1.0.1"
resolved "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-1.0.1.tgz#c76e8aafbdb6e5c83265bf50324e2f2e024eb12a"
integrity sha512-s/ggaNehYVqmLgTXEv12Lbb72bsOD2r5DhAqPgtDdaI/YFNXVzz0zHFVJnhjIjn7Nak8GbL4nzT2q0RA5div+A==
hast-util-parse-selector@^2.2.0:
version "2.2.0"
resolved "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.0.tgz#2175f18cdd697308fc3431d5c29a9e48dfa4817a"
integrity sha512-trw0pqZN7+sH9k7hPWCJNZUbWW2KroSIM/XpIy3G5ZMtx9LSabCyoSp4skJZ4q/eZ5UOBPtvWh4W9c+RE3HRoQ==
hast-util-phrasing@^1.0.0:
version "1.0.1"
resolved "https://registry.npmjs.org/hast-util-phrasing/-/hast-util-phrasing-1.0.1.tgz#c2167222ac18c93459681aeba06d8169fd267de2"
integrity sha512-PS7eg0yzYyVsTEf82CyrY0nMevcjofTcs7ygi3m6ykggveKqmNc39+/1JWT478piWt3hq5gOsXbMoCxjRQi+rA==
dependencies:
hast-util-embedded "^1.0.0"
hast-util-has-property "^1.0.0"
hast-util-is-body-ok-link "^1.0.0"
hast-util-is-element "^1.0.0"
hast-util-to-html@^4.0.0:
version "4.0.1"
resolved "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-4.0.1.tgz#3666b05afb62bd69f8f5e6c94db04dea19438e2a"
integrity sha512-2emzwyf0xEsc4TBIPmDJmBttIw8R4SXAJiJZoiRR/s47ODYWgOqNoDbf2SJAbMbfNdFWMiCSOrI3OVnX6Qq2Mg==
dependencies:
ccount "^1.0.0"
comma-separated-tokens "^1.0.1"
hast-util-is-element "^1.0.0"
hast-util-whitespace "^1.0.0"
html-void-elements "^1.0.0"
property-information "^4.0.0"
space-separated-tokens "^1.0.0"
stringify-entities "^1.0.1"
unist-util-is "^2.0.0"
xtend "^4.0.1"
hast-util-whitespace@^1.0.0:
version "1.0.1"
resolved "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-1.0.1.tgz#d67da2c87637b1ce1d85dd15b270ba057930149a"
integrity sha512-Mfx2ZnmVMTAopZ8as42nKrNt650tCZYhy/MPeO1Imdg/cmCWK6GUSnFrrE3ezGjVifn7x5zMfu8jrjwIGyImSw==
hastscript@^4.0.0:
version "4.1.0"
resolved "https://registry.npmjs.org/hastscript/-/hastscript-4.1.0.tgz#ea5593fa6f6709101fc790ced818393ddaa045ce"
integrity sha512-bOTn9hEfzewvHyXdbYGKqOr/LOz+2zYhKbC17U2YAjd16mnjqB1BQ0nooM/RdMy/htVyli0NAznXiBtwDi1cmQ==
dependencies:
comma-separated-tokens "^1.0.0"
hast-util-parse-selector "^2.2.0"
property-information "^4.0.0"
space-separated-tokens "^1.0.0"
html-void-elements@^1.0.0:
version "1.0.3"
resolved "https://registry.npmjs.org/html-void-elements/-/html-void-elements-1.0.3.tgz#956707dbecd10cf658c92c5d27fee763aa6aa982"
integrity sha512-SaGhCDPXJVNrQyKMtKy24q6IMdXg5FCPN3z+xizxw9l+oXQw5fOoaj/ERU5KqWhSYhXtW5bWthlDbTDLBhJQrA==
html-whitespace-sensitive-tag-names@^1.0.0:
version "1.0.0"
resolved "https://registry.npmjs.org/html-whitespace-sensitive-tag-names/-/html-whitespace-sensitive-tag-names-1.0.0.tgz#fd6ed3a3d631ce29341aefe26a8fea720d3adfa7"
integrity sha1-/W7To9Yxzik0Gu/iao/qcg0636c=
inherits@^2.0.1:
version "2.0.3"
resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
is-alphabetical@^1.0.0:
version "1.0.2"
resolved "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.2.tgz#1fa6e49213cb7885b75d15862fb3f3d96c884f41"
integrity sha512-V0xN4BYezDHcBSKb1QHUFMlR4as/XEuCZBzMJUU4n7+Cbt33SmUnSol+pnXFvLxSHNq2CemUXNdaXV6Flg7+xg==
is-alphanumerical@^1.0.0:
version "1.0.2"
resolved "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.2.tgz#1138e9ae5040158dc6ff76b820acd6b7a181fd40"
integrity sha512-pyfU/0kHdISIgslFfZN9nfY1Gk3MquQgUm1mJTjdkEPpkAKNWuBTSqFwewOpR7N351VkErCiyV71zX7mlQQqsg==
dependencies:
is-alphabetical "^1.0.0"
is-decimal "^1.0.0"
is-buffer@^2.0.0:
version "2.0.3"
resolved "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz#4ecf3fcf749cbd1e472689e109ac66261a25e725"
integrity sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==
is-decimal@^1.0.0:
version "1.0.2"
resolved "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.2.tgz#894662d6a8709d307f3a276ca4339c8fa5dff0ff"
integrity sha512-TRzl7mOCchnhchN+f3ICUCzYvL9ul7R+TYOsZ8xia++knyZAJfv/uA1FvQXsAnYIl1T3B2X5E/J7Wb1QXiIBXg==
is-hexadecimal@^1.0.0:
version "1.0.2"
resolved "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.2.tgz#b6e710d7d07bb66b98cb8cece5c9b4921deeb835"
integrity sha512-but/G3sapV3MNyqiDBLrOi4x8uCIw0RY3o/Vb5GT0sMFHrVV7731wFSVy41T5FO1og7G0gXLJh0MkgPRouko/A==
is-plain-obj@^1.1.0:
version "1.1.0"
resolved "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e"
integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4=
is-whitespace-character@^1.0.0:
version "1.0.2"
resolved "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.2.tgz#ede53b4c6f6fb3874533751ec9280d01928d03ed"
integrity sha512-SzM+T5GKUCtLhlHFKt2SDAX2RFzfS6joT91F2/WSi9LxgFdsnhfPK/UIA+JhRR2xuyLdrCys2PiFDrtn1fU5hQ==
is-word-character@^1.0.0:
version "1.0.2"
resolved "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.2.tgz#46a5dac3f2a1840898b91e576cd40d493f3ae553"
integrity sha512-T3FlsX8rCHAH8e7RE7PfOPZVFQlcV3XRF9eOOBQ1uf70OxO7CjjSOjeImMPCADBdYWcStAbVbYvJ1m2D3tb+EA==
markdown-escapes@^1.0.0:
version "1.0.2"
resolved "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.2.tgz#e639cbde7b99c841c0bacc8a07982873b46d2122"
integrity sha512-lbRZ2mE3Q9RtLjxZBZ9+IMl68DKIXaVAhwvwn9pmjnPLS0h/6kyBMgNhqi1xFJ/2yv6cSyv0jbiZavZv93JkkA==
mdast-util-definitions@^1.2.0:
version "1.2.3"
resolved "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-1.2.3.tgz#49f936b09207c45b438db19551652934312f04f0"
integrity sha512-P6wpRO8YVQ1iv30maMc93NLh7COvufglBE8/ldcOyYmk5EbfF0YeqlLgtqP/FOBU501Kqar1x5wYWwB3Nga74g==
dependencies:
unist-util-visit "^1.0.0"
mdast-util-to-hast@^3.0.0:
version "3.0.2"
resolved "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-3.0.2.tgz#26b1971f49d6db1e3428463a12e66c89db5021cb"
integrity sha512-YI8Ea3TFWEZrS31+6Q/d8ZYTOSDKM06IPc3l2+OMFX1o3JTG2mrztlmzDsUMwIXLWofEdTVl/WXBgRG6ddlU/A==
dependencies:
collapse-white-space "^1.0.0"
detab "^2.0.0"
mdast-util-definitions "^1.2.0"
mdurl "^1.0.1"
trim "0.0.1"
trim-lines "^1.0.0"
unist-builder "^1.0.1"
unist-util-generated "^1.1.0"
unist-util-position "^3.0.0"
unist-util-visit "^1.1.0"
xtend "^4.0.1"
mdurl@^1.0.1:
version "1.0.1"
resolved "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e"
integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=
object-assign@^4.1.0:
version "4.1.1"
resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
once@^1.4.0:
version "1.4.0"
resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
dependencies:
wrappy "1"
parse-entities@^1.1.0:
version "1.2.0"
resolved "https://registry.npmjs.org/parse-entities/-/parse-entities-1.2.0.tgz#9deac087661b2e36814153cb78d7e54a4c5fd6f4"
integrity sha512-XXtDdOPLSB0sHecbEapQi6/58U/ODj/KWfIXmmMCJF/eRn8laX6LZbOyioMoETOOJoWRW8/qTSl5VQkUIfKM5g==
dependencies:
character-entities "^1.0.0"
character-entities-legacy "^1.0.0"
character-reference-invalid "^1.0.0"
is-alphanumerical "^1.0.0"
is-decimal "^1.0.0"
is-hexadecimal "^1.0.0"
property-information@^4.0.0:
version "4.2.0"
resolved "https://registry.npmjs.org/property-information/-/property-information-4.2.0.tgz#f0e66e07cbd6fed31d96844d958d153ad3eb486e"
integrity sha512-TlgDPagHh+eBKOnH2VYvk8qbwsCG/TAJdmTL7f1PROUcSO8qt/KSmShEQ/OKvock8X9tFjtqjCScyOkkkvIKVQ==
dependencies:
xtend "^4.0.1"
rehype-document@^2.2.0:
version "2.2.0"
resolved "https://registry.npmjs.org/rehype-document/-/rehype-document-2.2.0.tgz#cf884a1b05811c3f1f46ec7e85ffb59d60c1e134"
integrity sha512-/eIHrU84/mdikF2HjEh1zcfylKjj6xlga9MPS3nvv50gO5xAsjtqHPZ2Jom0XUfgsOQkqvV9S/HzqrTTjWQq0A==
dependencies:
doctype "^2.0.0"
hastscript "^4.0.0"
unist-builder "^1.0.1"
rehype-format@^2.3.0:
version "2.3.0"
resolved "https://registry.npmjs.org/rehype-format/-/rehype-format-2.3.0.tgz#ebbf6b8579e8194574c1ac4dfb306c29c0b074da"
integrity sha512-uv09q8BdbeRIo5LLrt8cMnONX6HUvpzvcwxjLiC5XLIeYb6KA7AS2inSJXQJ1Wu2B5rHK8CQgcoiig4Jr8krGA==
dependencies:
hast-util-embedded "^1.0.1"
hast-util-phrasing "^1.0.0"
html-whitespace-sensitive-tag-names "^1.0.0"
rehype-minify-whitespace "^2.0.0"
repeat-string "^1.5.4"
unist-util-visit-parents "^1.0.0"
rehype-minify-whitespace@^2.0.0:
version "2.0.3"
resolved "https://registry.npmjs.org/rehype-minify-whitespace/-/rehype-minify-whitespace-2.0.3.tgz#9aef3b73d0dfbcf890844d10d8f45fd5bdf145ec"
integrity sha512-KzOH3F92J7Wvr3WuaqSO69FuN+vwbitVYxdSolLXrwLwdo67VXn/qSYGR7gnYDJKgfm/+m3l8hZHY43Zg+YscQ==
dependencies:
collapse-white-space "^1.0.0"
hast-util-embedded "^1.0.0"
hast-util-has-property "^1.0.0"
hast-util-is-body-ok-link "^1.0.0"
hast-util-is-element "^1.0.0"
html-whitespace-sensitive-tag-names "^1.0.0"
unist-util-is "^2.0.0"
unist-util-modify-children "^1.0.0"
rehype-stringify@^4.0.0:
version "4.0.0"
resolved "https://registry.npmjs.org/rehype-stringify/-/rehype-stringify-4.0.0.tgz#2efd32f81862f9ab05c738b0d1ebe8a32fa87dac"
integrity sha512-ZWBQg2fW3/75jms314hu4YIqqlAwXdbzpmwd4ez/q4nKA/zKnVUKso0xe6PfGr5Xy5GXpn4uDr9gAYgBXam7vA==
dependencies:
hast-util-to-html "^4.0.0"
xtend "^4.0.1"
remark-parse@^6.0.1:
version "6.0.1"
resolved "https://registry.npmjs.org/remark-parse/-/remark-parse-6.0.1.tgz#62bc4fc91045dbb0a9fc6900150b0404e2598e99"
integrity sha512-H9h8c/uafJAoVoHvIBMzWuUDxDckW7+tc60/OkstZQw6fv7qDX6ALl3A8a1G6aRrx1s4WeaF0spm4WbXHAHcOw==
dependencies:
collapse-white-space "^1.0.2"
is-alphabetical "^1.0.0"
is-decimal "^1.0.0"
is-whitespace-character "^1.0.0"
is-word-character "^1.0.0"
markdown-escapes "^1.0.0"
parse-entities "^1.1.0"
repeat-string "^1.5.4"
state-toggle "^1.0.0"
trim "0.0.1"
trim-trailing-lines "^1.0.0"
unherit "^1.0.4"
unist-util-remove-position "^1.0.0"
vfile-location "^2.0.0"
xtend "^4.0.1"
remark-rehype@^3.0.1:
version "3.0.1"
resolved "https://registry.npmjs.org/remark-rehype/-/remark-rehype-3.0.1.tgz#7c35c08e022ca55bd33719548dd555b1a721a181"
integrity sha512-A9oIvjlUwY2qLNrgoH7MxQb6EEs7kgdOXLtY/5CYCnvsupor7e7gTGmfkzccBkqJ/6nkbEdiX3hfY11FAvYGHg==
dependencies:
mdast-util-to-hast "^3.0.0"
repeat-string@^1.5.4:
version "1.6.1"
resolved "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637"
integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc=
replace-ext@1.0.0:
version "1.0.0"
resolved "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb"
integrity sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=
space-separated-tokens@^1.0.0:
version "1.1.2"
resolved "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.2.tgz#e95ab9d19ae841e200808cd96bc7bd0adbbb3412"
integrity sha512-G3jprCEw+xFEs0ORweLmblJ3XLymGGr6hxZYTYZjIlvDti9vOBUjRQa1Rzjt012aRrocKstHwdNi+F7HguPsEA==
dependencies:
trim "0.0.1"
state-toggle@^1.0.0:
version "1.0.1"
resolved "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.1.tgz#c3cb0974f40a6a0f8e905b96789eb41afa1cde3a"
integrity sha512-Qe8QntFrrpWTnHwvwj2FZTgv+PKIsp0B9VxLzLLbSpPXWOgRgc5LVj/aTiSfK1RqIeF9jeC1UeOH8Q8y60A7og==
stringify-entities@^1.0.1:
version "1.3.2"
resolved "https://registry.npmjs.org/stringify-entities/-/stringify-entities-1.3.2.tgz#a98417e5471fd227b3e45d3db1861c11caf668f7"
integrity sha512-nrBAQClJAPN2p+uGCVJRPIPakKeKWZ9GtBCmormE7pWOSlHat7+x5A8gx85M7HM5Dt0BP3pP5RhVW77WdbJJ3A==
dependencies:
character-entities-html4 "^1.0.0"
character-entities-legacy "^1.0.0"
is-alphanumerical "^1.0.0"
is-hexadecimal "^1.0.0"
trim-lines@^1.0.0:
version "1.1.1"
resolved "https://registry.npmjs.org/trim-lines/-/trim-lines-1.1.1.tgz#da738ff58fa74817588455e30b11b85289f2a396"
integrity sha512-X+eloHbgJGxczUk1WSjIvn7aC9oN3jVE3rQfRVKcgpavi3jxtCn0VVKtjOBj64Yop96UYn/ujJRpTbCdAF1vyg==
trim-trailing-lines@^1.0.0:
version "1.1.1"
resolved "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.1.tgz#e0ec0810fd3c3f1730516b45f49083caaf2774d9"
integrity sha512-bWLv9BbWbbd7mlqqs2oQYnLD/U/ZqeJeJwbO0FG2zA1aTq+HTvxfHNKFa/HGCVyJpDiioUYaBhfiT6rgk+l4mg==
trim@0.0.1:
version "0.0.1"
resolved "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz#5858547f6b290757ee95cccc666fb50084c460dd"
integrity sha1-WFhUf2spB1fulczMZm+1AITEYN0=
trough@^1.0.0:
version "1.0.3"
resolved "https://registry.npmjs.org/trough/-/trough-1.0.3.tgz#e29bd1614c6458d44869fc28b255ab7857ef7c24"
integrity sha512-fwkLWH+DimvA4YCy+/nvJd61nWQQ2liO/nF/RjkTpiOGi+zxZzVkhb1mvbHIIW4b/8nDsYI8uTmAlc0nNkRMOw==
unherit@^1.0.4:
version "1.1.1"
resolved "https://registry.npmjs.org/unherit/-/unherit-1.1.1.tgz#132748da3e88eab767e08fabfbb89c5e9d28628c"
integrity sha512-+XZuV691Cn4zHsK0vkKYwBEwB74T3IZIcxrgn2E4rKwTfFyI1zCh7X7grwh9Re08fdPlarIdyWgI8aVB3F5A5g==
dependencies:
inherits "^2.0.1"
xtend "^4.0.1"
unified-stream@^1.0.2:
version "1.0.2"
resolved "https://registry.npmjs.org/unified-stream/-/unified-stream-1.0.2.tgz#e905138dfb0ffbb2e64e49b2ea89fc09e32a8ee5"
integrity sha512-hMPof8kORTeQwHjZ14rSM7Bb0prwFkjt248n9ZLkRBbxRLG3cIb+9htMRxMoGx8A3OiyTx3qfUZEcPV1P5a/YQ==
dependencies:
once "^1.4.0"
unified@^7.0.0:
version "7.0.0"
resolved "https://registry.npmjs.org/unified/-/unified-7.0.0.tgz#9c8f4fcee78f8e7e895f0e3d6adb53bd015e1a53"
integrity sha512-j+Sm7upmmt3RXPBeA+KFGYBlHBxClnby2DtxezFKwMfhWTAklY4WbEdhwRo6c6GpuHdi04YDsyPKY/kh5a/xnQ==
dependencies:
bail "^1.0.0"
extend "^3.0.0"
is-plain-obj "^1.1.0"
trough "^1.0.0"
vfile "^3.0.0"
x-is-string "^0.1.0"
unist-builder@^1.0.1:
version "1.0.3"
resolved "https://registry.npmjs.org/unist-builder/-/unist-builder-1.0.3.tgz#ab0f9d0f10936b74f3e913521955b0478e0ff036"
integrity sha512-/KB8GEaoeHRyIqClL+Kam+Y5NWJ6yEiPsAfv1M+O1p+aKGgjR89WwoEHKTyOj17L6kAlqtKpAgv2nWvdbQDEig==
dependencies:
object-assign "^4.1.0"
unist-util-generated@^1.1.0:
version "1.1.2"
resolved "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.2.tgz#8b993f9239d8e560be6ee6e91c3f7b7208e5ce25"
integrity sha512-1HcwiEO62dr0XWGT+abVK4f0aAm8Ik8N08c5nAYVmuSxfvpA9rCcNyX/le8xXj1pJK5nBrGlZefeWB6bN8Pstw==
unist-util-is@^2.0.0, unist-util-is@^2.1.2:
version "2.1.2"
resolved "https://registry.npmjs.org/unist-util-is/-/unist-util-is-2.1.2.tgz#1193fa8f2bfbbb82150633f3a8d2eb9a1c1d55db"
integrity sha512-YkXBK/H9raAmG7KXck+UUpnKiNmUdB+aBGrknfQ4EreE1banuzrKABx3jP6Z5Z3fMSPMQQmeXBlKpCbMwBkxVw==
unist-util-modify-children@^1.0.0:
version "1.1.3"
resolved "https://registry.npmjs.org/unist-util-modify-children/-/unist-util-modify-children-1.1.3.tgz#d764a935f612dfb21b1bb92b0ea24321dc19a5f7"
integrity sha512-Aw3Us+NPrJGYWyLhcaqYzgxd/pryIanDNHVVvwdtTEEQ3Yfa/+sjnT2EeAAHbtTMAaYEdPW3XN6jxbzVWAo/BQ==
dependencies:
array-iterate "^1.0.0"
unist-util-position@^3.0.0:
version "3.0.1"
resolved "https://registry.npmjs.org/unist-util-position/-/unist-util-position-3.0.1.tgz#8e220c24658239bf7ddafada5725ed0ea1ebbc26"
integrity sha512-05QfJDPI7PE1BIUtAxeSV+cDx21xP7+tUZgSval5CA7tr0pHBwybF7OnEa1dOFqg6BfYH/qiMUnWwWj+Frhlww==
unist-util-remove-position@^1.0.0:
version "1.1.2"
resolved "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.2.tgz#86b5dad104d0bbfbeb1db5f5c92f3570575c12cb"
integrity sha512-XxoNOBvq1WXRKXxgnSYbtCF76TJrRoe5++pD4cCBsssSiWSnPEktyFrFLE8LTk3JW5mt9hB0Sk5zn4x/JeWY7Q==
dependencies:
unist-util-visit "^1.1.0"
unist-util-stringify-position@^1.0.0, unist-util-stringify-position@^1.1.1:
version "1.1.2"
resolved "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz#3f37fcf351279dcbca7480ab5889bb8a832ee1c6"
integrity sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ==
unist-util-visit-parents@^1.0.0:
version "1.1.2"
resolved "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-1.1.2.tgz#f6e3afee8bdbf961c0e6f028ea3c0480028c3d06"
integrity sha512-yvo+MMLjEwdc3RhhPYSximset7rwjMrdt9E41Smmvg25UQIenzrN83cRnF1JMzoMi9zZOQeYXHSDf7p+IQkW3Q==
unist-util-visit-parents@^2.0.0:
version "2.0.1"
resolved "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.0.1.tgz#63fffc8929027bee04bfef7d2cce474f71cb6217"
integrity sha512-6B0UTiMfdWql4cQ03gDTCSns+64Zkfo2OCbK31Ov0uMizEz+CJeAp0cgZVb5Fhmcd7Bct2iRNywejT0orpbqUA==
dependencies:
unist-util-is "^2.1.2"
unist-util-visit@^1.0.0, unist-util-visit@^1.1.0:
version "1.4.0"
resolved "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.0.tgz#1cb763647186dc26f5e1df5db6bd1e48b3cc2fb1"
integrity sha512-FiGu34ziNsZA3ZUteZxSFaczIjGmksfSgdKqBfOejrrfzyUy5b7YrlzT1Bcvi+djkYDituJDy2XB7tGTeBieKw==
dependencies:
unist-util-visit-parents "^2.0.0"
vfile-location@^2.0.0:
version "2.0.3"
resolved "https://registry.npmjs.org/vfile-location/-/vfile-location-2.0.3.tgz#083ba80e50968e8d420be49dd1ea9a992131df77"
integrity sha512-zM5/l4lfw1CBoPx3Jimxoc5RNDAHHpk6AM6LM0pTIkm5SUSsx8ZekZ0PVdf0WEZ7kjlhSt7ZlqbRL6Cd6dBs6A==
vfile-message@^1.0.0:
version "1.0.1"
resolved "https://registry.npmjs.org/vfile-message/-/vfile-message-1.0.1.tgz#51a2ccd8a6b97a7980bb34efb9ebde9632e93677"
integrity sha512-vSGCkhNvJzO6VcWC6AlJW4NtYOVtS+RgCaqFIYUjoGIlHnFL+i0LbtYvonDWOMcB97uTPT4PRsyYY7REWC9vug==
dependencies:
unist-util-stringify-position "^1.1.1"
vfile@^3.0.0:
version "3.0.1"
resolved "https://registry.npmjs.org/vfile/-/vfile-3.0.1.tgz#47331d2abe3282424f4a4bb6acd20a44c4121803"
integrity sha512-y7Y3gH9BsUSdD4KzHsuMaCzRjglXN0W2EcMf0gpvu6+SbsGhMje7xDc8AEoeXy6mIwCKMI6BkjMsRjzQbhMEjQ==
dependencies:
is-buffer "^2.0.0"
replace-ext "1.0.0"
unist-util-stringify-position "^1.0.0"
vfile-message "^1.0.0"
wrappy@1:
version "1.0.2"
resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
x-is-string@^0.1.0:
version "0.1.0"
resolved "https://registry.npmjs.org/x-is-string/-/x-is-string-0.1.0.tgz#474b50865af3a49a9c4657f05acd145458f77d82"
integrity sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI=
xtend@^4.0.1:
version "4.0.1"
resolved "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"
integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68=

View File

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

View File

@@ -1,52 +0,0 @@
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'); // 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'); // eslint-disable-line import/no-extraneous-dependencies
const writeFile = promisify(fs.writeFile);
exports.build = async ({
files, entrypoint, workPath, meta,
}) => {
console.log('downloading user files...');
const downloadedFiles = await download(files, workPath, meta);
console.log('writing package.json...');
const packageJson = { dependencies: { 'mdx-deck': '1.7.15' } };
const packageJsonPath = path.join(workPath, 'package.json');
await writeFile(packageJsonPath, JSON.stringify(packageJson));
console.log('installing dependencies...');
process.env.PUPPETEER_SKIP_CHROMIUM_DOWNLOAD = '1'; // TODO opts argument for runNpmInstall
await runNpmInstall(path.dirname(packageJsonPath), [
'--prod',
'--prefer-offline',
]);
console.log('building...');
const outDir = await getWritableDirectory();
const entrypointFsPath = downloadedFiles[entrypoint].fsPath;
const mountpoint = path.dirname(entrypoint);
const build = require(path.join(
workPath,
'node_modules/mdx-deck/lib/build.js',
));
await build({
html: true,
dirname: workPath,
outDir,
globals: {
FILENAME: JSON.stringify(entrypointFsPath),
},
});
return glob('**', outDir, mountpoint);
};
exports.prepareCache = async ({ workPath }) => ({
...(await glob('node_modules/**', workPath)),
...(await glob('package-lock.json', workPath)),
...(await glob('yarn.lock', workPath)),
});

View File

@@ -1,14 +0,0 @@
{
"name": "@now/mdx-deck",
"version": "0.5.5",
"license": "MIT",
"homepage": "https://zeit.co/docs/v2/deployments/official-builders/mdx-deck-now-mdx-deck",
"repository": {
"type": "git",
"url": "https://github.com/zeit/now-builders.git",
"directory": "packages/now-mdx-deck"
},
"scripts": {
"test": "jest"
}
}

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
{
"name": "@now/next",
"version": "0.5.4",
"version": "0.5.5",
"license": "MIT",
"main": "./dist/index",
"homepage": "https://zeit.co/docs/v2/deployments/official-builders/next-js-now-next",
@@ -15,7 +15,7 @@
"directory": "packages/now-next"
},
"dependencies": {
"@now/node-bridge": "1.2.2",
"@now/node-bridge": "1.2.3",
"fs-extra": "^7.0.0",
"get-port": "^5.0.0",
"resolve-from": "^5.0.0",
@@ -28,7 +28,6 @@
"@types/next-server": "^8.0.0",
"@types/resolve-from": "^5.0.1",
"@types/semver": "^6.0.0",
"jest": "^24.7.1",
"typescript": "3.5.2"
}
}

View File

@@ -151,10 +151,6 @@ function startDevServer(entryPath: string, runtimeEnv: EnvConfig) {
return { forked, getUrl };
}
export const config = {
maxLambdaSize: '5mb',
};
export const build = async ({
files,
workPath,
@@ -416,7 +412,8 @@ export const build = async ({
const pathname = page.replace(/\.html$/, '');
if (isDynamicRoute(pathname)) {
dynamicPages.push(pathname);
dynamicPages.push(normalizePage(pathname));
return;
}
exportedPageRoutes.push({
@@ -511,6 +508,8 @@ export const build = async ({
}),
{}
);
let dynamicPrefix = path.join('/', entryDirectory);
dynamicPrefix = dynamicPrefix === '/' ? '' : dynamicPrefix;
let dynamicRoutes = getDynamicRoutes(
entryPath,
@@ -522,6 +521,7 @@ export const build = async ({
if (staticPages[`${route.dest}.html`.substr(1)]) {
route.dest = `${route.dest}.html`;
}
route.src = route.src.replace('^', `^${dynamicPrefix}`);
return route;
});

View File

@@ -236,6 +236,7 @@ function getRoutes(
if (isDynamicRoute(pageName)) {
dynamicPages.push(normalizePage(pageName));
continue;
}
routes.push({
@@ -257,7 +258,10 @@ function getRoutes(
...getDynamicRoutes(entryPath, entryDirectory, dynamicPages).map(
(route: { src: string; dest: string }) => {
// convert to make entire RegExp match as one group
route.src = route.src.replace('^', '^(').replace('$', ')$');
route.src = route.src
.replace('^', `^${prefix}(`)
.replace('(\\/', '(')
.replace('$', ')$');
route.dest = `${url}/$1`;
return route;
}
@@ -289,7 +293,8 @@ function getRoutes(
export function getDynamicRoutes(
entryPath: string,
entryDirectory: string,
dynamicPages: string[]
dynamicPages: string[],
isDev?: boolean
): { src: string; dest: string }[] {
if (!dynamicPages.length) {
return [];
@@ -324,9 +329,14 @@ export function getDynamicRoutes(
const routes: { src: string; dest: string }[] = [];
pageMatchers.forEach(pageMatcher => {
// in `now dev` we don't need to prefix the destination
const dest = !isDev
? path.join('/', entryDirectory, pageMatcher.pageName)
: pageMatcher.pageName;
routes.push({
src: pageMatcher.matcher.source,
dest: path.join('/', entryDirectory, pageMatcher.pageName),
dest,
});
});
return routes;

View File

@@ -1,6 +1,6 @@
{
"name": "@now/node-bridge",
"version": "1.2.2",
"version": "1.2.3",
"license": "MIT",
"main": "./index.js",
"repository": {
@@ -19,8 +19,6 @@
},
"devDependencies": {
"@types/aws-lambda": "8.10.19",
"@types/node": "11.9.4",
"jest": "24.1.0",
"typescript": "3.5.2"
}
}

View File

@@ -44,7 +44,7 @@ interface ServerLike {
* error here and force the process to exit so that the lambda invocation
* returns an Unhandled error quickly.
*/
process.on('unhandledRejection', (err: Error) => {
process.on('unhandledRejection', err => {
console.error('Unhandled rejection:', err);
process.exit(1);
});

View File

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

View File

@@ -1,178 +0,0 @@
const fs = require('fs-extra');
const path = require('path');
const {
FileBlob,
FileFsRef,
download,
createLambda,
glob,
runNpmInstall,
runPackageJsonScript,
getNodeVersion,
getSpawnOptions,
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 */
/**
* @typedef {Object} BuildParamsType
* @property {Files} files - Files object
* @property {string} entrypoint - Entrypoint specified for the builder
* @property {Object} config - User-passed config from now.json
* @property {string} workPath - Working directory for this build
*/
/**
* @param {BuildParamsType} buildParams
* @param {Object} [options]
* @param {string[]} [options.npmArguments]
*/
async function downloadInstallAndBundle(
{
files, entrypoint, workPath, meta,
},
{ npmArguments = [] } = {},
) {
console.log('downloading user files...');
const downloadedFiles = await download(files, workPath, meta);
console.log("installing dependencies for user's code...");
const entrypointFsDirname = path.join(workPath, path.dirname(entrypoint));
const nodeVersion = await getNodeVersion(entrypointFsDirname);
const spawnOpts = getSpawnOptions(meta, nodeVersion);
await runNpmInstall(entrypointFsDirname, npmArguments, spawnOpts);
return {
downloadedFiles,
entrypointFsDirname,
spawnOpts,
nodeVersion,
};
}
async function compile(workPath, downloadedFiles, entrypoint, config) {
const input = downloadedFiles[entrypoint].fsPath;
const inputDir = path.dirname(input);
const ncc = require('@zeit/ncc');
const { code, map, assets } = await ncc(input, {
sourceMap: true,
sourceMapRegister: true,
});
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 includeFiles) {
// eslint-disable-next-line no-await-in-loop
const files = await glob(pattern, inputDir);
// eslint-disable-next-line no-restricted-syntax
for (const assetName of Object.keys(files)) {
const stream = files[assetName].toStream();
const { mode } = files[assetName];
// eslint-disable-next-line no-await-in-loop
const { data } = await FileBlob.fromStream({ stream });
assets[assetName] = {
source: data,
permissions: mode,
};
}
}
}
const preparedFiles = {};
// move all user code to 'user' subdirectory
preparedFiles[entrypoint] = new FileBlob({ data: code });
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];
const blob2 = new FileBlob({ data, mode });
preparedFiles[path.join(path.dirname(entrypoint), assetName)] = blob2;
}
return preparedFiles;
}
exports.config = {
maxLambdaSize: '15mb',
};
/**
* @param {BuildParamsType} buildParams
* @returns {Promise<Files>}
*/
exports.build = async ({
files, entrypoint, config, workPath, meta = {},
}) => {
const {
downloadedFiles,
entrypointFsDirname,
spawnOptions,
nodeVersion,
} = await downloadInstallAndBundle(
{
files,
entrypoint,
workPath,
meta,
},
{ npmArguments: ['--prefer-offline'] },
);
console.log('running user script...');
await runPackageJsonScript(entrypointFsDirname, 'now-build', spawnOptions);
console.log('preparing lambda files...');
let preparedFiles;
if (config && config.bundle === false) {
preparedFiles = await glob('**', workPath);
} else {
console.log('compiling entrypoint with ncc...');
preparedFiles = await compile(
workPath,
downloadedFiles,
entrypoint,
config,
);
}
const launcherPath = path.join(__dirname, 'launcher.js');
let launcherData = await fs.readFile(launcherPath, 'utf8');
launcherData = launcherData.replace(
'// PLACEHOLDER',
[`require("./${entrypoint}");`].join(' '),
);
const launcherFiles = {
'launcher.js': new FileBlob({ data: launcherData }),
'bridge.js': new FileFsRef({ fsPath: require('@now/node-bridge') }),
};
// Use the system-installed version of `node` when running via `now dev`
const runtime = meta.isDev ? 'nodejs' : nodeVersion.runtime;
const lambda = await createLambda({
files: { ...preparedFiles, ...launcherFiles },
handler: 'launcher.launcher',
runtime,
});
return { [entrypoint]: lambda };
};
exports.prepareCache = async ({ workPath }) => ({
...(await glob('node_modules/**', workPath)),
...(await glob('package-lock.json', workPath)),
...(await glob('yarn.lock', workPath)),
});
exports.shouldServe = shouldServe;

View File

@@ -1,32 +0,0 @@
const { Server } = require('http');
const { Bridge } = require('./bridge.js');
const bridge = new Bridge();
const saveListen = Server.prototype.listen;
Server.prototype.listen = function listen() {
bridge.setServer(this);
Server.prototype.listen = saveListen;
return bridge.listen();
};
if (!process.env.NODE_ENV) {
process.env.NODE_ENV = process.env.NOW_REGION === 'dev1' ? 'development' : 'production';
}
try {
// PLACEHOLDER
} catch (err) {
if (err.code === 'MODULE_NOT_FOUND') {
console.error(err.message);
console.error(
'Did you forget to add it to "dependencies" in `package.json`?',
);
process.exit(1);
} else {
console.error(err);
process.exit(1);
}
}
exports.launcher = bridge.launcher;

View File

@@ -1,19 +0,0 @@
{
"name": "@now/node-server",
"version": "0.8.2",
"license": "MIT",
"homepage": "https://zeit.co/docs/v2/deployments/official-builders/node-js-server-now-node-server",
"repository": {
"type": "git",
"url": "https://github.com/zeit/now-builders.git",
"directory": "packages/now-node-server"
},
"dependencies": {
"@now/node-bridge": "1.2.2",
"@zeit/ncc": "0.18.5",
"fs-extra": "7.0.1"
},
"scripts": {
"test": "jest"
}
}

View File

@@ -1,11 +0,0 @@
const cowsay = require('cowsay').say;
const http = require('http');
// test that process.env is not replaced by webpack
process.env.NODE_ENV = 'development';
const server = http.createServer((req, resp) => {
resp.end(cowsay({ text: 'cow:RANDOMNESS_PLACEHOLDER' }));
});
server.listen();

View File

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

View File

@@ -1,11 +0,0 @@
const yodasay = require('yodasay').say;
const http = require('http');
// test that process.env is not replaced by webpack
process.env.NODE_ENV = 'development';
const server = http.createServer((req, resp) => {
resp.end(yodasay({ text: 'yoda:RANDOMNESS_PLACEHOLDER' }));
});
server.listen();

View File

@@ -1,10 +0,0 @@
const assert = require('assert');
const http = require('http');
const server = http.createServer((req, resp) => {
assert(!process.env.RANDOMNESS_BUILD_ENV_VAR);
assert(process.env.RANDOMNESS_ENV_VAR);
resp.end('BUILD_TIME_PLACEHOLDER:build-env');
});
server.listen();

View File

@@ -1,12 +0,0 @@
const assert = require('assert');
const fs = require('fs');
assert(process.env.RANDOMNESS_BUILD_ENV_VAR);
assert(!process.env.RANDOMNESS_ENV_VAR);
fs.writeFileSync(
'index.js',
fs
.readFileSync('index.js', 'utf8')
.replace('BUILD_TIME_PLACEHOLDER', process.env.RANDOMNESS_BUILD_ENV_VAR),
);

View File

@@ -1,5 +0,0 @@
{
"scripts": {
"now-build": "node now-build.js"
}
}

View File

@@ -1,10 +0,0 @@
const assert = require('assert');
const http = require('http');
const server = http.createServer((req, resp) => {
assert(!process.env.RANDOMNESS_BUILD_ENV_VAR);
assert(process.env.RANDOMNESS_ENV_VAR);
resp.end(`${process.env.RANDOMNESS_ENV_VAR}:env`);
});
server.listen();

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,21 +0,0 @@
{
"version": 2,
"builds": [
{ "src": "with-bundle/index.js", "use": "@now/node-server" },
{
"src": "without-bundle/index.js",
"use": "@now/node-server",
"config": { "bundle": false }
}
],
"probes": [
{
"path": "/with-bundle",
"mustContain": "RANDOMNESS_PLACEHOLDER:with-bundle"
},
{
"path": "/without-bundle",
"mustContain": "RANDOMNESS_PLACEHOLDER:without-bundle"
}
]
}

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,24 +0,0 @@
const express = require('express');
const { ApolloServer, gql } = require('apollo-server-express');
const typeDefs = gql`
type Query {
hello: String
}
`;
const resolvers = {
Query: {
hello: () => 'apollo:RANDOMNESS_PLACEHOLDER',
},
};
const server = new ApolloServer({ typeDefs, resolvers, introspection: true });
const app = express();
server.applyMiddleware({ app });
app.get('/', (req, resp) => {
resp.redirect('/graphql');
});
app.listen({ port: 4000 });

View File

@@ -1,7 +0,0 @@
{
"dependencies": {
"apollo-server-express": "^2.2.2",
"express": "^4.16.4",
"graphql": "^14.0.2"
}
}

View File

@@ -1,13 +0,0 @@
{
"version": 2,
"builds": [{ "src": "apollo/index.js", "use": "@now/node-server" }],
"routes": [{ "src": "/.*", "dest": "apollo/index.js" }],
"probes": [
{
"path": "/graphql",
"method": "POST",
"body": { "query": "{hello}" },
"mustContain": "apollo:RANDOMNESS_PLACEHOLDER"
}
]
}

View File

@@ -1,5 +0,0 @@
const express = require('express');
const app = express();
app.listen();

View File

@@ -1,6 +0,0 @@
const express = require('express');
const app = express();
app.use(express.static('templates'));
app.listen();

View File

@@ -1,25 +0,0 @@
{
"version": 2,
"builds": [
{
"src": "index.js",
"use": "@now/node-server",
"config": {
"includeFiles": ["templates/**"]
}
},
{
"src": "accepts-string/index.js",
"use": "@now/node-server",
"config": {
"includeFiles": "templates/**"
}
}
],
"probes": [
{
"path": "/",
"mustContain": "Hello Now!"
}
]
}

View File

@@ -1,5 +0,0 @@
{
"dependencies": {
"express": "^4.16.4"
}
}

View File

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

View File

@@ -1,3 +1,4 @@
/dist
/src/bridge.d.ts
/src/bridge.ts
/test/fixtures/**/types.d.ts
/test/fixtures/11-symlinks/symlink

View File

@@ -1,12 +1,7 @@
#!/bin/bash
set -euo pipefail
bridge_entrypoint="$(node -p 'require.resolve("@now/node-bridge")')"
bridge_defs="$(dirname "$bridge_entrypoint")/bridge.d.ts"
if [ ! -e "$bridge_defs" ]; then
yarn install
fi
bridge_defs="$(dirname $(pwd))/now-node-bridge/src/bridge.ts"
cp -v "$bridge_defs" src
@@ -16,6 +11,8 @@ tsc
# todo: improve
# copy type file for ts test
cp dist/types.d.ts test/fixtures/15-helpers/ts/types.d.ts
# setup symlink for symlink test
ln -sf symlinked-asset test/fixtures/11-symlinks/symlink
# use types.d.ts as the main types export
mv dist/types.d.ts dist/types
@@ -27,3 +24,20 @@ rm dist/helpers.js
ncc build src/helpers.ts -o dist/helpers
mv dist/helpers/index.js dist/helpers.js
rm -rf dist/helpers
# build source-map-support/register for source maps
ncc build ../../node_modules/source-map-support/register -o dist/source-map-support
mv dist/source-map-support/index.js dist/source-map-support.js
rm -rf dist/source-map-support
# build typescript
ncc build ../../node_modules/typescript/lib/typescript -o dist/typescript
mv dist/typescript/index.js dist/typescript.js
mkdir -p dist/typescript/lib
mv dist/typescript/typescript/lib/*.js dist/typescript/lib/
mv dist/typescript/typescript/lib/*.d.ts dist/typescript/lib/
rm -r dist/typescript/typescript
ncc build src/index.ts -o dist/main
mv dist/main/index.js dist/index.js
rm -rf dist/main

View File

@@ -1,6 +1,6 @@
{
"name": "@now/node",
"version": "0.11.1",
"version": "0.12.0",
"license": "MIT",
"main": "./dist/index",
"homepage": "https://zeit.co/docs/v2/deployments/official-builders/node-js-now-node",
@@ -9,29 +9,31 @@
"url": "https://github.com/zeit/now-builders.git",
"directory": "packages/now-node"
},
"dependencies": {
"@now/node-bridge": "1.2.2",
"@types/node": "*",
"@zeit/ncc": "0.18.5",
"@zeit/ncc-watcher": "1.0.3"
},
"scripts": {
"build": "./build.sh",
"test": "npm run build && jest",
"prepublish": "npm run build"
"prepublishOnly": "npm run build"
},
"files": [
"dist"
],
"dependencies": {
"@types/node": "*"
},
"devDependencies": {
"@babel/core": "7.5.0",
"@babel/plugin-transform-modules-commonjs": "7.5.0",
"@types/content-type": "1.1.3",
"@types/cookie": "0.3.3",
"@types/etag": "1.8.0",
"@types/test-listen": "1.1.0",
"@zeit/ncc": "0.20.4",
"@zeit/node-file-trace": "0.2.1",
"content-type": "1.0.4",
"cookie": "0.4.0",
"etag": "1.8.1",
"node-fetch": "2.6.0",
"source-map-support": "0.5.12",
"test-listen": "1.1.0",
"typescript": "3.5.2"
}

View File

@@ -0,0 +1,30 @@
const babel = require('@babel/core');
const pluginTransformModulesCommonJs = require('@babel/plugin-transform-modules-commonjs');
export function compile(
filename: string,
source: string
): { code: string; map: any } {
return babel.transform(source, {
filename,
babelrc: false,
highlightCode: false,
compact: false,
sourceType: 'module',
sourceMaps: true,
parserOpts: {
plugins: [
'asyncGenerators',
'classProperties',
'classPrivateProperties',
'classPrivateMethods',
'optionalCatchBinding',
'objectRestSpread',
'numericSeparator',
'dynamicImport',
'importMeta',
],
},
plugins: [pluginTransformModulesCommonJs],
});
}

View File

@@ -1,3 +1,4 @@
// we intentionally import these types here
// to test that they are exported from index
// We intentionally import these types here
// which will fail at compile time if exports
// are not found in the index file
import { NowRequest, NowResponse } from './index';

View File

@@ -14,8 +14,8 @@ function getBodyParser(req: NowRequest, body: Buffer) {
return undefined;
}
const { parse: parseCT } = require('content-type');
const { type } = parseCT(req.headers['content-type']);
const { parse: parseContentType } = require('content-type');
const { type } = parseContentType(req.headers['content-type']);
if (type === 'application/json') {
try {
@@ -31,7 +31,7 @@ function getBodyParser(req: NowRequest, body: Buffer) {
if (type === 'application/x-www-form-urlencoded') {
const { parse: parseQS } = require('querystring');
// remark : querystring.parse does not produce an iterable object
// note: querystring.parse does not produce an iterable object
// https://nodejs.org/api/querystring.html#querystring_querystring_parse_str_sep_eq_options
return parseQS(body.toString());
}
@@ -84,7 +84,7 @@ function setCharset(type: string, charset: string) {
return format(parsed);
}
function createETag(body: any, encoding: string | undefined) {
function createETag(body: any, encoding: 'utf8' | undefined) {
const etag = require('etag');
const buf = !Buffer.isBuffer(body) ? Buffer.from(body, encoding) : body;
return etag(buf, { weak: true });
@@ -92,7 +92,7 @@ function createETag(body: any, encoding: string | undefined) {
function send(req: NowRequest, res: NowResponse, body: any): NowResponse {
let chunk: unknown = body;
let encoding: string | undefined;
let encoding: 'utf8' | undefined;
switch (typeof chunk) {
// string defaulting to html
@@ -176,9 +176,12 @@ function send(req: NowRequest, res: NowResponse, body: any): NowResponse {
if (req.method === 'HEAD') {
// skip body for HEAD
res.end();
} else {
// respond
} else if (encoding) {
// respond with encoding
res.end(chunk, encoding);
} else {
// respond without encoding
res.end(chunk);
}
return res;

View File

@@ -1,9 +1,9 @@
import { Assets, NccOptions } from '@zeit/ncc';
import { join, dirname, relative, sep } from 'path';
import { NccWatcher, WatcherResult } from '@zeit/ncc-watcher';
import { basename, dirname, join, relative, resolve, sep } from 'path';
import nodeFileTrace from '@zeit/node-file-trace';
import {
glob,
download,
File,
FileBlob,
FileFsRef,
Files,
@@ -19,9 +19,13 @@ import {
} from '@now/build-utils';
export { NowRequest, NowResponse } from './types';
import { makeLauncher } from './launcher';
import { readFileSync, lstatSync, readlinkSync, statSync } from 'fs';
import { Compile } from './typescript';
interface CompilerConfig {
debug?: boolean;
includeFiles?: string | string[];
excludeFiles?: string | string[];
}
interface DownloadOptions {
@@ -31,26 +35,18 @@ interface DownloadOptions {
meta: Meta;
}
const watchers: Map<string, NccWatcher> = new Map();
const libPathRegEx = /^node_modules|[\/\\]node_modules[\/\\]/;
const LAUNCHER_FILENAME = '___now_launcher';
const BRIDGE_FILENAME = '___now_bridge';
const HELPERS_FILENAME = '___now_helpers';
const SOURCEMAP_SUPPORT_FILENAME = '__sourcemap_support';
function getWatcher(entrypoint: string, options: NccOptions): NccWatcher {
let watcher = watchers.get(entrypoint);
if (!watcher) {
watcher = new NccWatcher(entrypoint, options);
watchers.set(entrypoint, watcher);
}
return watcher;
}
const S_IFMT = 61440; /* 0170000 type of file */
const S_IFLNK = 40960; /* 0120000 symbolic link */
function toBuffer(data: string | Buffer): Buffer {
if (typeof data === 'string') {
return Buffer.from(data, 'utf8');
}
return data;
function isSymbolicLink(mode: number): boolean {
return (mode & S_IFMT) === S_IFLNK;
}
async function downloadInstallAndBundle({
@@ -78,111 +74,212 @@ async function compile(
entrypoint: string,
config: CompilerConfig,
{ isDev, filesChanged, filesRemoved }: Meta
): Promise<{ preparedFiles: Files; watch: string[] }> {
const input = entrypointPath;
const inputDir = dirname(input);
const rootIncludeFiles = inputDir.split(sep).pop() || '';
const options: NccOptions = {
sourceMap: true,
sourceMapRegister: true,
};
let code: string;
let map: string | undefined;
let assets: Assets | undefined;
let watch: string[] = [];
if (isDev) {
const watcher = getWatcher(entrypointPath, options);
const result = await watcher.build(
Array.isArray(filesChanged)
? filesChanged.map(f => join(workPath, f))
: undefined,
Array.isArray(filesRemoved)
? filesRemoved.map(f => join(workPath, f))
: undefined
);
code = result.code;
map = result.map;
assets = result.assets;
watch = [...result.files, ...result.dirs, ...result.missing]
.filter(f => f.startsWith(workPath))
.map(f => relative(workPath, f))
.concat(Object.keys(assets || {}));
} else {
const ncc = require('@zeit/ncc');
const result = await ncc(input, {
sourceMap: true,
sourceMapRegister: true,
});
code = result.code;
map = result.map;
assets = result.assets;
}
): Promise<{
preparedFiles: Files;
shouldAddSourcemapSupport: boolean;
watch: string[];
}> {
const inputFiles = new Set<string>([entrypointPath]);
if (!assets) assets = {};
const sourceCache = new Map<string, string | Buffer | null>();
const fsCache = new Map<string, File>();
const tsCompiled = new Set<String>();
if (config && config.includeFiles) {
let shouldAddSourcemapSupport = false;
if (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)) {
const stream = files[assetName].toStream();
const { mode } = files[assetName];
const { data } = await FileBlob.fromStream({ stream });
let fullPath = join(rootIncludeFiles, assetName);
// if asset contain directory
// no need to use `rootIncludeFiles`
if (assetName.includes(sep)) {
fullPath = assetName;
}
assets[fullPath] = {
source: toBuffer(data),
permissions: mode,
};
}
const files = await glob(pattern, workPath);
await Promise.all(
Object.keys(files).map(async file => {
const entry: FileFsRef = files[file];
fsCache.set(file, entry);
const stream = entry.toStream();
const { data } = await FileBlob.fromStream({ stream });
if (file.endsWith('.ts') || file.endsWith('.tsx')) {
sourceCache.set(
file,
compileTypeScript(resolve(workPath, file), data.toString())
);
} else {
sourceCache.set(file, data);
}
inputFiles.add(resolve(workPath, file));
})
);
}
}
if (config.debug) {
console.log(
'tracing input files: ' +
[...inputFiles].map(p => relative(workPath, p)).join(', ')
);
}
const preparedFiles: Files = {};
preparedFiles[entrypoint] = new FileBlob({ data: code });
if (map) {
preparedFiles[`${entrypoint.replace('.ts', '.js')}.map`] = new FileBlob({
data: toBuffer(map),
let tsCompile: Compile;
function compileTypeScript(path: string, source: string): string {
const relPath = relative(workPath, path);
if (config.debug) {
console.log('compiling typescript file ' + relPath);
}
if (!tsCompile) {
tsCompile = require('./typescript').init({
basePath: workPath,
logError: true,
});
}
try {
var { code, map } = tsCompile(source, path);
} catch (e) {
if (config.debug) {
console.error(e);
console.log(
'TypeScript compilation failed, falling back to basic transformModule'
);
}
// If TypeScript compile fails, attempt a direct non-typecheck compile
var { code, map } = tsCompile(source, path, true);
}
tsCompiled.add(relPath);
preparedFiles[
relPath.slice(0, -3 - Number(path.endsWith('x'))) + '.js.map'
] = new FileBlob({
data: JSON.stringify(map),
});
source = code;
shouldAddSourcemapSupport = true;
return source;
}
// move all user code to 'user' subdirectory
// eslint-disable-next-line no-restricted-syntax
for (const assetName of Object.keys(assets)) {
const { source: data, permissions: mode } = assets[assetName];
const blob2 = new FileBlob({ data, mode });
preparedFiles[join(dirname(entrypoint), assetName)] = blob2;
const { fileList, esmFileList } = await nodeFileTrace([...inputFiles], {
base: workPath,
ts: true,
ignore: config.excludeFiles,
readFile(fsPath: string): Buffer | string | null {
const relPath = relative(workPath, fsPath);
const cached = sourceCache.get(relPath);
if (cached) return cached.toString();
// null represents a not found
if (cached === null) return null;
try {
let source: string | Buffer = readFileSync(fsPath);
if (fsPath.endsWith('.ts') || fsPath.endsWith('.tsx')) {
source = compileTypeScript(fsPath, source.toString());
}
const { mode } = lstatSync(fsPath);
if (isSymbolicLink(mode))
throw new Error('Internal error: Unexpected symlink.');
const entry = new FileBlob({ data: source, mode });
fsCache.set(relPath, entry);
sourceCache.set(relPath, source);
return source.toString();
} catch (e) {
if (e.code === 'ENOENT' || e.code === 'EISDIR') {
sourceCache.set(relPath, null);
return null;
}
throw e;
}
},
});
if (config.debug) {
console.log('traced files:');
console.log('\t' + fileList.join('\n\t'));
}
return { preparedFiles, watch };
for (const path of fileList) {
let entry = fsCache.get(path);
if (!entry) {
const fsPath = resolve(workPath, path);
const { mode } = lstatSync(fsPath);
if (isSymbolicLink(mode)) {
entry = new FileFsRef({ fsPath, mode });
} else {
const source = readFileSync(fsPath);
entry = new FileBlob({ data: source, mode });
}
}
if (isSymbolicLink(entry.mode) && entry.fsPath) {
// ensure the symlink target is added to the file list
const symlinkTarget = relative(
workPath,
resolve(dirname(entry.fsPath), readlinkSync(entry.fsPath))
);
if (
!symlinkTarget.startsWith('..' + sep) &&
fileList.indexOf(symlinkTarget) === -1
) {
const stats = statSync(resolve(workPath, symlinkTarget));
if (stats.isFile()) {
fileList.push(symlinkTarget);
}
}
}
// Rename .ts -> .js (except for entry)
if (path !== entrypoint && tsCompiled.has(path)) {
preparedFiles[
path.slice(0, -3 - Number(path.endsWith('x'))) + '.js'
] = entry;
} else preparedFiles[path] = entry;
}
// Compile ES Modules into CommonJS
const esmPaths = esmFileList.filter(
file =>
!file.endsWith('.ts') &&
!file.endsWith('.tsx') &&
!file.match(libPathRegEx)
);
if (esmPaths.length) {
const babelCompile = require('./babel').compile;
for (const path of esmPaths) {
if (config.debug) {
console.log('compiling es module file ' + path);
}
const filename = basename(path);
const { data: source } = await FileBlob.fromStream({
stream: preparedFiles[path].toStream(),
});
const { code, map } = babelCompile(filename, source);
shouldAddSourcemapSupport = true;
preparedFiles[path] = new FileBlob({
data: `${code}\n//# sourceMappingURL=${filename}.map`,
});
delete map.sourcesContent;
preparedFiles[path + '.map'] = new FileBlob({
data: JSON.stringify(map),
});
}
}
return {
preparedFiles,
shouldAddSourcemapSupport,
watch: fileList,
};
}
export const version = 2;
export const config = {
maxLambdaSize: '5mb',
};
export async function build({
files,
entrypoint,
workPath,
config,
config = {},
meta = {},
}: BuildOptions) {
const shouldAddHelpers = !(config && config.helpers === false);
const shouldAddHelpers = config.helpers !== false;
const {
entrypointPath,
@@ -199,8 +296,8 @@ export async function build({
console.log('running user script...');
await runPackageJsonScript(entrypointFsDirname, 'now-build', spawnOpts);
console.log('compiling entrypoint with ncc...');
const { preparedFiles, watch } = await compile(
console.log('tracing input files...');
const { preparedFiles, shouldAddSourcemapSupport, watch } = await compile(
workPath,
entrypointPath,
entrypoint,
@@ -214,14 +311,22 @@ export async function build({
entrypointPath: `./${entrypoint}`,
bridgePath: `./${BRIDGE_FILENAME}`,
helpersPath: `./${HELPERS_FILENAME}`,
sourcemapSupportPath: `./${SOURCEMAP_SUPPORT_FILENAME}`,
shouldAddHelpers,
shouldAddSourcemapSupport,
}),
}),
[`${BRIDGE_FILENAME}.js`]: new FileFsRef({
fsPath: require('@now/node-bridge'),
fsPath: join(__dirname, 'bridge.js'),
}),
};
if (shouldAddSourcemapSupport) {
launcherFiles[`${SOURCEMAP_SUPPORT_FILENAME}.js`] = new FileFsRef({
fsPath: join(__dirname, 'source-map-support.js'),
});
}
if (shouldAddHelpers) {
launcherFiles[`${HELPERS_FILENAME}.js`] = new FileFsRef({
fsPath: join(__dirname, 'helpers.js'),
@@ -231,12 +336,15 @@ export async function build({
// Use the system-installed version of `node` when running via `now dev`
const runtime = meta.isDev ? 'nodejs' : nodeVersion.runtime;
// Enable the raw AWS API and use this handler
const awsLambdaHandler = config.awsLambdaHandler as string;
const lambda = await createLambda({
files: {
...preparedFiles,
...launcherFiles,
...(awsLambdaHandler ? {} : launcherFiles),
},
handler: `${LAUNCHER_FILENAME}.launcher`,
handler: awsLambdaHandler || `${LAUNCHER_FILENAME}.launcher`,
runtime,
});

View File

@@ -2,18 +2,22 @@ type LauncherConfiguration = {
entrypointPath: string;
bridgePath: string;
helpersPath: string;
sourcemapSupportPath: string;
shouldAddHelpers?: boolean;
shouldAddSourcemapSupport?: boolean;
};
export function makeLauncher({
entrypointPath,
bridgePath,
helpersPath,
sourcemapSupportPath,
shouldAddHelpers = false,
shouldAddSourcemapSupport = false,
}: LauncherConfiguration): string {
return `const { Bridge } = require("${bridgePath}");
const { Server } = require("http");
${shouldAddSourcemapSupport ? `require("${sourcemapSupportPath}");\n` : ''}
let isServerListening = false;
let bridge = new Bridge();
const saveListen = Server.prototype.listen;

View File

@@ -0,0 +1,472 @@
import { relative, basename, resolve, dirname } from 'path';
import _ts from 'typescript';
/*
* Fork of TS-Node - https://github.com/TypeStrong/ts-node
* Copyright Blake Embrey
* MIT License
*/
/**
* Debugging `ts-node`.
*/
const shouldDebug = false;
const debug = shouldDebug
? console.log.bind(console, 'ts-node')
: () => undefined;
const debugFn = shouldDebug
? <T, U>(key: string, fn: (arg: T) => U) => {
let i = 0;
return (x: T) => {
debug(key, x, ++i);
return fn(x);
};
}
: <T, U>(_: string, fn: (arg: T) => U) => fn;
/**
* Common TypeScript interfaces between versions.
*/
interface TSCommon {
version: typeof _ts.version;
sys: typeof _ts.sys;
ScriptSnapshot: typeof _ts.ScriptSnapshot;
displayPartsToString: typeof _ts.displayPartsToString;
createLanguageService: typeof _ts.createLanguageService;
getDefaultLibFilePath: typeof _ts.getDefaultLibFilePath;
getPreEmitDiagnostics: typeof _ts.getPreEmitDiagnostics;
flattenDiagnosticMessageText: typeof _ts.flattenDiagnosticMessageText;
transpileModule: typeof _ts.transpileModule;
ModuleKind: typeof _ts.ModuleKind;
ScriptTarget: typeof _ts.ScriptTarget;
findConfigFile: typeof _ts.findConfigFile;
readConfigFile: typeof _ts.readConfigFile;
parseJsonConfigFileContent: typeof _ts.parseJsonConfigFileContent;
formatDiagnostics: typeof _ts.formatDiagnostics;
formatDiagnosticsWithColorAndContext: typeof _ts.formatDiagnosticsWithColorAndContext;
}
/**
* Registration options.
*/
interface Options {
basePath?: string;
pretty?: boolean | null;
logError?: boolean | null;
files?: boolean | null;
compiler?: string;
ignore?: string[];
project?: string;
compilerOptions?: object;
ignoreDiagnostics?: Array<number | string>;
readFile?: (path: string) => string | undefined;
fileExists?: (path: string) => boolean;
transformers?: _ts.CustomTransformers;
}
/**
* Track the project information.
*/
class MemoryCache {
fileContents = new Map<string, string>();
fileVersions = new Map<string, number>();
constructor(rootFileNames: string[] = []) {
for (const fileName of rootFileNames) this.fileVersions.set(fileName, 1);
}
}
/**
* Default register options.
*/
const DEFAULTS: Options = {
files: null,
pretty: null,
compiler: undefined,
compilerOptions: undefined,
ignore: undefined,
project: undefined,
ignoreDiagnostics: undefined,
logError: null,
};
/**
* Default TypeScript compiler options required by `ts-node`.
*/
const TS_NODE_COMPILER_OPTIONS = {
sourceMap: true,
inlineSourceMap: false,
inlineSources: true,
declaration: false,
noEmit: false,
outDir: '$$ts-node$$',
};
/**
* Replace backslashes with forward slashes.
*/
function normalizeSlashes(value: string): string {
return value.replace(/\\/g, '/');
}
/**
* Return type for registering `ts-node`.
*/
export type Compile = (
code: string,
fileName: string,
skipTypeCheck?: boolean
) => { code: string; map: string };
/**
* Cached fs operation wrapper.
*/
function cachedLookup<T>(fn: (arg: string) => T): (arg: string) => T {
const cache = new Map<string, T>();
return (arg: string): T => {
if (!cache.has(arg)) {
cache.set(arg, fn(arg));
}
return cache.get(arg)!;
};
}
/**
* Register TypeScript compiler.
*/
export function init(opts: Options = {}): Compile {
const options = Object.assign({}, DEFAULTS, opts);
const ignoreDiagnostics = [
6059, // "'rootDir' is expected to contain all source files."
18002, // "The 'files' list in config file is empty."
18003, // "No inputs were found in config file."
...(options.ignoreDiagnostics || []),
].map(Number);
// Require the TypeScript compiler and configuration.
const cwd = options.basePath || process.cwd();
const nowNodeBase = resolve(__dirname, '../../../');
try {
var compiler = require.resolve(options.compiler || 'typescript', {
paths: [cwd, nowNodeBase],
});
} catch (e) {
compiler = require.resolve(eval('"./typescript"'));
}
const ts: typeof _ts = require(compiler);
if (compiler.startsWith(nowNodeBase)) {
console.log('Using TypeScript ' + ts.version + ' (now internal)');
} else {
console.log('Using TypeScript ' + ts.version + ' (local user-provided)');
}
const transformers = options.transformers || undefined;
const readFile = options.readFile || ts.sys.readFile;
const fileExists = options.fileExists || ts.sys.fileExists;
const formatDiagnostics =
process.stdout.isTTY || options.pretty
? ts.formatDiagnosticsWithColorAndContext
: ts.formatDiagnostics;
const diagnosticHost: _ts.FormatDiagnosticsHost = {
getNewLine: () => ts.sys.newLine,
getCurrentDirectory: () => cwd,
getCanonicalFileName: path => path,
};
function createTSError(diagnostics: ReadonlyArray<_ts.Diagnostic>) {
const diagnosticText = formatDiagnostics(diagnostics, diagnosticHost);
return new Error(diagnosticText);
}
function reportTSError(configDiagnosticList: _ts.Diagnostic[]) {
const error = createTSError(configDiagnosticList);
if (options.logError) {
// Print error in red color and continue execution.
console.error('\x1b[31m%s\x1b[0m', error);
} else {
// Throw error and exit the script.
throw error;
}
}
// we create a custom build per tsconfig.json instance
const builds = new Map<string, Build>();
function getBuild(configFileName: string = ''): Build {
let build = builds.get(configFileName);
if (build) return build;
const config = readConfig(configFileName);
/**
* Create the basic required function using transpile mode.
*/
let getOutput = function(code: string, fileName: string): [string, string] {
const result = ts.transpileModule(code, {
fileName,
transformers,
compilerOptions: config.options,
reportDiagnostics: true,
});
const diagnosticList = result.diagnostics
? filterDiagnostics(result.diagnostics, ignoreDiagnostics)
: [];
if (diagnosticList.length) reportTSError(diagnosticList);
return [result.outputText, result.sourceMapText as string];
};
// Use full language services when the fast option is disabled.
let getOutputTypeCheck: (
code: string,
fileName: string
) => [string, string];
{
const memoryCache = new MemoryCache(config.fileNames);
const cachedReadFile = cachedLookup(debugFn('readFile', readFile));
// Create the compiler host for type checking.
const serviceHost: _ts.LanguageServiceHost = {
getScriptFileNames: () => Array.from(memoryCache.fileVersions.keys()),
getScriptVersion: (fileName: string) => {
const version = memoryCache.fileVersions.get(fileName);
return version === undefined ? '' : version.toString();
},
getScriptSnapshot(fileName: string) {
let contents = memoryCache.fileContents.get(fileName);
// Read contents into TypeScript memory cache.
if (contents === undefined) {
contents = cachedReadFile(fileName);
if (contents === undefined) return;
memoryCache.fileVersions.set(fileName, 1);
memoryCache.fileContents.set(fileName, contents);
}
return ts.ScriptSnapshot.fromString(contents);
},
readFile: cachedReadFile,
readDirectory: cachedLookup(
debugFn('readDirectory', ts.sys.readDirectory)
),
getDirectories: cachedLookup(
debugFn('getDirectories', ts.sys.getDirectories)
),
fileExists: cachedLookup(debugFn('fileExists', fileExists)),
directoryExists: cachedLookup(
debugFn('directoryExists', ts.sys.directoryExists)
),
getNewLine: () => ts.sys.newLine,
useCaseSensitiveFileNames: () => ts.sys.useCaseSensitiveFileNames,
getCurrentDirectory: () => cwd,
getCompilationSettings: () => config.options,
getDefaultLibFileName: () => ts.getDefaultLibFilePath(config.options),
getCustomTransformers: () => transformers,
};
const registry = ts.createDocumentRegistry(
ts.sys.useCaseSensitiveFileNames,
cwd
);
const service = ts.createLanguageService(serviceHost, registry);
// Set the file contents into cache manually.
const updateMemoryCache = function(contents: string, fileName: string) {
const fileVersion = memoryCache.fileVersions.get(fileName) || 0;
// Avoid incrementing cache when nothing has changed.
if (memoryCache.fileContents.get(fileName) === contents) return;
memoryCache.fileVersions.set(fileName, fileVersion + 1);
memoryCache.fileContents.set(fileName, contents);
};
getOutputTypeCheck = function(code: string, fileName: string) {
updateMemoryCache(code, fileName);
const output = service.getEmitOutput(fileName);
// Get the relevant diagnostics - this is 3x faster than `getPreEmitDiagnostics`.
const diagnostics = service
.getSemanticDiagnostics(fileName)
.concat(service.getSyntacticDiagnostics(fileName));
const diagnosticList = filterDiagnostics(
diagnostics,
ignoreDiagnostics
);
if (diagnosticList.length) reportTSError(diagnosticList);
if (output.emitSkipped) {
throw new TypeError(`${relative(cwd, fileName)}: Emit skipped`);
}
// Throw an error when requiring `.d.ts` files.
if (output.outputFiles.length === 0) {
throw new TypeError(
'Unable to require `.d.ts` file.\n' +
'This is usually the result of a faulty configuration or import. ' +
'Make sure there is a `.js`, `.json` or another executable extension and ' +
'loader (attached before `ts-node`) available alongside ' +
`\`${basename(fileName)}\`.`
);
}
return [output.outputFiles[1].text, output.outputFiles[0].text];
};
}
builds.set(
configFileName,
(build = {
getOutput,
getOutputTypeCheck,
})
);
return build;
}
// determine the tsconfig.json path for a given folder
function detectConfig(basePath: string): string | undefined {
basePath = normalizeSlashes(basePath);
let configFileName: string | undefined = undefined;
// Read project configuration when available.
configFileName = options.project
? normalizeSlashes(resolve(cwd, options.project))
: ts.findConfigFile(normalizeSlashes(cwd), fileExists);
if (configFileName) return normalizeSlashes(configFileName);
}
/**
* Load TypeScript configuration.
*/
function readConfig(configFileName: string): _ts.ParsedCommandLine {
let config: any = { compilerOptions: {} };
let basePath = normalizeSlashes(dirname(configFileName));
// Read project configuration when available.
if (configFileName) {
const result = ts.readConfigFile(configFileName, readFile);
// Return diagnostics.
if (result.error) {
const errorResult = {
errors: [result.error],
fileNames: [],
options: {},
};
const configDiagnosticList = filterDiagnostics(
errorResult.errors,
ignoreDiagnostics
);
// Render the configuration errors.
if (configDiagnosticList.length) reportTSError(configDiagnosticList);
return errorResult;
}
config = result.config;
}
// Remove resolution of "files".
if (!options.files) {
config.files = [];
config.include = [];
}
// Override default configuration options `ts-node` requires.
config.compilerOptions = Object.assign(
{},
config.compilerOptions,
options.compilerOptions,
TS_NODE_COMPILER_OPTIONS
);
const configResult = fixConfig(
ts,
ts.parseJsonConfigFileContent(
config,
ts.sys,
basePath,
undefined,
configFileName
)
);
if (configFileName) {
const configDiagnosticList = filterDiagnostics(
configResult.errors,
ignoreDiagnostics
);
// Render the configuration errors.
if (configDiagnosticList.length) reportTSError(configDiagnosticList);
}
return configResult;
}
// Create a simple TypeScript compiler proxy.
function compile(code: string, fileName: string, skipTypeCheck?: boolean) {
const configFileName = detectConfig(fileName);
const build = getBuild(configFileName);
const [value, sourceMap] = (skipTypeCheck
? build.getOutput
: build.getOutputTypeCheck)(code, fileName);
const output = {
code: value,
map: Object.assign(JSON.parse(sourceMap), {
file: basename(fileName),
sources: [fileName],
}),
};
delete output.map.sourceRoot;
return output;
}
return compile;
}
interface Build {
getOutput(code: string, fileName: string): [string, string];
getOutputTypeCheck(code: string, fileName: string): [string, string];
}
/**
* Do post-processing on config options to support `ts-node`.
*/
function fixConfig(ts: TSCommon, config: _ts.ParsedCommandLine) {
// Delete options that *should not* be passed through.
delete config.options.out;
delete config.options.outFile;
delete config.options.composite;
delete config.options.declarationDir;
delete config.options.declarationMap;
delete config.options.emitDeclarationOnly;
delete config.options.tsBuildInfoFile;
delete config.options.incremental;
// Target ES5 output by default (instead of ES3).
if (config.options.target === undefined) {
config.options.target = ts.ScriptTarget.ESNext;
}
// Target CommonJS, always!
config.options.module = ts.ModuleKind.CommonJS;
return config;
}
/**
* Filter diagnostics.
*/
function filterDiagnostics(diagnostics: _ts.Diagnostic[], ignore: number[]) {
return diagnostics.filter(x => ignore.indexOf(x.code) === -1);
}

View File

@@ -0,0 +1 @@
export default 'tsx';

View File

@@ -0,0 +1,5 @@
import dep from './dep';
export default function handler(req: any, res: any) {
res.end(dep);
}

View File

@@ -0,0 +1,10 @@
{
"version": 2,
"builds": [{ "src": "index.ts", "use": "@now/node" }],
"probes": [
{
"path": "/",
"mustContain": "tsx"
}
]
}

View File

@@ -0,0 +1,11 @@
{
"compilerOptions": {
"strict": true,
"esModuleInterop": true,
"sourceMap": true,
"lib": ["esnext"],
"target": "esnext",
"module": "commonjs"
},
"include": ["index.ts"]
}

View File

@@ -0,0 +1,5 @@
import fs from 'fs';
export default function handler(req, res) {
res.end(fs.readFileSync(`${__dirname}/symlink`));
}

View File

@@ -0,0 +1,15 @@
{
"version": 2,
"builds": [
{
"src": "index.js",
"use": "@now/node"
}
],
"probes": [
{
"path": "/",
"mustContain": "asdf"
}
]
}

View File

@@ -0,0 +1 @@
asdf

View File

@@ -0,0 +1,11 @@
export default function handler(req, res) {
try {
if (req) {
// eslint-disable-next-line no-unused-expressions
req.notdefined.something;
}
res.end('Should not print');
} catch (error) {
res.end(error.stack);
}
}

View File

@@ -0,0 +1,10 @@
{
"version": 2,
"builds": [{ "src": "index.js", "use": "@now/node" }],
"probes": [
{
"path": "/",
"mustContain": "index.js:5"
}
]
}

View File

@@ -0,0 +1,16 @@
import { IncomingMessage, ServerResponse } from 'http';
import { parse } from 'url';
const func = (req: IncomingMessage, res: ServerResponse) => {
if (req.url) {
const url = parse(req.url);
res.writeHead(302, {
Location: url.pathname
? url.pathname.replace(/\/+/g, '/') + (url.search ? url.search : '')
: '/',
});
res.end();
}
};
export default func;

View File

@@ -0,0 +1,8 @@
{
"name": "functions",
"version": "1.0.0",
"main": "index.js",
"devDependencies": {
"@types/node": "12.6.1"
}
}

View File

@@ -0,0 +1,18 @@
import { IncomingMessage, ServerResponse } from 'http';
import { parse } from 'url';
const func = (req: IncomingMessage, res: ServerResponse) => {
const { referer } = req.headers;
if (!referer) {
res.writeHead(302, { Location: `/404` });
return;
}
const {
host,
query: { section },
} = parse(referer, true);
res.writeHead(302, { Location: `/deployments/${host}/${section}` });
res.end();
};
export default func;

View File

@@ -0,0 +1,20 @@
import { IncomingMessage, ServerResponse } from 'http';
import { parse } from 'url';
const func = (req: IncomingMessage, res: ServerResponse) => {
if (req.url) {
const url = parse(req.url);
let pathname = url.pathname;
if (pathname && pathname.slice(-1) === '/') {
// remove all leading `/`s, keep one
pathname = pathname.replace(/^\/+/g, '/');
const location = pathname.slice(0, -1) + (url.search ? url.search : '');
/*res.writeHead(302, {
Location: location
})*/
res.end(`trailing-redirect:RANDOMNESS_PLACEHOLDER:${location}`);
}
}
};
export default func;

View File

@@ -0,0 +1,22 @@
{
"compilerOptions": {
"target": "es5" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */,
"module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */,
"lib": [
"es2015"
] /* Specify library files to be included in the compilation. */,
/* Strict Type-Checking Options */
"strict": true /* Enable all strict type-checking options. */,
"noImplicitAny": true /* Raise error on expressions and declarations with an implied 'any' type. */,
"strictNullChecks": true /* Enable strict null checks. */,
"strictFunctionTypes": true /* Enable strict checking of function types. */,
"strictBindCallApply": true /* Enable strict 'bind', 'call', and 'apply' methods on functions. */,
"strictPropertyInitialization": true /* Enable strict checking of property initialization in classes. */,
"noImplicitThis": true /* Raise error on 'this' expressions with an implied 'any' type. */,
"alwaysStrict": true /* Parse in strict mode and emit "use strict" for each source file. */,
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
},
"exclude": ["./screenshot-api/**"]
}

View File

@@ -0,0 +1,9 @@
import { NowRequest, NowResponse } from '@now/node';
export default function(req: NowRequest, res: NowResponse) {
if (req) {
res.end('root:RANDOMNESS_PLACEHOLDER');
} else {
res.end('no req found');
}
}

View File

@@ -0,0 +1,36 @@
{
"version": 2,
"builds": [
{ "src": "functions/referer-redirect.ts", "use": "@now/node" },
{ "src": "functions/double-redirect.ts", "use": "@now/node" },
{ "src": "functions/trailing-redirect.ts", "use": "@now/node" },
{ "src": "index.ts", "use": "@now/node" }
],
"routes": [
{
"src": "/",
"dest": "index.ts"
},
{
"src": "(/.*)/$",
"dest": "/functions/trailing-redirect.ts"
},
{
"src": "^.*?//.*$",
"dest": "/functions/double-redirect.ts"
},
{
"handle": "filesystem"
}
],
"probes": [
{
"path": "/",
"mustContain": "root:RANDOMNESS_PLACEHOLDER"
},
{
"path": "//",
"mustContain": "trailing-redirect:RANDOMNESS_PLACEHOLDER"
}
]
}

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