Compare commits

..

19 Commits

Author SHA1 Message Date
Steven
b0e4f2590d Publish Stable
- @now/cgi@1.0.2
 - @now/go@1.0.2
 - @now/python@1.1.2
2020-02-05 15:09:14 -05:00
Leo Lamprecht
f0d58eac8c Remove now dev suggestion (#3748) 2020-02-05 20:50:21 +01:00
Steven
dae830d2b6 [examples] Fix hugo theme (#3746)
The Hugo theme was lost when transferring from `zeit/now-examples` to `zeit/now`.

This PR fixes the `.gitignore` file to include the `dist` directory and override our root `.gitignore`.
2020-02-05 19:30:08 +00:00
dependabot[bot]
e3071e4e29 Bump mixin-deep from 1.3.1 to 1.3.2 in /packages/now-cgi (#3736)
Bumps [mixin-deep](https://github.com/jonschlinkert/mixin-deep) from 1.3.1 to 1.3.2.
- [Release notes](https://github.com/jonschlinkert/mixin-deep/releases)
- [Commits](https://github.com/jonschlinkert/mixin-deep/compare/1.3.1...1.3.2)

Signed-off-by: dependabot[bot] <support@github.com>
2020-02-05 09:52:08 -05:00
Steven
073d7ece23 Publish Canary
- @now/build-utils@1.3.9-canary.0
 - now@17.0.0-canary.34
2020-02-05 08:29:10 -05:00
Andy Bitz
071258ba33 Publish Stable
- @now/build-utils@1.3.8
2020-02-05 03:27:31 +01:00
Andy
c0e00dc69a [now-build-utils] Fix build script check (#3743) 2020-02-05 03:27:17 +01:00
luc
6e5c136337 Publish Canary
- now@17.0.0-canary.33
2020-02-05 02:26:53 +01:00
Steven
60428cd4cf [now-cli] Bump @zeit/fun to 0.11.2 (#3741)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-02-05 02:20:54 +01:00
Luc
c6b9d80eec Fix now cli breaking tests (#3742) 2020-02-05 02:17:43 +01:00
Luc
953bdc10e5 [now-cli] Fix prompts and fetch team on windows (#3740)
* fix fetch on windows

* update inquirer

Co-authored-by: Leo Lamprecht <mindrun@icloud.com>
2020-02-05 01:58:49 +01:00
Andy Bitz
becdbd2136 Publish Stable
- @now/build-utils@1.3.7
2020-02-05 01:52:02 +01:00
Luc
da9bb31259 [now-cli] Handle no framework detected case (#3738)
* handle no framework detected case

* remove related test

* simplify

Co-authored-by: Leo Lamprecht <mindrun@icloud.com>
2020-02-05 01:49:13 +01:00
Luc
8cbf036921 [now-cli] Do not prompt for root directory when project is linked (#3737)
* do not prompt for root directory when linked

* run tests

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
Co-authored-by: Leo Lamprecht <mindrun@icloud.com>
2020-02-05 01:48:52 +01:00
Andy
8f66e4a308 [now-build-utils] Handle empty buildCommand and outputDirectory (#3739)
* [now-build-utils] Handle empty buildCommand and outputDirectory

* Update comment
2020-02-05 01:47:54 +01:00
Luc
9627b612f2 [now-cli] Do not show spinners with --debug (#3732)
* create output.wait and use it

* fix printing "ended" multiple times

* update more `wait` -> `output.spinner`

* timeout -> delay
2020-02-04 23:23:37 +01:00
Luc
8a9ded6d61 [now-cli] Slugify suggested project name (#3733)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-02-04 22:29:07 +01:00
Steven
d89c772bd5 [now-build-utils] Exclude _test.go files (#3735)
Typically, Go tests are side-by-side with their source files in a `_test.go`.

The Go documentation says the following:

> To write a new test suite, create a file whose name ends _test.go that contains the TestXxx functions as described here. Put the file in the same package as the one being tested. The file will be excluded from regular package builds but will be included when the “go test” command is run. [View Docs](https://golang.org/pkg/testing/)

This PR excludes the test files from being turned into Serverless Functions.
2020-02-04 21:11:26 +00:00
Steven
32137586b9 Publish Stable
- @now/static-build@0.14.11
2020-02-04 15:10:33 -05:00
47 changed files with 378 additions and 262 deletions

View File

@@ -16,7 +16,6 @@ To quickly start a new project, run the following commands:
```
now init # Pick an example project to clone
cd <PROJECT> # Change directory to the newly created project
now dev # Run locally during development
now # Deploy to the cloud
```

View File

@@ -28,3 +28,5 @@ npm-debug.log
/junit.xml
partials/structure/stylesheet.html
!dist

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
!function(n){function t(e){if(r[e])return r[e].exports;var o=r[e]={i:e,l:!1,exports:{}};return n[e].call(o.exports,o,o.exports,t),o.l=!0,o.exports}var r={};t.m=n,t.c=r,t.i=function(n){return n},t.d=function(n,r,e){t.o(n,r)||Object.defineProperty(n,r,{configurable:!1,enumerable:!0,get:e})},t.n=function(n){var r=n&&n.__esModule?function(){return n.default}:function(){return n};return t.d(r,"a",r),r},t.o=function(n,t){return Object.prototype.hasOwnProperty.call(n,t)},t.p="",t(t.s=1)}([function(n,t){},function(n,t,r){"use strict";var e=r(0);!function(n){n&&n.__esModule}(e)}]);

View File

@@ -1,6 +1,6 @@
{
"name": "@now/build-utils",
"version": "1.3.7-canary.2",
"version": "1.3.9-canary.0",
"license": "MIT",
"main": "./dist/index.js",
"types": "./dist/index.d.js",

View File

@@ -28,7 +28,7 @@ function getApiBuilders({ tag }: Pick<Options, 'tag'> = {}): Builder[] {
return [
{ src: 'api/**/*.js', use: `@now/node${withTag}`, config },
{ src: 'api/**/*.ts', use: `@now/node${withTag}`, config },
{ src: 'api/**/*.go', use: `@now/go${withTag}`, config },
{ src: 'api/**/!(*_test).go', use: `@now/go${withTag}`, config },
{ src: 'api/**/*.py', use: `@now/python${withTag}`, config },
{ src: 'api/**/*.rb', use: `@now/ruby${withTag}`, config },
];
@@ -423,10 +423,18 @@ export async function detectBuilders(
let frontendBuilder: Builder | null = null;
if (hasBuildScript(pkg) || buildCommand || framework) {
// Everything will be static if either is an empty string
const ignoreBuild = buildCommand === '' || outputDirectory === '';
if (!ignoreBuild && (hasBuildScript(pkg) || buildCommand || framework)) {
frontendBuilder = detectFrontBuilder(pkg, builders, files, options);
} else {
if (!options.ignoreBuildScript && pkg && builders.length === 0) {
if (
!ignoreBuild &&
!options.ignoreBuildScript &&
pkg &&
builders.length === 0
) {
// We only show this error when there are no api builders
// since the dependencies of the pkg could be used for those
errors.push({
@@ -442,7 +450,9 @@ export async function detectBuilders(
// when there are no build steps
const outDir = outputDirectory || 'public';
if (hasDirectory(outDir, files)) {
// If `outputDirectory` is an empty string,
// we'll default to the root directory.
if (hasDirectory(outDir, files) && outputDirectory !== '') {
frontendBuilder = {
use: '@now/static',
src: `${outDir}/**/*`,

View File

@@ -151,6 +151,27 @@ describe('Test `detectBuilders`', () => {
expect(builders!.length).toBe(2);
});
it('api go with test files', async () => {
const files = [
'api/index.go',
'api/index_test.go',
'api/test.go',
'api/testing_another.go',
'api/readme.md',
'api/config/staging.go',
'api/config/staging_test.go',
'api/config/production.go',
'api/config/production_test.go',
'api/src/controllers/health.go',
'api/src/controllers/user.module.go',
'api/src/controllers/user.module_test.go',
];
const { builders } = await detectBuilders(files);
expect(builders!.length).toBe(7);
expect(builders!.some(b => b.src.endsWith('_test.go'))).toBe(false);
});
it('just public', async () => {
const files = ['public/index.html', 'public/favicon.ico', 'README.md'];
@@ -745,6 +766,53 @@ describe('Test `detectBuilders`', () => {
},
]);
});
it('All static if `buildCommand` is an empty string', async () => {
const files = ['index.html'];
const projectSettings = { buildCommand: '' };
const { builders, errors } = await detectBuilders(files, null, {
projectSettings,
});
expect(errors).toBe(null);
expect(builders).toBe(null);
});
it('All static if `outputDirectory` is an empty string', async () => {
const files = ['index.html'];
const projectSettings = { outputDirectory: '' };
const { builders, errors } = await detectBuilders(files, null, {
projectSettings,
});
expect(errors).toBe(null);
expect(builders).toBe(null);
});
it('All static if `buildCommand` is an empty string with an `outputDirectory`', async () => {
const files = ['out/index.html'];
const projectSettings = { buildCommand: '', outputDirectory: 'out' };
const { builders, errors } = await detectBuilders(files, null, {
projectSettings,
});
expect(errors).toBe(null);
expect(builders![0]!.use).toBe('@now/static');
expect(builders![0]!.src).toBe('out/**/*');
});
it('do not require build script when `buildCommand` is an empty string', async () => {
const files = ['index.html', 'about.html', 'package.json'];
const projectSettings = { buildCommand: '', outputDirectory: '' };
const pkg = {
scripts: {
build: 'false',
},
};
const { builders, errors } = await detectBuilders(files, pkg, {
projectSettings,
});
expect(builders).toBe(null);
expect(errors).toBe(null);
});
});
it('Test `detectRoutes`', async () => {

View File

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

View File

@@ -15,7 +15,7 @@
"@zeit/best@0.4.3":
version "0.4.3"
resolved "http://registry.npmjs.org/@zeit/best/-/best-0.4.3.tgz#eaebdfa8b24121a97b1753501ea8c9330d549b30"
resolved "https://registry.npmjs.org/@zeit/best/-/best-0.4.3.tgz#eaebdfa8b24121a97b1753501ea8c9330d549b30"
dependencies:
arg "1.0.0"
chalk "2.3.1"
@@ -144,7 +144,7 @@ call-me-maybe@^1.0.1:
chalk@2.3.1:
version "2.3.1"
resolved "http://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz#523fe2678aec7b04e8041909292fe8b17059b796"
resolved "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz#523fe2678aec7b04e8041909292fe8b17059b796"
dependencies:
ansi-styles "^3.2.0"
escape-string-regexp "^1.0.5"
@@ -585,8 +585,8 @@ minimatch@^3.0.4:
brace-expansion "^1.1.7"
mixin-deep@^1.2.0:
version "1.3.1"
resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.1.tgz#a49e7268dce1a0d9698e45326c5626df3543d0fe"
version "1.3.2"
resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566"
dependencies:
for-in "^1.0.2"
is-extendable "^1.0.1"
@@ -704,7 +704,7 @@ rmfr@2.0.0:
safe-regex@^1.1.0:
version "1.1.0"
resolved "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e"
resolved "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e"
dependencies:
ret "~0.1.10"

View File

@@ -1,6 +1,6 @@
{
"name": "now",
"version": "17.0.0-canary.32",
"version": "17.0.0-canary.34",
"preferGlobal": true,
"license": "Apache-2.0",
"description": "The command-line interface for Now",
@@ -63,6 +63,7 @@
},
"devDependencies": {
"@sentry/node": "5.5.0",
"@sindresorhus/slugify": "0.10.0",
"@types/ansi-escapes": "3.0.0",
"@types/ansi-regex": "4.0.0",
"@types/async-retry": "1.2.1",
@@ -92,7 +93,7 @@
"@types/which": "1.3.1",
"@types/write-json-file": "2.2.1",
"@zeit/dockerignore": "0.0.5",
"@zeit/fun": "0.11.0",
"@zeit/fun": "0.11.2",
"@zeit/ncc": "0.18.5",
"@zeit/source-map-support": "0.6.2",
"ajv": "6.10.2",
@@ -131,7 +132,7 @@
"http-proxy": "1.17.0",
"ignore": "4.0.6",
"ini": "1.3.4",
"inquirer": "3.3.0",
"inquirer": "7.0.4",
"is-port-reachable": "3.0.0",
"is-url": "1.2.2",
"jaro-winkler": "0.2.8",

View File

@@ -8,12 +8,11 @@ import getAliases from '../../util/alias/get-aliases';
import getScope from '../../util/get-scope.ts';
import stamp from '../../util/output/stamp.ts';
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
config,
} = ctx;
const { currentTeam } = config;
const { apiUrl } = ctx;
@@ -22,7 +21,7 @@ export default async function ls(ctx, opts, args, output) {
apiUrl,
token,
currentTeam,
debug: debugEnabled
debug: debugEnabled,
});
let contextName = null;
@@ -51,7 +50,7 @@ export default async function ls(ctx, opts, args, output) {
return 1;
}
cancelWait = wait(
cancelWait = output.spinner(
args[0]
? `Fetching alias details for "${args[0]}" under ${chalk.bold(
contextName
@@ -112,13 +111,13 @@ function printAliasTable(aliases) {
? a.deployment.url
: chalk.gray(''),
a.alias,
ms(Date.now() - new Date(a.created))
])
ms(Date.now() - new Date(a.created)),
]),
],
{
align: ['l', 'l', 'r'],
hsep: ' '.repeat(4),
stringLength: strlen
stringLength: strlen,
}
).replace(/^/gm, ' ')}\n\n`;
}
@@ -130,13 +129,13 @@ function printPathAliasTable(rules) {
rules.map(rule => [
rule.pathname ? rule.pathname : chalk.cyan('[fallthrough]'),
rule.method ? rule.method : '*',
rule.dest
rule.dest,
])
),
{
align: ['l', 'l', 'l', 'l'],
hsep: ' '.repeat(6),
stringLength: strlen
stringLength: strlen,
}
).replace(/^(.*)/gm, ' $1')}\n`;
}

View File

@@ -21,7 +21,7 @@ export default async function({ creditCards, clear = false, contextName }) {
name: {
label: rightPad('Full Name', 12),
placeholder: 'John Appleseed',
validateValue: data => data.trim().length > 0
validateValue: data => data.trim().length > 0,
},
cardNumber: {
@@ -36,7 +36,7 @@ export default async function({ creditCards, clear = false, contextName }) {
return false;
}
return ccValidator.isValidCardNumber(data, type);
}
},
},
ccv: {
@@ -46,7 +46,7 @@ export default async function({ creditCards, clear = false, contextName }) {
validateValue: data => {
const brand = state.cardNumber.brand.toLowerCase();
return ccValidator.doesCvvMatchType(data, brand);
}
},
},
expDate: {
@@ -54,8 +54,8 @@ export default async function({ creditCards, clear = false, contextName }) {
mask: 'expDate',
placeholder: 'mm / yyyy',
middleware: expDateMiddleware,
validateValue: data => !ccValidator.isExpired(...data.split(' / '))
}
validateValue: data => !ccValidator.isExpired(...data.split(' / ')),
},
};
async function render() {
@@ -80,7 +80,7 @@ export default async function({ creditCards, clear = false, contextName }) {
mask: piece.mask,
validateKeypress: piece.validateKeypress,
validateValue: piece.validateValue,
autoComplete: piece.autoComplete
autoComplete: piece.autoComplete,
});
piece.value = result;
@@ -135,7 +135,7 @@ export default async function({ creditCards, clear = false, contextName }) {
name: state.name.value,
cardNumber: state.cardNumber.value,
ccv: state.ccv.value,
expDate: state.expDate.value
expDate: state.expDate.value,
});
stopSpinner();
@@ -156,9 +156,9 @@ export default async function({ creditCards, clear = false, contextName }) {
stopSpinner();
const linesToClear = state.error ? 15 : 14;
process.stdout.write(ansiEscapes.eraseLines(linesToClear));
state.error = `${chalk.red(
'> Error!'
)} ${err.message} Please make sure the info is correct`;
state.error = `${chalk.red('> Error!')} ${
err.message
} Please make sure the info is correct`;
await render();
}
}

View File

@@ -5,7 +5,6 @@ import Now from '../../util';
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';
@@ -110,7 +109,7 @@ async function add(
(res, item) => res.concat(item.split(',')),
[]
);
const cancelWait = wait(
const cancelWait = output.spinner(
`Generating a certificate for ${chalk.bold(cns.join(', '))}`
);

View File

@@ -404,6 +404,7 @@ export default async function main(
}
org = await selectOrg(
output,
'Which scope do you want to deploy to?',
client,
ctx.config.currentTeam,
@@ -427,8 +428,10 @@ export default async function main(
if (typeof projectOrNewProjectName === 'string') {
newProjectName = projectOrNewProjectName;
rootDirectory = await inputRootDirectory(path, output, autoConfirm);
} else {
project = projectOrNewProjectName;
rootDirectory = project.rootDirectory;
// we can already link the project
await linkFolderToProject(
@@ -443,8 +446,6 @@ export default async function main(
);
status = 'linked';
}
rootDirectory = await inputRootDirectory(path, output, autoConfirm);
}
const sourcePath = rootDirectory ? join(path, rootDirectory) : path;
@@ -455,7 +456,9 @@ export default async function main(
output,
path,
sourcePath,
project ? `To change your project settings, go to https://zeit.co/${org.slug}/${project.name}/settings` : ''
project
? `To change your project settings, go to https://zeit.co/${org.slug}/${project.name}/settings`
: ''
)) === false
) {
return 1;

View File

@@ -13,7 +13,6 @@ import param from '../../util/output/param';
import promptBool from '../../util/input/prompt-bool';
import purchaseDomain from '../../util/domains/purchase-domain';
import stamp from '../../util/output/stamp';
import wait from '../../util/output/wait';
type Options = {
'--debug': boolean;
@@ -27,7 +26,7 @@ export default async function buy(
) {
const {
authConfig: { token },
config
config,
} = ctx;
const { currentTeam } = config;
const { apiUrl } = ctx;
@@ -100,7 +99,7 @@ export default async function buy(
let buyResult;
const purchaseStamp = stamp();
const stopPurchaseSpinner = wait('Purchasing');
const stopPurchaseSpinner = output.spinner('Purchasing');
try {
buyResult = await purchaseDomain(client, domainName, price);

View File

@@ -9,7 +9,6 @@ import listInput from '../../util/input/list';
import listItem from '../../util/output/list-item';
import promptBool from '../../util/input/prompt-bool';
import toHumanPath from '../../util/humanize-path';
import wait from '../../util/output/wait';
import { Output } from '../../util/output';
import { NowContext } from '../../types';
import success from '../../util/output/success';
@@ -24,10 +23,10 @@ type Options = {
};
type Example = {
name: string,
visible: boolean,
suggestions: string[]
}
name: string;
visible: boolean;
suggestions: string[];
};
const EXAMPLE_API = 'https://now-example-files.zeit.sh';
@@ -40,7 +39,7 @@ export default async function init(
const [name, dir] = args;
const force = opts['-f'] || opts['--force'];
const examples = await fetchExampleList();
const examples = await fetchExampleList(output);
if (!examples) {
throw new Error(`Could not fetch example list.`);
@@ -56,22 +55,22 @@ export default async function init(
return 0;
}
return extractExample(chosen, dir, force);
return extractExample(output, chosen, dir, force);
}
if (exampleList.includes(name)) {
return extractExample(name, dir, force);
return extractExample(output, name, dir, force);
}
const oldExample = examples.find(x => !x.visible && x.name === name);
if (oldExample) {
return extractExample(name, dir, force, 'v1');
return extractExample(output, name, dir, force, 'v1');
}
const found = await guess(exampleList, name);
if (typeof found === 'string') {
return extractExample(found, dir, force);
return extractExample(output, found, dir, force);
}
console.log(info('No changes made.'));
@@ -81,8 +80,8 @@ export default async function init(
/**
* Fetch example list json
*/
async function fetchExampleList() {
const stopSpinner = wait('Fetching examples');
async function fetchExampleList(output: Output) {
const stopSpinner = output.spinner('Fetching examples');
const url = `${EXAMPLE_API}/v2/list.json`;
try {
@@ -93,7 +92,7 @@ async function fetchExampleList() {
throw new Error(`Failed fetching list.json (${resp.statusText}).`);
}
return await resp.json() as Example[];
return (await resp.json()) as Example[];
} catch (e) {
stopSpinner();
}
@@ -106,22 +105,28 @@ async function chooseFromDropdown(message: string, exampleList: string[]) {
const choices = exampleList.map(name => ({
name,
value: name,
short: name
short: name,
}));
return listInput({
message,
separator: false,
choices
choices,
});
}
/**
* Extract example to directory
*/
async function extractExample(name: string, dir: string, force?: boolean, ver: string = 'v2') {
async function extractExample(
output: Output,
name: string,
dir: string,
force?: boolean,
ver: string = 'v2'
) {
const folder = prepareFolder(process.cwd(), dir || name, force);
const stopSpinner = wait(`Fetching ${name}`);
const stopSpinner = output.spinner(`Fetching ${name}`);
const url = `${EXAMPLE_API}/${ver}/download/${name}.tar.gz`;

View File

@@ -9,7 +9,6 @@ import createOutput from '../util/output';
import Now from '../util';
import logo from '../util/output/logo';
import elapsed from '../util/output/elapsed.ts';
import wait from '../util/output/wait';
import { handleError } from '../util/error';
import strlen from '../util/strlen.ts';
import Client from '../util/client.ts';
@@ -79,13 +78,16 @@ export default async function main(ctx) {
return 1;
}
const { authConfig: { token }, config } = ctx;
const {
authConfig: { token },
config,
} = ctx;
const { currentTeam } = config;
const client = new Client({
apiUrl,
token,
currentTeam,
debug: debugEnabled
debug: debugEnabled,
});
let contextName = null;
@@ -104,7 +106,7 @@ export default async function main(ctx) {
// resolve the deployment, since we might have been given an alias
const depFetchStart = Date.now();
const cancelWait = wait(
const cancelWait = output.spinner(
`Fetching deployment "${id}" in ${chalk.bold(contextName)}`
);
@@ -140,7 +142,7 @@ export default async function main(ctx) {
limits,
version,
routes,
readyState
readyState,
} = deployment;
const isBuilds = version === 2;
@@ -159,7 +161,7 @@ export default async function main(ctx) {
)}/events?types=event`
)
),
isBuilds ? now.fetch(buildsUrl) : { builds: [] }
isBuilds ? now.fetch(buildsUrl) : { builds: [] },
]);
cancelWait();
@@ -174,7 +176,9 @@ export default async function main(ctx) {
print(` ${chalk.cyan('version')}\t${version}\n`);
print(` ${chalk.cyan('id')}\t\t${finalId}\n`);
print(` ${chalk.cyan('name')}\t${name}\n`);
print(` ${chalk.cyan('readyState')}\t${stateString(state || readyState)}\n`);
print(
` ${chalk.cyan('readyState')}\t${stateString(state || readyState)}\n`
);
if (!isBuilds) {
print(` ${chalk.cyan('type')}\t${type}\n`);
}
@@ -255,7 +259,7 @@ export default async function main(ctx) {
`${table(t, {
align: ['l', 'c', 'c', 'c'],
hsep: ' '.repeat(8),
stringLength: strlen
stringLength: strlen,
}).replace(/^(.*)/gm, ' $1')}\n`
);
print('\n');
@@ -269,9 +273,9 @@ export default async function main(ctx) {
events.forEach(data => {
if (!data.event) return; // keepalive
print(
` ${chalk.gray(
new Date(data.created).toISOString()
)} ${data.event} ${getEventMetadata(data)}\n`
` ${chalk.gray(new Date(data.created).toISOString())} ${
data.event
} ${getEventMetadata(data)}\n`
);
});
print('\n');

View File

@@ -8,7 +8,6 @@ import chalk from 'chalk';
import ua from '../util/ua.ts';
import getArgs from '../util/get-args';
import error from '../util/output/error';
import wait from '../util/output/wait';
import highlight from '../util/output/highlight';
import ok from '../util/output/ok';
import cmd from '../util/output/cmd.ts';
@@ -191,7 +190,7 @@ const login = async ctx => {
let verificationToken;
let securityCode;
stopSpinner = wait('Sending you an email');
stopSpinner = output.spinner('Sending you an email');
try {
const data = await executeLogin(apiUrl, email);
@@ -216,7 +215,7 @@ const login = async ctx => {
)}.\n`
);
stopSpinner = wait('Waiting for your confirmation');
stopSpinner = output.spinner('Waiting for your confirmation');
let token;

View File

@@ -6,7 +6,6 @@ import logo from '../util/output/logo';
import elapsed from '../util/output/elapsed.ts';
import { maybeURL, normalizeURL, parseInstanceURL } from '../util/url';
import printEvents from '../util/events';
import wait from '../util/output/wait';
import Client from '../util/client.ts';
import getScope from '../util/get-scope.ts';
@@ -165,7 +164,7 @@ export default async function main(ctx) {
const id = deploymentIdOrURL;
const depFetchStart = Date.now();
const cancelWait = wait(
const cancelWait = output.spinner(
`Fetching deployment "${id}" in ${chalk.bold(contextName)}`
);
@@ -287,12 +286,12 @@ function printLogShort(log) {
data = JSON.stringify(obj, null, 2);
} else {
data = (log.text || '')
.replace(/\n$/, '')
.replace(/^\n/, '')
// eslint-disable-next-line no-control-regex
.replace(/\x1b\[1000D/g, '')
.replace(/\x1b\[0K/g, '')
.replace(/\x1b\[1A/g, '');
.replace(/\n$/, '')
.replace(/^\n/, '')
// eslint-disable-next-line no-control-regex
.replace(/\x1b\[1000D/g, '')
.replace(/\x1b\[0K/g, '')
.replace(/\x1b\[1A/g, '');
if (/warning/i.test(data)) {
data = chalk.yellow(data);
} else if (log.type === 'stderr') {

View File

@@ -6,7 +6,6 @@ import table from 'text-table';
import Now from '../util';
import getAliases from '../util/alias/get-aliases';
import createOutput from '../util/output';
import wait from '../util/output/wait';
import logo from '../util/output/logo';
import cmd from '../util/output/cmd.ts';
import elapsed from '../util/output/elapsed.ts';
@@ -132,7 +131,7 @@ export default async function main(ctx) {
throw err;
}
const cancelWait = wait(
const cancelWait = output.spinner(
`Fetching deployment(s) ${ids
.map(id => `"${id}"`)
.join(' ')} in ${chalk.bold(contextName)}`

View File

@@ -57,7 +57,7 @@ export default async function({ apiUrl, token, teams, config }) {
validateKeypress: validateSlugKeypress,
initialValue: slug,
valid: team,
forceLowerCase: true
forceLowerCase: true,
});
} catch (err) {
if (err.message === 'USER_ABORT') {
@@ -95,7 +95,7 @@ export default async function({ apiUrl, token, teams, config }) {
try {
name = await textInput({
label: `- ${teamNamePrefix}`,
validateKeypress: validateNameKeypress
validateKeypress: validateNameKeypress,
});
} catch (err) {
if (err.message === 'USER_ABORT') {
@@ -153,7 +153,7 @@ export default async function({ apiUrl, token, teams, config }) {
introMsg: 'Invite your teammates! When done, press enter on an empty field',
noopMsg: `You can invite teammates later by running ${cmd(
'now teams invite'
)}`
)}`,
});
gracefulExit();

View File

@@ -30,7 +30,7 @@ const domains = Array.from(
'inbox.com',
'mail.com',
'gmx.com',
'icloud.com'
'icloud.com',
])
);
@@ -56,17 +56,15 @@ const emailAutoComplete = (value, teamSlug) => {
return false;
};
export default async function(
{
teams,
args,
config,
introMsg,
noopMsg = 'No changes made',
apiUrl,
token
} = {}
) {
export default async function({
teams,
args,
config,
introMsg,
noopMsg = 'No changes made',
apiUrl,
token,
} = {}) {
const { currentTeam: currentTeamId } = config;
const stopSpinner = wait('Fetching teams');
@@ -86,7 +84,11 @@ export default async function(
if (!currentTeam) {
// We specifically need a team scope here
let err = `You can't run this command under ${param(user.username || user.email)}.\nPlease select a team scope using ${cmd('now switch')} or use ${cmd('--scope')}`;
let err = `You can't run this command under ${param(
user.username || user.email
)}.\nPlease select a team scope using ${cmd('now switch')} or use ${cmd(
'--scope'
)}`;
return fatalError(err);
}
@@ -107,7 +109,9 @@ export default async function(
userInfo = res.name || res.username;
} catch (err) {
if (err.code === 'user_not_found') {
console.error(error(`No user exists with the email address "${email}".`));
console.error(
error(`No user exists with the email address "${email}".`)
);
return 1;
}
@@ -115,7 +119,11 @@ export default async function(
}
stopSpinner();
console.log(`${chalk.cyan(chars.tick)} ${email}${userInfo ? ` (${userInfo})` : ''} ${elapsed()}`);
console.log(
`${chalk.cyan(chars.tick)} ${email}${
userInfo ? ` (${userInfo})` : ''
} ${elapsed()}`
);
} else {
console.log(`${chalk.red(`${email}`)} ${chalk.gray('[invalid]')}`);
}
@@ -135,7 +143,7 @@ export default async function(
email = await textInput({
label: `- ${inviteUserPrefix}`,
validateValue: validateEmail,
autoComplete: value => emailAutoComplete(value, currentTeam.slug)
autoComplete: value => emailAutoComplete(value, currentTeam.slug),
});
} catch (err) {
if (err.message !== 'USER_ABORT') {
@@ -149,7 +157,10 @@ export default async function(
stopSpinner = wait(inviteUserPrefix + email);
try {
// eslint-disable-next-line no-await-in-loop
const { name, username } = await teams.inviteUser({ teamId: currentTeam.id, email });
const { name, username } = await teams.inviteUser({
teamId: currentTeam.id,
email,
});
stopSpinner();
const userInfo = name || username;
email = `${email}${userInfo ? ` (${userInfo})` : ''} ${elapsed()}`;

View File

@@ -27,20 +27,20 @@ export default async function({ teams, config, apiUrl, token }) {
if (accountIsCurrent) {
currentTeam = {
slug: user.username || user.email
slug: user.username || user.email,
};
}
const teamList = list.map(({ slug, name }) => ({
name,
value: slug,
current: slug === currentTeam.slug ? chars.tick : ''
current: slug === currentTeam.slug ? chars.tick : '',
}));
teamList.unshift({
name: user.email,
value: user.username || user.email,
current: (accountIsCurrent && chars.tick) || ''
current: (accountIsCurrent && chars.tick) || '',
});
// Let's bring the current team to the beginning of the list

View File

@@ -3,7 +3,6 @@ import { Output } from '../output';
import * as ERRORS from '../errors-ts';
import Client from '../client';
import createCertForAlias from '../certs/create-cert-for-alias';
import wait from '../output/wait';
export type AliasRecord = {
uid: string;
@@ -20,7 +19,7 @@ export default async function createAlias(
alias: string,
externalDomain: boolean
) {
let cancelMessage = wait(`Creating alias`);
let cancelMessage = output.spinner(`Creating alias`);
const result = await performCreateAlias(
client,
contextName,
@@ -41,7 +40,7 @@ export default async function createAlias(
return cert;
}
let cancelMessage = wait(`Creating alias`);
let cancelMessage = output.spinner(`Creating alias`);
const secondTry = await performCreateAlias(
client,
contextName,
@@ -66,7 +65,7 @@ async function performCreateAlias(
`/now/deployments/${deployment.uid}/aliases`,
{
method: 'POST',
body: { alias }
body: { alias },
}
);
} catch (error) {
@@ -77,7 +76,10 @@ async function performCreateAlias(
return { uid: error.uid, alias: error.alias } as AliasRecord;
}
if (error.code === 'deployment_not_found') {
return new ERRORS.DeploymentNotFound({ context: contextName, id: deployment.uid });
return new ERRORS.DeploymentNotFound({
context: contextName,
id: deployment.uid,
});
}
if (error.code === 'gone') {
return new ERRORS.DeploymentFailedAliasImpossible();
@@ -94,7 +96,7 @@ async function performCreateAlias(
}
}
if (error.status === 400) {
return new ERRORS.DeploymentNotReady({url: deployment.url })
return new ERRORS.DeploymentNotReady({ url: deployment.url });
}
throw error;

View File

@@ -3,7 +3,6 @@ import chalk from 'chalk';
import getAppLastDeployment from '../deploy/get-app-last-deployment';
import getAppName from '../deploy/get-app-name';
import fetchDeploymentByIdOrHost from '../deploy/get-deployment-by-id-or-host';
import wait from '../output/wait';
import Client from '../client';
import { Output } from '../output';
import { User, Config } from '../../types';
@@ -17,7 +16,7 @@ export default async function getDeploymentForAlias(
contextName: string,
localConfig: Config
) {
const cancelWait = wait(
const cancelWait = output.spinner(
`Fetching deployment to alias in ${chalk.bold(contextName)}`
);

View File

@@ -4,7 +4,6 @@ import * as ERRORS from '../errors-ts';
import Client from '../client';
import createCertForAlias from '../certs/create-cert-for-alias';
import setupDomain from '../domains/setup-domain';
import wait from '../output/wait';
const NOW_SH_REGEX = /\.now\.sh$/;
@@ -34,6 +33,7 @@ export default async function upsertPathAlias(
}
const result = await performUpsertPathAlias(
output,
client,
alias,
rules,
@@ -51,23 +51,26 @@ export default async function upsertPathAlias(
return cert;
}
return performUpsertPathAlias(client, alias, rules, contextName);
return performUpsertPathAlias(output, client, alias, rules, contextName);
}
return result;
}
async function performUpsertPathAlias(
output: Output,
client: Client,
alias: string,
rules: PathRule[],
contextName: string
) {
const cancelMessage = wait(`Updating path alias rules for ${alias}`);
const cancelMessage = output.spinner(
`Updating path alias rules for ${alias}`
);
try {
const record = await client.fetch<AliasRecord>(`/now/aliases`, {
body: { alias, rules },
method: 'POST'
method: 'POST',
});
cancelMessage();
return record;

View File

@@ -5,7 +5,6 @@ import createCertForCns from './create-cert-for-cns';
import getWildcardCnsForAlias from './get-wildcard-cns-for-alias';
import joinWords from '../output/join-words';
import stamp from '../output/stamp';
import wait from '../output/wait';
export default async function createCertificateForAlias(
output: Output,
@@ -15,7 +14,7 @@ export default async function createCertificateForAlias(
shouldBeWildcard: boolean
) {
const cns = shouldBeWildcard ? getWildcardCnsForAlias(alias) : [alias];
const cancelMessage = wait(`Generating a certificate...`);
const cancelMessage = output.spinner(`Generating a certificate...`);
const certStamp = stamp();
const cert = await createCertForCns(client, cns, context);
if (cert instanceof NowError) {
@@ -25,9 +24,9 @@ export default async function createCertificateForAlias(
cancelMessage();
output.log(
`Certificate for ${joinWords(
cert.cns
)} (${cert.uid}) created ${certStamp()}`
`Certificate for ${joinWords(cert.cns)} (${
cert.uid
}) created ${certStamp()}`
);
return cert;
}

View File

@@ -4,7 +4,6 @@ import { Output } from '../output';
import Client from '../client';
import createCertForCns from '../certs/create-cert-for-cns';
import setupDomain from '../domains/setup-domain';
import wait from '../output/wait';
import { InvalidDomain } from '../errors-ts';
export default async function generateCertForDeploy(
@@ -23,7 +22,9 @@ export default async function generateCertForDeploy(
return new InvalidDomain(deployURL);
}
const cancelSetupWait = wait(`Setting custom suffix domain ${domain}`);
const cancelSetupWait = output.spinner(
`Setting custom suffix domain ${domain}`
);
const result = await setupDomain(output, client, domain, contextName);
cancelSetupWait();
if (result instanceof NowError) {
@@ -31,7 +32,7 @@ export default async function generateCertForDeploy(
}
// Generate the certificate with the given parameters
const cancelCertWait = wait(
const cancelCertWait = output.spinner(
`Generating a wildcard certificate for ${domain}`
);
const cert = await createCertForCns(

View File

@@ -6,7 +6,6 @@ import {
DeploymentOptions,
NowClientOptions,
} from 'now-client';
import wait from '../output/wait';
import { Output } from '../output';
// @ts-ignore
import Now from '../../util';
@@ -106,7 +105,7 @@ export default async function processDeployment({
let buildSpinner = null;
let deploySpinner = null;
let deployingSpinner = wait(
let deployingSpinner = output.spinner(
isSettingUpProject
? `Setting up project`
: `Deploying ${chalk.bold(`${org.slug}/${projectName}`)}`,
@@ -183,8 +182,8 @@ export default async function processDeployment({
if (queuedSpinner === null) {
queuedSpinner =
event.payload.readyState === 'QUEUED'
? wait('Queued', 0)
: wait('Building', 0);
? output.spinner('Queued', 0)
: output.spinner('Building', 0);
}
}
@@ -194,7 +193,7 @@ export default async function processDeployment({
}
if (buildSpinner === null) {
buildSpinner = wait('Building', 0);
buildSpinner = output.spinner('Building', 0);
}
}
@@ -206,7 +205,7 @@ export default async function processDeployment({
buildSpinner();
}
deploySpinner = wait('Completing', 0);
deploySpinner = output.spinner('Completing', 0);
}
// Handle error events

View File

@@ -20,7 +20,6 @@ import {
import pkg from '../../../package.json';
import { NoBuilderCacheError } from '../errors-ts';
import wait from '../output/wait';
import { Output } from '../output';
import { getDistTag } from '../get-dist-tag';
@@ -246,7 +245,7 @@ export async function installBuilders(
return;
}
const stopSpinner = wait(
const stopSpinner = output.spinner(
`Installing ${pluralize(
'Runtime',
packagesToInstall.length

View File

@@ -9,7 +9,6 @@ import getDomainStatus from './get-domain-status';
import promptBool from '../input/prompt-bool';
import purchaseDomain from './purchase-domain';
import stamp from '../output/stamp';
import wait from '../output/wait';
import * as ERRORS from '../errors-ts';
const isTTY = process.stdout.isTTY;
@@ -20,7 +19,7 @@ export default async function purchaseDomainIfAvailable(
domain: string,
contextName: string
) {
const cancelWait = wait(`Checking status of ${chalk.bold(domain)}`);
const cancelWait = output.spinner(`Checking status of ${chalk.bold(domain)}`);
const buyDomainStamp = stamp();
const { available } = await getDomainStatus(client, domain);

View File

@@ -1,6 +1,8 @@
import Client from './client';
import { APIError, InvalidToken } from './errors-ts';
import { Team } from '../types';
// @ts-ignore
import NowTeams from './teams.js';
let teams: Team[] | undefined;
@@ -8,10 +10,15 @@ export default async function getTeams(client: Client) {
if (teams) return teams;
try {
const res = await client.fetch<{ teams: Team[] }>('/teams');
// we're using NowTeams because `client.fetch` hangs on windows
const teamClient = new NowTeams({
apiUrl: client._apiUrl,
token: client._token,
debug: client._debug,
});
teams = res.teams;
return teams;
const teams = (await teamClient.ls()).teams;
return teams as Team[];
} catch (error) {
if (error instanceof APIError && error.status === 403) {
throw new InvalidToken();

View File

@@ -43,7 +43,9 @@ export default async function editProjectSettings(
}
output.print(
`Auto-detected project settings (${chalk.bold(framework.name)}):\n`
!framework.slug
? `No framework detected. Default project settings:\n`
: `Auto-detected project settings (${chalk.bold(framework.name)}):\n`
);
settings.framework = framework.slug;

View File

@@ -6,7 +6,7 @@ import chalk from 'chalk';
import { ProjectNotFound } from '../../util/errors-ts';
import { Output } from '../output';
import { Project, Org } from '../../types';
import wait from '../output/wait';
import slugify from '@sindresorhus/slugify';
export default async function inputProject(
output: Output,
@@ -19,16 +19,26 @@ export default async function inputProject(
return detectedProjectName;
}
const slugifiedName = slugify(detectedProjectName);
// attempt to auto-detect a project to link
let detectedProject = null;
const existingProjectSpinner = wait('Searching for existing projects…', 1000);
const existingProjectSpinner = output.spinner(
'Searching for existing projects…',
1000
);
try {
const project = await getProjectByIdOrName(
client,
detectedProjectName,
org.id
);
detectedProject = project instanceof ProjectNotFound ? null : project;
const [project, slugifiedProject] = await Promise.all([
getProjectByIdOrName(client, detectedProjectName, org.id),
slugifiedName !== detectedProjectName
? getProjectByIdOrName(client, slugifiedName, org.id)
: null,
]);
detectedProject = !(project instanceof ProjectNotFound)
? project
: !(slugifiedProject instanceof ProjectNotFound)
? slugifiedProject
: null;
} catch (error) {}
existingProjectSpinner();
@@ -42,7 +52,7 @@ export default async function inputProject(
if (
await confirm(
`Found project ${chalk.cyan(
`${org.slug}/${detectedProjectName}`
`${org.slug}/${detectedProject.name}`
)}. Link to it?`,
true
)
@@ -74,7 +84,7 @@ export default async function inputProject(
continue;
}
const spinner = wait('Verifying project name…', 1000);
const spinner = output.spinner('Verifying project name…', 1000);
try {
project = await getProjectByIdOrName(client, projectName, org.id);
} finally {
@@ -97,7 +107,7 @@ export default async function inputProject(
type: 'input',
name: 'newProjectName',
message: `Whats your projects name?`,
default: !detectedProject ? detectedProjectName : undefined,
default: !detectedProject ? slugifiedName : undefined,
});
newProjectName = answers.newProjectName as string;
@@ -106,7 +116,7 @@ export default async function inputProject(
continue;
}
const spinner = wait('Verifying project name…', 1000);
const spinner = output.spinner('Verifying project name…', 1000);
let existingProject: Project | ProjectNotFound;
try {
existingProject = await getProjectByIdOrName(

View File

@@ -3,11 +3,12 @@ import inquirer from 'inquirer';
import getUser from '../get-user';
import getTeams from '../get-teams';
import { User, Team, Org } from '../../types';
import wait from '../output/wait';
import { Output } from '../output';
type Choice = { name: string; value: Org };
export default async function selectProject(
export default async function selectOrg(
output: Output,
question: string,
client: Client,
currentTeam?: string,
@@ -15,7 +16,7 @@ export default async function selectProject(
): Promise<Org> {
require('./patch-inquirer');
const spinner = wait('Loading scopes…', 1000);
const spinner = output.spinner('Loading scopes…', 1000);
let user: User;
let teams: Team[];
try {

View File

@@ -2,6 +2,7 @@ import chalk from 'chalk';
import boxen from 'boxen';
import { format } from 'util';
import { Console } from 'console';
import wait from './wait';
export type Output = ReturnType<typeof createOutput>;
@@ -76,6 +77,20 @@ export default function createOutput({ debug: debugEnabled = false } = {}) {
}
}
function spinner(message: string, delay: number = 300) {
if (debugEnabled) {
debug(`Spinner invoked (${message}) with a ${delay}ms delay`);
let isEnded = false;
return () => {
if (isEnded) return;
isEnded = true;
debug(`Spinner ended (${message})`);
};
}
return wait(message, delay);
}
// This is pretty hacky, but since we control the version of Node.js
// being used because of `pkg` it's safe to do in this case.
const c = {
@@ -109,5 +124,6 @@ export default function createOutput({ debug: debugEnabled = false } = {}) {
dim,
time,
note,
spinner,
};
}

View File

@@ -2,7 +2,7 @@ import ora from 'ora';
import chalk from 'chalk';
import eraseLines from './erase-lines';
export default function wait(msg: string, timeout: number = 300, _ora = ora) {
export default function wait(msg: string, delay: number = 300, _ora = ora) {
let spinner: ReturnType<typeof _ora>;
let running = false;
@@ -11,7 +11,7 @@ export default function wait(msg: string, timeout: number = 300, _ora = ora) {
spinner.color = 'gray';
spinner.start();
running = true;
}, timeout);
}, delay);
const cancel = () => {
clearTimeout(planned);

View File

@@ -12,7 +12,6 @@ import { Project } from '../../types';
import { Org, ProjectLink } from '../../types';
import chalk from 'chalk';
import { prependEmoji, emoji } from '../emoji';
import wait from '../output/wait';
const readFile = promisify(fs.readFile);
const writeFile = promisify(fs.writeFile);
@@ -86,7 +85,7 @@ export async function getLinkedOrg(
return { status: 'not_linked', org: null };
}
const spinner = wait('Retrieving scope…', 1000);
const spinner = output.spinner('Retrieving scope…', 1000);
try {
const org = await getOrgById(client, orgId);
@@ -141,7 +140,7 @@ export async function getLinkedProject(
return { status: 'not_linked', org: null, project: null };
}
const spinner = wait('Retrieving project…', 1000);
const spinner = output.spinner('Retrieving project…', 1000);
let org: Org | null;
let project: Project | ProjectNotFound | null;
try {

View File

@@ -1,5 +1,4 @@
import chalk from 'chalk';
import wait from '../output/wait';
import joinWords from '../output/join-words';
import * as Errors from '../errors-ts';
import { Output } from '../output';
@@ -17,7 +16,7 @@ export default async function patchDeploymentScale(
scaleArgs: ScaleArgs,
url: string
) {
const cancelWait = wait(
const cancelWait = output.spinner(
`Setting scale rules for ${joinWords(
Object.keys(scaleArgs).map(dc => `${chalk.bold(dc)}`)
)}`
@@ -28,7 +27,7 @@ export default async function patchDeploymentScale(
`/v3/now/deployments/${encodeURIComponent(deploymentId)}/instances`,
{
method: 'PATCH',
body: scaleArgs
body: scaleArgs,
}
);
cancelWait();

View File

@@ -4,7 +4,6 @@ import { Output } from '../output';
import * as ERRORS from '../errors-ts';
import Client from '../client';
import joinWords from '../output/join-words';
import wait from '../output/wait';
type ScaleArgs = {
min: number;
@@ -18,7 +17,7 @@ export default async function setScale(
scaleArgs: ScaleArgs | DeploymentScale,
url: string
) {
const cancelWait = wait(
const cancelWait = output.spinner(
`Setting scale rules for ${joinWords(
Object.keys(scaleArgs).map(dc => `${chalk.bold(dc)}`)
)}`
@@ -29,7 +28,7 @@ export default async function setScale(
`/v3/now/deployments/${encodeURIComponent(deploymentId)}/instances`,
{
method: 'PUT',
body: scaleArgs
body: scaleArgs,
}
);
cancelWait();

View File

@@ -9,7 +9,6 @@ import Client from '../client';
import joinWords from '../output/join-words';
import stamp from '../output/stamp';
import verifyDeploymentScale from './verify-deployment-scale';
import wait from '../output/wait';
export default async function waitForScale(
output: Output,
@@ -19,7 +18,7 @@ export default async function waitForScale(
) {
const remainingDCs = new Set(Object.keys(scale));
const scaleStamp = stamp();
let cancelWait = renderWaitDcs(Array.from(remainingDCs.keys()));
let cancelWait = renderWaitDcs(output, Array.from(remainingDCs.keys()));
for await (const dcReady of verifyDeploymentScale(
output,
@@ -43,13 +42,13 @@ export default async function waitForScale(
}
if (remainingDCs.size > 0) {
cancelWait = renderWaitDcs(Array.from(remainingDCs.keys()));
cancelWait = renderWaitDcs(output, Array.from(remainingDCs.keys()));
}
}
}
function renderWaitDcs(dcs: string[]) {
return wait(
function renderWaitDcs(output: Output, dcs: string[]) {
return output.spinner(
`Waiting for instances in ${joinWords(
dcs.map(dc => chalk.bold(dc))
)} to be ready`

View File

@@ -2149,54 +2149,6 @@ test('should show prompts to set up project', async t => {
t.is(text.includes('<h1>custom hello</h1>'), true, text);
});
test('should not prompt "project settings overwrite" for undetected projects', async t => {
const directory = fixture('static-deployment');
const projectName = `static-deployment-${
Math.random()
.toString(36)
.split('.')[1]
}`;
// remove previously linked project if it exists
await remove(path.join(directory, '.now'));
const now = execa(binaryPath, [directory, ...defaultArgs]);
await waitForPrompt(now, chunk => /Set up and deploy [^?]+\?/.test(chunk));
now.stdin.write('yes\n');
await waitForPrompt(now, chunk =>
chunk.includes('Which scope do you want to deploy to?')
);
now.stdin.write('\n');
await waitForPrompt(now, chunk =>
chunk.includes('Link to existing project?')
);
now.stdin.write('no\n');
await waitForPrompt(now, chunk =>
chunk.includes('Whats your projects name?')
);
now.stdin.write(`${projectName}\n`);
await waitForPrompt(now, chunk =>
chunk.includes('In which directory is your code located?')
);
now.stdin.write('\n');
await waitForPrompt(now, chunk => {
t.false(
chunk.includes('Want to override the settings?'),
'Should not ask to override'
);
return chunk.includes('Linked to');
});
const output = await now;
t.is(output.exitCode, 0, formatOutput(output));
});
test('should prefill "project name" prompt with folder name', async t => {
const projectName = `static-deployment-${
Math.random()
@@ -2237,6 +2189,11 @@ test('should prefill "project name" prompt with folder name', async t => {
);
now.stdin.write('\n');
await waitForPrompt(now, chunk =>
chunk.includes('Want to override the settings?')
);
now.stdin.write('no\n');
const output = await now;
t.is(output.exitCode, 0, formatOutput(output));
});
@@ -2292,6 +2249,11 @@ test('should prefill "project name" prompt with --name', async t => {
);
now.stdin.write('\n');
await waitForPrompt(now, chunk =>
chunk.includes('Want to override the settings?')
);
now.stdin.write('no\n');
const output = await now;
t.is(output.exitCode, 0, formatOutput(output));
});
@@ -2348,6 +2310,11 @@ test('should prefill "project name" prompt with now.json `name`', async t => {
);
now.stdin.write('\n');
await waitForPrompt(now, chunk =>
chunk.includes('Want to override the settings?')
);
now.stdin.write('no\n');
const output = await now;
t.is(output.exitCode, 0, formatOutput(output));

View File

@@ -1,6 +1,6 @@
{
"name": "@now/go",
"version": "1.0.2-canary.0",
"version": "1.0.2",
"license": "MIT",
"main": "./dist/index",
"homepage": "https://zeit.co/docs/runtimes#official-runtimes/go",

View File

@@ -3,14 +3,24 @@ const path = require('path');
const {
packAndDeploy,
testDeployment
testDeployment,
} = require('../../../test/lib/deployment/test-deployment.js');
jest.setTimeout(4 * 60 * 1000);
const buildUtilsUrl = '@canary';
let buildUtilsUrl;
let builderUrl;
beforeAll(async () => {
if (!buildUtilsUrl) {
const buildUtilsPath = path.resolve(
__dirname,
'..',
'..',
'now-build-utils'
);
buildUtilsUrl = await packAndDeploy(buildUtilsPath);
console.log('buildUtilsUrl', buildUtilsUrl);
}
const builderPath = path.resolve(__dirname, '..');
builderUrl = await packAndDeploy(builderPath);
console.log('builderUrl', builderUrl);

View File

@@ -1,6 +1,6 @@
{
"name": "@now/python",
"version": "1.1.2-canary.0",
"version": "1.1.2",
"main": "./dist/index.js",
"license": "MIT",
"homepage": "https://zeit.co/docs/runtimes#official-runtimes/python",

View File

@@ -1,6 +1,6 @@
{
"name": "@now/static-build",
"version": "0.14.11-canary.2",
"version": "0.14.11",
"license": "MIT",
"main": "./dist/index",
"homepage": "https://zeit.co/docs/runtimes#official-runtimes/static-builds",

View File

@@ -1363,6 +1363,14 @@
resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea"
integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==
"@sindresorhus/slugify@0.10.0":
version "0.10.0"
resolved "https://registry.yarnpkg.com/@sindresorhus/slugify/-/slugify-0.10.0.tgz#8878609a6a468a110690abbfb65171769cd9a8d4"
integrity sha512-R/3PVAS0rIbrH/qJRb4ma/5pG3oyQKW1Ws4bsc/Fscfb6HWeB0CNWD3bnPAiWi5PYLnl33TcsXCKXNOPwBpyaw==
dependencies:
escape-string-regexp "^2.0.0"
lodash.deburr "^4.1.0"
"@sinonjs/commons@^1", "@sinonjs/commons@^1.3.0":
version "1.6.0"
resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.6.0.tgz#ec7670432ae9c8eb710400d112c201a362d83393"
@@ -2042,10 +2050,10 @@
agentkeepalive "3.4.1"
debug "3.1.0"
"@zeit/fun@0.11.0":
version "0.11.0"
resolved "https://registry.yarnpkg.com/@zeit/fun/-/fun-0.11.0.tgz#e226af0a2b63020a0e233dd37a2ceb2ac2e68fe3"
integrity sha512-w9IqoMV6SIKVmQbocKKvllgL27im7YQfTFV/0hjIgASfi8yQgPIj7mo76VFosRS0HQA5MEIzYz+oigdelOTIOQ==
"@zeit/fun@0.11.2":
version "0.11.2"
resolved "https://registry.yarnpkg.com/@zeit/fun/-/fun-0.11.2.tgz#a9ac34c8db09f8de40f7e727bdfde808c1be6505"
integrity sha512-1LoKTF2jq7YT3eATD/iTRuaTmvVtX3pWi3SVZPAgDTb70OLklpDkvVA/Z7dqP/WMB3gVGBdQNIhWfPTlBwrHEA==
dependencies:
async-listen "1.0.0"
debug "4.1.1"
@@ -3205,11 +3213,6 @@ chalk@^3.0.0:
ansi-styles "^4.1.0"
supports-color "^7.1.0"
chardet@^0.4.0:
version "0.4.2"
resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2"
integrity sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=
chardet@^0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
@@ -4735,15 +4738,6 @@ extend@~3.0.2:
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
external-editor@^2.0.4:
version "2.2.0"
resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.2.0.tgz#045511cfd8d133f3846673d1047c154e214ad3d5"
integrity sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==
dependencies:
chardet "^0.4.0"
iconv-lite "^0.4.17"
tmp "^0.0.33"
external-editor@^3.0.3:
version "3.1.0"
resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495"
@@ -5756,7 +5750,7 @@ iconv-lite@0.4.19:
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b"
integrity sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==
iconv-lite@0.4.24, iconv-lite@^0.4.17, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13:
iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13:
version "0.4.24"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
@@ -5918,24 +5912,23 @@ init-package-json@^1.10.3:
validate-npm-package-license "^3.0.1"
validate-npm-package-name "^3.0.0"
inquirer@3.3.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.3.0.tgz#9dd2f2ad765dcab1ff0443b491442a20ba227dc9"
integrity sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==
inquirer@7.0.4:
version "7.0.4"
resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.0.4.tgz#99af5bde47153abca23f5c7fc30db247f39da703"
integrity sha512-Bu5Td5+j11sCkqfqmUTiwv+tWisMtP0L7Q8WrqA2C/BbBhy1YTdFrvjjlrKq8oagA/tLQBski2Gcx/Sqyi2qSQ==
dependencies:
ansi-escapes "^3.0.0"
chalk "^2.0.0"
cli-cursor "^2.1.0"
ansi-escapes "^4.2.1"
chalk "^2.4.2"
cli-cursor "^3.1.0"
cli-width "^2.0.0"
external-editor "^2.0.4"
figures "^2.0.0"
lodash "^4.3.0"
mute-stream "0.0.7"
external-editor "^3.0.3"
figures "^3.0.0"
lodash "^4.17.15"
mute-stream "0.0.8"
run-async "^2.2.0"
rx-lite "^4.0.8"
rx-lite-aggregates "^4.0.8"
string-width "^2.1.0"
strip-ansi "^4.0.0"
rxjs "^6.5.3"
string-width "^4.1.0"
strip-ansi "^5.1.0"
through "^2.3.6"
inquirer@^6.2.0:
@@ -7217,6 +7210,11 @@ lodash.clonedeep@^4.5.0:
resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef"
integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=
lodash.deburr@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/lodash.deburr/-/lodash.deburr-4.1.0.tgz#ddb1bbb3ef07458c0177ba07de14422cb033ff9b"
integrity sha1-3bG7s+8HRYwBd7oH3hRCLLAz/5s=
lodash.flattendeep@^4.4.0:
version "4.4.0"
resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2"
@@ -7287,7 +7285,7 @@ lodash.uniq@^4.5.0:
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=
lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.2.1, lodash@^4.3.0:
lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.2.1:
version "4.17.15"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
@@ -9542,14 +9540,14 @@ run-queue@^1.0.0, run-queue@^1.0.3:
dependencies:
aproba "^1.1.1"
rx-lite-aggregates@4.0.8, rx-lite-aggregates@^4.0.8:
rx-lite-aggregates@4.0.8:
version "4.0.8"
resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be"
integrity sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=
dependencies:
rx-lite "*"
rx-lite@*, rx-lite@^4.0.8:
rx-lite@*:
version "4.0.8"
resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444"
integrity sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=
@@ -9561,6 +9559,13 @@ rxjs@^6.3.3, rxjs@^6.4.0:
dependencies:
tslib "^1.9.0"
rxjs@^6.5.3:
version "6.5.4"
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.4.tgz#e0777fe0d184cec7872df147f303572d414e211c"
integrity sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q==
dependencies:
tslib "^1.9.0"
safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
version "5.1.2"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
@@ -9725,7 +9730,7 @@ shellwords@^0.1.1:
resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b"
integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==
signal-exit@3.0.2, signal-exit@^3.0.0, signal-exit@^3.0.2:
signal-exit@3.0.2, signal-exit@TooTallNate/signal-exit#update/sighub-to-sigint-on-windows, signal-exit@^3.0.0, signal-exit@^3.0.2:
version "3.0.2"
resolved "https://codeload.github.com/TooTallNate/signal-exit/tar.gz/58088fa7f715149f8411e089a4a6e3fe6ed265ec"