Compare commits

..

6 Commits

Author SHA1 Message Date
Steven
e083aa3750 Publish
- @now/node@0.8.1
2019-06-08 14:56:27 -04:00
Steven
941f675657 [now-node] Change helpers to opt-in (#591)
* [now-node] Change helpers to opt-in

* Fix tests

* Fix tests
2019-06-08 14:55:56 -04:00
Steven
6fad726abb Publish
- @now/build-utils@0.5.7
 - @now/node@0.8.0
2019-06-08 10:38:13 -04:00
Luc
dd22051d6b [now-node] Add tests for types exports (#590)
* helpers.test.js -> helpers.test.ts

* import NowRequest and NowResponse in test

* fix addHelpers return type

* add comments
2019-06-08 10:36:05 -04:00
Luc
7e86cb403f [now-node] Add Express-like API (#577)
* first iteration of express-like api for @now/node

* fix error when config is undefined

* add integration test for helpers

* add `res.status()` to helpers integration test

* fix error caused by config values being strings

* add helpers opt-out integration test

* add `helpers.js` to deployed files

* add boolean and number to config values types

* update config.helpers to work with boolean

* add unit tests

* fix type error in config type

* add unit test for req.body

* ignore errors not generated in helpers

* Update packages/now-node/test/fixtures/15-helpers/no-helpers/index.js

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

* update config type

* use ternary instead of filtering with `Boolean`

* add probe in 15-helpers

* add probe for ts function

* ncc `helpers.js`

* fix Config type

* fix @now/rust type issue

* add comment in build.sh

* test that content-type header is correctly added

* add missing tsconfig.json in fixtures

* add `body` to fix `Invalid JSON` errors

* Revert "add `body` to fix `Invalid JSON` errors"

This reverts commit 9b2ff55409501140f0d7411d121fc3a4dfd34ccc.

* make `helpers` false by default

* add method POST to probe for helpers

* Revert "make `helpers` false by default"

This reverts commit d029a432a0bf2463e1613e6cfd76929ce6e45073.

* replace POST requests by GET in probes

* remove unnecessary comments

* destructure in parseQuery

* keep @now/rust unchanged

* Request -> NowRequest and Response -> NowResponse

* improve config types

* add NowListener type

* export NowRequest and NowResponse

* generate `.d.ts` files

* add types to helpers/ts fixtures

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

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

* Update packages/now-node/build.sh

Co-Authored-By: Steven <steven@ceriously.com>
2019-06-08 10:35:45 -04:00
Nathan Rajlich
d19d557738 [now-node] Add watch array for Builder v2 API (#582)
* [now-node] Add `watch` array

For `now dev`

* Use ncc-watcher from npm registry

* Update `yarn.lock`

* Fix integration tests

* Apply @styfle's suggestions

* Update `@zeit/ncc-watcher` to v1.0.3
2019-06-08 10:35:23 -04:00
19 changed files with 710 additions and 36 deletions

View File

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

View File

@@ -16,7 +16,14 @@ export interface Files {
}
export interface Config {
[key: string]: string;
[key: string]: string | string[] | boolean | number | undefined;
maxLambdaSize?: string;
includeFiles?: string | string[];
bundle?: boolean;
ldsflags?: string;
helpers?: boolean;
rust?: string;
debug?: boolean;
}
export interface Meta {

View File

@@ -1,2 +1,3 @@
/dist
/src/bridge.d.ts
/test/fixtures/**/types.d.ts

View File

@@ -0,0 +1,45 @@
declare function ncc(
entrypoint: string,
options?: ncc.NccOptions
): ncc.NccResult;
declare namespace ncc {
export interface NccOptions {
watch?: any;
sourceMap?: boolean;
sourceMapRegister?: boolean;
}
export interface Asset {
source: Buffer;
permissions: number;
}
export interface Assets {
[name: string]: Asset;
}
export interface BuildResult {
err: Error | null | undefined;
code: string;
map: string | undefined;
assets: Assets | undefined;
permissions: number | undefined;
}
export type HandlerFn = (params: BuildResult) => void;
export type HandlerCallback = (fn: HandlerFn) => void;
export type RebuildFn = () => void;
export type RebuildCallback = (fn: RebuildFn) => void;
export type CloseCallback = () => void;
export interface NccResult {
handler: HandlerCallback;
rebuild: RebuildCallback;
close: CloseCallback;
}
}
declare module '@zeit/ncc' {
export = ncc;
}

View File

@@ -10,3 +10,13 @@ fi
cp -v "$bridge_defs" src
tsc
# bundle helpers.ts with ncc
rm dist/helpers.js
ncc build src/helpers.ts -o dist/helpers
mv dist/helpers/index.js dist/helpers.js
rm -rf dist/helpers
# todo: improve
# copy type file for ts test
cp dist/types.d.ts test/fixtures/15-helpers/ts/types.d.ts

View File

@@ -0,0 +1,4 @@
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
};

View File

@@ -1,6 +1,6 @@
{
"name": "@now/node",
"version": "0.7.4",
"version": "0.8.1",
"license": "MIT",
"main": "./dist/index",
"repository": {
@@ -11,6 +11,7 @@
"dependencies": {
"@now/node-bridge": "^1.1.4",
"@zeit/ncc": "0.18.5",
"@zeit/ncc-watcher": "1.0.3",
"fs-extra": "7.0.1"
},
"scripts": {
@@ -22,8 +23,18 @@
"dist"
],
"devDependencies": {
"@types/content-type": "1.1.3",
"@types/cookie": "0.3.3",
"@types/jest": "24.0.13",
"@types/node": "11.9.4",
"@types/test-listen": "1.1.0",
"content-type": "1.0.4",
"cookie": "0.4.0",
"jest": "24.1.0",
"node-fetch": "2.6.0",
"raw-body": "2.4.0",
"test-listen": "1.1.0",
"ts-jest": "24.0.2",
"typescript": "3.3.3"
}
}

View File

@@ -0,0 +1,152 @@
import { parse as parseCookies } from 'cookie';
import { Stream } from 'stream';
import getRawBody from 'raw-body';
import { URL } from 'url';
import { parse as parseCT } from 'content-type';
import { RequestListener } from 'http';
import { NowRequest, NowResponse } from './types';
type NowListener = (req: NowRequest, res: NowResponse) => void | Promise<void>;
async function parseBody(req: NowRequest, limit: string = '1mb') {
const contentType = parseCT(req.headers['content-type'] || 'text/plain');
const { type, parameters } = contentType;
const encoding = parameters.charset || 'utf-8';
let buffer;
try {
buffer = await getRawBody(req, { encoding, limit });
} catch (e) {
if (e.type === 'entity.too.large') {
throw new ApiError(413, `Body exceeded ${limit} limit`);
} else {
throw new ApiError(400, 'Invalid body');
}
}
const body = buffer.toString();
if (type === 'application/json' || type === 'application/ld+json') {
return parseJson(body);
} else if (type === 'application/x-www-form-urlencoded') {
const qs = require('querystring');
return qs.decode(body);
} else {
return body;
}
}
// Parse `JSON` and handles invalid `JSON` strings
function parseJson(str: string) {
try {
return JSON.parse(str);
} catch (e) {
throw new ApiError(400, 'Invalid JSON');
}
}
function parseQuery({ url = '/' }: NowRequest) {
// we provide a placeholder base url because we only want searchParams
const params = new URL(url, 'https://n').searchParams;
const obj: { [key: string]: string | string[] } = {};
for (const [key, value] of params) {
obj[key] = value;
}
return obj;
}
function sendStatusCode(res: NowResponse, statusCode: number) {
res.statusCode = statusCode;
return res;
}
function sendData(res: NowResponse, body: any) {
if (body === null) {
res.end();
return;
}
const contentType = res.getHeader('Content-Type');
if (Buffer.isBuffer(body)) {
if (!contentType) {
res.setHeader('Content-Type', 'application/octet-stream');
}
res.setHeader('Content-Length', body.length);
res.end(body);
return;
}
if (body instanceof Stream) {
if (!contentType) {
res.setHeader('Content-Type', 'application/octet-stream');
}
body.pipe(res);
return;
}
let str = body;
// Stringify JSON body
if (typeof body === 'object' || typeof body === 'number') {
str = JSON.stringify(body);
res.setHeader('Content-Type', 'application/json; charset=utf-8');
}
res.setHeader('Content-Length', Buffer.byteLength(str));
res.end(str);
}
function sendJson(res: NowResponse, jsonBody: any): void {
// Set header to application/json
res.setHeader('Content-Type', 'application/json; charset=utf-8');
// Use send to handle request
res.send(jsonBody);
}
export class ApiError extends Error {
readonly statusCode: number;
constructor(statusCode: number, message: string) {
super(message);
this.statusCode = statusCode;
}
}
export function sendError(
res: NowResponse,
statusCode: number,
message: string
) {
res.statusCode = statusCode;
res.statusMessage = message;
res.end();
}
export function addHelpers(listener: NowListener): RequestListener {
return async function(_req, _res) {
const req = _req as NowRequest;
const res = _res as NowResponse;
try {
req.cookies = parseCookies(req.headers.cookie || '');
req.query = parseQuery(req);
req.body = await parseBody(req);
res.status = statusCode => sendStatusCode(res, statusCode);
res.send = data => sendData(res, data);
res.json = data => sendJson(res, data);
listener(req, res);
} catch (err) {
if (err instanceof ApiError) {
sendError(res, err.statusCode, err.message);
} else {
throw err;
}
}
};
}

View File

@@ -1,5 +1,7 @@
import { join, dirname, sep } from 'path';
import { readFile } from 'fs-extra';
import { Assets, NccOptions } from '@zeit/ncc';
import { join, dirname, relative, sep } from 'path';
import { NccWatcher, WatcherResult } from '@zeit/ncc-watcher';
import {
glob,
download,
@@ -14,6 +16,7 @@ import {
BuildOptions,
shouldServe,
} from '@now/build-utils';
export { NowRequest, NowResponse } from './types';
interface CompilerConfig {
includeFiles?: string | string[];
@@ -23,10 +26,28 @@ interface DownloadOptions {
files: Files;
entrypoint: string;
workPath: string;
meta?: Meta;
meta: Meta;
npmArguments?: string[];
}
const watchers: Map<string, NccWatcher> = new Map();
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;
}
function toBuffer(data: string | Buffer): Buffer {
if (typeof data === 'string') {
return Buffer.from(data, 'utf8');
}
return data;
}
async function downloadInstallAndBundle({
files,
entrypoint,
@@ -46,18 +67,51 @@ async function downloadInstallAndBundle({
}
async function compile(
workPath: string,
entrypointPath: string,
entrypoint: string,
config: CompilerConfig
): Promise<Files> {
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 ncc = require('@zeit/ncc');
const { code, map, assets } = await ncc(input, {
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));
} else {
const ncc = require('@zeit/ncc');
const result = await ncc(input, {
sourceMap: true,
sourceMapRegister: true,
});
code = result.code;
map = result.map;
assets = result.assets;
}
if (!assets) assets = {};
if (config && config.includeFiles) {
const includeFiles =
@@ -81,7 +135,7 @@ async function compile(
}
assets[fullPath] = {
source: data,
source: toBuffer(data),
permissions: mode,
};
}
@@ -89,11 +143,15 @@ async function compile(
}
const preparedFiles: Files = {};
// move all user code to 'user' subdirectory
preparedFiles[entrypoint] = new FileBlob({ data: code });
preparedFiles[`${entrypoint.replace('.ts', '.js')}.map`] = new FileBlob({
data: map,
});
if (map) {
preparedFiles[`${entrypoint.replace('.ts', '.js')}.map`] = new FileBlob({
data: toBuffer(map),
});
}
// 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];
@@ -101,9 +159,11 @@ async function compile(
preparedFiles[join(dirname(entrypoint), assetName)] = blob2;
}
return preparedFiles;
return { preparedFiles, watch };
}
export const version = 2;
export const config = {
maxLambdaSize: '5mb',
};
@@ -113,8 +173,10 @@ export async function build({
entrypoint,
workPath,
config,
meta,
meta = {},
}: BuildOptions) {
const shouldAddHelpers = config && config.helpers;
const {
entrypointPath,
entrypointFsDirname,
@@ -130,7 +192,13 @@ export async function build({
await runPackageJsonScript(entrypointFsDirname, 'now-build');
console.log('compiling entrypoint with ncc...');
const preparedFiles = await compile(entrypointPath, entrypoint, config);
const { preparedFiles, watch } = await compile(
workPath,
entrypointPath,
entrypoint,
config,
meta
);
const launcherPath = join(__dirname, 'launcher.js');
let launcherData = await readFile(launcherPath, 'utf8');
@@ -139,21 +207,32 @@ export async function build({
[
`listener = require("./${entrypoint}");`,
'if (listener.default) listener = listener.default;',
shouldAddHelpers
? 'listener = require("./helpers").addHelpers(listener)'
: '',
].join(' ')
);
const launcherFiles = {
const launcherFiles: Files = {
'launcher.js': new FileBlob({ data: launcherData }),
'bridge.js': new FileFsRef({ fsPath: require('@now/node-bridge') }),
};
if (shouldAddHelpers) {
launcherFiles['helpers.js'] = new FileFsRef({
fsPath: join(__dirname, 'helpers.js'),
});
}
const lambda = await createLambda({
files: { ...preparedFiles, ...launcherFiles },
handler: 'launcher.launcher',
runtime: 'nodejs8.10',
});
return { [entrypoint]: lambda };
const output = { [entrypoint]: lambda };
const result = { output, watch };
return result;
}
export async function prepareCache({ workPath }: PrepareCacheOptions) {

View File

@@ -0,0 +1,13 @@
import { ServerResponse, IncomingMessage } from 'http';
export type NowRequest = IncomingMessage & {
query: { [key: string]: string | string[] };
cookies: { [key: string]: string };
body: any;
};
export type NowResponse = ServerResponse & {
send: (body: any) => void;
json: (body: any) => void;
status: (statusCode: number) => void;
};

View File

@@ -0,0 +1,17 @@
/* eslint-disable prefer-destructuring */
module.exports = (req, res) => {
res.status(200);
let who = 'anonymous';
if (req.body && req.body.who) {
who = req.body.who;
} else if (req.query.who) {
who = req.query.who;
} else if (req.cookies.who) {
who = req.cookies.who;
}
res.send(`hello ${who}:RANDOMNESS_PLACEHOLDER`);
};

View File

@@ -0,0 +1,5 @@
module.exports = (req, res) => {
const areHelpersAvailable = typeof req.query !== 'undefined';
res.end(`${areHelpersAvailable ? 'yes' : 'no'}:RANDOMNESS_PLACEHOLDER`);
};

View File

@@ -0,0 +1,37 @@
{
"version": 2,
"builds": [
{ "src": "index.js", "use": "@now/node", "config": { "helpers": true } },
{ "src": "ts/index.ts", "use": "@now/node", "config": { "helpers": true } },
{ "src": "no-helpers/index.js", "use": "@now/node" }
],
"probes": [
{
"path": "/",
"mustContain": "hello anonymous:RANDOMNESS_PLACEHOLDER"
},
{
"path": "/ts",
"mustContain": "hello:RANDOMNESS_PLACEHOLDER"
},
{
"path": "/?who=bill",
"mustContain": "hello bill:RANDOMNESS_PLACEHOLDER"
},
{
"path": "/",
"method": "POST",
"body": { "who": "john" },
"mustContain": "hello john:RANDOMNESS_PLACEHOLDER"
},
{
"path": "/",
"headers": { "cookie": "who=chris" },
"mustContain": "hello chris:RANDOMNESS_PLACEHOLDER"
},
{
"path": "/no-helpers/",
"mustContain": "no:RANDOMNESS_PLACEHOLDER"
}
]
}

View File

@@ -0,0 +1,6 @@
import { NowRequest, NowResponse } from './types';
export default function listener(req: NowRequest, res: NowResponse) {
res.status(200);
res.send('hello:RANDOMNESS_PLACEHOLDER');
}

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,127 @@
/* global beforeAll, beforeEach, afterAll, expect, it, jest */
import fetch from 'node-fetch';
import { createServer, Server } from 'http';
import listen from 'test-listen';
import { mocked } from 'ts-jest/utils';
// we intentionally import these types from src/index
// to test that they are exported
import { NowRequest, NowResponse } from '../src/index';
import { addHelpers } from '../src/helpers';
const mockListener = mocked(
jest.fn((req: NowRequest, res: NowResponse): void => {})
);
const listener = addHelpers(mockListener);
let server: Server;
let url: string;
beforeAll(async () => {
server = createServer(listener);
url = await listen(server);
});
beforeEach(() => {
mockListener.mockReset();
});
afterAll(async () => {
await server.close();
});
it('req.query should reflect querystring in the url', async () => {
mockListener.mockImplementation((req, res) => {
res.send('hello');
});
await fetch(`${url}/?who=bill&where=us`);
expect(mockListener.mock.calls[0][0].query).toMatchObject({
who: 'bill',
where: 'us',
});
});
it('req.cookies should reflect req.cookie header', async () => {
mockListener.mockImplementation((req, res) => {
res.send('hello');
});
await fetch(url, {
headers: {
cookie: 'who=bill; where=us',
},
});
expect(mockListener.mock.calls[0][0].cookies).toMatchObject({
who: 'bill',
where: 'us',
});
});
it('req.body should contained the parsed body', async () => {
mockListener.mockImplementation((req, res) => {
res.send('hello');
});
await fetch(url, {
method: 'POST',
body: 'hello',
});
expect(mockListener.mock.calls[0][0].body).toBe('hello');
});
it('req.body should contained the parsed json when content-type is application/json', async () => {
mockListener.mockImplementation((req, res) => {
res.send('hello');
});
const json = {
who: 'bill',
where: 'us',
};
await fetch(url, {
method: 'POST',
body: JSON.stringify(json),
headers: { 'content-type': 'application/json' },
});
expect(mockListener.mock.calls[0][0].body).toMatchObject(json);
});
it('res.send() should send text', async () => {
mockListener.mockImplementation((req, res) => {
res.send('hello');
});
const res = await fetch(url);
expect(await res.text()).toBe('hello');
});
it('res.json() should send json', async () => {
mockListener.mockImplementation((req, res) => {
res.json({ who: 'bill' });
});
const res = await fetch(url);
const contentType = res.headers.get('content-type') || '';
expect(contentType.includes('application/json')).toBe(true);
expect(await res.json()).toMatchObject({ who: 'bill' });
});
it('res.status() should set the status code', async () => {
mockListener.mockImplementation((req, res) => {
res.status(404);
res.end();
});
const res = await fetch(url);
expect(res.status).toBe(404);
});

View File

@@ -7,7 +7,8 @@
"module": "commonjs",
"outDir": "dist",
"sourceMap": false,
"declaration": false
"declaration": true,
"typeRoots": ["./@types", "./node_modules/@types"]
},
"include": ["src/**/*"],
"exclude": ["node_modules"]

View File

@@ -12,7 +12,7 @@ it(
'Should build the airtable folder',
async () => {
const { buildResult } = await runBuildForFolder('airtable');
expect(buildResult['index.js']).toBeDefined();
expect(buildResult.output['index.js']).toBeDefined();
},
TWO_MINUTES,
);
@@ -21,7 +21,7 @@ it(
'Should build the aws-sdk folder',
async () => {
const { buildResult } = await runBuildForFolder('aws-sdk');
expect(buildResult['index.js']).toBeDefined();
expect(buildResult.output['index.js']).toBeDefined();
},
TWO_MINUTES,
);
@@ -30,7 +30,7 @@ it(
'Should build the axios folder',
async () => {
const { buildResult } = await runBuildForFolder('axios');
expect(buildResult['index.js']).toBeDefined();
expect(buildResult.output['index.js']).toBeDefined();
},
TWO_MINUTES,
);
@@ -39,7 +39,7 @@ it(
'Should build the mongoose folder',
async () => {
const { buildResult } = await runBuildForFolder('mongoose');
expect(buildResult['index.js']).toBeDefined();
expect(buildResult.output['index.js']).toBeDefined();
},
TWO_MINUTES,
);

170
yarn.lock
View File

@@ -940,6 +940,16 @@
dependencies:
"@babel/types" "^7.3.0"
"@types/content-type@1.1.3":
version "1.1.3"
resolved "https://registry.yarnpkg.com/@types/content-type/-/content-type-1.1.3.tgz#3688bd77fc12f935548eef102a4e34c512b03a07"
integrity sha512-pv8VcFrZ3fN93L4rTNIbbUzdkzjEyVMp5mPVjsFfOYTDOZMZiZ8P1dhu+kEv3faYyKzZgLlSvnyQNFg+p/v5ug==
"@types/cookie@0.3.3":
version "0.3.3"
resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.3.3.tgz#85bc74ba782fb7aa3a514d11767832b0e3bc6803"
integrity sha512-LKVP3cgXBT9RYj+t+9FDKwS5tdI+rPBXaNSkma7hvqy35lc7mAokC2zsqWJH0LaqIt3B962nuYI77hsJoT1gow==
"@types/cross-spawn@6.0.0":
version "6.0.0"
resolved "https://registry.yarnpkg.com/@types/cross-spawn/-/cross-spawn-6.0.0.tgz#320aaf1d1a12979f1b84fe7a5590a7e860bf3a80"
@@ -1006,6 +1016,18 @@
resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.0.tgz#1eb8c033e98cf4e1a4cedcaf8bcafe8cb7591e85"
integrity sha512-eAtOAFZefEnfJiRFQBGw1eYqa5GTLCZ1y86N0XSI/D6EB+E8z6VPV/UL7Gi5UEclFqoQk+6NRqEDsfmDLXn8sg==
"@types/jest-diff@*":
version "20.0.1"
resolved "https://registry.yarnpkg.com/@types/jest-diff/-/jest-diff-20.0.1.tgz#35cc15b9c4f30a18ef21852e255fdb02f6d59b89"
integrity sha512-yALhelO3i0hqZwhjtcr6dYyaLoCHbAMshwtj6cGxTvHZAKXHsYGdff6E8EPw3xLKY0ELUTQ69Q1rQiJENnccMA==
"@types/jest@24.0.13":
version "24.0.13"
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-24.0.13.tgz#10f50b64cb05fb02411fbba49e9042a3a11da3f9"
integrity sha512-3m6RPnO35r7Dg+uMLj1+xfZaOgIHHHut61djNjzwExXN4/Pm9has9C6I1KMYSfz7mahDhWUOVg4HW/nZdv5Pww==
dependencies:
"@types/jest-diff" "*"
"@types/minimatch@*":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
@@ -1101,6 +1123,13 @@
dependencies:
"@types/node" "*"
"@types/test-listen@1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@types/test-listen/-/test-listen-1.1.0.tgz#db7e5b0e277b4a3ee7b90770dae1a41b186458af"
integrity sha512-y6ZfbSzYHniCeY6ZAzsQjSAdJInNVoEz4Uhsb81W+RCoNYA59yoG/+XbqPqCPj2KCU3Wa6RFWSozutkGIHIsNQ==
dependencies:
"@types/node" "*"
"@types/uglify-js@*":
version "3.0.4"
resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-3.0.4.tgz#96beae23df6f561862a830b4288a49e86baac082"
@@ -1158,7 +1187,14 @@
globby "8.0.0"
signal-exit "3.0.2"
"@zeit/ncc@0.18.5":
"@zeit/ncc-watcher@1.0.3":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@zeit/ncc-watcher/-/ncc-watcher-1.0.3.tgz#c4569d13db7b80a96a7672047c069400e69913ae"
integrity sha512-367wm9bGMBCwT8kHQckw8UY/iYhC9rdzj357FBoM0SjVvWv53yziEmd12RkeF1EsBs0F2a1uBYdUaUvGo6LfkA==
dependencies:
"@zeit/ncc" "^0.18.5"
"@zeit/ncc@0.18.5", "@zeit/ncc@^0.18.5":
version "0.18.5"
resolved "https://registry.yarnpkg.com/@zeit/ncc/-/ncc-0.18.5.tgz#5687df6c32f1a2e2486aa110b3454ccebda4fb9c"
integrity sha512-F+SbvEAh8rchiRXqQbmD1UmbePY7dCOKTbvfFtbVbK2xMH/tyri5YKfNxXKK7eL9EWkkbqB3NTVQO6nokApeBA==
@@ -1891,6 +1927,13 @@ browser-resolve@^1.11.3:
dependencies:
resolve "1.1.7"
bs-logger@0.x:
version "0.2.6"
resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8"
integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==
dependencies:
fast-json-stable-stringify "2.x"
bser@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/bser/-/bser-2.0.0.tgz#9ac78d3ed5d915804fd87acb158bc797147a1719"
@@ -1921,7 +1964,7 @@ buffer-fill@^1.0.0:
resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c"
integrity sha1-+PeLdniYiO858gXNY39o5wISKyw=
buffer-from@^1.0.0:
buffer-from@1.x, buffer-from@^1.0.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
@@ -1961,6 +2004,11 @@ byte-size@^4.0.3:
resolved "https://registry.yarnpkg.com/byte-size/-/byte-size-4.0.4.tgz#29d381709f41aae0d89c631f1c81aec88cd40b23"
integrity sha512-82RPeneC6nqCdSwCX2hZUz3JPOvN5at/nTEw/CMf05Smu3Hrpo9Psb7LjN+k+XndNArG1EY8L4+BM3aTM4BCvw==
bytes@3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6"
integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==
cacache@^11.0.1, cacache@^11.2.0:
version "11.3.1"
resolved "https://registry.yarnpkg.com/cacache/-/cacache-11.3.1.tgz#d09d25f6c4aca7a6d305d141ae332613aa1d515f"
@@ -2424,6 +2472,11 @@ contains-path@^0.1.0:
resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a"
integrity sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=
content-type@1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
conventional-changelog-angular@^5.0.2:
version "5.0.2"
resolved "https://registry.yarnpkg.com/conventional-changelog-angular/-/conventional-changelog-angular-5.0.2.tgz#39d945635e03b6d0c9d4078b1df74e06163dc66a"
@@ -2514,6 +2567,11 @@ convert-source-map@^1.1.0, convert-source-map@^1.1.1, convert-source-map@^1.4.0,
dependencies:
safe-buffer "~5.1.1"
cookie@0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba"
integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==
copy-concurrently@^1.0.0:
version "1.0.5"
resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0"
@@ -2864,6 +2922,11 @@ delegates@^1.0.0:
resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=
depd@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=
detab@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/detab/-/detab-2.0.1.tgz#531f5e326620e2fd4f03264a905fb3bcc8af4df4"
@@ -3512,7 +3575,7 @@ fast-glob@^2.0.2:
merge2 "^1.2.3"
micromatch "^3.1.10"
fast-json-stable-stringify@^2.0.0:
fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2"
integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I=
@@ -4387,6 +4450,17 @@ http-cache-semantics@^3.8.1:
resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2"
integrity sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==
http-errors@1.7.2:
version "1.7.2"
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f"
integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==
dependencies:
depd "~1.1.2"
inherits "2.0.3"
setprototypeof "1.1.1"
statuses ">= 1.5.0 < 2"
toidentifier "1.0.0"
http-proxy-agent@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405"
@@ -4504,7 +4578,7 @@ inflight@^1.0.4:
once "^1.3.0"
wrappy "1"
inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3:
inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
@@ -6261,18 +6335,18 @@ json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1:
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=
json5@^0.5.1:
version "0.5.1"
resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821"
integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=
json5@^2.1.0:
json5@2.x, json5@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.0.tgz#e7a0c62c48285c628d20a10b85c89bb807c32850"
integrity sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ==
dependencies:
minimist "^1.2.0"
json5@^0.5.1:
version "0.5.1"
resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821"
integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=
jsonfile@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"
@@ -6753,6 +6827,11 @@ make-dir@^1.0.0, make-dir@^1.3.0:
dependencies:
pify "^3.0.0"
make-error@1.x:
version "1.3.5"
resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.5.tgz#efe4e81f6db28cadd605c70f29c831b58ef776c8"
integrity sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==
make-fetch-happen@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-4.0.1.tgz#141497cb878f243ba93136c83d8aba12c216c083"
@@ -7056,7 +7135,7 @@ mixin-deep@^1.2.0:
for-in "^1.0.2"
is-extendable "^1.0.1"
"mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0:
mkdirp@0.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0:
version "0.5.1"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=
@@ -8156,6 +8235,16 @@ randomatic@^3.0.0:
kind-of "^6.0.0"
math-random "^1.0.1"
raw-body@2.4.0:
version "2.4.0"
resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332"
integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==
dependencies:
bytes "3.1.0"
http-errors "1.7.2"
iconv-lite "0.4.24"
unpipe "1.0.0"
rc@^1.1.2, rc@^1.2.7:
version "1.2.8"
resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
@@ -8578,6 +8667,13 @@ resolve@1.1.7:
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=
resolve@1.x:
version "1.11.1"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.11.1.tgz#ea10d8110376982fef578df8fc30b9ac30a07a3e"
integrity sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw==
dependencies:
path-parse "^1.0.6"
resolve@^1.3.2:
version "1.10.0"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.10.0.tgz#3bdaaeaf45cc07f375656dfd2e54ed0810b101ba"
@@ -8768,6 +8864,11 @@ semver@^4.0.3:
resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.6.tgz#300bc6e0e86374f7ba61068b5b1ecd57fc6532da"
integrity sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=
semver@^5.5:
version "5.7.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b"
integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==
semver@~5.3.0:
version "5.3.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"
@@ -8803,6 +8904,11 @@ set-value@^2.0.0:
is-plain-object "^2.0.3"
split-string "^3.0.1"
setprototypeof@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683"
integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==
shebang-command@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
@@ -9106,6 +9212,11 @@ static-extend@^0.1.1:
define-property "^0.2.5"
object-copy "^0.1.0"
"statuses@>= 1.5.0 < 2":
version "1.5.0"
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=
stealthy-require@^1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b"
@@ -9457,6 +9568,11 @@ test-exclude@^5.0.0:
read-pkg-up "^4.0.0"
require-main-filename "^1.0.1"
test-listen@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/test-listen/-/test-listen-1.1.0.tgz#2ba614d96c3bc9157469003027b42a495dd83b6a"
integrity sha512-OyEVi981C1sb9NX1xayfgZls3p8QTDRwp06EcgxSgd1kktaENBW8dO15i8v/7Fi15j0IYQctJzk5J+hyEBId2w==
text-extensions@^1.0.0:
version "1.9.0"
resolved "https://registry.yarnpkg.com/text-extensions/-/text-extensions-1.9.0.tgz#1853e45fee39c945ce6f6c36b2d659b5aabc2a26"
@@ -9570,6 +9686,11 @@ to-regex@^3.0.1, to-regex@^3.0.2:
regex-not "^1.0.2"
safe-regex "^1.1.0"
toidentifier@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
tough-cookie@>=2.3.3, tough-cookie@^2.3.4:
version "2.5.0"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
@@ -9640,6 +9761,21 @@ trough@^1.0.0:
resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.3.tgz#e29bd1614c6458d44869fc28b255ab7857ef7c24"
integrity sha512-fwkLWH+DimvA4YCy+/nvJd61nWQQ2liO/nF/RjkTpiOGi+zxZzVkhb1mvbHIIW4b/8nDsYI8uTmAlc0nNkRMOw==
ts-jest@24.0.2:
version "24.0.2"
resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-24.0.2.tgz#8dde6cece97c31c03e80e474c749753ffd27194d"
integrity sha512-h6ZCZiA1EQgjczxq+uGLXQlNgeg02WWJBbeT8j6nyIBRQdglqbvzDoHahTEIiS6Eor6x8mK6PfZ7brQ9Q6tzHw==
dependencies:
bs-logger "0.x"
buffer-from "1.x"
fast-json-stable-stringify "2.x"
json5 "2.x"
make-error "1.x"
mkdirp "0.x"
resolve "1.x"
semver "^5.5"
yargs-parser "10.x"
tslib@^1.9.0:
version "1.9.3"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286"
@@ -9849,6 +9985,11 @@ universalify@^0.1.0:
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
unpipe@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=
unset-value@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559"
@@ -10261,6 +10402,13 @@ yallist@^3.0.0, yallist@^3.0.2:
resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9"
integrity sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==
yargs-parser@10.x:
version "10.1.0"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8"
integrity sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==
dependencies:
camelcase "^4.1.0"
yargs-parser@^11.1.1:
version "11.1.1"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-11.1.1.tgz#879a0865973bca9f6bab5cbdf3b1c67ec7d3bcf4"