mirror of
https://github.com/LukeHagar/vercel.git
synced 2025-12-11 21:07:47 +00:00
Compare commits
23 Commits
create-inp
...
@vercel/bu
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3c42649916 | ||
|
|
c1891f64f4 | ||
|
|
2fc46c0d47 | ||
|
|
73b112b1f7 | ||
|
|
548afd371a | ||
|
|
d0877c1023 | ||
|
|
326fe0f0e6 | ||
|
|
346e665bb0 | ||
|
|
9a27ccbe6d | ||
|
|
3b6d96891b | ||
|
|
07d8d11989 | ||
|
|
8a16e8eb65 | ||
|
|
63e9de8932 | ||
|
|
c6d588201b | ||
|
|
0b1ff4bf62 | ||
|
|
14102ddf56 | ||
|
|
49f88975b9 | ||
|
|
13f3db06a8 | ||
|
|
78e2c012f9 | ||
|
|
f707f13821 | ||
|
|
9ed967034d | ||
|
|
1825b58df8 | ||
|
|
c82a55c460 |
@@ -1,2 +0,0 @@
|
|||||||
---
|
|
||||||
---
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
---
|
|
||||||
---
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
---
|
|
||||||
---
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
---
|
|
||||||
---
|
|
||||||
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
---
|
|
||||||
"@vercel/remix-builder": patch
|
|
||||||
---
|
|
||||||
|
|
||||||
Add `mjs` and `mts` extensions to vite detection
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
---
|
|
||||||
---
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
---
|
|
||||||
|
|
||||||
Update CODEOWNERS
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
---
|
|
||||||
---
|
|
||||||
22
.github/CODEOWNERS
vendored
22
.github/CODEOWNERS
vendored
@@ -2,17 +2,17 @@
|
|||||||
# https://help.github.com/en/articles/about-code-owners
|
# https://help.github.com/en/articles/about-code-owners
|
||||||
|
|
||||||
# Restricted Paths
|
# Restricted Paths
|
||||||
* @TooTallNate @EndangeredMassa @trek @onsclom @jeffsee55
|
* @TooTallNate @EndangeredMassa @trek @onsclom @jeffsee55 @erikareads
|
||||||
/.github/workflows @TooTallNate @EndangeredMassa @trek @onsclom @jeffsee55 @ijjk
|
/.github/workflows @TooTallNate @EndangeredMassa @trek @onsclom @jeffsee55 @erikareads @ijjk
|
||||||
/packages/fs-detectors @TooTallNate @EndangeredMassa @trek @onsclom @jeffsee55 @agadzik @chloetedder
|
/packages/fs-detectors @TooTallNate @EndangeredMassa @trek @onsclom @jeffsee55 @erikareads @agadzik @chloetedder
|
||||||
/packages/next @TooTallNate @EndangeredMassa @trek @onsclom @jeffsee55 @timneutkens @ijjk @ztanner @huozhi @Ethan-Arrowood @styfle
|
/packages/next @TooTallNate @EndangeredMassa @trek @onsclom @jeffsee55 @erikareads @timneutkens @ijjk @ztanner @huozhi @Ethan-Arrowood @styfle
|
||||||
/packages/routing-utils @TooTallNate @EndangeredMassa @trek @onsclom @jeffsee55 @ijjk
|
/packages/routing-utils @TooTallNate @EndangeredMassa @trek @onsclom @jeffsee55 @erikareads @ijjk
|
||||||
/packages/static-build @TooTallNate @EndangeredMassa @trek @onsclom @jeffsee55
|
/packages/static-build @TooTallNate @EndangeredMassa @trek @onsclom @jeffsee55 @erikareads
|
||||||
/packages/edge @TooTallNate @EndangeredMassa @trek @onsclom @jeffsee55 @vercel/compute
|
/packages/edge @TooTallNate @EndangeredMassa @trek @onsclom @jeffsee55 @erikareads @vercel/compute
|
||||||
/examples @TooTallNate @EndangeredMassa @trek @onsclom @jeffsee55 @leerob
|
/examples @TooTallNate @EndangeredMassa @trek @onsclom @jeffsee55 @erikareads @leerob
|
||||||
/examples/create-react-app @TooTallNate @EndangeredMassa @trek @onsclom @jeffsee55 @Timer
|
/examples/create-react-app @TooTallNate @EndangeredMassa @trek @onsclom @jeffsee55 @erikareads @Timer
|
||||||
/examples/nextjs @TooTallNate @EndangeredMassa @trek @onsclom @jeffsee55 @timneutkens @ijjk @ztanner @huozhi @Ethan-Arrowood @styfle
|
/examples/nextjs @TooTallNate @EndangeredMassa @trek @onsclom @jeffsee55 @erikareads @timneutkens @ijjk @ztanner @huozhi @Ethan-Arrowood @styfle
|
||||||
/packages/node @TooTallNate @EndangeredMassa @trek @onsclom @jeffsee55 @Kikobeats
|
/packages/node @TooTallNate @EndangeredMassa @trek @onsclom @jeffsee55 @erikareads @Kikobeats
|
||||||
|
|
||||||
# Unrestricted Paths
|
# Unrestricted Paths
|
||||||
.changeset/
|
.changeset/
|
||||||
|
|||||||
62
.github/dependabot.yml
vendored
62
.github/dependabot.yml
vendored
@@ -90,8 +90,15 @@ updates:
|
|||||||
prefix: '[framework-fixtures]'
|
prefix: '[framework-fixtures]'
|
||||||
package-ecosystem: 'npm'
|
package-ecosystem: 'npm'
|
||||||
allow:
|
allow:
|
||||||
- dependency-name: '@angular*'
|
|
||||||
- dependency-name: '@ionic*'
|
- dependency-name: '@ionic*'
|
||||||
|
- dependency-name: '@angular*'
|
||||||
|
ignore:
|
||||||
|
- dependency-name: '@ionic*'
|
||||||
|
update-types:
|
||||||
|
['version-update:semver-major', 'version-update:semver-patch']
|
||||||
|
- dependency-name: '@angular*'
|
||||||
|
update-types:
|
||||||
|
['version-update:semver-major', 'version-update:semver-patch']
|
||||||
groups:
|
groups:
|
||||||
core:
|
core:
|
||||||
patterns:
|
patterns:
|
||||||
@@ -100,6 +107,35 @@ updates:
|
|||||||
update-types:
|
update-types:
|
||||||
- 'minor'
|
- 'minor'
|
||||||
|
|
||||||
|
- directory: /packages/static-build/test/fixtures/ionic-react-v7
|
||||||
|
schedule:
|
||||||
|
interval: 'daily'
|
||||||
|
open-pull-requests-limit: 1
|
||||||
|
reviewers:
|
||||||
|
- 'trek'
|
||||||
|
- 'TooTallNate'
|
||||||
|
- 'EndangeredMassa'
|
||||||
|
commit-message:
|
||||||
|
prefix: '[framework-fixtures]'
|
||||||
|
package-ecosystem: 'npm'
|
||||||
|
allow:
|
||||||
|
- dependency-name: '@ionic*'
|
||||||
|
- dependency-name: 'react*'
|
||||||
|
ignore:
|
||||||
|
- dependency-name: '@ionic*'
|
||||||
|
update-types:
|
||||||
|
['version-update:semver-major', 'version-update:semver-patch']
|
||||||
|
- dependency-name: 'react*'
|
||||||
|
update-types:
|
||||||
|
['version-update:semver-major', 'version-update:semver-patch']
|
||||||
|
groups:
|
||||||
|
core:
|
||||||
|
patterns:
|
||||||
|
- '@ionic*'
|
||||||
|
- 'react*'
|
||||||
|
update-types:
|
||||||
|
- 'minor'
|
||||||
|
|
||||||
- directory: /packages/static-build/test/fixtures/nuxt-v3
|
- directory: /packages/static-build/test/fixtures/nuxt-v3
|
||||||
schedule:
|
schedule:
|
||||||
interval: 'daily'
|
interval: 'daily'
|
||||||
@@ -139,6 +175,30 @@ updates:
|
|||||||
update-types:
|
update-types:
|
||||||
- 'minor'
|
- 'minor'
|
||||||
|
|
||||||
|
- directory: /packages/static-build/test/fixtures/preact-v10
|
||||||
|
schedule:
|
||||||
|
interval: 'daily'
|
||||||
|
open-pull-requests-limit: 1
|
||||||
|
reviewers:
|
||||||
|
- 'trek'
|
||||||
|
- 'TooTallNate'
|
||||||
|
- 'EndangeredMassa'
|
||||||
|
commit-message:
|
||||||
|
prefix: '[framework-fixtures]'
|
||||||
|
package-ecosystem: 'npm'
|
||||||
|
allow:
|
||||||
|
- dependency-name: 'preact*'
|
||||||
|
ignore:
|
||||||
|
- dependency-name: 'preact*'
|
||||||
|
update-types:
|
||||||
|
['version-update:semver-major', 'version-update:semver-patch']
|
||||||
|
groups:
|
||||||
|
core:
|
||||||
|
patterns:
|
||||||
|
- 'preact*'
|
||||||
|
update-types:
|
||||||
|
- 'minor'
|
||||||
|
|
||||||
- directory: /packages/static-build/test/fixtures/stencil-v4
|
- directory: /packages/static-build/test/fixtures/stencil-v4
|
||||||
schedule:
|
schedule:
|
||||||
interval: 'daily'
|
interval: 'daily'
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { lstatSync, readdirSync } from 'fs';
|
|||||||
export async function deployExample(filename: string) {
|
export async function deployExample(filename: string) {
|
||||||
const { testDeployment } = require('../../test/lib/deployment/test-deployment.js');
|
const { testDeployment } = require('../../test/lib/deployment/test-deployment.js');
|
||||||
const example = basename(filename).replace(/\.test\.ts$/, '');
|
const example = basename(filename).replace(/\.test\.ts$/, '');
|
||||||
await testDeployment(join(filename, '..', '..', '..', example));
|
await testDeployment(join(process.cwd(), example));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getExamples() {
|
export function getExamples() {
|
||||||
|
|||||||
@@ -8,6 +8,6 @@ menu:
|
|||||||
main: {}
|
main: {}
|
||||||
---
|
---
|
||||||
|
|
||||||
This is an example of a custom shortcode that you can put right into your content. You will need to add a form action to the the shortcode to make it work. Check out [Formspree](https://formspree.io/) for a simple, free form service.
|
This is an example of a custom shortcode that you can put right into your content. You will need to add a form action to the shortcode to make it work. Check out [Formspree](https://formspree.io/) for a simple, free form service.
|
||||||
|
|
||||||
{{< form-contact action="https://example.com" >}}
|
{{< form-contact action="https://example.com" >}}
|
||||||
|
|||||||
3
examples/package.json
vendored
3
examples/package.json
vendored
@@ -9,7 +9,8 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/jest": "27.4.1",
|
"@types/jest": "27.4.1",
|
||||||
"@vercel/frameworks": "3.0.0"
|
"@vercel/build-utils": "7.11.0",
|
||||||
|
"@vercel/frameworks": "3.0.1"
|
||||||
},
|
},
|
||||||
"version": null
|
"version": null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,19 @@
|
|||||||
# @vercel-internals/types
|
# @vercel-internals/types
|
||||||
|
|
||||||
|
## 1.0.29
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [[`73b112b1f`](https://github.com/vercel/vercel/commit/73b112b1f74480e1bb941e1b754105fc7dace401)]:
|
||||||
|
- @vercel/build-utils@7.11.0
|
||||||
|
|
||||||
|
## 1.0.28
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [[`1825b58df`](https://github.com/vercel/vercel/commit/1825b58df8d783e79f0addf262618f422246f4b3)]:
|
||||||
|
- @vercel/build-utils@7.10.0
|
||||||
|
|
||||||
## 1.0.27
|
## 1.0.27
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"private": true,
|
"private": true,
|
||||||
"name": "@vercel-internals/types",
|
"name": "@vercel-internals/types",
|
||||||
"version": "1.0.27",
|
"version": "1.0.29",
|
||||||
"types": "index.d.ts",
|
"types": "index.d.ts",
|
||||||
"main": "index.d.ts",
|
"main": "index.d.ts",
|
||||||
"files": [
|
"files": [
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/node": "14.14.31",
|
"@types/node": "14.14.31",
|
||||||
"@vercel-internals/constants": "1.0.4",
|
"@vercel-internals/constants": "1.0.4",
|
||||||
"@vercel/build-utils": "7.9.1",
|
"@vercel/build-utils": "7.11.0",
|
||||||
"@vercel/routing-utils": "3.1.0"
|
"@vercel/routing-utils": "3.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
"source-map-support": "0.5.12",
|
"source-map-support": "0.5.12",
|
||||||
"ts-eager": "2.0.2",
|
"ts-eager": "2.0.2",
|
||||||
"ts-jest": "29.1.0",
|
"ts-jest": "29.1.0",
|
||||||
"turbo": "1.12.5",
|
"turbo": "1.13.0",
|
||||||
"typescript": "4.9.5"
|
"typescript": "4.9.5"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -1,5 +1,17 @@
|
|||||||
# @vercel/build-utils
|
# @vercel/build-utils
|
||||||
|
|
||||||
|
## 7.11.0
|
||||||
|
|
||||||
|
### Minor Changes
|
||||||
|
|
||||||
|
- Add `getOsRelease()` and `getProvidedRuntime()` functions ([#11370](https://github.com/vercel/vercel/pull/11370))
|
||||||
|
|
||||||
|
## 7.10.0
|
||||||
|
|
||||||
|
### Minor Changes
|
||||||
|
|
||||||
|
- Allow environment variables to be specified for `EdgeFunction` ([#11029](https://github.com/vercel/vercel/pull/11029))
|
||||||
|
|
||||||
## 7.9.1
|
## 7.9.1
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@vercel/build-utils",
|
"name": "@vercel/build-utils",
|
||||||
"version": "7.9.1",
|
"version": "7.11.0",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
"types": "./dist/index.d.js",
|
"types": "./dist/index.d.js",
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { Files, FunctionFramework } from './types';
|
import type { Env, Files, FunctionFramework } from './types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An Edge Functions output
|
* An Edge Functions output
|
||||||
@@ -23,6 +23,11 @@ export class EdgeFunction {
|
|||||||
*/
|
*/
|
||||||
entrypoint: string;
|
entrypoint: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Environment variables for the edge function to use at runtime.
|
||||||
|
*/
|
||||||
|
environment?: Env;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The list of files to be included in the edge function bundle.
|
* The list of files to be included in the edge function bundle.
|
||||||
*/
|
*/
|
||||||
@@ -48,5 +53,6 @@ export class EdgeFunction {
|
|||||||
this.assets = params.assets;
|
this.assets = params.assets;
|
||||||
this.regions = params.regions;
|
this.regions = params.regions;
|
||||||
this.framework = params.framework;
|
this.framework = params.framework;
|
||||||
|
this.environment = params.environment;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -103,6 +103,7 @@ export {
|
|||||||
export { EdgeFunction } from './edge-function';
|
export { EdgeFunction } from './edge-function';
|
||||||
export { readConfigFile } from './fs/read-config-file';
|
export { readConfigFile } from './fs/read-config-file';
|
||||||
export { normalizePath } from './fs/normalize-path';
|
export { normalizePath } from './fs/normalize-path';
|
||||||
|
export { getOsRelease, getProvidedRuntime } from './os';
|
||||||
|
|
||||||
export * from './should-serve';
|
export * from './should-serve';
|
||||||
export * from './schemas';
|
export * from './schemas';
|
||||||
|
|||||||
@@ -5,11 +5,7 @@ import minimatch from 'minimatch';
|
|||||||
import { readlink } from 'fs-extra';
|
import { readlink } from 'fs-extra';
|
||||||
import { isSymbolicLink, isDirectory } from './fs/download';
|
import { isSymbolicLink, isDirectory } from './fs/download';
|
||||||
import streamToBuffer from './fs/stream-to-buffer';
|
import streamToBuffer from './fs/stream-to-buffer';
|
||||||
import type { Files, Config, FunctionFramework } from './types';
|
import type { Config, Env, Files, FunctionFramework } from './types';
|
||||||
|
|
||||||
interface Environment {
|
|
||||||
[key: string]: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type LambdaOptions = LambdaOptionsWithFiles | LambdaOptionsWithZipBuffer;
|
export type LambdaOptions = LambdaOptionsWithFiles | LambdaOptionsWithZipBuffer;
|
||||||
|
|
||||||
@@ -21,7 +17,7 @@ export interface LambdaOptionsBase {
|
|||||||
architecture?: LambdaArchitecture;
|
architecture?: LambdaArchitecture;
|
||||||
memory?: number;
|
memory?: number;
|
||||||
maxDuration?: number;
|
maxDuration?: number;
|
||||||
environment?: Environment;
|
environment?: Env;
|
||||||
allowQuery?: string[];
|
allowQuery?: string[];
|
||||||
regions?: string[];
|
regions?: string[];
|
||||||
supportsMultiPayloads?: boolean;
|
supportsMultiPayloads?: boolean;
|
||||||
@@ -69,7 +65,7 @@ export class Lambda {
|
|||||||
architecture?: LambdaArchitecture;
|
architecture?: LambdaArchitecture;
|
||||||
memory?: number;
|
memory?: number;
|
||||||
maxDuration?: number;
|
maxDuration?: number;
|
||||||
environment: Environment;
|
environment: Env;
|
||||||
allowQuery?: string[];
|
allowQuery?: string[];
|
||||||
regions?: string[];
|
regions?: string[];
|
||||||
/**
|
/**
|
||||||
|
|||||||
42
packages/build-utils/src/os.ts
Normal file
42
packages/build-utils/src/os.ts
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
import { readFile } from 'fs-extra';
|
||||||
|
import { isErrnoException } from '@vercel/error-utils';
|
||||||
|
|
||||||
|
export async function getOsRelease() {
|
||||||
|
try {
|
||||||
|
const data = await readFile('/etc/os-release', 'utf8');
|
||||||
|
return await parseOsRelease(data);
|
||||||
|
} catch (err) {
|
||||||
|
if (isErrnoException(err) && err.code === 'ENOENT') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function parseOsRelease(data: string) {
|
||||||
|
const obj: Record<string, string> = {};
|
||||||
|
// Example file contents:
|
||||||
|
// NAME="Amazon Linux"
|
||||||
|
// VERSION="2023"
|
||||||
|
// ID="amzn"
|
||||||
|
// ID_LIKE="fedora"
|
||||||
|
for (const line of data.trim().split('\n')) {
|
||||||
|
const m = /(?<key>.*)="(?<value>.*)"/.exec(line);
|
||||||
|
if (!m?.groups) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
obj[m.groups.key] = m.groups.value;
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getProvidedRuntime() {
|
||||||
|
const os = await getOsRelease();
|
||||||
|
if (!os) {
|
||||||
|
return 'provided.al2023';
|
||||||
|
}
|
||||||
|
|
||||||
|
return os.PRETTY_NAME === 'Amazon Linux 2'
|
||||||
|
? 'provided.al2'
|
||||||
|
: 'provided.al2023';
|
||||||
|
}
|
||||||
@@ -3,5 +3,8 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "mkdir -p public && (printf \"npm version: \" && npm -v) > public/index.txt"
|
"build": "mkdir -p public && (printf \"npm version: \" && npm -v) > public/index.txt"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "16.x"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,5 +5,8 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"once": "^1.4.0"
|
"once": "^1.4.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "16.x"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,5 +6,8 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"exeggcute": "^1.0.0",
|
"exeggcute": "^1.0.0",
|
||||||
"once": "^1.4.0"
|
"once": "^1.4.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "16.x"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,5 +5,8 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"sharp": "0.33.2"
|
"sharp": "0.33.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "16.x"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
89
packages/build-utils/test/unit.get-os-release.test.ts
vendored
Normal file
89
packages/build-utils/test/unit.get-os-release.test.ts
vendored
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
import { parseOsRelease } from '../src/os';
|
||||||
|
|
||||||
|
describe('getOsRelease()', () => {
|
||||||
|
it('should parse `amazonlinux:2`', async () => {
|
||||||
|
const data = `NAME="Amazon Linux"
|
||||||
|
VERSION="2"
|
||||||
|
ID="amzn"
|
||||||
|
ID_LIKE="centos rhel fedora"
|
||||||
|
VERSION_ID="2"
|
||||||
|
PRETTY_NAME="Amazon Linux 2"
|
||||||
|
ANSI_COLOR="0;33"
|
||||||
|
CPE_NAME="cpe:2.3:o:amazon:amazon_linux:2"
|
||||||
|
HOME_URL="https://amazonlinux.com/"
|
||||||
|
SUPPORT_END="2025-06-30"
|
||||||
|
`;
|
||||||
|
const parsed = await parseOsRelease(data);
|
||||||
|
expect(parsed).toMatchObject({
|
||||||
|
ANSI_COLOR: '0;33',
|
||||||
|
CPE_NAME: 'cpe:2.3:o:amazon:amazon_linux:2',
|
||||||
|
HOME_URL: 'https://amazonlinux.com/',
|
||||||
|
ID: 'amzn',
|
||||||
|
ID_LIKE: 'centos rhel fedora',
|
||||||
|
NAME: 'Amazon Linux',
|
||||||
|
PRETTY_NAME: 'Amazon Linux 2',
|
||||||
|
SUPPORT_END: '2025-06-30',
|
||||||
|
VERSION: '2',
|
||||||
|
VERSION_ID: '2',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should parse `amazonlinux:2023`', async () => {
|
||||||
|
const data = `NAME="Amazon Linux"
|
||||||
|
VERSION="2023"
|
||||||
|
ID="amzn"
|
||||||
|
ID_LIKE="fedora"
|
||||||
|
VERSION_ID="2023"
|
||||||
|
PLATFORM_ID="platform:al2023"
|
||||||
|
PRETTY_NAME="Amazon Linux 2023"
|
||||||
|
ANSI_COLOR="0;33"
|
||||||
|
CPE_NAME="cpe:2.3:o:amazon:amazon_linux:2023"
|
||||||
|
HOME_URL="https://aws.amazon.com/linux/"
|
||||||
|
BUG_REPORT_URL="https://github.com/amazonlinux/amazon-linux-2023"
|
||||||
|
SUPPORT_END="2028-03-01"
|
||||||
|
`;
|
||||||
|
const parsed = await parseOsRelease(data);
|
||||||
|
expect(parsed).toMatchObject({
|
||||||
|
NAME: 'Amazon Linux',
|
||||||
|
VERSION: '2023',
|
||||||
|
ID: 'amzn',
|
||||||
|
ID_LIKE: 'fedora',
|
||||||
|
VERSION_ID: '2023',
|
||||||
|
PLATFORM_ID: 'platform:al2023',
|
||||||
|
PRETTY_NAME: 'Amazon Linux 2023',
|
||||||
|
ANSI_COLOR: '0;33',
|
||||||
|
CPE_NAME: 'cpe:2.3:o:amazon:amazon_linux:2023',
|
||||||
|
HOME_URL: 'https://aws.amazon.com/linux/',
|
||||||
|
BUG_REPORT_URL: 'https://github.com/amazonlinux/amazon-linux-2023',
|
||||||
|
SUPPORT_END: '2028-03-01',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should parse `ubuntu:jammy`', async () => {
|
||||||
|
const data = `PRETTY_NAME="Ubuntu 22.04.3 LTS"
|
||||||
|
NAME="Ubuntu"
|
||||||
|
VERSION_ID="22.04"
|
||||||
|
VERSION="22.04.3 LTS (Jammy Jellyfish)"
|
||||||
|
VERSION_CODENAME=jammy
|
||||||
|
ID=ubuntu
|
||||||
|
ID_LIKE=debian
|
||||||
|
HOME_URL="https://www.ubuntu.com/"
|
||||||
|
SUPPORT_URL="https://help.ubuntu.com/"
|
||||||
|
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
|
||||||
|
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
|
||||||
|
UBUNTU_CODENAME=jammy
|
||||||
|
`;
|
||||||
|
const parsed = await parseOsRelease(data);
|
||||||
|
expect(parsed).toMatchObject({
|
||||||
|
PRETTY_NAME: 'Ubuntu 22.04.3 LTS',
|
||||||
|
NAME: 'Ubuntu',
|
||||||
|
VERSION_ID: '22.04',
|
||||||
|
VERSION: '22.04.3 LTS (Jammy Jellyfish)',
|
||||||
|
HOME_URL: 'https://www.ubuntu.com/',
|
||||||
|
SUPPORT_URL: 'https://help.ubuntu.com/',
|
||||||
|
BUG_REPORT_URL: 'https://bugs.launchpad.net/ubuntu/',
|
||||||
|
PRIVACY_POLICY_URL:
|
||||||
|
'https://www.ubuntu.com/legal/terms-and-policies/privacy-policy',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1,5 +1,35 @@
|
|||||||
# vercel
|
# vercel
|
||||||
|
|
||||||
|
## 33.6.3
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Handle `--repo` linked in `vc deploy --prebuilt` ([#11309](https://github.com/vercel/vercel/pull/11309))
|
||||||
|
|
||||||
|
- Revert "[cli] extract `isZeroConfigBuild` into utility function (#11316)" ([#11350](https://github.com/vercel/vercel/pull/11350))
|
||||||
|
|
||||||
|
- Replace `inquirer` with `@inquirer/prompts` ([#11321](https://github.com/vercel/vercel/pull/11321))
|
||||||
|
|
||||||
|
- Updated dependencies [[`73b112b1f`](https://github.com/vercel/vercel/commit/73b112b1f74480e1bb941e1b754105fc7dace401), [`346e665bb`](https://github.com/vercel/vercel/commit/346e665bb021e6034bc70c82ef336485622595fe), [`73b112b1f`](https://github.com/vercel/vercel/commit/73b112b1f74480e1bb941e1b754105fc7dace401), [`548afd371`](https://github.com/vercel/vercel/commit/548afd371aa7a9dd3a7f4c60f7f94a7084d8023e)]:
|
||||||
|
- @vercel/go@3.1.0
|
||||||
|
- @vercel/node@3.0.26
|
||||||
|
- @vercel/build-utils@7.11.0
|
||||||
|
- @vercel/static-build@2.4.6
|
||||||
|
|
||||||
|
## 33.6.2
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Added sunset warning to secrets command. ([#11333](https://github.com/vercel/vercel/pull/11333))
|
||||||
|
|
||||||
|
- Swap jest for vitest in CLI unit tests ([#11302](https://github.com/vercel/vercel/pull/11302))
|
||||||
|
|
||||||
|
- Updated dependencies [[`988f7b75a`](https://github.com/vercel/vercel/commit/988f7b75a27387e84fce541b844f984d2c151980), [`1825b58df`](https://github.com/vercel/vercel/commit/1825b58df8d783e79f0addf262618f422246f4b3)]:
|
||||||
|
- @vercel/remix-builder@2.1.5
|
||||||
|
- @vercel/build-utils@7.10.0
|
||||||
|
- @vercel/node@3.0.25
|
||||||
|
- @vercel/static-build@2.4.5
|
||||||
|
|
||||||
## 33.6.1
|
## 33.6.1
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "vercel",
|
"name": "vercel",
|
||||||
"version": "33.6.1",
|
"version": "33.6.3",
|
||||||
"preferGlobal": true,
|
"preferGlobal": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"description": "The command-line interface for Vercel",
|
"description": "The command-line interface for Vercel",
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "jest --reporters=default --reporters=jest-junit --env node --verbose --bail",
|
"test": "jest --reporters=default --reporters=jest-junit --env node --verbose --bail",
|
||||||
"test-unit": "pnpm test test/unit/",
|
"test-unit": "pnpm vitest test/unit/",
|
||||||
"test-e2e": "rimraf test/fixtures/integration && pnpm test test/integration-1.test.ts test/integration-2.test.ts test/integration-3.test.ts",
|
"test-e2e": "rimraf test/fixtures/integration && pnpm test test/integration-1.test.ts test/integration-2.test.ts test/integration-3.test.ts",
|
||||||
"test-dev": "pnpm test test/dev/",
|
"test-dev": "pnpm test test/dev/",
|
||||||
"coverage": "codecov",
|
"coverage": "codecov",
|
||||||
@@ -31,22 +31,27 @@
|
|||||||
"node": ">= 16"
|
"node": ">= 16"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vercel/build-utils": "7.9.1",
|
"@vercel/build-utils": "7.11.0",
|
||||||
"@vercel/fun": "1.1.0",
|
"@vercel/fun": "1.1.0",
|
||||||
"@vercel/go": "3.0.5",
|
"@vercel/go": "3.1.0",
|
||||||
"@vercel/hydrogen": "1.0.2",
|
"@vercel/hydrogen": "1.0.2",
|
||||||
"@vercel/next": "4.1.6",
|
"@vercel/next": "4.1.6",
|
||||||
"@vercel/node": "3.0.24",
|
"@vercel/node": "3.0.26",
|
||||||
"@vercel/python": "4.1.1",
|
"@vercel/python": "4.1.1",
|
||||||
"@vercel/redwood": "2.0.8",
|
"@vercel/redwood": "2.0.8",
|
||||||
"@vercel/remix-builder": "2.1.4",
|
"@vercel/remix-builder": "2.1.5",
|
||||||
"@vercel/ruby": "2.0.5",
|
"@vercel/ruby": "2.0.5",
|
||||||
"@vercel/static-build": "2.4.4",
|
"@vercel/static-build": "2.4.6",
|
||||||
"chokidar": "3.3.1"
|
"chokidar": "3.3.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@alex_neo/jest-expect-message": "1.0.5",
|
"@alex_neo/jest-expect-message": "1.0.5",
|
||||||
"@edge-runtime/node-utils": "2.3.0",
|
"@edge-runtime/node-utils": "2.3.0",
|
||||||
|
"@inquirer/checkbox": "2.2.0",
|
||||||
|
"@inquirer/confirm": "3.1.0",
|
||||||
|
"@inquirer/expand": "2.1.0",
|
||||||
|
"@inquirer/input": "2.1.1",
|
||||||
|
"@inquirer/select": "2.2.0",
|
||||||
"@next/env": "11.1.2",
|
"@next/env": "11.1.2",
|
||||||
"@sentry/node": "5.5.0",
|
"@sentry/node": "5.5.0",
|
||||||
"@sindresorhus/slugify": "0.11.0",
|
"@sindresorhus/slugify": "0.11.0",
|
||||||
@@ -63,7 +68,6 @@
|
|||||||
"@types/glob": "7.1.1",
|
"@types/glob": "7.1.1",
|
||||||
"@types/http-proxy": "1.16.2",
|
"@types/http-proxy": "1.16.2",
|
||||||
"@types/ini": "1.3.31",
|
"@types/ini": "1.3.31",
|
||||||
"@types/inquirer": "7.3.1",
|
|
||||||
"@types/jest": "27.4.1",
|
"@types/jest": "27.4.1",
|
||||||
"@types/jest-expect-message": "1.0.3",
|
"@types/jest-expect-message": "1.0.3",
|
||||||
"@types/json-parse-better-errors": "1.0.0",
|
"@types/json-parse-better-errors": "1.0.0",
|
||||||
@@ -88,12 +92,13 @@
|
|||||||
"@types/yauzl-promise": "2.1.0",
|
"@types/yauzl-promise": "2.1.0",
|
||||||
"@vercel-internals/constants": "1.0.4",
|
"@vercel-internals/constants": "1.0.4",
|
||||||
"@vercel-internals/get-package-json": "1.0.0",
|
"@vercel-internals/get-package-json": "1.0.0",
|
||||||
"@vercel-internals/types": "1.0.27",
|
"@vercel-internals/types": "1.0.29",
|
||||||
"@vercel/client": "13.1.7",
|
"@vercel/client": "13.1.9",
|
||||||
"@vercel/error-utils": "2.0.2",
|
"@vercel/error-utils": "2.0.2",
|
||||||
"@vercel/frameworks": "3.0.0",
|
"@vercel/frameworks": "3.0.1",
|
||||||
"@vercel/fs-detectors": "5.2.1",
|
"@vercel/fs-detectors": "5.2.2",
|
||||||
"@vercel/routing-utils": "3.1.0",
|
"@vercel/routing-utils": "3.1.0",
|
||||||
|
"@vitest/expect": "1.4.0",
|
||||||
"ajv": "6.12.2",
|
"ajv": "6.12.2",
|
||||||
"alpha-sort": "2.0.1",
|
"alpha-sort": "2.0.1",
|
||||||
"ansi-escapes": "4.3.2",
|
"ansi-escapes": "4.3.2",
|
||||||
@@ -126,7 +131,6 @@
|
|||||||
"glob": "7.1.2",
|
"glob": "7.1.2",
|
||||||
"http-proxy": "1.18.1",
|
"http-proxy": "1.18.1",
|
||||||
"ini": "3.0.0",
|
"ini": "3.0.0",
|
||||||
"inquirer": "7.0.4",
|
|
||||||
"is-docker": "2.2.1",
|
"is-docker": "2.2.1",
|
||||||
"is-port-reachable": "3.1.0",
|
"is-port-reachable": "3.1.0",
|
||||||
"is-url": "1.2.2",
|
"is-url": "1.2.2",
|
||||||
@@ -165,6 +169,8 @@
|
|||||||
"ts-node": "10.9.1",
|
"ts-node": "10.9.1",
|
||||||
"universal-analytics": "0.4.20",
|
"universal-analytics": "0.4.20",
|
||||||
"utility-types": "2.1.0",
|
"utility-types": "2.1.0",
|
||||||
|
"vite": "5.1.6",
|
||||||
|
"vitest": "1.3.1",
|
||||||
"which": "3.0.0",
|
"which": "3.0.0",
|
||||||
"write-json-file": "2.2.0",
|
"write-json-file": "2.2.0",
|
||||||
"xdg-app-paths": "5.1.0",
|
"xdg-app-paths": "5.1.0",
|
||||||
|
|||||||
@@ -278,9 +278,7 @@ export default async function bisect(client: Client): Promise<number> {
|
|||||||
if (openEnabled) {
|
if (openEnabled) {
|
||||||
await open(testUrl);
|
await open(testUrl);
|
||||||
}
|
}
|
||||||
const answer = await client.prompt({
|
action = await client.input.expand({
|
||||||
type: 'expand',
|
|
||||||
name: 'action',
|
|
||||||
message: 'Select an action:',
|
message: 'Select an action:',
|
||||||
choices: [
|
choices: [
|
||||||
{ key: 'g', name: 'Good', value: 'good' },
|
{ key: 'g', name: 'Good', value: 'good' },
|
||||||
@@ -288,7 +286,6 @@ export default async function bisect(client: Client): Promise<number> {
|
|||||||
{ key: 's', name: 'Skip', value: 'skip' },
|
{ key: 's', name: 'Skip', value: 'skip' },
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
action = answer.action;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action === 'good') {
|
if (action === 'good') {
|
||||||
@@ -342,11 +339,7 @@ function getCommit(deployment: Deployment) {
|
|||||||
async function prompt(client: Client, message: string): Promise<string> {
|
async function prompt(client: Client, message: string): Promise<string> {
|
||||||
// eslint-disable-next-line no-constant-condition
|
// eslint-disable-next-line no-constant-condition
|
||||||
while (true) {
|
while (true) {
|
||||||
const { val } = await client.prompt({
|
const val = await client.input.text({ message });
|
||||||
type: 'input',
|
|
||||||
name: 'val',
|
|
||||||
message,
|
|
||||||
});
|
|
||||||
if (val) {
|
if (val) {
|
||||||
return val;
|
return val;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import dotenv from 'dotenv';
|
|||||||
import semver from 'semver';
|
import semver from 'semver';
|
||||||
import minimatch from 'minimatch';
|
import minimatch from 'minimatch';
|
||||||
import { join, normalize, relative, resolve, sep } from 'path';
|
import { join, normalize, relative, resolve, sep } from 'path';
|
||||||
import frameworks from '@vercel/frameworks';
|
import { frameworkList } from '@vercel/frameworks';
|
||||||
import {
|
import {
|
||||||
getDiscontinuedNodeVersions,
|
getDiscontinuedNodeVersions,
|
||||||
normalizePath,
|
normalizePath,
|
||||||
@@ -695,7 +695,7 @@ async function getFramework(
|
|||||||
): Promise<{ version: string } | undefined> {
|
): Promise<{ version: string } | undefined> {
|
||||||
const detectedFramework = await detectFrameworkRecord({
|
const detectedFramework = await detectFrameworkRecord({
|
||||||
fs: new LocalFileSystemDetector(cwd),
|
fs: new LocalFileSystemDetector(cwd),
|
||||||
frameworkList: frameworks,
|
frameworkList,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!detectedFramework) {
|
if (!detectedFramework) {
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ function readConfirmation(output: Output, msg: string, certs: Cert[]) {
|
|||||||
}).replace(/^(.*)/gm, ' $1')}\n`
|
}).replace(/^(.*)/gm, ' $1')}\n`
|
||||||
);
|
);
|
||||||
output.print(
|
output.print(
|
||||||
`${chalk.bold.red('> Are you sure?')} ${chalk.gray('[y/N] ')}`
|
`${chalk.bold.red('> Are you sure?')} ${chalk.gray('(y/N) ')}`
|
||||||
);
|
);
|
||||||
process.stdin
|
process.stdin
|
||||||
.on('data', d => {
|
.on('data', d => {
|
||||||
|
|||||||
@@ -303,7 +303,10 @@ export default async (client: Client): Promise<number> => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// build `--prebuilt`
|
// build `--prebuilt`
|
||||||
|
let vercelOutputDir: string | undefined;
|
||||||
if (argv['--prebuilt']) {
|
if (argv['--prebuilt']) {
|
||||||
|
vercelOutputDir = join(cwd, '.vercel/output');
|
||||||
|
|
||||||
// For repo-style linking, update `cwd` to be the Project
|
// For repo-style linking, update `cwd` to be the Project
|
||||||
// subdirectory when `rootDirectory` setting is defined
|
// subdirectory when `rootDirectory` setting is defined
|
||||||
if (
|
if (
|
||||||
@@ -311,10 +314,10 @@ export default async (client: Client): Promise<number> => {
|
|||||||
link.repoRoot &&
|
link.repoRoot &&
|
||||||
link.project.rootDirectory
|
link.project.rootDirectory
|
||||||
) {
|
) {
|
||||||
cwd = join(cwd, link.project.rootDirectory);
|
vercelOutputDir = join(cwd, link.project.rootDirectory, '.vercel/output');
|
||||||
}
|
}
|
||||||
|
|
||||||
const prebuiltExists = await fs.pathExists(join(cwd, '.vercel/output'));
|
const prebuiltExists = await fs.pathExists(vercelOutputDir);
|
||||||
if (!prebuiltExists) {
|
if (!prebuiltExists) {
|
||||||
error(
|
error(
|
||||||
`The ${param(
|
`The ${param(
|
||||||
@@ -326,7 +329,7 @@ export default async (client: Client): Promise<number> => {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const prebuiltBuild = await getPrebuiltJson(cwd);
|
const prebuiltBuild = await getPrebuiltJson(vercelOutputDir);
|
||||||
|
|
||||||
// Ensure that there was not a build error
|
// Ensure that there was not a build error
|
||||||
const prebuiltError =
|
const prebuiltError =
|
||||||
@@ -545,6 +548,7 @@ export default async (client: Client): Promise<number> => {
|
|||||||
forceNew: argv['--force'],
|
forceNew: argv['--force'],
|
||||||
withCache: argv['--with-cache'],
|
withCache: argv['--with-cache'],
|
||||||
prebuilt: argv['--prebuilt'],
|
prebuilt: argv['--prebuilt'],
|
||||||
|
vercelOutputDir,
|
||||||
rootDirectory,
|
rootDirectory,
|
||||||
quiet,
|
quiet,
|
||||||
wantsPublic: Boolean(argv['--public'] || localConfig.public),
|
wantsPublic: Boolean(argv['--public'] || localConfig.public),
|
||||||
@@ -572,7 +576,7 @@ export default async (client: Client): Promise<number> => {
|
|||||||
nodeVersion,
|
nodeVersion,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (status !== 'not_linked') {
|
if (status === 'linked') {
|
||||||
createArgs.projectSettings = {
|
createArgs.projectSettings = {
|
||||||
...createArgs.projectSettings,
|
...createArgs.projectSettings,
|
||||||
...localConfigurationOverrides,
|
...localConfigurationOverrides,
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ function readConfirmation(
|
|||||||
}).replace(/^(.*)/gm, ' $1')}\n`
|
}).replace(/^(.*)/gm, ' $1')}\n`
|
||||||
);
|
);
|
||||||
output.print(
|
output.print(
|
||||||
`${chalk.bold.red('> Are you sure?')} ${chalk.gray('[y/N] ')}`
|
`${chalk.bold.red('> Are you sure?')} ${chalk.gray('(y/N) ')}`
|
||||||
);
|
);
|
||||||
process.stdin
|
process.stdin
|
||||||
.on('data', d => {
|
.on('data', d => {
|
||||||
|
|||||||
27
packages/cli/src/commands/env/add.ts
vendored
27
packages/cli/src/commands/env/add.ts
vendored
@@ -29,9 +29,6 @@ export default async function add(
|
|||||||
args: string[],
|
args: string[],
|
||||||
output: Output
|
output: Output
|
||||||
) {
|
) {
|
||||||
// improve the way we show inquirer prompts
|
|
||||||
require('../../util/input/patch-inquirer');
|
|
||||||
|
|
||||||
const stdInput = await readStandardInput(client.stdin);
|
const stdInput = await readStandardInput(client.stdin);
|
||||||
let [envName, envTargetArg, envGitBranch] = args;
|
let [envName, envTargetArg, envGitBranch] = args;
|
||||||
|
|
||||||
@@ -67,15 +64,11 @@ export default async function add(
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (!envName) {
|
while (!envName) {
|
||||||
const { inputName } = await client.prompt({
|
envName = await client.input.text({
|
||||||
type: 'input',
|
|
||||||
name: 'inputName',
|
|
||||||
message: `What’s the name of the variable?`,
|
message: `What’s the name of the variable?`,
|
||||||
});
|
});
|
||||||
|
|
||||||
envName = inputName;
|
if (!envName) {
|
||||||
|
|
||||||
if (!inputName) {
|
|
||||||
output.error('Name cannot be empty');
|
output.error('Name cannot be empty');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -107,9 +100,7 @@ export default async function add(
|
|||||||
if (stdInput) {
|
if (stdInput) {
|
||||||
envValue = stdInput;
|
envValue = stdInput;
|
||||||
} else {
|
} else {
|
||||||
const { inputValue } = await client.prompt({
|
const inputValue = await client.input.text({
|
||||||
type: 'input',
|
|
||||||
name: 'inputValue',
|
|
||||||
message: `What’s the value of ${envName}?`,
|
message: `What’s the value of ${envName}?`,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -117,16 +108,12 @@ export default async function add(
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (envTargets.length === 0) {
|
while (envTargets.length === 0) {
|
||||||
const { inputTargets } = await client.prompt({
|
envTargets = await client.input.checkbox({
|
||||||
name: 'inputTargets',
|
|
||||||
type: 'checkbox',
|
|
||||||
message: `Add ${envName} to which Environments (select multiple)?`,
|
message: `Add ${envName} to which Environments (select multiple)?`,
|
||||||
choices,
|
choices,
|
||||||
});
|
});
|
||||||
|
|
||||||
envTargets = inputTargets;
|
if (envTargets.length === 0) {
|
||||||
|
|
||||||
if (inputTargets.length === 0) {
|
|
||||||
output.error('Please select at least one Environment');
|
output.error('Please select at least one Environment');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -137,9 +124,7 @@ export default async function add(
|
|||||||
envTargets.length === 1 &&
|
envTargets.length === 1 &&
|
||||||
envTargets[0] === 'preview'
|
envTargets[0] === 'preview'
|
||||||
) {
|
) {
|
||||||
const { inputValue } = await client.prompt({
|
const inputValue = await client.input.text({
|
||||||
type: 'input',
|
|
||||||
name: 'inputValue',
|
|
||||||
message: `Add ${envName} to which Git branch? (leave empty for all Preview branches)?`,
|
message: `Add ${envName} to which Git branch? (leave empty for all Preview branches)?`,
|
||||||
});
|
});
|
||||||
envGitBranch = inputValue || '';
|
envGitBranch = inputValue || '';
|
||||||
|
|||||||
11
packages/cli/src/commands/env/rm.ts
vendored
11
packages/cli/src/commands/env/rm.ts
vendored
@@ -29,9 +29,6 @@ export default async function rm(
|
|||||||
args: string[],
|
args: string[],
|
||||||
output: Output
|
output: Output
|
||||||
) {
|
) {
|
||||||
// improve the way we show inquirer prompts
|
|
||||||
require('../../util/input/patch-inquirer');
|
|
||||||
|
|
||||||
if (args.length > 3) {
|
if (args.length > 3) {
|
||||||
output.error(
|
output.error(
|
||||||
`Invalid number of arguments. Usage: ${getCommandName(
|
`Invalid number of arguments. Usage: ${getCommandName(
|
||||||
@@ -44,9 +41,7 @@ export default async function rm(
|
|||||||
let [envName, envTarget, envGitBranch] = args;
|
let [envName, envTarget, envGitBranch] = args;
|
||||||
|
|
||||||
while (!envName) {
|
while (!envName) {
|
||||||
const { inputName } = await client.prompt({
|
const inputName = await client.input.text({
|
||||||
type: 'input',
|
|
||||||
name: 'inputName',
|
|
||||||
message: `What’s the name of the variable?`,
|
message: `What’s the name of the variable?`,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -86,9 +81,7 @@ export default async function rm(
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (envs.length > 1) {
|
while (envs.length > 1) {
|
||||||
const { id } = await client.prompt({
|
const id = await client.input.select({
|
||||||
name: 'id',
|
|
||||||
type: 'list',
|
|
||||||
message: `Remove ${envName} from which Environments?`,
|
message: `Remove ${envName} from which Environments?`,
|
||||||
choices: envs.map(env => ({ value: env.id, name: formatEnvTarget(env) })),
|
choices: envs.map(env => ({ value: env.id, name: formatEnvTarget(env) })),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -277,7 +277,7 @@ function readConfirmation(
|
|||||||
}
|
}
|
||||||
|
|
||||||
output.print(
|
output.print(
|
||||||
`${chalk.bold.red('> Are you sure?')} ${chalk.gray('[y/N] ')}`
|
`${chalk.bold.red('> Are you sure?')} ${chalk.gray('(y/N) ')}`
|
||||||
);
|
);
|
||||||
|
|
||||||
process.stdin
|
process.stdin
|
||||||
|
|||||||
@@ -2,9 +2,14 @@ import { packageName, getCommandName } from '../../util/pkg-name';
|
|||||||
|
|
||||||
export const secretsCommand = {
|
export const secretsCommand = {
|
||||||
name: 'secrets',
|
name: 'secrets',
|
||||||
description: `NOTE: The ${getCommandName(
|
description:
|
||||||
|
'WARNING: On May 1st, 2024 secrets will be automatically converted to sensitive Environment Variables for Preview and Production environments. Secrets attached to Development environments will not be migrated.\n' +
|
||||||
|
`The ${getCommandName(
|
||||||
|
'secrets'
|
||||||
|
)} command will be deprecated at this time, please use the ${getCommandName(
|
||||||
'env'
|
'env'
|
||||||
)} command is recommended instead of ${getCommandName('secrets')}`,
|
)} command instead.\n` +
|
||||||
|
'See https://vercel.com/changelog/legacy-environment-variable-secrets-are-being-sunset for more information.',
|
||||||
arguments: [
|
arguments: [
|
||||||
{
|
{
|
||||||
name: 'command',
|
name: 'command',
|
||||||
|
|||||||
@@ -78,6 +78,12 @@ async function run({ output, contextName, currentTeam, client }) {
|
|||||||
|
|
||||||
const commandName = getCommandName('secret ' + subcommand);
|
const commandName = getCommandName('secret ' + subcommand);
|
||||||
|
|
||||||
|
output.warn(
|
||||||
|
'On May 1st, 2024 secrets will be automatically converted to sensitive Environment Variables for Preview and Production environments.\n' +
|
||||||
|
'Secrets attached to Development environments will not be migrated.' +
|
||||||
|
'See https://vercel.com/changelog/legacy-environment-variable-secrets-are-being-sunset for more information.'
|
||||||
|
);
|
||||||
|
|
||||||
if (subcommand === 'ls' || subcommand === 'list') {
|
if (subcommand === 'ls' || subcommand === 'list') {
|
||||||
output.note(
|
output.note(
|
||||||
`The ${getCommandName(
|
`The ${getCommandName(
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
import frameworkList from '@vercel/frameworks';
|
import { frameworkList } from '@vercel/frameworks';
|
||||||
|
|
||||||
export function sortBuilders<B extends { use: string }>(builds: B[]): B[] {
|
export function sortBuilders<B extends { use: string }>(builds: B[]): B[] {
|
||||||
const frontendRuntimeSet = new Set(
|
const frontendRuntimeSet = new Set(
|
||||||
frameworkList.map(f => f.useRuntime?.use || '@vercel/static-build')
|
frameworkList.map(f => f.useRuntime?.use || '@vercel/static-build')
|
||||||
);
|
);
|
||||||
const toNumber = (build: B) => (frontendRuntimeSet.has(build.use) ? 0 : 1);
|
const toNumber = (build: B) => (frontendRuntimeSet.has(build.use) ? 0 : 1);
|
||||||
|
|
||||||
return builds.sort((build1, build2) => {
|
return builds.sort((build1, build2) => {
|
||||||
return toNumber(build1) - toNumber(build2);
|
return toNumber(build1) - toNumber(build2);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
import { bold } from 'chalk';
|
import { bold, gray } from 'chalk';
|
||||||
import inquirer from 'inquirer';
|
import checkbox from '@inquirer/checkbox';
|
||||||
|
import confirm from '@inquirer/confirm';
|
||||||
|
import expand from '@inquirer/expand';
|
||||||
|
import input from '@inquirer/input';
|
||||||
|
import select from '@inquirer/select';
|
||||||
import { EventEmitter } from 'events';
|
import { EventEmitter } from 'events';
|
||||||
import { URL } from 'url';
|
import { URL } from 'url';
|
||||||
import { VercelConfig } from '@vercel/client';
|
import { VercelConfig } from '@vercel/client';
|
||||||
@@ -66,8 +70,8 @@ export default class Client extends EventEmitter implements Stdio {
|
|||||||
agent?: Agent;
|
agent?: Agent;
|
||||||
localConfig?: VercelConfig;
|
localConfig?: VercelConfig;
|
||||||
localConfigPath?: string;
|
localConfigPath?: string;
|
||||||
prompt!: inquirer.PromptModule;
|
|
||||||
requestIdCounter: number;
|
requestIdCounter: number;
|
||||||
|
input;
|
||||||
|
|
||||||
constructor(opts: ClientOptions) {
|
constructor(opts: ClientOptions) {
|
||||||
super();
|
super();
|
||||||
@@ -83,7 +87,29 @@ export default class Client extends EventEmitter implements Stdio {
|
|||||||
this.localConfig = opts.localConfig;
|
this.localConfig = opts.localConfig;
|
||||||
this.localConfigPath = opts.localConfigPath;
|
this.localConfigPath = opts.localConfigPath;
|
||||||
this.requestIdCounter = 1;
|
this.requestIdCounter = 1;
|
||||||
this._createPromptModule();
|
|
||||||
|
const theme = {
|
||||||
|
prefix: gray('?'),
|
||||||
|
style: { answer: gray },
|
||||||
|
};
|
||||||
|
this.input = {
|
||||||
|
text: (opts: Parameters<typeof input>[0]) =>
|
||||||
|
input({ theme, ...opts }, { input: this.stdin, output: this.stderr }),
|
||||||
|
checkbox: <T>(opts: Parameters<typeof checkbox<T>>[0]) =>
|
||||||
|
checkbox<T>(
|
||||||
|
{ theme, ...opts },
|
||||||
|
{ input: this.stdin, output: this.stderr }
|
||||||
|
),
|
||||||
|
expand: (opts: Parameters<typeof expand>[0]) =>
|
||||||
|
expand({ theme, ...opts }, { input: this.stdin, output: this.stderr }),
|
||||||
|
confirm: (opts: Parameters<typeof confirm>[0]) =>
|
||||||
|
confirm({ theme, ...opts }, { input: this.stdin, output: this.stderr }),
|
||||||
|
select: <T>(opts: Parameters<typeof select<T>>[0]) =>
|
||||||
|
select<T>(
|
||||||
|
{ theme, ...opts },
|
||||||
|
{ input: this.stdin, output: this.stderr }
|
||||||
|
),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
retry<T>(fn: RetryFunction<T>, { retries = 3, maxTimeout = Infinity } = {}) {
|
retry<T>(fn: RetryFunction<T>, { retries = 3, maxTimeout = Infinity } = {}) {
|
||||||
@@ -229,13 +255,6 @@ export default class Client extends EventEmitter implements Stdio {
|
|||||||
this.output.debug(`Retrying: ${error}\n${error.stack}`);
|
this.output.debug(`Retrying: ${error}\n${error.stack}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
_createPromptModule() {
|
|
||||||
this.prompt = inquirer.createPromptModule({
|
|
||||||
input: this.stdin as NodeJS.ReadStream,
|
|
||||||
output: this.stderr as NodeJS.WriteStream,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
get cwd(): string {
|
get cwd(): string {
|
||||||
return process.cwd();
|
return process.cwd();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ const getGlobalPathConfig = (): string => {
|
|||||||
];
|
];
|
||||||
|
|
||||||
// The customPath flag is the preferred location,
|
// The customPath flag is the preferred location,
|
||||||
// followed by the the vercel directory,
|
// followed by the vercel directory,
|
||||||
// followed by the now directory.
|
// followed by the now directory.
|
||||||
// If none of those exist, use the vercel directory.
|
// If none of those exist, use the vercel directory.
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ export default async function getPrebuiltJson(
|
|||||||
directory: string
|
directory: string
|
||||||
): Promise<BuildsManifest | null> {
|
): Promise<BuildsManifest | null> {
|
||||||
try {
|
try {
|
||||||
return await fs.readJSON(join(directory, '.vercel/output/builds.json'));
|
return await fs.readJSON(join(directory, 'builds.json'));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// ignoring error
|
// ignoring error
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ export default async function processDeployment({
|
|||||||
withCache?: boolean;
|
withCache?: boolean;
|
||||||
org: Org;
|
org: Org;
|
||||||
prebuilt: boolean;
|
prebuilt: boolean;
|
||||||
|
vercelOutputDir?: string;
|
||||||
projectName: string;
|
projectName: string;
|
||||||
isSettingUpProject: boolean;
|
isSettingUpProject: boolean;
|
||||||
archive?: ArchiveFormat;
|
archive?: ArchiveFormat;
|
||||||
@@ -71,6 +72,7 @@ export default async function processDeployment({
|
|||||||
withCache,
|
withCache,
|
||||||
quiet,
|
quiet,
|
||||||
prebuilt,
|
prebuilt,
|
||||||
|
vercelOutputDir,
|
||||||
rootDirectory,
|
rootDirectory,
|
||||||
} = args;
|
} = args;
|
||||||
|
|
||||||
@@ -92,6 +94,7 @@ export default async function processDeployment({
|
|||||||
force,
|
force,
|
||||||
withCache,
|
withCache,
|
||||||
prebuilt,
|
prebuilt,
|
||||||
|
vercelOutputDir,
|
||||||
rootDirectory,
|
rootDirectory,
|
||||||
skipAutoDetectionConfirmation,
|
skipAutoDetectionConfirmation,
|
||||||
archive,
|
archive,
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ import {
|
|||||||
detectApiExtensions,
|
detectApiExtensions,
|
||||||
isOfficialRuntime,
|
isOfficialRuntime,
|
||||||
} from '@vercel/fs-detectors';
|
} from '@vercel/fs-detectors';
|
||||||
import frameworkList from '@vercel/frameworks';
|
import { frameworkList } from '@vercel/frameworks';
|
||||||
|
|
||||||
import cmd from '../output/cmd';
|
import cmd from '../output/cmd';
|
||||||
import link from '../output/link';
|
import link from '../output/link';
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ export interface CreateOptions {
|
|||||||
project?: string;
|
project?: string;
|
||||||
wantsPublic: boolean;
|
wantsPublic: boolean;
|
||||||
prebuilt?: boolean;
|
prebuilt?: boolean;
|
||||||
|
vercelOutputDir?: string;
|
||||||
rootDirectory?: string | null;
|
rootDirectory?: string | null;
|
||||||
meta: Dictionary<string>;
|
meta: Dictionary<string>;
|
||||||
gitMetadata?: GitMetadata;
|
gitMetadata?: GitMetadata;
|
||||||
@@ -117,6 +118,7 @@ export default class Now extends EventEmitter {
|
|||||||
name,
|
name,
|
||||||
project,
|
project,
|
||||||
prebuilt = false,
|
prebuilt = false,
|
||||||
|
vercelOutputDir,
|
||||||
rootDirectory,
|
rootDirectory,
|
||||||
wantsPublic,
|
wantsPublic,
|
||||||
meta,
|
meta,
|
||||||
@@ -179,6 +181,7 @@ export default class Now extends EventEmitter {
|
|||||||
skipAutoDetectionConfirmation,
|
skipAutoDetectionConfirmation,
|
||||||
cwd,
|
cwd,
|
||||||
prebuilt,
|
prebuilt,
|
||||||
|
vercelOutputDir,
|
||||||
rootDirectory,
|
rootDirectory,
|
||||||
noWait,
|
noWait,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -5,14 +5,8 @@ export default async function confirm(
|
|||||||
message: string,
|
message: string,
|
||||||
preferred: boolean
|
preferred: boolean
|
||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
require('./patch-inquirer');
|
return client.input.confirm({
|
||||||
|
|
||||||
const answers = await client.prompt({
|
|
||||||
type: 'confirm',
|
|
||||||
name: 'value',
|
|
||||||
message,
|
message,
|
||||||
default: preferred,
|
default: preferred,
|
||||||
});
|
});
|
||||||
|
|
||||||
return answers.value;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import inquirer from 'inquirer';
|
|
||||||
import confirm from './confirm';
|
import confirm from './confirm';
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
import frameworkList, { Framework } from '@vercel/frameworks';
|
import { frameworkList, Framework } from '@vercel/frameworks';
|
||||||
import Client from '../client';
|
import Client from '../client';
|
||||||
import { isSettingValue } from '../is-setting-value';
|
import { isSettingValue } from '../is-setting-value';
|
||||||
import type { ProjectSettings } from '@vercel-internals/types';
|
import type { ProjectSettings } from '@vercel-internals/types';
|
||||||
@@ -125,48 +124,26 @@ export default async function editProjectSettings(
|
|||||||
return settings;
|
return settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
const choices = settingKeys.reduce<Array<{ name: string; value: string }>>(
|
const choices = settingKeys.reduce((acc, setting) => {
|
||||||
(acc, setting) => {
|
|
||||||
const skip =
|
const skip =
|
||||||
setting === 'framework' ||
|
setting === 'framework' ||
|
||||||
setting === 'commandForIgnoringBuildStep' ||
|
setting === 'commandForIgnoringBuildStep' ||
|
||||||
setting === 'installCommand' ||
|
setting === 'installCommand' ||
|
||||||
localConfigurationOverrides?.[setting];
|
localConfigurationOverrides?.[setting];
|
||||||
if (!skip) {
|
if (skip) return acc;
|
||||||
acc.push({ name: settingMap[setting], value: setting });
|
return [...acc, { name: settingMap[setting], value: setting }];
|
||||||
}
|
}, [] as { name: string; value: ConfigKeys }[]);
|
||||||
return acc;
|
|
||||||
},
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
|
|
||||||
const { settingFields } = await inquirer.prompt<{
|
const settingFields = await client.input.checkbox({
|
||||||
settingFields: Array<
|
|
||||||
Exclude<
|
|
||||||
ConfigKeys,
|
|
||||||
'framework' | 'commandForIgnoringBuildStep' | 'installCommand'
|
|
||||||
>
|
|
||||||
>;
|
|
||||||
}>({
|
|
||||||
name: 'settingFields',
|
|
||||||
type: 'checkbox',
|
|
||||||
message: 'Which settings would you like to overwrite (select multiple)?',
|
message: 'Which settings would you like to overwrite (select multiple)?',
|
||||||
choices,
|
choices,
|
||||||
});
|
});
|
||||||
|
|
||||||
for (let setting of settingFields) {
|
for (let setting of settingFields) {
|
||||||
const field = settingMap[setting];
|
const field = settingMap[setting];
|
||||||
const answers = await inquirer.prompt<{
|
settings[setting] = await client.input.text({
|
||||||
[k in Exclude<
|
|
||||||
ConfigKeys,
|
|
||||||
'framework' | 'commandForIgnoringBuildStep' | 'installCommand'
|
|
||||||
>]: string;
|
|
||||||
}>({
|
|
||||||
type: 'input',
|
|
||||||
name: setting,
|
|
||||||
message: `What's your ${chalk.bold(field)}?`,
|
message: `What's your ${chalk.bold(field)}?`,
|
||||||
});
|
});
|
||||||
settings[setting] = answers[setting];
|
|
||||||
}
|
}
|
||||||
return settings;
|
return settings;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,12 +78,9 @@ export default async function inputProject(
|
|||||||
let project: Project | ProjectNotFound | null = null;
|
let project: Project | ProjectNotFound | null = null;
|
||||||
|
|
||||||
while (!project || project instanceof ProjectNotFound) {
|
while (!project || project instanceof ProjectNotFound) {
|
||||||
const answers = await client.prompt({
|
const projectName = await client.input.text({
|
||||||
type: 'input',
|
message: 'What’s the name of your existing project?',
|
||||||
name: 'existingProjectName',
|
|
||||||
message: `What’s the name of your existing project?`,
|
|
||||||
});
|
});
|
||||||
const projectName = answers.existingProjectName as string;
|
|
||||||
|
|
||||||
if (!projectName) {
|
if (!projectName) {
|
||||||
output.error(`Project name cannot be empty`);
|
output.error(`Project name cannot be empty`);
|
||||||
@@ -109,13 +106,10 @@ export default async function inputProject(
|
|||||||
let newProjectName: string | null = null;
|
let newProjectName: string | null = null;
|
||||||
|
|
||||||
while (!newProjectName) {
|
while (!newProjectName) {
|
||||||
const answers = await client.prompt({
|
newProjectName = await client.input.text({
|
||||||
type: 'input',
|
|
||||||
name: 'newProjectName',
|
|
||||||
message: `What’s your project’s name?`,
|
message: `What’s your project’s name?`,
|
||||||
default: !detectedProject ? slugifiedName : undefined,
|
default: !detectedProject ? slugifiedName : undefined,
|
||||||
});
|
});
|
||||||
newProjectName = answers.newProjectName as string;
|
|
||||||
|
|
||||||
if (!newProjectName) {
|
if (!newProjectName) {
|
||||||
output.error(`Project name cannot be empty`);
|
output.error(`Project name cannot be empty`);
|
||||||
|
|||||||
@@ -14,9 +14,7 @@ export async function inputRootDirectory(
|
|||||||
|
|
||||||
// eslint-disable-next-line no-constant-condition
|
// eslint-disable-next-line no-constant-condition
|
||||||
while (true) {
|
while (true) {
|
||||||
const { rootDirectory } = await client.prompt({
|
const rootDirectory = await client.input.text({
|
||||||
type: 'input',
|
|
||||||
name: 'rootDirectory',
|
|
||||||
message: `In which directory is your code located?`,
|
message: `In which directory is your code located?`,
|
||||||
transformer: (input: string) => {
|
transformer: (input: string) => {
|
||||||
return `${chalk.dim(`./`)}${input}`;
|
return `${chalk.dim(`./`)}${input}`;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import inquirer from 'inquirer';
|
import { Separator } from '@inquirer/select';
|
||||||
import stripAnsi from 'strip-ansi';
|
import stripAnsi from 'strip-ansi';
|
||||||
import Client from '../client';
|
import Client from '../client';
|
||||||
import eraseLines from '../output/erase-lines';
|
import eraseLines from '../output/erase-lines';
|
||||||
@@ -14,7 +14,7 @@ interface ListSeparator {
|
|||||||
separator: string;
|
separator: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ListChoice = ListEntry | ListSeparator | typeof inquirer.Separator;
|
export type ListChoice = ListEntry | ListSeparator | typeof Separator;
|
||||||
|
|
||||||
interface ListOptions {
|
interface ListOptions {
|
||||||
message: string;
|
message: string;
|
||||||
@@ -54,8 +54,6 @@ export default async function list(
|
|||||||
eraseFinalAnswer = false, // If true, the line with the final answer that inquirer prints will be erased before returning
|
eraseFinalAnswer = false, // If true, the line with the final answer that inquirer prints will be erased before returning
|
||||||
}: ListOptions
|
}: ListOptions
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
require('./patch-inquirer');
|
|
||||||
|
|
||||||
let biggestLength = 0;
|
let biggestLength = 0;
|
||||||
let selected: string | undefined;
|
let selected: string | undefined;
|
||||||
|
|
||||||
@@ -70,14 +68,14 @@ export default async function list(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const choices = _choices.map(choice => {
|
const choices = _choices.map(choice => {
|
||||||
if (choice instanceof inquirer.Separator) {
|
if (choice instanceof Separator) {
|
||||||
return choice;
|
return choice;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('separator' in choice) {
|
if ('separator' in choice) {
|
||||||
const prefix = `── ${choice.separator} `;
|
const prefix = `── ${choice.separator} `;
|
||||||
const suffix = '─'.repeat(biggestLength - getLength(prefix));
|
const suffix = '─'.repeat(biggestLength - getLength(prefix));
|
||||||
return new inquirer.Separator(`${prefix}${suffix}`);
|
return new Separator(`${prefix}${suffix}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('short' in choice) {
|
if ('short' in choice) {
|
||||||
@@ -93,11 +91,11 @@ export default async function list(
|
|||||||
|
|
||||||
if (separator) {
|
if (separator) {
|
||||||
for (let i = 0; i < choices.length; i += 2) {
|
for (let i = 0; i < choices.length; i += 2) {
|
||||||
choices.splice(i, 0, new inquirer.Separator(' '));
|
choices.splice(i, 0, new Separator(' '));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const cancelSeparator = new inquirer.Separator('─'.repeat(biggestLength));
|
const cancelSeparator = new Separator('─'.repeat(biggestLength));
|
||||||
const _cancel = {
|
const _cancel = {
|
||||||
name: 'Cancel',
|
name: 'Cancel',
|
||||||
value: '',
|
value: '',
|
||||||
@@ -110,18 +108,16 @@ export default async function list(
|
|||||||
choices.push(cancelSeparator, _cancel);
|
choices.push(cancelSeparator, _cancel);
|
||||||
}
|
}
|
||||||
|
|
||||||
const answer = await client.prompt({
|
const answer = await client.input.select({
|
||||||
name: 'value',
|
|
||||||
type: 'list',
|
|
||||||
default: selected,
|
|
||||||
message,
|
message,
|
||||||
choices,
|
choices,
|
||||||
pageSize,
|
pageSize,
|
||||||
|
default: selected,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (eraseFinalAnswer === true) {
|
if (eraseFinalAnswer === true) {
|
||||||
process.stdout.write(eraseLines(2));
|
process.stdout.write(eraseLines(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
return answer.value;
|
return answer;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,210 +0,0 @@
|
|||||||
import chalk from 'chalk';
|
|
||||||
import inquirer from 'inquirer';
|
|
||||||
import Prompt from 'inquirer/lib/prompts/base';
|
|
||||||
import Choice from 'inquirer/lib/objects/choice';
|
|
||||||
import Separator from 'inquirer/lib/objects/separator';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Here we patch inquirer with some tweaks:
|
|
||||||
* - update "list" to use ● and ○ and hide tips
|
|
||||||
* - update "checkbox" to use ◻︎ and ◼︎ and hide tips
|
|
||||||
* - use '?' before questions
|
|
||||||
* - do not apply color to question's answer
|
|
||||||
*/
|
|
||||||
|
|
||||||
// adjusted from https://github.com/SBoudrias/Inquirer.js/blob/942908f17319343d1acc7b876f990797c5695918/packages/inquirer/lib/prompts/base.js#L126
|
|
||||||
const getQuestion = function (this: Prompt) {
|
|
||||||
let message = `${chalk.gray('?')} ${this.opt.message} `;
|
|
||||||
|
|
||||||
if (this.opt.type === 'confirm') {
|
|
||||||
if (this.opt.default === 'y/N') {
|
|
||||||
message += `[y/${chalk.bold('N')}] `;
|
|
||||||
} else {
|
|
||||||
message += `[${chalk.bold('Y')}/n] `;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Append the default if available, and if question isn't answered
|
|
||||||
else if (this.opt.default != null && this.status !== 'answered') {
|
|
||||||
message += chalk.dim(`(${this.opt.default}) `);
|
|
||||||
}
|
|
||||||
|
|
||||||
return message;
|
|
||||||
};
|
|
||||||
|
|
||||||
inquirer.prompt.prompts.list.prototype.getQuestion = getQuestion;
|
|
||||||
inquirer.prompt.prompts.checkbox.prototype.getQuestion = getQuestion;
|
|
||||||
inquirer.prompt.prompts.input.prototype.getQuestion = getQuestion;
|
|
||||||
inquirer.prompt.prompts.confirm.prototype.getQuestion = getQuestion;
|
|
||||||
|
|
||||||
// adjusted from https://github.com/SBoudrias/Inquirer.js/blob/942908f17319343d1acc7b876f990797c5695918/packages/inquirer/lib/prompts/list.js#L80
|
|
||||||
inquirer.prompt.prompts.list.prototype.render = function () {
|
|
||||||
// Render question
|
|
||||||
let message = this.getQuestion();
|
|
||||||
|
|
||||||
// Render choices or answer depending on the state
|
|
||||||
if (this.status === 'answered') {
|
|
||||||
message += this.opt.choices.getChoice(this.selected).short;
|
|
||||||
} else {
|
|
||||||
let choicesStr = listRender(this.opt.choices, this.selected);
|
|
||||||
let indexPosition = this.opt.choices.indexOf(
|
|
||||||
this.opt.choices.getChoice(this.selected)
|
|
||||||
);
|
|
||||||
message +=
|
|
||||||
'\n' +
|
|
||||||
this.paginator.paginate(choicesStr, indexPosition, this.opt.pageSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.firstRender = false;
|
|
||||||
|
|
||||||
this.screen.render(message);
|
|
||||||
};
|
|
||||||
|
|
||||||
function listRender(choices: (Choice | Separator)[], pointer: number) {
|
|
||||||
let output = '';
|
|
||||||
let separatorOffset = 0;
|
|
||||||
|
|
||||||
choices.forEach((choice, i) => {
|
|
||||||
if (choice.type === 'separator') {
|
|
||||||
separatorOffset++;
|
|
||||||
output += ' ' + choice + '\n';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (choice.disabled) {
|
|
||||||
separatorOffset++;
|
|
||||||
output += ' - ' + choice.name;
|
|
||||||
output +=
|
|
||||||
' (' +
|
|
||||||
(typeof choice.disabled === 'string' ? choice.disabled : 'Disabled') +
|
|
||||||
')';
|
|
||||||
output += '\n';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let isSelected = i - separatorOffset === pointer;
|
|
||||||
let line = (isSelected ? '● ' : '○ ') + choice.name;
|
|
||||||
|
|
||||||
if (isSelected) {
|
|
||||||
line = chalk.cyan(line);
|
|
||||||
}
|
|
||||||
output += line + ' \n';
|
|
||||||
});
|
|
||||||
|
|
||||||
return output.replace(/\n$/, '');
|
|
||||||
}
|
|
||||||
|
|
||||||
// adjusted from https://github.com/SBoudrias/Inquirer.js/blob/942908f17319343d1acc7b876f990797c5695918/packages/inquirer/lib/prompts/checkbox.js#L84
|
|
||||||
inquirer.prompt.prompts.checkbox.prototype.render = function (error?: string) {
|
|
||||||
// Render question
|
|
||||||
let message = this.getQuestion();
|
|
||||||
let bottomContent = '';
|
|
||||||
|
|
||||||
if (!this.spaceKeyPressed) {
|
|
||||||
message +=
|
|
||||||
'(Press ' +
|
|
||||||
chalk.cyan.bold('<space>') +
|
|
||||||
' to select, ' +
|
|
||||||
chalk.cyan.bold('<a>') +
|
|
||||||
' to toggle all, ' +
|
|
||||||
chalk.cyan.bold('<i>') +
|
|
||||||
' to invert selection)';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Render choices or answer depending on the state
|
|
||||||
if (this.status === 'answered') {
|
|
||||||
message += this.selection.length > 0 ? this.selection.join(', ') : 'None';
|
|
||||||
} else {
|
|
||||||
let choicesStr = renderChoices(this.opt.choices, this.pointer);
|
|
||||||
let indexPosition = this.opt.choices.indexOf(
|
|
||||||
this.opt.choices.getChoice(this.pointer)
|
|
||||||
);
|
|
||||||
message +=
|
|
||||||
'\n' +
|
|
||||||
this.paginator.paginate(choicesStr, indexPosition, this.opt.pageSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
bottomContent = chalk.red('>> ') + error;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.screen.render(message, bottomContent);
|
|
||||||
};
|
|
||||||
|
|
||||||
function renderChoices(choices: (Choice | Separator)[], pointer: number) {
|
|
||||||
let output = '';
|
|
||||||
let separatorOffset = 0;
|
|
||||||
|
|
||||||
choices.forEach(function (choice, i) {
|
|
||||||
if (choice.type === 'separator') {
|
|
||||||
separatorOffset++;
|
|
||||||
output += '' + choice + '\n';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (choice.disabled) {
|
|
||||||
separatorOffset++;
|
|
||||||
output += '- ' + choice.name;
|
|
||||||
output +=
|
|
||||||
' (' +
|
|
||||||
(typeof choice.disabled === 'string' ? choice.disabled : 'Disabled') +
|
|
||||||
')';
|
|
||||||
} else {
|
|
||||||
if (i - separatorOffset === pointer) {
|
|
||||||
output += chalk.cyan(
|
|
||||||
(choice.checked ? '› ▪︎' : '› ▫︎') + ' ' + choice.name
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
output += chalk.cyan(
|
|
||||||
(choice.checked ? ' ▪︎' : ' ▫︎') + ' ' + choice.name
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
output += '\n';
|
|
||||||
});
|
|
||||||
|
|
||||||
return output.replace(/\n$/, '');
|
|
||||||
}
|
|
||||||
|
|
||||||
// adjusted from https://github.com/SBoudrias/Inquirer.js/blob/942908f17319343d1acc7b876f990797c5695918/packages/inquirer/lib/prompts/input.js#L44
|
|
||||||
inquirer.prompt.prompts.input.prototype.render = function (error?: string) {
|
|
||||||
let bottomContent = '';
|
|
||||||
let appendContent = '';
|
|
||||||
let message = this.getQuestion();
|
|
||||||
let transformer = this.opt.transformer;
|
|
||||||
let isFinal = this.status === 'answered';
|
|
||||||
|
|
||||||
if (isFinal) {
|
|
||||||
appendContent = this.answer;
|
|
||||||
} else {
|
|
||||||
appendContent = this.rl.line;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (transformer) {
|
|
||||||
message += transformer(appendContent, this.answers, { isFinal });
|
|
||||||
} else {
|
|
||||||
message += appendContent;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
bottomContent = chalk.red('>> ') + error;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.screen.render(message, bottomContent);
|
|
||||||
};
|
|
||||||
|
|
||||||
// adjusted from https://github.com/SBoudrias/Inquirer.js/blob/942908f17319343d1acc7b876f990797c5695918/packages/inquirer/lib/prompts/confirm.js#L64
|
|
||||||
inquirer.prompt.prompts.confirm.prototype.render = function (answer?: boolean) {
|
|
||||||
let message = this.getQuestion();
|
|
||||||
|
|
||||||
if (this.status === 'answered') {
|
|
||||||
message += answer ? 'y' : 'n';
|
|
||||||
} else {
|
|
||||||
message += this.rl.line;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.screen.render(message);
|
|
||||||
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
@@ -10,7 +10,6 @@ export default async function selectOrg(
|
|||||||
question: string,
|
question: string,
|
||||||
autoConfirm?: boolean
|
autoConfirm?: boolean
|
||||||
): Promise<Org> {
|
): Promise<Org> {
|
||||||
require('./patch-inquirer');
|
|
||||||
const {
|
const {
|
||||||
output,
|
output,
|
||||||
config: { currentTeam },
|
config: { currentTeam },
|
||||||
@@ -52,14 +51,9 @@ export default async function selectOrg(
|
|||||||
return choices[defaultChoiceIndex].value;
|
return choices[defaultChoiceIndex].value;
|
||||||
}
|
}
|
||||||
|
|
||||||
const answers = await client.prompt({
|
return await client.input.select({
|
||||||
type: 'list',
|
|
||||||
name: 'org',
|
|
||||||
message: question,
|
message: question,
|
||||||
choices,
|
choices,
|
||||||
default: defaultChoiceIndex,
|
default: choices[defaultChoiceIndex].value,
|
||||||
});
|
});
|
||||||
|
|
||||||
const org = answers.org;
|
|
||||||
return org;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ export default function text({
|
|||||||
// Tab
|
// Tab
|
||||||
// Right arrow
|
// Right arrow
|
||||||
autoCompleteChars = new Set(['\t', '\x1b[C']),
|
autoCompleteChars = new Set(['\t', '\x1b[C']),
|
||||||
// If true, converts everything the user types to to lowercase
|
// If true, converts everything the user types to lowercase
|
||||||
forceLowerCase = false,
|
forceLowerCase = false,
|
||||||
}: TextParams = {}): Promise<string> {
|
}: TextParams = {}): Promise<string> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
import inquirer from 'inquirer';
|
import { Separator } from '@inquirer/checkbox';
|
||||||
import pluralize from 'pluralize';
|
import pluralize from 'pluralize';
|
||||||
import { homedir } from 'os';
|
import { homedir } from 'os';
|
||||||
import slugify from '@sindresorhus/slugify';
|
import slugify from '@sindresorhus/slugify';
|
||||||
@@ -144,16 +144,13 @@ export async function ensureRepoLink(
|
|||||||
if (yes) {
|
if (yes) {
|
||||||
remoteName = defaultRemote;
|
remoteName = defaultRemote;
|
||||||
} else {
|
} else {
|
||||||
const answer = await client.prompt({
|
remoteName = await client.input.select({
|
||||||
type: 'list',
|
|
||||||
name: 'value',
|
|
||||||
message: 'Which Git remote should be used?',
|
message: 'Which Git remote should be used?',
|
||||||
choices: remoteNames.map(name => {
|
choices: remoteNames.map(name => {
|
||||||
return { name: name, value: name };
|
return { name: name, value: name };
|
||||||
}),
|
}),
|
||||||
default: defaultRemote,
|
default: defaultRemote,
|
||||||
});
|
});
|
||||||
remoteName = answer.value;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const repoUrl = remoteUrls[remoteName];
|
const repoUrl = remoteUrls[remoteName];
|
||||||
@@ -222,15 +219,13 @@ export async function ensureRepoLink(
|
|||||||
selected = projects;
|
selected = projects;
|
||||||
} else {
|
} else {
|
||||||
const addSeparators = projects.length > 0 && detectedProjectsCount > 0;
|
const addSeparators = projects.length > 0 && detectedProjectsCount > 0;
|
||||||
const answer = await client.prompt({
|
selected = await client.input.checkbox<Project | NewProject>({
|
||||||
type: 'checkbox',
|
|
||||||
name: 'selected',
|
|
||||||
message: `Which Projects should be ${
|
message: `Which Projects should be ${
|
||||||
projects.length ? 'linked to' : 'created'
|
projects.length ? 'linked to' : 'created'
|
||||||
}?`,
|
}?`,
|
||||||
choices: [
|
choices: [
|
||||||
...(addSeparators
|
...(addSeparators
|
||||||
? [new inquirer.Separator('----- Existing Projects -----')]
|
? [new Separator('----- Existing Projects -----')]
|
||||||
: []),
|
: []),
|
||||||
...projects.map(project => {
|
...projects.map(project => {
|
||||||
return {
|
return {
|
||||||
@@ -240,7 +235,7 @@ export async function ensureRepoLink(
|
|||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
...(addSeparators
|
...(addSeparators
|
||||||
? [new inquirer.Separator('----- New Projects to be created -----')]
|
? [new Separator('----- New Projects to be created -----')]
|
||||||
: []),
|
: []),
|
||||||
...Array.from(detectedProjects.entries()).flatMap(
|
...Array.from(detectedProjects.entries()).flatMap(
|
||||||
([rootDirectory, frameworks]) =>
|
([rootDirectory, frameworks]) =>
|
||||||
@@ -264,12 +259,11 @@ export async function ensureRepoLink(
|
|||||||
},
|
},
|
||||||
// Checked by default when there are no other existing Projects
|
// Checked by default when there are no other existing Projects
|
||||||
checked: projects.length === 0,
|
checked: projects.length === 0,
|
||||||
};
|
} as const;
|
||||||
})
|
})
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
selected = answer.selected;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selected.length === 0) {
|
if (selected.length === 0) {
|
||||||
|
|||||||
@@ -62,12 +62,7 @@ export async function readInput(
|
|||||||
|
|
||||||
while (!input) {
|
while (!input) {
|
||||||
try {
|
try {
|
||||||
const { val } = await client.prompt({
|
input = await client.input.text({ message });
|
||||||
type: 'input',
|
|
||||||
name: 'val',
|
|
||||||
message,
|
|
||||||
});
|
|
||||||
input = val;
|
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
console.log(); // \n
|
console.log(); // \n
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
import frameworkList, { Framework } from '@vercel/frameworks';
|
import { frameworkList, Framework } from '@vercel/frameworks';
|
||||||
import {
|
import {
|
||||||
detectFrameworks,
|
detectFrameworks,
|
||||||
getWorkspacePackagePaths,
|
getWorkspacePackagePaths,
|
||||||
|
|||||||
@@ -97,16 +97,13 @@ async function getProjectLinkFromRepoLink(
|
|||||||
} else {
|
} else {
|
||||||
const selectableProjects =
|
const selectableProjects =
|
||||||
projects.length > 0 ? projects : repoLink.repoConfig.projects;
|
projects.length > 0 ? projects : repoLink.repoConfig.projects;
|
||||||
const { p } = await client.prompt({
|
project = await client.input.select({
|
||||||
name: 'p',
|
|
||||||
type: 'list',
|
|
||||||
message: `Please select a Project:`,
|
message: `Please select a Project:`,
|
||||||
choices: selectableProjects.map(p => ({
|
choices: selectableProjects.map(p => ({
|
||||||
value: p,
|
value: p,
|
||||||
name: p.name,
|
name: p.name,
|
||||||
})),
|
})),
|
||||||
});
|
});
|
||||||
project = p;
|
|
||||||
}
|
}
|
||||||
if (project) {
|
if (project) {
|
||||||
return {
|
return {
|
||||||
|
|||||||
6
packages/cli/test/dev/fixtures/08-hugo/package.json
Normal file
6
packages/cli/test/dev/fixtures/08-hugo/package.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"private": true,
|
||||||
|
"engines": {
|
||||||
|
"node": "16.x"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,6 +10,6 @@ menu:
|
|||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
This is an example of a custom shortcode that you can put right into your content. You will need to add a form action to the the shortcode to make it work. Check out [Formspree](https://formspree.io/) for a simple, free form service.
|
This is an example of a custom shortcode that you can put right into your content. You will need to add a form action to the shortcode to make it work. Check out [Formspree](https://formspree.io/) for a simple, free form service.
|
||||||
|
|
||||||
{{< form-contact action="https://example.com" >}}
|
{{< form-contact action="https://example.com" >}}
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"private": true,
|
||||||
|
"engines": {
|
||||||
|
"node": "16.x"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"private": true,
|
||||||
|
"engines": {
|
||||||
|
"node": "16.x"
|
||||||
|
}
|
||||||
|
}
|
||||||
6
packages/cli/test/dev/fixtures/go/package.json
Normal file
6
packages/cli/test/dev/fixtures/go/package.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"private": true,
|
||||||
|
"engines": {
|
||||||
|
"node": "16.x"
|
||||||
|
}
|
||||||
|
}
|
||||||
6
packages/cli/test/dev/fixtures/python-flask/package.json
Normal file
6
packages/cli/test/dev/fixtures/python-flask/package.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"private": true,
|
||||||
|
"engines": {
|
||||||
|
"node": "16.x"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import { name } from '../backend/app'
|
||||||
|
|
||||||
|
export default async function handler(request, response) {
|
||||||
|
return response.status(200).send(`Hello, ${name}!`);
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export const name = 'Batman'
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"name": "vercel-ts-test",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"main": "index.js",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
}
|
||||||
|
}
|
||||||
4
packages/cli/test/dev/fixtures/vercel-ts-test/yarn.lock
Normal file
4
packages/cli/test/dev/fixtures/vercel-ts-test/yarn.lock
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||||
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
@@ -119,7 +119,6 @@ test(
|
|||||||
await testPath(200, `/api/date`, new RegExp(`Current date is ${year}`));
|
await testPath(200, `/api/date`, new RegExp(`Current date is ${year}`));
|
||||||
await testPath(200, `/api/date.py`, new RegExp(`Current date is ${year}`));
|
await testPath(200, `/api/date.py`, new RegExp(`Current date is ${year}`));
|
||||||
await testPath(200, `/api/headers`, (body: any, res: any) => {
|
await testPath(200, `/api/headers`, (body: any, res: any) => {
|
||||||
// @ts-ignore
|
|
||||||
const { host } = new URL(res.url);
|
const { host } = new URL(res.url);
|
||||||
expect(body).toBe(host);
|
expect(body).toBe(host);
|
||||||
});
|
});
|
||||||
@@ -198,7 +197,6 @@ test(
|
|||||||
);
|
);
|
||||||
|
|
||||||
await testPath(200, `/api/dump`, (body: any, res: any, isDev: any) => {
|
await testPath(200, `/api/dump`, (body: any, res: any, isDev: any) => {
|
||||||
// @ts-ignore
|
|
||||||
const { host } = new URL(res.url);
|
const { host } = new URL(res.url);
|
||||||
const { env, headers } = JSON.parse(body);
|
const { env, headers } = JSON.parse(body);
|
||||||
|
|
||||||
|
|||||||
@@ -544,4 +544,18 @@ describe('[vercel dev] ESM serverless functions', () => {
|
|||||||
{ skipDeploy: true }
|
{ skipDeploy: true }
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
test(
|
||||||
|
'[vercel dev] TypeScript importing another TS file, type=commonjs',
|
||||||
|
testFixtureStdio(
|
||||||
|
'vercel-ts-test',
|
||||||
|
async (_testPath: any, port: number) => {
|
||||||
|
const res = await fetch(`http://localhost:${port}/api/test`);
|
||||||
|
validateResponseHeaders(res);
|
||||||
|
const text = await res.text();
|
||||||
|
expect(text).toEqual('Hello, Batman!');
|
||||||
|
},
|
||||||
|
{ skipDeploy: true }
|
||||||
|
)
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -7,5 +7,8 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"exeggcute": "^1.0.0",
|
"exeggcute": "^1.0.0",
|
||||||
"once": "^1.4.0"
|
"once": "^1.4.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "18.x"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -348,6 +348,9 @@ module.exports = async function prepare(session, binaryPath, tmpFixturesDir) {
|
|||||||
},
|
},
|
||||||
'lambda-with-php-runtime': {
|
'lambda-with-php-runtime': {
|
||||||
'api/test.php': `<?php echo 'Hello from PHP'; ?>`,
|
'api/test.php': `<?php echo 'Hello from PHP'; ?>`,
|
||||||
|
'package.json': JSON.stringify({
|
||||||
|
engines: { node: '18.x' },
|
||||||
|
}),
|
||||||
'vercel.json': JSON.stringify({
|
'vercel.json': JSON.stringify({
|
||||||
functions: {
|
functions: {
|
||||||
'api/**/*.php': {
|
'api/**/*.php': {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { afterAll } from 'vitest';
|
||||||
import findUp from 'find-up';
|
import findUp from 'find-up';
|
||||||
import fs from 'fs-extra';
|
import fs from 'fs-extra';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import stripAnsi from 'strip-ansi';
|
||||||
import type { CLIProcess } from './types';
|
import type { CLIProcess } from './types';
|
||||||
|
|
||||||
function getPromptErrorDetails(
|
function getPromptErrorDetails(
|
||||||
@@ -54,7 +55,7 @@ export default async function waitForPrompt(
|
|||||||
};
|
};
|
||||||
|
|
||||||
const onData = (rawChunk: Buffer) => {
|
const onData = (rawChunk: Buffer) => {
|
||||||
const chunk = rawChunk.toString();
|
const chunk = stripAnsi(rawChunk.toString());
|
||||||
|
|
||||||
mostRecentChunk = chunk;
|
mostRecentChunk = chunk;
|
||||||
console.log('> ' + chunk);
|
console.log('> ' + chunk);
|
||||||
|
|||||||
4
packages/cli/test/integration-3.test.ts
vendored
4
packages/cli/test/integration-3.test.ts
vendored
@@ -617,7 +617,7 @@ test('ensure we render a prompt when deploying home directory', async () => {
|
|||||||
binaryPath,
|
binaryPath,
|
||||||
[directory, '--public', '--name', session, '--force'],
|
[directory, '--public', '--name', session, '--force'],
|
||||||
{
|
{
|
||||||
input: 'N',
|
input: 'N\n',
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -625,7 +625,7 @@ test('ensure we render a prompt when deploying home directory', async () => {
|
|||||||
expect(exitCode, formatOutput({ stdout, stderr })).toBe(0);
|
expect(exitCode, formatOutput({ stdout, stderr })).toBe(0);
|
||||||
|
|
||||||
expect(stderr).toContain(
|
expect(stderr).toContain(
|
||||||
'You are deploying your home directory. Do you want to continue? [y/N]'
|
'You are deploying your home directory. Do you want to continue?'
|
||||||
);
|
);
|
||||||
expect(stderr).toContain('Canceled');
|
expect(stderr).toContain('Canceled');
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
const originalCwd = process.cwd();
|
const originalCwd = process.cwd();
|
||||||
|
import { afterAll, beforeAll, afterEach } from 'vitest';
|
||||||
|
|
||||||
// Register Jest matcher extensions for CLI unit tests
|
// Register Jest matcher extensions for CLI unit tests
|
||||||
import './matchers';
|
import './matchers';
|
||||||
@@ -93,8 +94,6 @@ export class MockClient extends Client {
|
|||||||
this.stderr.pause();
|
this.stderr.pause();
|
||||||
this.stderr.isTTY = true;
|
this.stderr.isTTY = true;
|
||||||
|
|
||||||
this._createPromptModule();
|
|
||||||
|
|
||||||
this.output = new Output(this.stderr);
|
this.output = new Output(this.stderr);
|
||||||
|
|
||||||
this.argv = [];
|
this.argv = [];
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { beforeEach } from 'vitest';
|
||||||
import { URL } from 'url';
|
import { URL } from 'url';
|
||||||
import chance from 'chance';
|
import chance from 'chance';
|
||||||
import { client } from './client';
|
import { client } from './client';
|
||||||
|
|||||||
@@ -1,63 +1,13 @@
|
|||||||
/**
|
import { expect } from 'vitest';
|
||||||
* This file registers the custom Jest "matchers" that are useful for
|
import { toOutput } from './matchers';
|
||||||
* writing CLI unit tests, and sets them up to be recognized by TypeScript.
|
|
||||||
*
|
|
||||||
* References:
|
|
||||||
* - https://haspar.us/notes/adding-jest-custom-matchers-in-typescript
|
|
||||||
* - https://gist.github.com/hasparus/4ebaa17ec5d3d44607f522bcb1cda9fb
|
|
||||||
*/
|
|
||||||
|
|
||||||
/// <reference types="@types/jest" />
|
interface ToOutputMatchers<R = unknown> {
|
||||||
|
toOutput: (test: string, timeout?: number) => Promise<R>;
|
||||||
|
}
|
||||||
|
|
||||||
import * as matchers from './matchers';
|
declare module 'vitest' {
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
||||||
type Tail<T extends unknown[]> = T extends [infer _Head, ...infer Tail]
|
|
||||||
? Tail
|
|
||||||
: never;
|
|
||||||
|
|
||||||
type AnyFunction = (...args: any[]) => any;
|
|
||||||
type PromiseFunction = (...args: any[]) => Promise<any>;
|
|
||||||
|
|
||||||
type GetMatcherType<TP, TResult> = TP extends PromiseFunction
|
|
||||||
? (...args: Tail<Parameters<TP>>) => Promise<TResult>
|
|
||||||
: TP extends AnyFunction
|
|
||||||
? (...args: Tail<Parameters<TP>>) => TResult
|
|
||||||
: TP;
|
|
||||||
|
|
||||||
type GetMatchersType<TMatchers, TResult> = {
|
|
||||||
[P in keyof TMatchers]: GetMatcherType<TMatchers[P], TResult>;
|
|
||||||
};
|
|
||||||
|
|
||||||
type FirstParam<T extends AnyFunction> = Parameters<T>[0];
|
|
||||||
|
|
||||||
type OnlyMethodsWhereFirstArgIsOfType<TObject, TWantedFirstArg> = {
|
|
||||||
[P in keyof TObject]: TObject[P] extends AnyFunction
|
|
||||||
? TWantedFirstArg extends FirstParam<TObject[P]>
|
|
||||||
? TObject[P]
|
|
||||||
: [
|
|
||||||
`Error: this function is present only when received is:`,
|
|
||||||
FirstParam<TObject[P]>
|
|
||||||
]
|
|
||||||
: TObject[P];
|
|
||||||
};
|
|
||||||
|
|
||||||
declare global {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
||||||
namespace jest {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
||||||
interface Matchers<R, T = {}>
|
interface Assertion<T = any> extends ToOutputMatchers<T> {}
|
||||||
extends GetMatchersType<
|
|
||||||
OnlyMethodsWhereFirstArgIsOfType<typeof matchers, T>,
|
|
||||||
R
|
|
||||||
> {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const jestExpect = (global as any).expect;
|
expect.extend({ toOutput });
|
||||||
|
|
||||||
if (jestExpect !== undefined) {
|
|
||||||
jestExpect.extend(matchers);
|
|
||||||
} else {
|
|
||||||
console.error("Couldn't find Jest's global expect.");
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -5,15 +5,19 @@ import {
|
|||||||
printReceived,
|
printReceived,
|
||||||
} from 'jest-matcher-utils';
|
} from 'jest-matcher-utils';
|
||||||
import type { Readable } from 'stream';
|
import type { Readable } from 'stream';
|
||||||
import type { MatcherState } from 'expect';
|
import type { MatcherState } from '@vitest/expect';
|
||||||
import type { MatcherHintOptions } from 'jest-matcher-utils';
|
import type { MatcherHintOptions } from 'jest-matcher-utils';
|
||||||
|
import stripAnsi from 'strip-ansi';
|
||||||
|
|
||||||
export async function toOutput(
|
export async function toOutput(
|
||||||
this: MatcherState,
|
this: MatcherState,
|
||||||
stream: Readable,
|
stream: Readable,
|
||||||
test: string,
|
test: string,
|
||||||
timeout = 3000
|
timeout = 3000
|
||||||
) {
|
): Promise<{
|
||||||
|
pass: boolean;
|
||||||
|
message: () => string;
|
||||||
|
}> {
|
||||||
const { isNot } = this;
|
const { isNot } = this;
|
||||||
const matcherName = 'toOutput';
|
const matcherName = 'toOutput';
|
||||||
const matcherHintOptions: MatcherHintOptions = {
|
const matcherHintOptions: MatcherHintOptions = {
|
||||||
@@ -27,7 +31,7 @@ export async function toOutput(
|
|||||||
matcherHint(matcherName, 'stream', 'test', matcherHintOptions) + '\n\n';
|
matcherHint(matcherName, 'stream', 'test', matcherHintOptions) + '\n\n';
|
||||||
|
|
||||||
function onData(data: string) {
|
function onData(data: string) {
|
||||||
output += data;
|
output += stripAnsi(data);
|
||||||
if (output.includes(test)) {
|
if (output.includes(test)) {
|
||||||
cleanup();
|
cleanup();
|
||||||
resolve({
|
resolve({
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||||
|
|
||||||
exports[`help command help output snapshots column width 40 1`] = `
|
exports[`help command > help output snapshots > column width 40 1`] = `
|
||||||
"
|
"
|
||||||
▲ [1mvercel[22m [1mdeploy[22m [project-path] [options]
|
▲ [1mvercel[22m [1mdeploy[22m [project-path] [options]
|
||||||
|
|
||||||
@@ -186,7 +186,7 @@ exports[`help command help output snapshots column width 40 1`] = `
|
|||||||
"
|
"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`help command help output snapshots column width 80 1`] = `
|
exports[`help command > help output snapshots > column width 80 1`] = `
|
||||||
"
|
"
|
||||||
▲ [1mvercel[22m [1mdeploy[22m [project-path] [options]
|
▲ [1mvercel[22m [1mdeploy[22m [project-path] [options]
|
||||||
|
|
||||||
@@ -260,7 +260,7 @@ exports[`help command help output snapshots column width 80 1`] = `
|
|||||||
"
|
"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`help command help output snapshots column width 120 1`] = `
|
exports[`help command > help output snapshots > column width 120 1`] = `
|
||||||
"
|
"
|
||||||
▲ [1mvercel[22m [1mdeploy[22m [project-path] [options]
|
▲ [1mvercel[22m [1mdeploy[22m [project-path] [options]
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { describe, expect, it } from 'vitest';
|
||||||
import { client } from '../../mocks/client';
|
import { client } from '../../mocks/client';
|
||||||
import alias from '../../../src/commands/alias';
|
import alias from '../../../src/commands/alias';
|
||||||
import { useUser } from '../../mocks/user';
|
import { useUser } from '../../mocks/user';
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { describe, expect, it } from 'vitest';
|
||||||
import { client } from '../../mocks/client';
|
import { client } from '../../mocks/client';
|
||||||
import { useUser } from '../../mocks/user';
|
import { useUser } from '../../mocks/user';
|
||||||
import bisect from '../../../src/commands/bisect';
|
import bisect from '../../../src/commands/bisect';
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { beforeAll, beforeEach, describe, expect, it } from 'vitest';
|
||||||
import fs from 'fs-extra';
|
import fs from 'fs-extra';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
import { getWriteableDirectory } from '@vercel/build-utils';
|
import { getWriteableDirectory } from '@vercel/build-utils';
|
||||||
@@ -7,8 +8,9 @@ import { defaultProject, useProject } from '../../../mocks/project';
|
|||||||
import { useTeams } from '../../../mocks/team';
|
import { useTeams } from '../../../mocks/team';
|
||||||
import { useUser } from '../../../mocks/user';
|
import { useUser } from '../../../mocks/user';
|
||||||
import { execSync } from 'child_process';
|
import { execSync } from 'child_process';
|
||||||
|
import { vi } from 'vitest';
|
||||||
|
|
||||||
jest.setTimeout(6 * 60 * 1000);
|
vi.setConfig({ testTimeout: 6 * 60 * 1000 });
|
||||||
|
|
||||||
const fixture = (name: string) =>
|
const fixture = (name: string) =>
|
||||||
join(__dirname, '../../../fixtures/unit/commands/build', name);
|
join(__dirname, '../../../fixtures/unit/commands/build', name);
|
||||||
@@ -932,7 +934,7 @@ describe('build', () => {
|
|||||||
name: 'Error',
|
name: 'Error',
|
||||||
message:
|
message:
|
||||||
'Invalid vercel.json - `rewrites[2]` should NOT have additional property `src`. Did you mean `source`?',
|
'Invalid vercel.json - `rewrites[2]` should NOT have additional property `src`. Did you mean `source`?',
|
||||||
stack: expect.stringContaining('at validateConfig'),
|
stack: expect.stringContaining('at Module.validateConfig'),
|
||||||
hideStackTrace: true,
|
hideStackTrace: true,
|
||||||
code: 'INVALID_VERCEL_CONFIG',
|
code: 'INVALID_VERCEL_CONFIG',
|
||||||
link: 'https://vercel.com/docs/concepts/projects/project-configuration#rewrites',
|
link: 'https://vercel.com/docs/concepts/projects/project-configuration#rewrites',
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { describe, expect, it } from 'vitest';
|
||||||
import { client } from '../../mocks/client';
|
import { client } from '../../mocks/client';
|
||||||
import certs from '../../../src/commands/certs';
|
import certs from '../../../src/commands/certs';
|
||||||
import { useUser } from '../../mocks/user';
|
import { useUser } from '../../mocks/user';
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { describe, expect, it } from 'vitest';
|
||||||
import bytes from 'bytes';
|
import bytes from 'bytes';
|
||||||
import fs from 'fs-extra';
|
import fs from 'fs-extra';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { describe, expect, it } from 'vitest';
|
||||||
import { client } from '../../mocks/client';
|
import { client } from '../../mocks/client';
|
||||||
import dns from '../../../src/commands/dns';
|
import dns from '../../../src/commands/dns';
|
||||||
import { useUser } from '../../mocks/user';
|
import { useUser } from '../../mocks/user';
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { describe, expect, it } from 'vitest';
|
||||||
import { client } from '../../mocks/client';
|
import { client } from '../../mocks/client';
|
||||||
import domains from '../../../src/commands/domains';
|
import domains from '../../../src/commands/domains';
|
||||||
import { useUser } from '../../mocks/user';
|
import { useUser } from '../../mocks/user';
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { describe, expect, it } from 'vitest';
|
||||||
import fs from 'fs-extra';
|
import fs from 'fs-extra';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { parse } from 'dotenv';
|
import { parse } from 'dotenv';
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { describe, expect, it } from 'vitest';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
import fs from 'fs-extra';
|
import fs from 'fs-extra';
|
||||||
import { useUser } from '../../mocks/user';
|
import { useUser } from '../../mocks/user';
|
||||||
@@ -526,7 +527,7 @@ describe('git', () => {
|
|||||||
`Found a repository in your local Git Config: https://github.com/user/repo`
|
`Found a repository in your local Git Config: https://github.com/user/repo`
|
||||||
);
|
);
|
||||||
await expect(client.stderr).toOutput(
|
await expect(client.stderr).toOutput(
|
||||||
`Do you still want to connect https://github.com/user2/repo2? [y/N]`
|
`Do you still want to connect https://github.com/user2/repo2? (y/N)`
|
||||||
);
|
);
|
||||||
client.stdin.write('y\n');
|
client.stdin.write('y\n');
|
||||||
await expect(client.stderr).toOutput(
|
await expect(client.stderr).toOutput(
|
||||||
@@ -574,7 +575,7 @@ describe('git', () => {
|
|||||||
`Found multiple Git repositories in your local Git config:\n • origin: https://github.com/user/repo.git\n • secondary: https://github.com/user/repo2.git`
|
`Found multiple Git repositories in your local Git config:\n • origin: https://github.com/user/repo.git\n • secondary: https://github.com/user/repo2.git`
|
||||||
);
|
);
|
||||||
await expect(client.stderr).toOutput(
|
await expect(client.stderr).toOutput(
|
||||||
`Do you still want to connect https://github.com/user3/repo3? [y/N]`
|
`Do you still want to connect https://github.com/user3/repo3? (y/N)`
|
||||||
);
|
);
|
||||||
client.stdin.write('y\n');
|
client.stdin.write('y\n');
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { describe, expect, test } from 'vitest';
|
||||||
import {
|
import {
|
||||||
help,
|
help,
|
||||||
lineToString,
|
lineToString,
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { describe, expect, it } from 'vitest';
|
||||||
import { client } from '../../mocks/client';
|
import { client } from '../../mocks/client';
|
||||||
import { useUser } from '../../mocks/user';
|
import { useUser } from '../../mocks/user';
|
||||||
import { useDeployment } from '../../mocks/deployment';
|
import { useDeployment } from '../../mocks/deployment';
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { describe, it, expect } from 'vitest';
|
||||||
import { basename, join } from 'path';
|
import { basename, join } from 'path';
|
||||||
import { readJSON } from 'fs-extra';
|
import { readJSON } from 'fs-extra';
|
||||||
import link from '../../../src/commands/link';
|
import link from '../../../src/commands/link';
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { describe, it, expect } from 'vitest';
|
||||||
import createLineIterator from 'line-async-iterator';
|
import createLineIterator from 'line-async-iterator';
|
||||||
import { client } from '../../mocks/client';
|
import { client } from '../../mocks/client';
|
||||||
import { useUser } from '../../mocks/user';
|
import { useUser } from '../../mocks/user';
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
|
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
||||||
import login from '../../../src/commands/login';
|
import login from '../../../src/commands/login';
|
||||||
import { emoji } from '../../../src/util/emoji';
|
import { emoji } from '../../../src/util/emoji';
|
||||||
import { client } from '../../mocks/client';
|
import { client } from '../../mocks/client';
|
||||||
import { useUser } from '../../mocks/user';
|
import { useUser } from '../../mocks/user';
|
||||||
|
import { vi } from 'vitest';
|
||||||
|
|
||||||
jest.setTimeout(10000);
|
vi.setConfig({ testTimeout: 10000 });
|
||||||
|
|
||||||
describe('login', () => {
|
describe('login', () => {
|
||||||
it('should not allow the `--token` flag', async () => {
|
it('should not allow the `--token` flag', async () => {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { describe, it, expect } from 'vitest';
|
||||||
import createLineIterator from 'line-async-iterator';
|
import createLineIterator from 'line-async-iterator';
|
||||||
import projects from '../../../src/commands/project';
|
import projects from '../../../src/commands/project';
|
||||||
import { useUser } from '../../mocks/user';
|
import { useUser } from '../../mocks/user';
|
||||||
@@ -45,55 +46,6 @@ describe('project', () => {
|
|||||||
expect(data).toEqual([project.project.name, 'https://foobar.com']);
|
expect(data).toEqual([project.project.name, 'https://foobar.com']);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should list projects running on an soon-to-be-deprecated Node.js version', async () => {
|
|
||||||
jest.useFakeTimers().setSystemTime(new Date('2023-12-08'));
|
|
||||||
|
|
||||||
const user = useUser();
|
|
||||||
useTeams('team_dummy');
|
|
||||||
const project = useProject({
|
|
||||||
...defaultProject,
|
|
||||||
nodeVersion: '16.x',
|
|
||||||
});
|
|
||||||
|
|
||||||
client.setArgv('project', 'ls', '--update-required');
|
|
||||||
await projects(client);
|
|
||||||
|
|
||||||
const lines = createLineIterator(client.stderr);
|
|
||||||
|
|
||||||
let line = await lines.next();
|
|
||||||
expect(line.value).toEqual(`Fetching projects in ${user.username}`);
|
|
||||||
|
|
||||||
line = await lines.next();
|
|
||||||
expect(line.value).toEqual(
|
|
||||||
'WARN! The following Node.js versions will be deprecated soon: 16.x. Please upgrade your projects immediately.'
|
|
||||||
);
|
|
||||||
line = await lines.next();
|
|
||||||
expect(line.value).toEqual(
|
|
||||||
'> For more information visit: https://vercel.com/docs/functions/serverless-functions/runtimes/node-js#node.js-version'
|
|
||||||
);
|
|
||||||
line = await lines.next();
|
|
||||||
expect(line.value).toContain(user.username);
|
|
||||||
|
|
||||||
// empty line
|
|
||||||
line = await lines.next();
|
|
||||||
expect(line.value).toEqual('');
|
|
||||||
|
|
||||||
line = await lines.next();
|
|
||||||
const header = parseSpacedTableRow(line.value!);
|
|
||||||
expect(header).toEqual([
|
|
||||||
'Project Name',
|
|
||||||
'Latest Production URL',
|
|
||||||
'Updated',
|
|
||||||
]);
|
|
||||||
|
|
||||||
line = await lines.next();
|
|
||||||
const data = parseSpacedTableRow(line.value!);
|
|
||||||
data.pop();
|
|
||||||
expect(data).toEqual([project.project.name, 'https://foobar.com']);
|
|
||||||
|
|
||||||
jest.clearAllTimers();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should list projects when there is no production deployment', async () => {
|
it('should list projects when there is no production deployment', async () => {
|
||||||
const user = useUser();
|
const user = useUser();
|
||||||
useTeams('team_dummy');
|
useTeams('team_dummy');
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { describe, expect, it } from 'vitest';
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
import { client } from '../../mocks/client';
|
import { client } from '../../mocks/client';
|
||||||
import { defaultProject, useProject } from '../../mocks/project';
|
import { defaultProject, useProject } from '../../mocks/project';
|
||||||
@@ -9,8 +10,9 @@ import { useDeployment } from '../../mocks/deployment';
|
|||||||
import { useTeams } from '../../mocks/team';
|
import { useTeams } from '../../mocks/team';
|
||||||
import { useUser } from '../../mocks/user';
|
import { useUser } from '../../mocks/user';
|
||||||
import sleep from '../../../src/util/sleep';
|
import sleep from '../../../src/util/sleep';
|
||||||
|
import { vi } from 'vitest';
|
||||||
|
|
||||||
jest.setTimeout(60000);
|
vi.setConfig({ testTimeout: 60000 });
|
||||||
|
|
||||||
describe('promote', () => {
|
describe('promote', () => {
|
||||||
it('should error if timeout is invalid', async () => {
|
it('should error if timeout is invalid', async () => {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { describe, expect, it } from 'vitest';
|
||||||
import fs from 'fs-extra';
|
import fs from 'fs-extra';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import pull from '../../../src/commands/pull';
|
import pull from '../../../src/commands/pull';
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { describe, expect, it } from 'vitest';
|
||||||
import { client } from '../../mocks/client';
|
import { client } from '../../mocks/client';
|
||||||
import { defaultProject, useProject } from '../../mocks/project';
|
import { defaultProject, useProject } from '../../mocks/project';
|
||||||
import redeploy from '../../../src/commands/redeploy';
|
import redeploy from '../../../src/commands/redeploy';
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { describe, expect, it } from 'vitest';
|
||||||
import { client } from '../../mocks/client';
|
import { client } from '../../mocks/client';
|
||||||
import {
|
import {
|
||||||
defaultProject,
|
defaultProject,
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { describe, expect, it } from 'vitest';
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
import { client } from '../../mocks/client';
|
import { client } from '../../mocks/client';
|
||||||
import { defaultProject, useProject } from '../../mocks/project';
|
import { defaultProject, useProject } from '../../mocks/project';
|
||||||
@@ -9,8 +10,9 @@ import { useDeployment } from '../../mocks/deployment';
|
|||||||
import { useTeams } from '../../mocks/team';
|
import { useTeams } from '../../mocks/team';
|
||||||
import { useUser } from '../../mocks/user';
|
import { useUser } from '../../mocks/user';
|
||||||
import sleep from '../../../src/util/sleep';
|
import sleep from '../../../src/util/sleep';
|
||||||
|
import { vi } from 'vitest';
|
||||||
|
|
||||||
jest.setTimeout(60000);
|
vi.setConfig({ testTimeout: 60000 });
|
||||||
|
|
||||||
describe('rollback', () => {
|
describe('rollback', () => {
|
||||||
it('should error if timeout is invalid', async () => {
|
it('should error if timeout is invalid', async () => {
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user