Compare commits

..

31 Commits

Author SHA1 Message Date
Steven
3fa7b80bde Publish
- @now/build-utils@0.9.6
 - @now/next@0.5.8
 - @now/node@0.12.2
2019-07-31 08:30:21 -04:00
Steven
d012e73166 [now-node] Bump node-file-trace to 0.2.5 (#852) 2019-07-31 08:29:09 -04:00
Andy
d6c46da37f [now-build-utils] Remove @now/nuxt from default builders (#850) 2019-07-31 08:29:04 -04:00
Andy
1508932ad6 [now-static-build] Allow setting the tag for zero-config builders (#842)
* [now-static-build] Allow to set the `tag` for zero-config builders

This reverts commit 32b6f1d6a9047920d6cc40385de711022f77c4d4.

* Remove unsupported builders

* Fix setting the tag
2019-07-31 08:28:58 -04:00
Steven
873b099f53 [now-node] Bump node-file-trace to 0.2.4 (#849) 2019-07-31 08:28:52 -04:00
Steven
6546d3b67d [now-build-utils] Fix require file path for legacy builders (#846)
* [now-build-utils] Fix require file path

* Add more tests
2019-07-31 08:28:46 -04:00
Steven
34ad4ac33a [now-next] Fix dev-server bundle output (#847)
* [now-next] Fix dev-server bundle

* [now-next] Fix bundle output dev-server
2019-07-31 08:28:39 -04:00
Steven
01d0b017af Publish
- @now/build-utils@0.9.5
 - @now/next@0.5.7
 - @now/node@0.12.1
 - @now/static-build@0.9.2
2019-07-30 07:38:20 -04:00
Steven
db88ad4b32 [master] Clean up package.json to match canary 2019-07-30 07:28:41 -04:00
Andy Bitz
4b846c3c88 Revert "[now-static-build] Allow to set the tag for zero-config builders"
This reverts commit d74d5141e4cb2c4e1e8a50bd66cad8d36f57e734.
2019-07-30 07:24:49 -04:00
Andy Bitz
2731435e3b [now-static-build] Allow to set the tag for zero-config builders 2019-07-30 07:24:43 -04:00
Steven
f18e1a6bd4 [now-static-build] Use ncc before publishing to npm (#839) 2019-07-30 07:24:31 -04:00
Steven
167d7bedec [now-next] Use ncc before publishing to npm (#832)
* [now-next] Change bridge build step

* Remove dependency on @now/node-bridge

* Test: print deploymentUrl

* Rename build script

* Use ncc before publishing

* Move deps to devDependencies
2019-07-30 07:24:11 -04:00
Sophearak Tha
cd0b1d61d1 [now-build-utils] Add debug() function (#831)
* Add `debug()` function

* Apply suggestions from code review

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

* Update packages/now-build-utils/src/debug.ts

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

* Apply suggestions from code review

Co-Authored-By: Steven <steven@ceriously.com>
2019-07-30 07:21:44 -04:00
Steven
86dc3708d2 [now-node] Fix 18-nested-tsconfig tests (#830)
* [now-node] Fix nested-tsconfig tests

* Remove unnecessary test
2019-07-30 07:21:19 -04:00
paulogdm
1e79eae029 Update _error.js route to return 404 status (#828) 2019-07-30 07:21:07 -04:00
paulogdm
d0c954210a Update types.ts (#829) 2019-07-30 07:20:55 -04:00
Steven
67c3481779 [now-build-utils] Use ncc before publishing to npm (#820)
* [now-build-utils] Use ncc before publish to npm

* Test all foreign fixtures

* Revert tests, but keep now-next
2019-07-30 07:20:42 -04:00
Steven
67473afd5b [now-node] Bump node-file-trace to 0.2.3 (#819)
* Silence vscode error

* Bump node-file-trace to 0.2.3

* Add test for mixed modules
2019-07-30 07:20:19 -04:00
Steven
3d52610acf [now-node] Fix symlink regression (#813) 2019-07-30 07:20:07 -04:00
Steven
729ba010c4 [now-node] Change TS default to esModuleInterop=true (#789)
* [now-node] Default to esModuleInterop=true

* Add test fixture 19-default-import-ts

* Change back to match ts-node
2019-07-30 07:19:51 -04:00
Steven
a470e563dc [now-node] Add logs with time for each step (#786)
* [now-node] Add logs with time for each step

* Fix typo
2019-07-30 07:19:33 -04:00
ywg-jean
15f674b8b7 [now-node] Yarn workspaces/transpilation followup (#782)
* 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!

* adds test with ts files in a subdir

* Updates typescript example to avoid node internal special casing

The initial example ended up passing even with a flawed implementation
because it unknowingly relied on a special case within node module's
resulotion engine which automaticaly resolves index files
within a module if they are located in the same directory as the
module's `package.json`

* upgrade to node-file-trace 0.2.2

* cleanup manual debugging leftovers

* fix yarn lock for node-file-trace 0.2.2

* more cleanup of manual tests

I offer my apologies about this mess
2019-07-30 07:19:15 -04:00
Andy Bitz
1e4e6b68e0 Publish
- @now/build-utils@0.9.4
2019-07-24 22:27:49 +02:00
Andy
2332100cff [now-build-utils] Do not use canary for zero config (#821) 2019-07-24 22:27:34 +02:00
Steven
9cb6f500b0 Publish
- @now/build-utils@0.9.3
 - @now/next@0.5.6
2019-07-23 14:45:11 -04:00
Joe Haddad
79a2bfde35 [now-next] Add immutable header to Next.js static assets (#810)
* Add immutable header to Next.js static assets

* Verify builder injects immutable header

* Use incorrect type

* Add missing field

* Add missing else clause
2019-07-23 14:43:29 -04:00
Luis Fernando Alvarez D
86a659e5c5 Normalize slash for nested paths (#788)
* Fixed slash issue in nested folders for Windows

* Added a test for dynamic routes in dev
2019-07-23 14:43:18 -04:00
Andy Bitz
0f00110db7 Publish
- @now/static-build@0.9.1
2019-07-22 20:51:23 +02:00
Andy
03ca6975ed [now-static-build] Use dev command in zero config when there is no (#808)
command
2019-07-22 20:50:25 +02:00
Andy
001813c529 [now-static-build] Adjust error message (#807) 2019-07-22 20:50:16 +02:00
56 changed files with 444 additions and 157 deletions

View File

@@ -44,6 +44,7 @@
},
"devDependencies": {
"@types/node": "*",
"@zeit/ncc": "0.20.4",
"async-retry": "1.2.3",
"buffer-replace": "1.0.0",
"codecov": "3.2.0",

View File

@@ -0,0 +1,6 @@
tsc
rm dist/index.js
ncc build src/index.ts -o dist/main
mv dist/main/index.js dist/index.js
rm -rf dist/main

View File

@@ -1 +1 @@
module.exports = require('../dist/fs/download').default;
module.exports = require('../dist/index').download;

View File

@@ -1 +1 @@
module.exports = require('../dist/fs/get-writable-directory').default;
module.exports = require('../dist/index').getWriteableDirectory;

View File

@@ -1 +1 @@
module.exports = require('../dist/fs/glob').default;
module.exports = require('../dist/index').glob;

View File

@@ -1 +1 @@
module.exports = require('../dist/fs/rename').default;
module.exports = require('../dist/index').rename;

View File

@@ -1 +1 @@
module.exports = require('../dist/fs/run-user-scripts');
module.exports = require('../dist/index');

View File

@@ -1 +1 @@
module.exports = require('../dist/fs/stream-to-buffer').default;
module.exports = require('../dist/index').streamToBuffer;

View File

@@ -1,6 +1,6 @@
{
"name": "@now/build-utils",
"version": "0.9.2",
"version": "0.9.6",
"license": "MIT",
"main": "./dist/index.js",
"types": "./dist/index.d.js",
@@ -11,23 +11,9 @@
"directory": "packages/now-build-utils"
},
"scripts": {
"build": "tsc",
"test": "tsc && jest",
"prepublishOnly": "tsc"
},
"dependencies": {
"async-retry": "1.2.3",
"async-sema": "2.1.4",
"cross-spawn": "6.0.5",
"end-of-stream": "1.4.1",
"fs-extra": "7.0.0",
"glob": "7.1.3",
"into-stream": "5.0.0",
"minimatch": "3.0.4",
"multistream": "2.1.1",
"node-fetch": "2.2.0",
"semver": "6.1.1",
"yazl": "2.4.3"
"build": "./build.sh",
"test": "./build.sh && jest",
"prepublishOnly": "./build.sh"
},
"devDependencies": {
"@types/async-retry": "^1.2.1",
@@ -39,7 +25,19 @@
"@types/node-fetch": "^2.1.6",
"@types/semver": "6.0.0",
"@types/yazl": "^2.4.1",
"async-retry": "1.2.3",
"async-sema": "2.1.4",
"cross-spawn": "6.0.5",
"end-of-stream": "1.4.1",
"execa": "^1.0.0",
"typescript": "3.5.2"
"fs-extra": "7.0.0",
"glob": "7.1.3",
"into-stream": "5.0.0",
"minimatch": "3.0.4",
"multistream": "2.1.1",
"node-fetch": "2.2.0",
"semver": "6.1.1",
"typescript": "3.5.2",
"yazl": "2.4.3"
}
}

View File

@@ -0,0 +1,7 @@
export default function debug(message: string, ...additional: any[]) {
if (process.env.NOW_BUILDER_DEBUG) {
console.log(message, ...additional);
} else if (process.env.NOW_BUILDER_ANNOTATE) {
console.log(`[now-builder-debug] ${message}`, ...additional);
}
}

View File

@@ -6,24 +6,24 @@ interface ErrorResponse {
message: string;
}
interface Options {
tag?: 'canary' | 'latest';
}
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 }],
['nuxt', { src, use: '@now/nuxt', config }],
]);
const API_BUILDERS: Builder[] = [
{ src: 'api/**/*.js', use: '@now/node@canary', config },
{ src: 'api/**/*.ts', use: '@now/node@canary', config },
{ src: 'api/**/*.rs', use: '@now/rust', config },
{ src: 'api/**/*.js', use: '@now/node', config },
{ src: 'api/**/*.ts', use: '@now/node', config },
{ src: 'api/**/*.go', use: '@now/go', config },
{ src: 'api/**/*.php', use: '@now/php', config },
{ src: 'api/**/*.py', use: '@now/python', config },
{ src: 'api/**/*.rb', use: '@now/ruby', config },
{ src: 'api/**/*.sh', use: '@now/bash', config },
];
const MISSING_BUILD_SCRIPT_ERROR: ErrorResponse = {
@@ -101,7 +101,8 @@ async function detectApiBuilders(files: string[]): Promise<Builder[]> {
// to determine what builders to use
export async function detectBuilders(
files: string[],
pkg?: PackageJson | undefined | null
pkg?: PackageJson | undefined | null,
options?: Options
): Promise<{
builders: Builder[] | null;
errors: ErrorResponse[] | null;
@@ -109,7 +110,7 @@ export async function detectBuilders(
const errors: ErrorResponse[] = [];
// Detect all builders for the `api` directory before anything else
const builders = await detectApiBuilders(files);
let builders = await detectApiBuilders(files);
if (pkg && hasBuildScript(pkg)) {
builders.push(await detectBuilder(pkg));
@@ -145,6 +146,22 @@ export async function detectBuilders(
}
}
// Change the tag for the builders
if (builders && builders.length) {
const tag = options && options.tag;
if (tag) {
builders = builders.map((builder: Builder) => {
// @now/static has no canary builder
if (builder.use !== '@now/static') {
builder.use = `${builder.use}@${tag}`;
}
return builder;
});
}
}
return {
builders: builders.length ? builders : null,
errors: errors.length ? errors : null,

View File

@@ -18,6 +18,7 @@ import streamToBuffer from './fs/stream-to-buffer';
import shouldServe from './should-serve';
import { detectBuilders } from './detect-builders';
import { detectRoutes } from './detect-routes';
import debug from './debug';
export {
FileBlob,
@@ -40,6 +41,7 @@ export {
shouldServe,
detectBuilders,
detectRoutes,
debug,
};
export * from './types';

View File

@@ -23,6 +23,8 @@ export interface Route {
headers?: {
[key: string]: string;
};
continue?: boolean;
status?: number;
}
export interface Config {

View File

@@ -116,6 +116,36 @@ it('should match all semver ranges', () => {
);
});
it('should support require by path for legacy builders', () => {
const index = require('@now/build-utils');
const download2 = require('@now/build-utils/fs/download.js');
const getWriteableDirectory2 = require('@now/build-utils/fs/get-writable-directory.js');
const glob2 = require('@now/build-utils/fs/glob.js');
const rename2 = require('@now/build-utils/fs/rename.js');
const {
runNpmInstall: runNpmInstall2,
} = require('@now/build-utils/fs/run-user-scripts.js');
const streamToBuffer2 = require('@now/build-utils/fs/stream-to-buffer.js');
const FileBlob2 = require('@now/build-utils/file-blob.js');
const FileFsRef2 = require('@now/build-utils/file-fs-ref.js');
const FileRef2 = require('@now/build-utils/file-ref.js');
const { Lambda: Lambda2 } = require('@now/build-utils/lambda.js');
expect(download2).toBe(index.download);
expect(getWriteableDirectory2).toBe(index.getWriteableDirectory);
expect(glob2).toBe(index.glob);
expect(rename2).toBe(index.rename);
expect(runNpmInstall2).toBe(index.runNpmInstall);
expect(streamToBuffer2).toBe(index.streamToBuffer);
expect(FileBlob2).toBe(index.FileBlob);
expect(FileFsRef2).toBe(index.FileFsRef);
expect(FileRef2).toBe(index.FileRef);
expect(Lambda2).toBe(index.Lambda);
});
// own fixtures
const fixturesPath = path.resolve(__dirname, 'fixtures');
@@ -135,7 +165,7 @@ for (const fixture of fs.readdirSync(fixturesPath)) {
// few foreign tests
const buildersToTestWith = ['now-node', 'now-static-build'];
const buildersToTestWith = ['now-next', 'now-node', 'now-static-build'];
// eslint-disable-next-line no-restricted-syntax
for (const builder of buildersToTestWith) {
@@ -147,7 +177,7 @@ for (const builder of buildersToTestWith) {
// eslint-disable-next-line no-restricted-syntax
for (const fixture of fs.readdirSync(fixturesPath2)) {
// don't run all foreign fixtures, just some
if (['01-cowsay', '03-env-vars'].includes(fixture)) {
if (['01-cowsay', '01-cache-headers', '03-env-vars'].includes(fixture)) {
// eslint-disable-next-line no-loop-func
it(`should build ${builder}/${fixture}`, async () => {
await expect(
@@ -224,7 +254,7 @@ it('Test `detectBuilders`', async () => {
// no package.json + no build + raw static + api
const files = ['api/users.js', 'index.html'];
const { builders, errors } = await detectBuilders(files);
expect(builders[0].use).toBe('@now/node@canary');
expect(builders[0].use).toBe('@now/node');
expect(builders[0].src).toBe('api/users.js');
expect(builders[1].use).toBe('@now/static');
expect(builders[1].src).toBe('index.html');
@@ -236,7 +266,7 @@ it('Test `detectBuilders`', async () => {
// package.json + no build + root + api
const files = ['index.html', 'api/[endpoint].js', 'static/image.png'];
const { builders, errors } = await detectBuilders(files);
expect(builders[0].use).toBe('@now/node@canary');
expect(builders[0].use).toBe('@now/node');
expect(builders[0].src).toBe('api/[endpoint].js');
expect(builders[1].use).toBe('@now/static');
expect(builders[1].src).toBe('index.html');
@@ -255,7 +285,7 @@ it('Test `detectBuilders`', async () => {
];
const { builders } = await detectBuilders(files);
expect(builders[0].use).toBe('@now/node@canary');
expect(builders[0].use).toBe('@now/node');
expect(builders[0].src).toBe('api/[endpoint]/[id].js');
expect(builders.length).toBe(1);
}
@@ -269,7 +299,7 @@ it('Test `detectBuilders`', async () => {
const files = ['package.json', 'api/endpoint.js', 'public/index.html'];
const { builders } = await detectBuilders(files, pkg);
expect(builders[0].use).toBe('@now/node@canary');
expect(builders[0].use).toBe('@now/node');
expect(builders[0].src).toBe('api/endpoint.js');
expect(builders[1].use).toBe('@now/next');
expect(builders[1].src).toBe('package.json');
@@ -285,7 +315,7 @@ it('Test `detectBuilders`', async () => {
const files = ['package.json', 'api/endpoint.js', 'index.html'];
const { builders } = await detectBuilders(files, pkg);
expect(builders[0].use).toBe('@now/node@canary');
expect(builders[0].use).toBe('@now/node');
expect(builders[0].src).toBe('api/endpoint.js');
expect(builders[1].use).toBe('@now/next');
expect(builders[1].src).toBe('package.json');
@@ -297,7 +327,7 @@ it('Test `detectBuilders`', async () => {
const files = ['api/endpoint.js', 'index.html', 'favicon.ico'];
const { builders } = await detectBuilders(files);
expect(builders[0].use).toBe('@now/node@canary');
expect(builders[0].use).toBe('@now/node');
expect(builders[0].src).toBe('api/endpoint.js');
expect(builders[1].use).toBe('@now/static');
expect(builders[1].src).toBe('favicon.ico');
@@ -316,7 +346,7 @@ it('Test `detectBuilders`', async () => {
];
const { builders } = await detectBuilders(files);
expect(builders[0].use).toBe('@now/node@canary');
expect(builders[0].use).toBe('@now/node');
expect(builders[0].src).toBe('api/endpoint.js');
expect(builders[1].use).toBe('@now/static');
expect(builders[1].src).toBe('public/**/*');
@@ -355,7 +385,7 @@ it('Test `detectBuilders`', async () => {
const files = ['package.json', 'pages/index.js'];
const { builders } = await detectBuilders(files, pkg);
expect(builders[0].use).toBe('@now/nuxt');
expect(builders[0].use).toBe('@now/static-build');
expect(builders[0].src).toBe('package.json');
expect(builders.length).toBe(1);
}
@@ -366,7 +396,7 @@ it('Test `detectBuilders`', async () => {
const files = ['package.json', 'api/[endpoint].js'];
const { builders } = await detectBuilders(files, pkg);
expect(builders[0].use).toBe('@now/node@canary');
expect(builders[0].use).toBe('@now/node');
expect(builders[0].src).toBe('api/[endpoint].js');
expect(builders.length).toBe(1);
}
@@ -397,6 +427,25 @@ it('Test `detectBuilders`', async () => {
expect(builders).toBe(null);
expect(errors).toBe(null);
}
{
// package.json + api + canary
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: 'canary' });
expect(builders[0].use).toBe('@now/node@canary');
expect(builders[1].use).toBe('@now/node@canary');
expect(builders[2].use).toBe('@now/next@canary');
expect(builders.length).toBe(3);
}
});
it('Test `detectRoutes`', async () => {

View File

@@ -1,2 +1,2 @@
/dist
/src/now__bridge.d.ts
/src/now__bridge.ts

16
packages/now-next/build.sh Executable file
View File

@@ -0,0 +1,16 @@
#!/bin/bash
set -euo pipefail
bridge_defs="$(dirname $(pwd))/now-node-bridge/src/bridge.ts"
cp -v "$bridge_defs" src/now__bridge.ts
tsc
ncc build src/dev-server.ts -o dist/dev
mv dist/dev/index.js dist/dev-server.js
rm -rf dist/dev
ncc build src/index.ts -o dist/main
mv dist/main/index.js dist/index.js
rm -rf dist/main

View File

@@ -1,11 +0,0 @@
#!/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 --cwd "$bridge_entrypoint"
fi
cp -v "$bridge_defs" src/now__bridge.d.ts

View File

@@ -1,33 +1,30 @@
{
"name": "@now/next",
"version": "0.5.5",
"version": "0.5.8",
"license": "MIT",
"main": "./dist/index",
"homepage": "https://zeit.co/docs/v2/deployments/official-builders/next-js-now-next",
"scripts": {
"build": "./getBridgeTypes.sh && tsc",
"test": "npm run build && jest",
"prepublish": "yarn run build"
"build": "./build.sh",
"test": "./build.sh && jest",
"prepublishOnly": "./build.sh"
},
"repository": {
"type": "git",
"url": "https://github.com/zeit/now-builders.git",
"directory": "packages/now-next"
},
"dependencies": {
"@now/node-bridge": "1.2.3",
"fs-extra": "^7.0.0",
"get-port": "^5.0.0",
"resolve-from": "^5.0.0",
"semver": "^5.6.0"
},
"files": [
"dist"
],
"devDependencies": {
"@types/next-server": "^8.0.0",
"@types/resolve-from": "^5.0.1",
"@types/semver": "^6.0.0",
"@types/next-server": "8.0.0",
"@types/resolve-from": "5.0.1",
"@types/semver": "6.0.0",
"fs-extra": "7.0.0",
"get-port": "5.0.0",
"resolve-from": "5.0.0",
"semver": "6.1.1",
"typescript": "3.5.2"
}
}

View File

@@ -1,4 +1,4 @@
import { ChildProcess, fork, SpawnOptions } from 'child_process';
import { ChildProcess, fork } from 'child_process';
import {
pathExists,
readFile,
@@ -16,33 +16,34 @@ import {
FileBlob,
FileFsRef,
Files,
getNodeVersion,
getSpawnOptions,
glob,
Lambda,
PrepareCacheOptions,
runNpmInstall,
runPackageJsonScript,
getNodeVersion,
getSpawnOptions,
Route,
} from '@now/build-utils';
import createServerlessConfig from './create-serverless-config';
import nextLegacyVersions from './legacy-versions';
import {
EnvConfig,
excludeFiles,
filesFromDirectory,
getDynamicRoutes,
getNextConfig,
getPathsInside,
getRoutes,
includeOnlyEntryDirectory,
isDynamicRoute,
normalizePackageJson,
filesFromDirectory,
normalizePage,
stringMap,
syncEnvVars,
validateEntrypoint,
normalizePage,
getDynamicRoutes,
isDynamicRoute,
} from './utils';
import createServerlessConfig from './create-serverless-config';
interface BuildParamsMeta {
isDev: boolean | undefined;
@@ -157,7 +158,7 @@ export const build = async ({
entrypoint,
meta = {} as BuildParamsMeta,
}: BuildParamsType): Promise<{
routes?: ({ src?: string; dest?: string } | { handle: string })[];
routes: Route[];
output: Files;
watch?: string[];
childProcesses: ChildProcess[];
@@ -301,7 +302,7 @@ export const build = async ({
await unlinkFile(path.join(entryPath, '.npmrc'));
}
const exportedPageRoutes: { src: string; dest: string }[] = [];
const exportedPageRoutes: Route[] = [];
const lambdas: { [key: string]: Lambda } = {};
const staticPages: { [key: string]: FileFsRef } = {};
const dynamicPages: string[] = [];
@@ -330,7 +331,7 @@ export const build = async ({
);
const launcherFiles = {
'now__bridge.js': new FileFsRef({
fsPath: require('@now/node-bridge'),
fsPath: path.join(__dirname, 'now__bridge.js'),
}),
};
const nextFiles: { [key: string]: FileFsRef } = {
@@ -394,7 +395,7 @@ export const build = async ({
console.log('preparing lambda files...');
const launcherFiles = {
'now__bridge.js': new FileFsRef({
fsPath: require('@now/node-bridge'),
fsPath: path.join(__dirname, 'now__bridge.js'),
}),
'now__launcher.js': new FileFsRef({
fsPath: path.join(__dirname, 'launcher.js'),
@@ -536,6 +537,16 @@ export const build = async ({
routes: [
// Static exported pages (.html rewrites)
...exportedPageRoutes,
// Before we handle static files we need to set proper caching headers
{
// This ensures we only match known emitted-by-Next.js files and not
// user-emitted files which may be missing a hash in their filename.
src: '/_next/static/(?:[^/]+/pages|chunks|runtime)/.+',
// Next.js assets contain a hash or entropy in their filenames, so they
// are guaranteed to be unique and cacheable indefinitely.
headers: { 'cache-control': 'public,max-age=31536000,immutable' },
continue: true,
},
// Next.js page lambdas, `static/` folder, reserved assets, and `public/`
// folder
{ handle: 'filesystem' },
@@ -547,6 +558,7 @@ export const build = async ({
{
src: path.join('/', entryDirectory, '.*'),
dest: path.join('/', entryDirectory, '_error'),
status: 404,
},
]),
],

View File

@@ -3,8 +3,8 @@ if (!process.env.NODE_ENV) {
process.env.NOW_REGION === 'dev1' ? 'development' : 'production';
}
const { Server } = require('http');
const { Bridge } = require('./now__bridge');
import { Server } from 'http';
import { Bridge } from './now__bridge';
const page = require('./page');
// page.render is for React rendering

View File

@@ -228,7 +228,7 @@ function getRoutes(
const relativeToPages = path.relative('pages', relativePath);
const extension = path.extname(relativeToPages);
const pageName = relativeToPages.replace(extension, '');
const pageName = relativeToPages.replace(extension, '').replace(/\\/g, '/');
if (pageName.startsWith('_')) {
continue;

View File

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

View File

@@ -0,0 +1,12 @@
{
"version": 2,
"builds": [{ "src": "package.json", "use": "@now/next" }],
"probes": [
{
"path": "/_next/static/testing-build-id/pages/index.js",
"responseHeaders": {
"cache-control": "public,max-age=31536000,immutable"
}
}
]
}

View File

@@ -0,0 +1,7 @@
{
"dependencies": {
"next": "latest",
"react": "^16.8.6",
"react-dom": "^16.8.6"
}
}

View File

@@ -0,0 +1 @@
export default () => 'Hi';

View File

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

View File

@@ -22,6 +22,24 @@ describe('build meta dev', () => {
export default () => 'Index page'
`,
}),
'pages/nested/[param].js': new FileBlob({
mode: 0o777,
data: `
export default () => 'Dynamic page'
`,
}),
'pages/nested/page.tsx': new FileBlob({
mode: 0o777,
data: `
export default () => 'Nested page'
`,
}),
'pages/api/test.js': new FileBlob({
mode: 0o777,
data: `
export default (req, res) => res.status(200).end('API Route')
`,
}),
// This file should be omitted because `pages/index.js` will use the same route
'public/index': new FileBlob({
mode: 0o777,
@@ -39,9 +57,14 @@ describe('build meta dev', () => {
"now-build": "next build"
},
"dependencies": {
"next": "8",
"next": "9",
"react": "16",
"react-dom": "16"
},
"devDependencies": {
"@types/node": "12",
"@types/react": "16",
"typescript": "3"
}
}
`,
@@ -80,11 +103,20 @@ describe('build meta dev', () => {
{ src: '/static/(.*)', dest: 'http://localhost:5000/static/$1' },
{ src: '/index', dest: 'http://localhost:5000/index' },
{ src: '/', dest: 'http://localhost:5000/' },
{ src: '/nested/page', dest: 'http://localhost:5000/nested/page' },
{ src: '/api/test', dest: 'http://localhost:5000/api/test' },
{
src: '^/(nested\\/([^\\/]+?)(?:\\/)?)$',
dest: 'http://localhost:5000/$1',
},
{ src: '/data.txt', dest: 'http://localhost:5000/data.txt' },
]);
expect(watch).toEqual([
'next.config.js',
'pages/index.js',
'pages/nested/[param].js',
'pages/nested/page.tsx',
'pages/api/test.js',
'public/index',
'public/data.txt',
'package.json',

View File

@@ -0,0 +1,13 @@
describe('export', () => {
it('should require by path main', async () => {
const main = require('@now/next');
expect(main).toBeDefined();
});
it('should require by path dev-server relative to index', async () => {
const index = require('@now/next/dist/index.js');
const server = require('@now/next/dist/dev-server.js');
expect(index).toBeDefined();
expect(server).toBeDefined();
});
});

View File

@@ -6,7 +6,7 @@ const {
normalizePackageJson,
getNextConfig,
} = require('@now/next/dist/utils');
const FileRef = require('@now/build-utils/file-ref'); // eslint-disable-line import/no-extraneous-dependencies
const { FileRef } = require('@now/build-utils'); // eslint-disable-line import/no-extraneous-dependencies
describe('getNextConfig', () => {
const workPath = path.join(__dirname, 'fixtures');

View File

@@ -1,6 +1,6 @@
{
"name": "@now/node",
"version": "0.12.0",
"version": "0.12.2",
"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.1",
"@zeit/node-file-trace": "0.2.5",
"content-type": "1.0.4",
"cookie": "0.4.0",
"etag": "1.8.1",

View File

@@ -56,13 +56,17 @@ async function downloadInstallAndBundle({
meta,
}: DownloadOptions) {
console.log('downloading user files...');
const downloadTime = Date.now();
const downloadedFiles = await download(files, workPath, meta);
console.log(`download complete [${Date.now() - downloadTime}ms]`);
console.log("installing dependencies for user's code...");
const installTime = Date.now();
const entrypointFsDirname = join(workPath, dirname(entrypoint));
const nodeVersion = await getNodeVersion(entrypointFsDirname);
const spawnOpts = getSpawnOptions(meta, nodeVersion);
await runNpmInstall(entrypointFsDirname, ['--prefer-offline'], spawnOpts);
console.log(`install complete [${Date.now() - installTime}ms]`);
const entrypointPath = downloadedFiles[entrypoint].fsPath;
return { entrypointPath, entrypointFsDirname, nodeVersion, spawnOpts };
@@ -72,8 +76,7 @@ async function compile(
workPath: string,
entrypointPath: string,
entrypoint: string,
config: CompilerConfig,
{ isDev, filesChanged, filesRemoved }: Meta
config: CompilerConfig
): Promise<{
preparedFiles: Files;
shouldAddSourcemapSupport: boolean;
@@ -162,6 +165,7 @@ async function compile(
const { fileList, esmFileList } = await nodeFileTrace([...inputFiles], {
base: workPath,
ts: true,
mixedModules: true,
ignore: config.excludeFiles,
readFile(fsPath: string): Buffer | string | null {
const relPath = relative(workPath, fsPath);
@@ -175,9 +179,12 @@ async function compile(
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 });
let entry: File;
if (isSymbolicLink(mode)) {
entry = new FileFsRef({ fsPath, mode });
} else {
entry = new FileBlob({ data: source, mode });
}
fsCache.set(relPath, entry);
sourceCache.set(relPath, source);
return source.toString();
@@ -294,16 +301,19 @@ export async function build({
});
console.log('running user script...');
const runScriptTime = Date.now();
await runPackageJsonScript(entrypointFsDirname, 'now-build', spawnOpts);
console.log(`script complete [${Date.now() - runScriptTime}ms]`);
console.log('tracing input files...');
const traceTime = Date.now();
const { preparedFiles, shouldAddSourcemapSupport, watch } = await compile(
workPath,
entrypointPath,
entrypoint,
config,
meta
config
);
console.log(`trace complete [${Date.now() - traceTime}ms]`);
const launcherFiles: Files = {
[`${LAUNCHER_FILENAME}.js`]: new FileBlob({

View File

@@ -453,11 +453,18 @@ function fixConfig(ts: TSCommon, config: _ts.ParsedCommandLine) {
delete config.options.tsBuildInfoFile;
delete config.options.incremental;
// Target ES5 output by default (instead of ES3).
// Target esnext output by default (instead of ES3).
// This will prevent TS from polyfill/downlevel emit.
if (config.options.target === undefined) {
config.options.target = ts.ScriptTarget.ESNext;
}
// When mixing TS with JS, its best to enable this flag.
// This is useful when no `tsconfig.json` is supplied.
if (config.options.esModuleInterop === undefined) {
config.options.esModuleInterop = true;
}
// Target CommonJS, always!
config.options.module = ts.ModuleKind.CommonJS;

View File

@@ -3,13 +3,15 @@ import { parse } from 'url';
const func = (req: IncomingMessage, res: ServerResponse) => {
if (req.url) {
const url = parse(req.url);
const { pathname, search } = parse(req.url);
const location = pathname
? pathname.replace(/\/+/g, '/') + (search ? search : '')
: '/';
/*
res.writeHead(302, {
Location: url.pathname
? url.pathname.replace(/\/+/g, '/') + (url.search ? url.search : '')
: '/',
});
res.end();
Location: location
});*/
res.end(`double-redirect:RANDOMNESS_PLACEHOLDER:${location}`);
}
};

View File

@@ -29,7 +29,7 @@
"mustContain": "root:RANDOMNESS_PLACEHOLDER"
},
{
"path": "//",
"path": "/pricing/",
"mustContain": "trailing-redirect:RANDOMNESS_PLACEHOLDER"
}
]

View File

@@ -0,0 +1,8 @@
//@ts-ignore test will compile during deployment
import express from 'express';
const router = express.Router();
export default function handler(req: any, res: any) {
if (router && req) res.end('default-import:RANDOMNESS_PLACEHOLDER');
else res.end('failed to fetch default import');
}

View File

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

View File

@@ -0,0 +1,6 @@
{
"dependencies": {
"@types/express": "4.17.0",
"express": "4.17.1"
}
}

View File

@@ -0,0 +1,11 @@
import { dep1 } from './js/ecmascript-module';
const { dep2 } = require('./js/commonjs-module');
module.exports = (req, res) => {
if (req && typeof dep1 === 'string' && typeof dep2 === 'string') {
res.end('mixed-modules:js:RANDOMNESS_PLACEHOLDER');
} else {
res.end('import failed');
}
};

View File

@@ -0,0 +1,11 @@
import { IncomingMessage, ServerResponse } from 'http';
import { dep1 } from './ts/ecmascript-module';
const { dep2 } = require('./ts/commonjs-module');
module.exports = (req: IncomingMessage, res: ServerResponse) => {
if (req && typeof dep1 === 'string' && typeof dep2 === 'string') {
res.end('mixed-modules:ts:RANDOMNESS_PLACEHOLDER');
} else {
res.end('import failed');
}
};

View File

@@ -0,0 +1 @@
module.exports = { dep2: 'dep2' };

View File

@@ -0,0 +1,2 @@
export const dep1 = 'dep1';
export const another = 'another';

View File

@@ -0,0 +1,5 @@
{
"engines": {
"node": "10.x"
}
}

View File

@@ -0,0 +1,14 @@
{
"version": 2,
"builds": [{ "src": "entrypoint**", "use": "@now/node" }],
"probes": [
{
"path": "/entrypoint.js",
"mustContain": "mixed-modules:js:RANDOMNESS_PLACEHOLDER"
},
{
"path": "/entrypoint.ts",
"mustContain": "mixed-modules:ts:RANDOMNESS_PLACEHOLDER"
}
]
}

View File

@@ -0,0 +1 @@
module.exports = { dep2: 'dep2' };

View File

@@ -0,0 +1 @@
export const dep1 = 'dep1';

View File

@@ -0,0 +1,5 @@
{
"engines": {
"node": "10.x"
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "@builders-typescript-test/lib",
"main": "index.ts",
"main": "src/index",
"version": "1.0.0",
"devDependencies": {
"typescript": "^3.4.5"

View File

@@ -1,4 +1,4 @@
{
"extends": "../../tsconfig.json",
"include": ["./**/*.ts"]
"include": ["src/**/*.ts"]
}

View File

@@ -0,0 +1,4 @@
#!/bin/bash
set -euo pipefail
ncc build src/index.ts -o dist

View File

@@ -1,6 +1,6 @@
{
"name": "@now/static-build",
"version": "0.9.0",
"version": "0.9.2",
"license": "MIT",
"main": "./dist/index",
"homepage": "https://zeit.co/docs/v2/deployments/official-builders/static-build-now-static-build",
@@ -13,17 +13,15 @@
"directory": "packages/now-static-build"
},
"scripts": {
"build": "tsc",
"test": "tsc && jest",
"prepublishOnly": "tsc"
},
"dependencies": {
"cross-spawn": "6.0.5",
"get-port": "5.0.0",
"promise-timeout": "1.3.0"
"build": "./build.sh",
"test": "./build.sh && jest",
"prepublishOnly": "./build.sh"
},
"devDependencies": {
"@types/promise-timeout": "1.3.0",
"cross-spawn": "6.0.5",
"get-port": "5.0.0",
"promise-timeout": "1.3.0",
"typescript": "3.5.2"
}
}

View File

@@ -58,9 +58,7 @@ function validateDistDir(
: `\nMake sure you configure the the correct distDir: ${docsUrl}`;
if (!exists()) {
throw new Error(
`Build was unable to create the distDir: "${distDirName}".${info}`
);
throw new Error(`No output directory named "${distDirName}" found.${info}`);
}
if (!isDirectory()) {
@@ -76,10 +74,9 @@ function validateDistDir(
}
}
function getCommand(pkg: PackageJson, cmd: string, config: Config) {
function getCommand(pkg: PackageJson, cmd: string, { zeroConfig }: Config) {
// The `dev` script can be `now dev`
const nowCmd = `now-${cmd}`;
const { zeroConfig } = config;
if (!zeroConfig && cmd === 'dev') {
return nowCmd;
@@ -95,7 +92,7 @@ function getCommand(pkg: PackageJson, cmd: string, config: Config) {
return cmd;
}
return nowCmd;
return zeroConfig ? cmd : nowCmd;
}
export const version = 2;

View File

@@ -52,6 +52,7 @@ async function nowDeploy (bodies, randomness) {
}
console.log('id', deploymentId);
console.log('deploymentUrl', `https://${deploymentUrl}`);
for (let i = 0; i < 750; i += 1) {
const { state } = await deploymentGet(deploymentId);

View File

@@ -102,6 +102,21 @@ async function testDeployment (
+ ` Response headers:\n ${headers}`
);
}
} else if (probe.responseHeaders) {
// eslint-disable-next-line no-loop-func
Object.keys(probe.responseHeaders).forEach((header) => {
if (resp.headers.get(header) !== probe.responseHeaders[header]) {
const headers = Array.from(resp.headers.entries())
.map(([ k, v ]) => ` ${k}=${v}`)
.join('\n');
throw new Error(
`Fetched page ${probeUrl} does not contain header ${header}: \`${
probe.responseHeaders[header]
}\`.\n\nResponse headers:\n ${headers}`
);
}
});
} else {
assert(false, 'probe must have a test condition');
}

View File

@@ -1135,11 +1135,6 @@
resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b"
integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==
"@now/node-bridge@1.2.2":
version "1.2.2"
resolved "https://registry.yarnpkg.com/@now/node-bridge/-/node-bridge-1.2.2.tgz#b4740d8806227b8dd1d4d8481e21b3b30ad299b4"
integrity sha512-E5xqal3QRN8RvcQ4Q82vtg/hvWmQWaIYp2bJHd550Ps/kemGabcwAAQsP/TUM/4b5oYlOmjrfuYPq9AhMvFqkQ==
"@now/php-bridge@^0.5.3":
version "0.5.3"
resolved "https://registry.yarnpkg.com/@now/php-bridge/-/php-bridge-0.5.3.tgz#fe8cc02af247b323979347ebbb7090b547938694"
@@ -1369,27 +1364,16 @@
dependencies:
"@types/node" "*"
"@types/next-server@*", "@types/next-server@^8.0.0":
version "8.1.2"
resolved "https://registry.yarnpkg.com/@types/next-server/-/next-server-8.1.2.tgz#64c64c74ff9975338447ea0174ca430165895bab"
integrity sha512-Fm4QhAxwDlC9AHiGy23Lhv7DeTTt1O1s7tnAsyVOLPjePmYXPZVbOCrxd2oRHZnIIYWw41JelLbq4hN1B5idlQ==
"@types/next-server@8.0.0":
version "8.0.0"
resolved "https://registry.yarnpkg.com/@types/next-server/-/next-server-8.0.0.tgz#255ed9b0cf5a518b0137dd6a72a4f9aeddbbeb7d"
integrity sha512-TYWT510LScQJU6ACRqcnnK1IBdeZsXCOGgMvZrAgghQ6TXD1xE92qdTHh051WtXrcm9OjisZhI0Jx3i9PU3IuA==
dependencies:
"@types/next" "*"
"@types/node" "*"
"@types/react" "*"
"@types/react-loadable" "*"
"@types/next@*":
version "8.0.6"
resolved "https://registry.yarnpkg.com/@types/next/-/next-8.0.6.tgz#e4ceb01069b82bfe20d98bb3ba2cb65eb5c77bdd"
integrity sha512-NEPE5PpZ0atyX08I5B06A94OaygoZkLyv4zsZ9OkxbaCe9tIbIYzNWIievY36zXtOFL44JS/MArUuVdAUK9kCQ==
dependencies:
"@types/next-server" "*"
"@types/node" "*"
"@types/node-fetch" "*"
"@types/react" "*"
"@types/node-fetch@*", "@types/node-fetch@^2.1.6", "@types/node-fetch@^2.3.0":
"@types/node-fetch@^2.1.6", "@types/node-fetch@^2.3.0":
version "2.3.7"
resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.3.7.tgz#b7212e895100f8642dbdab698472bab5f3c1d2f1"
integrity sha512-+bKtuxhj/TYSSP1r4CZhfmyA0vm/aDRQNo7vbAgf6/cZajn0SAniGGST07yvI4Q+q169WTa2/x9gEHfJrkcALw==
@@ -1427,7 +1411,7 @@
"@types/prop-types" "*"
csstype "^2.2.0"
"@types/resolve-from@^5.0.1":
"@types/resolve-from@5.0.1":
version "5.0.1"
resolved "https://registry.yarnpkg.com/@types/resolve-from/-/resolve-from-5.0.1.tgz#2714eaa840c0472dcfa96ec3fb9d170dbf0b677d"
integrity sha512-1G7n5Jtr5inoS1Ez2Y9Efedk9/wH6uGQslbfhGTOw9J42PCAwuyaDgQHW7fIq02+shwB02kM/w31W8gMxI8ORg==
@@ -1444,11 +1428,6 @@
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-6.0.0.tgz#86ba89f02a414e39c68d02b351872e4ed31bd773"
integrity sha512-OO0srjOGH99a4LUN2its3+r6CBYcplhJ466yLqs+zvAWgphCpS8hYZEZ797tRDP/QKcqTdb/YCN6ifASoAWkrQ==
"@types/semver@^6.0.0":
version "6.0.1"
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-6.0.1.tgz#a984b405c702fa5a7ec6abc56b37f2ba35ef5af6"
integrity sha512-ffCdcrEE5h8DqVxinQjo+2d1q+FV5z7iNtPofw3JsrltSoSVlOGaW0rY8XxtO9XukdTn8TaCGWmk2VFGhI70mg==
"@types/stack-utils@^1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e"
@@ -1482,9 +1461,9 @@
source-map "^0.6.1"
"@types/webpack@*":
version "4.4.35"
resolved "https://registry.yarnpkg.com/@types/webpack/-/webpack-4.4.35.tgz#b7088eb2d471d5645e5503d272783cafa753583b"
integrity sha512-kf+mn/+CB4HsFb+Rz0QBRlo8nNC9LFhwqeK5xxhd3FEPRWJv6MFVnljKV5ARac56+syO8vIhq+nGt860+3wx7A==
version "4.32.1"
resolved "https://registry.yarnpkg.com/@types/webpack/-/webpack-4.32.1.tgz#6e95010e806f808abd6551c112097ac09035aacf"
integrity sha512-9n38CBx9uga1FEAdTipnt0EkbKpsCJFh7xJb1LE65FFb/A6OOLFX022vYsGC1IyVCZ/GroNg9u/RMmlDxGcLIw==
dependencies:
"@types/anymatch" "*"
"@types/node" "*"
@@ -1520,10 +1499,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.1":
version "0.2.1"
resolved "https://registry.yarnpkg.com/@zeit/node-file-trace/-/node-file-trace-0.2.1.tgz#f16fec1da4fdb74fa8d44732e6d28c2532567562"
integrity sha512-1VBtDyl2SPqwr+upvx7fNaNmYwEETOFnMu0MfNH1U4mDLf6i9aR2ll5XNaB4h76J/ZP9GAFBEB/DoREmOPM4Rg==
"@zeit/node-file-trace@0.2.5":
version "0.2.5"
resolved "https://registry.yarnpkg.com/@zeit/node-file-trace/-/node-file-trace-0.2.5.tgz#be69738b89fa084dfc51454ec4e0089d25888ef6"
integrity sha512-K7BNYZg19PQFzA3CpaPvjCc/sE0vgUMsVn4f1LurDk/e9aizjmrZCKPQpsGhEhGGR/jtPPMqBLhWVQM3k/trKQ==
dependencies:
acorn "^6.1.1"
acorn-stage3 "^2.0.0"
@@ -3551,7 +3530,7 @@ get-pkg-repo@^1.0.0:
parse-github-repo-url "^1.3.0"
through2 "^2.0.0"
get-port@5.0.0, get-port@^5.0.0:
get-port@5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/get-port/-/get-port-5.0.0.tgz#aa22b6b86fd926dd7884de3e23332c9f70c031a6"
integrity sha512-imzMU0FjsZqNa6BqOjbbW6w5BivHIuQKopjpPqcnx0AVHJQKCxK1O+Ab3OrVXhrekqfVMjwA9ZYu062R+KcIsQ==
@@ -6670,7 +6649,7 @@ resolve-cwd@^2.0.0:
dependencies:
resolve-from "^3.0.0"
resolve-from@*, resolve-from@^5.0.0:
resolve-from@*, resolve-from@5.0.0, resolve-from@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69"
integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==