Compare commits

..

32 Commits

Author SHA1 Message Date
Andy Bitz
4a6ddf8b1d Publish
- gatsby-plugin-now@1.2.1
 - @now/build-utils@0.10.0
 - @now/cgi@0.1.6
 - now@16.2.0
 - now-client@5.1.2
 - @now/go@0.5.12
 - @now/next@1.0.0
 - @now/node-bridge@1.2.5
 - @now/node@1.0.0
 - @now/python@0.2.18
 - @now/routing-utils@1.2.4
 - @now/ruby@0.1.6
 - @now/static-build@0.9.10
2019-09-05 18:25:48 +02:00
Andy Bitz
eeb1b2442c Revert "[now-cli] Implement now-client deployments in Now CLI (#2875)"
This reverts commit 129f234aaa.
2019-09-05 00:03:23 +02:00
Max
129f234aaa [now-cli] Implement now-client deployments in Now CLI (#2875)
* Imlement `now-client` deployments in Now CLI

* Move now-client to dev dependencies

* Fix missing config for legacy deployments

* Restore no files warning

* Improve error handling

* Port over `--prod`

* Handle single files and warnings better

* Fix legacy deployment env config

* Handle build errors in events

* Don't use ncc for now-client

* Extract `for...await` logic into a `.ts` file

* Revert "Don't use ncc for now-client"

This reverts commit e481a04058952f7011bf5523445256f1b8882dda.

* Add `typings` field to `now-client`

* Regenerate yarn.lock

* Add bootstrap step to CircleCI

* Add bootstrap step before build

* Revert "Add bootstrap step before build"

This reverts commit db9e1113937f113cca8c7c05d5c800fd5d61e84b.

* Revert "Add bootstrap step to CircleCI"

This reverts commit 02c0006a073614814fd174ccbaf1e4e0d8dd3dbf.

* Build `now-client` before CLI

* Sort build scripts

* Tweak empty deployment detection

* Add bootstrap step before build

* Remove now-client dependency from now-client

* Use local dependencies

* Fix paths and regenerate lockfile

* Bypass broken linting rule

* Remove lint ignore

* Use `tsc` instead of `ncc` for `now-client`

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

* Fix output path for tsc build

* [test] Supress TS warning

* Update packages/now-cli/src/commands/deploy/latest.js

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

* Update packages/now-cli/src/commands/deploy/latest.js

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

* Update packages/now-client/package.json

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

* Change `now-client` output to `dist`

* Implement file events in now-client and bring back progressbar

* Update build script sorting

* Add new logic tests for `now-client`

* Remove redundant target check

* Remove now-client dependency and use local code

* Set exact dependency versions

* Revert "Set exact dependency versions"

This reverts commit e0a31eaf10e498271c9253439d4bbd650738c694.

* Revert local now-client import

* Revert `now-client` dependency to local path

* Implement feedback

* Fix formatting

* Only handle alias errors if `readyState` is `READY`

* Update packages/now-cli/src/commands/deploy/latest.js

Co-Authored-By: Andy <AndyBitz@users.noreply.github.com>

* Update packages/now-cli/src/commands/deploy/latest.js

Co-Authored-By: Andy <AndyBitz@users.noreply.github.com>
2019-09-04 23:54:21 +02:00
Nathan Rajlich
331c352e2b [now-cli] Update pcre-to-regexp to v1.0.0 (#2932)
No improvements, per say, but the module has been converted to
TypeScript so it supplies its own type definitions now, and we
can delete our hand-crafted typings from this repo.
2019-09-04 23:46:31 +02:00
Nathan Rajlich
2ccbaea9dd [now-cli] Remove deprecated @now/php builder from bundled builders tarball (#2907)
`@now/php` has been deprecated in favor of community-maintained
`now-php`, so don't bundle the deprecated builder with Now CLI.
2019-09-04 23:45:44 +02:00
Sophearak Tha
069eca3c62 [now-cli] Remove annotate from now logs (#2937)
* Remove annotate from `now logs`

* Filter out runtime logs to be consistency with dashboard logs

* Add integration test
2019-09-04 23:44:13 +02:00
Nathan Rajlich
305e364f8b [now-cli] Output --json to stdout for now alias ls <url> (#2922)
Fixes #1337.
2019-09-04 23:41:27 +02:00
Nathan Rajlich
4068805ae0 [now-cli] Use xdg-app-paths for now dev cache dir (#2921)
* [now-cli] Use `xdg-app-paths` for `now dev` cache dir

For consistency, because #2877 uses this module.
No need for multiple modules that do the same thing.

* Update `@zeit/fun` to v0.9.3
2019-09-04 23:36:16 +02:00
Andy
9a1e7a4a7a [now-cli] Handle now certs ls for users and teams without certificates (#2945)
* [now-cli] Fix `now certs ls` when the user or team has no certs

* Add tests and move to typescript

* Move index and add to typescript

* Fix reduce function in ls

* Added linebreak

* Update packages/now-cli/src/commands/certs/add.ts

Co-Authored-By: Naoyuki Kanezawa <naoyuki.kanezawa@gmail.com>
2019-09-04 23:25:31 +02:00
Naoyuki Kanezawa
bbad3d1b96 Add the nameservers verification check and improve messages (#2943)
* add the nameservers verification check and improve messages

* fix verify message condition
2019-09-04 23:25:23 +02:00
Nathan Rajlich
c62116d9a4 [now-cli] Remove now update from --help output (#2951)
Fixes #2940.
2019-09-04 23:25:11 +02:00
Nathan Rajlich
c94086ff21 [now-cli] Remove scale subcommand from --help (#2923)
Fixes #1998.
2019-09-04 23:25:00 +02:00
Andy
e99caa7b97 Fix the prettier config (#2946)
* Fix the prettier config

* Try prettier
2019-09-04 23:24:52 +02:00
Andy
658b9e9007 [now-cli] Install dependencies before running now dev in tests (#2948)
* [now-cli] Install dependencies before running `now dev` in tests

* Check install exit code

* Add more logging

* Add more logging

* More logging

* Include yarn.lock file

* Add lock files to dev fixtures

* Ignore test

* Ignore another test

* Ignore another test

* Whitespace

* Install deps for unit tests

* Whitespace
2019-09-04 23:24:45 +02:00
Luc
3ef27ae45c [gatsby-plugin-now] Add new package w/support for Gatsby Redirects (#2897)
* add gatsby-plugin-now

* add test

* adjust with lerna

* fix test

* add tests to circleci

* add support for defaultRoutes functions

* add defaultRoutes to gatsby

* fix types

* add test case for gatsby redirects

* remove gatsby, react, react-dom from monorepo deps

* chmod +x build.sh

* add missing build script in fixtures

* do stuff during tests to avoid persistence issue

* move tests setup to build step

* copy gatsby plugin files in test case

* bring back ncc step

* prettier gatsby-plugin-now

* add missing semicolons

* remove eslint, prettier from plugin

* persist build step copied file

* fetch without following redirects

* add files in package.json

* remove force

* fix tests probes

* fetch location is not raw location

* fix test

* add readme

* fix type error

* adjust tests

* add support for `force`

* add tests for `force`

* adjust tests again

* gatsby-plugin-now@1.1.0

* `"` -> `'`

* tweak redirect names in test by precaution

* change file name and delete when consumed

* format files

* gatsby-plugin-now@1.2.0

* Apply suggestions from code review

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

* tests -> test

* add --verbose

* adjust circleci to persist fixtures

* trigger tests

* add repository and homepage in package.json

* glob files after `defaultRoute` invocation
2019-09-04 23:23:58 +02:00
Andy
e669cd1152 [now-node][now-next] Skip installing user dependencies for now dev (#2926)
* Skip installing user dependencies for `now dev`

* Update type

* Install dependecies for test

* Add comma-dangle for @now/next

* Revert "Add comma-dangle for @now/next"

This reverts commit 720d5630f309ec44eb65e280af29db5b14bd50eb.

* Add trailing commas

* Reset typescript update

* Add trailing commas

* Bump @zeit/node-file-trace

* Readd trailing comma

* Bump @zeit/node-file-trace in @now/node
2019-09-04 23:23:47 +02:00
Sophearak Tha
b22aa7c0cf [now-go] Add GO_BUILD_FLAGS support for go build custom flags (#2916)
* Add `GO_BUILD_FLAGS` support for go build custom flags

* Using string-argv package

* Simplify condition
2019-09-04 23:23:33 +02:00
Joe Haddad
582cbb61fb [now-next] Create default file with correct target (#2924) 2019-09-04 23:23:10 +02:00
Sophearak Tha
7f4197cf43 [now-node] Cleanup debug output (#2927)
* Ensure traced files have annotate present in all lines

* Remove traced file logs

* Remove `compiling es module file` log

* Cleanup debug output
2019-09-04 23:22:49 +02:00
JJ Kasper
30889db487 [now-next] Use patched version of yazl and trace API pages separate (#2919)
* Update to trace API files separately and use modified yazl

* Remove jszip dependency

* Pin yazl dependency and add types

* Update more types
2019-09-04 23:22:30 +02:00
Luc
2d08d5d23e [tests] Unify .editorconfig (#2920) 2019-09-04 23:22:16 +02:00
Luc
59e7367e03 [tests] Unify linting and autoformatting (#2914)
* add prettier and eslint on root

* remove eslint from now-cli

* adjust root package.json

* adjust eslintignore

* adjust now-cli rules

* remove @zeit/git-hooks in packages

* adjust now-client eslint config

* add lint-staged and hook on pre-commit

* add pre-commit script

* replace @zeit/git-hooks with husky

* remove unnecessary script

* fix eslint errors

* trigger tests

* fix fixable errors

* fix fixable errors (bis)

* revert two changes
2019-09-04 23:22:02 +02:00
Naoyuki Kanezawa
84af278e86 [tests] Remove fixtures files for integration tests (#2910) 2019-09-04 23:21:51 +02:00
JJ Kasper
67d9ee39e2 [now-next] Optimize lambda creation (#2892)
* Optimize zipping lambdas for now-next

* Update to use jszip to get around bug in yazl

* Add pseudo layer utils

* Apply suggestions from code review

Co-Authored-By: Joe Haddad <joe.haddad@zeit.co>

* Update sema concurrency from tests

* Update packages/now-next/src/index.ts

* Use custom types to fix broken @types package

* Add license header

* Revert "Use custom types to fix broken @types package"

This reverts commit 82441285155f6e0899c43dffdd5e000ecbd7b1b6.

* Fix CI Yarn installation

* TypeScript types should never be hoisted

* Fix all typechecking
2019-09-04 23:21:32 +02:00
Joe Haddad
6c67bb81f7 [now-next] Do not add initial files to lambda (#2894) 2019-09-04 23:21:03 +02:00
Steven
aba19701c0 [tests] Ignore fixtures in GitHub Languages & fix yarn.lock (#2890) 2019-09-04 23:20:47 +02:00
Sophearak Tha
bb79402999 [now-next] Use debug() from build-utils (#2881)
* [now-next] Use `debug()` from build-utils (#909)

* Use `debug()` from build-utils

* Revert back to warning output

* Remove unnecessary debug check
2019-09-04 23:20:37 +02:00
Sophearak Tha
420bc4b244 [now-go] Use debug() from build-utils (#2885)
* [now-go] Use `debug()` from build-utils (#923)

* Use `debug()` from build-utils

* Apply suggestions from code review

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

* Print errors

* Apply suggestions from code review

Co-Authored-By: Steven <steven@ceriously.com>
2019-09-04 23:20:27 +02:00
Sophearak Tha
323c3d74cb [now-ruby] Use debug() from build-utils (#2883) 2019-09-04 23:20:20 +02:00
Sophearak Tha
4ecec8a8f6 [now-node] Use debug() from build-utils (#2880)
* Use `debug()` from build-utils

* Remove condition
2019-09-04 23:20:13 +02:00
Sophearak Tha
98883f9978 [now-static-build] Use debug() from build-utils (#2884) 2019-09-04 23:20:04 +02:00
Sophearak Tha
37cf3be437 [now-python] Use debug() from build-utils (#2882)
* Use `debug()` from build-utils

* Apply suggestions from code review

Co-Authored-By: Steven <steven@ceriously.com>
2019-09-04 23:19:45 +02:00
174 changed files with 125065 additions and 1752 deletions

View File

@@ -1,6 +1,5 @@
version: 2
jobs:
install:
docker:
- image: circleci/node:10
@@ -11,9 +10,9 @@ jobs:
- checkout
- restore_cache:
keys:
- v1-dependencies-{{ checksum "yarn.lock" }}
# fallback to using the latest cache if no exact match is found
- v1-dependencies-
- v1-dependencies-{{ checksum "yarn.lock" }}
# fallback to using the latest cache if no exact match is found
- v1-dependencies-
- run:
name: Updating apt packages
command: sudo apt-get update
@@ -22,10 +21,11 @@ jobs:
command: sudo apt-get install golang-go
- run:
name: Installing Dependencies
command: yarn install
command: yarn install --check-files --frozen-lockfile
- save_cache:
paths:
- node_modules
- packages/gatsby-plugin-now/node_modules
- packages/now-build-utils/node_modules
- packages/now-cgi/node_modules
- packages/now-cli/node_modules
@@ -43,6 +43,7 @@ jobs:
root: .
paths:
- node_modules
- packages/gatsby-plugin-now/node_modules
- packages/now-build-utils/node_modules
- packages/now-cgi/node_modules
- packages/now-cli/node_modules
@@ -75,6 +76,7 @@ jobs:
- persist_to_workspace:
root: .
paths:
- packages/gatsby-plugin-now/test/fixtures
- packages/now-build-utils/dist
- packages/now-cgi/dist
- packages/now-cli/dist
@@ -91,6 +93,7 @@ jobs:
- packages/now-routing-utils/dist
- packages/now-ruby/dist
- packages/now-static-build/dist
- packages/now-static-build/test/fixtures/10a-gatsby-redirects/plugins
test-lint:
docker:

32
.eslintignore Normal file
View File

@@ -0,0 +1,32 @@
node_modules
dist
# gatsby-plugin-now
packages/gatsby-plugin-now/test/fixtures
# now-cli
packages/now-cli/@types
packages/now-cli/download
packages/now-cli/dist
packages/now-cli/test/fixtures
packages/now-cli/test/dev/fixtures
packages/now-cli/bin
packages/now-cli/link
packages/now-cli/src/util/dev/templates/*.ts
# now-client
packages/now-client/tests/fixtures
packages/now-client/lib
# now-next
packages/now-next/test/fixtures
# now-node
packages/now-node/src/bridge.ts
packages/now-node/test/fixtures
# now-node-bridge
packages/now-node-bridge/bridge.*
# now-static-build
packages/now-static-build/test/fixtures

64
.eslintrc.json Normal file
View File

@@ -0,0 +1,64 @@
{
"root": true,
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 2018,
"sourceType": "module",
"modules": true
},
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"prettier",
"prettier/@typescript-eslint"
],
"env": {
"node": true,
"jest": true,
"es6": true
},
"rules": {
"require-atomic-updates": 0,
"@typescript-eslint/ban-ts-ignore": 0,
"@typescript-eslint/camelcase": 0,
"@typescript-eslint/explicit-function-return-type": 0,
"@typescript-eslint/no-empty-function": 0,
"@typescript-eslint/no-use-before-define": 0
},
"overrides": [
{
"files": ["**/*.js"],
"rules": {
"@typescript-eslint/no-var-requires": "off"
}
},
{
"files": ["packages/now-cli/**/*"],
"rules": {
"lines-between-class-members": 0,
"no-async-promise-executor": 0,
"no-control-regex": 0,
"no-empty": 0,
"prefer-const": 0,
"prefer-destructuring": 0,
"@typescript-eslint/ban-types": 0,
"@typescript-eslint/consistent-type-assertions": 0,
"@typescript-eslint/member-delimiter-style": 0,
"@typescript-eslint/no-empty-function": 0,
"@typescript-eslint/no-explicit-any": 0,
"@typescript-eslint/no-inferrable-types": 0,
"@typescript-eslint/no-var-requires": 0
}
},
{
"files": ["packages/now-client/**/*"],
"rules": {
"prefer-const": 0,
"require-atomic-updates": 0,
"@typescript-eslint/ban-ts-ignore": 0,
"@typescript-eslint/no-explicit-any": 0
}
}
]
}

3
.gitattributes vendored Normal file
View File

@@ -0,0 +1,3 @@
# Ignore test fixtures in GitHub Languages
# See https://github.com/github/linguist#vendored-code
packages/*/test/* linguist-vendored

View File

@@ -24,7 +24,7 @@ jobs:
with:
node-version: ${{ matrix.node-version }}
- name: Install
run: yarn install --pure-lockfile
run: yarn install --check-files --frozen-lockfile
- name: Build
run: yarn build
- name: Publish

2
.gitignore vendored
View File

@@ -12,7 +12,9 @@ packages/now-cli/.builders
packages/now-cli/assets
packages/now-cli/src/util/dev/templates/*.ts
packages/now-cli/test/**/yarn.lock
!packages/now-cli/test/dev/**/yarn.lock
packages/now-cli/test/**/node_modules
packages/now-cli/test/dev/fixtures/08-hugo/hugo
packages/now-cli/test/dev/fixtures/**/dist
packages/now-cli/test/dev/fixtures/**/public
packages/now-cli/test/fixtures/integration

4
.prettierrc Normal file
View File

@@ -0,0 +1,4 @@
{
"singleQuote": true,
"trailingComma": "es5"
}

View File

@@ -1,32 +1,60 @@
{
"name": "now-builders",
"version": "0.0.0",
"private": true,
"license": "MIT",
"workspaces": [
"packages/*"
],
"dependencies": {
"lerna": "3.16.4"
},
"devDependencies": {
"@zeit/ncc": "0.20.4",
"async-retry": "1.2.3",
"buffer-replace": "1.0.0",
"node-fetch": "2.6.0"
},
"scripts": {
"lerna": "lerna",
"bootstrap": "lerna bootstrap",
"publish-stable": "git checkout master && git pull && lerna version --exact",
"publish-canary": "git checkout canary && git pull && lerna version prerelease --preid canary --exact",
"publish-from-github": "./.circleci/publish.sh",
"build": "node run.js build all",
"test-lint": "node run.js test-lint",
"test-unit": "node run.js test-unit",
"test-integration": "node run.js test-integration",
"test-integration-once": "node run.js test-integration-once",
"test-integration-now-dev": "node run.js test-integration-now-dev"
"name": "now-builders",
"version": "0.0.0",
"private": true,
"license": "MIT",
"workspaces": {
"packages": [
"packages/*"
],
"nohoist": [
"**/@types/**"
]
},
"dependencies": {
"lerna": "3.16.4"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "2.0.0",
"@typescript-eslint/parser": "2.0.0",
"@zeit/ncc": "0.20.4",
"async-retry": "1.2.3",
"buffer-replace": "1.0.0",
"eslint": "6.2.2",
"eslint-config-prettier": "6.1.0",
"husky": "3.0.4",
"lint-staged": "9.2.5",
"node-fetch": "2.6.0",
"prettier": "1.18.2"
},
"scripts": {
"lerna": "lerna",
"bootstrap": "lerna bootstrap",
"publish-stable": "git checkout master && git pull && lerna version --exact",
"publish-canary": "git checkout canary && git pull && lerna version prerelease --preid canary --exact",
"publish-from-github": "./.circleci/publish.sh",
"build": "node run.js build all",
"test-lint": "node run.js test-lint",
"test-unit": "node run.js test-unit",
"test-integration": "node run.js test-integration",
"test-integration-once": "node run.js test-integration-once",
"test-integration-now-dev": "node run.js test-integration-now-dev",
"lint": "eslint . --ext .ts,.js"
},
"lint-staged": {
"*.{js,ts}": [
"prettier --write",
"eslint",
"git add"
],
"*.{json,md}": [
"prettier --write",
"git add"
]
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
}
}

View File

@@ -0,0 +1,6 @@
#!/bin/bash
set -euo pipefail
# build fixtures for tests
yarn --cwd test/fixtures install
yarn --cwd test/fixtures run build

View File

@@ -0,0 +1,33 @@
const path = require('path');
const writeFile = require('util').promisify(require('fs').writeFile);
const REDIRECT_FILE_NAME = '__now_routes_g4t5bY.json';
exports.onPostBuild = async ({ store }) => {
const { redirects, program } = store.getState();
if (!redirects.length === 0) {
return;
}
const routes = [{ handle: 'filesystem' }];
for (const redirect of redirects) {
const route = {
src: redirect.fromPath,
status: redirect.statusCode || (redirect.isPermanent ? 301 : 302),
headers: { Location: redirect.toPath }
};
if (redirect.force) {
routes.unshift(route);
} else {
routes.push(route);
}
}
await writeFile(
path.join(program.directory, 'public', REDIRECT_FILE_NAME),
JSON.stringify(routes)
);
};

View File

@@ -0,0 +1 @@
// noop

View File

@@ -0,0 +1,32 @@
{
"name": "gatsby-plugin-now",
"version": "1.2.1",
"main": "index.js",
"license": "MIT",
"homepage": "https://github.com/zeit/now/tree/canary/packages/gatsby-plugin-now",
"repository": {
"type": "git",
"url": "https://github.com/zeit/now.git",
"directory": "packages/gatsby-plugin-now"
},
"scripts": {
"build": "./build.sh",
"test-integration-once": "jest --verbose"
},
"files": [
"index.js",
"gatsby-node.js"
],
"peerDependencies": {
"gatsby": ">=2.0.0"
},
"devDependencies": {
"jest": "24.9.0"
},
"jest": {
"testPathIgnorePatterns": [
"/node_modules/",
"<rootDir>/test/fixtures/"
]
}
}

View File

@@ -0,0 +1,24 @@
# gatsby-plugin-now
This plugin generates [Now Routes](https://zeit.co/docs/v2/advanced/routes) for [redirects](https://www.gatsbyjs.org/docs/actions/#createRedirect) you configured for to your Gatsby project.
### Usage
1. Install the plugin:
```
npm install gatsby-plugin-now --save-dev
```
2. Add it to the configuration file:
```
// gatsby-config.js
module.exports = {
plugins: [
'gatsby-plugin-now'
]
}
```
3. [Deploy your project to ZEIT Now](https://www.gatsbyjs.org/docs/deploying-to-zeit-now/)

View File

@@ -0,0 +1,86 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`test generated now routes 1`] = `
Array [
Object {
"headers": Object {
"Location": "/",
},
"src": "/my-special-redirect",
"status": 302,
},
Object {
"handle": "filesystem",
},
Object {
"headers": Object {
"Location": "/page-2",
},
"src": "/page2",
"status": 301,
},
Object {
"headers": Object {
"Location": "/page-2/",
},
"src": "/page2/",
"status": 301,
},
Object {
"headers": Object {
"Location": "/",
},
"src": "/orange",
"status": 302,
},
Object {
"headers": Object {
"Location": "/",
},
"src": "/grape",
"status": 302,
},
Object {
"headers": Object {
"Location": "/page-2/",
},
"src": "/blue",
"status": 302,
},
Object {
"headers": Object {
"Location": "/page-2/",
},
"src": "/randirect",
"status": 302,
},
Object {
"headers": Object {
"Location": "/",
},
"src": "/juice",
"status": 302,
},
Object {
"headers": Object {
"Location": "/",
},
"src": "/soda",
"status": 302,
},
Object {
"headers": Object {
"Location": "/page-2/",
},
"src": "/donut",
"status": 302,
},
Object {
"headers": Object {
"Location": "/page-2/",
},
"src": "/randorect",
"status": 302,
},
]
`;

View File

@@ -0,0 +1,4 @@
public
node_modules
.cache
yarn.lock

View File

@@ -0,0 +1,3 @@
module.exports = {
plugins: [{ resolve: require.resolve('../../') }]
};

View File

@@ -0,0 +1,105 @@
'use strict';
// Implement the Gatsby API “createPages”. This is called once the
// data layer is bootstrapped to let plugins create pages from data.
exports.createPages = ({ actions }) => {
// need createRedirect action in actions collection
// to make the redirection magic happen.
// https://www.gatsbyjs.org/docs/bound-action-creators/
const { createRedirect } = actions;
// Lets set up some string consts to use thoroughout the following.
// MDN > JavaScript reference > Statements and declarations
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const
// Maybe we usually redirect to page 2, with trailing slash.
const page2Path = `/page-2/`;
// But sometimes to homepage.
const homePath = `/`;
// One-off redirect, note trailing slash missing on fromPath and
// toPath here.
createRedirect({
fromPath: `/page2`,
isPermanent: true,
redirectInBrowser: true,
toPath: `/page-2`
});
// Another one-off redirect, note trailing slash on toPath here.
// This time we want trailing slash on toPath so we use
// page2Path. Need to handle trailing-slashed and non-trailing-
// slashed fromPaths separately, Gatsby serves page components
// at either version by default, but we need to explicitly redirect
// both versions independently, more on page components:
// Docs > Building with Components
// https://www.gatsbyjs.org/docs/building-with-components/
// and handling trailing slashes:
// Docs > Creating and modifying pages > Removing trailing slashes
// https://www.gatsbyjs.org/docs/creating-and-modifying-pages/#removing-trailing-slashes
createRedirect({
fromPath: `/page2/`,
isPermanent: true,
redirectInBrowser: true,
toPath: page2Path
});
// One approach to handle several redirects at once is to create an
// array of from/to path pairs.
let redirectBatch1 = [
{ f: `/orange`, t: `/` },
// We could use homePath and page2Path directly here.
{ f: `/grape`, t: homePath },
{ f: `/blue`, t: page2Path },
// or leave to empty and swap for page2Path later on.
{ f: `/randirect`, t: `` }
];
// Then we can loop through the array of object literals to create
// each redirect. A for loop would do the trick
for (var { f: f, t: t } of redirectBatch1) {
// Here we swap any empty toPath values for trusty page 2 via
// page2Path.
if (t === ``) {
t = page2Path;
}
createRedirect({
fromPath: f,
redirectInBrowser: true,
toPath: t
});
// Uncomment next line to see loop in action during build
// console.log('\nRedirecting:\n' + f + '\nTo:\n' + t + '\n');
// or check .cache/redirects.json post-compile.
}
// A more modern approach might use forEach rather than for...of
// Compare
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Loops_and_iteration#for...of_statement
// and
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach
let redirectBatch2 = [
{ f: `/juice`, t: `/` },
{ f: `/soda`, t: `/` },
{ f: `/donut`, t: page2Path },
{ f: `/randorect`, t: `` }
];
redirectBatch2.forEach(({ f, t }) => {
if (t === ``) {
t = page2Path;
}
createRedirect({
fromPath: f,
redirectInBrowser: true,
toPath: t
});
// Uncomment next line to see forEach in action during build
// console.log('\nRedirecting:\n' + f + '\nTo:\n' + t + '\n');
});
createRedirect({
fromPath: '/my-special-redirect',
toPath: homePath,
force: true
});
};

View File

@@ -0,0 +1,11 @@
{
"name": "fixtures",
"dependencies": {
"gatsby": "2.14.0",
"react": "16.9.0",
"react-dom": "16.9.0"
},
"scripts": {
"build": "gatsby build"
}
}

View File

@@ -0,0 +1,9 @@
import React from 'react';
const IndexPage = () => (
<div>
<h1>Hi people</h1>
</div>
);
export default IndexPage;

View File

@@ -0,0 +1,5 @@
test('test generated now routes', async () => {
const nowRoutes = require('./fixtures/public/__now_routes_g4t5bY.json');
expect(nowRoutes).toMatchSnapshot();
});

View File

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

View File

@@ -10,20 +10,20 @@ interface Options {
tag?: 'canary' | 'latest' | string;
}
const src: string = 'package.json';
const src = 'package.json';
const config: Config = { zeroConfig: true };
const MISSING_BUILD_SCRIPT_ERROR: ErrorResponse = {
code: 'missing_build_script',
message:
'Your `package.json` file is missing a `build` property inside the `script` property.' +
'\nMore details: https://zeit.co/docs/v2/advanced/platform/frequently-asked-questions#missing-build-script',
'\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 }],
['next', { src, use: '@now/next', config }]
]);
}
@@ -35,7 +35,7 @@ function getApiBuilders(): Builder[] {
{ 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 },
{ src: 'api/**/*.rb', use: '@now/ruby', config }
];
}
@@ -96,8 +96,8 @@ async function detectApiBuilders(files: string[]): Promise<Builder[]> {
.sort(sortFiles)
.filter(ignoreApiFilter)
.map(file => {
const result = getApiBuilders().find(
({ src }): boolean => minimatch(file, src)
const result = getApiBuilders().find(({ src }): boolean =>
minimatch(file, src)
);
return result ? { ...result, src: file } : null;
@@ -138,7 +138,7 @@ export async function detectBuilders(
builders.push({
use: '@now/static',
src: 'public/**/*',
config,
config
});
} else if (builders.length > 0) {
// We can't use pattern matching, since `!(api)` and `!(api)/**/*`
@@ -150,7 +150,7 @@ export async function detectBuilders(
.map(name => ({
use: '@now/static',
src: name,
config,
config
}))
);
}
@@ -177,6 +177,6 @@ export async function detectBuilders(
return {
builders: builders.length ? builders : null,
errors: errors.length ? errors : null,
errors: errors.length ? errors : null
};
}

View File

@@ -43,37 +43,35 @@ function getSegmentName(segment: string): string | null {
function createRouteFromPath(filePath: string): Route {
const parts = filePath.split('/');
let counter: number = 1;
let counter = 1;
const query: string[] = [];
const srcParts = parts.map(
(segment, index): string => {
const name = getSegmentName(segment);
const isLast = index === parts.length - 1;
const srcParts = parts.map((segment, index): string => {
const name = getSegmentName(segment);
const isLast = index === parts.length - 1;
if (name !== null) {
// We can't use `URLSearchParams` because `$` would get escaped
query.push(`${name}=$${counter++}`);
return `([^\\/]+)`;
} else if (isLast) {
const { name: fileName, ext } = parsePath(segment);
const isIndex = fileName === 'index';
const prefix = isIndex ? '\\/' : '';
if (name !== null) {
// We can't use `URLSearchParams` because `$` would get escaped
query.push(`${name}=$${counter++}`);
return `([^\\/]+)`;
} else if (isLast) {
const { name: fileName, ext } = parsePath(segment);
const isIndex = fileName === 'index';
const prefix = isIndex ? '\\/' : '';
const names = [
prefix,
prefix + escapeName(fileName),
prefix + escapeName(fileName) + escapeName(ext),
].filter(Boolean);
const names = [
prefix,
prefix + escapeName(fileName),
prefix + escapeName(fileName) + escapeName(ext)
].filter(Boolean);
// Either filename with extension, filename without extension
// or nothing when the filename is `index`
return `(${names.join('|')})${isIndex ? '?' : ''}`;
}
return segment;
// Either filename with extension, filename without extension
// or nothing when the filename is `index`
return `(${names.join('|')})${isIndex ? '?' : ''}`;
}
);
return segment;
});
const { name: fileName } = parsePath(filePath);
const isIndex = fileName === 'index';
@@ -230,8 +228,8 @@ async function detectApiRoutes(files: string[]): Promise<RoutesResult> {
message:
`The segment "${conflictingSegment}" occurres more than ` +
`one time in your path "${file}". Please make sure that ` +
`every segment in a path is unique`,
},
`every segment in a path is unique`
}
};
}
@@ -251,8 +249,8 @@ async function detectApiRoutes(files: string[]): Promise<RoutesResult> {
message:
`Two or more files have conflicting paths or names. ` +
`Please make sure path segments and filenames, without their extension, are unique. ` +
`The path "${file}" has conflicts with ${messagePaths}`,
},
`The path "${file}" has conflicts with ${messagePaths}`
}
};
}
@@ -263,7 +261,7 @@ async function detectApiRoutes(files: string[]): Promise<RoutesResult> {
if (defaultRoutes.length) {
defaultRoutes.push({
status: 404,
src: '/api(\\/.*)?$',
src: '/api(\\/.*)?$'
});
}
@@ -289,7 +287,7 @@ export async function detectRoutes(
if (routesResult.defaultRoutes && hasPublicBuilder(builders)) {
routesResult.defaultRoutes.push({
src: '/(.*)',
dest: '/public/$1',
dest: '/public/$1'
});
}

View File

@@ -1,6 +1,7 @@
import assert from 'assert';
import fs from 'fs-extra';
import path from 'path';
import debug from '../debug';
import spawn from 'cross-spawn';
import { SpawnOptions } from 'child_process';
import { deprecate } from 'util';
@@ -128,8 +129,14 @@ async function scanParentDirs(destPath: string, readPackageJson = false) {
export async function runNpmInstall(
destPath: string,
args: string[] = [],
spawnOpts?: SpawnOptions
spawnOpts?: SpawnOptions,
meta?: Meta
) {
if (meta && meta.isDev) {
debug('Skipping dependency installation because dev mode is enabled');
return;
}
assert(path.isAbsolute(destPath));
let commandArgs = args;

View File

@@ -185,8 +185,8 @@ export interface ShouldServeOptions {
}
export interface PackageJson {
name: string;
version: string;
name?: string;
version?: string;
engines?: {
[key: string]: string;
node: string;

View File

@@ -1,20 +1,16 @@
/* global beforeAll, expect, it, jest */
const path = require('path');
const fs = require('fs-extra');
// eslint-disable-next-line import/no-extraneous-dependencies
const execa = require('execa');
const assert = require('assert');
const { createZip } = require('../dist/lambda');
const {
glob, download, detectBuilders, detectRoutes,
} = require('../');
const { glob, download, detectBuilders, detectRoutes } = require('../');
const {
getSupportedNodeVersion,
defaultSelection,
defaultSelection
} = require('../dist/fs/node-version');
const {
packAndDeploy,
testDeployment,
testDeployment
} = require('../../../test/lib/deployment/test-deployment');
jest.setTimeout(4 * 60 * 1000);
@@ -42,7 +38,7 @@ it('should re-create symlinks properly', async () => {
const [linkStat, aStat] = await Promise.all([
fs.lstat(path.join(outDir, 'link.txt')),
fs.lstat(path.join(outDir, 'a.txt')),
fs.lstat(path.join(outDir, 'a.txt'))
]);
assert(linkStat.isSymbolicLink());
assert(aStat.isFile());
@@ -64,7 +60,7 @@ it('should create zip files with symlinks properly', async () => {
const [linkStat, aStat] = await Promise.all([
fs.lstat(path.join(outDir, 'link.txt')),
fs.lstat(path.join(outDir, 'a.txt')),
fs.lstat(path.join(outDir, 'a.txt'))
]);
assert(linkStat.isSymbolicLink());
assert(aStat.isFile());
@@ -86,33 +82,33 @@ it('should match all semver ranges', () => {
// See https://docs.npmjs.com/files/package.json#engines
expect(getSupportedNodeVersion('10.0.0')).resolves.toHaveProperty(
'major',
10,
10
);
expect(getSupportedNodeVersion('10.x')).resolves.toHaveProperty('major', 10);
expect(getSupportedNodeVersion('>=10')).resolves.toHaveProperty('major', 10);
expect(getSupportedNodeVersion('>=10.3.0')).resolves.toHaveProperty(
'major',
10,
10
);
expect(getSupportedNodeVersion('8.5.0 - 10.5.0')).resolves.toHaveProperty(
'major',
10,
10
);
expect(getSupportedNodeVersion('>=9.0.0')).resolves.toHaveProperty(
'major',
10,
10
);
expect(getSupportedNodeVersion('>=9.5.0 <=10.5.0')).resolves.toHaveProperty(
'major',
10,
10
);
expect(getSupportedNodeVersion('~10.5.0')).resolves.toHaveProperty(
'major',
10,
10
);
expect(getSupportedNodeVersion('^10.5.0')).resolves.toHaveProperty(
'major',
10,
10
);
});
@@ -124,7 +120,7 @@ it('should support require by path for legacy builders', () => {
const glob2 = require('@now/build-utils/fs/glob.js');
const rename2 = require('@now/build-utils/fs/rename.js');
const {
runNpmInstall: runNpmInstall2,
runNpmInstall: runNpmInstall2
} = require('@now/build-utils/fs/run-user-scripts.js');
const streamToBuffer2 = require('@now/build-utils/fs/stream-to-buffer.js');
@@ -162,8 +158,8 @@ for (const fixture of fs.readdirSync(fixturesPath)) {
await expect(
testDeployment(
{ builderUrl, buildUtilsUrl },
path.join(fixturesPath, fixture),
),
path.join(fixturesPath, fixture)
)
).resolves.toBeDefined();
});
}
@@ -176,7 +172,7 @@ const buildersToTestWith = ['now-next', 'now-node', 'now-static-build'];
for (const builder of buildersToTestWith) {
const fixturesPath2 = path.resolve(
__dirname,
`../../${builder}/test/fixtures`,
`../../${builder}/test/fixtures`
);
// eslint-disable-next-line no-restricted-syntax
@@ -188,8 +184,8 @@ for (const builder of buildersToTestWith) {
await expect(
testDeployment(
{ builderUrl, buildUtilsUrl },
path.join(fixturesPath2, fixture),
),
path.join(fixturesPath2, fixture)
)
).resolves.toBeDefined();
});
}
@@ -210,7 +206,7 @@ it('Test `detectBuilders`', async () => {
// package.json + no build + next
const pkg = {
scripts: { build: 'next build' },
dependencies: { next: '9.0.0' },
dependencies: { next: '9.0.0' }
};
const files = ['package.json', 'pages/index.js'];
const { builders, errors } = await detectBuilders(files, pkg);
@@ -222,7 +218,7 @@ it('Test `detectBuilders`', async () => {
// package.json + no build + next
const pkg = {
scripts: { build: 'next build' },
devDependencies: { next: '9.0.0' },
devDependencies: { next: '9.0.0' }
};
const files = ['package.json', 'pages/index.js'];
const { builders, errors } = await detectBuilders(files, pkg);
@@ -286,7 +282,7 @@ it('Test `detectBuilders`', async () => {
const files = [
'api/_utils/handler.js',
'api/[endpoint]/.helper.js',
'api/[endpoint]/[id].js',
'api/[endpoint]/[id].js'
];
const { builders } = await detectBuilders(files);
@@ -299,7 +295,7 @@ it('Test `detectBuilders`', async () => {
// api + next + public
const pkg = {
scripts: { build: 'next build' },
devDependencies: { next: '9.0.0' },
devDependencies: { next: '9.0.0' }
};
const files = ['package.json', 'api/endpoint.js', 'public/index.html'];
@@ -315,7 +311,7 @@ it('Test `detectBuilders`', async () => {
// api + next + raw static
const pkg = {
scripts: { build: 'next build' },
devDependencies: { next: '9.0.0' },
devDependencies: { next: '9.0.0' }
};
const files = ['package.json', 'api/endpoint.js', 'index.html'];
@@ -347,7 +343,7 @@ it('Test `detectBuilders`', async () => {
'api/endpoint.js',
'public/index.html',
'public/favicon.ico',
'README.md',
'README.md'
];
const { builders } = await detectBuilders(files);
@@ -371,7 +367,7 @@ it('Test `detectBuilders`', async () => {
// next + public
const pkg = {
scripts: { build: 'next build' },
devDependencies: { next: '9.0.0' },
devDependencies: { next: '9.0.0' }
};
const files = ['package.json', 'public/index.html', 'README.md'];
@@ -385,7 +381,7 @@ it('Test `detectBuilders`', async () => {
// nuxt
const pkg = {
scripts: { build: 'nuxt build' },
dependencies: { nuxt: '2.8.1' },
dependencies: { nuxt: '2.8.1' }
};
const files = ['package.json', 'pages/index.js'];
@@ -437,12 +433,12 @@ it('Test `detectBuilders`', async () => {
// package.json + api + canary
const pkg = {
scripts: { build: 'next build' },
dependencies: { next: '9.0.0' },
dependencies: { next: '9.0.0' }
};
const files = [
'pages/index.js',
'api/[endpoint].js',
'api/[endpoint]/[id].js',
'api/[endpoint]/[id].js'
];
const { builders } = await detectBuilders(files, pkg, { tag: 'canary' });
@@ -456,12 +452,12 @@ it('Test `detectBuilders`', async () => {
// package.json + api + latest
const pkg = {
scripts: { build: 'next build' },
dependencies: { next: '9.0.0' },
dependencies: { next: '9.0.0' }
};
const files = [
'pages/index.js',
'api/[endpoint].js',
'api/[endpoint]/[id].js',
'api/[endpoint]/[id].js'
];
const { builders } = await detectBuilders(files, pkg, { tag: 'latest' });
@@ -475,12 +471,12 @@ it('Test `detectBuilders`', async () => {
// package.json + api + random tag
const pkg = {
scripts: { build: 'next build' },
dependencies: { next: '9.0.0' },
dependencies: { next: '9.0.0' }
};
const files = [
'pages/index.js',
'api/[endpoint].js',
'api/[endpoint]/[id].js',
'api/[endpoint]/[id].js'
];
const { builders } = await detectBuilders(files, pkg, { tag: 'haha' });
@@ -549,7 +545,7 @@ it('Test `detectRoutes`', async () => {
const files = [
'public/index.html',
'api/[endpoint].js',
'api/[endpoint]/[id].js',
'api/[endpoint]/[id].js'
];
const { builders } = await detectBuilders(files);
@@ -564,7 +560,7 @@ it('Test `detectRoutes`', async () => {
{
const pkg = {
scripts: { build: 'next build' },
devDependencies: { next: '9.0.0' },
devDependencies: { next: '9.0.0' }
};
const files = ['public/index.html', 'api/[endpoint].js'];
@@ -592,7 +588,7 @@ it('Test `detectRoutes`', async () => {
expect(defaultRoutes.length).toBe(3);
expect(defaultRoutes[0].src).toBe(
'^/api/date(\\/|\\/index|\\/index\\.js)?$',
'^/api/date(\\/|\\/index|\\/index\\.js)?$'
);
expect(defaultRoutes[0].dest).toBe('/api/date/index.js');
expect(defaultRoutes[1].src).toBe('^/api/(date|date\\.js)$');
@@ -607,7 +603,7 @@ it('Test `detectRoutes`', async () => {
expect(defaultRoutes.length).toBe(3);
expect(defaultRoutes[0].src).toBe(
'^/api/([^\\/]+)(\\/|\\/index|\\/index\\.js)?$',
'^/api/([^\\/]+)(\\/|\\/index|\\/index\\.js)?$'
);
expect(defaultRoutes[0].dest).toBe('/api/[date]/index.js?date=$1');
expect(defaultRoutes[1].src).toBe('^/api/(date|date\\.js)$');
@@ -621,7 +617,7 @@ it('Test `detectRoutes`', async () => {
'api/users/index.ts',
'api/users/index.d.ts',
'api/food.ts',
'api/ts/gold.ts',
'api/ts/gold.ts'
];
const { builders } = await detectBuilders(files);
const { defaultRoutes } = await detectRoutes(files, builders);
@@ -645,39 +641,39 @@ it('Test `detectBuilders` and `detectRoutes`', async () => {
{
path: '/api/my-endpoint',
mustContain: 'my-endpoint',
status: 200,
status: 200
},
{
path: '/api/other-endpoint',
mustContain: 'other-endpoint',
status: 200,
status: 200
},
{
path: '/api/team/zeit',
mustContain: 'team/zeit',
status: 200,
status: 200
},
{
path: '/api/user/myself',
mustContain: 'user/myself',
status: 200,
status: 200
},
{
path: '/api/not-okay/',
status: 404,
status: 404
},
{
path: '/api',
status: 404,
status: 404
},
{
path: '/api/',
status: 404,
status: 404
},
{
path: '/',
mustContain: 'hello from index.txt',
},
mustContain: 'hello from index.txt'
}
];
const { builders } = await detectBuilders(files, pkg);
@@ -686,12 +682,12 @@ it('Test `detectBuilders` and `detectRoutes`', async () => {
const nowConfig = { builds: builders, routes: defaultRoutes, probes };
await fs.writeFile(
path.join(fixture, 'now.json'),
JSON.stringify(nowConfig, null, 2),
JSON.stringify(nowConfig, null, 2)
);
const deployment = await testDeployment(
{ builderUrl, buildUtilsUrl },
fixture,
fixture
);
expect(deployment).toBeDefined();
});
@@ -705,32 +701,32 @@ it('Test `detectBuilders` and `detectRoutes` with `index` files', async () => {
const probes = [
{
path: '/api/not-okay',
status: 404,
status: 404
},
{
path: '/api',
mustContain: 'hello from api/index.js',
status: 200,
status: 200
},
{
path: '/api/',
mustContain: 'hello from api/index.js',
status: 200,
status: 200
},
{
path: '/api/index',
mustContain: 'hello from api/index.js',
status: 200,
status: 200
},
{
path: '/api/index.js',
mustContain: 'hello from api/index.js',
status: 200,
status: 200
},
{
path: '/api/date.js',
mustContain: 'hello from api/date.js',
status: 200,
status: 200
},
{
// Someone might expect this to be `date.js`,
@@ -739,27 +735,27 @@ it('Test `detectBuilders` and `detectRoutes` with `index` files', async () => {
// so it is not special cased
path: '/api/date',
mustContain: 'hello from api/date/index.js',
status: 200,
status: 200
},
{
path: '/api/date/',
mustContain: 'hello from api/date/index.js',
status: 200,
status: 200
},
{
path: '/api/date/index',
mustContain: 'hello from api/date/index.js',
status: 200,
status: 200
},
{
path: '/api/date/index.js',
mustContain: 'hello from api/date/index.js',
status: 200,
status: 200
},
{
path: '/',
mustContain: 'hello from index.txt',
},
mustContain: 'hello from index.txt'
}
];
const { builders } = await detectBuilders(files, pkg);
@@ -768,12 +764,12 @@ it('Test `detectBuilders` and `detectRoutes` with `index` files', async () => {
const nowConfig = { builds: builders, routes: defaultRoutes, probes };
await fs.writeFile(
path.join(fixture, 'now.json'),
JSON.stringify(nowConfig, null, 2),
JSON.stringify(nowConfig, null, 2)
);
const deployment = await testDeployment(
{ builderUrl, buildUtilsUrl },
fixture,
fixture
);
expect(deployment).toBeDefined();
});

View File

@@ -1,32 +0,0 @@
root = true
[*]
indent_style = tab
indent_size = 4
tab_width = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[{*.json,*.json.example,*.gyp,*.yml}]
indent_style = space
indent_size = 2
[*.py]
indent_style = space
indent_size = 4
[*.md]
trim_trailing_whitespace = false
# Ideal settings - some plugins might support these.
[*.js]
quote_type = single
[{*.c,*.cc,*.h,*.hh,*.cpp,*.hpp,*.m,*.mm,*.mpp,*.js,*.java,*.go,*.rs,*.php,*.ng,*.jsx,*.ts,*.d,*.cs,*.swift}]
curly_bracket_next_line = false
spaces_around_operators = true
spaces_around_brackets = outside
# close enough to 1TB
indent_brace_style = K&R

View File

@@ -1,2 +1 @@
node_modules
handler

View File

@@ -1,17 +1,15 @@
const path = require('path');
const { mkdirp, copyFile } = require('fs-extra');
const glob = require('@now/build-utils/fs/glob'); // eslint-disable-line import/no-extraneous-dependencies
const download = require('@now/build-utils/fs/download'); // eslint-disable-line import/no-extraneous-dependencies
const { createLambda } = require('@now/build-utils/lambda'); // eslint-disable-line import/no-extraneous-dependencies
const getWritableDirectory = require('@now/build-utils/fs/get-writable-directory'); // eslint-disable-line import/no-extraneous-dependencies
const { shouldServe } = require('@now/build-utils'); // eslint-disable-line import/no-extraneous-dependencies
const glob = require('@now/build-utils/fs/glob');
const download = require('@now/build-utils/fs/download');
const { createLambda } = require('@now/build-utils/lambda');
const getWritableDirectory = require('@now/build-utils/fs/get-writable-directory');
const { shouldServe } = require('@now/build-utils');
exports.analyze = ({ files, entrypoint }) => files[entrypoint].digest;
exports.build = async ({
workPath, files, entrypoint, meta,
}) => {
exports.build = async ({ workPath, files, entrypoint, meta }) => {
console.log('downloading files...');
const outDir = await getWritableDirectory();
@@ -26,7 +24,7 @@ exports.build = async ({
// For now only the entrypoint file is copied into the lambda
await copyFile(
path.join(workPath, entrypoint),
path.join(outDir, entrypoint),
path.join(outDir, entrypoint)
);
const lambda = await createLambda({
@@ -34,12 +32,12 @@ exports.build = async ({
handler: 'handler',
runtime: 'go1.x',
environment: {
SCRIPT_FILENAME: entrypoint,
},
SCRIPT_FILENAME: entrypoint
}
});
return {
[entrypoint]: lambda,
[entrypoint]: lambda
};
};

View File

@@ -1,6 +1,6 @@
{
"name": "@now/cgi",
"version": "0.1.5",
"version": "0.1.6",
"license": "MIT",
"repository": {
"type": "git",

View File

@@ -1,8 +0,0 @@
@types
download
dist
test/fixtures
test/dev/fixtures
bin
link
src/util/dev/templates/*.ts

View File

@@ -1,86 +0,0 @@
module.exports = {
'extends': [
'airbnb',
'prettier'
],
'parser': '@typescript-eslint/parser',
'parserOptions': {
'ecmaVersion': 2018,
'sourceType': 'module',
'modules': true
},
'plugins': [
'@typescript-eslint'
],
'settings': {
'import/resolver': {
'typescript': {
}
}
},
'rules': {
'quotes': [
2,
'single',
{
'allowTemplateLiterals': true
}
],
'class-methods-use-this': 0,
'consistent-return': 0,
'func-names': 0,
'global-require': 0,
'guard-for-in': 0,
'import/no-duplicates': 0,
'import/no-dynamic-require': 0,
'import/no-extraneous-dependencies': 0,
'import/prefer-default-export': 0,
'lines-between-class-members': 0,
'no-await-in-loop': 0,
'no-bitwise': 0,
'no-console': 0,
'no-continue': 0,
'no-control-regex': 0,
'no-empty': 0,
'no-loop-func': 0,
'no-nested-ternary': 0,
'no-param-reassign': 0,
'no-plusplus': 0,
'no-restricted-globals': 0,
'no-restricted-syntax': 0,
'no-shadow': 0,
'no-underscore-dangle': 0,
'no-use-before-define': 0,
'prefer-const': 0,
'prefer-destructuring': 0,
'camelcase': 0,
'no-unused-vars': 0, // in favor of '@typescript-eslint/no-unused-vars'
// 'indent': 0 // in favor of '@typescript-eslint/indent'
'@typescript-eslint/no-unused-vars': 'warn',
// '@typescript-eslint/indent': ['error', 2] // this might conflict with a lot ongoing changes
'@typescript-eslint/no-array-constructor': 'error',
'@typescript-eslint/adjacent-overload-signatures': 'error',
'@typescript-eslint/class-name-casing': 'error',
'@typescript-eslint/interface-name-prefix': 'error',
'@typescript-eslint/no-empty-interface': 'error',
'@typescript-eslint/no-inferrable-types': 'error',
'@typescript-eslint/no-misused-new': 'error',
'@typescript-eslint/no-namespace': 'error',
'@typescript-eslint/no-non-null-assertion': 'error',
'@typescript-eslint/no-parameter-properties': 'error',
'@typescript-eslint/no-triple-slash-reference': 'error',
'@typescript-eslint/prefer-namespace-keyword': 'error',
'@typescript-eslint/type-annotation-spacing': 'error',
// '@typescript-eslint/array-type': 'error',
// '@typescript-eslint/ban-types': 'error',
// '@typescript-eslint/explicit-function-return-type': 'warn',
// '@typescript-eslint/explicit-member-accessibility': 'error',
// '@typescript-eslint/member-delimiter-style': 'error',
// '@typescript-eslint/no-angle-bracket-type-assertion': 'error',
// '@typescript-eslint/no-explicit-any': 'warn',
// '@typescript-eslint/no-object-literal-type-assertion': 'error',
// '@typescript-eslint/no-use-before-define': 'error',
// '@typescript-eslint/no-var-requires': 'error',
// '@typescript-eslint/prefer-interface': 'error'
}
}

View File

@@ -1,3 +0,0 @@
declare module 'cache-or-tmp-directory' {
export default function (appName: string) : string | null
}

View File

@@ -1,3 +0,0 @@
declare module 'pcre-to-regexp' {
export default function (pattern: string, keys?: string[]): RegExp
}

View File

@@ -1,6 +1,6 @@
{
"name": "now",
"version": "16.1.3",
"version": "16.2.0",
"preferGlobal": true,
"license": "Apache-2.0",
"description": "The command-line interface for Now",
@@ -11,17 +11,15 @@
"directory": "packages/now-cli"
},
"scripts": {
"test": "yarn test-lint",
"preinstall": "node ./scripts/preinstall.js",
"test-unit": "nyc ava test/*unit.js --serial --fail-fast --verbose",
"test-integration": "ava test/integration.js --serial --fail-fast",
"test-integration-now-dev": "ava test/dev/integration.js --serial --fail-fast --verbose",
"test-lint": "eslint . --ext .js,.ts",
"prepublishOnly": "yarn build",
"coverage": "nyc report --reporter=text-lcov > coverage.lcov && codecov",
"build": "ts-node ./scripts/build.ts",
"build-dev": "ts-node ./scripts/build.ts --dev",
"format-modified": "prettier --parser typescript --write --single-quote `git diff --name-only HEAD * | grep -e \".*\\.ts$\" -e \".*\\.js$\" | xargs echo`"
"test-lint": "eslint . --ext .ts,.js --ignore-path ../../.eslintignore"
},
"nyc": {
"include": [
@@ -42,12 +40,6 @@
"instrument": true,
"all": true
},
"git": {
"pre-commit": [
"test-lint",
"format-modified"
]
},
"bin": {
"now": "./dist/index.js"
},
@@ -69,12 +61,11 @@
"node": ">= 8.11"
},
"devDependencies": {
"@now/build-utils": "0.9.14",
"@now/build-utils": "0.10.0",
"@now/go": "latest",
"@now/next": "latest",
"@now/node": "latest",
"@now/php": "latest",
"@now/routing-utils": "1.2.3",
"@now/routing-utils": "1.2.3-canary.0",
"@now/static-build": "latest",
"@sentry/node": "5.5.0",
"@types/ansi-escapes": "3.0.0",
@@ -106,11 +97,8 @@
"@types/universal-analytics": "0.4.2",
"@types/which": "1.3.1",
"@types/write-json-file": "2.2.1",
"@typescript-eslint/eslint-plugin": "1.6.0",
"@typescript-eslint/parser": "1.1.0",
"@zeit/dockerignore": "0.0.5",
"@zeit/fun": "0.9.1",
"@zeit/git-hooks": "0.1.4",
"@zeit/fun": "0.9.3",
"@zeit/ncc": "0.18.5",
"@zeit/source-map-support": "0.6.2",
"ajv": "6.10.2",
@@ -123,7 +111,6 @@
"async-sema": "2.1.4",
"ava": "2.2.0",
"bytes": "3.0.0",
"cache-or-tmp-directory": "1.0.0",
"chalk": "2.4.2",
"chokidar": "2.1.6",
"clipboardy": "2.1.0",
@@ -142,13 +129,6 @@
"email-validator": "1.1.1",
"epipebomb": "1.0.0",
"escape-html": "1.0.3",
"eslint": "5.16.0",
"eslint-config-airbnb": "17.1.0",
"eslint-config-prettier": "4.1.0",
"eslint-import-resolver-typescript": "1.1.1",
"eslint-plugin-import": "2.16.0",
"eslint-plugin-jsx-a11y": "6.2.1",
"eslint-plugin-react": "7.12.4",
"esm": "3.1.4",
"execa": "1.0.0",
"fetch-h2": "2.0.3",
@@ -170,10 +150,9 @@
"npm-package-arg": "6.1.0",
"nyc": "13.2.0",
"ora": "3.4.0",
"pcre-to-regexp": "0.0.5",
"pcre-to-regexp": "1.0.0",
"pluralize": "7.0.0",
"pre-commit": "1.2.2",
"prettier": "1.16.2",
"printf": "0.2.5",
"progress": "2.0.3",
"promisepipe": "3.0.0",

View File

@@ -11,7 +11,10 @@ import strlen from '../../util/strlen.ts';
import wait from '../../util/output/wait';
export default async function ls(ctx, opts, args, output) {
const { authConfig: { token }, config } = ctx;
const {
authConfig: { token },
config
} = ctx;
const { currentTeam } = config;
const { apiUrl } = ctx;
const { '--debug': debugEnabled } = opts;
@@ -48,15 +51,13 @@ export default async function ls(ctx, opts, args, output) {
return 1;
}
if (!opts['--json']) {
cancelWait = wait(
args[0]
? `Fetching alias details for "${args[0]}" under ${chalk.bold(
contextName
)}`
: `Fetching aliases under ${chalk.bold(contextName)}`
);
}
cancelWait = wait(
args[0]
? `Fetching alias details for "${args[0]}" under ${chalk.bold(
contextName
)}`
: `Fetching aliases under ${chalk.bold(contextName)}`
);
const aliases = await getAliases(now);
if (cancelWait) cancelWait();
@@ -72,7 +73,7 @@ export default async function ls(ctx, opts, args, output) {
}
if (opts['--json']) {
output.print(JSON.stringify({ rules: alias.rules }, null, 2));
console.log(JSON.stringify({ rules: alias.rules }, null, 2));
} else {
const rules = alias.rules || [];
output.log(
@@ -105,11 +106,11 @@ function printAliasTable(aliases) {
a.rules && a.rules.length
? chalk.cyan(`[${plural('rule', a.rules.length, true)}]`)
: // for legacy reasons, we might have situations
// where the deployment was deleted and the alias
// not collected appropriately, and we need to handle it
a.deployment && a.deployment.url
? a.deployment.url
: chalk.gray(''),
// where the deployment was deleted and the alias
// not collected appropriately, and we need to handle it
a.deployment && a.deployment.url
? a.deployment.url
: chalk.gray(''),
a.alias,
ms(Date.now() - new Date(a.created))
])

View File

@@ -80,7 +80,9 @@ export default async function set(
}
if (!isValidName(args[0])) {
output.error(`The provided argument "${args[0]}" is not a valid deployment`);
output.error(
`The provided argument "${args[0]}" is not a valid deployment`
);
return 1;
}
@@ -212,6 +214,7 @@ export default async function set(
for (const target of targets) {
output.log(`Assigning alias ${target} to deployment ${deployment.url}`);
const isWildcard = isWildcardAlias(target);
const record = await assignAlias(
output,
client,
@@ -222,13 +225,14 @@ export default async function set(
);
const handleResult = handleSetupDomainError(
output,
handleCreateAliasError(output, record)
handleCreateAliasError(output, record),
isWildcard
);
if (handleResult === 1) {
return 1;
}
const prefix = isWildcardAlias(handleResult.alias) ? '' : 'https://';
const prefix = isWildcard ? '' : 'https://';
console.log(
`${chalk.cyan('> Success!')} ${chalk.bold(
@@ -246,10 +250,15 @@ type SetupDomainError = Exclude<SetupDomainResolve, Domain>;
function handleSetupDomainError<T>(
output: Output,
error: SetupDomainError | T
error: SetupDomainError | T,
isWildcard: boolean = false
): T | 1 {
if (error instanceof ERRORS.DomainVerificationFailed) {
const { nsVerification, txtVerification, domain } = error.meta;
if (
error instanceof ERRORS.DomainVerificationFailed ||
error instanceof ERRORS.DomainNsNotVerifiedForWildcard
) {
const { nsVerification, domain } = error.meta;
output.error(
`We could not alias since the domain ${domain} could not be verified due to the following reasons:\n`
);
@@ -265,25 +274,34 @@ function handleSetupDomainError<T>(
{ extraSpace: ' ' }
)}\n\n`
);
output.print(
` ${chalk.gray(
'b)'
)} DNS TXT verification failed since found no matching records.`
);
output.print(
`\n${formatDnsTable(
[['_now', 'TXT', txtVerification.verificationRecord]],
{ extraSpace: ' ' }
)}\n\n`
);
output.print(
` Once your domain uses either the nameservers or the TXT DNS record from above, run again ${cmd(
'now domains verify <domain>'
)}.\n`
);
output.print(
` We will also periodically run a verification check for you and you will receive an email once your domain is verified.\n`
);
if (error instanceof ERRORS.DomainVerificationFailed && !isWildcard) {
const { txtVerification } = error.meta;
output.print(
` ${chalk.gray(
'b)'
)} DNS TXT verification failed since found no matching records.`
);
output.print(
`\n${formatDnsTable(
[['_now', 'TXT', txtVerification.verificationRecord]],
{ extraSpace: ' ' }
)}\n\n`
);
output.print(
` Once your domain uses either the nameservers or the TXT DNS record from above, run again ${cmd(
'now domains verify <domain>'
)}.\n`
);
output.print(
` We will also periodically run a verification check for you and you will receive an email once your domain is verified.\n`
);
} else {
output.print(
` Once your domain uses the nameservers from above, run again ${cmd(
'now domains verify <domain>'
)}.\n`
);
}
output.print(' Read more: https://err.sh/now/domain-verification\n');
return 1;
}
@@ -349,9 +367,7 @@ function handleSetupDomainError<T>(
if (error instanceof ERRORS.DomainPurchasePending) {
output.error(
`The domain ${
error.meta.domain
} is processing and will be available once the order is completed.`
`The domain ${error.meta.domain} is processing and will be available once the order is completed.`
);
output.print(
` An email will be sent upon completion so you can alias to your new domain.\n`
@@ -467,9 +483,7 @@ function handleCreateAliasError<T>(
}
if (error instanceof ERRORS.ForbiddenScaleMinInstances) {
output.error(
`You can't scale to more than ${
error.meta.max
} min instances with your current plan.`
`You can't scale to more than ${error.meta.max} min instances with your current plan.`
);
return 1;
}
@@ -490,9 +504,7 @@ function handleCreateAliasError<T>(
if (error instanceof ERRORS.CertMissing) {
output.error(
`There is no certificate for the domain ${
error.meta.domain
} and it could not be created.`
`There is no certificate for the domain ${error.meta.domain} and it could not be created.`
);
output.log(
`Please generate a new certificate manually with ${cmd(

View File

@@ -1,12 +1,15 @@
import chalk from 'chalk';
// @ts-ignore
import Now from '../../util';
import Client from '../../util/client.ts';
import getScope from '../../util/get-scope.ts';
import stamp from '../../util/output/stamp.ts';
import Client from '../../util/client';
import getScope from '../../util/get-scope';
import stamp from '../../util/output/stamp';
import wait from '../../util/output/wait';
import createCertFromFile from '../../util/certs/create-cert-from-file';
import createCertForCns from '../../util/certs/create-cert-for-cns';
import { NowContext } from '../../types';
import { Output } from '../../util/output';
import {
DomainPermissionDenied,
@@ -14,7 +17,20 @@ import {
} from '../../util/errors-ts';
import handleCertError from '../../util/certs/handle-cert-error';
async function add(ctx, opts, args, output) {
interface Options {
'--overwrite'?: boolean;
'--debug'?: boolean;
'--crt'?: string;
'--key'?: string;
'--ca'?: string;
}
async function add(
ctx: NowContext,
opts: Options,
args: string[],
output: Output
): Promise<number> {
const {
authConfig: { token },
config
@@ -77,10 +93,12 @@ async function add(ctx, opts, args, output) {
// Create a custom certificate from the given file paths
cert = await createCertFromFile(now, keyPath, crtPath, caPath, contextName);
if (cert instanceof InvalidCert) {
output.error(`The provided certificate is not valid and can't be added.`);
return 1;
}
if (cert instanceof DomainPermissionDenied) {
output.error(
`You don't have permissions over domain ${chalk.underline(
@@ -97,6 +115,7 @@ async function add(ctx, opts, args, output) {
'now certs issue <cn> <cns>'
)} instead`
);
if (args.length < 1) {
output.error(
`Invalid number of arguments to create a custom certificate entry. Usage:`
@@ -107,34 +126,43 @@ async function add(ctx, opts, args, output) {
}
// Create the certificate from the given array of CNs
const cns = args.reduce((res, item) => [...res, ...item.split(',')], []);
const cns = args.reduce<string[]>((res, item) => res.concat(item.split(',')), []);
const cancelWait = wait(
`Generating a certificate for ${chalk.bold(cns.join(', '))}`
);
cert = await createCertForCns(now, cns, contextName);
cancelWait();
const result = handleCertError(output, cert);
if (result === 1) {
return result
}
if (cert instanceof DomainPermissionDenied) {
output.error(
`You don't have permissions over domain ${chalk.underline(
cert.meta.domain
)} under ${chalk.bold(cert.meta.context)}.`
);
return 1;
}
}
// Print success message
output.success(
`Certificate entry for ${chalk.bold(
cert.cns.join(', ')
)} created ${addStamp()}`
);
const result = handleCertError(output, cert);
if (result === 1) {
return result;
}
if (cert instanceof DomainPermissionDenied) {
output.error(
`You don't have permissions over domain ${chalk.underline(
cert.meta.domain
)} under ${chalk.bold(cert.meta.context)}.`
);
return 1;
}
if (cert instanceof Error) {
// All cert errors are handled above,
// so this is only for typescript
throw cert;
} else {
// Print success message
output.success(
`Certificate entry for ${chalk.bold(
cert.cns.join(', ')
)} created ${addStamp()}`
);
}
return 0;
}

View File

@@ -1,6 +1,6 @@
//
import chalk from 'chalk';
// @ts-ignore
import { handleError } from '../../util/error';
import createOutput from '../../util/output';
@@ -12,6 +12,7 @@ import add from './add';
import issue from './issue';
import ls from './ls';
import rm from './rm';
import { NowContext } from '../../types';
const help = () => {
console.log(`
@@ -71,7 +72,7 @@ const COMMAND_CONFIG = {
rm: ['rm', 'remove']
};
export default async function main(ctx) {
export default async function main(ctx: NowContext) {
let argv;
try {

View File

@@ -3,16 +3,29 @@ import ms from 'ms';
import plural from 'pluralize';
import psl from 'psl';
import table from 'text-table';
// @ts-ignore
import Now from '../../util';
import cmd from '../../util/output/cmd';
import Client from '../../util/client.ts';
import getScope from '../../util/get-scope.ts';
import stamp from '../../util/output/stamp.ts';
import Client from '../../util/client';
import getScope from '../../util/get-scope';
import stamp from '../../util/output/stamp';
import getCerts from '../../util/certs/get-certs';
import { CertNotFound } from '../../util/errors-ts';
import strlen from '../../util/strlen.ts';
import strlen from '../../util/strlen';
import { Output } from '../../util/output';
import { NowContext, Cert } from '../../types';
async function ls(ctx, opts, args, output) {
interface Options {
'--debug'?: boolean;
'--after'?: string;
}
async function ls(
ctx: NowContext,
opts: Options,
args: string[],
output: Output
): Promise<number> {
const { authConfig: { token }, config } = ctx;
const { currentTeam } = config;
const { apiUrl } = ctx;
@@ -32,7 +45,6 @@ async function ls(ctx, opts, args, output) {
throw err;
}
// $FlowFixMe
const now = new Now({ apiUrl, token, debug, currentTeam });
const lsStamp = stamp();
@@ -55,7 +67,6 @@ async function ls(ctx, opts, args, output) {
throw certificates;
}
const { uid: lastCert } = certificates[certificates.length - 1];
const certs = sortByCn(certificates);
output.log(
@@ -65,7 +76,8 @@ async function ls(ctx, opts, args, output) {
);
if (certs.length >= 100) {
output.note(`There may be more certificates that can be retrieved with ${cmd(`now ${process.argv.slice(2).join(' ')} --after=${lastCert}`)}.`);
const { uid: lastCert } = certificates[certificates.length - 1];
output.note(`There may be more certificates that can be retrieved with ${cmd(`now ${process.argv.slice(2).join(' ')} --after=${lastCert}`)}.\n`);
}
if (certs.length > 0) {
@@ -75,7 +87,7 @@ async function ls(ctx, opts, args, output) {
return 0;
}
function formatCertsTable(certsList) {
function formatCertsTable(certsList: Cert[]) {
return `${table(
[formatCertsTableHead(), ...formatCertsTableBody(certsList)],
{
@@ -86,7 +98,7 @@ function formatCertsTable(certsList) {
).replace(/^(.*)/gm, ' $1')}\n`;
}
function formatCertsTableHead() {
function formatCertsTableHead(): string[] {
return [
chalk.dim('id'),
chalk.dim('cns'),
@@ -96,15 +108,12 @@ function formatCertsTableHead() {
];
}
function formatCertsTableBody(certsList) {
function formatCertsTableBody(certsList: Cert[]) {
const now = new Date();
return certsList.reduce(
(result, cert) => [...result, ...formatCert(now, cert)],
[]
);
return certsList.reduce<string[][]>((result, cert) => result.concat(formatCert(now, cert)), []);
}
function formatCert(time, cert) {
function formatCert(time: Date, cert: Cert) {
return cert.cns.map(
(cn, idx) =>
idx === 0
@@ -113,26 +122,26 @@ function formatCert(time, cert) {
);
}
function formatCertNonFirstCn(cn, multiple) {
function formatCertNonFirstCn(cn: string, multiple: boolean): string[] {
return ['', formatCertCn(cn, multiple), '', '', ''];
}
function formatCertCn(cn, multiple) {
function formatCertCn(cn: string, multiple: boolean) {
return multiple ? `${chalk.gray('-')} ${chalk.bold(cn)}` : chalk.bold(cn);
}
function formatCertFirstCn(time, cert, cn, multiple) {
function formatCertFirstCn(time: Date, cert: Cert, cn: string, multiple: boolean): string[] {
return [
cert.uid,
formatCertCn(cn, multiple),
formatExpirationDate(new Date(cert.expiration)),
cert.autoRenew ? 'yes' : 'no',
chalk.gray(ms(time - new Date(cert.created)))
chalk.gray(ms(time.getTime() - new Date(cert.created).getTime()))
];
}
function formatExpirationDate(date) {
const diff = date - Date.now();
function formatExpirationDate(date: Date) {
const diff = date.getTime() - Date.now();
return diff < 0
? chalk.gray(`${ms(-diff)} ago`)
: chalk.gray(`in ${ms(diff)}`);
@@ -143,8 +152,8 @@ function formatExpirationDate(date) {
* to 'wildcard' since that will allow psl get the root domain
* properly to make the comparison.
*/
function sortByCn(certsList) {
return certsList.concat().sort((a, b) => {
function sortByCn(certsList: Cert[]) {
return certsList.concat().sort((a: Cert, b: Cert) => {
const domainA = psl.get(a.cns[0].replace('*', 'wildcard'));
const domainB = psl.get(b.cns[0].replace('*', 'wildcard'));
if (!domainA || !domainB) return 0;

View File

@@ -10,7 +10,9 @@ export const latestHelp = () => `
${chalk.dim('Basic')}
deploy [path] Performs a deployment ${chalk.bold('(default)')}
deploy [path] Performs a deployment ${chalk.bold(
'(default)'
)}
dev Start a local development server
init [example] Initialize an example project
ls | list [app] Lists deployments
@@ -18,7 +20,6 @@ export const latestHelp = () => `
login [email] Logs into your account or creates a new one
logout Logs out of your account
switch [scope] Switches between teams and your personal account
update Updates Now CLI to the latest version
help [cmd] Displays complete help for [cmd]
${chalk.dim('Advanced')}
@@ -29,7 +30,6 @@ export const latestHelp = () => `
certs [cmd] Manages your SSL certificates
secrets [name] Manages your secret environment variables
logs [url] Displays the logs for a deployment
scale [args] Scales the instance count of a deployment
teams Manages your teams
whoami Shows the username of the currently logged in user
@@ -115,7 +115,7 @@ export const latestArgs = {
'-e': '--env',
'-b': '--build-env',
'-C': '--no-clipboard',
'-m': '--meta'
'-m': '--meta',
};
export const legacyArgsMri = {
@@ -126,7 +126,7 @@ export const legacyArgsMri = {
'meta',
'session-affinity',
'regions',
'dotenv'
'dotenv',
],
boolean: [
'help',
@@ -143,11 +143,11 @@ export const legacyArgsMri = {
'public',
'no-scale',
'no-verify',
'dotenv'
'dotenv',
],
default: {
C: false,
clipboard: true
clipboard: true,
},
alias: {
env: 'e',
@@ -164,8 +164,8 @@ export const legacyArgsMri = {
'session-affinity': 'S',
name: 'n',
project: 'P',
alias: 'a'
}
alias: 'a',
},
};
// The following arg parsing is simply to make it compatible

View File

@@ -202,7 +202,6 @@ const promptForEnvFields = async (list: string[]) => {
});
}
// eslint-disable-next-line import/no-unassigned-import
require('../../util/input/patch-inquirer');
log('Please enter values for the following environment variables:');

View File

@@ -23,7 +23,7 @@ export default async function verify(
) {
const {
authConfig: { token },
config
config,
} = ctx;
const { currentTeam } = config;
const { apiUrl } = ctx;
@@ -122,16 +122,11 @@ export default async function verify(
return 1;
}
if (result.txtVerifiedAt) {
if (result.nsVerifiedAt) {
console.log(
`${chalk.cyan('> Success!')} Domain ${chalk.bold(
domain.name
)} was verified using DNS TXT record. ${verifyStamp()}`
);
output.print(
` You can verify with nameservers too. Run ${cmd(
`now domains inspect ${domain.name}`
)} to find out the intended set.\n`
)} was verified using nameservers. ${verifyStamp()}`
);
return 0;
}
@@ -139,7 +134,12 @@ export default async function verify(
console.log(
`${chalk.cyan('> Success!')} Domain ${chalk.bold(
domain.name
)} was verified using nameservers. ${verifyStamp()}`
)} was verified using DNS TXT record. ${verifyStamp()}`
);
output.print(
` You can verify with nameservers too. Run ${cmd(
`now domains inspect ${domain.name}`
)} to find out the intended set.\n`
);
return 0;
}

View File

@@ -136,7 +136,10 @@ export default async function main(ctx) {
types = argv.all ? [] : ['command', 'stdout', 'stderr', 'exit'];
outputMode = argv.output in logPrinters ? argv.output : 'short';
const { authConfig: { token }, config } = ctx;
const {
authConfig: { token },
config
} = ctx;
const { currentTeam } = config;
const now = new Now({ apiUrl, token, debug, currentTeam });
const client = new Client({
@@ -295,10 +298,25 @@ function printLogShort(log) {
const date = new Date(log.created).toISOString();
data.split('\n').forEach((line, i) => {
if (line.includes('START RequestId:') || line.includes('END RequestId:')) {
return;
}
if (line.includes('REPORT RequestId:')) {
line = line.substring(line.indexOf('Duration:'), line.length);
}
if (i === 0) {
console.log(`${chalk.dim(date)} ${line}`);
console.log(
`${chalk.dim(date)} ${line.replace('[now-builder-debug] ', '')}`
);
} else {
console.log(`${' '.repeat(date.length)} ${line}`);
console.log(
`${' '.repeat(date.length)} ${line.replace(
'[now-builder-debug] ',
''
)}`
);
}
});

View File

@@ -8,7 +8,7 @@ import { createHash } from 'crypto';
import { createGunzip } from 'zlib';
import { join, resolve } from 'path';
import { funCacheDir } from '@zeit/fun';
import cacheDirectory from 'cache-or-tmp-directory';
import XDGAppPaths from 'xdg-app-paths';
import {
createReadStream,
mkdirp,
@@ -80,7 +80,7 @@ export async function prepareCacheDir() {
const { NOW_BUILDER_CACHE_DIR } = process.env;
const designated = NOW_BUILDER_CACHE_DIR
? resolve(NOW_BUILDER_CACHE_DIR)
: cacheDirectory('co.zeit.now');
: XDGAppPaths('co.zeit.now').cache();
if (!designated) {
throw new NoBuilderCacheError();

View File

@@ -9,6 +9,7 @@ import maybeGetDomainByName from './maybe-get-domain-by-name';
import purchaseDomainIfAvailable from './purchase-domain-if-available';
import verifyDomain from './verify-domain';
import extractDomain from '../alias/extract-domain';
import isWildcardAlias from '../alias/is-wildcard-alias';
export default async function setupDomain(
output: Output,
@@ -34,7 +35,7 @@ export default async function setupDomain(
if (info) {
output.debug(`Domain ${domain} found for the given context`);
if (!info.verified) {
if (!info.verified || (!info.nsVerifiedAt && isWildcardAlias(alias))) {
output.debug(
`Domain ${domain} is not verified, trying to perform a verification`
);
@@ -47,8 +48,17 @@ export default async function setupDomain(
output.debug(`Domain ${domain} verification failed`);
return verificationResult;
}
if (!verificationResult.nsVerifiedAt && isWildcardAlias(alias)) {
return new ERRORS.DomainNsNotVerifiedForWildcard({
domain,
nsVerification: {
intendedNameservers: verificationResult.intendedNameservers,
nameservers: verificationResult.nameservers
}
});
}
output.debug(`Domain ${domain} successfuly verified`);
output.debug(`Domain ${domain} successfuly verified`);
return maybeGetDomainByName(client, contextName, domain) as Promise<
Domain
>;

View File

@@ -252,6 +252,31 @@ export type TXTVerificationError = {
values: string[];
};
/**
* This error is returned when the domain is not verified by nameservers for wildcard alias.
*/
export class DomainNsNotVerifiedForWildcard extends NowError<
'DOMAIN_NS_NOT_VERIFIED_FOR_WILDCARD',
{
domain: string;
nsVerification: NSVerificationError;
}
> {
constructor({
domain,
nsVerification
}: {
domain: string;
nsVerification: NSVerificationError;
}) {
super({
code: 'DOMAIN_NS_NOT_VERIFIED_FOR_WILDCARD',
meta: { domain, nsVerification },
message: `The domain ${domain} is not verified by nameservers for wildcard alias.`
});
}
}
/**
* Used when a domain is validated because we tried to add it to an account
* via API or for any other reason.
@@ -561,7 +586,7 @@ export class DeploymentNotFound extends NowError<
*/
export class DeploymentNotReady extends NowError<
'DEPLOYMENT_NOT_READY',
{ url: string; }
{ url: string }
> {
constructor({ url = '' }: { url: string }) {
super({
@@ -986,8 +1011,14 @@ export class InvalidEmail extends NowError<'INVALID_EMAIL', { email: string }> {
}
}
export class AccountNotFound extends NowError<'ACCOUNT_NOT_FOUND', { email: string }> {
constructor(email: string, message: string = `Please sign up: https://zeit.co/signup`) {
export class AccountNotFound extends NowError<
'ACCOUNT_NOT_FOUND',
{ email: string }
> {
constructor(
email: string,
message: string = `Please sign up: https://zeit.co/signup`
) {
super({
code: 'ACCOUNT_NOT_FOUND',
message,
@@ -1090,7 +1121,10 @@ export class MissingDotenvVarsError extends NowError<
}
}
export class DeploymentsRateLimited extends NowError<'DEPLOYMENTS_RATE_LIMITED', {}> {
export class DeploymentsRateLimited extends NowError<
'DEPLOYMENTS_RATE_LIMITED',
{}
> {
constructor(message: string) {
super({
code: 'DEPLOYMENTS_RATE_LIMITED',
@@ -1121,7 +1155,7 @@ export class ProjectNotFound extends NowError<'PROJECT_NOT_FOUND', {}> {
}
export class AliasDomainConfigured extends NowError<'DOMAIN_CONFIGURED', {}> {
constructor({ message }: { message: string; }) {
constructor({ message }: { message: string }) {
super({
code: 'DOMAIN_CONFIGURED',
meta: {},
@@ -1131,7 +1165,7 @@ export class AliasDomainConfigured extends NowError<'DOMAIN_CONFIGURED', {}> {
}
export class MissingBuildScript extends NowError<'MISSING_BUILD_SCRIPT', {}> {
constructor({ message }: { message: string; }) {
constructor({ message }: { message: string }) {
super({
code: 'MISSING_BUILD_SCRIPT',
meta: {},
@@ -1141,7 +1175,7 @@ export class MissingBuildScript extends NowError<'MISSING_BUILD_SCRIPT', {}> {
}
export class ConflictingFilePath extends NowError<'CONFLICTING_FILE_PATH', {}> {
constructor({ message }: { message: string; }) {
constructor({ message }: { message: string }) {
super({
code: 'CONFLICTING_FILE_PATH',
meta: {},
@@ -1150,8 +1184,11 @@ export class ConflictingFilePath extends NowError<'CONFLICTING_FILE_PATH', {}> {
}
}
export class ConflictingPathSegment extends NowError<'CONFLICTING_PATH_SEGMENT', {}> {
constructor({ message }: { message: string; }) {
export class ConflictingPathSegment extends NowError<
'CONFLICTING_PATH_SEGMENT',
{}
> {
constructor({ message }: { message: string }) {
super({
code: 'CONFLICTING_PATH_SEGMENT',
meta: {},

View File

@@ -2,7 +2,6 @@ import inquirer from 'inquirer';
import stripAnsi from 'strip-ansi';
import eraseLines from '../output/erase-lines';
// eslint-disable-next-line import/no-unassigned-import
import './patch-inquirer';
function getLength(string) {

View File

@@ -1,4 +1,3 @@
/* eslint-disable import/no-unresolved */
import path from 'path';
import pkg from '../../package.json';

View File

@@ -1,5 +1,4 @@
import test from 'ava';
import { filterPackage } from '../src/util/dev/builder-cache';
test('[dev-builder] filter install "latest", cached canary', async t => {

View File

@@ -1,5 +1,4 @@
import test from 'ava';
import devRouter from '../src/util/dev/router';
test('[dev-router] 301 redirection', async t => {

View File

@@ -1,6 +1,8 @@
import url from 'url';
import test from 'ava';
import path from 'path';
import execa from 'execa';
import fs from 'fs-extra';
import fetch from 'node-fetch';
import listen from 'async-listen';
import { request, createServer } from 'http';
@@ -9,9 +11,20 @@ import DevServer from '../src/util/dev/server';
import { installBuilders, getBuildUtils } from '../src/util/dev/builder-cache';
import parseListen from '../src/util/dev/parse-listen';
async function runNpmInstall(fixturePath) {
if (await fs.exists(path.join(fixturePath, 'package.json'))) {
return execa('yarn', ['install'], { cwd: fixturePath });
}
}
function testFixture(name, fn) {
return async t => {
let server;
const fixturePath = path.join(__dirname, 'fixtures', 'unit', name);
await runNpmInstall(fixturePath);
try {
let readyResolve;
let readyPromise = new Promise(resolve => {
@@ -29,7 +42,6 @@ function testFixture(name, fn) {
origReady(msg);
};
const fixturePath = path.join(__dirname, `fixtures/unit/${name}`);
server = new DevServer(fixturePath, { output, debug });
await server.start(0);

View File

@@ -0,0 +1,8 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
moment@^2.24.0:
version "2.24.0"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b"
integrity sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==

File diff suppressed because it is too large Load Diff

View File

@@ -34,3 +34,5 @@ node_modules
/public
/test/coverage-jest
/test/coverage-karma
!yarn.lock

View File

@@ -1,2 +1 @@
README.md
yarn.lock

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,4 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -53,11 +53,19 @@ async function exec(directory, args = []) {
});
}
async function runNpmInstall(fixturePath) {
if (await fs.exists(path.join(fixturePath, 'package.json'))) {
return execa('yarn', ['install'], { cwd: fixturePath });
}
}
function formatOutput({ stderr, stdout }) {
return `Received:\n"${stderr}"\n"${stdout}"`;
}
function testFixture(directory, opts = {}, args = []) {
async function testFixture(directory, opts = {}, args = []) {
await runNpmInstall(directory);
port = ++port;
return {
dev: execa(binaryPath, ['dev', directory, '-l', String(port), ...args], {
@@ -74,6 +82,9 @@ function testFixtureStdio(directory, fn) {
return async t => {
let dev;
const dir = fixture(directory);
await runNpmInstall(dir);
try {
port = ++port;
let output = '';
@@ -112,7 +123,10 @@ test('[now dev] validate builds', async t => {
const output = await exec(directory);
t.is(output.code, 1, formatOutput(output));
t.regex(output.stderr, /Invalid `builds` property: \[0\]\.src should be string/gm);
t.regex(
output.stderr,
/Invalid `builds` property: \[0\]\.src should be string/gm
);
});
test('[now dev] validate routes', async t => {
@@ -120,12 +134,15 @@ test('[now dev] validate routes', async t => {
const output = await exec(directory);
t.is(output.code, 1, formatOutput(output));
t.regex(output.stderr, /Invalid `routes` property: \[0\]\.src should be string/gm);
t.regex(
output.stderr,
/Invalid `routes` property: \[0\]\.src should be string/gm
);
});
test('[now dev] 00-list-directory', async t => {
const directory = fixture('00-list-directory');
const { dev, port } = testFixture(directory);
const { dev, port } = await testFixture(directory);
try {
// start `now dev` detached in child_process
@@ -147,7 +164,7 @@ test('[now dev] 00-list-directory', async t => {
test('[now dev] 01-node', async t => {
const directory = fixture('01-node');
const { dev, port } = testFixture(directory);
const { dev, port } = await testFixture(directory);
try {
// start `now dev` detached in child_process
@@ -169,7 +186,9 @@ test('[now dev] 01-node', async t => {
if (satisfies(process.version, '10.x')) {
test('[now dev] 02-angular-node', async t => {
const directory = fixture('02-angular-node');
const { dev, port } = testFixture(directory, { stdio: 'pipe' }, ['--debug']);
const { dev, port } = await testFixture(directory, { stdio: 'pipe' }, [
'--debug'
]);
let stderr = '';
@@ -256,7 +275,7 @@ test(
test('[now dev] 07-hexo-node', async t => {
const directory = fixture('07-hexo-node');
const { dev, port } = testFixture(directory);
const { dev, port } = await testFixture(directory);
try {
// start `now dev` detached in child_process
@@ -289,7 +308,7 @@ test(
test('[now dev] 10-nextjs-node', async t => {
const directory = fixture('10-nextjs-node');
const { dev, port } = testFixture(directory);
const { dev, port } = await testFixture(directory);
try {
// start `now dev` detached in child_process
@@ -309,7 +328,7 @@ test('[now dev] 10-nextjs-node', async t => {
// test('[now dev] 11-nuxtjs-node', async t => {
// const directory = fixture('11-nuxtjs-node');
// const { dev, port } = testFixture(directory);
// const { dev, port } = await testFixture(directory);
// try {
// // start `now dev` detached in child_process
@@ -330,7 +349,7 @@ test('[now dev] 10-nextjs-node', async t => {
test('[now dev] 12-polymer-node', async t => {
const directory = fixture('12-polymer-node');
const { dev, port } = testFixture(directory);
const { dev, port } = await testFixture(directory);
try {
// start `now dev` detached in child_process
@@ -350,7 +369,7 @@ test('[now dev] 12-polymer-node', async t => {
test('[now dev] 13-preact-node', async t => {
const directory = fixture('13-preact-node');
const { dev, port } = testFixture(directory);
const { dev, port } = await testFixture(directory);
try {
// start `now dev` detached in child_process
@@ -370,7 +389,7 @@ test('[now dev] 13-preact-node', async t => {
test('[now dev] 14-svelte-node', async t => {
const directory = fixture('14-svelte-node');
const { dev, port } = testFixture(directory);
const { dev, port } = await testFixture(directory);
try {
// start `now dev` detached in child_process
@@ -390,7 +409,7 @@ test('[now dev] 14-svelte-node', async t => {
// test('[now dev] 15-umijs-node', async t => {
// const directory = fixture('15-umijs-node');
// const { dev, port } = testFixture(directory);
// const { dev, port } = await testFixture(directory);
// try {
// // start `now dev` detached in child_process
@@ -409,49 +428,54 @@ test('[now dev] 14-svelte-node', async t => {
// }
// });
test('[now dev] 16-vue-node', async t => {
const directory = fixture('16-vue-node');
const { dev, port } = testFixture(directory);
if (satisfies(process.version, '^8.12.0 || >=9.7.0')) {
test('[now dev] 16-vue-node', async t => {
const directory = fixture('16-vue-node');
const { dev, port } = await testFixture(directory);
try {
// start `now dev` detached in child_process
dev.unref();
try {
// start `now dev` detached in child_process
dev.unref();
const result = await fetchWithRetry(`http://localhost:${port}`, 180);
const response = await result;
const result = await fetchWithRetry(`http://localhost:${port}`, 180);
const response = await result;
validateResponseHeaders(t, response);
validateResponseHeaders(t, response);
const body = await response.text();
t.regex(body, /Vue.js \+ Node.js API/gm);
} finally {
dev.kill('SIGTERM');
}
});
const body = await response.text();
t.regex(body, /Vue.js \+ Node.js API/gm);
} finally {
dev.kill('SIGTERM');
}
});
test('[now dev] 17-vuepress-node', async t => {
const directory = fixture('17-vuepress-node');
const { dev, port } = await testFixture(directory);
test('[now dev] 17-vuepress-node', async t => {
const directory = fixture('17-vuepress-node');
const { dev, port } = testFixture(directory);
try {
// start `now dev` detached in child_process
dev.unref();
try {
// start `now dev` detached in child_process
dev.unref();
const result = await fetchWithRetry(`http://localhost:${port}`, 180);
const response = await result;
const result = await fetchWithRetry(`http://localhost:${port}`, 180);
const response = await result;
validateResponseHeaders(t, response);
validateResponseHeaders(t, response);
const body = await response.text();
t.regex(body, /VuePress \+ Node.js API/gm);
} finally {
dev.kill('SIGTERM');
}
});
const body = await response.text();
t.regex(body, /VuePress \+ Node.js API/gm);
} finally {
dev.kill('SIGTERM');
}
});
} else {
console.log(
'Skipping `10-vue-node` and `17-vuepress-node` test since it requires Node ^8.12.0 || >=9.7.0'
);
}
test('[now dev] double slashes redirect', async t => {
const directory = fixture('01-node');
const { dev, port } = testFixture(directory);
const { dev, port } = await testFixture(directory);
try {
// start `now dev` detached in child_process
@@ -596,7 +620,7 @@ test(
test('[now dev] temporary directory listing', async t => {
const directory = fixture('temporary-directory-listing');
const { dev, port } = testFixture(directory);
const { dev, port } = await testFixture(directory);
try {
// start `now dev` detached in child_process
@@ -629,7 +653,7 @@ test('[now dev] temporary directory listing', async t => {
test('[now dev] add a `package.json` to trigger `@now/static-build`', async t => {
const directory = fixture('trigger-static-build');
const { dev, port } = testFixture(directory);
const { dev, port } = await testFixture(directory);
try {
dev.unref();
@@ -666,7 +690,7 @@ test('[now dev] add a `package.json` to trigger `@now/static-build`', async t =>
test('[now dev] no build matches warning', async t => {
const directory = fixture('no-build-matches');
const { dev } = testFixture(directory, {
const { dev } = await testFixture(directory, {
stdio: ['ignore', 'pipe', 'pipe']
});
@@ -689,33 +713,39 @@ test('[now dev] no build matches warning', async t => {
}
});
test('[now dev] do not recursivly check the path', async t => {
const directory = fixture('handle-filesystem-missing');
const { dev, port } = testFixture(directory);
if (satisfies(process.version, '^8.10.0 || ^10.13.0 || >=11.10.1')) {
test('[now dev] do not recursivly check the path', async t => {
const directory = fixture('handle-filesystem-missing');
const { dev, port } = await testFixture(directory);
try {
dev.unref();
try {
dev.unref();
{
const response = await fetchWithRetry(`http://localhost:${port}`, 180);
validateResponseHeaders(t, response);
const body = await response.text();
t.is(body.trim(), 'hello');
{
const response = await fetchWithRetry(`http://localhost:${port}`, 180);
validateResponseHeaders(t, response);
const body = await response.text();
t.is(body.trim(), 'hello');
}
{
const response = await fetch(`http://localhost:${port}/favicon.txt`);
validateResponseHeaders(t, response);
t.is(response.status, 404);
}
} finally {
dev.kill('SIGTERM');
}
{
const response = await fetch(`http://localhost:${port}/favicon.txt`);
validateResponseHeaders(t, response);
t.is(response.status, 404);
}
} finally {
dev.kill('SIGTERM');
}
});
});
} else {
console.log(
'Skipping `do not recursivly check the path` test since it requires Node ^8.10.0 || ^10.13.0 || >=11.10.1'
);
}
test('[now dev] render warning for empty cwd dir', async t => {
const directory = fixture('empty');
const { dev, port } = testFixture(directory, {
const { dev, port } = await testFixture(directory, {
stdio: ['ignore', 'pipe', 'pipe']
});

View File

View File

@@ -1,6 +0,0 @@
FROM alpine
ARG NONCE
RUN mkdir /public
RUN echo $NONCE > /public/index.html

View File

@@ -1 +0,0 @@
{"version":1,"type":"static"}

View File

@@ -1,6 +0,0 @@
FROM alpine
ARG FOO
RUN mkdir /public
RUN echo $FOO > /public/index.html

View File

@@ -1 +0,0 @@
{"version":1,"type":"static","build":{"env":{"FOO":"bar"}}}

View File

@@ -1,12 +0,0 @@
{
"version": 2,
"routes": [
{
"src": "/(.*)",
"status": 301,
"headers": {
"Location": "https://google.com"
}
}
]
}

View File

@@ -1 +0,0 @@
<span>test</span

View File

@@ -1 +0,0 @@
{"builder": 1, "type": "static"}

View File

@@ -1,6 +0,0 @@
<form action="/contact.php" method="POST">
Post message for now-builders-ci-bot-255 right here:
<textarea name="Message" />
<button>Submit</button>
</form>

View File

@@ -1,6 +0,0 @@
{
"version": 2,
"builds": [
{ "src": "*.html", "use": "@now/static" }
]
}

View File

@@ -1 +0,0 @@
<span>test alias</span

View File

@@ -1 +0,0 @@
{ "alias": "test.now.sh", "builds": [ { "src": "*.html", "use": "@now/static" } ] }

View File

@@ -1 +0,0 @@
<span>test scope email</span

View File

@@ -1 +0,0 @@
{ "scope": "now-builders-ci-bot-255@zeit.pub", "builds": [ { "src": "*.html", "use": "@now/static" } ], "version": 2 }

View File

@@ -1 +0,0 @@
<span>test scope username</span

View File

@@ -1 +0,0 @@
{ "scope": "now-builders-ci-bot-255", "builds": [ { "src": "*.html", "use": "@now/static" } ] }

View File

@@ -1,13 +0,0 @@
FROM mhart/alpine-node:latest
LABEL name "now-cli-dockerfile-now-builders-ci-bot-255"
RUN mkdir /app
WORKDIR /app
COPY package.json /app
RUN yarn
COPY index.js /app
EXPOSE 3000
CMD ["yarn", "start"]

View File

@@ -1,4 +0,0 @@
module.exports = () => ({
id: 'now-builders-ci-bot-255'
})

View File

@@ -1,3 +0,0 @@
{
"version": 1
}

View File

@@ -1,12 +0,0 @@
{
"name": "node-test-now-builders-ci-bot-255",
"main": "index.js",
"license": "MIT",
"scripts": {
"start": "micro"
},
"dependencies": {
"micro": "latest"
}
}

View File

@@ -1 +0,0 @@
{"scripts":{"build":"echo hello && exit 1"}}

View File

@@ -1,4 +0,0 @@
module.exports = () => ({
id: 'now-builders-ci-bot-255'
})

View File

@@ -1,3 +0,0 @@
{
"version": 1
}

View File

@@ -1,12 +0,0 @@
{
"name": "node-test-now-builders-ci-bot-255",
"main": "index.js",
"license": "MIT",
"scripts": {
"start": "micro"
},
"dependencies": {
"micro": "latest"
}
}

View File

@@ -1,5 +0,0 @@
{
"scripts": {
"dev": "now dev"
}
}

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