mirror of
https://github.com/LukeHagar/vercel.git
synced 2025-12-11 12:57:46 +00:00
Compare commits
55 Commits
@vercel/no
...
@vercel/py
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6d312d85b2 | ||
|
|
10d4e51ac5 | ||
|
|
57231a0d60 | ||
|
|
e0e9cffc8d | ||
|
|
d0d0520111 | ||
|
|
9bb3067de2 | ||
|
|
decdf27fb5 | ||
|
|
4b376a564a | ||
|
|
b7e93524e3 | ||
|
|
62283356b8 | ||
|
|
3305f5e832 | ||
|
|
a938706916 | ||
|
|
b8bc682d3e | ||
|
|
f5ca497b75 | ||
|
|
b0898a6659 | ||
|
|
ab329f0fe8 | ||
|
|
8b35333446 | ||
|
|
a92467719b | ||
|
|
f6f16b0347 | ||
|
|
92ad73b8f3 | ||
|
|
849eedf0f2 | ||
|
|
848a62e4a5 | ||
|
|
cb784aeb9c | ||
|
|
3035e18fb6 | ||
|
|
eb40c4c4a0 | ||
|
|
c90ee12b17 | ||
|
|
78be0200b4 | ||
|
|
1b6f3a0f65 | ||
|
|
eceb15ace9 | ||
|
|
fa3f701e05 | ||
|
|
9953fc765f | ||
|
|
29ea1af971 | ||
|
|
083aad448e | ||
|
|
314a105ba1 | ||
|
|
1abda9ca87 | ||
|
|
7a0fed970c | ||
|
|
2f461a8b0b | ||
|
|
ec894bdf7f | ||
|
|
009cea6d30 | ||
|
|
1bab21026e | ||
|
|
bcebab7517 | ||
|
|
45b73c7e86 | ||
|
|
a732d30c84 | ||
|
|
8504735808 | ||
|
|
9d64312aaa | ||
|
|
a8ad176262 | ||
|
|
0ee089a501 | ||
|
|
d8bc570f60 | ||
|
|
f15cba6148 | ||
|
|
989f0d8139 | ||
|
|
6784e77516 | ||
|
|
6baefc825a | ||
|
|
0a08e4b23e | ||
|
|
b265e13d40 | ||
|
|
50e04dd858 |
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
@@ -10,7 +10,7 @@
|
|||||||
/packages/edge @vercel/compute
|
/packages/edge @vercel/compute
|
||||||
/examples @leerob
|
/examples @leerob
|
||||||
/examples/create-react-app @Timer
|
/examples/create-react-app @Timer
|
||||||
/examples/nextjs @timneutkens @ijjk @styfle @ztanner
|
/examples/nextjs @timneutkens @ijjk @styfle @ztanner @huozhi
|
||||||
/examples/hugo @styfle
|
/examples/hugo @styfle
|
||||||
/examples/jekyll @styfle
|
/examples/jekyll @styfle
|
||||||
/examples/zola @styfle
|
/examples/zola @styfle
|
||||||
|
|||||||
13
.github/workflows/test.yml
vendored
13
.github/workflows/test.yml
vendored
@@ -83,7 +83,7 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
FORCE_COLOR: '1'
|
FORCE_COLOR: '1'
|
||||||
- name: Test ${{matrix.packageName}}
|
- name: Test ${{matrix.packageName}}
|
||||||
run: node utils/gen.js && node_modules/.bin/turbo run test --cache-dir=".turbo" --log-order=stream --scope=${{matrix.packageName}} --no-deps -- ${{ join(matrix.testPaths, ' ') }}
|
run: node utils/gen.js && node_modules/.bin/turbo run test --summarize --cache-dir=".turbo" --log-order=stream --scope=${{matrix.packageName}} --no-deps -- ${{ join(matrix.testPaths, ' ') }}
|
||||||
shell: bash
|
shell: bash
|
||||||
env:
|
env:
|
||||||
JEST_JUNIT_OUTPUT_FILE: ${{github.workspace}}/.junit-reports/${{matrix.scriptName}}-${{matrix.packageName}}-${{matrix.chunkNumber}}-${{ matrix.runner }}.xml
|
JEST_JUNIT_OUTPUT_FILE: ${{github.workspace}}/.junit-reports/${{matrix.scriptName}}-${{matrix.packageName}}-${{matrix.chunkNumber}}-${{ matrix.runner }}.xml
|
||||||
@@ -91,13 +91,18 @@ jobs:
|
|||||||
VERCEL_TEST_TOKEN: ${{ secrets.VERCEL_TEST_TOKEN }}
|
VERCEL_TEST_TOKEN: ${{ secrets.VERCEL_TEST_TOKEN }}
|
||||||
VERCEL_TEST_REGISTRATION_URL: ${{ secrets.VERCEL_TEST_REGISTRATION_URL }}
|
VERCEL_TEST_REGISTRATION_URL: ${{ secrets.VERCEL_TEST_REGISTRATION_URL }}
|
||||||
FORCE_COLOR: '1'
|
FORCE_COLOR: '1'
|
||||||
|
- name: 'Determing Turbo HIT or MISS'
|
||||||
|
id: turbo-summary
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
TURBO_MISS_COUNT=`node utils/determine-turbo-hit-or-miss.js`
|
||||||
|
echo "MISS COUNT: $TURBO_MISS_COUNT"
|
||||||
|
echo "misses=$TURBO_MISS_COUNT" >> $GITHUB_OUTPUT
|
||||||
- name: fetch ssl certificate after tests (linux, os x)
|
- name: fetch ssl certificate after tests (linux, os x)
|
||||||
if: matrix.runner != 'windows-latest'
|
if: matrix.runner != 'windows-latest'
|
||||||
run: echo | openssl s_client -showcerts -servername 'api.vercel.com' -connect 76.76.21.21:443
|
run: echo | openssl s_client -showcerts -servername 'api.vercel.com' -connect 76.76.21.21:443
|
||||||
|
|
||||||
- name: 'Upload Test Report to Datadog'
|
- name: 'Upload Test Report to Datadog'
|
||||||
if: always()
|
if: ${{ steps['turbo-summary'].outputs.misses != '0' }}
|
||||||
run: 'npx @datadog/datadog-ci@2.18.1 junit upload --service vercel-cli .junit-reports'
|
run: 'npx @datadog/datadog-ci@2.18.1 junit upload --service vercel-cli .junit-reports'
|
||||||
env:
|
env:
|
||||||
DATADOG_API_KEY: ${{secrets.DATADOG_API_KEY_CLI}}
|
DATADOG_API_KEY: ${{secrets.DATADOG_API_KEY_CLI}}
|
||||||
|
|||||||
@@ -3,9 +3,10 @@
|
|||||||
This directory is a brief example of an [Astro](https://astro.build/) site that can be deployed to Vercel with zero configuration. This demo showcases:
|
This directory is a brief example of an [Astro](https://astro.build/) site that can be deployed to Vercel with zero configuration. This demo showcases:
|
||||||
|
|
||||||
- `/` - A static page (pre-rendered)
|
- `/` - A static page (pre-rendered)
|
||||||
- `/ssr` - A page that uses server-side rendering (through Vercel Edge Functions)
|
- `/ssr` - A page that uses server-side rendering (through [Vercel Edge Functions](https://vercel.com/docs/functions/edge-functions))
|
||||||
- `/ssr-with-swr-caching` - Similar to the previous page, but also caches the response on the Vercel Edge Network using `cache-control` headers
|
- `/ssr-with-swr-caching` - Similar to the previous page, but also caches the response on the [Vercel Edge Network](https://vercel.com/docs/edge-network/overview) using `cache-control` headers
|
||||||
- `/edge.json` - An Astro API Endpoint that returns JSON data using Vercel Edge Functions
|
- `/image` - Astro [Asset](https://docs.astro.build/en/guides/assets/) using Vercel [Image Optimization](https://vercel.com/docs/image-optimization)
|
||||||
|
- `/edge.json` - An Astro API Endpoint that returns JSON data using [Vercel Edge Functions](https://vercel.com/docs/functions/edge-functions)
|
||||||
|
|
||||||
Learn more about [Astro on Vercel](https://vercel.com/docs/frameworks/astro).
|
Learn more about [Astro on Vercel](https://vercel.com/docs/frameworks/astro).
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,17 @@
|
|||||||
import { defineConfig } from 'astro/config';
|
import { defineConfig } from 'astro/config';
|
||||||
|
// Use Vercel Edge Functions (Recommended)
|
||||||
import vercel from '@astrojs/vercel/edge';
|
import vercel from '@astrojs/vercel/edge';
|
||||||
|
// Can also use Serverless Functions
|
||||||
|
// import vercel from '@astrojs/vercel/serverless';
|
||||||
|
// Or a completely static build
|
||||||
|
// import vercel from '@astrojs/vercel/static';
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
output: 'server',
|
output: 'server',
|
||||||
adapter: vercel(),
|
experimental: {
|
||||||
|
assets: true
|
||||||
|
},
|
||||||
|
adapter: vercel({
|
||||||
|
imageService: true,
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -8,8 +8,8 @@
|
|||||||
"astro": "astro"
|
"astro": "astro"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@astrojs/vercel": "3.2.2",
|
"@astrojs/vercel": "3.8.2",
|
||||||
"astro": "^2.2.1",
|
"astro": "^2.10.14",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
"web-vitals": "^3.3.1"
|
"web-vitals": "^3.3.1"
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
examples/astro/src/assets/logo.png
Normal file
BIN
examples/astro/src/assets/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.2 KiB |
2
examples/astro/src/env.d.ts
vendored
2
examples/astro/src/env.d.ts
vendored
@@ -1,4 +1,4 @@
|
|||||||
/// <reference types="astro/client" />
|
/// <reference types="astro/client-image" />
|
||||||
|
|
||||||
interface ImportMetaEnv {
|
interface ImportMetaEnv {
|
||||||
readonly PUBLIC_VERCEL_ANALYTICS_ID: string;
|
readonly PUBLIC_VERCEL_ANALYTICS_ID: string;
|
||||||
|
|||||||
6
examples/astro/src/pages/image.astro
Normal file
6
examples/astro/src/pages/image.astro
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
import { Image } from 'astro:assets';
|
||||||
|
import astroLogo from '../assets/logo.png';
|
||||||
|
---
|
||||||
|
|
||||||
|
<Image src={astroLogo} alt="Astro Logo" width={50} quality={75} />
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
<!-- Replace the API key with your own, see:
|
<!-- Replace the API key with your own, see:
|
||||||
https://developers.google.com/maps/documentation/javascript/get-api-key -->
|
https://developers.google.com/maps/documentation/javascript/get-api-key -->
|
||||||
<!-- <script async="" defer="" src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB8pf6ZdFQj5qw7rc_HSGrhUwQKfIe9ICw"></script> -->
|
<!-- <script async="" defer="" src="https://maps.googleapis.com/maps/api/js?key=<YOUR_GOOGLE_MAPS_API_KEY>"></script> -->
|
||||||
|
|
||||||
<noscript>Please enable JavaScript to continue using this application.</noscript>
|
<noscript>Please enable JavaScript to continue using this application.</noscript>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ npm run dev
|
|||||||
yarn dev
|
yarn dev
|
||||||
# or
|
# or
|
||||||
pnpm dev
|
pnpm dev
|
||||||
|
# or
|
||||||
|
bun dev
|
||||||
```
|
```
|
||||||
|
|
||||||
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
||||||
|
|||||||
633
examples/nextjs/package-lock.json
generated
633
examples/nextjs/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -9,17 +9,17 @@
|
|||||||
"lint": "next lint"
|
"lint": "next lint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/node": "20.5.1",
|
"@types/node": "20.6.3",
|
||||||
"@types/react": "18.2.20",
|
"@types/react": "18.2.22",
|
||||||
"@types/react-dom": "18.2.7",
|
"@types/react-dom": "18.2.7",
|
||||||
"autoprefixer": "10.4.15",
|
"autoprefixer": "10.4.15",
|
||||||
"eslint": "8.47.0",
|
"eslint": "8.49.0",
|
||||||
"eslint-config-next": "13.4.19",
|
"eslint-config-next": "13.5.2",
|
||||||
"next": "13.4.19",
|
"next": "13.5.2",
|
||||||
"postcss": "8.4.28",
|
"postcss": "8.4.30",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
"react-dom": "18.2.0",
|
"react-dom": "18.2.0",
|
||||||
"tailwindcss": "3.3.3",
|
"tailwindcss": "3.3.3",
|
||||||
"typescript": "5.1.6"
|
"typescript": "5.2.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
2
examples/package.json
vendored
2
examples/package.json
vendored
@@ -9,7 +9,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/jest": "27.4.1",
|
"@types/jest": "27.4.1",
|
||||||
"@vercel/frameworks": "2.0.1"
|
"@vercel/frameworks": "2.0.2"
|
||||||
},
|
},
|
||||||
"version": null
|
"version": null
|
||||||
}
|
}
|
||||||
|
|||||||
5
examples/remix/.gitignore
vendored
5
examples/remix/.gitignore
vendored
@@ -4,9 +4,4 @@ node_modules
|
|||||||
/build
|
/build
|
||||||
/public/build
|
/public/build
|
||||||
.env
|
.env
|
||||||
|
|
||||||
.vercel
|
.vercel
|
||||||
.output
|
|
||||||
|
|
||||||
/api/index.js
|
|
||||||
/api/index.js.map
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export default function App() {
|
|||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charSet="utf-8" />
|
<meta charSet="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<Meta />
|
<Meta />
|
||||||
<Links />
|
<Links />
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
@@ -1,10 +1,15 @@
|
|||||||
import type { V2_MetaFunction } from "@vercel/remix";
|
import type { MetaFunction } from "@vercel/remix";
|
||||||
|
|
||||||
export const meta: V2_MetaFunction = () => [{ title: "New Remix App" }];
|
export const meta: MetaFunction = () => {
|
||||||
|
return [
|
||||||
|
{ title: "New Remix App" },
|
||||||
|
{ name: "description", content: "Welcome to Remix!" },
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
export default function Index() {
|
export default function Index() {
|
||||||
return (
|
return (
|
||||||
<div style={{ fontFamily: "system-ui, sans-serif", lineHeight: "1.4" }}>
|
<div style={{ fontFamily: "system-ui, sans-serif", lineHeight: "1.8" }}>
|
||||||
<h1>Welcome to Remix</h1>
|
<h1>Welcome to Remix</h1>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import type { V2_MetaFunction } from "@vercel/remix";
|
import type { MetaFunction } from "@vercel/remix";
|
||||||
|
|
||||||
export const config = { runtime: "edge" };
|
export const config = { runtime: "edge" };
|
||||||
|
|
||||||
export const meta: V2_MetaFunction = () => [{ title: "Remix@Edge | New Remix App" }];
|
export const meta: MetaFunction = () => [{ title: "Remix@Edge | New Remix App" }];
|
||||||
|
|
||||||
export default function Edge() {
|
export default function Edge() {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,32 +1,34 @@
|
|||||||
{
|
{
|
||||||
|
"name": "my-remix-app",
|
||||||
"private": true,
|
"private": true,
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "remix build",
|
"build": "remix build",
|
||||||
"dev": "remix dev",
|
"dev": "remix dev --manual",
|
||||||
"start": "remix-serve build",
|
"start": "remix-serve ./build/index.js",
|
||||||
"typecheck": "tsc"
|
"typecheck": "tsc"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@remix-run/css-bundle": "^1.18.0",
|
"@remix-run/css-bundle": "^2.0.0",
|
||||||
"@remix-run/node": "^1.18.0",
|
"@remix-run/node": "^2.0.0",
|
||||||
"@remix-run/react": "^1.18.0",
|
"@remix-run/react": "^2.0.0",
|
||||||
"@remix-run/serve": "^1.18.0",
|
"@remix-run/serve": "^2.0.0",
|
||||||
"@vercel/analytics": "^0.1.11",
|
"@vercel/analytics": "^1.0.2",
|
||||||
"@vercel/remix": "^1.18.0",
|
"@vercel/remix": "^2.0.0",
|
||||||
"isbot": "^3.6.8",
|
"isbot": "^3.6.8",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0"
|
"react-dom": "^18.2.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@remix-run/dev": "^1.18.0",
|
"@remix-run/dev": "^2.0.0",
|
||||||
"@remix-run/eslint-config": "^1.18.0",
|
"@remix-run/eslint-config": "^2.0.0",
|
||||||
"@types/react": "^18.0.25",
|
"@types/react": "^18.2.20",
|
||||||
"@types/react-dom": "^18.0.11",
|
"@types/react-dom": "^18.2.7",
|
||||||
"eslint": "^8.28.0",
|
"eslint": "^8.38.0",
|
||||||
"typescript": "^5.1.3"
|
"typescript": "^5.1.6"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16"
|
"node": ">=18.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,8 @@
|
|||||||
/** @type {import('@remix-run/dev').AppConfig} */
|
/** @type {import('@remix-run/dev').AppConfig} */
|
||||||
module.exports = {
|
export default {
|
||||||
future: {
|
|
||||||
v2_dev: true,
|
|
||||||
v2_errorBoundary: true,
|
|
||||||
v2_headers: true,
|
|
||||||
v2_meta: true,
|
|
||||||
v2_normalizeFormMethod: true,
|
|
||||||
v2_routeConvention: true,
|
|
||||||
},
|
|
||||||
ignoredRouteFiles: ["**/.*"],
|
ignoredRouteFiles: ["**/.*"],
|
||||||
serverModuleFormat: "cjs",
|
|
||||||
// appDirectory: "app",
|
// appDirectory: "app",
|
||||||
// assetsBuildDirectory: "public/build",
|
// assetsBuildDirectory: "public/build",
|
||||||
// serverBuildPath: "build/index.js",
|
|
||||||
// publicPath: "/build/",
|
// publicPath: "/build/",
|
||||||
|
// serverBuildPath: "build/index.js",
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
{
|
{
|
||||||
"include": ["remix.env.d.ts", "**/*.ts", "**/*.tsx"],
|
"include": ["remix.env.d.ts", "**/*.ts", "**/*.tsx"],
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"lib": ["DOM", "DOM.Iterable", "ES2019"],
|
"lib": ["DOM", "DOM.Iterable", "ES2022"],
|
||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"jsx": "react-jsx",
|
"jsx": "react-jsx",
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "Bundler",
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"target": "ES2019",
|
"target": "ES2022",
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
|||||||
@@ -1,5 +1,19 @@
|
|||||||
# @vercel-internals/types
|
# @vercel-internals/types
|
||||||
|
|
||||||
|
## 1.0.11
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [[`decdf27fb`](https://github.com/vercel/vercel/commit/decdf27fb5ca914fe50a9320c4fd50ef79d2fbb3)]:
|
||||||
|
- @vercel/build-utils@7.2.1
|
||||||
|
|
||||||
|
## 1.0.10
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [[`50e04dd85`](https://github.com/vercel/vercel/commit/50e04dd8584664c842a86c15d92d654f4ea8dcbb), [`45b73c7e8`](https://github.com/vercel/vercel/commit/45b73c7e86458564dc0bab007f6f6365c4c4ab5d), [`d8bc570f6`](https://github.com/vercel/vercel/commit/d8bc570f604950d97156d4f33c8accecf3b3b28f)]:
|
||||||
|
- @vercel/build-utils@7.2.0
|
||||||
|
|
||||||
## 1.0.9
|
## 1.0.9
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
2
internals/types/index.d.ts
vendored
2
internals/types/index.d.ts
vendored
@@ -65,6 +65,8 @@ export type User = {
|
|||||||
billing: Billing;
|
billing: Billing;
|
||||||
name?: string;
|
name?: string;
|
||||||
limited?: boolean;
|
limited?: boolean;
|
||||||
|
version?: 'northstar';
|
||||||
|
defaultTeamId?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface Team {
|
export interface Team {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"private": true,
|
"private": true,
|
||||||
"name": "@vercel-internals/types",
|
"name": "@vercel-internals/types",
|
||||||
"version": "1.0.9",
|
"version": "1.0.11",
|
||||||
"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.1.1",
|
"@vercel/build-utils": "7.2.1",
|
||||||
"@vercel/routing-utils": "3.0.0"
|
"@vercel/routing-utils": "3.0.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.10.13",
|
"turbo": "1.10.14",
|
||||||
"typescript": "4.9.5"
|
"typescript": "4.9.5"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -1,5 +1,23 @@
|
|||||||
# @vercel/build-utils
|
# @vercel/build-utils
|
||||||
|
|
||||||
|
## 7.2.1
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Internal variants ([#10549](https://github.com/vercel/vercel/pull/10549))
|
||||||
|
|
||||||
|
## 7.2.0
|
||||||
|
|
||||||
|
### Minor Changes
|
||||||
|
|
||||||
|
- Add new optional prerender field: experimentalStreamingLambdaPath ([#10476](https://github.com/vercel/vercel/pull/10476))
|
||||||
|
|
||||||
|
- [build-utils] Add zero config detection for bun package manager ([#10486](https://github.com/vercel/vercel/pull/10486))
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- add `experimentalBypassFor` field to Prerender ([#10481](https://github.com/vercel/vercel/pull/10481))
|
||||||
|
|
||||||
## 7.1.1
|
## 7.1.1
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@vercel/build-utils",
|
"name": "@vercel/build-utils",
|
||||||
"version": "7.1.1",
|
"version": "7.2.1",
|
||||||
"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",
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import { cloneEnv } from '../clone-env';
|
|||||||
// Only allow one `runNpmInstall()` invocation to run concurrently
|
// Only allow one `runNpmInstall()` invocation to run concurrently
|
||||||
const runNpmInstallSema = new Sema(1);
|
const runNpmInstallSema = new Sema(1);
|
||||||
|
|
||||||
export type CliType = 'yarn' | 'npm' | 'pnpm';
|
export type CliType = 'yarn' | 'npm' | 'pnpm' | 'bun';
|
||||||
|
|
||||||
export interface ScanParentDirsResult {
|
export interface ScanParentDirsResult {
|
||||||
/**
|
/**
|
||||||
@@ -284,26 +284,34 @@ export async function scanParentDirs(
|
|||||||
readPackageJson && pkgJsonPath
|
readPackageJson && pkgJsonPath
|
||||||
? JSON.parse(await fs.readFile(pkgJsonPath, 'utf8'))
|
? JSON.parse(await fs.readFile(pkgJsonPath, 'utf8'))
|
||||||
: undefined;
|
: undefined;
|
||||||
const [yarnLockPath, npmLockPath, pnpmLockPath] = await walkParentDirsMulti({
|
const [yarnLockPath, npmLockPath, pnpmLockPath, bunLockPath] =
|
||||||
base: '/',
|
await walkParentDirsMulti({
|
||||||
start: destPath,
|
base: '/',
|
||||||
filenames: ['yarn.lock', 'package-lock.json', 'pnpm-lock.yaml'],
|
start: destPath,
|
||||||
});
|
filenames: [
|
||||||
|
'yarn.lock',
|
||||||
|
'package-lock.json',
|
||||||
|
'pnpm-lock.yaml',
|
||||||
|
'bun.lockb',
|
||||||
|
],
|
||||||
|
});
|
||||||
let lockfilePath: string | undefined;
|
let lockfilePath: string | undefined;
|
||||||
let lockfileVersion: number | undefined;
|
let lockfileVersion: number | undefined;
|
||||||
let cliType: CliType = 'yarn';
|
let cliType: CliType = 'yarn';
|
||||||
|
|
||||||
const [hasYarnLock, packageLockJson, pnpmLockYaml] = await Promise.all([
|
const [hasYarnLock, packageLockJson, pnpmLockYaml, bunLockBin] =
|
||||||
Boolean(yarnLockPath),
|
await Promise.all([
|
||||||
npmLockPath
|
Boolean(yarnLockPath),
|
||||||
? readConfigFile<{ lockfileVersion: number }>(npmLockPath)
|
npmLockPath
|
||||||
: null,
|
? readConfigFile<{ lockfileVersion: number }>(npmLockPath)
|
||||||
pnpmLockPath
|
: null,
|
||||||
? readConfigFile<{ lockfileVersion: number }>(pnpmLockPath)
|
pnpmLockPath
|
||||||
: null,
|
? readConfigFile<{ lockfileVersion: number }>(pnpmLockPath)
|
||||||
]);
|
: null,
|
||||||
|
bunLockPath ? fs.readFile(bunLockPath, 'utf8') : null,
|
||||||
|
]);
|
||||||
|
|
||||||
// Priority order is Yarn > pnpm > npm
|
// Priority order is Yarn > pnpm > npm > bun
|
||||||
if (hasYarnLock) {
|
if (hasYarnLock) {
|
||||||
cliType = 'yarn';
|
cliType = 'yarn';
|
||||||
lockfilePath = yarnLockPath;
|
lockfilePath = yarnLockPath;
|
||||||
@@ -315,6 +323,11 @@ export async function scanParentDirs(
|
|||||||
cliType = 'npm';
|
cliType = 'npm';
|
||||||
lockfilePath = npmLockPath;
|
lockfilePath = npmLockPath;
|
||||||
lockfileVersion = packageLockJson.lockfileVersion;
|
lockfileVersion = packageLockJson.lockfileVersion;
|
||||||
|
} else if (bunLockBin) {
|
||||||
|
cliType = 'bun';
|
||||||
|
lockfilePath = bunLockPath;
|
||||||
|
// TODO: read "bun-lockfile-format-v0"
|
||||||
|
lockfileVersion = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const packageJsonPath = pkgJsonPath || undefined;
|
const packageJsonPath = pkgJsonPath || undefined;
|
||||||
@@ -451,6 +464,10 @@ export async function runNpmInstall(
|
|||||||
commandArgs = args
|
commandArgs = args
|
||||||
.filter(a => a !== '--prefer-offline')
|
.filter(a => a !== '--prefer-offline')
|
||||||
.concat(['install', '--unsafe-perm']);
|
.concat(['install', '--unsafe-perm']);
|
||||||
|
} else if (cliType === 'bun') {
|
||||||
|
// @see options https://bun.sh/docs/cli/install
|
||||||
|
opts.prettyCommand = 'bun install';
|
||||||
|
commandArgs = ['install', ...args];
|
||||||
} else {
|
} else {
|
||||||
opts.prettyCommand = 'yarn install';
|
opts.prettyCommand = 'yarn install';
|
||||||
commandArgs = ['install', ...args];
|
commandArgs = ['install', ...args];
|
||||||
@@ -505,6 +522,7 @@ export function getEnvForPackageManager({
|
|||||||
const npm7 = '/node16/bin-npm7';
|
const npm7 = '/node16/bin-npm7';
|
||||||
const pnpm7 = '/pnpm7/node_modules/.bin';
|
const pnpm7 = '/pnpm7/node_modules/.bin';
|
||||||
const pnpm8 = '/pnpm8/node_modules/.bin';
|
const pnpm8 = '/pnpm8/node_modules/.bin';
|
||||||
|
const bun1 = '/bun1';
|
||||||
const corepackEnabled = env.ENABLE_EXPERIMENTAL_COREPACK === '1';
|
const corepackEnabled = env.ENABLE_EXPERIMENTAL_COREPACK === '1';
|
||||||
if (cliType === 'npm') {
|
if (cliType === 'npm') {
|
||||||
if (
|
if (
|
||||||
@@ -516,7 +534,7 @@ export function getEnvForPackageManager({
|
|||||||
) {
|
) {
|
||||||
// Ensure that npm 7 is at the beginning of the `$PATH`
|
// Ensure that npm 7 is at the beginning of the `$PATH`
|
||||||
newEnv.PATH = `${npm7}${path.delimiter}${oldPath}`;
|
newEnv.PATH = `${npm7}${path.delimiter}${oldPath}`;
|
||||||
console.log('Detected `package-lock.json` generated by npm 7+...');
|
console.log('Detected `package-lock.json` generated by npm 7+');
|
||||||
}
|
}
|
||||||
} else if (cliType === 'pnpm') {
|
} else if (cliType === 'pnpm') {
|
||||||
if (
|
if (
|
||||||
@@ -528,7 +546,7 @@ export function getEnvForPackageManager({
|
|||||||
// Ensure that pnpm 7 is at the beginning of the `$PATH`
|
// Ensure that pnpm 7 is at the beginning of the `$PATH`
|
||||||
newEnv.PATH = `${pnpm7}${path.delimiter}${oldPath}`;
|
newEnv.PATH = `${pnpm7}${path.delimiter}${oldPath}`;
|
||||||
console.log(
|
console.log(
|
||||||
`Detected \`pnpm-lock.yaml\` version ${lockfileVersion} generated by pnpm 7...`
|
`Detected \`pnpm-lock.yaml\` version ${lockfileVersion} generated by pnpm 7`
|
||||||
);
|
);
|
||||||
} else if (
|
} else if (
|
||||||
typeof lockfileVersion === 'number' &&
|
typeof lockfileVersion === 'number' &&
|
||||||
@@ -539,7 +557,16 @@ export function getEnvForPackageManager({
|
|||||||
// Ensure that pnpm 8 is at the beginning of the `$PATH`
|
// Ensure that pnpm 8 is at the beginning of the `$PATH`
|
||||||
newEnv.PATH = `${pnpm8}${path.delimiter}${oldPath}`;
|
newEnv.PATH = `${pnpm8}${path.delimiter}${oldPath}`;
|
||||||
console.log(
|
console.log(
|
||||||
`Detected \`pnpm-lock.yaml\` version ${lockfileVersion} generated by pnpm 8...`
|
`Detected \`pnpm-lock.yaml\` version ${lockfileVersion} generated by pnpm 8`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else if (cliType === 'bun') {
|
||||||
|
if (!oldPath.includes(bun1) && !corepackEnabled) {
|
||||||
|
// Ensure that Bun 1 is at the beginning of the `$PATH`
|
||||||
|
newEnv.PATH = `${bun1}${path.delimiter}${oldPath}`;
|
||||||
|
console.log('Detected `bun.lockb` generated by Bun');
|
||||||
|
console.warn(
|
||||||
|
'Warning: Bun is used as a package manager at build time only, not at runtime with Functions'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -548,7 +575,6 @@ export function getEnvForPackageManager({
|
|||||||
newEnv.YARN_NODE_LINKER = 'node-modules';
|
newEnv.YARN_NODE_LINKER = 'node-modules';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return newEnv;
|
return newEnv;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -614,6 +640,8 @@ export async function runPackageJsonScript(
|
|||||||
opts.prettyCommand = `npm run ${scriptName}`;
|
opts.prettyCommand = `npm run ${scriptName}`;
|
||||||
} else if (cliType === 'pnpm') {
|
} else if (cliType === 'pnpm') {
|
||||||
opts.prettyCommand = `pnpm run ${scriptName}`;
|
opts.prettyCommand = `pnpm run ${scriptName}`;
|
||||||
|
} else if (cliType === 'bun') {
|
||||||
|
opts.prettyCommand = `bun run ${scriptName}`;
|
||||||
} else {
|
} else {
|
||||||
opts.prettyCommand = `yarn run ${scriptName}`;
|
opts.prettyCommand = `yarn run ${scriptName}`;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { File } from './types';
|
import type { File, HasField } from './types';
|
||||||
import { Lambda } from './lambda';
|
import { Lambda } from './lambda';
|
||||||
|
|
||||||
interface PrerenderOptions {
|
interface PrerenderOptions {
|
||||||
@@ -12,6 +12,8 @@ interface PrerenderOptions {
|
|||||||
initialStatus?: number;
|
initialStatus?: number;
|
||||||
passQuery?: boolean;
|
passQuery?: boolean;
|
||||||
sourcePath?: string;
|
sourcePath?: string;
|
||||||
|
experimentalBypassFor?: HasField;
|
||||||
|
experimentalStreamingLambdaPath?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Prerender {
|
export class Prerender {
|
||||||
@@ -26,6 +28,8 @@ export class Prerender {
|
|||||||
public initialStatus?: number;
|
public initialStatus?: number;
|
||||||
public passQuery?: boolean;
|
public passQuery?: boolean;
|
||||||
public sourcePath?: string;
|
public sourcePath?: string;
|
||||||
|
public experimentalBypassFor?: HasField;
|
||||||
|
public experimentalStreamingLambdaPath?: string;
|
||||||
|
|
||||||
constructor({
|
constructor({
|
||||||
expiration,
|
expiration,
|
||||||
@@ -38,6 +42,8 @@ export class Prerender {
|
|||||||
initialStatus,
|
initialStatus,
|
||||||
passQuery,
|
passQuery,
|
||||||
sourcePath,
|
sourcePath,
|
||||||
|
experimentalBypassFor,
|
||||||
|
experimentalStreamingLambdaPath,
|
||||||
}: PrerenderOptions) {
|
}: PrerenderOptions) {
|
||||||
this.type = 'Prerender';
|
this.type = 'Prerender';
|
||||||
this.expiration = expiration;
|
this.expiration = expiration;
|
||||||
@@ -86,6 +92,26 @@ export class Prerender {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (experimentalBypassFor !== undefined) {
|
||||||
|
if (
|
||||||
|
!Array.isArray(experimentalBypassFor) ||
|
||||||
|
experimentalBypassFor.some(
|
||||||
|
field =>
|
||||||
|
typeof field !== 'object' ||
|
||||||
|
// host doesn't need a key
|
||||||
|
(field.type !== 'host' && typeof field.key !== 'string') ||
|
||||||
|
typeof field.type !== 'string' ||
|
||||||
|
(field.value !== undefined && typeof field.value !== 'string')
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
throw new Error(
|
||||||
|
'The `experimentalBypassFor` argument for `Prerender` must be Array of objects with fields `type`, `key` and optionally `value`.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.experimentalBypassFor = experimentalBypassFor;
|
||||||
|
}
|
||||||
|
|
||||||
if (typeof fallback === 'undefined') {
|
if (typeof fallback === 'undefined') {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'The `fallback` argument for `Prerender` needs to be a `FileBlob`, `FileFsRef`, `FileRef`, or null.'
|
'The `fallback` argument for `Prerender` needs to be a `FileBlob`, `FileFsRef`, `FileRef`, or null.'
|
||||||
@@ -130,5 +156,14 @@ export class Prerender {
|
|||||||
}
|
}
|
||||||
this.allowQuery = allowQuery;
|
this.allowQuery = allowQuery;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (experimentalStreamingLambdaPath !== undefined) {
|
||||||
|
if (typeof experimentalStreamingLambdaPath !== 'string') {
|
||||||
|
throw new Error(
|
||||||
|
'The `experimentalStreamingLambdaPath` argument for `Prerender` must be a string.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
this.experimentalStreamingLambdaPath = experimentalStreamingLambdaPath;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,6 +45,18 @@ export interface Config {
|
|||||||
[key: string]: unknown;
|
[key: string]: unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type HasField = Array<
|
||||||
|
| {
|
||||||
|
type: 'host';
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: 'header' | 'cookie' | 'query';
|
||||||
|
key: string;
|
||||||
|
value?: string;
|
||||||
|
}
|
||||||
|
>;
|
||||||
|
|
||||||
export interface Meta {
|
export interface Meta {
|
||||||
isDev?: boolean;
|
isDev?: boolean;
|
||||||
devCacheDir?: string;
|
devCacheDir?: string;
|
||||||
@@ -422,6 +434,13 @@ export interface Cron {
|
|||||||
schedule: string;
|
schedule: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Proper description once complete
|
||||||
|
export interface Flag {
|
||||||
|
key: string;
|
||||||
|
defaultValue?: unknown;
|
||||||
|
metadata: Record<string, unknown>;
|
||||||
|
}
|
||||||
|
|
||||||
/** The framework which created the function */
|
/** The framework which created the function */
|
||||||
export interface FunctionFramework {
|
export interface FunctionFramework {
|
||||||
slug: string;
|
slug: string;
|
||||||
@@ -446,6 +465,7 @@ export interface BuildResultV2Typical {
|
|||||||
framework?: {
|
framework?: {
|
||||||
version: string;
|
version: string;
|
||||||
};
|
};
|
||||||
|
flags?: Flag[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export type BuildResultV2 = BuildResultV2Typical | BuildResultBuildOutput;
|
export type BuildResultV2 = BuildResultV2Typical | BuildResultBuildOutput;
|
||||||
|
|||||||
2
packages/build-utils/test/fixtures/30-bun-v1/.gitignore
vendored
Normal file
2
packages/build-utils/test/fixtures/30-bun-v1/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
.vercel
|
||||||
|
public
|
||||||
8
packages/build-utils/test/fixtures/30-bun-v1/build.js
vendored
Normal file
8
packages/build-utils/test/fixtures/30-bun-v1/build.js
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import { mkdir, rm, writeFile } from 'node:fs/promises'
|
||||||
|
import { say } from 'cowsay'
|
||||||
|
|
||||||
|
const text = say({ text: `bun version: ${process.versions.bun}` })
|
||||||
|
const content = say({ text })
|
||||||
|
await rm('./public', { recursive: true, force: true })
|
||||||
|
await mkdir('./public', { recursive: true })
|
||||||
|
await writeFile('./public/index.txt', content)
|
||||||
BIN
packages/build-utils/test/fixtures/30-bun-v1/bun.lockb
vendored
Executable file
BIN
packages/build-utils/test/fixtures/30-bun-v1/bun.lockb
vendored
Executable file
Binary file not shown.
9
packages/build-utils/test/fixtures/30-bun-v1/package.json
vendored
Normal file
9
packages/build-utils/test/fixtures/30-bun-v1/package.json
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"build": "bun build.js"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"cowsay": "1.5.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
8
packages/build-utils/test/fixtures/30-bun-v1/probes.json
vendored
Normal file
8
packages/build-utils/test/fixtures/30-bun-v1/probes.json
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"probes": [
|
||||||
|
{
|
||||||
|
"path": "/",
|
||||||
|
"mustContain": "bun version: 1"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -133,6 +133,22 @@ describe('Test `getEnvForPackageManager()`', () => {
|
|||||||
PATH: `/pnpm7/node_modules/.bin${delimiter}foo`,
|
PATH: `/pnpm7/node_modules/.bin${delimiter}foo`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'should set path if bun v1 is detected',
|
||||||
|
args: {
|
||||||
|
cliType: 'bun',
|
||||||
|
nodeVersion: { major: 18, range: '18.x', runtime: 'nodejs18.x' },
|
||||||
|
lockfileVersion: 0,
|
||||||
|
env: {
|
||||||
|
FOO: 'bar',
|
||||||
|
PATH: '/usr/local/bin',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: {
|
||||||
|
FOO: 'bar',
|
||||||
|
PATH: `/bun1${delimiter}/usr/local/bin`,
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'should not set pnpm path if corepack is enabled',
|
name: 'should not set pnpm path if corepack is enabled',
|
||||||
args: {
|
args: {
|
||||||
|
|||||||
109
packages/build-utils/test/unit.test.ts
vendored
109
packages/build-utils/test/unit.test.ts
vendored
@@ -344,6 +344,70 @@ it('should support initialHeaders and initialStatus correctly', async () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should support experimentalBypassFor correctly', async () => {
|
||||||
|
new Prerender({
|
||||||
|
expiration: 1,
|
||||||
|
fallback: null,
|
||||||
|
group: 1,
|
||||||
|
bypassToken: 'some-long-bypass-token-to-make-it-work',
|
||||||
|
experimentalBypassFor: [{ type: 'header', key: 'Next-Action' }],
|
||||||
|
});
|
||||||
|
new Prerender({
|
||||||
|
expiration: 1,
|
||||||
|
fallback: null,
|
||||||
|
group: 1,
|
||||||
|
bypassToken: 'some-long-bypass-token-to-make-it-work',
|
||||||
|
experimentalBypassFor: [
|
||||||
|
{ type: 'header', key: 'Next-Action' },
|
||||||
|
{
|
||||||
|
type: 'cookie',
|
||||||
|
key: '__prerender_bypass',
|
||||||
|
value: 'some-long-bypass-token-to-make-it-work',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
new Prerender({
|
||||||
|
expiration: 1,
|
||||||
|
fallback: null,
|
||||||
|
group: 1,
|
||||||
|
bypassToken: 'some-long-bypass-token-to-make-it-work',
|
||||||
|
experimentalBypassFor: [{ type: 'query', key: 'bypass', value: '1' }],
|
||||||
|
});
|
||||||
|
new Prerender({
|
||||||
|
expiration: 1,
|
||||||
|
fallback: null,
|
||||||
|
group: 1,
|
||||||
|
bypassToken: 'some-long-bypass-token-to-make-it-work',
|
||||||
|
experimentalBypassFor: [{ type: 'host', value: 'vercel.com' }],
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(() => {
|
||||||
|
new Prerender({
|
||||||
|
expiration: 1,
|
||||||
|
fallback: null,
|
||||||
|
group: 1,
|
||||||
|
bypassToken: 'some-long-bypass-token-to-make-it-work',
|
||||||
|
// @ts-expect-error: testing invalid args
|
||||||
|
experimentalBypassFor: 'foo',
|
||||||
|
});
|
||||||
|
}).toThrowError(
|
||||||
|
'The `experimentalBypassFor` argument for `Prerender` must be Array of objects with fields `type`, `key` and optionally `value`.'
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(() => {
|
||||||
|
new Prerender({
|
||||||
|
expiration: 1,
|
||||||
|
fallback: null,
|
||||||
|
group: 1,
|
||||||
|
bypassToken: 'some-long-bypass-token-to-make-it-work',
|
||||||
|
// @ts-expect-error: testing invalid args
|
||||||
|
experimentalBypassFor: [{ type: 'header', value: { foo: 'bar' } }],
|
||||||
|
});
|
||||||
|
}).toThrowError(
|
||||||
|
'The `experimentalBypassFor` argument for `Prerender` must be Array of objects with fields `type`, `key` and optionally `value`.'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should support passQuery correctly', async () => {
|
it('should support passQuery correctly', async () => {
|
||||||
new Prerender({
|
new Prerender({
|
||||||
expiration: 1,
|
expiration: 1,
|
||||||
@@ -387,6 +451,42 @@ it('should support passQuery correctly', async () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should support experimentalStreamingLambdaPath correctly', async () => {
|
||||||
|
new Prerender({
|
||||||
|
expiration: 1,
|
||||||
|
fallback: null,
|
||||||
|
group: 1,
|
||||||
|
bypassToken: 'some-long-bypass-token-to-make-it-work',
|
||||||
|
experimentalStreamingLambdaPath: undefined,
|
||||||
|
});
|
||||||
|
new Prerender({
|
||||||
|
expiration: 1,
|
||||||
|
fallback: null,
|
||||||
|
group: 1,
|
||||||
|
bypassToken: 'some-long-bypass-token-to-make-it-work',
|
||||||
|
experimentalStreamingLambdaPath: '/some/path/to/lambda',
|
||||||
|
});
|
||||||
|
new Prerender({
|
||||||
|
expiration: 1,
|
||||||
|
fallback: null,
|
||||||
|
group: 1,
|
||||||
|
bypassToken: 'some-long-bypass-token-to-make-it-work',
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(() => {
|
||||||
|
new Prerender({
|
||||||
|
expiration: 1,
|
||||||
|
fallback: null,
|
||||||
|
group: 1,
|
||||||
|
bypassToken: 'some-long-bypass-token-to-make-it-work',
|
||||||
|
// @ts-expect-error testing invalid field
|
||||||
|
experimentalStreamingLambdaPath: 1,
|
||||||
|
});
|
||||||
|
}).toThrowError(
|
||||||
|
`The \`experimentalStreamingLambdaPath\` argument for \`Prerender\` must be a string.`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should support require by path for legacy builders', () => {
|
it('should support require by path for legacy builders', () => {
|
||||||
const index = require('../');
|
const index = require('../');
|
||||||
|
|
||||||
@@ -440,6 +540,15 @@ it(
|
|||||||
ms('1m')
|
ms('1m')
|
||||||
);
|
);
|
||||||
|
|
||||||
|
it('should return cliType bun and correct lock file for bun v1', async () => {
|
||||||
|
const fixture = path.join(__dirname, 'fixtures', '30-bun-v1');
|
||||||
|
const result = await scanParentDirs(fixture);
|
||||||
|
expect(result.cliType).toEqual('bun');
|
||||||
|
expect(result.lockfileVersion).toEqual(0);
|
||||||
|
expect(result.lockfilePath).toEqual(path.join(fixture, 'bun.lockb'));
|
||||||
|
expect(result.packageJsonPath).toEqual(path.join(fixture, 'package.json'));
|
||||||
|
});
|
||||||
|
|
||||||
it('should return lockfileVersion 2 with npm7', async () => {
|
it('should return lockfileVersion 2 with npm7', async () => {
|
||||||
const fixture = path.join(__dirname, 'fixtures', '20-npm-7');
|
const fixture = path.join(__dirname, 'fixtures', '20-npm-7');
|
||||||
const result = await scanParentDirs(fixture);
|
const result = await scanParentDirs(fixture);
|
||||||
|
|||||||
@@ -1,5 +1,79 @@
|
|||||||
# vercel
|
# vercel
|
||||||
|
|
||||||
|
## 32.3.0
|
||||||
|
|
||||||
|
### Minor Changes
|
||||||
|
|
||||||
|
- [cli] Support northstar users ([#10535](https://github.com/vercel/vercel/pull/10535))
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Internal variants ([#10549](https://github.com/vercel/vercel/pull/10549))
|
||||||
|
|
||||||
|
- [speed insights] Prepare for migration to new speed insights package ([#10500](https://github.com/vercel/vercel/pull/10500))
|
||||||
|
|
||||||
|
- Updated dependencies [[`b0898a665`](https://github.com/vercel/vercel/commit/b0898a66591d5296dc38ffcf0e8345c9338b72f3), [`10d4e51ac`](https://github.com/vercel/vercel/commit/10d4e51ac57b76f05ddc0bf3adf220e2490244fc), [`decdf27fb`](https://github.com/vercel/vercel/commit/decdf27fb5ca914fe50a9320c4fd50ef79d2fbb3), [`f5ca497b7`](https://github.com/vercel/vercel/commit/f5ca497b7522a2dad637cef238da9716ac133057), [`ab329f0fe`](https://github.com/vercel/vercel/commit/ab329f0fe88e9cb72607d0cba41f5e168d77e077), [`d0d052011`](https://github.com/vercel/vercel/commit/d0d0520111264434d57d5920de0f622f6a2588dc), [`9bb3067de`](https://github.com/vercel/vercel/commit/9bb3067de28be77f3ce268a31a7aa6184836dfb1)]:
|
||||||
|
- @vercel/static-build@2.0.7
|
||||||
|
- @vercel/node@3.0.6
|
||||||
|
- @vercel/build-utils@7.2.1
|
||||||
|
- @vercel/next@4.0.7
|
||||||
|
- @vercel/python@4.0.2
|
||||||
|
- @vercel/redwood@2.0.3
|
||||||
|
- @vercel/remix-builder@2.0.7
|
||||||
|
- @vercel/go@3.0.2
|
||||||
|
|
||||||
|
## 32.2.5
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [[`849eedf0f`](https://github.com/vercel/vercel/commit/849eedf0f2841211e4175d374f1cf01330bf9611), [`f6f16b034`](https://github.com/vercel/vercel/commit/f6f16b0347bac9f5c33c79ccb1fb9fd9d254cae5), [`3035e18fb`](https://github.com/vercel/vercel/commit/3035e18fb67dfe7031e235a74136a41948f86d5a), [`cb784aeb9`](https://github.com/vercel/vercel/commit/cb784aeb9c9e4eddf1c65b61849a87edb1117af1)]:
|
||||||
|
- @vercel/next@4.0.6
|
||||||
|
- @vercel/remix-builder@2.0.6
|
||||||
|
|
||||||
|
## 32.2.4
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Add support for bun detection in monorepo ([#10511](https://github.com/vercel/vercel/pull/10511))
|
||||||
|
|
||||||
|
- Updated dependencies [[`1b6f3a0f6`](https://github.com/vercel/vercel/commit/1b6f3a0f6534f71c7486a4e33ac199f1da330626)]:
|
||||||
|
- @vercel/static-build@2.0.6
|
||||||
|
|
||||||
|
## 32.2.3
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [[`083aad448`](https://github.com/vercel/vercel/commit/083aad448e45edae296da3201eec9f890a01d22d)]:
|
||||||
|
- @vercel/next@4.0.5
|
||||||
|
|
||||||
|
## 32.2.2
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [[`7a0fed970`](https://github.com/vercel/vercel/commit/7a0fed970c39cb8f4df70544ded3284d3538b06a), [`2f461a8b0`](https://github.com/vercel/vercel/commit/2f461a8b0bcbdd05da0516395c2905c2d0242682), [`1bab21026`](https://github.com/vercel/vercel/commit/1bab21026ec0bb8a4a8fbeac3d6e4a197f1030fd)]:
|
||||||
|
- @vercel/next@4.0.4
|
||||||
|
- @vercel/remix-builder@2.0.5
|
||||||
|
|
||||||
|
## 32.2.1
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Update @vercel/fun@1.1.0 ([#10477](https://github.com/vercel/vercel/pull/10477))
|
||||||
|
|
||||||
|
- [node] upgrade edge-runtime ([#10451](https://github.com/vercel/vercel/pull/10451))
|
||||||
|
|
||||||
|
- Updated dependencies [[`6784e7751`](https://github.com/vercel/vercel/commit/6784e77516ba180a691e3c48323b32bb4506d7b6), [`a8ad17626`](https://github.com/vercel/vercel/commit/a8ad176262ef822860ce338927e6f959961d2d32), [`0ee089a50`](https://github.com/vercel/vercel/commit/0ee089a501ebb78901c4afe1658e794917998f8f), [`f15cba614`](https://github.com/vercel/vercel/commit/f15cba6148a0cdb6975db7724775c35ab7d929b2), [`b265e13d4`](https://github.com/vercel/vercel/commit/b265e13d40d541b77148fa79ac60b4c4dd10974c), [`50e04dd85`](https://github.com/vercel/vercel/commit/50e04dd8584664c842a86c15d92d654f4ea8dcbb), [`45b73c7e8`](https://github.com/vercel/vercel/commit/45b73c7e86458564dc0bab007f6f6365c4c4ab5d), [`a732d30c8`](https://github.com/vercel/vercel/commit/a732d30c8409f96f59ea5406e974a6c4186cc130), [`9d64312aa`](https://github.com/vercel/vercel/commit/9d64312aaaa875a4e193b7602c50e5dc68979aad), [`6baefc825`](https://github.com/vercel/vercel/commit/6baefc825ad7cfc3a5edce31cb4244721452f753), [`989f0d813`](https://github.com/vercel/vercel/commit/989f0d813910d8d67ed355de93018f1dcd91b6ba), [`d8bc570f6`](https://github.com/vercel/vercel/commit/d8bc570f604950d97156d4f33c8accecf3b3b28f)]:
|
||||||
|
- @vercel/go@3.0.1
|
||||||
|
- @vercel/redwood@2.0.2
|
||||||
|
- @vercel/remix-builder@2.0.4
|
||||||
|
- @vercel/hydrogen@1.0.1
|
||||||
|
- @vercel/static-build@2.0.5
|
||||||
|
- @vercel/build-utils@7.2.0
|
||||||
|
- @vercel/next@4.0.3
|
||||||
|
- @vercel/node@3.0.5
|
||||||
|
- @vercel/python@4.0.1
|
||||||
|
- @vercel/ruby@2.0.2
|
||||||
|
|
||||||
## 32.2.0
|
## 32.2.0
|
||||||
|
|
||||||
### Minor Changes
|
### Minor Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "vercel",
|
"name": "vercel",
|
||||||
"version": "32.2.0",
|
"version": "32.3.0",
|
||||||
"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",
|
||||||
@@ -31,20 +31,20 @@
|
|||||||
"node": ">= 16"
|
"node": ">= 16"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vercel/build-utils": "7.1.1",
|
"@vercel/build-utils": "7.2.1",
|
||||||
"@vercel/go": "3.0.0",
|
"@vercel/go": "3.0.2",
|
||||||
"@vercel/hydrogen": "1.0.0",
|
"@vercel/hydrogen": "1.0.1",
|
||||||
"@vercel/next": "4.0.2",
|
"@vercel/next": "4.0.7",
|
||||||
"@vercel/node": "3.0.4",
|
"@vercel/node": "3.0.6",
|
||||||
"@vercel/python": "4.0.0",
|
"@vercel/python": "4.0.2",
|
||||||
"@vercel/redwood": "2.0.1",
|
"@vercel/redwood": "2.0.3",
|
||||||
"@vercel/remix-builder": "2.0.3",
|
"@vercel/remix-builder": "2.0.7",
|
||||||
"@vercel/ruby": "2.0.1",
|
"@vercel/ruby": "2.0.2",
|
||||||
"@vercel/static-build": "2.0.4"
|
"@vercel/static-build": "2.0.7"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@alex_neo/jest-expect-message": "1.0.5",
|
"@alex_neo/jest-expect-message": "1.0.5",
|
||||||
"@edge-runtime/node-utils": "2.2.0",
|
"@edge-runtime/node-utils": "2.2.1",
|
||||||
"@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",
|
||||||
@@ -86,12 +86,12 @@
|
|||||||
"@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.9",
|
"@vercel-internals/types": "1.0.11",
|
||||||
"@vercel/client": "13.0.2",
|
"@vercel/client": "13.0.4",
|
||||||
"@vercel/error-utils": "2.0.1",
|
"@vercel/error-utils": "2.0.1",
|
||||||
"@vercel/frameworks": "2.0.1",
|
"@vercel/frameworks": "2.0.2",
|
||||||
"@vercel/fs-detectors": "5.0.2",
|
"@vercel/fs-detectors": "5.1.0",
|
||||||
"@vercel/fun": "1.0.4",
|
"@vercel/fun": "1.1.0",
|
||||||
"@vercel/ncc": "0.24.0",
|
"@vercel/ncc": "0.24.0",
|
||||||
"@vercel/routing-utils": "3.0.0",
|
"@vercel/routing-utils": "3.0.0",
|
||||||
"@zeit/source-map-support": "0.6.2",
|
"@zeit/source-map-support": "0.6.2",
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ export const help = () => `
|
|||||||
pull [path] Pull your Project Settings from the cloud
|
pull [path] Pull your Project Settings from the cloud
|
||||||
redeploy [url|id] Rebuild and deploy a previous deployment.
|
redeploy [url|id] Rebuild and deploy a previous deployment.
|
||||||
rollback [url|id] Quickly revert back to a previous deployment
|
rollback [url|id] Quickly revert back to a previous deployment
|
||||||
switch [scope] Switches between teams and your personal account
|
switch [scope] Switches between different scopes
|
||||||
|
|
||||||
${chalk.dim('Advanced')}
|
${chalk.dim('Advanced')}
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import {
|
|||||||
NowBuildError,
|
NowBuildError,
|
||||||
Cron,
|
Cron,
|
||||||
validateNpmrc,
|
validateNpmrc,
|
||||||
|
Flag,
|
||||||
} from '@vercel/build-utils';
|
} from '@vercel/build-utils';
|
||||||
import {
|
import {
|
||||||
detectBuilders,
|
detectBuilders,
|
||||||
@@ -93,6 +94,7 @@ interface BuildOutputConfig {
|
|||||||
version: string;
|
version: string;
|
||||||
};
|
};
|
||||||
crons?: Cron[];
|
crons?: Cron[];
|
||||||
|
flags?: Flag[];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -426,6 +428,23 @@ async function doBuild(
|
|||||||
|
|
||||||
const ops: Promise<Error | void>[] = [];
|
const ops: Promise<Error | void>[] = [];
|
||||||
|
|
||||||
|
const dependencies = [
|
||||||
|
...Object.keys(pkg?.dependencies ?? {}),
|
||||||
|
...Object.keys(pkg?.devDependencies ?? {}),
|
||||||
|
];
|
||||||
|
|
||||||
|
const isUsingSpeedInsights = dependencies.some(
|
||||||
|
d => d === '@vercel/speed-insights'
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isUsingSpeedInsights && process.env.VERCEL_ANALYTICS_ID) {
|
||||||
|
output.warn(
|
||||||
|
`The \`VERCEL_ANALYTICS_ID\` environment variable is deprecated and will be removed in a future release. Please remove it from your environment variables`
|
||||||
|
);
|
||||||
|
|
||||||
|
delete process.env.VERCEL_ANALYTICS_ID;
|
||||||
|
}
|
||||||
|
|
||||||
// Write the `detectedBuilders` result to output dir
|
// Write the `detectedBuilders` result to output dir
|
||||||
const buildsJsonBuilds = new Map<Builder, SerializedBuilder>(
|
const buildsJsonBuilds = new Map<Builder, SerializedBuilder>(
|
||||||
builds.map(build => {
|
builds.map(build => {
|
||||||
@@ -627,6 +646,7 @@ async function doBuild(
|
|||||||
const mergedWildcard = mergeWildcard(buildResults.values());
|
const mergedWildcard = mergeWildcard(buildResults.values());
|
||||||
const mergedOverrides: Record<string, PathOverride> =
|
const mergedOverrides: Record<string, PathOverride> =
|
||||||
overrides.length > 0 ? Object.assign({}, ...overrides) : undefined;
|
overrides.length > 0 ? Object.assign({}, ...overrides) : undefined;
|
||||||
|
const mergedFlags = mergeFlags(buildResults.values());
|
||||||
|
|
||||||
const framework = await getFramework(cwd, buildResults);
|
const framework = await getFramework(cwd, buildResults);
|
||||||
|
|
||||||
@@ -640,6 +660,7 @@ async function doBuild(
|
|||||||
overrides: mergedOverrides,
|
overrides: mergedOverrides,
|
||||||
framework,
|
framework,
|
||||||
crons: mergedCrons,
|
crons: mergedCrons,
|
||||||
|
flags: mergedFlags,
|
||||||
};
|
};
|
||||||
await fs.writeJSON(join(outputDir, 'config.json'), config, { spaces: 2 });
|
await fs.writeJSON(join(outputDir, 'config.json'), config, { spaces: 2 });
|
||||||
|
|
||||||
@@ -774,3 +795,15 @@ function mergeWildcard(
|
|||||||
}
|
}
|
||||||
return wildcard;
|
return wildcard;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function mergeFlags(
|
||||||
|
buildResults: Iterable<BuildResult | BuildOutputConfig>
|
||||||
|
): BuildResultV2Typical['flags'] {
|
||||||
|
return Array.from(buildResults).flatMap(result => {
|
||||||
|
if ('flags' in result) {
|
||||||
|
return result.flags ?? [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ export const domainsCommand: Command = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'move',
|
name: 'move',
|
||||||
description: 'Move a domain to another user or team',
|
description: 'Move a domain to another scope',
|
||||||
arguments: [
|
arguments: [
|
||||||
{
|
{
|
||||||
name: 'name',
|
name: 'name',
|
||||||
|
|||||||
@@ -53,6 +53,12 @@ export default async function move(
|
|||||||
|
|
||||||
const teams = await getTeams(client);
|
const teams = await getTeams(client);
|
||||||
const matchId = await findDestinationMatch(destination, user, teams);
|
const matchId = await findDestinationMatch(destination, user, teams);
|
||||||
|
|
||||||
|
if (matchId && matchId === user.id && user.version === 'northstar') {
|
||||||
|
output.error(`You may not move your domain to your user account.`);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (!matchId && !opts['--yes']) {
|
if (!matchId && !opts['--yes']) {
|
||||||
output.warn(
|
output.warn(
|
||||||
`You're not a member of ${param(destination)}. ` +
|
`You're not a member of ${param(destination)}. ` +
|
||||||
|
|||||||
7
packages/cli/src/commands/env/pull.ts
vendored
7
packages/cli/src/commands/env/pull.ts
vendored
@@ -55,6 +55,12 @@ function tryReadHeadSync(path: string, length: number) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const VARIABLES_TO_IGNORE = [
|
||||||
|
'VERCEL_ANALYTICS_ID',
|
||||||
|
'VERCEL_SPEED_INSIGHTS_ID',
|
||||||
|
'VERCEL_WEB_ANALYTICS_ID',
|
||||||
|
];
|
||||||
|
|
||||||
export default async function pull(
|
export default async function pull(
|
||||||
client: Client,
|
client: Client,
|
||||||
link: ProjectLinked,
|
link: ProjectLinked,
|
||||||
@@ -131,6 +137,7 @@ export default async function pull(
|
|||||||
CONTENTS_PREFIX +
|
CONTENTS_PREFIX +
|
||||||
Object.keys(records)
|
Object.keys(records)
|
||||||
.sort()
|
.sort()
|
||||||
|
.filter(key => !VARIABLES_TO_IGNORE.includes(key))
|
||||||
.map(key => `${key}="${escapeValue(records[key])}"`)
|
.map(key => `${key}="${escapeValue(records[key])}"`)
|
||||||
.join('\n') +
|
.join('\n') +
|
||||||
'\n';
|
'\n';
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import Client from '../../util/client';
|
|||||||
import { LoginResult } from '../../util/login/types';
|
import { LoginResult } from '../../util/login/types';
|
||||||
import { help } from '../help';
|
import { help } from '../help';
|
||||||
import { loginCommand } from './command';
|
import { loginCommand } from './command';
|
||||||
|
import { updateCurrentTeamAfterLogin } from '../../util/login/update-current-team-after-login';
|
||||||
|
|
||||||
export default async function login(client: Client): Promise<number> {
|
export default async function login(client: Client): Promise<number> {
|
||||||
const { output } = client;
|
const { output } = client;
|
||||||
@@ -67,20 +68,16 @@ export default async function login(client: Client): Promise<number> {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the token was upgraded (not a new login), then don't modify
|
const isNewLogin = !client.authConfig.token;
|
||||||
// the current scope.
|
|
||||||
if (!client.authConfig.token) {
|
|
||||||
if (result.teamId) {
|
|
||||||
// SSO login, so set the current scope to the appropriate Team
|
|
||||||
client.config.currentTeam = result.teamId;
|
|
||||||
} else {
|
|
||||||
delete client.config.currentTeam;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save the user's authentication token to the configuration file.
|
// Save the user's authentication token to the configuration file.
|
||||||
client.authConfig.token = result.token;
|
client.authConfig.token = result.token;
|
||||||
|
|
||||||
|
// If we have a new login, update `currentTeam`
|
||||||
|
if (isNewLogin) {
|
||||||
|
await updateCurrentTeamAfterLogin(client, output, result.teamId);
|
||||||
|
}
|
||||||
|
|
||||||
writeToAuthConfigFile(client.authConfig);
|
writeToAuthConfigFile(client.authConfig);
|
||||||
writeToConfigFile(client.config);
|
writeToConfigFile(client.config);
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { packageName } from '../../util/pkg-name';
|
|||||||
|
|
||||||
export const logoutCommand: Command = {
|
export const logoutCommand: Command = {
|
||||||
name: 'logout',
|
name: 'logout',
|
||||||
description: 'Logout the current authenticated user or team.',
|
description: 'Logout the current authenticated user.',
|
||||||
arguments: [],
|
arguments: [],
|
||||||
options: [],
|
options: [],
|
||||||
examples: [
|
examples: [
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export const projectCommand: Command = {
|
|||||||
subcommands: [
|
subcommands: [
|
||||||
{
|
{
|
||||||
name: 'ls',
|
name: 'ls',
|
||||||
description: 'Show all projects in the selected team/user',
|
description: 'Show all projects in the selected scope',
|
||||||
arguments: [],
|
arguments: [],
|
||||||
options: [],
|
options: [],
|
||||||
examples: [],
|
examples: [],
|
||||||
|
|||||||
@@ -39,11 +39,12 @@ export default async function list(client: Client): Promise<number> {
|
|||||||
apiVersion: 2,
|
apiVersion: 2,
|
||||||
});
|
});
|
||||||
let { currentTeam } = config;
|
let { currentTeam } = config;
|
||||||
const accountIsCurrent = !currentTeam;
|
|
||||||
|
|
||||||
output.spinner('Fetching user information');
|
output.spinner('Fetching user information');
|
||||||
const user = await getUser(client);
|
const user = await getUser(client);
|
||||||
|
|
||||||
|
const accountIsCurrent = !currentTeam && user.version !== 'northstar';
|
||||||
|
|
||||||
if (accountIsCurrent) {
|
if (accountIsCurrent) {
|
||||||
currentTeam = user.id;
|
currentTeam = user.id;
|
||||||
}
|
}
|
||||||
@@ -55,12 +56,14 @@ export default async function list(client: Client): Promise<number> {
|
|||||||
current: id === currentTeam ? chars.tick : '',
|
current: id === currentTeam ? chars.tick : '',
|
||||||
}));
|
}));
|
||||||
|
|
||||||
teamList.unshift({
|
if (user.version !== 'northstar') {
|
||||||
id: user.id,
|
teamList.unshift({
|
||||||
name: user.email,
|
id: user.id,
|
||||||
value: user.username || user.email,
|
name: user.email,
|
||||||
current: accountIsCurrent ? chars.tick : '',
|
value: user.username || user.email,
|
||||||
});
|
current: accountIsCurrent ? chars.tick : '',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Bring the current Team to the beginning of the list
|
// Bring the current Team to the beginning of the list
|
||||||
if (!accountIsCurrent) {
|
if (!accountIsCurrent) {
|
||||||
@@ -71,18 +74,21 @@ export default async function list(client: Client): Promise<number> {
|
|||||||
|
|
||||||
// Printing
|
// Printing
|
||||||
output.stopSpinner();
|
output.stopSpinner();
|
||||||
console.log(); // empty line
|
client.stdout.write('\n'); // empty line
|
||||||
|
|
||||||
table(
|
table(
|
||||||
['', 'id', 'email / name'],
|
['', 'id', 'email / name'],
|
||||||
teamList.map(team => [team.current, team.value, team.name]),
|
teamList.map(team => [team.current, team.value, team.name]),
|
||||||
[1, 5]
|
[1, 5],
|
||||||
|
(str: string) => {
|
||||||
|
client.stdout.write(str);
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
if (pagination?.count === 20) {
|
if (pagination?.count === 20) {
|
||||||
const flags = getCommandFlags(argv, ['_', '--next', '-N', '-d']);
|
const flags = getCommandFlags(argv, ['_', '--next', '-N', '-d']);
|
||||||
const nextCmd = `${packageName} teams ls${flags} --next ${pagination.next}`;
|
const nextCmd = `${packageName} teams ls${flags} --next ${pagination.next}`;
|
||||||
console.log(); // empty line
|
client.stdout.write('\n'); // empty line
|
||||||
output.log(`To display the next page run ${cmd(nextCmd)}`);
|
output.log(`To display the next page run ${cmd(nextCmd)}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -70,14 +70,21 @@ export default async function main(client: Client, desiredSlug?: string) {
|
|||||||
suffix += ` ${emoji('locked')}`;
|
suffix += ` ${emoji('locked')}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const personalAccountChoice =
|
||||||
|
user.version === 'northstar'
|
||||||
|
? []
|
||||||
|
: [
|
||||||
|
{ separator: 'Personal Account' },
|
||||||
|
{
|
||||||
|
name: `${user.name || user.email} (${user.username})${suffix}`,
|
||||||
|
value: user.username,
|
||||||
|
short: user.username,
|
||||||
|
selected: personalScopeSelected,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
const choices = [
|
const choices = [
|
||||||
{ separator: 'Personal Account' },
|
...personalAccountChoice,
|
||||||
{
|
|
||||||
name: `${user.name || user.email} (${user.username})${suffix}`,
|
|
||||||
value: user.username,
|
|
||||||
short: user.username,
|
|
||||||
selected: personalScopeSelected,
|
|
||||||
},
|
|
||||||
{ separator: 'Teams' },
|
{ separator: 'Teams' },
|
||||||
...teamChoices,
|
...teamChoices,
|
||||||
];
|
];
|
||||||
@@ -97,6 +104,11 @@ export default async function main(client: Client, desiredSlug?: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (desiredSlug === user.username || desiredSlug === user.email) {
|
if (desiredSlug === user.username || desiredSlug === user.email) {
|
||||||
|
if (user.version === 'northstar') {
|
||||||
|
output.error('You cannot set your Personal Account as the scope.');
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
// Switch to user's personal account
|
// Switch to user's personal account
|
||||||
if (personalScopeSelected) {
|
if (personalScopeSelected) {
|
||||||
output.log('No changes made');
|
output.log('No changes made');
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ import { ProxyAgent } from 'proxy-agent';
|
|||||||
import box from './util/output/box';
|
import box from './util/output/box';
|
||||||
import { execExtension } from './util/extension/exec';
|
import { execExtension } from './util/extension/exec';
|
||||||
import { help } from './args';
|
import { help } from './args';
|
||||||
|
import { updateCurrentTeamAfterLogin } from './util/login/update-current-team-after-login';
|
||||||
|
|
||||||
const VERCEL_DIR = getGlobalPathConfig();
|
const VERCEL_DIR = getGlobalPathConfig();
|
||||||
const VERCEL_CONFIG_PATH = configFiles.getConfigFilePath();
|
const VERCEL_CONFIG_PATH = configFiles.getConfigFilePath();
|
||||||
@@ -337,17 +338,12 @@ const main = async () => {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result.teamId) {
|
|
||||||
// SSO login, so set the current scope to the appropriate Team
|
|
||||||
client.config.currentTeam = result.teamId;
|
|
||||||
} else {
|
|
||||||
delete client.config.currentTeam;
|
|
||||||
}
|
|
||||||
|
|
||||||
// When `result` is a string it's the user's authentication token.
|
// When `result` is a string it's the user's authentication token.
|
||||||
// It needs to be saved to the configuration file.
|
// It needs to be saved to the configuration file.
|
||||||
client.authConfig.token = result.token;
|
client.authConfig.token = result.token;
|
||||||
|
|
||||||
|
await updateCurrentTeamAfterLogin(client, output, result.teamId);
|
||||||
|
|
||||||
configFiles.writeToAuthConfigFile(client.authConfig);
|
configFiles.writeToAuthConfigFile(client.authConfig);
|
||||||
configFiles.writeToConfigFile(client.config);
|
configFiles.writeToConfigFile(client.config);
|
||||||
|
|
||||||
@@ -447,6 +443,11 @@ const main = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (user.id === scope || user.email === scope || user.username === scope) {
|
if (user.id === scope || user.email === scope || user.username === scope) {
|
||||||
|
if (user.version === 'northstar') {
|
||||||
|
output.error('You cannot set your Personal Account as the scope.');
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
delete client.config.currentTeam;
|
delete client.config.currentTeam;
|
||||||
} else {
|
} else {
|
||||||
let teams = [];
|
let teams = [];
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ export async function initCorepack({
|
|||||||
const pkgManagerName = pkg.packageManager.split('@')[0];
|
const pkgManagerName = pkg.packageManager.split('@')[0];
|
||||||
// We must explicitly call `corepack enable npm` since `corepack enable`
|
// We must explicitly call `corepack enable npm` since `corepack enable`
|
||||||
// doesn't work with npm. See https://github.com/nodejs/corepack/pull/24
|
// doesn't work with npm. See https://github.com/nodejs/corepack/pull/24
|
||||||
// Also, `corepack enable` is too broad and will change the verison of
|
// Also, `corepack enable` is too broad and will change the version of
|
||||||
// yarn & pnpm even though those versions are not specified by the user.
|
// yarn & pnpm even though those versions are not specified by the user.
|
||||||
// See https://github.com/nodejs/corepack#known-good-releases
|
// See https://github.com/nodejs/corepack#known-good-releases
|
||||||
// Finally, we use `--install-directory` so we can cache the result to
|
// Finally, we use `--install-directory` so we can cache the result to
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ export class TeamDeleted extends NowError<'TEAM_DELETED', {}> {
|
|||||||
constructor() {
|
constructor() {
|
||||||
super({
|
super({
|
||||||
code: 'TEAM_DELETED',
|
code: 'TEAM_DELETED',
|
||||||
message: `Your team was deleted. You can switch to a different one using ${getCommandName(
|
message: `Your team was deleted or you were removed from the team. You can switch to a different one using ${getCommandName(
|
||||||
`switch`
|
`switch`
|
||||||
)}.`,
|
)}.`,
|
||||||
meta: {},
|
meta: {},
|
||||||
|
|||||||
@@ -15,9 +15,12 @@ export default async function getScope(
|
|||||||
const user = await getUser(client);
|
const user = await getUser(client);
|
||||||
let contextName = user.username || user.email;
|
let contextName = user.username || user.email;
|
||||||
let team: Team | null = null;
|
let team: Team | null = null;
|
||||||
|
const defaultTeamId =
|
||||||
|
user.version === 'northstar' ? user.defaultTeamId : undefined;
|
||||||
|
const currentTeamOrDefaultTeamId = client.config.currentTeam || defaultTeamId;
|
||||||
|
|
||||||
if (client.config.currentTeam && opts.getTeam !== false) {
|
if (currentTeamOrDefaultTeamId && opts.getTeam !== false) {
|
||||||
team = await getTeamById(client, client.config.currentTeam);
|
team = await getTeamById(client, currentTeamOrDefaultTeamId);
|
||||||
|
|
||||||
if (!team) {
|
if (!team) {
|
||||||
throw new TeamDeleted();
|
throw new TeamDeleted();
|
||||||
|
|||||||
@@ -25,11 +25,18 @@ export default async function selectOrg(
|
|||||||
output.stopSpinner();
|
output.stopSpinner();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const personalAccountChoice =
|
||||||
|
user.version === 'northstar'
|
||||||
|
? []
|
||||||
|
: [
|
||||||
|
{
|
||||||
|
name: user.name || user.username,
|
||||||
|
value: { type: 'user', id: user.id, slug: user.username },
|
||||||
|
} as const,
|
||||||
|
];
|
||||||
|
|
||||||
const choices: Choice[] = [
|
const choices: Choice[] = [
|
||||||
{
|
...personalAccountChoice,
|
||||||
name: user.name || user.username,
|
|
||||||
value: { type: 'user', id: user.id, slug: user.username },
|
|
||||||
},
|
|
||||||
...teams.map<Choice>(team => ({
|
...teams.map<Choice>(team => ({
|
||||||
name: team.name || team.slug,
|
name: team.name || team.slug,
|
||||||
value: { type: 'team', id: team.id, slug: team.slug },
|
value: { type: 'team', id: team.id, slug: team.slug },
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import type Client from '../client';
|
||||||
|
import type { Output } from '../output';
|
||||||
|
import getUser from '../get-user';
|
||||||
|
|
||||||
|
// NOTE: `client.authConfig.token` must be set before calling this
|
||||||
|
export async function updateCurrentTeamAfterLogin(
|
||||||
|
client: Client,
|
||||||
|
output: Output,
|
||||||
|
ssoTeamId?: string
|
||||||
|
) {
|
||||||
|
if (ssoTeamId) {
|
||||||
|
client.config.currentTeam = ssoTeamId;
|
||||||
|
} else {
|
||||||
|
let user = null;
|
||||||
|
try {
|
||||||
|
user = await getUser(client);
|
||||||
|
} catch (err: unknown) {
|
||||||
|
// Shouldn't happen since we just logged in
|
||||||
|
output.error('Failed to fetch the logged in user. Please try again.');
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user.version === 'northstar' && user.defaultTeamId) {
|
||||||
|
client.config.currentTeam = user.defaultTeamId;
|
||||||
|
} else {
|
||||||
|
delete client.config.currentTeam;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,7 +9,8 @@ const printLine = (data: string[], sizes: number[]) =>
|
|||||||
export default function table(
|
export default function table(
|
||||||
fieldNames: string[] = [],
|
fieldNames: string[] = [],
|
||||||
data: string[][] = [],
|
data: string[][] = [],
|
||||||
margins: number[] = []
|
margins: number[] = [],
|
||||||
|
print: (str: string) => void
|
||||||
) {
|
) {
|
||||||
// Compute size of each column
|
// Compute size of each column
|
||||||
const sizes = data
|
const sizes = data
|
||||||
@@ -26,10 +27,12 @@ export default function table(
|
|||||||
.map((size, i) => (i < margins.length && size + margins[i]) || size);
|
.map((size, i) => (i < margins.length && size + margins[i]) || size);
|
||||||
|
|
||||||
// Print header
|
// Print header
|
||||||
console.log(chalk.grey(printLine(fieldNames, sizes)));
|
print(chalk.grey(printLine(fieldNames, sizes)));
|
||||||
|
print('\n');
|
||||||
|
|
||||||
// Print content
|
// Print content
|
||||||
for (const row of data) {
|
for (const row of data) {
|
||||||
console.log(printLine(row, sizes));
|
print(printLine(row, sizes));
|
||||||
|
print('\n');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -415,6 +415,24 @@ module.exports = async function prepare(session, binaryPath, tmpFixturesDir) {
|
|||||||
projectId: 'QmRoBYhejkkmssotLZr8tWgewPdPcjYucYUNERFbhJrRNi',
|
projectId: 'QmRoBYhejkkmssotLZr8tWgewPdPcjYucYUNERFbhJrRNi',
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
|
'vc-build-speed-insights': {
|
||||||
|
'.vercel/project.json': JSON.stringify({
|
||||||
|
orgId: '.',
|
||||||
|
projectId: '.',
|
||||||
|
settings: {
|
||||||
|
framework: null,
|
||||||
|
installCommand: 'echo "skipping install"',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
'package.json': JSON.stringify({
|
||||||
|
scripts: {
|
||||||
|
build: 'mkdir -p public && echo hi > public/index.txt',
|
||||||
|
},
|
||||||
|
dependencies: {
|
||||||
|
'@vercel/speed-insights': '0.0.1',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
},
|
||||||
'vc-build-static-build': {
|
'vc-build-static-build': {
|
||||||
'.vercel/project.json': JSON.stringify({
|
'.vercel/project.json': JSON.stringify({
|
||||||
orgId: '.',
|
orgId: '.',
|
||||||
|
|||||||
3
packages/cli/test/integration-1.test.ts
vendored
3
packages/cli/test/integration-1.test.ts
vendored
@@ -16,7 +16,6 @@ import {
|
|||||||
import formatOutput from './helpers/format-output';
|
import formatOutput from './helpers/format-output';
|
||||||
import type http from 'http';
|
import type http from 'http';
|
||||||
import type { CLIProcess } from './helpers/types';
|
import type { CLIProcess } from './helpers/types';
|
||||||
import type {} from './helpers/types';
|
|
||||||
const TEST_TIMEOUT = 3 * 60 * 1000;
|
const TEST_TIMEOUT = 3 * 60 * 1000;
|
||||||
jest.setTimeout(TEST_TIMEOUT);
|
jest.setTimeout(TEST_TIMEOUT);
|
||||||
|
|
||||||
@@ -105,6 +104,8 @@ function mockLoginApi(req: http.IncomingMessage, res: http.ServerResponse) {
|
|||||||
query.email === email
|
query.email === email
|
||||||
) {
|
) {
|
||||||
res.end(JSON.stringify({ token }));
|
res.end(JSON.stringify({ token }));
|
||||||
|
} else if (method === 'GET' && pathname === '/v2/user') {
|
||||||
|
res.end(JSON.stringify({ user: { email } }));
|
||||||
} else {
|
} else {
|
||||||
res.statusCode = 405;
|
res.statusCode = 405;
|
||||||
res.end(JSON.stringify({ code: 'method_not_allowed' }));
|
res.end(JSON.stringify({ code: 'method_not_allowed' }));
|
||||||
|
|||||||
18
packages/cli/test/integration-2.test.ts
vendored
18
packages/cli/test/integration-2.test.ts
vendored
@@ -79,6 +79,8 @@ function mockLoginApi(req: http.IncomingMessage, res: http.ServerResponse) {
|
|||||||
query.email === email
|
query.email === email
|
||||||
) {
|
) {
|
||||||
res.end(JSON.stringify({ token }));
|
res.end(JSON.stringify({ token }));
|
||||||
|
} else if (method === 'GET' && pathname === '/v2/user') {
|
||||||
|
res.end(JSON.stringify({ user: { email } }));
|
||||||
} else {
|
} else {
|
||||||
res.statusCode = 405;
|
res.statusCode = 405;
|
||||||
res.end(JSON.stringify({ code: 'method_not_allowed' }));
|
res.end(JSON.stringify({ code: 'method_not_allowed' }));
|
||||||
@@ -1152,6 +1154,22 @@ test('[vc build] should build project with `@vercel/static-build`', async () =>
|
|||||||
expect(builds.builds[0].use).toBe('@vercel/static-build');
|
expect(builds.builds[0].use).toBe('@vercel/static-build');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('[vc build] should build project with `@vercel/speed-insights`', async () => {
|
||||||
|
try {
|
||||||
|
process.env.VERCEL_ANALYTICS_ID = '123';
|
||||||
|
|
||||||
|
const directory = await setupE2EFixture('vc-build-speed-insights');
|
||||||
|
const output = await execCli(binaryPath, ['build'], { cwd: directory });
|
||||||
|
expect(output.exitCode, formatOutput(output)).toBe(0);
|
||||||
|
expect(output.stderr).toContain('Build Completed in .vercel/output');
|
||||||
|
expect(output.stderr).toContain(
|
||||||
|
'The `VERCEL_ANALYTICS_ID` environment variable is deprecated and will be removed in a future release. Please remove it from your environment variables'
|
||||||
|
);
|
||||||
|
} finally {
|
||||||
|
delete process.env.VERCEL_ANALYTICS_ID;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
test('[vc build] should not include .vercel when distDir is "."', async () => {
|
test('[vc build] should not include .vercel when distDir is "."', async () => {
|
||||||
const directory = await setupE2EFixture('static-build-dist-dir');
|
const directory = await setupE2EFixture('static-build-dist-dir');
|
||||||
const output = await execCli(binaryPath, ['build'], { cwd: directory });
|
const output = await execCli(binaryPath, ['build'], { cwd: directory });
|
||||||
|
|||||||
2
packages/cli/test/integration-3.test.ts
vendored
2
packages/cli/test/integration-3.test.ts
vendored
@@ -89,6 +89,8 @@ function mockLoginApi(req: http.IncomingMessage, res: http.ServerResponse) {
|
|||||||
query.email === email
|
query.email === email
|
||||||
) {
|
) {
|
||||||
res.end(JSON.stringify({ token }));
|
res.end(JSON.stringify({ token }));
|
||||||
|
} else if (method === 'GET' && pathname === '/v2/user') {
|
||||||
|
res.end(JSON.stringify({ user: { email } }));
|
||||||
} else {
|
} else {
|
||||||
res.statusCode = 405;
|
res.statusCode = 405;
|
||||||
res.end(JSON.stringify({ code: 'method_not_allowed' }));
|
res.end(JSON.stringify({ code: 'method_not_allowed' }));
|
||||||
|
|||||||
@@ -40,3 +40,15 @@ export function useDomains() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function useDomain(postfix: string) {
|
||||||
|
client.scenario.get(
|
||||||
|
`/v4/domains/${encodeURIComponent(`example-${postfix}.com`)}`,
|
||||||
|
(req, res) => {
|
||||||
|
const domain = createDomain(postfix);
|
||||||
|
res.json({
|
||||||
|
domain,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,10 +7,12 @@ export function useTeams(
|
|||||||
failMissingToken?: boolean;
|
failMissingToken?: boolean;
|
||||||
failInvalidToken?: boolean;
|
failInvalidToken?: boolean;
|
||||||
failNoAccess?: boolean;
|
failNoAccess?: boolean;
|
||||||
|
apiVersion?: number;
|
||||||
} = {
|
} = {
|
||||||
failMissingToken: false,
|
failMissingToken: false,
|
||||||
failInvalidToken: false,
|
failInvalidToken: false,
|
||||||
failNoAccess: false,
|
failNoAccess: false,
|
||||||
|
apiVersion: 1,
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
const id = teamId || chance().guid();
|
const id = teamId || chance().guid();
|
||||||
@@ -59,11 +61,11 @@ export function useTeams(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
client.scenario.get('/v1/teams', (_req, res) => {
|
client.scenario.get(`/v${options.apiVersion}/teams`, (_req, res) => {
|
||||||
res.json({
|
res.json({
|
||||||
teams,
|
teams,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
return teams;
|
return options.apiVersion === 2 ? { teams } : teams;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
import chance from 'chance';
|
import chance from 'chance';
|
||||||
import { client } from './client';
|
import { client } from './client';
|
||||||
|
import type { User } from '@vercel-internals/types';
|
||||||
|
|
||||||
export function useUser() {
|
export function useUser(additionalAttrs: Partial<User> = {}) {
|
||||||
const user = {
|
const user = {
|
||||||
id: chance().guid(),
|
id: chance().guid(),
|
||||||
email: chance().email(),
|
email: chance().email(),
|
||||||
name: chance().name(),
|
name: chance().name(),
|
||||||
username: chance().first().toLowerCase(),
|
username: chance().first().toLowerCase(),
|
||||||
|
...additionalAttrs,
|
||||||
};
|
};
|
||||||
client.scenario.get('/v2/user', (_req, res) => {
|
client.scenario.get('/v2/user', (_req, res) => {
|
||||||
res.json({
|
res.json({
|
||||||
|
|||||||
173
packages/cli/test/northstar.test.ts
vendored
Normal file
173
packages/cli/test/northstar.test.ts
vendored
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
import type http from 'http';
|
||||||
|
import fs from 'fs-extra';
|
||||||
|
import path from 'path';
|
||||||
|
import { parse as parseUrl } from 'url';
|
||||||
|
import { execCli } from './helpers/exec';
|
||||||
|
import waitForPrompt from './helpers/wait-for-prompt';
|
||||||
|
import getGlobalDir from './helpers/get-global-dir';
|
||||||
|
import { listTmpDirs } from './helpers/get-tmp-dir';
|
||||||
|
import formatOutput from './helpers/format-output';
|
||||||
|
import { User } from '@vercel-internals/types';
|
||||||
|
|
||||||
|
const binaryPath = path.resolve(__dirname, `../scripts/start.js`);
|
||||||
|
|
||||||
|
function getGlobalConfigPath() {
|
||||||
|
return path.join(getGlobalDir(), 'config.json');
|
||||||
|
}
|
||||||
|
|
||||||
|
function getConfigAuthPath() {
|
||||||
|
return path.join(getGlobalDir(), 'auth.json');
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
try {
|
||||||
|
await fs.remove(getGlobalConfigPath());
|
||||||
|
await fs.remove(getConfigAuthPath());
|
||||||
|
} catch (err) {
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
if (localApiServer) {
|
||||||
|
localApiServer.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
const allTmpDirs = listTmpDirs();
|
||||||
|
for (const tmpDir of allTmpDirs) {
|
||||||
|
tmpDir.removeCallback();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function mockApi(user: Partial<User>) {
|
||||||
|
return function (req: http.IncomingMessage, res: http.ServerResponse) {
|
||||||
|
const { url = '/', method } = req;
|
||||||
|
let { pathname = '/', query = {} } = parseUrl(url, true);
|
||||||
|
const securityCode = 'Bears Beets Battlestar Galactica';
|
||||||
|
res.setHeader('content-type', 'application/json');
|
||||||
|
if (
|
||||||
|
method === 'POST' &&
|
||||||
|
pathname === '/registration' &&
|
||||||
|
query.mode === 'login'
|
||||||
|
) {
|
||||||
|
res.end(JSON.stringify({ token: 'test', securityCode }));
|
||||||
|
} else if (
|
||||||
|
method === 'GET' &&
|
||||||
|
pathname === '/registration/verify' &&
|
||||||
|
query.email === user.email
|
||||||
|
) {
|
||||||
|
res.end(JSON.stringify({ token: 'test' }));
|
||||||
|
} else if (method === 'GET' && pathname === '/v2/user') {
|
||||||
|
res.end(JSON.stringify({ user }));
|
||||||
|
} else {
|
||||||
|
res.statusCode = 405;
|
||||||
|
res.end(JSON.stringify({ code: 'method_not_allowed' }));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
let localApiServer: any;
|
||||||
|
function setupLocalApiServer(user: Partial<User>) {
|
||||||
|
return new Promise<string>(resolve => {
|
||||||
|
localApiServer = require('http')
|
||||||
|
.createServer(mockApi(user))
|
||||||
|
.listen(0, () => {
|
||||||
|
const { port } = localApiServer.address();
|
||||||
|
const loginApiUrl = `http://localhost:${port}`;
|
||||||
|
resolve(loginApiUrl);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loginSteps(
|
||||||
|
vercel: ReturnType<typeof execCli>,
|
||||||
|
user: Partial<User>
|
||||||
|
) {
|
||||||
|
await waitForPrompt(vercel, 'Continue with Email');
|
||||||
|
vercel.stdin?.write('\x1B[B'); // Down arrow
|
||||||
|
vercel.stdin?.write('\x1B[B'); // Down arrow
|
||||||
|
vercel.stdin?.write('\x1B[B'); // Down arrow
|
||||||
|
vercel.stdin?.write('\r'); // Return key
|
||||||
|
await waitForPrompt(vercel, 'Enter your email address');
|
||||||
|
vercel.stdin?.write(user.email);
|
||||||
|
vercel.stdin?.write('\r');
|
||||||
|
await waitForPrompt(
|
||||||
|
vercel,
|
||||||
|
`Email authentication complete for ${user.email}`
|
||||||
|
);
|
||||||
|
return vercel;
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('CLI initialization', () => {
|
||||||
|
describe('login required before running a command', () => {
|
||||||
|
describe('non-northstar', () => {
|
||||||
|
const user = {
|
||||||
|
id: 'test-id',
|
||||||
|
username: 'test-username',
|
||||||
|
email: 'test@example.com',
|
||||||
|
};
|
||||||
|
|
||||||
|
it('should not set currentTeam to defaultTeamId', async () => {
|
||||||
|
const loginApiUrl = await setupLocalApiServer(user);
|
||||||
|
const vercel = execCli(
|
||||||
|
binaryPath,
|
||||||
|
['domains', 'invalidSubCommand', '--api', loginApiUrl],
|
||||||
|
{ env: { FORCE_TTY: '1' } }
|
||||||
|
);
|
||||||
|
const steps = loginSteps(vercel, user);
|
||||||
|
await waitForPrompt(vercel, 'Please specify a valid subcommand');
|
||||||
|
const output = await steps;
|
||||||
|
expect(output.exitCode, formatOutput(output)).toBe(2);
|
||||||
|
const config = await fs.readJSON(getGlobalConfigPath());
|
||||||
|
expect(config.currentTeam).toBeUndefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('northstar', () => {
|
||||||
|
const user = {
|
||||||
|
id: 'test-id',
|
||||||
|
username: 'test-username',
|
||||||
|
email: 'test@example.com',
|
||||||
|
version: 'northstar',
|
||||||
|
defaultTeamId: 'test-default-team-id',
|
||||||
|
};
|
||||||
|
it('should set currentTeam to defaultTeamId', async () => {
|
||||||
|
const loginApiUrl = await setupLocalApiServer(user);
|
||||||
|
const vercel = execCli(
|
||||||
|
binaryPath,
|
||||||
|
['domains', 'invalidSubCommand', '--api', loginApiUrl],
|
||||||
|
{ env: { FORCE_TTY: '1' } }
|
||||||
|
);
|
||||||
|
const steps = loginSteps(vercel, user);
|
||||||
|
await waitForPrompt(vercel, 'Please specify a valid subcommand');
|
||||||
|
const output = await steps;
|
||||||
|
expect(output.exitCode, formatOutput(output)).toBe(2);
|
||||||
|
const config = await fs.readJSON(getGlobalConfigPath());
|
||||||
|
expect(config.currentTeam).toEqual(user.defaultTeamId);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not allow setting user as scope', async () => {
|
||||||
|
const loginApiUrl = await setupLocalApiServer(user);
|
||||||
|
const vercel = execCli(
|
||||||
|
binaryPath,
|
||||||
|
[
|
||||||
|
'domains',
|
||||||
|
'invalidSubCommand',
|
||||||
|
'--api',
|
||||||
|
loginApiUrl,
|
||||||
|
'--scope',
|
||||||
|
user.username,
|
||||||
|
],
|
||||||
|
{ env: { FORCE_TTY: '1' } }
|
||||||
|
);
|
||||||
|
const steps = loginSteps(vercel, user);
|
||||||
|
await waitForPrompt(
|
||||||
|
vercel,
|
||||||
|
'You cannot set your Personal Account as the scope.'
|
||||||
|
);
|
||||||
|
const output = await steps;
|
||||||
|
expect(output.exitCode, formatOutput(output)).toBe(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
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';
|
||||||
import { useDomains } from '../../mocks/domains';
|
import { useTeams } from '../../mocks/team';
|
||||||
|
import { useDomain, useDomains } from '../../mocks/domains';
|
||||||
|
|
||||||
describe('domains', () => {
|
describe('domains', () => {
|
||||||
it('should list up to 20 domains by default', async () => {
|
it('should list up to 20 domains by default', async () => {
|
||||||
@@ -21,4 +22,19 @@ describe('domains', () => {
|
|||||||
await expect(client.stderr).toOutput('example-1.com');
|
await expect(client.stderr).toOutput('example-1.com');
|
||||||
await expect(exitCodePromise).resolves.toEqual(0);
|
await expect(exitCodePromise).resolves.toEqual(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('northstar', () => {
|
||||||
|
it('should prevent moving a domain to a user account', async () => {
|
||||||
|
const { username } = useUser({ version: 'northstar' });
|
||||||
|
useTeams();
|
||||||
|
useDomain('northstar');
|
||||||
|
client.setArgv('domains', 'move', 'example-northstar.com', username);
|
||||||
|
const exitCodePromise = domains(client);
|
||||||
|
await expect(client.stderr).toOutput(
|
||||||
|
`Fetching domain example-northstar.com under ${username}
|
||||||
|
Error: You may not move your domain to your user account.`
|
||||||
|
);
|
||||||
|
await expect(exitCodePromise).resolves.toEqual(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -426,5 +426,46 @@ describe('env', () => {
|
|||||||
);
|
);
|
||||||
expect(gitignoreAfter).toBe(gitignoreBefore);
|
expect(gitignoreAfter).toBe(gitignoreBefore);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should not pull VERCEL_ANALYTICS_ID', async () => {
|
||||||
|
useUser();
|
||||||
|
useTeams('team_dummy');
|
||||||
|
useProject(
|
||||||
|
{
|
||||||
|
...defaultProject,
|
||||||
|
id: 'vercel-env-pull',
|
||||||
|
name: 'vercel-env-pull',
|
||||||
|
analytics: {
|
||||||
|
id: 'VC-ANALYTICS-ID',
|
||||||
|
enabledAt: Date.now(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
[
|
||||||
|
{
|
||||||
|
type: 'encrypted',
|
||||||
|
id: '781dt89g8r2h789g',
|
||||||
|
key: 'VERCEL_ANALYTICS_ID',
|
||||||
|
value: 'VC-ANALYTICS-ID',
|
||||||
|
target: ['development'],
|
||||||
|
configurationId: null,
|
||||||
|
updatedAt: 1557241361455,
|
||||||
|
createdAt: 1557241361455,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
);
|
||||||
|
const cwd = setupUnitFixture('vercel-env-pull');
|
||||||
|
client.cwd = cwd;
|
||||||
|
client.setArgv('env', 'pull', '--yes');
|
||||||
|
const exitCodePromise = env(client);
|
||||||
|
await expect(client.stderr).toOutput(
|
||||||
|
'Downloading `development` Environment Variables for Project '
|
||||||
|
);
|
||||||
|
await expect(client.stderr).toOutput('Created .env.local file');
|
||||||
|
await expect(exitCodePromise).resolves.toEqual(0);
|
||||||
|
|
||||||
|
const rawDevEnv = await fs.readFile(path.join(cwd, '.env.local'));
|
||||||
|
|
||||||
|
expect(rawDevEnv.toString().includes('VERCEL_ANALYTICS_ID')).toBeFalsy();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ import { setupTmpDir } from '../../helpers/setup-unit-fixture';
|
|||||||
|
|
||||||
describe('link', () => {
|
describe('link', () => {
|
||||||
it('should prompt for link', async () => {
|
it('should prompt for link', async () => {
|
||||||
const cwd = setupTmpDir();
|
|
||||||
const user = useUser();
|
const user = useUser();
|
||||||
|
const cwd = setupTmpDir();
|
||||||
useTeams('team_dummy');
|
useTeams('team_dummy');
|
||||||
const { project } = useProject({
|
const { project } = useProject({
|
||||||
...defaultProject,
|
...defaultProject,
|
||||||
|
|||||||
@@ -25,6 +25,22 @@ describe('login', () => {
|
|||||||
await expect(exitCodePromise).resolves.toEqual(0);
|
await expect(exitCodePromise).resolves.toEqual(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('northstar', () => {
|
||||||
|
it('should set currentTeam to defaultTeamId', async () => {
|
||||||
|
const user = useUser({
|
||||||
|
version: 'northstar',
|
||||||
|
defaultTeamId: 'northstar-defaultTeamId',
|
||||||
|
});
|
||||||
|
client.authConfig.token = undefined;
|
||||||
|
client.setArgv('login', user.email);
|
||||||
|
const exitCodePromise = login(client);
|
||||||
|
await expect(exitCodePromise).resolves.toEqual(0);
|
||||||
|
await expect(client.config.currentTeam).toEqual(
|
||||||
|
'northstar-defaultTeamId'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('interactive', () => {
|
describe('interactive', () => {
|
||||||
it('should allow login via email', async () => {
|
it('should allow login via email', async () => {
|
||||||
const user = useUser();
|
const user = useUser();
|
||||||
|
|||||||
81
packages/cli/test/unit/commands/switch.test.ts
Normal file
81
packages/cli/test/unit/commands/switch.test.ts
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
import { client } from '../../mocks/client';
|
||||||
|
import teamsSwitch from '../../../src/commands/teams/switch';
|
||||||
|
import { useUser } from '../../mocks/user';
|
||||||
|
import { useTeams } from '../../mocks/team';
|
||||||
|
|
||||||
|
describe('switch', () => {
|
||||||
|
describe('non-northstar', () => {
|
||||||
|
it('should let you switch to team and back', async () => {
|
||||||
|
const user = useUser();
|
||||||
|
const team = useTeams()[0];
|
||||||
|
|
||||||
|
// ? Switch to:
|
||||||
|
// ── Personal Account ──────────────
|
||||||
|
// ● Name (username) (current)
|
||||||
|
// ── Teams ─────────────────────────
|
||||||
|
// ○ Team (slug)
|
||||||
|
// ──────────────────────────────────
|
||||||
|
// ○ Cancel
|
||||||
|
let exitCodePromise = teamsSwitch(client);
|
||||||
|
await expect(client.stderr).toOutput('Switch to:');
|
||||||
|
client.stdin.write('\x1B[B'); // Down arrow
|
||||||
|
client.stdin.write('\r'); // Return key
|
||||||
|
await expect(exitCodePromise).resolves.toEqual(0);
|
||||||
|
await expect(client.stderr).toOutput(
|
||||||
|
`Success! The team ${team.name} (${team.slug}) is now active!`
|
||||||
|
);
|
||||||
|
|
||||||
|
// ? Switch to:
|
||||||
|
// ── Personal Account ──────────────
|
||||||
|
// ○ Name (username)
|
||||||
|
// ── Teams ─────────────────────────
|
||||||
|
// ● Team (slug) (current)
|
||||||
|
// ──────────────────────────────────
|
||||||
|
// ○ Cancel
|
||||||
|
exitCodePromise = teamsSwitch(client);
|
||||||
|
await expect(client.stderr).toOutput('Switch to:');
|
||||||
|
client.stdin.write('\x1B[A'); // Up arrow
|
||||||
|
client.stdin.write('\r'); // Return key
|
||||||
|
await expect(exitCodePromise).resolves.toEqual(0);
|
||||||
|
await expect(client.stderr).toOutput(
|
||||||
|
`Your account (${user.username}) is now active!`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('northstar', () => {
|
||||||
|
it('should not let you switch to personal account', async () => {
|
||||||
|
const user = useUser({
|
||||||
|
version: 'northstar',
|
||||||
|
});
|
||||||
|
const team = useTeams()[0];
|
||||||
|
client.config.currentTeam = team.id;
|
||||||
|
|
||||||
|
// ? Switch to:
|
||||||
|
// ── Teams ─────────────────────────
|
||||||
|
// ● Team (slug) (current)
|
||||||
|
// ──────────────────────────────────
|
||||||
|
// ○ Cancel
|
||||||
|
const exitCodePromise = teamsSwitch(client);
|
||||||
|
// Test that personal account is not displayed in scope switcher
|
||||||
|
await expect(client.stderr).not.toOutput(user.username);
|
||||||
|
client.stdin.write('\r'); // Return key
|
||||||
|
await expect(exitCodePromise).resolves.toEqual(0);
|
||||||
|
await expect(client.stderr).toOutput('No changes made');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not let you switch to personal account if desiredSlug is set as personal account', async () => {
|
||||||
|
const user = useUser({
|
||||||
|
version: 'northstar',
|
||||||
|
});
|
||||||
|
useTeams();
|
||||||
|
|
||||||
|
const exitCodePromise = teamsSwitch(client, user.username);
|
||||||
|
// Personal account should be hidden
|
||||||
|
await expect(client.stderr).toOutput(
|
||||||
|
'You cannot set your Personal Account as the scope.'
|
||||||
|
);
|
||||||
|
await expect(exitCodePromise).resolves.toEqual(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
30
packages/cli/test/unit/commands/teams.test.ts
Normal file
30
packages/cli/test/unit/commands/teams.test.ts
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import { client } from '../../mocks/client';
|
||||||
|
import teamsList from '../../../src/commands/teams/list';
|
||||||
|
import { useUser } from '../../mocks/user';
|
||||||
|
import { useTeams } from '../../mocks/team';
|
||||||
|
|
||||||
|
describe('teams', () => {
|
||||||
|
describe('ls', () => {
|
||||||
|
describe('non-northstar', () => {
|
||||||
|
it('should display your personal account', async () => {
|
||||||
|
const user = useUser();
|
||||||
|
useTeams(undefined, { apiVersion: 2 });
|
||||||
|
const exitCodePromise = teamsList(client);
|
||||||
|
await expect(client.stdout).toOutput(user.username);
|
||||||
|
await expect(exitCodePromise).resolves.toEqual(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('northstar', () => {
|
||||||
|
it('should not display your personal account', async () => {
|
||||||
|
const user = useUser({
|
||||||
|
version: 'northstar',
|
||||||
|
});
|
||||||
|
useTeams(undefined, { apiVersion: 2 });
|
||||||
|
const exitCodePromise = teamsList(client);
|
||||||
|
await expect(client.stdout).not.toOutput(user.username);
|
||||||
|
await expect(exitCodePromise).resolves.toEqual(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
68
packages/cli/test/unit/util/get-scope.test.ts
Normal file
68
packages/cli/test/unit/util/get-scope.test.ts
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
import { client } from '../../mocks/client';
|
||||||
|
import { useUser } from '../../mocks/user';
|
||||||
|
import { useTeams } from '../../mocks/team';
|
||||||
|
import getScope from '../../../src/util/get-scope';
|
||||||
|
|
||||||
|
describe('getScope', () => {
|
||||||
|
let mockTeam: ReturnType<typeof useTeams>[0];
|
||||||
|
let mockUser: ReturnType<typeof useUser>;
|
||||||
|
beforeEach(() => {
|
||||||
|
mockTeam = useTeams()[0];
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('non-northstar', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
mockUser = useUser();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return user if team is unspecified', async () => {
|
||||||
|
const { contextName, team, user } = await getScope(client);
|
||||||
|
await expect(user.id).toEqual(mockUser.id);
|
||||||
|
await expect(team).toBeNull();
|
||||||
|
await expect(contextName).toEqual(mockUser.username);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return team if team is specified', async () => {
|
||||||
|
client.config.currentTeam = mockTeam.id;
|
||||||
|
const { contextName, team, user } = await getScope(client);
|
||||||
|
await expect(user.id).toEqual(mockUser.id);
|
||||||
|
await expect(team?.id).toEqual(mockTeam.id);
|
||||||
|
await expect(contextName).toEqual(mockTeam.slug);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not return team if team is specified but getTeam is false', async () => {
|
||||||
|
client.config.currentTeam = mockTeam.id;
|
||||||
|
const { contextName, team, user } = await getScope(client, {
|
||||||
|
getTeam: false,
|
||||||
|
});
|
||||||
|
await expect(user.id).toEqual(mockUser.id);
|
||||||
|
await expect(team).toBeNull();
|
||||||
|
await expect(contextName).toEqual(mockUser.username);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('northstar', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
mockUser = useUser({
|
||||||
|
version: 'northstar',
|
||||||
|
defaultTeamId: mockTeam.id,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return default team', async () => {
|
||||||
|
const { contextName, team, user } = await getScope(client);
|
||||||
|
await expect(user.id).toEqual(mockUser.id);
|
||||||
|
await expect(team?.id).toEqual(mockTeam.id);
|
||||||
|
await expect(contextName).toEqual(mockTeam.slug);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not return default team if getTeam is false', async () => {
|
||||||
|
const { contextName, team, user } = await getScope(client, {
|
||||||
|
getTeam: false,
|
||||||
|
});
|
||||||
|
await expect(user.id).toEqual(mockUser.id);
|
||||||
|
await expect(team).toBeNull();
|
||||||
|
await expect(contextName).toEqual(mockUser.username);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
40
packages/cli/test/unit/util/input/select-org.test.ts
Normal file
40
packages/cli/test/unit/util/input/select-org.test.ts
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import { client } from '../../../mocks/client';
|
||||||
|
import selectOrg from '../../../../src/util/input/select-org';
|
||||||
|
import { useTeams } from '../../../mocks/team';
|
||||||
|
import { useUser } from '../../../mocks/user';
|
||||||
|
|
||||||
|
describe('selectOrg', () => {
|
||||||
|
describe('non-northstar', () => {
|
||||||
|
it('should allow selecting user', async () => {
|
||||||
|
const user = useUser();
|
||||||
|
useTeams();
|
||||||
|
const selectOrgPromise = selectOrg(client, 'Select the scope');
|
||||||
|
await expect(client.stderr).toOutput(user.name);
|
||||||
|
client.stdin.write('\r'); // Return key
|
||||||
|
await expect(selectOrgPromise).resolves.toHaveProperty('id', user.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should allow selecting team', async () => {
|
||||||
|
useUser();
|
||||||
|
const team = useTeams()[0];
|
||||||
|
const selectOrgPromise = selectOrg(client, 'Select the scope');
|
||||||
|
await expect(client.stderr).toOutput('Select the scope');
|
||||||
|
client.stdin.write('\x1B[B'); // Down arrow
|
||||||
|
client.stdin.write('\r'); // Return key
|
||||||
|
await expect(selectOrgPromise).resolves.toHaveProperty('id', team.id);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('northstar', () => {
|
||||||
|
it('should not allow selecting user', async () => {
|
||||||
|
const user = useUser({
|
||||||
|
version: 'northstar',
|
||||||
|
});
|
||||||
|
const team = useTeams()[0];
|
||||||
|
const selectOrgPromise = selectOrg(client, 'Select the scope');
|
||||||
|
await expect(client.stderr).not.toOutput(user.name);
|
||||||
|
client.stdin.write('\r'); // Return key
|
||||||
|
await expect(selectOrgPromise).resolves.toHaveProperty('id', team.id);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
import { client } from '../../../mocks/client';
|
||||||
|
import { useUser } from '../../../mocks/user';
|
||||||
|
import { updateCurrentTeamAfterLogin } from '../../../../src/util/login/update-current-team-after-login';
|
||||||
|
|
||||||
|
describe('updateCurrentTeamAfterLogin', () => {
|
||||||
|
describe('SSO Login', () => {
|
||||||
|
it('should set currentTeam to SSO team ID', async () => {
|
||||||
|
useUser();
|
||||||
|
await updateCurrentTeamAfterLogin(client, client.output, 'ssoTeamId');
|
||||||
|
await expect(client.config.currentTeam).toEqual('ssoTeamId');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('northstar', () => {
|
||||||
|
it('should set currentTeam to defaultTeamId', async () => {
|
||||||
|
useUser({
|
||||||
|
version: 'northstar',
|
||||||
|
defaultTeamId: 'defaultTeamId',
|
||||||
|
});
|
||||||
|
await updateCurrentTeamAfterLogin(client, client.output);
|
||||||
|
await expect(client.config.currentTeam).toEqual('defaultTeamId');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('non-northstar', () => {
|
||||||
|
it('should reset currentTeam', async () => {
|
||||||
|
client.config.currentTeam = 'previousTeamId';
|
||||||
|
useUser();
|
||||||
|
await updateCurrentTeamAfterLogin(client, client.output);
|
||||||
|
await expect(client.config.currentTeam).toBeUndefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1,5 +1,19 @@
|
|||||||
# @vercel/client
|
# @vercel/client
|
||||||
|
|
||||||
|
## 13.0.4
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [[`decdf27fb`](https://github.com/vercel/vercel/commit/decdf27fb5ca914fe50a9320c4fd50ef79d2fbb3)]:
|
||||||
|
- @vercel/build-utils@7.2.1
|
||||||
|
|
||||||
|
## 13.0.3
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [[`50e04dd85`](https://github.com/vercel/vercel/commit/50e04dd8584664c842a86c15d92d654f4ea8dcbb), [`45b73c7e8`](https://github.com/vercel/vercel/commit/45b73c7e86458564dc0bab007f6f6365c4c4ab5d), [`d8bc570f6`](https://github.com/vercel/vercel/commit/d8bc570f604950d97156d4f33c8accecf3b3b28f)]:
|
||||||
|
- @vercel/build-utils@7.2.0
|
||||||
|
|
||||||
## 13.0.2
|
## 13.0.2
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@vercel/client",
|
"name": "@vercel/client",
|
||||||
"version": "13.0.2",
|
"version": "13.0.4",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"typings": "dist/index.d.ts",
|
"typings": "dist/index.d.ts",
|
||||||
"homepage": "https://vercel.com",
|
"homepage": "https://vercel.com",
|
||||||
@@ -36,7 +36,7 @@
|
|||||||
"typescript": "4.9.5"
|
"typescript": "4.9.5"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vercel/build-utils": "7.1.1",
|
"@vercel/build-utils": "7.2.1",
|
||||||
"@vercel/routing-utils": "3.0.0",
|
"@vercel/routing-utils": "3.0.0",
|
||||||
"@zeit/fetch": "5.2.0",
|
"@zeit/fetch": "5.2.0",
|
||||||
"async-retry": "1.2.3",
|
"async-retry": "1.2.3",
|
||||||
|
|||||||
@@ -1,5 +1,23 @@
|
|||||||
# @vercel/edge
|
# @vercel/edge
|
||||||
|
|
||||||
|
## 1.1.0
|
||||||
|
|
||||||
|
### Minor Changes
|
||||||
|
|
||||||
|
- Add flag to geolocation ([#10443](https://github.com/vercel/vercel/pull/10443))
|
||||||
|
|
||||||
|
Usage
|
||||||
|
|
||||||
|
```
|
||||||
|
const { flag } = geolocation(req)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 1.0.2
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- [node] upgrade edge-runtime ([#10451](https://github.com/vercel/vercel/pull/10451))
|
||||||
|
|
||||||
## 1.0.1
|
## 1.0.1
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
- [CITY_HEADER_NAME](README.md#city_header_name)
|
- [CITY_HEADER_NAME](README.md#city_header_name)
|
||||||
- [COUNTRY_HEADER_NAME](README.md#country_header_name)
|
- [COUNTRY_HEADER_NAME](README.md#country_header_name)
|
||||||
|
- [EMOJI_FLAG_UNICODE_STARTING_POSITION](README.md#emoji_flag_unicode_starting_position)
|
||||||
- [IP_HEADER_NAME](README.md#ip_header_name)
|
- [IP_HEADER_NAME](README.md#ip_header_name)
|
||||||
- [LATITUDE_HEADER_NAME](README.md#latitude_header_name)
|
- [LATITUDE_HEADER_NAME](README.md#latitude_header_name)
|
||||||
- [LONGITUDE_HEADER_NAME](README.md#longitude_header_name)
|
- [LONGITUDE_HEADER_NAME](README.md#longitude_header_name)
|
||||||
@@ -53,6 +54,18 @@ Country of the original client IP as calculated by Vercel Proxy.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
### EMOJI_FLAG_UNICODE_STARTING_POSITION
|
||||||
|
|
||||||
|
• `Const` **EMOJI_FLAG_UNICODE_STARTING_POSITION**: `127397`
|
||||||
|
|
||||||
|
Unicode characters for emoji flags start at this number, and run up to 127469.
|
||||||
|
|
||||||
|
#### Defined in
|
||||||
|
|
||||||
|
[packages/edge/src/edge-headers.ts:34](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L34)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### IP_HEADER_NAME
|
### IP_HEADER_NAME
|
||||||
|
|
||||||
• `Const` **IP_HEADER_NAME**: `"x-real-ip"`
|
• `Const` **IP_HEADER_NAME**: `"x-real-ip"`
|
||||||
@@ -141,7 +154,7 @@ Returns the location information for the incoming request.
|
|||||||
|
|
||||||
#### Defined in
|
#### Defined in
|
||||||
|
|
||||||
[packages/edge/src/edge-headers.ts:106](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L106)
|
[packages/edge/src/edge-headers.ts:128](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L128)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -167,7 +180,7 @@ Returns the IP address of the request from the headers.
|
|||||||
|
|
||||||
#### Defined in
|
#### Defined in
|
||||||
|
|
||||||
[packages/edge/src/edge-headers.ts:77](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L77)
|
[packages/edge/src/edge-headers.ts:99](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L99)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ The location information of a given request.
|
|||||||
- [city](Geo.md#city)
|
- [city](Geo.md#city)
|
||||||
- [country](Geo.md#country)
|
- [country](Geo.md#country)
|
||||||
- [countryRegion](Geo.md#countryregion)
|
- [countryRegion](Geo.md#countryregion)
|
||||||
|
- [flag](Geo.md#flag)
|
||||||
- [latitude](Geo.md#latitude)
|
- [latitude](Geo.md#latitude)
|
||||||
- [longitude](Geo.md#longitude)
|
- [longitude](Geo.md#longitude)
|
||||||
- [region](Geo.md#region)
|
- [region](Geo.md#region)
|
||||||
@@ -23,7 +24,7 @@ The city that the request originated from.
|
|||||||
|
|
||||||
#### Defined in
|
#### Defined in
|
||||||
|
|
||||||
[packages/edge/src/edge-headers.ts:47](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L47)
|
[packages/edge/src/edge-headers.ts:50](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L50)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -35,7 +36,7 @@ The country that the request originated from.
|
|||||||
|
|
||||||
#### Defined in
|
#### Defined in
|
||||||
|
|
||||||
[packages/edge/src/edge-headers.ts:50](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L50)
|
[packages/edge/src/edge-headers.ts:53](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L53)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -48,7 +49,19 @@ See [docs](https://vercel.com/docs/concepts/edge-network/headers#x-vercel-ip-cou
|
|||||||
|
|
||||||
#### Defined in
|
#### Defined in
|
||||||
|
|
||||||
[packages/edge/src/edge-headers.ts:58](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L58)
|
[packages/edge/src/edge-headers.ts:64](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L64)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### flag
|
||||||
|
|
||||||
|
• `Optional` **flag**: `string`
|
||||||
|
|
||||||
|
The flag emoji for the country the request originated from.
|
||||||
|
|
||||||
|
#### Defined in
|
||||||
|
|
||||||
|
[packages/edge/src/edge-headers.ts:56](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L56)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -60,7 +73,7 @@ The latitude of the client.
|
|||||||
|
|
||||||
#### Defined in
|
#### Defined in
|
||||||
|
|
||||||
[packages/edge/src/edge-headers.ts:61](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L61)
|
[packages/edge/src/edge-headers.ts:67](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L67)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -72,7 +85,7 @@ The longitude of the client.
|
|||||||
|
|
||||||
#### Defined in
|
#### Defined in
|
||||||
|
|
||||||
[packages/edge/src/edge-headers.ts:64](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L64)
|
[packages/edge/src/edge-headers.ts:70](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L70)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -84,4 +97,4 @@ The [Vercel Edge Network region](https://vercel.com/docs/concepts/edge-network/r
|
|||||||
|
|
||||||
#### Defined in
|
#### Defined in
|
||||||
|
|
||||||
[packages/edge/src/edge-headers.ts:53](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L53)
|
[packages/edge/src/edge-headers.ts:59](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L59)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@vercel/edge",
|
"name": "@vercel/edge",
|
||||||
"version": "1.0.1",
|
"version": "1.1.0",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"module": "dist/index.mjs",
|
"module": "dist/index.mjs",
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
"build:docs": "typedoc && node scripts/fix-links.js && prettier --write docs/**/*.md docs/*.md"
|
"build:docs": "typedoc && node scripts/fix-links.js && prettier --write docs/**/*.md docs/*.md"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@edge-runtime/jest-environment": "2.3.0",
|
"@edge-runtime/jest-environment": "2.3.1",
|
||||||
"@types/jest": "27.4.1",
|
"@types/jest": "27.4.1",
|
||||||
"jest-junit": "16.0.0",
|
"jest-junit": "16.0.0",
|
||||||
"ts-node": "8.9.1",
|
"ts-node": "8.9.1",
|
||||||
|
|||||||
@@ -28,7 +28,10 @@ export const REGION_HEADER_NAME = 'x-vercel-ip-country-region';
|
|||||||
* The request ID for each request generated by Vercel Proxy.
|
* The request ID for each request generated by Vercel Proxy.
|
||||||
*/
|
*/
|
||||||
export const REQUEST_ID_HEADER_NAME = 'x-vercel-id';
|
export const REQUEST_ID_HEADER_NAME = 'x-vercel-id';
|
||||||
|
/**
|
||||||
|
* Unicode characters for emoji flags start at this number, and run up to 127469.
|
||||||
|
*/
|
||||||
|
export const EMOJI_FLAG_UNICODE_STARTING_POSITION = 127397;
|
||||||
/**
|
/**
|
||||||
* We define a new type so this function can be reused with
|
* We define a new type so this function can be reused with
|
||||||
* the global `Request`, `node-fetch` and other types.
|
* the global `Request`, `node-fetch` and other types.
|
||||||
@@ -49,6 +52,9 @@ export interface Geo {
|
|||||||
/** The country that the request originated from. */
|
/** The country that the request originated from. */
|
||||||
country?: string;
|
country?: string;
|
||||||
|
|
||||||
|
/** The flag emoji for the country the request originated from. */
|
||||||
|
flag?: string;
|
||||||
|
|
||||||
/** The [Vercel Edge Network region](https://vercel.com/docs/concepts/edge-network/regions) that received the request. */
|
/** The [Vercel Edge Network region](https://vercel.com/docs/concepts/edge-network/regions) that received the request. */
|
||||||
region?: string;
|
region?: string;
|
||||||
|
|
||||||
@@ -68,6 +74,22 @@ function getHeader(request: Request, key: string): string | undefined {
|
|||||||
return request.headers.get(key) ?? undefined;
|
return request.headers.get(key) ?? undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the 2 digit countryCode into a flag emoji by adding the current character value to the emoji flag unicode starting position. See [Country Code to Flag Emoji](https://dev.to/jorik/country-code-to-flag-emoji-a21) by Jorik Tangelder.
|
||||||
|
*
|
||||||
|
* @param countryCode The country code returned by: `getHeader(request, COUNTRY_HEADER_NAME)`.
|
||||||
|
* @returns A flag emoji or undefined.
|
||||||
|
*/
|
||||||
|
function getFlag(countryCode: string | undefined): string | undefined {
|
||||||
|
const regex = new RegExp('^[A-Z]{2}$').test(countryCode!);
|
||||||
|
if (!countryCode || !regex) return undefined;
|
||||||
|
return String.fromCodePoint(
|
||||||
|
...countryCode
|
||||||
|
.split('')
|
||||||
|
.map(char => EMOJI_FLAG_UNICODE_STARTING_POSITION + char.charCodeAt(0))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the IP address of the request from the headers.
|
* Returns the IP address of the request from the headers.
|
||||||
*
|
*
|
||||||
@@ -107,6 +129,7 @@ export function geolocation(request: Request): Geo {
|
|||||||
return {
|
return {
|
||||||
city: getHeader(request, CITY_HEADER_NAME),
|
city: getHeader(request, CITY_HEADER_NAME),
|
||||||
country: getHeader(request, COUNTRY_HEADER_NAME),
|
country: getHeader(request, COUNTRY_HEADER_NAME),
|
||||||
|
flag: getFlag(getHeader(request, COUNTRY_HEADER_NAME)),
|
||||||
countryRegion: getHeader(request, REGION_HEADER_NAME),
|
countryRegion: getHeader(request, REGION_HEADER_NAME),
|
||||||
region: getRegionFromRequestId(getHeader(request, REQUEST_ID_HEADER_NAME)),
|
region: getRegionFromRequestId(getHeader(request, REQUEST_ID_HEADER_NAME)),
|
||||||
latitude: getHeader(request, LATITUDE_HEADER_NAME),
|
latitude: getHeader(request, LATITUDE_HEADER_NAME),
|
||||||
|
|||||||
37
packages/edge/test/edge-headers.test.ts
vendored
37
packages/edge/test/edge-headers.test.ts
vendored
@@ -29,6 +29,7 @@ describe('`geolocation`', () => {
|
|||||||
const req = new Request('https://example.vercel.sh');
|
const req = new Request('https://example.vercel.sh');
|
||||||
expect(geolocation(req)).toEqual({
|
expect(geolocation(req)).toEqual({
|
||||||
city: undefined,
|
city: undefined,
|
||||||
|
flag: undefined,
|
||||||
country: undefined,
|
country: undefined,
|
||||||
countryRegion: undefined,
|
countryRegion: undefined,
|
||||||
latitude: undefined,
|
latitude: undefined,
|
||||||
@@ -41,7 +42,7 @@ describe('`geolocation`', () => {
|
|||||||
const req = new Request('https://example.vercel.sh', {
|
const req = new Request('https://example.vercel.sh', {
|
||||||
headers: {
|
headers: {
|
||||||
[CITY_HEADER_NAME]: 'Tel Aviv',
|
[CITY_HEADER_NAME]: 'Tel Aviv',
|
||||||
[COUNTRY_HEADER_NAME]: 'Israel',
|
[COUNTRY_HEADER_NAME]: 'IL',
|
||||||
[LATITUDE_HEADER_NAME]: '32.109333',
|
[LATITUDE_HEADER_NAME]: '32.109333',
|
||||||
[LONGITUDE_HEADER_NAME]: '34.855499',
|
[LONGITUDE_HEADER_NAME]: '34.855499',
|
||||||
[REGION_HEADER_NAME]: 'TA', // https://en.wikipedia.org/wiki/ISO_3166-2:IL
|
[REGION_HEADER_NAME]: 'TA', // https://en.wikipedia.org/wiki/ISO_3166-2:IL
|
||||||
@@ -50,7 +51,8 @@ describe('`geolocation`', () => {
|
|||||||
});
|
});
|
||||||
expect(geolocation(req)).toEqual<Geo>({
|
expect(geolocation(req)).toEqual<Geo>({
|
||||||
city: 'Tel Aviv',
|
city: 'Tel Aviv',
|
||||||
country: 'Israel',
|
flag: '🇮🇱',
|
||||||
|
country: 'IL',
|
||||||
latitude: '32.109333',
|
latitude: '32.109333',
|
||||||
longitude: '34.855499',
|
longitude: '34.855499',
|
||||||
region: 'fra1',
|
region: 'fra1',
|
||||||
@@ -62,7 +64,7 @@ describe('`geolocation`', () => {
|
|||||||
const req = new Request('https://example.vercel.sh', {
|
const req = new Request('https://example.vercel.sh', {
|
||||||
headers: {
|
headers: {
|
||||||
[CITY_HEADER_NAME]: 'Tokyo',
|
[CITY_HEADER_NAME]: 'Tokyo',
|
||||||
[COUNTRY_HEADER_NAME]: 'Japan',
|
[COUNTRY_HEADER_NAME]: 'JP',
|
||||||
[LATITUDE_HEADER_NAME]: '37.1233',
|
[LATITUDE_HEADER_NAME]: '37.1233',
|
||||||
[LONGITUDE_HEADER_NAME]: '30.733399',
|
[LONGITUDE_HEADER_NAME]: '30.733399',
|
||||||
[REGION_HEADER_NAME]: '13',
|
[REGION_HEADER_NAME]: '13',
|
||||||
@@ -71,7 +73,8 @@ describe('`geolocation`', () => {
|
|||||||
});
|
});
|
||||||
expect(geolocation(req)).toEqual<Geo>({
|
expect(geolocation(req)).toEqual<Geo>({
|
||||||
city: 'Tokyo',
|
city: 'Tokyo',
|
||||||
country: 'Japan',
|
flag: '🇯🇵',
|
||||||
|
country: 'JP',
|
||||||
latitude: '37.1233',
|
latitude: '37.1233',
|
||||||
longitude: '30.733399',
|
longitude: '30.733399',
|
||||||
region: 'hnd1',
|
region: 'hnd1',
|
||||||
@@ -83,7 +86,7 @@ describe('`geolocation`', () => {
|
|||||||
const req = new Request('https://example.vercel.sh', {
|
const req = new Request('https://example.vercel.sh', {
|
||||||
headers: {
|
headers: {
|
||||||
[CITY_HEADER_NAME]: 'Tokyo',
|
[CITY_HEADER_NAME]: 'Tokyo',
|
||||||
[COUNTRY_HEADER_NAME]: 'Japan',
|
[COUNTRY_HEADER_NAME]: 'JP',
|
||||||
[LATITUDE_HEADER_NAME]: '37.1233',
|
[LATITUDE_HEADER_NAME]: '37.1233',
|
||||||
[LONGITUDE_HEADER_NAME]: '30.733399',
|
[LONGITUDE_HEADER_NAME]: '30.733399',
|
||||||
[REGION_HEADER_NAME]: '13',
|
[REGION_HEADER_NAME]: '13',
|
||||||
@@ -91,7 +94,29 @@ describe('`geolocation`', () => {
|
|||||||
});
|
});
|
||||||
expect(geolocation(req)).toEqual<Geo>({
|
expect(geolocation(req)).toEqual<Geo>({
|
||||||
city: 'Tokyo',
|
city: 'Tokyo',
|
||||||
country: 'Japan',
|
flag: '🇯🇵',
|
||||||
|
country: 'JP',
|
||||||
|
latitude: '37.1233',
|
||||||
|
longitude: '30.733399',
|
||||||
|
region: 'dev1',
|
||||||
|
countryRegion: '13',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('returns undefined if countryCode is invalid', () => {
|
||||||
|
const req = new Request('https://example.vercel.sh', {
|
||||||
|
headers: {
|
||||||
|
[CITY_HEADER_NAME]: 'Tokyo',
|
||||||
|
[COUNTRY_HEADER_NAME]: 'AAA',
|
||||||
|
[LATITUDE_HEADER_NAME]: '37.1233',
|
||||||
|
[LONGITUDE_HEADER_NAME]: '30.733399',
|
||||||
|
[REGION_HEADER_NAME]: '13',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(geolocation(req)).toEqual<Geo>({
|
||||||
|
city: 'Tokyo',
|
||||||
|
flag: undefined,
|
||||||
|
country: 'AAA',
|
||||||
latitude: '37.1233',
|
latitude: '37.1233',
|
||||||
longitude: '30.733399',
|
longitude: '30.733399',
|
||||||
region: 'dev1',
|
region: 'dev1',
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
# @vercel/frameworks
|
# @vercel/frameworks
|
||||||
|
|
||||||
|
## 2.0.2
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Add `bun install` placeholder ([#10492](https://github.com/vercel/vercel/pull/10492))
|
||||||
|
|
||||||
## 2.0.1
|
## 2.0.1
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@vercel/frameworks",
|
"name": "@vercel/frameworks",
|
||||||
"version": "2.0.1",
|
"version": "2.0.2",
|
||||||
"main": "./dist/frameworks.js",
|
"main": "./dist/frameworks.js",
|
||||||
"types": "./dist/frameworks.d.ts",
|
"types": "./dist/frameworks.d.ts",
|
||||||
"files": [
|
"files": [
|
||||||
|
|||||||
@@ -42,7 +42,8 @@ export const frameworks = [
|
|||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
installCommand: {
|
installCommand: {
|
||||||
placeholder: '`yarn install`, `pnpm install`, or `npm install`',
|
placeholder:
|
||||||
|
'`yarn install`, `pnpm install`, `npm install`, or `bun install`',
|
||||||
},
|
},
|
||||||
buildCommand: {
|
buildCommand: {
|
||||||
placeholder: '`npm run build` or `blitz build`',
|
placeholder: '`npm run build` or `blitz build`',
|
||||||
@@ -82,7 +83,8 @@ export const frameworks = [
|
|||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
installCommand: {
|
installCommand: {
|
||||||
placeholder: '`yarn install`, `pnpm install`, or `npm install`',
|
placeholder:
|
||||||
|
'`yarn install`, `pnpm install`, `npm install`, or `bun install`',
|
||||||
},
|
},
|
||||||
buildCommand: {
|
buildCommand: {
|
||||||
placeholder: '`npm run build` or `next build`',
|
placeholder: '`npm run build` or `next build`',
|
||||||
@@ -125,7 +127,8 @@ export const frameworks = [
|
|||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
installCommand: {
|
installCommand: {
|
||||||
placeholder: '`yarn install`, `pnpm install`, or `npm install`',
|
placeholder:
|
||||||
|
'`yarn install`, `pnpm install`, `npm install`, or `bun install`',
|
||||||
},
|
},
|
||||||
buildCommand: {
|
buildCommand: {
|
||||||
placeholder: '`npm run build` or `gatsby build`',
|
placeholder: '`npm run build` or `gatsby build`',
|
||||||
@@ -214,7 +217,8 @@ export const frameworks = [
|
|||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
installCommand: {
|
installCommand: {
|
||||||
placeholder: '`yarn install`, `pnpm install`, or `npm install`',
|
placeholder:
|
||||||
|
'`yarn install`, `pnpm install`, `npm install`, or `bun install`',
|
||||||
},
|
},
|
||||||
buildCommand: {
|
buildCommand: {
|
||||||
value: 'remix build',
|
value: 'remix build',
|
||||||
@@ -252,7 +256,8 @@ export const frameworks = [
|
|||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
installCommand: {
|
installCommand: {
|
||||||
placeholder: '`yarn install` or `npm install`',
|
placeholder:
|
||||||
|
'`yarn install`, `pnpm install`, `npm install`, or `bun install`',
|
||||||
},
|
},
|
||||||
buildCommand: {
|
buildCommand: {
|
||||||
value: 'astro build',
|
value: 'astro build',
|
||||||
@@ -299,7 +304,8 @@ export const frameworks = [
|
|||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
installCommand: {
|
installCommand: {
|
||||||
placeholder: '`yarn install`, `pnpm install`, or `npm install`',
|
placeholder:
|
||||||
|
'`yarn install`, `pnpm install`, `npm install`, or `bun install`',
|
||||||
},
|
},
|
||||||
buildCommand: {
|
buildCommand: {
|
||||||
placeholder: '`npm run build` or `hexo generate`',
|
placeholder: '`npm run build` or `hexo generate`',
|
||||||
@@ -334,7 +340,8 @@ export const frameworks = [
|
|||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
installCommand: {
|
installCommand: {
|
||||||
placeholder: '`yarn install`, `pnpm install`, or `npm install`',
|
placeholder:
|
||||||
|
'`yarn install`, `pnpm install`, `npm install`, or `bun install`',
|
||||||
},
|
},
|
||||||
buildCommand: {
|
buildCommand: {
|
||||||
placeholder: '`npm run build` or `npx @11ty/eleventy`',
|
placeholder: '`npm run build` or `npx @11ty/eleventy`',
|
||||||
@@ -371,7 +378,8 @@ export const frameworks = [
|
|||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
installCommand: {
|
installCommand: {
|
||||||
placeholder: '`yarn install`, `pnpm install`, or `npm install`',
|
placeholder:
|
||||||
|
'`yarn install`, `pnpm install`, `npm install`, or `bun install`',
|
||||||
},
|
},
|
||||||
buildCommand: {
|
buildCommand: {
|
||||||
placeholder: '`npm run build` or `docusaurus build`',
|
placeholder: '`npm run build` or `docusaurus build`',
|
||||||
@@ -457,7 +465,8 @@ export const frameworks = [
|
|||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
installCommand: {
|
installCommand: {
|
||||||
placeholder: '`yarn install`, `pnpm install`, or `npm install`',
|
placeholder:
|
||||||
|
'`yarn install`, `pnpm install`, `npm install`, or `bun install`',
|
||||||
},
|
},
|
||||||
buildCommand: {
|
buildCommand: {
|
||||||
placeholder: '`npm run build` or `docusaurus-build`',
|
placeholder: '`npm run build` or `docusaurus-build`',
|
||||||
@@ -508,7 +517,8 @@ export const frameworks = [
|
|||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
installCommand: {
|
installCommand: {
|
||||||
placeholder: '`yarn install`, `pnpm install`, or `npm install`',
|
placeholder:
|
||||||
|
'`yarn install`, `pnpm install`, `npm install`, or `bun install`',
|
||||||
},
|
},
|
||||||
buildCommand: {
|
buildCommand: {
|
||||||
placeholder: '`npm run build` or `preact build`',
|
placeholder: '`npm run build` or `preact build`',
|
||||||
@@ -555,7 +565,8 @@ export const frameworks = [
|
|||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
installCommand: {
|
installCommand: {
|
||||||
placeholder: '`yarn install`, `pnpm install`, or `npm install`',
|
placeholder:
|
||||||
|
'`yarn install`, `pnpm install`, `npm install`, or `bun install`',
|
||||||
},
|
},
|
||||||
buildCommand: {
|
buildCommand: {
|
||||||
placeholder: '`npm run build` or `solid-start build`',
|
placeholder: '`npm run build` or `solid-start build`',
|
||||||
@@ -591,7 +602,8 @@ export const frameworks = [
|
|||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
installCommand: {
|
installCommand: {
|
||||||
placeholder: '`yarn install`, `pnpm install`, or `npm install`',
|
placeholder:
|
||||||
|
'`yarn install`, `pnpm install`, `npm install`, or `bun install`',
|
||||||
},
|
},
|
||||||
buildCommand: {
|
buildCommand: {
|
||||||
placeholder: '`npm run build` or `dojo build`',
|
placeholder: '`npm run build` or `dojo build`',
|
||||||
@@ -651,7 +663,8 @@ export const frameworks = [
|
|||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
installCommand: {
|
installCommand: {
|
||||||
placeholder: '`yarn install`, `pnpm install`, or `npm install`',
|
placeholder:
|
||||||
|
'`yarn install`, `pnpm install`, `npm install`, or `bun install`',
|
||||||
},
|
},
|
||||||
buildCommand: {
|
buildCommand: {
|
||||||
placeholder: '`npm run build` or `ember build`',
|
placeholder: '`npm run build` or `ember build`',
|
||||||
@@ -696,7 +709,8 @@ export const frameworks = [
|
|||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
installCommand: {
|
installCommand: {
|
||||||
placeholder: '`yarn install`, `pnpm install`, or `npm install`',
|
placeholder:
|
||||||
|
'`yarn install`, `pnpm install`, `npm install`, or `bun install`',
|
||||||
},
|
},
|
||||||
buildCommand: {
|
buildCommand: {
|
||||||
placeholder: '`npm run build` or `vue-cli-service build`',
|
placeholder: '`npm run build` or `vue-cli-service build`',
|
||||||
@@ -749,7 +763,8 @@ export const frameworks = [
|
|||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
installCommand: {
|
installCommand: {
|
||||||
placeholder: '`yarn install`, `pnpm install`, or `npm install`',
|
placeholder:
|
||||||
|
'`yarn install`, `pnpm install`, `npm install`, or `bun install`',
|
||||||
},
|
},
|
||||||
buildCommand: {
|
buildCommand: {
|
||||||
placeholder: '`npm run build` or `ng build && scully`',
|
placeholder: '`npm run build` or `ng build && scully`',
|
||||||
@@ -784,7 +799,8 @@ export const frameworks = [
|
|||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
installCommand: {
|
installCommand: {
|
||||||
placeholder: '`yarn install`, `pnpm install`, or `npm install`',
|
placeholder:
|
||||||
|
'`yarn install`, `pnpm install`, `npm install`, or `bun install`',
|
||||||
},
|
},
|
||||||
buildCommand: {
|
buildCommand: {
|
||||||
placeholder: '`npm run build` or `ng build`',
|
placeholder: '`npm run build` or `ng build`',
|
||||||
@@ -827,7 +843,8 @@ export const frameworks = [
|
|||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
installCommand: {
|
installCommand: {
|
||||||
placeholder: '`yarn install`, `pnpm install`, or `npm install`',
|
placeholder:
|
||||||
|
'`yarn install`, `pnpm install`, `npm install`, or `bun install`',
|
||||||
},
|
},
|
||||||
buildCommand: {
|
buildCommand: {
|
||||||
placeholder: '`npm run build` or `ng build`',
|
placeholder: '`npm run build` or `ng build`',
|
||||||
@@ -885,7 +902,8 @@ export const frameworks = [
|
|||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
installCommand: {
|
installCommand: {
|
||||||
placeholder: '`yarn install`, `pnpm install`, or `npm install`',
|
placeholder:
|
||||||
|
'`yarn install`, `pnpm install`, `npm install`, or `bun install`',
|
||||||
},
|
},
|
||||||
buildCommand: {
|
buildCommand: {
|
||||||
placeholder: '`npm run build` or `polymer build`',
|
placeholder: '`npm run build` or `polymer build`',
|
||||||
@@ -944,7 +962,8 @@ export const frameworks = [
|
|||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
installCommand: {
|
installCommand: {
|
||||||
placeholder: '`yarn install`, `pnpm install`, or `npm install`',
|
placeholder:
|
||||||
|
'`yarn install`, `pnpm install`, `npm install`, or `bun install`',
|
||||||
},
|
},
|
||||||
buildCommand: {
|
buildCommand: {
|
||||||
placeholder: '`npm run build` or `rollup -c`',
|
placeholder: '`npm run build` or `rollup -c`',
|
||||||
@@ -994,7 +1013,8 @@ export const frameworks = [
|
|||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
installCommand: {
|
installCommand: {
|
||||||
placeholder: '`yarn install`, `pnpm install`, or `npm install`',
|
placeholder:
|
||||||
|
'`yarn install`, `pnpm install`, `npm install`, or `bun install`',
|
||||||
},
|
},
|
||||||
buildCommand: {
|
buildCommand: {
|
||||||
placeholder: '`npm run build` or `svelte-kit build`',
|
placeholder: '`npm run build` or `svelte-kit build`',
|
||||||
@@ -1032,7 +1052,8 @@ export const frameworks = [
|
|||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
installCommand: {
|
installCommand: {
|
||||||
placeholder: '`yarn install`, `pnpm install`, or `npm install`',
|
placeholder:
|
||||||
|
'`yarn install`, `pnpm install`, `npm install`, or `bun install`',
|
||||||
},
|
},
|
||||||
buildCommand: {
|
buildCommand: {
|
||||||
placeholder: 'vite build',
|
placeholder: 'vite build',
|
||||||
@@ -1066,7 +1087,8 @@ export const frameworks = [
|
|||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
installCommand: {
|
installCommand: {
|
||||||
placeholder: '`yarn install`, `pnpm install`, or `npm install`',
|
placeholder:
|
||||||
|
'`yarn install`, `pnpm install`, `npm install`, or `bun install`',
|
||||||
},
|
},
|
||||||
buildCommand: {
|
buildCommand: {
|
||||||
placeholder: '`npm run build` or `react-scripts build`',
|
placeholder: '`npm run build` or `react-scripts build`',
|
||||||
@@ -1129,7 +1151,8 @@ export const frameworks = [
|
|||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
installCommand: {
|
installCommand: {
|
||||||
placeholder: '`yarn install`, `pnpm install`, or `npm install`',
|
placeholder:
|
||||||
|
'`yarn install`, `pnpm install`, `npm install`, or `bun install`',
|
||||||
},
|
},
|
||||||
buildCommand: {
|
buildCommand: {
|
||||||
placeholder: '`npm run build` or `react-scripts build`',
|
placeholder: '`npm run build` or `react-scripts build`',
|
||||||
@@ -1188,7 +1211,8 @@ export const frameworks = [
|
|||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
installCommand: {
|
installCommand: {
|
||||||
placeholder: '`yarn install`, `pnpm install`, or `npm install`',
|
placeholder:
|
||||||
|
'`yarn install`, `pnpm install`, `npm install`, or `bun install`',
|
||||||
},
|
},
|
||||||
buildCommand: {
|
buildCommand: {
|
||||||
placeholder: '`npm run build` or `gridsome build`',
|
placeholder: '`npm run build` or `gridsome build`',
|
||||||
@@ -1223,7 +1247,8 @@ export const frameworks = [
|
|||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
installCommand: {
|
installCommand: {
|
||||||
placeholder: '`yarn install`, `pnpm install`, or `npm install`',
|
placeholder:
|
||||||
|
'`yarn install`, `pnpm install`, `npm install`, or `bun install`',
|
||||||
},
|
},
|
||||||
buildCommand: {
|
buildCommand: {
|
||||||
placeholder: '`npm run build` or `umi build`',
|
placeholder: '`npm run build` or `umi build`',
|
||||||
@@ -1267,7 +1292,8 @@ export const frameworks = [
|
|||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
installCommand: {
|
installCommand: {
|
||||||
placeholder: '`yarn install`, `pnpm install`, or `npm install`',
|
placeholder:
|
||||||
|
'`yarn install`, `pnpm install`, `npm install`, or `bun install`',
|
||||||
},
|
},
|
||||||
buildCommand: {
|
buildCommand: {
|
||||||
placeholder: '`npm run build` or `sapper export`',
|
placeholder: '`npm run build` or `sapper export`',
|
||||||
@@ -1302,7 +1328,8 @@ export const frameworks = [
|
|||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
installCommand: {
|
installCommand: {
|
||||||
placeholder: '`yarn install`, `pnpm install`, or `npm install`',
|
placeholder:
|
||||||
|
'`yarn install`, `pnpm install`, `npm install`, or `bun install`',
|
||||||
},
|
},
|
||||||
buildCommand: {
|
buildCommand: {
|
||||||
placeholder: '`npm run build` or `saber build`',
|
placeholder: '`npm run build` or `saber build`',
|
||||||
@@ -1351,7 +1378,8 @@ export const frameworks = [
|
|||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
installCommand: {
|
installCommand: {
|
||||||
placeholder: '`yarn install`, `pnpm install`, or `npm install`',
|
placeholder:
|
||||||
|
'`yarn install`, `pnpm install`, `npm install`, or `bun install`',
|
||||||
},
|
},
|
||||||
buildCommand: {
|
buildCommand: {
|
||||||
placeholder: '`npm run build` or `stencil build`',
|
placeholder: '`npm run build` or `stencil build`',
|
||||||
@@ -1420,7 +1448,8 @@ export const frameworks = [
|
|||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
installCommand: {
|
installCommand: {
|
||||||
placeholder: '`yarn install`, `pnpm install`, or `npm install`',
|
placeholder:
|
||||||
|
'`yarn install`, `pnpm install`, `npm install`, or `bun install`',
|
||||||
},
|
},
|
||||||
buildCommand: {
|
buildCommand: {
|
||||||
placeholder: '`npm run build` or `nuxt generate`',
|
placeholder: '`npm run build` or `nuxt generate`',
|
||||||
@@ -1476,7 +1505,8 @@ export const frameworks = [
|
|||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
installCommand: {
|
installCommand: {
|
||||||
placeholder: '`yarn install`, `pnpm install`, or `npm install`',
|
placeholder:
|
||||||
|
'`yarn install`, `pnpm install`, `npm install`, or `bun install`',
|
||||||
},
|
},
|
||||||
buildCommand: {
|
buildCommand: {
|
||||||
value: 'yarn rw deploy vercel',
|
value: 'yarn rw deploy vercel',
|
||||||
@@ -1606,7 +1636,8 @@ export const frameworks = [
|
|||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
installCommand: {
|
installCommand: {
|
||||||
placeholder: '`yarn install`, `pnpm install`, or `npm install`',
|
placeholder:
|
||||||
|
'`yarn install`, `pnpm install`, `npm install`, or `bun install`',
|
||||||
},
|
},
|
||||||
buildCommand: {
|
buildCommand: {
|
||||||
placeholder: '`npm run build` or `brunch build --production`',
|
placeholder: '`npm run build` or `brunch build --production`',
|
||||||
@@ -1717,7 +1748,8 @@ export const frameworks = [
|
|||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
installCommand: {
|
installCommand: {
|
||||||
placeholder: '`yarn install`, `pnpm install`, or `npm install`',
|
placeholder:
|
||||||
|
'`yarn install`, `pnpm install`, `npm install`, or `bun install`',
|
||||||
},
|
},
|
||||||
buildCommand: {
|
buildCommand: {
|
||||||
value: 'shopify hydrogen build',
|
value: 'shopify hydrogen build',
|
||||||
@@ -1753,7 +1785,8 @@ export const frameworks = [
|
|||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
installCommand: {
|
installCommand: {
|
||||||
placeholder: '`yarn install`, `pnpm install`, or `npm install`',
|
placeholder:
|
||||||
|
'`yarn install`, `pnpm install`, `npm install`, or `bun install`',
|
||||||
},
|
},
|
||||||
buildCommand: {
|
buildCommand: {
|
||||||
placeholder: '`npm run build` or `vite build`',
|
placeholder: '`npm run build` or `vite build`',
|
||||||
@@ -1787,7 +1820,8 @@ export const frameworks = [
|
|||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
installCommand: {
|
installCommand: {
|
||||||
placeholder: '`yarn install`, `pnpm install`, or `npm install`',
|
placeholder:
|
||||||
|
'`yarn install`, `pnpm install`, `npm install`, or `bun install`',
|
||||||
},
|
},
|
||||||
buildCommand: {
|
buildCommand: {
|
||||||
placeholder: '`npm run build` or `vitepress build docs`',
|
placeholder: '`npm run build` or `vitepress build docs`',
|
||||||
@@ -1819,7 +1853,8 @@ export const frameworks = [
|
|||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
installCommand: {
|
installCommand: {
|
||||||
placeholder: '`yarn install`, `pnpm install`, or `npm install`',
|
placeholder:
|
||||||
|
'`yarn install`, `pnpm install`, `npm install`, or `bun install`',
|
||||||
},
|
},
|
||||||
buildCommand: {
|
buildCommand: {
|
||||||
placeholder: '`npm run build` or `vuepress build src`',
|
placeholder: '`npm run build` or `vuepress build src`',
|
||||||
@@ -1852,7 +1887,8 @@ export const frameworks = [
|
|||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
installCommand: {
|
installCommand: {
|
||||||
placeholder: '`yarn install`, `pnpm install`, or `npm install`',
|
placeholder:
|
||||||
|
'`yarn install`, `pnpm install`, `npm install`, or `bun install`',
|
||||||
},
|
},
|
||||||
buildCommand: {
|
buildCommand: {
|
||||||
placeholder: '`npm run build` or `parcel build`',
|
placeholder: '`npm run build` or `parcel build`',
|
||||||
@@ -1909,7 +1945,8 @@ export const frameworks = [
|
|||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
installCommand: {
|
installCommand: {
|
||||||
placeholder: '`yarn install`, `pnpm install`, or `npm install`',
|
placeholder:
|
||||||
|
'`yarn install`, `pnpm install`, `npm install`, or `bun install`',
|
||||||
},
|
},
|
||||||
buildCommand: {
|
buildCommand: {
|
||||||
placeholder: '`npm run build` or `sanity build`',
|
placeholder: '`npm run build` or `sanity build`',
|
||||||
@@ -1953,7 +1990,8 @@ export const frameworks = [
|
|||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
installCommand: {
|
installCommand: {
|
||||||
placeholder: '`yarn install`, `pnpm install`, or `npm install`',
|
placeholder:
|
||||||
|
'`yarn install`, `pnpm install`, `npm install`, or `bun install`',
|
||||||
},
|
},
|
||||||
buildCommand: {
|
buildCommand: {
|
||||||
value: 'storybook build',
|
value: 'storybook build',
|
||||||
@@ -1975,7 +2013,8 @@ export const frameworks = [
|
|||||||
description: 'No framework or an unoptimized framework.',
|
description: 'No framework or an unoptimized framework.',
|
||||||
settings: {
|
settings: {
|
||||||
installCommand: {
|
installCommand: {
|
||||||
placeholder: '`yarn install`, `pnpm install`, or `npm install`',
|
placeholder:
|
||||||
|
'`yarn install`, `pnpm install`, `npm install`, or `bun install`',
|
||||||
},
|
},
|
||||||
buildCommand: {
|
buildCommand: {
|
||||||
placeholder: '`npm run vercel-build` or `npm run build`',
|
placeholder: '`npm run vercel-build` or `npm run build`',
|
||||||
|
|||||||
@@ -1,5 +1,18 @@
|
|||||||
# @vercel/fs-detectors
|
# @vercel/fs-detectors
|
||||||
|
|
||||||
|
## 5.1.0
|
||||||
|
|
||||||
|
### Minor Changes
|
||||||
|
|
||||||
|
- Add support for bun detection in monorepo ([#10511](https://github.com/vercel/vercel/pull/10511))
|
||||||
|
|
||||||
|
## 5.0.3
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [[`ec894bdf7`](https://github.com/vercel/vercel/commit/ec894bdf7f167debded37183f11360756f577f14)]:
|
||||||
|
- @vercel/frameworks@2.0.2
|
||||||
|
|
||||||
## 5.0.2
|
## 5.0.2
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@vercel/fs-detectors",
|
"name": "@vercel/fs-detectors",
|
||||||
"version": "5.0.2",
|
"version": "5.1.0",
|
||||||
"description": "Vercel filesystem detectors",
|
"description": "Vercel filesystem detectors",
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
"types": "./dist/index.d.ts",
|
"types": "./dist/index.d.ts",
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vercel/error-utils": "2.0.1",
|
"@vercel/error-utils": "2.0.1",
|
||||||
"@vercel/frameworks": "2.0.1",
|
"@vercel/frameworks": "2.0.2",
|
||||||
"@vercel/routing-utils": "3.0.0",
|
"@vercel/routing-utils": "3.0.0",
|
||||||
"glob": "8.0.3",
|
"glob": "8.0.3",
|
||||||
"js-yaml": "4.1.0",
|
"js-yaml": "4.1.0",
|
||||||
@@ -36,7 +36,7 @@
|
|||||||
"@types/minimatch": "3.0.5",
|
"@types/minimatch": "3.0.5",
|
||||||
"@types/node": "14.18.33",
|
"@types/node": "14.18.33",
|
||||||
"@types/semver": "7.3.10",
|
"@types/semver": "7.3.10",
|
||||||
"@vercel/build-utils": "7.1.1",
|
"@vercel/build-utils": "7.2.1",
|
||||||
"jest-junit": "16.0.0",
|
"jest-junit": "16.0.0",
|
||||||
"typescript": "4.9.5"
|
"typescript": "4.9.5"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,6 +37,24 @@ export const packageManagers: Array<
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'bun',
|
||||||
|
slug: 'bun',
|
||||||
|
logo: '',
|
||||||
|
darkModeLogo: '',
|
||||||
|
detectors: {
|
||||||
|
some: [
|
||||||
|
{
|
||||||
|
path: 'bun.lockb',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'package.json',
|
||||||
|
// Depends on https://github.com/nodejs/corepack/pull/307
|
||||||
|
matchContent: '"packageManager":\\s*"bun@.*"',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'yarn',
|
name: 'yarn',
|
||||||
slug: 'yarn',
|
slug: 'yarn',
|
||||||
|
|||||||
0
packages/fs-detectors/test/fixtures/57-bun-with-lockfile/bun.lockb
vendored
Normal file
0
packages/fs-detectors/test/fixtures/57-bun-with-lockfile/bun.lockb
vendored
Normal file
1
packages/fs-detectors/test/fixtures/57-bun-with-lockfile/package.json
vendored
Normal file
1
packages/fs-detectors/test/fixtures/57-bun-with-lockfile/package.json
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{}
|
||||||
3
packages/fs-detectors/test/fixtures/58-bun-with-corepack/package.json
vendored
Normal file
3
packages/fs-detectors/test/fixtures/58-bun-with-corepack/package.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"packageManager": "bun@1.0.1"
|
||||||
|
}
|
||||||
@@ -14,6 +14,8 @@ describe('package-managers', () => {
|
|||||||
['54-yarn-with-corepack', 'yarn'],
|
['54-yarn-with-corepack', 'yarn'],
|
||||||
['55-pnpm-with-lockfile', 'pnpm'],
|
['55-pnpm-with-lockfile', 'pnpm'],
|
||||||
['56-pnpm-with-corepack', 'pnpm'],
|
['56-pnpm-with-corepack', 'pnpm'],
|
||||||
|
['57-bun-with-lockfile', 'bun'],
|
||||||
|
['58-bun-with-corepack', 'bun'],
|
||||||
])('with detectFramework', (fixturePath, frameworkSlug) => {
|
])('with detectFramework', (fixturePath, frameworkSlug) => {
|
||||||
const testName = `should detect package manager '${frameworkSlug}' for ${fixturePath}`;
|
const testName = `should detect package manager '${frameworkSlug}' for ${fixturePath}`;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,2 @@
|
|||||||
node_modules
|
node_modules
|
||||||
.DS_Store
|
.DS_Store
|
||||||
gatsby-browser.js
|
|
||||||
web-vitals.js
|
|
||||||
|
|||||||
7
packages/gatsby-plugin-vercel-analytics/CHANGELOG.md
Normal file
7
packages/gatsby-plugin-vercel-analytics/CHANGELOG.md
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# @vercel/gatsby-plugin-vercel-analytics
|
||||||
|
|
||||||
|
## 1.0.11
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Remove "babel" compilation ([#10546](https://github.com/vercel/vercel/pull/10546))
|
||||||
@@ -1,17 +1,13 @@
|
|||||||
{
|
{
|
||||||
"name": "@vercel/gatsby-plugin-vercel-analytics",
|
"name": "@vercel/gatsby-plugin-vercel-analytics",
|
||||||
"version": "1.0.10",
|
"version": "1.0.11",
|
||||||
"description": "Track Core Web Vitals in Gatsby projects with Vercel Speed Insights.",
|
"description": "Track Core Web Vitals in Gatsby projects with Vercel Speed Insights.",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"files": [
|
"files": [
|
||||||
"gatsby-browser.js",
|
"gatsby-browser.js",
|
||||||
"web-vitals.js"
|
"web-vitals.js"
|
||||||
],
|
],
|
||||||
"scripts": {
|
|
||||||
"build": "babel src --out-dir ."
|
|
||||||
},
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "7.12.1",
|
|
||||||
"web-vitals": "0.2.4"
|
"web-vitals": "0.2.4"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
@@ -33,8 +29,6 @@
|
|||||||
],
|
],
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "7.20.7",
|
|
||||||
"@babel/core": "7.5.0",
|
|
||||||
"jest-junit": "16.0.0"
|
"jest-junit": "16.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1 @@
|
|||||||
gatsby-node.*
|
|
||||||
!gatsby-node.ts
|
|
||||||
|
|
||||||
dist
|
dist
|
||||||
|
|||||||
@@ -1,5 +1,22 @@
|
|||||||
# @vercel/gatsby-plugin-vercel-builder
|
# @vercel/gatsby-plugin-vercel-builder
|
||||||
|
|
||||||
|
## 2.0.6
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Use "esbuild" to build package ([#10508](https://github.com/vercel/vercel/pull/10508))
|
||||||
|
|
||||||
|
- Updated dependencies [[`decdf27fb`](https://github.com/vercel/vercel/commit/decdf27fb5ca914fe50a9320c4fd50ef79d2fbb3)]:
|
||||||
|
- @vercel/build-utils@7.2.1
|
||||||
|
|
||||||
|
## 2.0.5
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [[`50e04dd85`](https://github.com/vercel/vercel/commit/50e04dd8584664c842a86c15d92d654f4ea8dcbb), [`45b73c7e8`](https://github.com/vercel/vercel/commit/45b73c7e86458564dc0bab007f6f6365c4c4ab5d), [`9d64312aa`](https://github.com/vercel/vercel/commit/9d64312aaaa875a4e193b7602c50e5dc68979aad), [`d8bc570f6`](https://github.com/vercel/vercel/commit/d8bc570f604950d97156d4f33c8accecf3b3b28f)]:
|
||||||
|
- @vercel/build-utils@7.2.0
|
||||||
|
- @vercel/node@3.0.5
|
||||||
|
|
||||||
## 2.0.4
|
## 2.0.4
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
8
packages/gatsby-plugin-vercel-builder/gatsby-node.js
Normal file
8
packages/gatsby-plugin-vercel-builder/gatsby-node.js
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
const { generateVercelBuildOutputAPI3Output } = require('./dist/index.js');
|
||||||
|
|
||||||
|
exports.onPostBuild = async ({ store }) => {
|
||||||
|
await generateVercelBuildOutputAPI3Output({
|
||||||
|
// validated by `pluginOptionSchema`
|
||||||
|
gatsbyStoreState: store.getState(),
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
// this gets built separately, so import from "dist" instead of "src"
|
|
||||||
import { generateVercelBuildOutputAPI3Output } from './dist';
|
|
||||||
|
|
||||||
export const onPostBuild = async ({ store }: { store: any }) => {
|
|
||||||
await generateVercelBuildOutputAPI3Output({
|
|
||||||
// validated by `pluginOptionSchema`
|
|
||||||
gatsbyStoreState: store.getState(),
|
|
||||||
});
|
|
||||||
};
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user