Compare commits

...

18 Commits

Author SHA1 Message Date
Steven
a56b32f670 Publish
- @now/next@0.7.0
 - @now/node@0.12.7
 - @now/python@0.2.16
 - @now/static-build@0.9.8
2019-08-22 10:30:13 -04:00
Kid
aea7df85f7 [now-static-build] Add Saber Optimization (#946)
* [now-static-build] Add Saber Optimization

* fix test fixtures

* Update packages/now-static-build/test/fixtures/25-saber/README.md

Co-Authored-By: Andy <AndyBitz@users.noreply.github.com>
2019-08-22 10:27:47 -04:00
Steven
c859ffc48c [now-node][now-next] Bump node-file-trace to 0.2.13 (#947) 2019-08-22 10:27:33 -04:00
hanabi1224
69ac545152 [now-static-build] Optimize default routes for vue (#799)
* optimize default routes for vue
2019-08-22 10:27:20 -04:00
Joe Haddad
76dbcceb01 [now-next] Always use node-file-trace if available (#944) 2019-08-22 10:26:32 -04:00
Stef
8c6d714258 Fix "TypeError: Cannot convert undefined or null to object" (#940) 2019-08-22 10:24:40 -04:00
Steven
55cefe988b [docs] Add instructions for deploying Builder as a tarball (#939) 2019-08-22 10:23:35 -04:00
Kai Richard König
d79611568f [now-python] More robust way to install the pipenv converter regardless of OS (#930) 2019-08-22 10:23:25 -04:00
Steven
18f979727a [now-node] Include global .d.ts and fail when noEmitOnError is true (#927)
* [now-node] Fix compiling global .d.ts files

* [now-node] Fix compiling global .d.ts files

* [now-node] Throw when noEmitOnError enabled

* Use exit intead of throw

* Add integration tests

* Fix probes

* Fix tests to check for failure

* Fix nested tsconfig.json

* Use register(props) instead of modifying ts-node

* Revert back to normalizeSlashes(cwd)

* Fix tests

* Add test for tsconfig.json

* Fix tests

* Update packages/now-node/test/fixtures/18-nested-tsconfig/now.json

Co-Authored-By: Luc <luc.leray@gmail.com>
2019-08-22 10:22:42 -04:00
Andy Bitz
96912577dc Publish
- @now/build-utils@0.9.13
2019-08-19 00:45:24 +02:00
Andy
d5372f7ac8 [now-build-utils] Fix detected builders tag (#943)
* [now-build-utils] Fix detected builders tag

* Fix non-api builders

* Remove logging

* Return a new copy instead of a reference
2019-08-19 00:44:48 +02:00
Joe Haddad
feb5456eb6 Publish
- @now/next@0.6.2
2019-08-18 14:31:36 -04:00
Joe Haddad
cc0c3cfbef Upgrade @zeit/node-file-trace to 0.2.11 (#942) 2019-08-18 14:25:44 -04:00
Steven
4fe6e94d83 Bump node-file-trace to 0.2.10 (#938) 2019-08-18 14:25:40 -04:00
Joe Haddad
ba6751f63e Publish
- @now/next@0.6.1
2019-08-14 13:07:39 -04:00
Joe Haddad
af105975d7 [now-next] Test on Node 8 and Node 10 (#933)
* Test on Node 8 and Node 10

* Update packages/now-next/test/fixtures/02-firebase-node-8/package.json

Co-Authored-By: Steven <steven@ceriously.com>
2019-08-14 13:06:54 -04:00
Joe Haddad
46e96d66ca [now-next] Join bundle require path manually (#932) 2019-08-14 13:06:48 -04:00
Joe Haddad
9aabd26fda [now-next] Use more appropriate semver comparisons (#925) 2019-08-14 13:06:40 -04:00
56 changed files with 548 additions and 148 deletions

View File

@@ -1,6 +1,6 @@
# Contributing
When contributing to this repository, please first discuss the change you wish to make via issue or [spectrum](https://spectrum.chat/zeit) with the owners of this repository before submitting a Pull Request.
When contributing to this repository, please first discuss the change you wish to make via [GitHub Issue](https://github.com/zeit/now-builders/issues/new) or [Spectrum](https://spectrum.chat/zeit) with the owners of this repository before submitting a Pull Request.
Please read our [code of conduct](CODE_OF_CONDUCT.md) and follow it in all your interactions with the project.
@@ -68,18 +68,29 @@ In such cases you can visit the URL of the failed deployment and append `/_logs`
The logs of this deployment will contain the actual error which may help you to understand what went wrong.
### @zeit/ncc integration
### @zeit/node-file-trace
Some of the builders use `@zeit/ncc` to bundle files before deployment. If you suspect an error with the bundling mechanism, you can run the `ncc` CLI with a couple modifications to the test.
Some of the Builders use `@zeit/node-file-trace` to tree-shake files before deployment. If you suspect an error with this tree-shaking mechanism, you can create the following script in your project:
For example if an error occurred in `now-node/test/fixtures/08-assets`
```
cd packages/now-node/test/fixtures/08-assets
yarn install
echo 'require("http").createServer(module.exports).listen(3000)' >> index.js
npx @zeit/ncc@0.20.1 build index.js --source-map
node dist
```js
const trace = require('@zeit/node-file-trace');
trace(['path/to/entrypoint.js'], {
ts: true,
mixedModules: true,
})
.then(o => console.log(o.fileList))
.then(e => console.error(e));
```
This will compile the test with the specific version of `ncc` and run the resulting file. If it fails here, then there is likely a bug in `ncc` and not the Builder.
When you run this script, you'll see all imported files. If anything file is missing, the bug is in [@zeit/node-file-trace](https://github.com/zeit/node-file-trace) and not the Builder.
## Deploy a Builder with existing project
Sometimes you want to test changes to a Builder against an existing project, maybe with `now dev` or an actual deployment. You can avoid publishing every Builder change to npm by uploading the Builder as a tarball.
1. Change directory to the desired Builder `cd ./packages/now-node`
2. Run `yarn build` to compile typescript and other build steps
3. Run `npm pack` to create a tarball file
4. Run `now *.tgz` to upload the tarball file and get a URL
5. Edit any existing `now.json` project and replace `use` with the URL
6. Run `now` or `now dev` to deploy with the experimental Builder

View File

@@ -1,6 +1,6 @@
{
"name": "@now/build-utils",
"version": "0.9.12",
"version": "0.9.13",
"license": "MIT",
"main": "./dist/index.js",
"types": "./dist/index.d.js",

View File

@@ -7,25 +7,12 @@ interface ErrorResponse {
}
interface Options {
tag?: 'canary' | 'latest';
tag?: 'canary' | 'latest' | string;
}
const src: string = 'package.json';
const config: Config = { zeroConfig: true };
// Static builders are special cased in `@now/static-build`
const BUILDERS = new Map<string, Builder>([
['next', { src, use: '@now/next', config }],
]);
const API_BUILDERS: Builder[] = [
{ src: 'api/**/*.js', use: '@now/node', config },
{ src: 'api/**/*.ts', use: '@now/node', config },
{ src: 'api/**/*.go', use: '@now/go', config },
{ src: 'api/**/*.py', use: '@now/python', config },
{ src: 'api/**/*.rb', use: '@now/ruby', config },
];
const MISSING_BUILD_SCRIPT_ERROR: ErrorResponse = {
code: 'missing_build_script',
message:
@@ -33,6 +20,25 @@ const MISSING_BUILD_SCRIPT_ERROR: ErrorResponse = {
'\nMore details: https://zeit.co/docs/v2/advanced/platform/frequently-asked-questions#missing-build-script',
};
// Static builders are special cased in `@now/static-build`
function getBuilders(): Map<string, Builder> {
return new Map<string, Builder>([
['next', { src, use: '@now/next', config }],
]);
}
// Must be a function to ensure that the returned
// object won't be a reference
function getApiBuilders(): Builder[] {
return [
{ src: 'api/**/*.js', use: '@now/node', config },
{ src: 'api/**/*.ts', use: '@now/node', config },
{ src: 'api/**/*.go', use: '@now/go', config },
{ src: 'api/**/*.py', use: '@now/python', config },
{ src: 'api/**/*.rb', use: '@now/ruby', config },
];
}
function hasPublicDirectory(files: string[]) {
return files.some(name => name.startsWith('public/'));
}
@@ -43,7 +49,7 @@ function hasBuildScript(pkg: PackageJson | undefined) {
}
async function detectBuilder(pkg: PackageJson): Promise<Builder> {
for (const [dependency, builder] of BUILDERS) {
for (const [dependency, builder] of getBuilders()) {
const deps = Object.assign({}, pkg.dependencies, pkg.devDependencies);
// Return the builder when a dependency matches
@@ -72,7 +78,7 @@ export function ignoreApiFilter(file: string) {
// 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))) {
if (getApiBuilders().every(({ src }) => !minimatch(file, src))) {
return false;
}
@@ -90,7 +96,7 @@ async function detectApiBuilders(files: string[]): Promise<Builder[]> {
.sort(sortFiles)
.filter(ignoreApiFilter)
.map(file => {
const result = API_BUILDERS.find(
const result = getApiBuilders().find(
({ src }): boolean => minimatch(file, src)
);
@@ -155,7 +161,10 @@ export async function detectBuilders(
const tag = options && options.tag;
if (tag) {
builders = builders.map((builder: Builder) => {
builders = builders.map((originBuilder: Builder) => {
// Copy builder to make sure it is not a reference
const builder = { ...originBuilder };
// @now/static has no canary builder
if (builder.use !== '@now/static') {
builder.use = `${builder.use}@${tag}`;

View File

@@ -451,6 +451,44 @@ it('Test `detectBuilders`', async () => {
expect(builders[2].use).toBe('@now/next@canary');
expect(builders.length).toBe(3);
}
{
// package.json + api + latest
const pkg = {
scripts: { build: 'next build' },
dependencies: { next: '9.0.0' },
};
const files = [
'pages/index.js',
'api/[endpoint].js',
'api/[endpoint]/[id].js',
];
const { builders } = await detectBuilders(files, pkg, { tag: 'latest' });
expect(builders[0].use).toBe('@now/node@latest');
expect(builders[1].use).toBe('@now/node@latest');
expect(builders[2].use).toBe('@now/next@latest');
expect(builders.length).toBe(3);
}
{
// package.json + api + random tag
const pkg = {
scripts: { build: 'next build' },
dependencies: { next: '9.0.0' },
};
const files = [
'pages/index.js',
'api/[endpoint].js',
'api/[endpoint]/[id].js',
];
const { builders } = await detectBuilders(files, pkg, { tag: 'haha' });
expect(builders[0].use).toBe('@now/node@haha');
expect(builders[1].use).toBe('@now/node@haha');
expect(builders[2].use).toBe('@now/next@haha');
expect(builders.length).toBe(3);
}
});
it('Test `detectRoutes`', async () => {

View File

@@ -1,6 +1,6 @@
{
"name": "@now/next",
"version": "0.6.0",
"version": "0.7.0",
"license": "MIT",
"main": "./dist/index",
"homepage": "https://zeit.co/docs/v2/deployments/official-builders/next-js-now-next",
@@ -21,7 +21,7 @@
"@types/next-server": "8.0.0",
"@types/resolve-from": "5.0.1",
"@types/semver": "6.0.0",
"@zeit/node-file-trace": "0.2.9",
"@zeit/node-file-trace": "0.2.13",
"fs-extra": "7.0.0",
"get-port": "5.0.0",
"resolve-from": "5.0.0",

View File

@@ -47,10 +47,7 @@ export default async function createServerlessConfig(
let target = 'serverless';
if (nextVersion) {
try {
if (
nextVersion.includes('canary') &&
semver.satisfies(nextVersion, `>=${ExperimentalTraceVersion}`)
) {
if (semver.gte(nextVersion, ExperimentalTraceVersion)) {
target = 'experimental-serverless-trace';
}
} catch (_ignored) {}

View File

@@ -451,7 +451,7 @@ export const build = async ({
try {
if (
realNextVersion &&
semver.satisfies(realNextVersion, `<${ExperimentalTraceVersion}`)
semver.lt(realNextVersion, ExperimentalTraceVersion)
) {
if (config.debug) {
console.log(
@@ -533,12 +533,12 @@ export const build = async ({
const label = `Creating lambda for page: "${page}"...`;
console.time(label);
const pageFileName = path.relative(workPath, pages[page].fsPath);
const pageFileName = path.normalize(
path.relative(workPath, pages[page].fsPath)
);
const launcher = launcherData.replace(
/__LAUNCHER_PAGE_PATH__/g,
JSON.stringify(
requiresTracing ? path.join('./', pageFileName) : './page'
)
JSON.stringify(requiresTracing ? `./${pageFileName}` : './page')
);
const launcherFiles = {
'now__bridge.js': new FileFsRef({

View File

@@ -0,0 +1,11 @@
{
"engines": {
"node": "8.10.x"
},
"dependencies": {
"next": "canary",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"firebase": "6.3.4"
}
}

View File

@@ -0,0 +1,5 @@
module.exports = {
generateBuildId() {
return 'testing-build-id';
},
};

View File

@@ -0,0 +1,8 @@
{
"version": 2,
"builds": [{ "src": "package.json", "use": "@now/next" }],
"probes": [
{ "path": "/nested/fb", "mustContain": "Hello Firebase: <!-- -->0" },
{ "path": "/nested/moar/fb", "mustContain": "Hello Firebase: <!-- -->0" }
]
}

View File

@@ -1,4 +1,7 @@
{
"engines": {
"node": "10.x"
},
"dependencies": {
"next": "canary",
"react": "^16.8.6",

View File

@@ -0,0 +1,19 @@
import firebase from 'firebase/app';
import 'firebase/firestore';
if (!firebase.apps.length) {
firebase.initializeApp({ projectId: 'noop' });
}
const store = firebase.firestore();
const Comp = ({ results }) => {
return <div>Hello Firebase: {results}</div>;
};
Comp.getInitialProps = async () => {
const query = await store.collection('users').get();
return { results: query.size };
};
export default Comp;

View File

@@ -0,0 +1,19 @@
import firebase from 'firebase/app';
import 'firebase/firestore';
if (!firebase.apps.length) {
firebase.initializeApp({ projectId: 'noop' });
}
const store = firebase.firestore();
const Comp = ({ results }) => {
return <div>Hello Firebase: {results}</div>;
};
Comp.getInitialProps = async () => {
const query = await store.collection('users').get();
return { results: query.size };
};
export default Comp;

View File

@@ -1,6 +1,6 @@
{
"name": "@now/node",
"version": "0.12.6",
"version": "0.12.7",
"license": "MIT",
"main": "./dist/index",
"homepage": "https://zeit.co/docs/v2/deployments/official-builders/node-js-now-node",
@@ -28,7 +28,7 @@
"@types/etag": "1.8.0",
"@types/test-listen": "1.1.0",
"@zeit/ncc": "0.20.4",
"@zeit/node-file-trace": "0.2.9",
"@zeit/node-file-trace": "0.2.13",
"content-type": "1.0.4",
"cookie": "0.4.0",
"etag": "1.8.1",

View File

@@ -21,7 +21,7 @@ import {
export { NowRequest, NowResponse } from './types';
import { makeLauncher } from './launcher';
import { readFileSync, lstatSync, readlinkSync, statSync } from 'fs';
import { Compile } from './typescript';
import { Register, register } from './typescript';
interface CompilerConfig {
debug?: boolean;
@@ -134,30 +134,20 @@ async function compile(
const preparedFiles: Files = {};
let tsCompile: Compile;
let tsCompile: Register;
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,
tsCompile = register({
basePath: workPath, // The base is the same as root now.json dir
project: path, // Resolve tsconfig.json from entrypoint dir
files: true, // Include all files such as global `.d.ts`
});
}
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);
}
const { code, map } = tsCompile(source, path);
tsCompiled.add(relPath);
preparedFiles[
relPath.slice(0, -3 - Number(path.endsWith('x'))) + '.js.map'

View File

@@ -112,11 +112,11 @@ function normalizeSlashes(value: string): string {
/**
* Return type for registering `ts-node`.
*/
export type Compile = (
export type Register = (
code: string,
fileName: string,
skipTypeCheck?: boolean
) => { code: string; map: string };
) => SourceOutput;
/**
* Cached fs operation wrapper.
@@ -136,7 +136,7 @@ function cachedLookup<T>(fn: (arg: string) => T): (arg: string) => T {
/**
* Register TypeScript compiler.
*/
export function init(opts: Options = {}): Compile {
export function register(opts: Options = {}): Register {
const options = Object.assign({}, DEFAULTS, opts);
const ignoreDiagnostics = [
@@ -148,7 +148,7 @@ export function init(opts: Options = {}): Compile {
// Require the TypeScript compiler and configuration.
const cwd = options.basePath || process.cwd();
const nowNodeBase = resolve(__dirname, '../../../');
const nowNodeBase = resolve(__dirname, '..', '..', '..');
try {
var compiler = require.resolve(options.compiler || 'typescript', {
paths: [cwd, nowNodeBase],
@@ -182,14 +182,18 @@ export function init(opts: Options = {}): Compile {
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;
function reportTSError(
diagnostics: _ts.Diagnostic[],
shouldExit: boolean | undefined
) {
if (!diagnostics || diagnostics.length === 0) {
return;
}
const error = createTSError(diagnostics);
// Print error in red color and continue execution.
console.error('\x1b[31m%s\x1b[0m', error);
if (shouldExit) {
process.exit(1);
}
}
@@ -204,7 +208,7 @@ export function init(opts: Options = {}): Compile {
/**
* Create the basic required function using transpile mode.
*/
let getOutput = function(code: string, fileName: string): [string, string] {
let getOutput = function(code: string, fileName: string): SourceOutput {
const result = ts.transpileModule(code, {
fileName,
transformers,
@@ -216,16 +220,13 @@ export function init(opts: Options = {}): Compile {
? filterDiagnostics(result.diagnostics, ignoreDiagnostics)
: [];
if (diagnosticList.length) reportTSError(diagnosticList);
reportTSError(diagnosticList, config.options.noEmitOnError);
return [result.outputText, result.sourceMapText as string];
return { code: result.outputText, map: result.sourceMapText as string };
};
// Use full language services when the fast option is disabled.
let getOutputTypeCheck: (
code: string,
fileName: string
) => [string, string];
let getOutputTypeCheck: (code: string, fileName: string) => SourceOutput;
{
const memoryCache = new MemoryCache(config.fileNames);
const cachedReadFile = cachedLookup(debugFn('readFile', readFile));
@@ -302,7 +303,7 @@ export function init(opts: Options = {}): Compile {
ignoreDiagnostics
);
if (diagnosticList.length) reportTSError(diagnosticList);
reportTSError(diagnosticList, config.options.noEmitOnError);
if (output.emitSkipped) {
throw new TypeError(`${relative(cwd, fileName)}: Emit skipped`);
@@ -319,7 +320,10 @@ export function init(opts: Options = {}): Compile {
);
}
return [output.outputFiles[1].text, output.outputFiles[0].text];
return {
code: output.outputFiles[1].text,
map: output.outputFiles[0].text,
};
};
}
@@ -340,7 +344,7 @@ export function init(opts: Options = {}): Compile {
// Read project configuration when available.
configFileName = options.project
? normalizeSlashes(resolve(cwd, options.project))
? ts.findConfigFile(normalizeSlashes(options.project), fileExists)
: ts.findConfigFile(normalizeSlashes(cwd), fileExists);
if (configFileName) return normalizeSlashes(configFileName);
@@ -369,7 +373,7 @@ export function init(opts: Options = {}): Compile {
ignoreDiagnostics
);
// Render the configuration errors.
if (configDiagnosticList.length) reportTSError(configDiagnosticList);
reportTSError(configDiagnosticList, true);
return errorResult;
}
@@ -407,17 +411,21 @@ export function init(opts: Options = {}): Compile {
ignoreDiagnostics
);
// Render the configuration errors.
if (configDiagnosticList.length) reportTSError(configDiagnosticList);
reportTSError(configDiagnosticList, configResult.options.noEmitOnError);
}
return configResult;
}
// Create a simple TypeScript compiler proxy.
function compile(code: string, fileName: string, skipTypeCheck?: boolean) {
function compile(
code: string,
fileName: string,
skipTypeCheck?: boolean
): SourceOutput {
const configFileName = detectConfig(fileName);
const build = getBuild(configFileName);
const [value, sourceMap] = (skipTypeCheck
const { code: value, map: sourceMap } = (skipTypeCheck
? build.getOutput
: build.getOutputTypeCheck)(code, fileName);
const output = {
@@ -435,8 +443,8 @@ export function init(opts: Options = {}): Compile {
}
interface Build {
getOutput(code: string, fileName: string): [string, string];
getOutputTypeCheck(code: string, fileName: string): [string, string];
getOutput(code: string, fileName: string): SourceOutput;
getOutputTypeCheck(code: string, fileName: string): SourceOutput;
}
/**
@@ -471,6 +479,11 @@ function fixConfig(ts: TSCommon, config: _ts.ParsedCommandLine) {
return config;
}
/**
* Internal source output.
*/
type SourceOutput = { code: string; map: string };
/**
* Filter diagnostics.
*/

View File

@@ -0,0 +1,5 @@
// This will compile differently when target is es5 vs es6
export function hello(name: string) {
`Hello ${name}`;
}

View File

@@ -0,0 +1,10 @@
import { IncomingMessage, ServerResponse } from 'http';
import { hello } from '../dep';
export default function(req: IncomingMessage, res: ServerResponse) {
if (req) {
res.end(hello.toString());
} else {
res.end('no req found');
}
}

View File

@@ -15,7 +15,7 @@
"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. */,
"noEmitOnError": true,
"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

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

View File

@@ -1,9 +1,7 @@
{
"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": "functions/*.ts", "use": "@now/node" },
{ "src": "index.ts", "use": "@now/node" }
],
"routes": [
@@ -26,7 +24,11 @@
"probes": [
{
"path": "/",
"mustContain": "root:RANDOMNESS_PLACEHOLDER"
"mustContain": "`"
},
{
"path": "/functions/es5.ts",
"mustContain": "+"
},
{
"path": "/pricing/",

View File

@@ -4,6 +4,7 @@
"version": "1.0.0",
"main": "index.js",
"devDependencies": {
"@now/node": "*",
"typescript": "3.5.3"
}
}

View File

@@ -6,7 +6,7 @@
"target": "esnext",
"module": "esnext",
"lib": ["dom", "es2017"],
"noEmit": true,
"noEmitOnError": true,
"moduleResolution": "node",
"allowSyntheticDefaultImports": true,
"strict": true,

View File

@@ -0,0 +1,6 @@
import { IncomingMessage, ServerResponse } from 'http';
export default function handler(req: IncomingMessage, res: ServerResponse) {
if (req && !req.thisDoesNotExist) {
res.end('no-emit-on-error-true:RANDOMNESS_PLACEHOLDER');
}
}

View File

@@ -0,0 +1,10 @@
{
"version": 2,
"builds": [{ "src": "index.ts", "use": "@now/node" }],
"probes": [
{
"path": "/",
"mustContain": "no-emit-on-error-true:RANDOMNESS_PLACEHOLDER"
}
]
}

View File

@@ -0,0 +1,6 @@
{
"private": true,
"devDependencies": {
"@types/node": "*"
}
}

View File

@@ -0,0 +1,10 @@
{
"compilerOptions": {
"strict": true,
"esModuleInterop": true,
"sourceMap": true,
"target": "esnext",
"noUnusedLocals": true,
"noEmitOnError": true
}
}

View File

@@ -0,0 +1,6 @@
import { IncomingMessage, ServerResponse } from 'http';
export default function handler(req: IncomingMessage, res: ServerResponse) {
if (req && !req.thisDoesNotExist) {
res.end('no-emit-on-error-false:RANDOMNESS_PLACEHOLDER');
}
}

View File

@@ -0,0 +1,10 @@
{
"version": 2,
"builds": [{ "src": "index.ts", "use": "@now/node" }],
"probes": [
{
"path": "/",
"mustContain": "no-emit-on-error-false:RANDOMNESS_PLACEHOLDER"
}
]
}

View File

@@ -0,0 +1,6 @@
{
"private": true,
"devDependencies": {
"@types/node": "*"
}
}

View File

@@ -0,0 +1,10 @@
{
"compilerOptions": {
"strict": true,
"esModuleInterop": true,
"sourceMap": true,
"target": "esnext",
"noUnusedLocals": true,
"noEmitOnError": false
}
}

View File

@@ -19,8 +19,25 @@ beforeAll(async () => {
const fixturesPath = path.resolve(__dirname, 'fixtures');
const testsThatFailToBuild = new Set(['45-noEmitOnError-true']);
// eslint-disable-next-line no-restricted-syntax
for (const fixture of fs.readdirSync(fixturesPath)) {
if (testsThatFailToBuild.has(fixture)) {
// eslint-disable-next-line no-loop-func
it(`should not build ${fixture}`, async () => {
try {
await testDeployment(
{ builderUrl, buildUtilsUrl },
path.join(fixturesPath, fixture),
);
} catch (err) {
expect(err.message).toMatch(/is ERROR/);
}
});
continue; //eslint-disable-line
}
// eslint-disable-next-line no-loop-func
it(`should build ${fixture}`, async () => {
await expect(

View File

@@ -1,6 +1,6 @@
{
"name": "@now/python",
"version": "0.2.15",
"version": "0.2.16",
"main": "./dist/index.js",
"license": "MIT",
"homepage": "https://zeit.co/docs/v2/deployments/official-builders/python-now-python",

View File

@@ -46,34 +46,10 @@ async function pipInstall(pipPath: string, workDir: string, ...args: string[]) {
}
}
async function pipInstallUser(pipPath: string, ...args: string[]) {
console.log(
`running "pip install --disable-pip-version-check --user ${args.join(
' '
)}"...`
);
try {
await execa(
pipPath,
['install', '--disable-pip-version-check', '--user', ...args],
{
stdio: 'inherit',
}
);
} catch (err) {
console.log(
`failed to run "pip install --disable-pip-version-check --user ${args.join(
' '
)}"`
);
throw err;
}
}
async function pipenvInstall(pyUserBase: string, srcDir: string) {
async function pipenvConvert(cmd: string, srcDir: string) {
console.log('running pipfile2req');
try {
const out = await execa.stdout(join(pyUserBase, 'bin', 'pipfile2req'), [], {
const out = await execa.stdout(cmd, [], {
cwd: srcDir,
});
fs.writeFileSync(join(srcDir, 'requirements.txt'), out);
@@ -108,8 +84,6 @@ export const build = async ({
workPath = destNow;
}
const pyUserBase = await getWriteableDirectory();
process.env.PYTHONUSERBASE = pyUserBase;
const pipPath = 'pip3';
try {
@@ -144,9 +118,23 @@ export const build = async ({
if (pipfileLockDir) {
console.log('found "Pipfile.lock"');
// Install pipenv.
await pipInstallUser(pipPath, 'pipfile-requirements', '--no-warn-script-location');
await pipenvInstall(pyUserBase, pipfileLockDir);
// Convert Pipenv.Lock to requirements.txt.
// We use a different`workPath` here because we want `pipfile-requirements` and it's dependencies
// to not be part of the lambda environment. By using pip's `--target` directive we can isolate
// it into a separate folder.
const tempDir = await getWriteableDirectory();
await pipInstall(
pipPath,
tempDir,
'pipfile-requirements',
'--no-warn-script-location'
);
// Python needs to know where to look up all the packages we just installed.
// We tell it to use the same location as used with `--target`
process.env.PYTHONPATH = tempDir;
const convertCmd = join(tempDir, 'bin', 'pipfile2req');
await pipenvConvert(convertCmd, pipfileLockDir);
}
fsFiles = await glob('**', workPath);

View File

@@ -1,6 +1,6 @@
{
"name": "@now/static-build",
"version": "0.9.7",
"version": "0.9.8",
"license": "MIT",
"main": "./dist/index",
"homepage": "https://zeit.co/docs/v2/deployments/official-builders/static-build-now-static-build",

View File

@@ -66,17 +66,12 @@ export default [
getOutputDirName: async () => 'dist',
defaultRoutes: [
{
src: '^/js/(.*)',
headers: { 'cache-control': 'max-age=31536000, immutable' },
src: '^/[^/]*\\.(js|txt|ico|json)',
headers: { 'cache-control': 'max-age=300' },
continue: true,
},
{
src: '^/css/(.*)',
headers: { 'cache-control': 'max-age=31536000, immutable' },
continue: true,
},
{
src: '^/img/(.*)',
src: '^/(img|js|css|fonts|media)/.*',
headers: { 'cache-control': 'max-age=31536000, immutable' },
continue: true,
},
@@ -84,7 +79,7 @@ export default [
handle: 'filesystem',
},
{
src: '/(.*)',
src: '^.*',
dest: '/index.html',
},
],
@@ -219,4 +214,23 @@ export default [
dependency: 'sapper',
getOutputDirName: async () => '__sapper__/export',
},
{
name: 'Saber',
dependency: 'saber',
getOutputDirName: async () => 'public',
defaultRoutes: [
{
src: '/_saber/.*',
headers: { 'cache-control': 'max-age=31536000, immutable' },
},
{
handle: 'filesystem',
},
{
src: '.*',
status: 404,
dest: '404.html',
},
],
},
];

View File

@@ -333,8 +333,14 @@ export async function build({
const spawnOpts = getSpawnOptions(meta, nodeVersion);
await runShellScript(path.join(workPath, entrypoint), [], spawnOpts);
validateDistDir(distPath, meta.isDev, config);
const output = await glob('**', distPath, mountpoint);
return glob('**', distPath, mountpoint);
return {
output,
routes: [],
watch: []
};
}
let message = `Build "src" is "${entrypoint}" but expected "package.json"`;

View File

@@ -4,21 +4,47 @@
{
"src": "package.json",
"use": "@now/static-build",
"config": { "zeroConfig": true }
"config": {
"zeroConfig": true
}
}
],
"probes": [
{ "path": "/", "mustContain": "13-vue" },
{
"path": "/",
"mustContain": "13-vue"
},
{
"path": "/js/app.js",
"headers": { "cache-control": "max-age=31536000, immutable" },
"headers": {
"cache-control": "max-age=31536000, immutable"
},
"mustContain": "function"
},
{
"path": "/css/app.css",
"headers": { "cache-control": "max-age=31536000, immutable" },
"headers": {
"cache-control": "max-age=31536000, immutable"
},
"mustContain": "font-family"
},
{ "path": "/923h3223329ddas", "mustContain": "13-vue" }
{
"path": "/robots.txt",
"headers": {
"cache-control": "max-age=300"
},
"mustContain": "Disallow"
},
{
"path": "/manifest.json",
"headers": {
"cache-control": "max-age=300"
},
"mustContain": "13-vue-manifest"
},
{
"path": "/923h3223329ddas",
"mustContain": "13-vue"
}
]
}

View File

@@ -0,0 +1,20 @@
{
"name": "13-vue-manifest",
"short_name": "13-vue-manifest",
"icons": [
{
"src": "./img/icons/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "./img/icons/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"start_url": "./index.html",
"display": "standalone",
"background_color": "#000000",
"theme_color": "#4DBA87"
}

View File

@@ -0,0 +1,2 @@
User-agent: *
Disallow:

View File

@@ -0,0 +1,4 @@
node_modules
*.log
.saber
public

View File

@@ -0,0 +1,11 @@
# my-saber-blog
## Scripts
### `npm run dev`
Run dev server at `http://localhost:3000`
### `npm run build`
Build your website to `public` folder which you can deploy to ZEIT Now, GitHub Pages, Netlify or wherever you want.

View File

@@ -0,0 +1,25 @@
{
"version": 2,
"builds": [
{
"src": "package.json",
"use": "@now/static-build",
"config": { "zeroConfig": true }
}
],
"probes": [
{
"path": "/",
"mustContain": "Your Awesome Title"
},
{
"path": "/_saber/js/client.js",
"headers": { "cache-control": "max-age=31536000, immutable" },
"mustContain": "function"
},
{
"path": "/not-exist",
"mustContain": "Back Home"
}
]
}

View File

@@ -0,0 +1,13 @@
{
"private": true,
"scripts": {
"dev": "saber",
"build": "saber build"
},
"devDependencies": {
"saber": "latest",
"saber-theme-minima": "latest",
"saber-plugin-feed": "latest",
"saber-plugin-query-posts": "latest"
}
}

View File

@@ -0,0 +1,9 @@
---
title: My Example Post
date: 2016-05-20
layout: post
---
Eos eu docendi tractatos sapientem, brute option menandri in vix, quando vivendo accommodare te ius. Nec melius fastidii constituam id, viderer theophrastus ad sit, hinc semper periculis cum id. Noluisse postulant assentior est in, no choro sadipscing repudiandae vix. Vis in euismod delenit dignissim. Ex quod nostrum sit, suas decore animal id ius, nobis solet detracto quo te.
No laudem altera adolescens has, volumus lucilius eum no. Eam ei nulla audiam efficiantur. Suas affert per no, ei tale nibh sea. Sea ne magna harum, in denique scriptorem sea, cetero alienum tibique ei eos. Labores persequeris referrentur eos ei.

View File

@@ -0,0 +1,11 @@
---
title: Some articles are just so long they deserve a really long title to see if things will break well
layout: post
date: 2016-05-18
---
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce bibendum neque eget nunc mattis eu sollicitudin enim tincidunt. Vestibulum lacus tortor, ultricies id dignissim ac, bibendum in velit. Proin convallis mi ac felis pharetra aliquam. Curabitur dignissim accumsan rutrum. In arcu magna, aliquet vel pretium et, molestie et arcu. Mauris lobortis nulla et felis ullamcorper bibendum. Phasellus et hendrerit mauris. Proin eget nibh a massa vestibulum pretium. Suspendisse eu nisl a ante aliquet bibendum quis a nunc. Praesent varius interdum vehicula. Aenean risus libero, placerat at vestibulum eget, ultricies eu enim. Praesent nulla tortor, malesuada adipiscing adipiscing sollicitudin, adipiscing eget est.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce bibendum neque eget nunc mattis eu sollicitudin enim tincidunt. Vestibulum lacus tortor, ultricies id dignissim ac, bibendum in velit. Proin convallis mi ac felis pharetra aliquam. Curabitur dignissim accumsan rutrum. In arcu magna, aliquet vel pretium et, molestie et arcu. Mauris lobortis nulla et felis ullamcorper bibendum. Phasellus et hendrerit mauris. Proin eget nibh a massa vestibulum pretium. Suspendisse eu nisl a ante aliquet bibendum quis a nunc. Praesent varius interdum vehicula. Aenean risus libero, placerat at vestibulum eget, ultricies eu enim. Praesent nulla tortor, malesuada adipiscing adipiscing sollicitudin, adipiscing eget est.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce bibendum neque eget nunc mattis eu sollicitudin enim tincidunt. Vestibulum lacus tortor, ultricies id dignissim ac, bibendum in velit. Proin convallis mi ac felis pharetra aliquam. Curabitur dignissim accumsan rutrum. In arcu magna, aliquet vel pretium et, molestie et arcu. Mauris lobortis nulla et felis ullamcorper bibendum. Phasellus et hendrerit mauris. Proin eget nibh a massa vestibulum pretium. Suspendisse eu nisl a ante aliquet bibendum quis a nunc. Praesent varius interdum vehicula. Aenean risus libero, placerat at vestibulum eget, ultricies eu enim. Praesent nulla tortor, malesuada adipiscing adipiscing sollicitudin, adipiscing eget est.

View File

@@ -0,0 +1,7 @@
---
title: 'Some articles are just so short that we have to make the footer stick'
date: 2016-05-19
layout: post
---
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

View File

@@ -0,0 +1,8 @@
---
title: About
layout: page
---
This is the Saber port of the base Jekyll theme. Check out the [GitHub project](https://github.com/egoist/saber-theme-minima) for detailed usages.
You can find out more info about customizing your theme, as well as basic Saber usage documentation at https://saber.land

View File

@@ -0,0 +1,6 @@
---
# Fallback to `default` layout if `index` is not found
layout: index
# Inject post list as `page.posts` (by saber-plugin-query-posts)
injectAllPosts: true
---

View File

@@ -0,0 +1,24 @@
theme: minima
siteConfig:
url: https://example.com
author: Author of This Site
email: author@your-domain.com
description: Write an awesome description for your new site here. You can edit this line in saber-config.yml. It will appear in your document head meta (for Google search results) site description.
themeConfig:
nav:
- text: Home
link: /
- text: About
link: /about.html
social:
twitter: saber_land
github: egoist
rss: true
plugins:
- resolve: saber-plugin-query-posts
- resolve: saber-plugin-feed
options:
atomFeed: true

View File

@@ -0,0 +1,3 @@
exports.getWebpackConfig = config => {
config.output.filename = 'js/[name].js';
};

View File

@@ -1480,10 +1480,10 @@
resolved "https://registry.yarnpkg.com/@zeit/ncc/-/ncc-0.20.4.tgz#00f0a25a88cac3712af4ba66561d9e281c6f05c9"
integrity sha512-fmq+F/QxPec+k/zvT7HiVpk7oiGFseS6brfT/AYqmCUp6QFRK7vZf2Ref46MImsg/g2W3g5X6SRvGRmOAvEfdA==
"@zeit/node-file-trace@0.2.9":
version "0.2.9"
resolved "https://registry.yarnpkg.com/@zeit/node-file-trace/-/node-file-trace-0.2.9.tgz#176aa55ae4800bfc847076b69b33df3bebc60201"
integrity sha512-OZU4HqNwlCEDIW67WTQnRjQ0ML7o9O8boPf1f9ffZbliKWRJrBPU+ydqvUtJeHICmY5Cjy9MQxwzo+q81G3uAA==
"@zeit/node-file-trace@0.2.13":
version "0.2.13"
resolved "https://registry.yarnpkg.com/@zeit/node-file-trace/-/node-file-trace-0.2.13.tgz#44b21a2c6bedc381f696ea03046c27cdd793cc9b"
integrity sha512-DxpZ1G1w88NnFwNcfUJlhkGsFCcx5kXksFEmhlBiI+k53km5vhRo6uO+ExI09YIcr29gOKglm1gusNiFEJaN8A==
dependencies:
acorn "^6.1.1"
acorn-stage3 "^2.0.0"