mirror of
https://github.com/LukeHagar/vercel.git
synced 2025-12-24 11:49:13 +00:00
Compare commits
144 Commits
@vercel/fr
...
@vercel/fr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
acc10e47c7 | ||
|
|
6a0e1e0b66 | ||
|
|
3468922108 | ||
|
|
e4895d979b | ||
|
|
733ff5ed85 | ||
|
|
0867f11a6a | ||
|
|
a6de052ed2 | ||
|
|
f5d48ec3bc | ||
|
|
6ec1180798 | ||
|
|
36db62a491 | ||
|
|
f9266e069f | ||
|
|
8163a153df | ||
|
|
c5e6bd1a7a | ||
|
|
c2f1bebd1f | ||
|
|
3138415533 | ||
|
|
8f6813bb63 | ||
|
|
734499fc03 | ||
|
|
f06988d914 | ||
|
|
71ac16220b | ||
|
|
8b3a4146af | ||
|
|
cfea31e6cf | ||
|
|
7090fec110 | ||
|
|
bc7c80fb9b | ||
|
|
91406abdb0 | ||
|
|
a5af8381ce | ||
|
|
2230ea6cc1 | ||
|
|
f057f0421b | ||
|
|
42c0b32a8d | ||
|
|
d61a1a7988 | ||
|
|
c438bbb362 | ||
|
|
cb5eef0eb5 | ||
|
|
79dee367cf | ||
|
|
dea58dea7e | ||
|
|
fecebfa7fa | ||
|
|
94d5612dce | ||
|
|
3eaf58bb74 | ||
|
|
e63cf40153 | ||
|
|
709c9509f4 | ||
|
|
6107c1ed22 | ||
|
|
7a0f377afe | ||
|
|
a04bf557fc | ||
|
|
b6736e82cf | ||
|
|
7923056bc0 | ||
|
|
71ff193ea3 | ||
|
|
c21d93de44 | ||
|
|
0039c8b5ce | ||
|
|
49c7178567 | ||
|
|
b038b29614 | ||
|
|
7a249a2284 | ||
|
|
a5e32ec31d | ||
|
|
bc5afe24c4 | ||
|
|
5070e3bbbd | ||
|
|
4ad1cbbd7d | ||
|
|
4f4e09477d | ||
|
|
cd35071f60 | ||
|
|
f373c94508 | ||
|
|
553c001eb0 | ||
|
|
f6c3a95783 | ||
|
|
c0bcef0ca4 | ||
|
|
4cd77608e8 | ||
|
|
e6b2980eba | ||
|
|
67e20a6ede | ||
|
|
c63679ea0a | ||
|
|
4280166df4 | ||
|
|
18ae78137c | ||
|
|
ebe4058073 | ||
|
|
942e76840e | ||
|
|
57515d2d07 | ||
|
|
ef30a46c03 | ||
|
|
113b8ac87b | ||
|
|
b56ac2717d | ||
|
|
aa8957ab10 | ||
|
|
c6c19354e8 | ||
|
|
96b2502133 | ||
|
|
2df0262675 | ||
|
|
1e47bbf32f | ||
|
|
00813a3945 | ||
|
|
a73ec6343f | ||
|
|
4bd70d4b6e | ||
|
|
c7bcea4081 | ||
|
|
aab95532d6 | ||
|
|
1b18c853c2 | ||
|
|
1663db7ca3 | ||
|
|
e80247fb99 | ||
|
|
a19edc985b | ||
|
|
4fd593ac09 | ||
|
|
1b0d72aba5 | ||
|
|
c52a59809e | ||
|
|
cdf55b3b1a | ||
|
|
8de42e0a70 | ||
|
|
7ff321310f | ||
|
|
2da72bc5e4 | ||
|
|
46950633f4 | ||
|
|
44b1dfe7c5 | ||
|
|
0278c7b7b9 | ||
|
|
761db597be | ||
|
|
671e63e7b8 | ||
|
|
f7bdc6cc26 | ||
|
|
e94a153b2f | ||
|
|
74e639a772 | ||
|
|
f00b08a820 | ||
|
|
6cdd38d130 | ||
|
|
2c950d47ae | ||
|
|
71b9f3a94b | ||
|
|
91b7f6dcd9 | ||
|
|
ba10fb4dd4 | ||
|
|
18c1c45ce3 | ||
|
|
67e556bc80 | ||
|
|
7235000181 | ||
|
|
5124d431ea | ||
|
|
c879401bbc | ||
|
|
6c6f3ce9d2 | ||
|
|
aa83680832 | ||
|
|
06113d3e39 | ||
|
|
5150f21404 | ||
|
|
eb6bb98406 | ||
|
|
d8e3b6e738 | ||
|
|
25da051d62 | ||
|
|
f57af66dc2 | ||
|
|
b2f71d5352 | ||
|
|
6115f0d74a | ||
|
|
14c877e468 | ||
|
|
d80732d74f | ||
|
|
b739c1845c | ||
|
|
e9f0fcf397 | ||
|
|
924a20a0fc | ||
|
|
fc3b74d06f | ||
|
|
380ed38c71 | ||
|
|
e228cdd373 | ||
|
|
9bd92535d6 | ||
|
|
5825e30700 | ||
|
|
6d5983eaae | ||
|
|
2fd59a3b5a | ||
|
|
d1d3e9384d | ||
|
|
8428632eb1 | ||
|
|
fa443035f6 | ||
|
|
de2c7e1633 | ||
|
|
75d2435138 | ||
|
|
5328bb69e2 | ||
|
|
e3fe368baa | ||
|
|
99832587c5 | ||
|
|
47d0d4f84a | ||
|
|
aba54ee6cf | ||
|
|
cd7d3ef1c5 |
8
.changeset/README.md
Normal file
8
.changeset/README.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# Changesets
|
||||
|
||||
Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
|
||||
with multi-package repos, or single-package repos to help you version and publish your code. You can
|
||||
find the full documentation for it [in our repository](https://github.com/changesets/changesets)
|
||||
|
||||
We have a quick list of common questions to get you started engaging with this project in
|
||||
[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)
|
||||
14
.changeset/config.json
Normal file
14
.changeset/config.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"$schema": "https://unpkg.com/@changesets/config@2.3.0/schema.json",
|
||||
"changelog": [
|
||||
"@svitejs/changesets-changelog-github-compact",
|
||||
{ "repo": "vercel/vercel" }
|
||||
],
|
||||
"commit": false,
|
||||
"fixed": [],
|
||||
"linked": [],
|
||||
"access": "public",
|
||||
"baseBranch": "main",
|
||||
"updateInternalDependencies": "patch",
|
||||
"ignore": []
|
||||
}
|
||||
4
.github/CODEOWNERS
vendored
4
.github/CODEOWNERS
vendored
@@ -1,6 +1,7 @@
|
||||
# Documentation
|
||||
# https://help.github.com/en/articles/about-code-owners
|
||||
|
||||
# Restricted Paths
|
||||
* @TooTallNate @EndangeredMassa @styfle @cb1kenobi @Ethan-Arrowood
|
||||
/.github/workflows @TooTallNate @EndangeredMassa @styfle @cb1kenobi @Ethan-Arrowood @ijjk
|
||||
/packages/fs-detectors @TooTallNate @EndangeredMassa @styfle @cb1kenobi @Ethan-Arrowood @agadzik @chloetedder
|
||||
@@ -14,3 +15,6 @@
|
||||
/examples/jekyll @styfle
|
||||
/examples/zola @styfle
|
||||
/packages/node @TooTallNate @EndangeredMassa @styfle @cb1kenobi @Ethan-Arrowood @Kikobeats
|
||||
|
||||
# Unrestricted Paths
|
||||
.changeset/
|
||||
|
||||
1
.github/CONTRIBUTING.md
vendored
1
.github/CONTRIBUTING.md
vendored
@@ -15,7 +15,6 @@ git clone https://github.com/vercel/vercel
|
||||
cd vercel
|
||||
corepack enable
|
||||
pnpm install
|
||||
pnpm bootstrap
|
||||
pnpm build
|
||||
pnpm lint
|
||||
pnpm test-unit
|
||||
|
||||
@@ -1,75 +1,78 @@
|
||||
name: Publish
|
||||
name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
tags:
|
||||
- '!*'
|
||||
|
||||
env:
|
||||
TURBO_REMOTE_ONLY: 'true'
|
||||
TURBO_TEAM: 'vercel'
|
||||
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
||||
|
||||
concurrency: ${{ github.workflow }}-${{ github.ref }}
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
name: Publish
|
||||
release:
|
||||
name: Release
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
id-token: write
|
||||
steps:
|
||||
- name: Checkout
|
||||
- name: Checkout Repo
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Check Release
|
||||
id: check-release
|
||||
run: |
|
||||
tag="$(git describe --tags --exact-match 2> /dev/null || :)"
|
||||
if [[ -z "$tag" ]];
|
||||
then
|
||||
echo "IS_RELEASE=false" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "IS_RELEASE=true" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
- name: Setup Go
|
||||
if: ${{ steps.check-release.outputs.IS_RELEASE == 'true' }}
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '1.13.15'
|
||||
|
||||
- name: Fetch git tags
|
||||
run: git fetch origin 'refs/tags/*:refs/tags/*'
|
||||
|
||||
- name: Setup Node
|
||||
if: ${{ steps.check-release.outputs.IS_RELEASE == 'true' }}
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
|
||||
- name: install npm@9
|
||||
run: npm i -g npm@9
|
||||
|
||||
- name: install pnpm@8.3.1
|
||||
run: npm i -g pnpm@8.3.1
|
||||
- name: Install
|
||||
if: ${{ steps.check-release.outputs.IS_RELEASE == 'true' }}
|
||||
run: pnpm install
|
||||
- name: Build
|
||||
if: ${{ steps.check-release.outputs.IS_RELEASE == 'true' }}
|
||||
|
||||
- name: Install Dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Build Packages
|
||||
run: pnpm build
|
||||
env:
|
||||
GA_TRACKING_ID: ${{ secrets.GA_TRACKING_ID }}
|
||||
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
|
||||
- name: Publish
|
||||
if: ${{ steps.check-release.outputs.IS_RELEASE == 'true' }}
|
||||
run: pnpm publish-from-github
|
||||
|
||||
- name: Create Release Pull Request or Publish to npm
|
||||
id: changesets
|
||||
uses: changesets/action@v1
|
||||
with:
|
||||
version: pnpm ci:version
|
||||
publish: pnpm ci:publish
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GH_TOKEN_PULL_REQUESTS }}
|
||||
NPM_CONFIG_PROVENANCE: 'true'
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN_ELEVATED }}
|
||||
GA_TRACKING_ID: ${{ secrets.GA_TRACKING_ID }}
|
||||
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
|
||||
- name: Trigger Update
|
||||
if: ${{ steps.check-release.outputs.IS_RELEASE == 'true' }}
|
||||
|
||||
- name: Trigger Update (if a Publish Happened)
|
||||
if: steps.changesets.outputs.published == 'true'
|
||||
uses: actions/github-script@v6
|
||||
with:
|
||||
github-token: ${{ secrets.GH_TOKEN_PULL_REQUESTS }}
|
||||
script: |
|
||||
const script = require('./utils/trigger-update-workflow.js')
|
||||
await script({ github, context })
|
||||
|
||||
- name: Set latest Release to `vercel` (if a Publish Happened)
|
||||
if: steps.changesets.outputs.published == 'true'
|
||||
uses: actions/github-script@v6
|
||||
with:
|
||||
github-token: ${{ secrets.GH_TOKEN_PULL_REQUESTS }}
|
||||
script: |
|
||||
const script = require('./utils/update-latest-release.js')
|
||||
await script({ github, context })
|
||||
26
.github/workflows/required-pr-label.yml
vendored
26
.github/workflows/required-pr-label.yml
vendored
@@ -1,26 +0,0 @@
|
||||
name: Required PR Label
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, labeled, unlabeled, synchronize]
|
||||
jobs:
|
||||
label:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check PR Labels
|
||||
uses: actions/github-script@v6
|
||||
with:
|
||||
script: |
|
||||
let missing = false;
|
||||
const labels = context.payload.pull_request.labels.map(l => l.name);
|
||||
if (labels.filter(l => l.startsWith('area:')).length === 0) {
|
||||
console.error('::error::Missing label: Please add at least one "area" label.');
|
||||
missing = true;
|
||||
}
|
||||
if (labels.filter(l => l.startsWith('semver:')).length !== 1) {
|
||||
console.error('::error::Missing label: Please add exactly one "semver" label.');
|
||||
missing = true;
|
||||
}
|
||||
if (missing) {
|
||||
process.exit(1);
|
||||
}
|
||||
console.log('::notice::Success: This pull request has correct labels, thanks!');
|
||||
16
.github/workflows/test-lint.yml
vendored
16
.github/workflows/test-lint.yml
vendored
@@ -19,6 +19,22 @@ concurrency:
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
|
||||
|
||||
jobs:
|
||||
enforce-changeset:
|
||||
name: Enforce Changeset
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'pull_request' && github.event.pull_request.title != 'Version Packages'
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: main
|
||||
- run: git checkout ${{ github.event.pull_request.head.ref }}
|
||||
- name: install pnpm@8.3.1
|
||||
run: npm i -g pnpm@8.3.1
|
||||
- run: pnpm install
|
||||
# Enforce a changeset file to be present
|
||||
- run: pnpm exec changeset status --since=main
|
||||
|
||||
test:
|
||||
name: Lint
|
||||
timeout-minutes: 10
|
||||
|
||||
22
.github/workflows/test.yml
vendored
22
.github/workflows/test.yml
vendored
@@ -41,7 +41,7 @@ jobs:
|
||||
echo "Files to test:"
|
||||
echo "$TESTS_ARRAY"
|
||||
echo "tests=$TESTS_ARRAY" >> $GITHUB_OUTPUT
|
||||
- uses: patrickedqvist/wait-for-vercel-preview@ae34b392ef30297f2b672f9afb3c329bde9bd487
|
||||
- uses: patrickedqvist/wait-for-vercel-preview@bfdff514ff78a669f2536e9f4dd4ef5813a704a2
|
||||
id: waitForTarball
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -97,11 +97,21 @@ jobs:
|
||||
if: matrix.runner != 'windows-latest'
|
||||
run: echo | openssl s_client -showcerts -servername 'api.vercel.com' -connect 76.76.21.21:443
|
||||
|
||||
conclusion:
|
||||
summary:
|
||||
name: Summary
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
if: always()
|
||||
needs:
|
||||
- test
|
||||
runs-on: ubuntu-latest
|
||||
name: E2E
|
||||
steps:
|
||||
- name: Done
|
||||
run: echo "Done."
|
||||
- name: Check All
|
||||
run: |-
|
||||
for status in ${{ join(needs.*.result, ' ') }}
|
||||
do
|
||||
if [ "$status" != "success" ] && [ "$status" != "skipped" ]
|
||||
then
|
||||
echo "Some checks failed"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
@@ -12,6 +12,7 @@ packages/gatsby-plugin-vercel-analytics
|
||||
node_modules
|
||||
dist
|
||||
pnpm-lock.yaml
|
||||
.changeset
|
||||
.vscode
|
||||
.DS_Store
|
||||
.next
|
||||
@@ -31,4 +32,4 @@ packages/**/test/fixtures
|
||||
packages/**/test/dev/fixtures
|
||||
packages/**/test/build-fixtures
|
||||
packages/**/test/cache-fixtures
|
||||
|
||||
packages/cli/src/util/dev/templates/*.ts
|
||||
|
||||
@@ -19,9 +19,7 @@
|
||||
|
||||
## Vercel
|
||||
|
||||
Vercel is the platform for frontend developers, providing the speed and reliability innovators need to create at the moment of inspiration.
|
||||
|
||||
We enable teams to iterate quickly and develop, preview, and ship delightful user experiences. Vercel has zero-configuration support for 35+ frontend frameworks and integrates with your headless content, commerce, or database of choice.
|
||||
Vercel's frontend cloud gives developers frameworks, workflows, and infrastructure to build a faster, more personalized web.
|
||||
|
||||
## Deploy
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
You ran `vercel dev` inside a project that contains a `vercel.json` file with `env` or `build.env` properties that use [Vercel Secrets](https://vercel.com/docs/concepts/projects/environment-variables).
|
||||
|
||||
In order to use environment variables in your project locally that have values defined using the Vercel Secrets format (e.g. `@my-secret-value`), you will need to provide the value as an environment variable using a `.env`.
|
||||
In order to use environment variables in your project locally that have values defined using the Vercel Secrets format (e.g. `@my-secret-value`), you will need to provide the value as an environment variable using a `.env.local`.
|
||||
|
||||
We require this to ensure your app works as you intend it to, in the development environment, and to provide you with a way to mirror or separate private environment variables within your applications, for example when connecting to a database.
|
||||
|
||||
@@ -12,11 +12,11 @@ Read below for how to address this error.
|
||||
|
||||
#### Possible Ways to Fix It
|
||||
|
||||
The error message will list environment variables that are required and which file they are required to be included in `.env`.
|
||||
The error message will list environment variables that are required and which file they are required to be included in `.env.local`.
|
||||
|
||||
If the file does not exist yet, please create the file that the error message mentions and insert the missing environment variable into it.
|
||||
|
||||
For example, if the error message shows that the environment variable `TEST` is missing from `.env`, then the `.env` file should look like this:
|
||||
For example, if the error message shows that the environment variable `TEST` is missing from `.env.local`, then the `.env.local` file should look like this:
|
||||
|
||||
```
|
||||
TEST=value
|
||||
|
||||
@@ -14,11 +14,7 @@ pnpm dev
|
||||
|
||||
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
||||
|
||||
You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file.
|
||||
|
||||
[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.js`.
|
||||
|
||||
The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.
|
||||
You can start editing the page by modifying `app/page.js`. The page auto-updates as you edit the file.
|
||||
|
||||
This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
17
examples/nextjs/app/layout.js
Normal file
17
examples/nextjs/app/layout.js
Normal file
@@ -0,0 +1,17 @@
|
||||
import './globals.css'
|
||||
import { Inter } from 'next/font/google'
|
||||
|
||||
const inter = Inter({ subsets: ['latin'] })
|
||||
|
||||
export const metadata = {
|
||||
title: 'Create Next App',
|
||||
description: 'Generated by create next app',
|
||||
}
|
||||
|
||||
export default function RootLayout({ children }) {
|
||||
return (
|
||||
<html lang="en">
|
||||
<body className={inter.className}>{children}</body>
|
||||
</html>
|
||||
)
|
||||
}
|
||||
95
examples/nextjs/app/page.js
Normal file
95
examples/nextjs/app/page.js
Normal file
@@ -0,0 +1,95 @@
|
||||
import Image from 'next/image'
|
||||
import styles from './page.module.css'
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<main className={styles.main}>
|
||||
<div className={styles.description}>
|
||||
<p>
|
||||
Get started by editing
|
||||
<code className={styles.code}>app/page.js</code>
|
||||
</p>
|
||||
<div>
|
||||
<a
|
||||
href="https://vercel.com?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
By{' '}
|
||||
<Image
|
||||
src="/vercel.svg"
|
||||
alt="Vercel Logo"
|
||||
className={styles.vercelLogo}
|
||||
width={100}
|
||||
height={24}
|
||||
priority
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={styles.center}>
|
||||
<Image
|
||||
className={styles.logo}
|
||||
src="/next.svg"
|
||||
alt="Next.js Logo"
|
||||
width={180}
|
||||
height={37}
|
||||
priority
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className={styles.grid}>
|
||||
<a
|
||||
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
|
||||
className={styles.card}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<h2>
|
||||
Docs <span>-></span>
|
||||
</h2>
|
||||
<p>Find in-depth information about Next.js features and API.</p>
|
||||
</a>
|
||||
|
||||
<a
|
||||
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
|
||||
className={styles.card}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<h2>
|
||||
Learn <span>-></span>
|
||||
</h2>
|
||||
<p>Learn about Next.js in an interactive course with quizzes!</p>
|
||||
</a>
|
||||
|
||||
<a
|
||||
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
|
||||
className={styles.card}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<h2>
|
||||
Templates <span>-></span>
|
||||
</h2>
|
||||
<p>Explore the Next.js 13 playground.</p>
|
||||
</a>
|
||||
|
||||
<a
|
||||
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
|
||||
className={styles.card}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<h2>
|
||||
Deploy <span>-></span>
|
||||
</h2>
|
||||
<p>
|
||||
Instantly deploy your Next.js site to a shareable URL with Vercel.
|
||||
</p>
|
||||
</a>
|
||||
</div>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
@@ -1,6 +1,4 @@
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {
|
||||
reactStrictMode: true,
|
||||
}
|
||||
const nextConfig = {}
|
||||
|
||||
module.exports = nextConfig
|
||||
|
||||
903
examples/nextjs/package-lock.json
generated
903
examples/nextjs/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -9,9 +9,9 @@
|
||||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"eslint": "8.39.0",
|
||||
"eslint-config-next": "13.3.4",
|
||||
"next": "13.3.4",
|
||||
"eslint": "8.43.0",
|
||||
"eslint-config-next": "13.4.7",
|
||||
"next": "13.4.7",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0"
|
||||
}
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
import '@/styles/globals.css'
|
||||
|
||||
export default function App({ Component, pageProps }) {
|
||||
return <Component {...pageProps} />
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
import { Html, Head, Main, NextScript } from 'next/document'
|
||||
|
||||
export default function Document() {
|
||||
return (
|
||||
<Html lang="en">
|
||||
<Head />
|
||||
<body>
|
||||
<Main />
|
||||
<NextScript />
|
||||
</body>
|
||||
</Html>
|
||||
)
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
|
||||
|
||||
export default function handler(req, res) {
|
||||
res.status(200).json({ name: 'John Doe' })
|
||||
}
|
||||
@@ -1,114 +0,0 @@
|
||||
import Head from 'next/head'
|
||||
import Image from 'next/image'
|
||||
import { Inter } from 'next/font/google'
|
||||
import styles from '@/styles/Home.module.css'
|
||||
|
||||
const inter = Inter({ subsets: ['latin'] })
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>Create Next App</title>
|
||||
<meta name="description" content="Generated by create next app" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
</Head>
|
||||
<main className={`${styles.main} ${inter.className}`}>
|
||||
<div className={styles.description}>
|
||||
<p>
|
||||
Get started by editing
|
||||
<code className={styles.code}>pages/index.js</code>
|
||||
</p>
|
||||
<div>
|
||||
<a
|
||||
href="https://vercel.com?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
By{' '}
|
||||
<Image
|
||||
src="/vercel.svg"
|
||||
alt="Vercel Logo"
|
||||
className={styles.vercelLogo}
|
||||
width={100}
|
||||
height={24}
|
||||
priority
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={styles.center}>
|
||||
<Image
|
||||
className={styles.logo}
|
||||
src="/next.svg"
|
||||
alt="Next.js Logo"
|
||||
width={180}
|
||||
height={37}
|
||||
priority
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className={styles.grid}>
|
||||
<a
|
||||
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
|
||||
className={styles.card}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<h2>
|
||||
Docs <span>-></span>
|
||||
</h2>
|
||||
<p>
|
||||
Find in-depth information about Next.js features and API.
|
||||
</p>
|
||||
</a>
|
||||
|
||||
<a
|
||||
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
|
||||
className={styles.card}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<h2>
|
||||
Learn <span>-></span>
|
||||
</h2>
|
||||
<p>
|
||||
Learn about Next.js in an interactive course with quizzes!
|
||||
</p>
|
||||
</a>
|
||||
|
||||
<a
|
||||
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
|
||||
className={styles.card}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<h2>
|
||||
Templates <span>-></span>
|
||||
</h2>
|
||||
<p>
|
||||
Discover and deploy boilerplate example Next.js projects.
|
||||
</p>
|
||||
</a>
|
||||
|
||||
<a
|
||||
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
|
||||
className={styles.card}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<h2>
|
||||
Deploy <span>-></span>
|
||||
</h2>
|
||||
<p>
|
||||
Instantly deploy your Next.js site to a shareable URL
|
||||
with Vercel.
|
||||
</p>
|
||||
</a>
|
||||
</div>
|
||||
</main>
|
||||
</>
|
||||
)
|
||||
}
|
||||
2
examples/package.json
vendored
2
examples/package.json
vendored
@@ -9,6 +9,6 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "27.4.1",
|
||||
"@vercel/frameworks": "1.3.0"
|
||||
"@vercel/frameworks": "1.4.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
{
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "preact build",
|
||||
"build": "NODE_OPTIONS=--openssl-legacy-provider preact build",
|
||||
"serve": "sirv build --port 8080 --cors --single",
|
||||
"dev": "preact watch",
|
||||
"lint": "eslint src",
|
||||
"test": "jest"
|
||||
},
|
||||
"engines": {
|
||||
"node": "16.x"
|
||||
"node": "18.x"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": "preact",
|
||||
@@ -17,19 +17,19 @@
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"enzyme": "^3.10.0",
|
||||
"enzyme-adapter-preact-pure": "^2.0.0",
|
||||
"eslint": "^6.0.1",
|
||||
"eslint-config-preact": "^1.1.0",
|
||||
"jest": "^24.9.0",
|
||||
"jest-preset-preact": "^1.0.0",
|
||||
"preact-cli": "^3.0.0",
|
||||
"sirv-cli": "1.0.3"
|
||||
"enzyme": "^3.11.0",
|
||||
"enzyme-adapter-preact-pure": "^4.1.0",
|
||||
"eslint": "^8.41.0",
|
||||
"eslint-config-preact": "^1.3.0",
|
||||
"jest": "^29.5.0",
|
||||
"jest-preset-preact": "^4.0.4",
|
||||
"preact-cli": "^3.4.5",
|
||||
"sirv-cli": "2.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"preact": "^10.3.2",
|
||||
"preact-render-to-string": "^5.1.4",
|
||||
"preact-router": "^3.2.1"
|
||||
"preact": "^10.15.0",
|
||||
"preact-render-to-string": "6.0.3",
|
||||
"preact-router": "^4.1.1"
|
||||
},
|
||||
"jest": {
|
||||
"preset": "jest-preset-preact",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,4 @@
|
||||
/** @type {import('eslint').Linter.Config} */
|
||||
module.exports = {
|
||||
extends: ["@remix-run/eslint-config", "@remix-run/eslint-config/node"],
|
||||
};
|
||||
|
||||
7
examples/remix/.gitignore
vendored
7
examples/remix/.gitignore
vendored
@@ -1,11 +1,12 @@
|
||||
node_modules
|
||||
|
||||
.cache
|
||||
/.cache
|
||||
/build
|
||||
/public/build
|
||||
.env
|
||||
|
||||
.vercel
|
||||
.output
|
||||
|
||||
/build/
|
||||
/public/build
|
||||
/api/index.js
|
||||
/api/index.js.map
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { MetaFunction } from "@vercel/remix";
|
||||
import { cssBundleHref } from "@remix-run/css-bundle";
|
||||
import {
|
||||
Links,
|
||||
LiveReload,
|
||||
@@ -8,17 +8,18 @@ import {
|
||||
ScrollRestoration,
|
||||
} from "@remix-run/react";
|
||||
import { Analytics } from "@vercel/analytics/react";
|
||||
import type { LinksFunction } from "@vercel/remix";
|
||||
|
||||
export const meta: MetaFunction = () => ({
|
||||
charset: "utf-8",
|
||||
title: "New Remix App",
|
||||
viewport: "width=device-width,initial-scale=1",
|
||||
});
|
||||
export const links: LinksFunction = () => [
|
||||
...(cssBundleHref ? [{ rel: "stylesheet", href: cssBundleHref }] : []),
|
||||
];
|
||||
|
||||
export default function App() {
|
||||
return (
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charSet="utf-8" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<Meta />
|
||||
<Links />
|
||||
</head>
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
import type { V2_MetaFunction } from "@vercel/remix";
|
||||
|
||||
export const meta: V2_MetaFunction = () => [{ title: "New Remix App" }];
|
||||
|
||||
export default function Index() {
|
||||
return (
|
||||
<div style={{ fontFamily: "system-ui, sans-serif", lineHeight: "1.4" }}>
|
||||
@@ -1,5 +1,9 @@
|
||||
import type { V2_MetaFunction } from "@vercel/remix";
|
||||
|
||||
export const config = { runtime: "edge" };
|
||||
|
||||
export const meta: V2_MetaFunction = () => [{ title: "Remix@Edge | New Remix App" }];
|
||||
|
||||
export default function Edge() {
|
||||
return (
|
||||
<div style={{ fontFamily: "system-ui, sans-serif", lineHeight: "1.4" }}>
|
||||
|
||||
@@ -3,24 +3,28 @@
|
||||
"sideEffects": false,
|
||||
"scripts": {
|
||||
"build": "remix build",
|
||||
"dev": "remix dev"
|
||||
"dev": "remix dev",
|
||||
"start": "remix-serve build",
|
||||
"typecheck": "tsc"
|
||||
},
|
||||
"dependencies": {
|
||||
"@remix-run/node": "^1.15.0",
|
||||
"@remix-run/react": "^1.15.0",
|
||||
"@remix-run/serve": "^1.15.0",
|
||||
"@remix-run/css-bundle": "^1.18.0",
|
||||
"@remix-run/node": "^1.18.0",
|
||||
"@remix-run/react": "^1.18.0",
|
||||
"@remix-run/serve": "^1.18.0",
|
||||
"@vercel/analytics": "^0.1.11",
|
||||
"@vercel/remix": "^1.15.0",
|
||||
"@vercel/remix": "^1.18.0",
|
||||
"isbot": "^3.6.8",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@remix-run/dev": "^1.15.0",
|
||||
"@remix-run/eslint-config": "^1.15.0",
|
||||
"@remix-run/dev": "^1.18.0",
|
||||
"@remix-run/eslint-config": "^1.18.0",
|
||||
"@types/react": "^18.0.25",
|
||||
"@types/react-dom": "^18.0.11",
|
||||
"eslint": "^8.28.0",
|
||||
"typescript": "^4.9.3"
|
||||
"typescript": "^5.1.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
|
||||
7492
examples/remix/pnpm-lock.yaml
generated
7492
examples/remix/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,15 @@
|
||||
/**
|
||||
* @type {import('@remix-run/dev').AppConfig}
|
||||
*/
|
||||
/** @type {import('@remix-run/dev').AppConfig} */
|
||||
module.exports = {
|
||||
ignoredRouteFiles: ['**/.*'],
|
||||
future: {
|
||||
v2_dev: true,
|
||||
v2_errorBoundary: true,
|
||||
v2_headers: true,
|
||||
v2_meta: true,
|
||||
v2_normalizeFormMethod: true,
|
||||
v2_routeConvention: true,
|
||||
},
|
||||
ignoredRouteFiles: ["**/.*"],
|
||||
serverModuleFormat: "cjs",
|
||||
// appDirectory: "app",
|
||||
// assetsBuildDirectory: "public/build",
|
||||
// serverBuildPath: "build/index.js",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
# Saber Example
|
||||
|
||||
This directory is a brief example of a [Saber](https://saber.land) site that can be deployed to Vercel with zero configuration.
|
||||
This directory is a brief example of a [Saber](https://saber.egoist.dev) site that can be deployed to Vercel with zero configuration.
|
||||
|
||||
## Deploy Your Own
|
||||
|
||||
|
||||
@@ -5,4 +5,4 @@ layout: page
|
||||
|
||||
This is the Saber port of the base Jekyll theme. Check out the [GitHub project](https://github.com/egoist/saber-theme-minima) for detailed usages.
|
||||
|
||||
You can find out more info about customizing your theme, as well as basic Saber usage documentation at https://saber.land
|
||||
You can find out more info about customizing your theme, as well as basic Saber usage documentation at https://saber.egoist.dev
|
||||
|
||||
@@ -7,18 +7,18 @@
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"solid-start-vercel": "^0.2.0",
|
||||
"typescript": "^4.8.3",
|
||||
"vite": "^3.1.0"
|
||||
"solid-start-vercel": "^0.2.26",
|
||||
"typescript": "^5.0.4",
|
||||
"vite": "^4.3.8"
|
||||
},
|
||||
"dependencies": {
|
||||
"@solidjs/meta": "^0.28.2",
|
||||
"@solidjs/router": "^0.5.0",
|
||||
"solid-js": "^1.6.0",
|
||||
"solid-start": "^0.2.0",
|
||||
"undici": "^5.11.0"
|
||||
"@solidjs/meta": "^0.28.5",
|
||||
"@solidjs/router": "^0.8.2",
|
||||
"solid-js": "^1.7.5",
|
||||
"solid-start": "^0.2.26",
|
||||
"undici": "^5.22.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "16.x"
|
||||
"node": "18.x"
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
4
examples/storybook/vercel.json
Normal file
4
examples/storybook/vercel.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"framework": "storybook",
|
||||
"buildCommand": "storybook build"
|
||||
}
|
||||
@@ -1,11 +1,10 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
extends: ['eslint:recommended', 'prettier'],
|
||||
plugins: ['svelte3'],
|
||||
overrides: [{ files: ['*.svelte'], processor: 'svelte3/svelte3' }],
|
||||
extends: ['eslint:recommended', 'plugin:svelte/recommended', 'prettier'],
|
||||
parserOptions: {
|
||||
sourceType: 'module',
|
||||
ecmaVersion: 2020
|
||||
ecmaVersion: 2020,
|
||||
extraFileExtensions: ['.svelte']
|
||||
},
|
||||
env: {
|
||||
browser: true,
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
engine-strict=true
|
||||
resolution-mode=highest
|
||||
|
||||
@@ -1,18 +1,12 @@
|
||||
# create-svelte
|
||||
# SvelteKit Demo app
|
||||
|
||||
Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/master/packages/create-svelte).
|
||||
The official demo app for SvelteKit, hosted on Vercel.
|
||||
|
||||
## Creating a project
|
||||
## Deploy Your Own
|
||||
|
||||
If you're seeing this, you've probably already done this step. Congrats!
|
||||
[](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fvercel%2Fvercel%2Ftree%2Fmain%2Fexamples%2Fsveltekit-1&project-name=sveltekit-vercel&repository-name=sveltekit-vercel&demo-title=SvelteKit%20%2B%20Vercel&demo-url=https%3A%2F%2Fsveltekit-template.vercel.app%2F)
|
||||
|
||||
```bash
|
||||
# create a new project in the current directory
|
||||
npm create svelte@latest
|
||||
|
||||
# create a new project in my-app
|
||||
npm create svelte@latest my-app
|
||||
```
|
||||
_Live Example: https://sveltekit-template.vercel.app_
|
||||
|
||||
## Developing
|
||||
|
||||
@@ -35,4 +29,8 @@ npm run build
|
||||
|
||||
You can preview the production build with `npm run preview`.
|
||||
|
||||
> To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment.
|
||||
## Speed Insights
|
||||
|
||||
Once deployed on Vercel, you can benefit from [Speed Insights](https://vercel.com/docs/concepts/speed-insights) simply by navigating to Vercel's dashboard, clicking on the 'Speed Insights' tab, and enabling the product.
|
||||
|
||||
You will get data once your application will be re-deployed and will receive visitors.
|
||||
|
||||
@@ -16,19 +16,20 @@
|
||||
"@fontsource/fira-mono": "^4.5.10",
|
||||
"@neoconfetti/svelte": "^1.0.0",
|
||||
"@playwright/test": "^1.28.1",
|
||||
"@sveltejs/adapter-vercel": "^1.0.0",
|
||||
"@sveltejs/kit": "^1.0.0",
|
||||
"@sveltejs/adapter-vercel": "^3.0.0",
|
||||
"@sveltejs/kit": "^1.5.0",
|
||||
"@types/cookie": "^0.5.1",
|
||||
"eslint": "^8.28.0",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-plugin-svelte3": "^4.0.0",
|
||||
"eslint-plugin-svelte": "^2.26.0",
|
||||
"prettier": "^2.8.0",
|
||||
"prettier-plugin-svelte": "^2.8.1",
|
||||
"svelte": "^3.54.0",
|
||||
"svelte-check": "^2.9.2",
|
||||
"typescript": "^4.9.3",
|
||||
"vite": "^4.0.0",
|
||||
"vitest": "^0.25.3"
|
||||
"svelte-check": "^3.0.1",
|
||||
"typescript": "^5.0.0",
|
||||
"vite": "^4.3.0",
|
||||
"vitest": "^0.25.3",
|
||||
"web-vitals": "^3.3.1"
|
||||
},
|
||||
"type": "module"
|
||||
}
|
||||
|
||||
@@ -4,7 +4,8 @@ const config = {
|
||||
command: 'npm run build && npm run preview',
|
||||
port: 4173
|
||||
},
|
||||
testDir: 'tests'
|
||||
testDir: 'tests',
|
||||
testMatch: /(.+\.)?(test|spec)\.[jt]s/
|
||||
};
|
||||
|
||||
export default config;
|
||||
|
||||
786
examples/sveltekit-1/pnpm-lock.yaml
generated
786
examples/sveltekit-1/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
15
examples/sveltekit-1/src/app.d.ts
vendored
15
examples/sveltekit-1/src/app.d.ts
vendored
@@ -1,9 +1,12 @@
|
||||
// See https://kit.svelte.dev/docs/types#app
|
||||
// for information about these interfaces
|
||||
// and what to do when importing types
|
||||
declare namespace App {
|
||||
// interface Error {}
|
||||
// interface Locals {}
|
||||
// interface PageData {}
|
||||
// interface Platform {}
|
||||
declare global {
|
||||
namespace App {
|
||||
// interface Error {}
|
||||
// interface Locals {}
|
||||
// interface PageData {}
|
||||
// interface Platform {}
|
||||
}
|
||||
}
|
||||
|
||||
export {};
|
||||
|
||||
63
examples/sveltekit-1/src/lib/vitals.js
Normal file
63
examples/sveltekit-1/src/lib/vitals.js
Normal file
@@ -0,0 +1,63 @@
|
||||
import { onCLS, onFCP, onFID, onLCP, onTTFB } from 'web-vitals';
|
||||
|
||||
const vitalsUrl = 'https://vitals.vercel-analytics.com/v1/vitals';
|
||||
|
||||
function getConnectionSpeed() {
|
||||
// @ts-ignore
|
||||
return navigator?.connection?.effectiveType ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("web-vitals").Metric} metric
|
||||
* @param {{ params: { [s: string]: any; } | ArrayLike<any>; path: string; analyticsId: string; debug: boolean; }} options
|
||||
*/
|
||||
function sendToAnalytics(metric, options) {
|
||||
const page = Object.entries(options.params).reduce(
|
||||
(acc, [key, value]) => acc.replace(value, `[${key}]`),
|
||||
options.path
|
||||
);
|
||||
|
||||
const body = {
|
||||
dsn: options.analyticsId,
|
||||
id: metric.id,
|
||||
page,
|
||||
href: location.href,
|
||||
event_name: metric.name,
|
||||
value: metric.value.toString(),
|
||||
speed: getConnectionSpeed()
|
||||
};
|
||||
|
||||
if (options.debug) {
|
||||
console.log('[Web Vitals]', metric.name, JSON.stringify(body, null, 2));
|
||||
}
|
||||
|
||||
const blob = new Blob([new URLSearchParams(body).toString()], {
|
||||
// This content type is necessary for `sendBeacon`
|
||||
type: 'application/x-www-form-urlencoded'
|
||||
});
|
||||
if (navigator.sendBeacon) {
|
||||
navigator.sendBeacon(vitalsUrl, blob);
|
||||
} else
|
||||
fetch(vitalsUrl, {
|
||||
body: blob,
|
||||
method: 'POST',
|
||||
credentials: 'omit',
|
||||
keepalive: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {any} options
|
||||
*/
|
||||
export function webVitals(options) {
|
||||
try {
|
||||
console.log(`[Web Vitals] for page ${options.path}`);
|
||||
onFID((metric) => sendToAnalytics(metric, options));
|
||||
onTTFB((metric) => sendToAnalytics(metric, options));
|
||||
onLCP((metric) => sendToAnalytics(metric, options));
|
||||
onCLS((metric) => sendToAnalytics(metric, options));
|
||||
onFCP((metric) => sendToAnalytics(metric, options));
|
||||
} catch (err) {
|
||||
console.error(`[Web Vitals] for page ${options.path}`, err);
|
||||
}
|
||||
}
|
||||
6
examples/sveltekit-1/src/routes/+layout.server.js
Normal file
6
examples/sveltekit-1/src/routes/+layout.server.js
Normal file
@@ -0,0 +1,6 @@
|
||||
import { env } from '$env/dynamic/private';
|
||||
|
||||
/** @type {import('./$types').LayoutServerLoad} */
|
||||
export function load() {
|
||||
return { analyticsId: env.VERCEL_ANALYTICS_ID };
|
||||
}
|
||||
@@ -1,6 +1,20 @@
|
||||
<script>
|
||||
import { browser } from '$app/environment';
|
||||
import { page } from '$app/stores';
|
||||
import { webVitals } from '$lib/vitals';
|
||||
import Header from './Header.svelte';
|
||||
import './styles.css';
|
||||
|
||||
/** @type {import('./$types').LayoutServerData} */
|
||||
export let data;
|
||||
|
||||
$: if (browser && data?.analyticsId) {
|
||||
webVitals({
|
||||
path: $page.url.pathname,
|
||||
params: $page.params,
|
||||
analyticsId: data.analyticsId
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="app">
|
||||
|
||||
@@ -107,11 +107,11 @@
|
||||
<a class="how-to-play" href="/sverdle/how-to-play">How to play</a>
|
||||
|
||||
<div class="grid" class:playing={!won} class:bad-guess={form?.badGuess}>
|
||||
{#each Array(6) as _, row}
|
||||
{#each Array.from(Array(6).keys()) as row (row)}
|
||||
{@const current = row === i}
|
||||
<h2 class="visually-hidden">Row {row + 1}</h2>
|
||||
<div class="row" class:current>
|
||||
{#each Array(5) as _, column}
|
||||
{#each Array.from(Array(5).keys()) as column (column)}
|
||||
{@const answer = data.answers[row]?.[column]}
|
||||
{@const value = data.guesses[row]?.[column] ?? ''}
|
||||
{@const selected = current && column === data.guesses[row].length}
|
||||
|
||||
@@ -2,5 +2,5 @@ import { expect, test } from '@playwright/test';
|
||||
|
||||
test('about page has expected h1', async ({ page }) => {
|
||||
await page.goto('/about');
|
||||
expect(await page.textContent('h1')).toBe('About this app');
|
||||
await expect(page.getByRole('heading', { name: 'About this app' })).toBeVisible();
|
||||
});
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import { sveltekit } from '@sveltejs/kit/vite';
|
||||
import { defineConfig } from 'vitest/config';
|
||||
|
||||
/** @type {import('vite').UserConfig} */
|
||||
const config = {
|
||||
export default defineConfig({
|
||||
plugins: [sveltekit()],
|
||||
test: {
|
||||
include: ['src/**/*.{test,spec}.{js,ts}']
|
||||
}
|
||||
};
|
||||
|
||||
export default config;
|
||||
});
|
||||
|
||||
@@ -6,20 +6,20 @@
|
||||
"lint": "vue-cli-service lint"
|
||||
},
|
||||
"engines": {
|
||||
"node": "16.x"
|
||||
"node": "18.x"
|
||||
},
|
||||
"dependencies": {
|
||||
"core-js": "^3.6.5",
|
||||
"vue": "^3.0.0"
|
||||
"core-js": "^3.30.2",
|
||||
"vue": "^3.3.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vue/cli-plugin-babel": "~4.5.0",
|
||||
"@vue/cli-plugin-eslint": "~4.5.0",
|
||||
"@vue/cli-service": "~4.5.0",
|
||||
"@vue/compiler-sfc": "^3.0.0",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"eslint": "^6.7.2",
|
||||
"eslint-plugin-vue": "^7.0.0"
|
||||
"@vue/cli-plugin-babel": "~5.0.8",
|
||||
"@vue/cli-plugin-eslint": "~5.0.8",
|
||||
"@vue/cli-service": "~5.0.8",
|
||||
"@vue/compiler-sfc": "^3.3.4",
|
||||
"@babel/eslint-parser": "^7.21.8",
|
||||
"eslint": "^8.4.1",
|
||||
"eslint-plugin-vue": "^9.14.0"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"root": true,
|
||||
@@ -31,7 +31,7 @@
|
||||
"eslint:recommended"
|
||||
],
|
||||
"parserOptions": {
|
||||
"parser": "babel-eslint"
|
||||
"parser": "@babel/eslint-parser"
|
||||
},
|
||||
"rules": {}
|
||||
},
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
22
internals/constants/CHANGELOG.md
Normal file
22
internals/constants/CHANGELOG.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# @vercel-internals/constants
|
||||
|
||||
## 1.0.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`346892210`](https://github.com/vercel/vercel/commit/3468922108f411482a72acd0331f0f2ee52a6d4c)]:
|
||||
- @vercel/build-utils@6.8.0
|
||||
|
||||
## 1.0.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`cd35071f6`](https://github.com/vercel/vercel/commit/cd35071f609d615d47bc04634c123b33768436cb)]:
|
||||
- @vercel/build-utils@6.7.5
|
||||
|
||||
## 1.0.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`c7bcea408`](https://github.com/vercel/vercel/commit/c7bcea408131df2d65338e50ce319a6d8e4a8a82)]:
|
||||
- @vercel/build-utils@6.7.4
|
||||
@@ -1,17 +1,18 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "@vercel-internals/constants",
|
||||
"version": "1.0.3",
|
||||
"types": "dist/index.d.ts",
|
||||
"main": "dist/index.js",
|
||||
"scripts": {
|
||||
"build": "tsc -p tsconfig.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vercel/build-utils": "6.3.2",
|
||||
"@vercel/routing-utils": "2.1.10"
|
||||
"@vercel/build-utils": "6.8.0",
|
||||
"@vercel/routing-utils": "2.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vercel-internals/tsconfig": "*",
|
||||
"@vercel-internals/tsconfig": "1.0.0",
|
||||
"@vercel/style-guide": "4.0.2",
|
||||
"typescript": "4.9.4"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "@vercel-internals/get-package-json",
|
||||
"version": "1.0.0",
|
||||
"types": "dist/index.d.ts",
|
||||
"main": "dist/index.js",
|
||||
"files": [
|
||||
@@ -14,7 +15,7 @@
|
||||
"devDependencies": {
|
||||
"@types/jest": "29.5.0",
|
||||
"@types/node": "14.14.31",
|
||||
"@vercel-internals/tsconfig": "*",
|
||||
"@vercel-internals/tsconfig": "1.0.0",
|
||||
"@vercel/style-guide": "4.0.2",
|
||||
"jest": "29.5.0",
|
||||
"ts-jest": "29.1.0",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "@vercel-internals/tsconfig",
|
||||
"version": "1.0.0",
|
||||
"description": "Node.js tsconfig file based on `@vercel/style-guide`",
|
||||
"files": [
|
||||
"tsconfig.json"
|
||||
|
||||
25
internals/types/CHANGELOG.md
Normal file
25
internals/types/CHANGELOG.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# @vercel-internals/types
|
||||
|
||||
## 1.0.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`346892210`](https://github.com/vercel/vercel/commit/3468922108f411482a72acd0331f0f2ee52a6d4c)]:
|
||||
- @vercel/build-utils@6.8.0
|
||||
- @vercel-internals/constants@1.0.3
|
||||
|
||||
## 1.0.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`cd35071f6`](https://github.com/vercel/vercel/commit/cd35071f609d615d47bc04634c123b33768436cb)]:
|
||||
- @vercel/build-utils@6.7.5
|
||||
- @vercel-internals/constants@1.0.2
|
||||
|
||||
## 1.0.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`c7bcea408`](https://github.com/vercel/vercel/commit/c7bcea408131df2d65338e50ce319a6d8e4a8a82)]:
|
||||
- @vercel/build-utils@6.7.4
|
||||
- @vercel-internals/constants@1.0.1
|
||||
94
internals/types/index.d.ts
vendored
94
internals/types/index.d.ts
vendored
@@ -157,6 +157,7 @@ export type Deployment = {
|
||||
errorLink?: string;
|
||||
errorMessage?: string | null;
|
||||
errorStep?: string;
|
||||
forced?: boolean;
|
||||
functions?: BuilderFunctions | null;
|
||||
gitSource?: {
|
||||
org?: string;
|
||||
@@ -183,6 +184,7 @@ export type Deployment = {
|
||||
ownerId?: string;
|
||||
plan?: 'enterprise' | 'hobby' | 'oss' | 'pro';
|
||||
previewCommentsEnabled?: boolean;
|
||||
private?: boolean;
|
||||
projectId?: string;
|
||||
projectSettings?: {
|
||||
buildCommand?: string | null;
|
||||
@@ -353,7 +355,7 @@ export interface Project extends ProjectSettings {
|
||||
link?: ProjectLinkData;
|
||||
alias?: ProjectAliasTarget[];
|
||||
latestDeployments?: Partial<Deployment>[];
|
||||
lastRollbackTarget: RollbackTarget | null;
|
||||
lastAliasRequest?: LastAliasRequest | null;
|
||||
}
|
||||
|
||||
export interface Org {
|
||||
@@ -363,31 +365,77 @@ export interface Org {
|
||||
}
|
||||
|
||||
export interface ProjectLink {
|
||||
/**
|
||||
* ID of the Vercel Project.
|
||||
*/
|
||||
projectId: string;
|
||||
/**
|
||||
* User or Team ID of the owner of the Vercel Project.
|
||||
*/
|
||||
orgId: string;
|
||||
/**
|
||||
* When linked as a repository, contains the absolute path
|
||||
* to the root directory of the repository.
|
||||
*/
|
||||
repoRoot?: string;
|
||||
/**
|
||||
* When linked as a repository, contains the relative path
|
||||
* to the selected project root directory.
|
||||
*/
|
||||
projectRootDirectory?: string;
|
||||
}
|
||||
|
||||
export interface PaginationOptions {
|
||||
prev: number;
|
||||
/**
|
||||
* Amount of items in the current page.
|
||||
* @example 20
|
||||
*/
|
||||
count: number;
|
||||
next?: number;
|
||||
/**
|
||||
* Timestamp that must be used to request the next page.
|
||||
* @example 1540095775951
|
||||
*/
|
||||
next: number | null;
|
||||
/**
|
||||
* Timestamp that must be used to request the previous page.
|
||||
* @example 1540095775951
|
||||
*/
|
||||
prev: number | null;
|
||||
}
|
||||
|
||||
export type ProjectLinkResult =
|
||||
| { status: 'linked'; org: Org; project: Project }
|
||||
| { status: 'not_linked'; org: null; project: null }
|
||||
| {
|
||||
status: 'error';
|
||||
exitCode: number;
|
||||
reason?:
|
||||
| 'HEADLESS'
|
||||
| 'NOT_AUTHORIZED'
|
||||
| 'TEAM_DELETED'
|
||||
| 'PATH_IS_FILE'
|
||||
| 'INVALID_ROOT_DIRECTORY'
|
||||
| 'MISSING_PROJECT_SETTINGS';
|
||||
};
|
||||
export type ProjectLinked = {
|
||||
status: 'linked';
|
||||
org: Org;
|
||||
project: Project;
|
||||
repoRoot?: string;
|
||||
};
|
||||
|
||||
export type ProjectNotLinked = {
|
||||
status: 'not_linked';
|
||||
org: null;
|
||||
project: null;
|
||||
};
|
||||
|
||||
export type ProjectLinkedError = {
|
||||
status: 'error';
|
||||
exitCode: number;
|
||||
reason?:
|
||||
| 'HEADLESS'
|
||||
| 'NOT_AUTHORIZED'
|
||||
| 'TEAM_DELETED'
|
||||
| 'PATH_IS_FILE'
|
||||
| 'INVALID_ROOT_DIRECTORY'
|
||||
| 'MISSING_PROJECT_SETTINGS';
|
||||
};
|
||||
|
||||
export type ProjectLinkResult =
|
||||
| ProjectLinked
|
||||
| ProjectNotLinked
|
||||
| ProjectLinkedError;
|
||||
|
||||
/**
|
||||
* @deprecated - `RollbackJobStatus` has been replace by `LastAliasRequest['jobStatus']`.
|
||||
*/
|
||||
export type RollbackJobStatus =
|
||||
| 'pending'
|
||||
| 'in-progress'
|
||||
@@ -395,6 +443,10 @@ export type RollbackJobStatus =
|
||||
| 'failed'
|
||||
| 'skipped';
|
||||
|
||||
/**
|
||||
* @deprecated - `RollbackTarget` has been renamed to `LastAliasRequest` so it can
|
||||
* be shared with "promote".
|
||||
*/
|
||||
export interface RollbackTarget {
|
||||
fromDeploymentId: string;
|
||||
jobStatus: RollbackJobStatus;
|
||||
@@ -402,6 +454,14 @@ export interface RollbackTarget {
|
||||
toDeploymentId: string;
|
||||
}
|
||||
|
||||
export interface LastAliasRequest {
|
||||
fromDeploymentId: string;
|
||||
jobStatus: 'pending' | 'in-progress' | 'succeeded' | 'failed' | 'skipped';
|
||||
requestedAt: number;
|
||||
toDeploymentId: string;
|
||||
type: 'rollback' | 'promote';
|
||||
}
|
||||
|
||||
export interface Token {
|
||||
id: string;
|
||||
name: string;
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "@vercel-internals/types",
|
||||
"version": "1.0.3",
|
||||
"types": "index.d.ts",
|
||||
"main": "index.d.ts",
|
||||
"dependencies": {
|
||||
"@types/node": "14.14.31",
|
||||
"@vercel-internals/constants": "*",
|
||||
"@vercel/build-utils": "6.3.2",
|
||||
"@vercel/routing-utils": "2.1.10"
|
||||
"@vercel-internals/constants": "1.0.3",
|
||||
"@vercel/build-utils": "6.8.0",
|
||||
"@vercel/routing-utils": "2.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vercel-internals/tsconfig": "*",
|
||||
"@vercel-internals/tsconfig": "1.0.0",
|
||||
"@vercel/style-guide": "4.0.2",
|
||||
"typescript": "4.9.4"
|
||||
}
|
||||
|
||||
13
lerna.json
13
lerna.json
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"npmClient": "pnpm",
|
||||
"useWorkspaces": true,
|
||||
"packages": ["packages/*"],
|
||||
"command": {
|
||||
"publish": {
|
||||
"npmClient": "npm",
|
||||
"allowBranch": ["main"],
|
||||
"registry": "https://registry.npmjs.org/"
|
||||
}
|
||||
},
|
||||
"version": "independent"
|
||||
}
|
||||
20
package.json
20
package.json
@@ -4,10 +4,9 @@
|
||||
"private": true,
|
||||
"license": "Apache-2.0",
|
||||
"packageManager": "pnpm@8.3.1",
|
||||
"dependencies": {
|
||||
"lerna": "5.6.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@changesets/cli": "2.26.1",
|
||||
"@svitejs/changesets-changelog-github-compact": "1.1.0",
|
||||
"@types/node": "14.18.33",
|
||||
"@typescript-eslint/eslint-plugin": "5.21.0",
|
||||
"@typescript-eslint/parser": "5.21.0",
|
||||
@@ -22,6 +21,7 @@
|
||||
"eslint-plugin-jest": "26.1.5",
|
||||
"execa": "3.2.0",
|
||||
"fs-extra": "11.1.0",
|
||||
"glob": "10.2.3",
|
||||
"husky": "7.0.4",
|
||||
"jest": "29.5.0",
|
||||
"json5": "2.1.1",
|
||||
@@ -32,16 +32,10 @@
|
||||
"source-map-support": "0.5.12",
|
||||
"ts-eager": "2.0.2",
|
||||
"ts-jest": "29.1.0",
|
||||
"typescript": "4.9.5",
|
||||
"turbo": "1.9.3"
|
||||
"turbo": "1.10.6",
|
||||
"typescript": "4.9.5"
|
||||
},
|
||||
"scripts": {
|
||||
"lerna": "lerna",
|
||||
"version": "pnpm install && git add pnpm-lock.yaml",
|
||||
"bootstrap": "lerna bootstrap",
|
||||
"publish-stable": "echo 'Run `pnpm changelog` for instructions'",
|
||||
"publish-from-github": "./utils/publish.sh",
|
||||
"changelog": "node utils/changelog.js",
|
||||
"build": "node utils/gen.js && turbo --no-update-notifier run build",
|
||||
"vercel-build": "pnpm build && pnpm run pack && cd api && node -r ts-eager/register ./_lib/script/build.ts",
|
||||
"pre-commit": "lint-staged",
|
||||
@@ -53,7 +47,9 @@
|
||||
"lint": "eslint . --cache --ext .ts,.js",
|
||||
"prettier-check": "prettier --check .",
|
||||
"prepare": "husky install",
|
||||
"pack": "cd utils && node -r ts-eager/register ./pack.ts"
|
||||
"pack": "cd utils && node -r ts-eager/register ./pack.ts",
|
||||
"ci:version": "changeset version && pnpm install --no-frozen-lockfile",
|
||||
"ci:publish": "pnpm publish -r && changeset tag"
|
||||
},
|
||||
"lint-staged": {
|
||||
"./{*,{api,packages,test,utils}/**/*}.{js,ts}": [
|
||||
|
||||
25
packages/build-utils/CHANGELOG.md
Normal file
25
packages/build-utils/CHANGELOG.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# @vercel/build-utils
|
||||
|
||||
## 6.8.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- Add `getNodeBinPaths()` and `traverseUpDirectories()` functions ([#10150](https://github.com/vercel/vercel/pull/10150))
|
||||
|
||||
## 6.7.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Publish missing build-utils ([`cd35071f6`](https://github.com/vercel/vercel/commit/cd35071f609d615d47bc04634c123b33768436cb))
|
||||
|
||||
## 6.7.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Remove usage of `env` from Edge Functions and Middleware ([#10018](https://github.com/vercel/vercel/pull/10018))
|
||||
|
||||
## 6.7.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Deprecate Node.js 14.x and 16.x with warning ([#9976](https://github.com/vercel/vercel/pull/9976))
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/build-utils",
|
||||
"version": "6.7.2",
|
||||
"version": "6.8.0",
|
||||
"license": "Apache-2.0",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.js",
|
||||
|
||||
@@ -27,12 +27,6 @@ export class EdgeFunction {
|
||||
*/
|
||||
files: Files;
|
||||
|
||||
/**
|
||||
* Extra environment variables in use for the user code, to be
|
||||
* assigned to the edge function.
|
||||
*/
|
||||
envVarsInUse?: string[];
|
||||
|
||||
/**
|
||||
* Extra binary files to be included in the edge function
|
||||
*/
|
||||
@@ -50,7 +44,6 @@ export class EdgeFunction {
|
||||
this.deploymentTarget = params.deploymentTarget;
|
||||
this.entrypoint = params.entrypoint;
|
||||
this.files = params.files;
|
||||
this.envVarsInUse = params.envVarsInUse;
|
||||
this.assets = params.assets;
|
||||
this.regions = params.regions;
|
||||
this.framework = params.framework;
|
||||
|
||||
@@ -6,8 +6,18 @@ import debug from '../debug';
|
||||
function getOptions() {
|
||||
const options = [
|
||||
{ major: 18, range: '18.x', runtime: 'nodejs18.x' },
|
||||
{ major: 16, range: '16.x', runtime: 'nodejs16.x' },
|
||||
{ major: 14, range: '14.x', runtime: 'nodejs14.x' },
|
||||
{
|
||||
major: 16,
|
||||
range: '16.x',
|
||||
runtime: 'nodejs16.x',
|
||||
discontinueDate: new Date('2023-08-15'),
|
||||
},
|
||||
{
|
||||
major: 14,
|
||||
range: '14.x',
|
||||
runtime: 'nodejs14.x',
|
||||
discontinueDate: new Date('2023-08-15'),
|
||||
},
|
||||
{
|
||||
major: 12,
|
||||
range: '12.x',
|
||||
|
||||
@@ -44,23 +44,33 @@ export interface ScanParentDirsResult {
|
||||
lockfileVersion?: number;
|
||||
}
|
||||
|
||||
export interface WalkParentDirsProps {
|
||||
export interface TraverseUpDirectoriesProps {
|
||||
/**
|
||||
* The highest directory, typically the workPath root of the project.
|
||||
* If this directory is reached and it doesn't contain the file, null is returned.
|
||||
*/
|
||||
base: string;
|
||||
/**
|
||||
* The directory to start searching, typically the same directory of the entrypoint.
|
||||
* If this directory doesn't contain the file, the parent is checked, etc.
|
||||
* The directory to start iterating from, typically the same directory of the entrypoint.
|
||||
*/
|
||||
start: string;
|
||||
/**
|
||||
* The highest directory, typically the workPath root of the project.
|
||||
*/
|
||||
base?: string;
|
||||
}
|
||||
|
||||
export interface WalkParentDirsProps
|
||||
extends Required<TraverseUpDirectoriesProps> {
|
||||
/**
|
||||
* The name of the file to search for, typically `package.json` or `Gemfile`.
|
||||
*/
|
||||
filename: string;
|
||||
}
|
||||
|
||||
export interface WalkParentDirsMultiProps
|
||||
extends Required<TraverseUpDirectoriesProps> {
|
||||
/**
|
||||
* The name of the file to search for, typically `package.json` or `Gemfile`.
|
||||
*/
|
||||
filenames: string[];
|
||||
}
|
||||
|
||||
export interface SpawnOptionsExtended extends SpawnOptions {
|
||||
/**
|
||||
* Pretty formatted command that is being spawned for logging purposes.
|
||||
@@ -131,6 +141,24 @@ export async function execCommand(command: string, options: SpawnOptions = {}) {
|
||||
return true;
|
||||
}
|
||||
|
||||
export function* traverseUpDirectories({
|
||||
start,
|
||||
base,
|
||||
}: TraverseUpDirectoriesProps) {
|
||||
let current: string | undefined = path.normalize(start);
|
||||
const normalizedRoot = base ? path.normalize(base) : undefined;
|
||||
while (current) {
|
||||
yield current;
|
||||
if (current === normalizedRoot) break;
|
||||
// Go up one directory
|
||||
const next = path.join(current, '..');
|
||||
current = next === current ? undefined : next;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use `getNodeBinPaths()` instead.
|
||||
*/
|
||||
export async function getNodeBinPath({
|
||||
cwd,
|
||||
}: {
|
||||
@@ -141,6 +169,15 @@ export async function getNodeBinPath({
|
||||
return path.join(dir, 'node_modules', '.bin');
|
||||
}
|
||||
|
||||
export function getNodeBinPaths({
|
||||
start,
|
||||
base,
|
||||
}: TraverseUpDirectoriesProps): string[] {
|
||||
return Array.from(traverseUpDirectories({ start, base })).map(dir =>
|
||||
path.join(dir, 'node_modules/.bin')
|
||||
);
|
||||
}
|
||||
|
||||
async function chmodPlusX(fsPath: string) {
|
||||
const s = await fs.stat(fsPath);
|
||||
const newMode = s.mode | 64 | 8 | 1; // eslint-disable-line no-bitwise
|
||||
@@ -297,22 +334,14 @@ export async function walkParentDirs({
|
||||
}: WalkParentDirsProps): Promise<string | null> {
|
||||
assert(path.isAbsolute(base), 'Expected "base" to be absolute path');
|
||||
assert(path.isAbsolute(start), 'Expected "start" to be absolute path');
|
||||
let parent = '';
|
||||
|
||||
for (let current = start; base.length <= current.length; current = parent) {
|
||||
const fullPath = path.join(current, filename);
|
||||
for (const dir of traverseUpDirectories({ start, base })) {
|
||||
const fullPath = path.join(dir, filename);
|
||||
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
if (await fs.pathExists(fullPath)) {
|
||||
return fullPath;
|
||||
}
|
||||
|
||||
parent = path.dirname(current);
|
||||
|
||||
if (parent === current) {
|
||||
// Reached root directory of the filesystem
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -322,14 +351,9 @@ async function walkParentDirsMulti({
|
||||
base,
|
||||
start,
|
||||
filenames,
|
||||
}: {
|
||||
base: string;
|
||||
start: string;
|
||||
filenames: string[];
|
||||
}): Promise<(string | undefined)[]> {
|
||||
let parent = '';
|
||||
for (let current = start; base.length <= current.length; current = parent) {
|
||||
const fullPaths = filenames.map(f => path.join(current, f));
|
||||
}: WalkParentDirsMultiProps): Promise<(string | undefined)[]> {
|
||||
for (const dir of traverseUpDirectories({ start, base })) {
|
||||
const fullPaths = filenames.map(f => path.join(dir, f));
|
||||
const existResults = await Promise.all(
|
||||
fullPaths.map(f => fs.pathExists(f))
|
||||
);
|
||||
@@ -338,13 +362,6 @@ async function walkParentDirsMulti({
|
||||
if (foundOneOrMore) {
|
||||
return fullPaths.map((f, i) => (existResults[i] ? f : undefined));
|
||||
}
|
||||
|
||||
parent = path.dirname(current);
|
||||
|
||||
if (parent === current) {
|
||||
// Reached root directory of the filesystem
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return [];
|
||||
|
||||
@@ -30,7 +30,9 @@ import {
|
||||
getNodeVersion,
|
||||
getSpawnOptions,
|
||||
getNodeBinPath,
|
||||
getNodeBinPaths,
|
||||
scanParentDirs,
|
||||
traverseUpDirectories,
|
||||
} from './fs/run-user-scripts';
|
||||
import {
|
||||
getLatestNodeVersion,
|
||||
@@ -43,6 +45,7 @@ import { getPlatformEnv } from './get-platform-env';
|
||||
import { getPrefixedEnvVars } from './get-prefixed-env-vars';
|
||||
import { cloneEnv } from './clone-env';
|
||||
import { hardLinkDir } from './hard-link-dir';
|
||||
import { validateNpmrc } from './validate-npmrc';
|
||||
|
||||
export {
|
||||
FileBlob,
|
||||
@@ -67,6 +70,7 @@ export {
|
||||
spawnCommand,
|
||||
walkParentDirs,
|
||||
getNodeBinPath,
|
||||
getNodeBinPaths,
|
||||
runNpmInstall,
|
||||
runBundleInstall,
|
||||
runPipInstall,
|
||||
@@ -88,6 +92,8 @@ export {
|
||||
getIgnoreFilter,
|
||||
cloneEnv,
|
||||
hardLinkDir,
|
||||
traverseUpDirectories,
|
||||
validateNpmrc,
|
||||
};
|
||||
|
||||
export { EdgeFunction } from './edge-function';
|
||||
|
||||
26
packages/build-utils/src/validate-npmrc.ts
Normal file
26
packages/build-utils/src/validate-npmrc.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { join } from 'path';
|
||||
import { readFile } from 'fs/promises';
|
||||
|
||||
/**
|
||||
* Checks if there is a `.npmrc` in the cwd (project root) and makes sure it
|
||||
* doesn't contain a `use-node-version`. This config setting is not supported
|
||||
* since it causes the package manager to install the Node.js version which in
|
||||
* the case of newer Node.js versions is not compatible with AWS due to
|
||||
* outdated GLIBC binaries.
|
||||
*
|
||||
* @see https://pnpm.io/npmrc#use-node-version
|
||||
*
|
||||
* @param cwd The current working directory (e.g. project root);
|
||||
*/
|
||||
export async function validateNpmrc(cwd: string): Promise<void> {
|
||||
const npmrc = await readFile(join(cwd, '.npmrc'), 'utf-8').catch(err => {
|
||||
if (err.code !== 'ENOENT') throw err;
|
||||
});
|
||||
|
||||
const nodeRegExp = /(?<!#.*)use-node-version/;
|
||||
if (npmrc?.match(nodeRegExp)) {
|
||||
throw new Error(
|
||||
'Detected unsupported "use-node-version" in your ".npmrc". Please use "engines" in your "package.json" instead.'
|
||||
);
|
||||
}
|
||||
}
|
||||
2
packages/build-utils/test/fixtures/29-npmrc/comment-use-node-version/.npmrc
vendored
Normal file
2
packages/build-utils/test/fixtures/29-npmrc/comment-use-node-version/.npmrc
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
foo=bar
|
||||
# use-node-version=16.16.0
|
||||
1
packages/build-utils/test/fixtures/29-npmrc/good/.npmrc
vendored
Normal file
1
packages/build-utils/test/fixtures/29-npmrc/good/.npmrc
vendored
Normal file
@@ -0,0 +1 @@
|
||||
foo=bar
|
||||
3
packages/build-utils/test/fixtures/29-npmrc/has-use-node-version/.npmrc
vendored
Normal file
3
packages/build-utils/test/fixtures/29-npmrc/has-use-node-version/.npmrc
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
foo=bar
|
||||
# the next line is not supported
|
||||
use-node-version=16.16.0
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"private": true,
|
||||
"engines": {
|
||||
"node": "16.14.0"
|
||||
"node": "18.2.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"private": true,
|
||||
"engines": {
|
||||
"node": "14.x"
|
||||
"node": "18.x"
|
||||
}
|
||||
}
|
||||
|
||||
17
packages/build-utils/test/unit.get-node-bin-paths.test.ts
vendored
Normal file
17
packages/build-utils/test/unit.get-node-bin-paths.test.ts
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
import { join } from 'path';
|
||||
import { getNodeBinPaths } from '../src/fs/run-user-scripts';
|
||||
|
||||
describe('getNodeBinPaths()', () => {
|
||||
const cwd = process.cwd();
|
||||
|
||||
it('should return array of `node_modules/.bin` paths', () => {
|
||||
const start = join(cwd, 'foo/bar/baz');
|
||||
const paths = getNodeBinPaths({ start, base: cwd });
|
||||
expect(paths).toEqual([
|
||||
join(cwd, 'foo/bar/baz/node_modules/.bin'),
|
||||
join(cwd, 'foo/bar/node_modules/.bin'),
|
||||
join(cwd, 'foo/node_modules/.bin'),
|
||||
join(cwd, 'node_modules/.bin'),
|
||||
]);
|
||||
});
|
||||
});
|
||||
66
packages/build-utils/test/unit.test.ts
vendored
66
packages/build-utils/test/unit.test.ts
vendored
@@ -140,20 +140,20 @@ it('should ignore node version in vercel dev getNodeVersion()', async () => {
|
||||
|
||||
it('should select project setting from config when no package.json is found and fallback undefined', async () => {
|
||||
expect(
|
||||
await getNodeVersion('/tmp', undefined, { nodeVersion: '16.x' }, {})
|
||||
).toHaveProperty('range', '16.x');
|
||||
await getNodeVersion('/tmp', undefined, { nodeVersion: '18.x' }, {})
|
||||
).toHaveProperty('range', '18.x');
|
||||
expect(warningMessages).toStrictEqual([]);
|
||||
});
|
||||
|
||||
it('should select project setting from config when no package.json is found and fallback is null', async () => {
|
||||
expect(
|
||||
await getNodeVersion('/tmp', null as any, { nodeVersion: '16.x' }, {})
|
||||
).toHaveProperty('range', '16.x');
|
||||
await getNodeVersion('/tmp', null as any, { nodeVersion: '18.x' }, {})
|
||||
).toHaveProperty('range', '18.x');
|
||||
expect(warningMessages).toStrictEqual([]);
|
||||
});
|
||||
|
||||
it('should select project setting from fallback when no package.json is found', async () => {
|
||||
expect(await getNodeVersion('/tmp', '16.x')).toHaveProperty('range', '16.x');
|
||||
expect(await getNodeVersion('/tmp', '18.x')).toHaveProperty('range', '18.x');
|
||||
expect(warningMessages).toStrictEqual([]);
|
||||
});
|
||||
|
||||
@@ -165,9 +165,9 @@ it('should prefer package.json engines over project setting from config and warn
|
||||
{ nodeVersion: '12.x' },
|
||||
{}
|
||||
)
|
||||
).toHaveProperty('range', '14.x');
|
||||
).toHaveProperty('range', '18.x');
|
||||
expect(warningMessages).toStrictEqual([
|
||||
'Warning: Due to "engines": { "node": "14.x" } in your `package.json` file, the Node.js Version defined in your Project Settings ("12.x") will not apply. Learn More: http://vercel.link/node-version',
|
||||
'Warning: Due to "engines": { "node": "18.x" } in your `package.json` file, the Node.js Version defined in your Project Settings ("12.x") will not apply. Learn More: http://vercel.link/node-version',
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -179,9 +179,9 @@ it('should warn when package.json engines is exact version', async () => {
|
||||
{},
|
||||
{}
|
||||
)
|
||||
).toHaveProperty('range', '16.x');
|
||||
).toHaveProperty('range', '18.x');
|
||||
expect(warningMessages).toStrictEqual([
|
||||
'Warning: Detected "engines": { "node": "16.14.0" } in your `package.json` with major.minor.patch, but only major Node.js Version can be selected. Learn More: http://vercel.link/node-version',
|
||||
'Warning: Detected "engines": { "node": "18.2.0" } in your `package.json` with major.minor.patch, but only major Node.js Version can be selected. Learn More: http://vercel.link/node-version',
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -204,30 +204,30 @@ it('should not warn when package.json engines matches project setting from confi
|
||||
await getNodeVersion(
|
||||
path.join(__dirname, 'pkg-engine-node'),
|
||||
undefined,
|
||||
{ nodeVersion: '14' },
|
||||
{ nodeVersion: '18' },
|
||||
{}
|
||||
)
|
||||
).toHaveProperty('range', '14.x');
|
||||
).toHaveProperty('range', '18.x');
|
||||
expect(warningMessages).toStrictEqual([]);
|
||||
|
||||
expect(
|
||||
await getNodeVersion(
|
||||
path.join(__dirname, 'pkg-engine-node'),
|
||||
undefined,
|
||||
{ nodeVersion: '14.x' },
|
||||
{ nodeVersion: '18.x' },
|
||||
{}
|
||||
)
|
||||
).toHaveProperty('range', '14.x');
|
||||
).toHaveProperty('range', '18.x');
|
||||
expect(warningMessages).toStrictEqual([]);
|
||||
|
||||
expect(
|
||||
await getNodeVersion(
|
||||
path.join(__dirname, 'pkg-engine-node'),
|
||||
undefined,
|
||||
{ nodeVersion: '<15' },
|
||||
{ nodeVersion: '<19' },
|
||||
{}
|
||||
)
|
||||
).toHaveProperty('range', '14.x');
|
||||
).toHaveProperty('range', '18.x');
|
||||
expect(warningMessages).toStrictEqual([]);
|
||||
});
|
||||
|
||||
@@ -238,7 +238,7 @@ it('should get latest node version', async () => {
|
||||
it('should throw for discontinued versions', async () => {
|
||||
// Mock a future date so that Node 8 and 10 become discontinued
|
||||
const realDateNow = Date.now.bind(global.Date);
|
||||
global.Date.now = () => new Date('2022-10-15').getTime();
|
||||
global.Date.now = () => new Date('2023-10-01').getTime();
|
||||
|
||||
expect(getSupportedNodeVersion('8.10.x', false)).rejects.toThrow();
|
||||
expect(getSupportedNodeVersion('8.10.x', true)).rejects.toThrow();
|
||||
@@ -246,12 +246,18 @@ it('should throw for discontinued versions', async () => {
|
||||
expect(getSupportedNodeVersion('10.x', true)).rejects.toThrow();
|
||||
expect(getSupportedNodeVersion('12.x', false)).rejects.toThrow();
|
||||
expect(getSupportedNodeVersion('12.x', true)).rejects.toThrow();
|
||||
expect(getSupportedNodeVersion('14.x', false)).rejects.toThrow();
|
||||
expect(getSupportedNodeVersion('14.x', true)).rejects.toThrow();
|
||||
expect(getSupportedNodeVersion('16.x', false)).rejects.toThrow();
|
||||
expect(getSupportedNodeVersion('16.x', true)).rejects.toThrow();
|
||||
|
||||
const discontinued = getDiscontinuedNodeVersions();
|
||||
expect(discontinued.length).toBe(3);
|
||||
expect(discontinued[0]).toHaveProperty('range', '12.x');
|
||||
expect(discontinued[1]).toHaveProperty('range', '10.x');
|
||||
expect(discontinued[2]).toHaveProperty('range', '8.10.x');
|
||||
expect(discontinued.length).toBe(5);
|
||||
expect(discontinued[0]).toHaveProperty('range', '16.x');
|
||||
expect(discontinued[1]).toHaveProperty('range', '14.x');
|
||||
expect(discontinued[2]).toHaveProperty('range', '12.x');
|
||||
expect(discontinued[3]).toHaveProperty('range', '10.x');
|
||||
expect(discontinued[4]).toHaveProperty('range', '8.10.x');
|
||||
|
||||
global.Date.now = realDateNow;
|
||||
});
|
||||
@@ -277,11 +283,31 @@ it('should warn for deprecated versions, soon to be discontinued', async () => {
|
||||
'major',
|
||||
12
|
||||
);
|
||||
expect(await getSupportedNodeVersion('14.x', false)).toHaveProperty(
|
||||
'major',
|
||||
14
|
||||
);
|
||||
expect(await getSupportedNodeVersion('14.x', true)).toHaveProperty(
|
||||
'major',
|
||||
14
|
||||
);
|
||||
expect(await getSupportedNodeVersion('16.x', false)).toHaveProperty(
|
||||
'major',
|
||||
16
|
||||
);
|
||||
expect(await getSupportedNodeVersion('16.x', true)).toHaveProperty(
|
||||
'major',
|
||||
16
|
||||
);
|
||||
expect(warningMessages).toStrictEqual([
|
||||
'Error: Node.js version 10.x has reached End-of-Life. Deployments created on or after 2021-04-20 will fail to build. Please set "engines": { "node": "18.x" } in your `package.json` file to use Node.js 18.',
|
||||
'Error: Node.js version 10.x has reached End-of-Life. Deployments created on or after 2021-04-20 will fail to build. Please set Node.js Version to 18.x in your Project Settings to use Node.js 18.',
|
||||
'Error: Node.js version 12.x has reached End-of-Life. Deployments created on or after 2022-10-03 will fail to build. Please set "engines": { "node": "18.x" } in your `package.json` file to use Node.js 18.',
|
||||
'Error: Node.js version 12.x has reached End-of-Life. Deployments created on or after 2022-10-03 will fail to build. Please set Node.js Version to 18.x in your Project Settings to use Node.js 18.',
|
||||
'Error: Node.js version 14.x has reached End-of-Life. Deployments created on or after 2023-08-15 will fail to build. Please set "engines": { "node": "18.x" } in your `package.json` file to use Node.js 18.',
|
||||
'Error: Node.js version 14.x has reached End-of-Life. Deployments created on or after 2023-08-15 will fail to build. Please set Node.js Version to 18.x in your Project Settings to use Node.js 18.',
|
||||
'Error: Node.js version 16.x has reached End-of-Life. Deployments created on or after 2023-08-15 will fail to build. Please set "engines": { "node": "18.x" } in your `package.json` file to use Node.js 18.',
|
||||
'Error: Node.js version 16.x has reached End-of-Life. Deployments created on or after 2023-08-15 will fail to build. Please set Node.js Version to 18.x in your Project Settings to use Node.js 18.',
|
||||
]);
|
||||
|
||||
global.Date.now = realDateNow;
|
||||
|
||||
50
packages/build-utils/test/unit.traverse-up-directories.test.ts
vendored
Normal file
50
packages/build-utils/test/unit.traverse-up-directories.test.ts
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
import { traverseUpDirectories } from '../src/fs/run-user-scripts';
|
||||
|
||||
const isWindows = process.platform === 'win32';
|
||||
|
||||
describe('traverseUpDirectories()', () => {
|
||||
test.each(
|
||||
isWindows
|
||||
? [
|
||||
{
|
||||
start: 'C:\\foo\\bar\\baz',
|
||||
expected: ['C:\\foo\\bar\\baz', 'C:\\foo\\bar', 'C:\\foo', 'C:\\'],
|
||||
},
|
||||
{
|
||||
start: 'C:\\foo\\..\\bar\\.\\baz',
|
||||
expected: ['C:\\bar\\baz', 'C:\\bar', 'C:\\'],
|
||||
},
|
||||
{
|
||||
start: 'C:\\foo\\bar\\baz\\another',
|
||||
base: 'C:\\foo\\bar',
|
||||
expected: [
|
||||
'C:\\foo\\bar\\baz\\another',
|
||||
'C:\\foo\\bar\\baz',
|
||||
'C:\\foo\\bar',
|
||||
],
|
||||
},
|
||||
]
|
||||
: [
|
||||
{
|
||||
start: '/foo/bar/baz',
|
||||
expected: ['/foo/bar/baz', '/foo/bar', '/foo', '/'],
|
||||
},
|
||||
{
|
||||
start: '/foo/../bar/./baz',
|
||||
expected: ['/bar/baz', '/bar', '/'],
|
||||
},
|
||||
{
|
||||
start: '/foo/bar/baz/another',
|
||||
base: '/foo/bar',
|
||||
expected: ['/foo/bar/baz/another', '/foo/bar/baz', '/foo/bar'],
|
||||
},
|
||||
]
|
||||
)(
|
||||
'should traverse start="$start", base="$base"',
|
||||
({ start, base, expected }) => {
|
||||
expect(Array.from(traverseUpDirectories({ start, base }))).toEqual(
|
||||
expected
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
22
packages/build-utils/test/unit.validate-npmrc.test.ts
vendored
Normal file
22
packages/build-utils/test/unit.validate-npmrc.test.ts
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
import { join } from 'path';
|
||||
import { validateNpmrc } from '../src/validate-npmrc';
|
||||
|
||||
const fixture = (name: string) => join(__dirname, 'fixtures', '29-npmrc', name);
|
||||
|
||||
describe('validateNpmrc', () => {
|
||||
it('should not error with no use-node-version', async () => {
|
||||
await expect(validateNpmrc(fixture('good'))).resolves.toBe(undefined);
|
||||
});
|
||||
|
||||
it('should throw when use-node-version is found', async () => {
|
||||
await expect(
|
||||
validateNpmrc(fixture('has-use-node-version'))
|
||||
).rejects.toThrow('Detected unsupported');
|
||||
});
|
||||
|
||||
it('should not error when use-node-version is commented out', async () => {
|
||||
await expect(
|
||||
validateNpmrc(fixture('comment-use-node-version'))
|
||||
).resolves.toBe(undefined);
|
||||
});
|
||||
});
|
||||
200
packages/cli/CHANGELOG.md
Normal file
200
packages/cli/CHANGELOG.md
Normal file
@@ -0,0 +1,200 @@
|
||||
# vercel
|
||||
|
||||
## 31.0.0
|
||||
|
||||
### Major Changes
|
||||
|
||||
- Update `vc dev` redirect response to match production behavior ([#10143](https://github.com/vercel/vercel/pull/10143))
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- require `--yes` to promote preview deployment ([#10135](https://github.com/vercel/vercel/pull/10135))
|
||||
|
||||
- [cli] Optimize write build result for vc build ([#10154](https://github.com/vercel/vercel/pull/10154))
|
||||
|
||||
- Only show relevant Project matches in Project selector ([#10114](https://github.com/vercel/vercel/pull/10114))
|
||||
|
||||
- [cli] Fix error message when token is invalid ([#10131](https://github.com/vercel/vercel/pull/10131))
|
||||
|
||||
- Updated dependencies [[`e4895d979`](https://github.com/vercel/vercel/commit/e4895d979b57e369e0618481c5974243887d72cc), [`346892210`](https://github.com/vercel/vercel/commit/3468922108f411482a72acd0331f0f2ee52a6d4c), [`346892210`](https://github.com/vercel/vercel/commit/3468922108f411482a72acd0331f0f2ee52a6d4c), [`a6de052ed`](https://github.com/vercel/vercel/commit/a6de052ed2f09cc80bf4c2d0f06bedd267a63cdc)]:
|
||||
- @vercel/next@3.8.7
|
||||
- @vercel/static-build@1.3.38
|
||||
- @vercel/build-utils@6.8.0
|
||||
- @vercel/remix-builder@1.8.15
|
||||
- @vercel/node@2.15.3
|
||||
|
||||
## 30.2.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [cli] do not force auto-assign value on deployments ([#10110](https://github.com/vercel/vercel/pull/10110))
|
||||
|
||||
- Updated dependencies [[`91406abdb`](https://github.com/vercel/vercel/commit/91406abdb0c332152fc6c7c1e4bd3a872b084434), [`2230ea6cc`](https://github.com/vercel/vercel/commit/2230ea6cc1b84c1f03227a4e197b7684635b5955), [`8b3a4146a`](https://github.com/vercel/vercel/commit/8b3a4146af68d2b7288c80a5b919d832dba929b5)]:
|
||||
- @vercel/node@2.15.2
|
||||
- @vercel/remix-builder@1.8.14
|
||||
- @vercel/static-build@1.3.37
|
||||
|
||||
## 30.2.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [cli] vc env pull should add `.env*.local` to `.gitignore` ([#10085](https://github.com/vercel/vercel/pull/10085))
|
||||
|
||||
- [cli] Fix team validation bug where you are apart of a team ([#10092](https://github.com/vercel/vercel/pull/10092))
|
||||
|
||||
- Add support for `vc dev` command with repo link ([#10082](https://github.com/vercel/vercel/pull/10082))
|
||||
|
||||
- Add support for `vc deploy --prebuilt` command with repo link ([#10083](https://github.com/vercel/vercel/pull/10083))
|
||||
|
||||
- Move readme copy logic to a helper function for `vc link` ([#10084](https://github.com/vercel/vercel/pull/10084))
|
||||
|
||||
- Add support for `vc pull` command with repo link ([#10078](https://github.com/vercel/vercel/pull/10078))
|
||||
|
||||
- Add support for `vc build` command with repo link ([#10075](https://github.com/vercel/vercel/pull/10075))
|
||||
|
||||
## 30.2.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`a04bf557f`](https://github.com/vercel/vercel/commit/a04bf557fc6e1080a117428977d0993dec78b004)]:
|
||||
- @vercel/node@2.15.1
|
||||
- @vercel/static-build@1.3.36
|
||||
|
||||
## 30.2.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [node] Add isomorphic functions ([#9947](https://github.com/vercel/vercel/pull/9947))
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Add `client.fetchPaginated()` helper function ([#10054](https://github.com/vercel/vercel/pull/10054))
|
||||
|
||||
- Updated dependencies [[`bc5afe24c`](https://github.com/vercel/vercel/commit/bc5afe24c4547dbf798b939199e8212c4b34038e), [`49c717856`](https://github.com/vercel/vercel/commit/49c7178567ec5bcebe633b598c8c9c0e1aa40fbb), [`0039c8b5c`](https://github.com/vercel/vercel/commit/0039c8b5cea975316a62c4f6aaca5d66d731cc0d)]:
|
||||
- @vercel/node@2.15.0
|
||||
- @vercel/remix-builder@1.8.13
|
||||
- @vercel/static-build@1.3.35
|
||||
|
||||
## 30.1.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Publish missing build-utils ([`cd35071f6`](https://github.com/vercel/vercel/commit/cd35071f609d615d47bc04634c123b33768436cb))
|
||||
|
||||
- Updated dependencies [[`cd35071f6`](https://github.com/vercel/vercel/commit/cd35071f609d615d47bc04634c123b33768436cb)]:
|
||||
- @vercel/build-utils@6.7.5
|
||||
- @vercel/node@2.14.5
|
||||
- @vercel/remix-builder@1.8.12
|
||||
- @vercel/static-build@1.3.34
|
||||
|
||||
## 30.1.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [cli] vc build ignore '.env\*' & ignore files for '@vercel/static' ([#10056](https://github.com/vercel/vercel/pull/10056))
|
||||
|
||||
- [cli] Ensure .npmrc does not contain use-node-version ([#10049](https://github.com/vercel/vercel/pull/10049))
|
||||
|
||||
## 30.1.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- New `vc promote` command ([#9984](https://github.com/vercel/vercel/pull/9984))
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Support `deploy` subcommand in "repo linked" mode ([#10013](https://github.com/vercel/vercel/pull/10013))
|
||||
|
||||
- [cli] Update `vc rollback` to use `lastRequestAlias` instead of `lastRollbackTarget` ([#10019](https://github.com/vercel/vercel/pull/10019))
|
||||
|
||||
- Fix `--cwd` flag with a relative path for `env`, `link`, `promote`, and `rollback` subcommands ([#10031](https://github.com/vercel/vercel/pull/10031))
|
||||
|
||||
- Updated dependencies [[`c6c19354e`](https://github.com/vercel/vercel/commit/c6c19354e852cfc1338b223058c4b07fdc71c723), [`b56ac2717`](https://github.com/vercel/vercel/commit/b56ac2717d6769eb400f9746f0a05431929b4501), [`c63679ea0`](https://github.com/vercel/vercel/commit/c63679ea0a6bc48c0759ccf3c0c0a8106bd324f0), [`c7bcea408`](https://github.com/vercel/vercel/commit/c7bcea408131df2d65338e50ce319a6d8e4a8a82)]:
|
||||
- @vercel/next@3.8.6
|
||||
- @vercel/build-utils@6.7.4
|
||||
- @vercel/node@2.14.4
|
||||
- @vercel/remix-builder@1.8.11
|
||||
- @vercel/static-build@1.3.33
|
||||
|
||||
## 30.0.0
|
||||
|
||||
### Major Changes
|
||||
|
||||
- Change `vc env pull` default output file to `.env.local` ([#9892](https://github.com/vercel/vercel/pull/9892))
|
||||
|
||||
- Remove `--platform-version` global common arg ([#9807](https://github.com/vercel/vercel/pull/9807))
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [cli] implement `vc deploy --prod --skip-build` ([#9836](https://github.com/vercel/vercel/pull/9836))
|
||||
|
||||
- New `vc redeploy` command ([#9956](https://github.com/vercel/vercel/pull/9956))
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Fix `vercel git connect` command when passing a URL parameter ([#9967](https://github.com/vercel/vercel/pull/9967))
|
||||
|
||||
## 29.4.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- Add `vercel link --repo` flag to link to repository (multiple projects), rather than an individual project (alpha) ([#8931](https://github.com/vercel/vercel/pull/8931))
|
||||
|
||||
## 29.3.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @vercel/static-build@1.3.32
|
||||
|
||||
## 29.3.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`2c950d47a`](https://github.com/vercel/vercel/commit/2c950d47aeb22a3de16f983259ea6f37a4555189), [`71b9f3a94`](https://github.com/vercel/vercel/commit/71b9f3a94b7922607f8f24bf7b2bd1742e62cc05), [`f00b08a82`](https://github.com/vercel/vercel/commit/f00b08a82085c3a63059f34f67f10ced92f2979c)]:
|
||||
- @vercel/static-build@1.3.31
|
||||
- @vercel/build-utils@6.7.3
|
||||
- @vercel/next@3.8.5
|
||||
- @vercel/node@2.14.3
|
||||
- @vercel/remix-builder@1.8.10
|
||||
|
||||
## 29.3.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`67e556bc8`](https://github.com/vercel/vercel/commit/67e556bc80c821c233120a2ec1611adb8e195baa), [`ba10fb4dd`](https://github.com/vercel/vercel/commit/ba10fb4dd4155a75df79b98a0c43a6c42eac7b62)]:
|
||||
- @vercel/remix-builder@1.8.9
|
||||
- @vercel/next@3.8.4
|
||||
|
||||
## 29.3.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`6c6f3ce9d`](https://github.com/vercel/vercel/commit/6c6f3ce9d228b1e038641e4bafb38c3487e7dff7)]:
|
||||
- @vercel/next@3.8.3
|
||||
|
||||
## 29.3.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [vc dev] Fix serverless function size limit condition ([#9961](https://github.com/vercel/vercel/pull/9961))
|
||||
|
||||
## 29.3.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Sort environment variables alphabetically in `vercel env pull` ([#9949](https://github.com/vercel/vercel/pull/9949))
|
||||
- Skip 50MB zip size limit for Python ([#9944](https://github.com/vercel/vercel/pull/9944))
|
||||
|
||||
## 29.3.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [cli] remove `vc rollback` beta label ([#9928](https://github.com/vercel/vercel/pull/9928))
|
||||
|
||||
## 29.2.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`6d5983eaa`](https://github.com/vercel/vercel/commit/6d5983eaaefe3fd2204f49c3228718ac64a452e3)]:
|
||||
- @vercel/remix-builder@1.8.8
|
||||
@@ -10,9 +10,7 @@
|
||||
|
||||
## Usage
|
||||
|
||||
Vercel is the platform for frontend developers, providing the speed and reliability innovators need to create at the moment of inspiration.
|
||||
|
||||
We enable teams to iterate quickly and develop, preview, and ship delightful user experiences. Vercel has zero-configuration support for 35+ frontend frameworks and integrates with your headless content, commerce, or database of choice.
|
||||
Vercel's frontend cloud gives developers frameworks, workflows, and infrastructure to build a faster, more personalized web.
|
||||
|
||||
To install the latest version of Vercel CLI, run this command:
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "vercel",
|
||||
"version": "29.1.1",
|
||||
"version": "31.0.0",
|
||||
"preferGlobal": true,
|
||||
"license": "Apache-2.0",
|
||||
"description": "The command-line interface for Vercel",
|
||||
@@ -32,19 +32,20 @@
|
||||
"node": ">= 14"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vercel/build-utils": "6.7.2",
|
||||
"@vercel/build-utils": "6.8.0",
|
||||
"@vercel/go": "2.5.1",
|
||||
"@vercel/hydrogen": "0.0.64",
|
||||
"@vercel/next": "3.8.2",
|
||||
"@vercel/node": "2.14.1",
|
||||
"@vercel/next": "3.8.7",
|
||||
"@vercel/node": "2.15.3",
|
||||
"@vercel/python": "3.1.60",
|
||||
"@vercel/redwood": "1.1.15",
|
||||
"@vercel/remix-builder": "1.8.7",
|
||||
"@vercel/remix-builder": "1.8.15",
|
||||
"@vercel/ruby": "1.3.76",
|
||||
"@vercel/static-build": "1.3.29"
|
||||
"@vercel/static-build": "1.3.38"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@alex_neo/jest-expect-message": "1.0.5",
|
||||
"@edge-runtime/node-utils": "2.1.0",
|
||||
"@next/env": "11.1.2",
|
||||
"@sentry/node": "5.5.0",
|
||||
"@sindresorhus/slugify": "0.11.0",
|
||||
@@ -81,16 +82,16 @@
|
||||
"@types/title": "3.4.1",
|
||||
"@types/universal-analytics": "0.4.2",
|
||||
"@types/update-notifier": "5.1.0",
|
||||
"@types/which": "1.3.2",
|
||||
"@types/which": "3.0.0",
|
||||
"@types/write-json-file": "2.2.1",
|
||||
"@types/yauzl-promise": "2.1.0",
|
||||
"@vercel-internals/constants": "*",
|
||||
"@vercel-internals/get-package-json": "*",
|
||||
"@vercel-internals/types": "*",
|
||||
"@vercel/client": "12.4.12",
|
||||
"@vercel-internals/constants": "1.0.3",
|
||||
"@vercel-internals/get-package-json": "1.0.0",
|
||||
"@vercel-internals/types": "1.0.3",
|
||||
"@vercel/client": "12.6.3",
|
||||
"@vercel/error-utils": "1.0.10",
|
||||
"@vercel/frameworks": "1.4.1",
|
||||
"@vercel/fs-detectors": "3.9.1",
|
||||
"@vercel/frameworks": "1.4.3",
|
||||
"@vercel/fs-detectors": "4.0.1",
|
||||
"@vercel/fun": "1.0.4",
|
||||
"@vercel/ncc": "0.24.0",
|
||||
"@vercel/routing-utils": "2.2.1",
|
||||
@@ -100,7 +101,7 @@
|
||||
"ansi-escapes": "4.3.2",
|
||||
"ansi-regex": "5.0.1",
|
||||
"arg": "5.0.0",
|
||||
"async-listen": "1.2.0",
|
||||
"async-listen": "3.0.0",
|
||||
"async-retry": "1.1.3",
|
||||
"async-sema": "2.1.4",
|
||||
"bytes": "3.0.0",
|
||||
@@ -118,6 +119,7 @@
|
||||
"escape-html": "1.0.3",
|
||||
"esm": "3.1.4",
|
||||
"execa": "3.2.0",
|
||||
"expect": "29.5.0",
|
||||
"express": "4.17.1",
|
||||
"fast-deep-equal": "3.1.3",
|
||||
"find-up": "4.1.0",
|
||||
@@ -147,6 +149,8 @@
|
||||
"pcre-to-regexp": "1.0.0",
|
||||
"pluralize": "7.0.0",
|
||||
"promisepipe": "3.0.0",
|
||||
"proxy": "2.0.0",
|
||||
"proxy-agent": "6.1.1",
|
||||
"psl": "1.1.31",
|
||||
"qr-image": "3.2.0",
|
||||
"raw-body": "2.4.1",
|
||||
@@ -165,6 +169,7 @@
|
||||
"ts-node": "10.9.1",
|
||||
"universal-analytics": "0.4.20",
|
||||
"utility-types": "2.1.0",
|
||||
"which": "3.0.0",
|
||||
"write-json-file": "2.2.0",
|
||||
"xdg-app-paths": "5.1.0",
|
||||
"yauzl-promise": "2.1.3"
|
||||
|
||||
84
packages/cli/src/args.ts
Normal file
84
packages/cli/src/args.ts
Normal file
@@ -0,0 +1,84 @@
|
||||
import chalk from 'chalk';
|
||||
import logo from './util/output/logo';
|
||||
import { getPkgName } from './util/pkg-name';
|
||||
|
||||
export const help = () => `
|
||||
${chalk.bold(`${logo} ${getPkgName()}`)} [options] <command | path>
|
||||
|
||||
${chalk.dim('For deploy command help, run `vercel deploy --help`')}
|
||||
|
||||
${chalk.dim('Commands:')}
|
||||
|
||||
${chalk.dim('Basic')}
|
||||
|
||||
deploy [path] Performs a deployment ${chalk.bold(
|
||||
'(default)'
|
||||
)}
|
||||
dev Start a local development server
|
||||
env Manages the Environment Variables for your current Project
|
||||
git Manage Git provider repository for your current Project
|
||||
help [cmd] Displays complete help for [cmd]
|
||||
init [example] Initialize an example project
|
||||
inspect [id] Displays information related to a deployment
|
||||
link [path] Link local directory to a Vercel Project
|
||||
ls | list [app] Lists deployments
|
||||
login [email] Logs into your account or creates a new one
|
||||
logout Logs out of your account
|
||||
promote [url|id] Promote an existing deployment to current
|
||||
pull [path] Pull your Project Settings from the cloud
|
||||
redeploy [url|id] Rebuild and deploy a previous deployment.
|
||||
rollback [url|id] Quickly revert back to a previous deployment
|
||||
switch [scope] Switches between teams and your personal account
|
||||
|
||||
${chalk.dim('Advanced')}
|
||||
|
||||
alias [cmd] Manages your domain aliases
|
||||
bisect Use binary search to find the deployment that introduced a bug
|
||||
certs [cmd] Manages your SSL certificates
|
||||
dns [name] Manages your DNS records
|
||||
domains [name] Manages your domain names
|
||||
logs [url] Displays the logs for a deployment
|
||||
projects Manages your Projects
|
||||
rm | remove [id] Removes a deployment
|
||||
secrets [name] Manages your global Secrets, for use in Environment Variables
|
||||
teams Manages your teams
|
||||
whoami Shows the username of the currently logged in user
|
||||
|
||||
${chalk.dim('Global Options:')}
|
||||
|
||||
-h, --help Output usage information
|
||||
-v, --version Output the version number
|
||||
--cwd Current working directory
|
||||
-A ${chalk.bold.underline('FILE')}, --local-config=${chalk.bold.underline(
|
||||
'FILE'
|
||||
)} Path to the local ${'`vercel.json`'} file
|
||||
-Q ${chalk.bold.underline('DIR')}, --global-config=${chalk.bold.underline(
|
||||
'DIR'
|
||||
)} Path to the global ${'`.vercel`'} directory
|
||||
-d, --debug Debug mode [off]
|
||||
--no-color No color mode [off]
|
||||
-S, --scope Set a custom scope
|
||||
-t ${chalk.underline('TOKEN')}, --token=${chalk.underline(
|
||||
'TOKEN'
|
||||
)} Login token
|
||||
|
||||
${chalk.dim('Examples:')}
|
||||
|
||||
${chalk.gray('–')} Deploy the current directory
|
||||
|
||||
${chalk.cyan(`$ ${getPkgName()}`)}
|
||||
|
||||
${chalk.gray('–')} Deploy a custom path
|
||||
|
||||
${chalk.cyan(`$ ${getPkgName()} /usr/src/project`)}
|
||||
|
||||
${chalk.gray('–')} Deploy with Environment Variables
|
||||
|
||||
${chalk.cyan(`$ ${getPkgName()} -e NODE_ENV=production`)}
|
||||
|
||||
${chalk.gray('–')} Show the usage information for the sub command ${chalk.dim(
|
||||
'`list`'
|
||||
)}
|
||||
|
||||
${chalk.cyan(`$ ${getPkgName()} help list`)}
|
||||
`;
|
||||
@@ -6,21 +6,19 @@ import chalk, { Chalk } from 'chalk';
|
||||
import { URLSearchParams, parse } from 'url';
|
||||
|
||||
import box from '../../util/output/box';
|
||||
import sleep from '../../util/sleep';
|
||||
import formatDate from '../../util/format-date';
|
||||
import link from '../../util/output/link';
|
||||
import logo from '../../util/output/logo';
|
||||
import getArgs from '../../util/get-args';
|
||||
import Client from '../../util/client';
|
||||
import { getPkgName } from '../../util/pkg-name';
|
||||
import { Deployment, PaginationOptions } from '@vercel-internals/types';
|
||||
import { Deployment } from '@vercel-internals/types';
|
||||
import { normalizeURL } from '../../util/bisect/normalize-url';
|
||||
import getScope from '../../util/get-scope';
|
||||
import getDeployment from '../../util/get-deployment';
|
||||
|
||||
interface Deployments {
|
||||
deployments: Deployment[];
|
||||
pagination: PaginationOptions;
|
||||
}
|
||||
|
||||
const pkgName = getPkgName();
|
||||
@@ -206,44 +204,34 @@ export default async function main(client: Client): Promise<number> {
|
||||
|
||||
// Fetch all the project's "READY" deployments with the pagination API
|
||||
let deployments: Deployment[] = [];
|
||||
let next: number | undefined = badDeployment.createdAt + 1;
|
||||
do {
|
||||
const query = new URLSearchParams();
|
||||
query.set('projectId', projectId);
|
||||
if (badDeployment.target) {
|
||||
query.set('target', badDeployment.target);
|
||||
}
|
||||
query.set('limit', '100');
|
||||
query.set('state', 'READY');
|
||||
if (next) {
|
||||
query.set('until', String(next));
|
||||
}
|
||||
|
||||
const res = await client.fetch<Deployments>(`/v6/deployments?${query}`, {
|
||||
const query = new URLSearchParams();
|
||||
query.set('projectId', projectId);
|
||||
if (badDeployment.target) {
|
||||
query.set('target', badDeployment.target);
|
||||
}
|
||||
query.set('state', 'READY');
|
||||
query.set('until', String(badDeployment.createdAt + 1));
|
||||
|
||||
for await (const chunk of client.fetchPaginated<Deployments>(
|
||||
`/v6/deployments?${query}`,
|
||||
{
|
||||
accountId: badDeployment.ownerId,
|
||||
});
|
||||
|
||||
next = res.pagination.next;
|
||||
|
||||
let newDeployments = res.deployments;
|
||||
}
|
||||
)) {
|
||||
let newDeployments = chunk.deployments;
|
||||
|
||||
// If we have the "good" deployment in this chunk, then we're done
|
||||
for (let i = 0; i < newDeployments.length; i++) {
|
||||
if (newDeployments[i].url === good) {
|
||||
// grab all deployments up until the good one
|
||||
newDeployments = newDeployments.slice(0, i);
|
||||
next = undefined;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
deployments = deployments.concat(newDeployments);
|
||||
|
||||
if (next) {
|
||||
// Small sleep to avoid rate limiting
|
||||
await sleep(100);
|
||||
}
|
||||
} while (next);
|
||||
}
|
||||
|
||||
if (!deployments.length) {
|
||||
output.error(
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import fs from 'fs-extra';
|
||||
import chalk from 'chalk';
|
||||
import dotenv from 'dotenv';
|
||||
import semver from 'semver';
|
||||
import minimatch from 'minimatch';
|
||||
import { join, normalize, relative, resolve, sep } from 'path';
|
||||
import frameworks from '@vercel/frameworks';
|
||||
import {
|
||||
getDiscontinuedNodeVersions,
|
||||
normalizePath,
|
||||
@@ -17,13 +20,14 @@ import {
|
||||
BuildResultV3,
|
||||
NowBuildError,
|
||||
Cron,
|
||||
validateNpmrc,
|
||||
} from '@vercel/build-utils';
|
||||
import {
|
||||
detectBuilders,
|
||||
detectFrameworkRecord,
|
||||
detectFrameworkVersion,
|
||||
LocalFileSystemDetector,
|
||||
} from '@vercel/fs-detectors';
|
||||
import minimatch from 'minimatch';
|
||||
import {
|
||||
appendRoutesToPhase,
|
||||
getTransformedRoutes,
|
||||
@@ -48,7 +52,7 @@ import {
|
||||
ProjectLinkAndSettings,
|
||||
readProjectSettings,
|
||||
} from '../util/projects/project-settings';
|
||||
import { VERCEL_DIR } from '../util/projects/link';
|
||||
import { getProjectLink, VERCEL_DIR } from '../util/projects/link';
|
||||
import confirm from '../util/input/confirm';
|
||||
import { emoji, prependEmoji } from '../util/emoji';
|
||||
import stamp from '../util/output/stamp';
|
||||
@@ -62,11 +66,7 @@ import { initCorepack, cleanupCorepack } from '../util/build/corepack';
|
||||
import { sortBuilders } from '../util/build/sort-builders';
|
||||
import { toEnumerableError } from '../util/error';
|
||||
import { validateConfig } from '../util/validate-config';
|
||||
|
||||
import { setMonorepoDefaultSettings } from '../util/build/monorepo';
|
||||
import frameworks from '@vercel/frameworks';
|
||||
import { detectFrameworkVersion } from '@vercel/fs-detectors';
|
||||
import semver from 'semver';
|
||||
|
||||
type BuildResult = BuildResultV2 | BuildResultV3;
|
||||
|
||||
@@ -133,6 +133,7 @@ const help = () => {
|
||||
};
|
||||
|
||||
export default async function main(client: Client): Promise<number> {
|
||||
let { cwd } = client;
|
||||
const { output } = client;
|
||||
|
||||
// Ensure that `vc build` is not being invoked recursively
|
||||
@@ -165,16 +166,29 @@ export default async function main(client: Client): Promise<number> {
|
||||
return 2;
|
||||
}
|
||||
|
||||
const cwd = process.cwd();
|
||||
|
||||
// Build `target` influences which environment variables will be used
|
||||
const target = argv['--prod'] ? 'production' : 'preview';
|
||||
const yes = Boolean(argv['--yes']);
|
||||
|
||||
try {
|
||||
await validateNpmrc(cwd);
|
||||
} catch (err) {
|
||||
output.prettyError(err);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// If repo linked, update `cwd` to the repo root
|
||||
const link = await getProjectLink(client, cwd);
|
||||
const projectRootDirectory = link?.projectRootDirectory ?? '';
|
||||
if (link?.repoRoot) {
|
||||
cwd = client.cwd = link.repoRoot;
|
||||
}
|
||||
|
||||
// TODO: read project settings from the API, fall back to local `project.json` if that fails
|
||||
|
||||
// Read project settings, and pull them from Vercel if necessary
|
||||
let project = await readProjectSettings(join(cwd, VERCEL_DIR));
|
||||
const vercelDir = join(cwd, projectRootDirectory, VERCEL_DIR);
|
||||
let project = await readProjectSettings(vercelDir);
|
||||
const isTTY = process.stdin.isTTY;
|
||||
while (!project?.settings) {
|
||||
let confirmed = yes;
|
||||
@@ -201,6 +215,7 @@ export default async function main(client: Client): Promise<number> {
|
||||
return 0;
|
||||
}
|
||||
const { argv: originalArgv } = client;
|
||||
client.cwd = join(cwd, projectRootDirectory);
|
||||
client.argv = [
|
||||
...originalArgv.slice(0, 2),
|
||||
'pull',
|
||||
@@ -211,12 +226,13 @@ export default async function main(client: Client): Promise<number> {
|
||||
if (result !== 0) {
|
||||
return result;
|
||||
}
|
||||
client.cwd = cwd;
|
||||
client.argv = originalArgv;
|
||||
project = await readProjectSettings(join(cwd, VERCEL_DIR));
|
||||
project = await readProjectSettings(vercelDir);
|
||||
}
|
||||
|
||||
// Delete output directory from potential previous build
|
||||
const defaultOutputDir = join(cwd, OUTPUT_DIR);
|
||||
const defaultOutputDir = join(cwd, projectRootDirectory, OUTPUT_DIR);
|
||||
const outputDir = argv['--output']
|
||||
? resolve(argv['--output'])
|
||||
: defaultOutputDir;
|
||||
@@ -235,7 +251,12 @@ export default async function main(client: Client): Promise<number> {
|
||||
const envToUnset = new Set<string>(['VERCEL', 'NOW_BUILDER']);
|
||||
|
||||
try {
|
||||
const envPath = join(cwd, VERCEL_DIR, `.env.${target}.local`);
|
||||
const envPath = join(
|
||||
cwd,
|
||||
projectRootDirectory,
|
||||
VERCEL_DIR,
|
||||
`.env.${target}.local`
|
||||
);
|
||||
// TODO (maybe?): load env vars from the API, fall back to the local file if that fails
|
||||
const dotenvResult = dotenv.config({
|
||||
path: envPath,
|
||||
|
||||
@@ -2,80 +2,27 @@ import chalk from 'chalk';
|
||||
import logo from '../../util/output/logo';
|
||||
import { getPkgName } from '../../util/pkg-name';
|
||||
|
||||
export const help = () => `
|
||||
${chalk.bold(`${logo} ${getPkgName()}`)} [options] <command | path>
|
||||
export const help = () => {
|
||||
return `
|
||||
${chalk.bold(`${logo} ${getPkgName()} [deploy]`)} [path-to-project] [options]
|
||||
|
||||
${chalk.dim('Commands:')}
|
||||
|
||||
${chalk.dim('Basic')}
|
||||
|
||||
deploy [path] Performs a deployment ${chalk.bold(
|
||||
'(default)'
|
||||
)}
|
||||
dev Start a local development server
|
||||
env Manages the Environment Variables for your current Project
|
||||
git Manage Git provider repository for your current Project
|
||||
help [cmd] Displays complete help for [cmd]
|
||||
init [example] Initialize an example project
|
||||
inspect [id] Displays information related to a deployment
|
||||
link [path] Link local directory to a Vercel Project
|
||||
ls | list [app] Lists deployments
|
||||
login [email] Logs into your account or creates a new one
|
||||
logout Logs out of your account
|
||||
pull [path] Pull your Project Settings from the cloud
|
||||
rollback [url|id] Quickly revert back to a previous deployment [beta]
|
||||
switch [scope] Switches between teams and your personal account
|
||||
|
||||
${chalk.dim('Advanced')}
|
||||
|
||||
alias [cmd] Manages your domain aliases
|
||||
bisect Use binary search to find the deployment that introduced a bug
|
||||
certs [cmd] Manages your SSL certificates
|
||||
dns [name] Manages your DNS records
|
||||
domains [name] Manages your domain names
|
||||
logs [url] Displays the logs for a deployment
|
||||
projects Manages your Projects
|
||||
rm | remove [id] Removes a deployment
|
||||
secrets [name] Manages your global Secrets, for use in Environment Variables
|
||||
teams Manages your teams
|
||||
whoami Shows the username of the currently logged in user
|
||||
|
||||
${chalk.dim('Options:')}
|
||||
|
||||
-h, --help Output usage information
|
||||
-v, --version Output the version number
|
||||
--cwd Current working directory
|
||||
-V, --platform-version Set the platform version to deploy to
|
||||
-A ${chalk.bold.underline('FILE')}, --local-config=${chalk.bold.underline(
|
||||
'FILE'
|
||||
)} Path to the local ${'`vercel.json`'} file
|
||||
-Q ${chalk.bold.underline('DIR')}, --global-config=${chalk.bold.underline(
|
||||
'DIR'
|
||||
)} Path to the global ${'`.vercel`'} directory
|
||||
-d, --debug Debug mode [off]
|
||||
--no-color No color mode [off]
|
||||
-f, --force Force a new deployment even if nothing has changed
|
||||
--with-cache Retain build cache when using "--force"
|
||||
-t ${chalk.underline('TOKEN')}, --token=${chalk.underline(
|
||||
'TOKEN'
|
||||
)} Login token
|
||||
-p, --public Deployment is public (${chalk.dim(
|
||||
'`/_src`'
|
||||
)} is exposed)
|
||||
-e, --env Include an env var during run time (e.g.: ${chalk.dim(
|
||||
'`-e KEY=value`'
|
||||
)}). Can appear many times.
|
||||
-b, --build-env Similar to ${chalk.dim(
|
||||
'`--env`'
|
||||
)} but for build time only.
|
||||
-m, --meta Add metadata for the deployment (e.g.: ${chalk.dim(
|
||||
'`-m KEY=value`'
|
||||
)}). Can appear many times.
|
||||
--no-wait Don't wait for the deployment to finish
|
||||
-S, --scope Set a custom scope
|
||||
--regions Set default regions to enable the deployment on
|
||||
--prod Create a production deployment
|
||||
-y, --yes Skip questions when setting up new project using default scope and settings
|
||||
--prod Create a production deployment
|
||||
-p, --public Deployment is public (${chalk.dim(
|
||||
'`/_src`'
|
||||
)} is exposed)
|
||||
-e, --env Include an env var during run time (e.g.: ${chalk.dim(
|
||||
'`-e KEY=value`'
|
||||
)}). Can appear many times.
|
||||
-b, --build-env Similar to ${chalk.dim(
|
||||
'`--env`'
|
||||
)} but for build time only.
|
||||
-m, --meta Add metadata for the deployment (e.g.: ${chalk.dim(
|
||||
'`-m KEY=value`'
|
||||
)}). Can appear many times.
|
||||
--no-wait Don't wait for the deployment to finish
|
||||
-f, --force Force a new deployment even if nothing has changed
|
||||
--with-cache Retain build cache when using "--force"
|
||||
--regions Set default regions to enable the deployment on
|
||||
|
||||
${chalk.dim('Examples:')}
|
||||
|
||||
@@ -89,14 +36,15 @@ export const help = () => `
|
||||
|
||||
${chalk.gray('–')} Deploy with Environment Variables
|
||||
|
||||
${chalk.cyan(
|
||||
`$ ${getPkgName()} -e NODE_ENV=production -e SECRET=@mysql-secret`
|
||||
)}
|
||||
${chalk.cyan(`$ ${getPkgName()} -e NODE_ENV=production`)}
|
||||
|
||||
${chalk.gray('–')} Show the usage information for the sub command ${chalk.dim(
|
||||
'`list`'
|
||||
)}
|
||||
${chalk.gray('–')} Deploy with prebuilt outputs
|
||||
|
||||
${chalk.cyan(`$ ${getPkgName()} help list`)}
|
||||
${chalk.cyan(`$ ${getPkgName()} build`)}
|
||||
${chalk.cyan(`$ ${getPkgName()} deploy --prebuilt`)}
|
||||
|
||||
${chalk.gray('–')} Write Deployment URL to a file
|
||||
|
||||
${chalk.cyan(`$ ${getPkgName()} > deployment-url.txt`)}
|
||||
`;
|
||||
};
|
||||
|
||||
@@ -2,7 +2,7 @@ import ms from 'ms';
|
||||
import fs from 'fs-extra';
|
||||
import bytes from 'bytes';
|
||||
import chalk from 'chalk';
|
||||
import { join, resolve, basename } from 'path';
|
||||
import { join, resolve } from 'path';
|
||||
import {
|
||||
fileNameSymbol,
|
||||
VALID_ARCHIVE_FORMATS,
|
||||
@@ -21,7 +21,6 @@ import stamp from '../../util/output/stamp';
|
||||
import createDeploy from '../../util/deploy/create-deploy';
|
||||
import getDeployment from '../../util/get-deployment';
|
||||
import parseMeta from '../../util/parse-meta';
|
||||
import linkStyle from '../../util/output/link';
|
||||
import param from '../../util/output/param';
|
||||
import {
|
||||
BuildsRateLimited,
|
||||
@@ -59,7 +58,6 @@ import validatePaths, {
|
||||
validateRootDirectory,
|
||||
} from '../../util/validate-paths';
|
||||
import { getCommandName } from '../../util/pkg-name';
|
||||
import { getPreferredPreviewURL } from '../../util/deploy/get-preferred-preview-url';
|
||||
import { Output } from '../../util/output';
|
||||
import { help } from './args';
|
||||
import { getDeploymentChecks } from '../../util/deploy/get-deployment-checks';
|
||||
@@ -70,8 +68,7 @@ import { isValidArchive } from '../../util/deploy/validate-archive-format';
|
||||
import { parseEnv } from '../../util/parse-env';
|
||||
import { errorToString, isErrnoException, isError } from '@vercel/error-utils';
|
||||
import { pickOverrides } from '../../util/projects/project-settings';
|
||||
import { isDeploying } from '../../util/deploy/is-deploying';
|
||||
import type { Deployment } from '@vercel-internals/types';
|
||||
import { printDeploymentStatus } from '../../util/deploy/print-deployment-status';
|
||||
|
||||
export default async (client: Client): Promise<number> => {
|
||||
const { output } = client;
|
||||
@@ -93,6 +90,7 @@ export default async (client: Client): Promise<number> => {
|
||||
'--prod': Boolean,
|
||||
'--archive': String,
|
||||
'--no-wait': Boolean,
|
||||
'--skip-domain': Boolean,
|
||||
'--yes': Boolean,
|
||||
'-f': '--force',
|
||||
'-p': '--public',
|
||||
@@ -132,24 +130,19 @@ export default async (client: Client): Promise<number> => {
|
||||
if (argv._.length > 0) {
|
||||
// If path is relative: resolve
|
||||
// if path is absolute: clear up strange `/` etc
|
||||
paths = argv._.map(item => resolve(process.cwd(), item));
|
||||
paths = argv._.map(item => resolve(client.cwd, item));
|
||||
} else {
|
||||
paths = [process.cwd()];
|
||||
paths = [client.cwd];
|
||||
}
|
||||
|
||||
// check paths
|
||||
const pathValidation = await validatePaths(client, paths);
|
||||
|
||||
if (!pathValidation.valid) {
|
||||
return pathValidation.exitCode;
|
||||
}
|
||||
|
||||
let localConfig = client.localConfig || readLocalConfig(paths[0]);
|
||||
|
||||
for (const path of paths) {
|
||||
try {
|
||||
await fs.stat(path);
|
||||
} catch (err) {
|
||||
output.error(
|
||||
`The specified file or directory "${basename(path)}" does not exist.`
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (localConfig) {
|
||||
const { version } = localConfig;
|
||||
const file = highlight(localConfig[fileNameSymbol]!);
|
||||
@@ -178,14 +171,7 @@ export default async (client: Client): Promise<number> => {
|
||||
|
||||
const quiet = !client.stdout.isTTY;
|
||||
|
||||
// check paths
|
||||
const pathValidation = await validatePaths(client, paths);
|
||||
|
||||
if (!pathValidation.valid) {
|
||||
return pathValidation.exitCode;
|
||||
}
|
||||
|
||||
const { path } = pathValidation;
|
||||
let { path: cwd } = pathValidation;
|
||||
const autoConfirm = argv['--yes'];
|
||||
|
||||
// deprecate --name
|
||||
@@ -217,56 +203,6 @@ export default async (client: Client): Promise<number> => {
|
||||
return target;
|
||||
}
|
||||
|
||||
// build `--prebuilt`
|
||||
if (argv['--prebuilt']) {
|
||||
const prebuiltExists = await fs.pathExists(join(path, '.vercel/output'));
|
||||
if (!prebuiltExists) {
|
||||
error(
|
||||
`The ${param(
|
||||
'--prebuilt'
|
||||
)} option was used, but no prebuilt output found in ".vercel/output". Run ${getCommandName(
|
||||
'build'
|
||||
)} to generate a local build.`
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const prebuiltBuild = await getPrebuiltJson(path);
|
||||
|
||||
// Ensure that there was not a build error
|
||||
const prebuiltError =
|
||||
prebuiltBuild?.error ||
|
||||
prebuiltBuild?.builds?.find(build => 'error' in build)?.error;
|
||||
if (prebuiltError) {
|
||||
output.log(
|
||||
`Prebuilt deployment cannot be created because ${getCommandName(
|
||||
'build'
|
||||
)} failed with error:\n`
|
||||
);
|
||||
prettyError(prebuiltError);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Ensure that the deploy target matches the build target
|
||||
const assumedTarget = target || 'preview';
|
||||
if (prebuiltBuild?.target && prebuiltBuild.target !== assumedTarget) {
|
||||
let specifyTarget = '';
|
||||
if (prebuiltBuild.target === 'production') {
|
||||
specifyTarget = ` --prod`;
|
||||
}
|
||||
|
||||
prettyError({
|
||||
message: `The ${param(
|
||||
'--prebuilt'
|
||||
)} option was used with the target environment "${assumedTarget}", but the prebuilt output found in ".vercel/output" was built with target environment "${
|
||||
prebuiltBuild.target
|
||||
}". Please run ${getCommandName(`--prebuilt${specifyTarget}`)}.`,
|
||||
link: 'https://vercel.link/prebuilt-environment-mismatch',
|
||||
});
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
const archive = argv['--archive'];
|
||||
if (typeof archive === 'string' && !isValidArchive(archive)) {
|
||||
output.error(`Format must be one of: ${VALID_ARCHIVE_FORMATS.join(', ')}`);
|
||||
@@ -274,7 +210,7 @@ export default async (client: Client): Promise<number> => {
|
||||
}
|
||||
|
||||
// retrieve `project` and `org` from .vercel
|
||||
const link = await getLinkedProject(client, path);
|
||||
const link = await getLinkedProject(client, cwd);
|
||||
|
||||
if (link.status === 'error') {
|
||||
return link.exitCode;
|
||||
@@ -291,7 +227,7 @@ export default async (client: Client): Promise<number> => {
|
||||
autoConfirm ||
|
||||
(await confirm(
|
||||
client,
|
||||
`Set up and deploy ${chalk.cyan(`“${toHumanPath(path)}”`)}?`,
|
||||
`Set up and deploy ${chalk.cyan(`“${toHumanPath(cwd)}”`)}?`,
|
||||
true
|
||||
));
|
||||
|
||||
@@ -338,7 +274,7 @@ export default async (client: Client): Promise<number> => {
|
||||
|
||||
if (typeof projectOrNewProjectName === 'string') {
|
||||
newProjectName = projectOrNewProjectName;
|
||||
rootDirectory = await inputRootDirectory(client, path, autoConfirm);
|
||||
rootDirectory = await inputRootDirectory(client, cwd, autoConfirm);
|
||||
} else {
|
||||
project = projectOrNewProjectName;
|
||||
rootDirectory = project.rootDirectory;
|
||||
@@ -346,8 +282,8 @@ export default async (client: Client): Promise<number> => {
|
||||
|
||||
// we can already link the project
|
||||
await linkFolderToProject(
|
||||
output,
|
||||
path,
|
||||
client,
|
||||
cwd,
|
||||
{
|
||||
projectId: project.id,
|
||||
orgId: org.id,
|
||||
@@ -359,11 +295,76 @@ export default async (client: Client): Promise<number> => {
|
||||
}
|
||||
}
|
||||
|
||||
// For repo-style linking, reset the path to the root of the repository
|
||||
if (link.status === 'linked' && link.repoRoot) {
|
||||
cwd = link.repoRoot;
|
||||
}
|
||||
|
||||
// At this point `org` should be populated
|
||||
if (!org) {
|
||||
throw new Error(`"org" is not defined`);
|
||||
}
|
||||
|
||||
// build `--prebuilt`
|
||||
if (argv['--prebuilt']) {
|
||||
// For repo-style linking, update `cwd` to be the Project
|
||||
// subdirectory when `rootDirectory` setting is defined
|
||||
if (
|
||||
link.status === 'linked' &&
|
||||
link.repoRoot &&
|
||||
link.project.rootDirectory
|
||||
) {
|
||||
cwd = join(cwd, link.project.rootDirectory);
|
||||
}
|
||||
|
||||
const prebuiltExists = await fs.pathExists(join(cwd, '.vercel/output'));
|
||||
if (!prebuiltExists) {
|
||||
error(
|
||||
`The ${param(
|
||||
'--prebuilt'
|
||||
)} option was used, but no prebuilt output found in ".vercel/output". Run ${getCommandName(
|
||||
'build'
|
||||
)} to generate a local build.`
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const prebuiltBuild = await getPrebuiltJson(cwd);
|
||||
|
||||
// Ensure that there was not a build error
|
||||
const prebuiltError =
|
||||
prebuiltBuild?.error ||
|
||||
prebuiltBuild?.builds?.find(build => 'error' in build)?.error;
|
||||
if (prebuiltError) {
|
||||
output.log(
|
||||
`Prebuilt deployment cannot be created because ${getCommandName(
|
||||
'build'
|
||||
)} failed with error:\n`
|
||||
);
|
||||
prettyError(prebuiltError);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Ensure that the deploy target matches the build target
|
||||
const assumedTarget = target || 'preview';
|
||||
if (prebuiltBuild?.target && prebuiltBuild.target !== assumedTarget) {
|
||||
let specifyTarget = '';
|
||||
if (prebuiltBuild.target === 'production') {
|
||||
specifyTarget = ` --prod`;
|
||||
}
|
||||
|
||||
prettyError({
|
||||
message: `The ${param(
|
||||
'--prebuilt'
|
||||
)} option was used with the target environment "${assumedTarget}", but the prebuilt output found in ".vercel/output" was built with target environment "${
|
||||
prebuiltBuild.target
|
||||
}". Please run ${getCommandName(`--prebuilt${specifyTarget}`)}.`,
|
||||
link: 'https://vercel.link/prebuilt-environment-mismatch',
|
||||
});
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Set the `contextName` and `currentTeam` as specified by the
|
||||
// Project Settings, so that API calls happen with the proper scope
|
||||
const contextName = org.slug;
|
||||
@@ -373,14 +374,14 @@ export default async (client: Client): Promise<number> => {
|
||||
// and upload the entire directory.
|
||||
const sourcePath =
|
||||
rootDirectory && !sourceFilesOutsideRootDirectory
|
||||
? join(path, rootDirectory)
|
||||
: path;
|
||||
? join(cwd, rootDirectory)
|
||||
: cwd;
|
||||
|
||||
if (
|
||||
rootDirectory &&
|
||||
(await validateRootDirectory(
|
||||
output,
|
||||
path,
|
||||
cwd,
|
||||
sourcePath,
|
||||
project
|
||||
? `To change your Project Settings, go to https://vercel.com/${org?.slug}/${project.name}/settings`
|
||||
@@ -393,7 +394,7 @@ export default async (client: Client): Promise<number> => {
|
||||
// If Root Directory is used we'll try to read the config
|
||||
// from there instead and use it if it exists.
|
||||
if (rootDirectory) {
|
||||
const rootDirectoryConfig = readLocalConfig(join(path, rootDirectory));
|
||||
const rootDirectoryConfig = readLocalConfig(join(cwd, rootDirectory));
|
||||
|
||||
if (rootDirectoryConfig) {
|
||||
debug(`Read local config from root directory (${rootDirectory})`);
|
||||
@@ -469,7 +470,7 @@ export default async (client: Client): Promise<number> => {
|
||||
parseMeta(argv['--meta'])
|
||||
);
|
||||
|
||||
const gitMetadata = await createGitMeta(path, output, project);
|
||||
const gitMetadata = await createGitMeta(cwd, output, project);
|
||||
|
||||
// Merge dotenv config, `env` from vercel.json, and `--env` / `-e` arguments
|
||||
const deploymentEnv = Object.assign(
|
||||
@@ -520,6 +521,9 @@ export default async (client: Client): Promise<number> => {
|
||||
}
|
||||
|
||||
try {
|
||||
// if this flag is not set, use `undefined` to allow the project setting to be used
|
||||
const autoAssignCustomDomains = argv['--skip-domain'] ? false : undefined;
|
||||
|
||||
const createArgs: CreateOptions = {
|
||||
name,
|
||||
env: deploymentEnv,
|
||||
@@ -543,6 +547,7 @@ export default async (client: Client): Promise<number> => {
|
||||
target,
|
||||
skipAutoDetectionConfirmation: autoConfirm,
|
||||
noWait,
|
||||
autoAssignCustomDomains,
|
||||
};
|
||||
|
||||
if (!localConfig.builds || localConfig.builds.length === 0) {
|
||||
@@ -559,11 +564,11 @@ export default async (client: Client): Promise<number> => {
|
||||
client,
|
||||
now,
|
||||
contextName,
|
||||
[sourcePath],
|
||||
sourcePath,
|
||||
createArgs,
|
||||
org,
|
||||
!project,
|
||||
path,
|
||||
cwd,
|
||||
archive
|
||||
);
|
||||
|
||||
@@ -595,11 +600,11 @@ export default async (client: Client): Promise<number> => {
|
||||
client,
|
||||
now,
|
||||
contextName,
|
||||
[sourcePath],
|
||||
sourcePath,
|
||||
createArgs,
|
||||
org,
|
||||
false,
|
||||
path
|
||||
cwd
|
||||
);
|
||||
}
|
||||
|
||||
@@ -728,7 +733,7 @@ export default async (client: Client): Promise<number> => {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return printDeploymentStatus(output, client, deployment, deployStamp, noWait);
|
||||
return printDeploymentStatus(client, deployment, deployStamp, noWait);
|
||||
};
|
||||
|
||||
function handleCreateDeployError(
|
||||
@@ -835,112 +840,3 @@ const addProcessEnv = async (
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const printDeploymentStatus = async (
|
||||
output: Output,
|
||||
client: Client,
|
||||
{
|
||||
readyState,
|
||||
alias: aliasList,
|
||||
aliasError,
|
||||
target,
|
||||
indications,
|
||||
url: deploymentUrl,
|
||||
aliasWarning,
|
||||
}: {
|
||||
readyState: Deployment['readyState'];
|
||||
alias: string[];
|
||||
aliasError: Error;
|
||||
target: string;
|
||||
indications: any;
|
||||
url: string;
|
||||
aliasWarning?: {
|
||||
code: string;
|
||||
message: string;
|
||||
link?: string;
|
||||
action?: string;
|
||||
};
|
||||
},
|
||||
deployStamp: () => string,
|
||||
noWait: boolean
|
||||
) => {
|
||||
indications = indications || [];
|
||||
const isProdDeployment = target === 'production';
|
||||
|
||||
let isStillBuilding = false;
|
||||
if (noWait) {
|
||||
if (isDeploying(readyState)) {
|
||||
isStillBuilding = true;
|
||||
output.print(
|
||||
prependEmoji(
|
||||
'Note: Deployment is still processing...',
|
||||
emoji('notice')
|
||||
) + '\n'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (!isStillBuilding && readyState !== 'READY') {
|
||||
output.error(
|
||||
`Your deployment failed. Please retry later. More: https://err.sh/vercel/deployment-error`
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (aliasError) {
|
||||
output.warn(
|
||||
`Failed to assign aliases${
|
||||
aliasError.message ? `: ${aliasError.message}` : ''
|
||||
}`
|
||||
);
|
||||
} else {
|
||||
// print preview/production url
|
||||
let previewUrl: string;
|
||||
// if `noWait` is true, then use the deployment url, not an alias
|
||||
if (!noWait && Array.isArray(aliasList) && aliasList.length > 0) {
|
||||
const previewUrlInfo = await getPreferredPreviewURL(client, aliasList);
|
||||
if (previewUrlInfo) {
|
||||
previewUrl = previewUrlInfo.previewUrl;
|
||||
} else {
|
||||
previewUrl = `https://${deploymentUrl}`;
|
||||
}
|
||||
} else {
|
||||
// fallback to deployment url
|
||||
previewUrl = `https://${deploymentUrl}`;
|
||||
}
|
||||
|
||||
output.print(
|
||||
prependEmoji(
|
||||
`${isProdDeployment ? 'Production' : 'Preview'}: ${chalk.bold(
|
||||
previewUrl
|
||||
)} ${deployStamp()}`,
|
||||
emoji('success')
|
||||
) + `\n`
|
||||
);
|
||||
}
|
||||
|
||||
if (aliasWarning?.message) {
|
||||
indications.push({
|
||||
type: 'warning',
|
||||
payload: aliasWarning.message,
|
||||
link: aliasWarning.link,
|
||||
action: aliasWarning.action,
|
||||
});
|
||||
}
|
||||
|
||||
const newline = '\n';
|
||||
for (let indication of indications) {
|
||||
const message =
|
||||
prependEmoji(chalk.dim(indication.payload), emoji(indication.type)) +
|
||||
newline;
|
||||
let link = '';
|
||||
if (indication.link)
|
||||
link =
|
||||
chalk.dim(
|
||||
`${indication.action || 'Learn More'}: ${linkStyle(indication.link)}`
|
||||
) + newline;
|
||||
output.print(message + link);
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
@@ -58,7 +58,13 @@ export default async function dev(
|
||||
let projectSettings: ProjectSettings | undefined;
|
||||
let envValues: Record<string, string> = {};
|
||||
if (link.status === 'linked') {
|
||||
const { project, org } = link;
|
||||
const { project, org, repoRoot } = link;
|
||||
|
||||
// If repo linked, update `cwd` to the repo root
|
||||
if (repoRoot) {
|
||||
cwd = repoRoot;
|
||||
}
|
||||
|
||||
client.config.currentTeam = org.type === 'team' ? org.id : undefined;
|
||||
|
||||
projectSettings = project;
|
||||
|
||||
6
packages/cli/src/commands/env/index.ts
vendored
6
packages/cli/src/commands/env/index.ts
vendored
@@ -26,7 +26,7 @@ const help = () => {
|
||||
ls [environment] [gitbranch] List all variables for the specified Environment
|
||||
add [name] [environment] [gitbranch] Add an Environment Variable (see examples below)
|
||||
rm [name] [environment] [gitbranch] Remove an Environment Variable (see examples below)
|
||||
pull [filename] Pull all Development Environment Variables from the cloud and write to a file [.env]
|
||||
pull [filename] Pull all Development Environment Variables from the cloud and write to a file [.env.local]
|
||||
|
||||
${chalk.dim('Options:')}
|
||||
|
||||
@@ -130,10 +130,9 @@ export default async function main(client: Client) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
const cwd = argv['--cwd'] || process.cwd();
|
||||
const subArgs = argv._.slice(1);
|
||||
const { subcommand, args } = getSubcommand(subArgs, COMMAND_CONFIG);
|
||||
const { output, config } = client;
|
||||
const { cwd, output, config } = client;
|
||||
|
||||
const target = argv['--environment']?.toLowerCase() || 'development';
|
||||
if (!isValidEnvTarget(target)) {
|
||||
@@ -168,6 +167,7 @@ export default async function main(client: Client) {
|
||||
case 'pull':
|
||||
return pull(
|
||||
client,
|
||||
link,
|
||||
project,
|
||||
target,
|
||||
argv,
|
||||
|
||||
32
packages/cli/src/commands/env/pull.ts
vendored
32
packages/cli/src/commands/env/pull.ts
vendored
@@ -2,7 +2,11 @@ import chalk from 'chalk';
|
||||
import { outputFile } from 'fs-extra';
|
||||
import { closeSync, openSync, readSync } from 'fs';
|
||||
import { resolve } from 'path';
|
||||
import type { Project, ProjectEnvTarget } from '@vercel-internals/types';
|
||||
import type {
|
||||
Project,
|
||||
ProjectEnvTarget,
|
||||
ProjectLinked,
|
||||
} from '@vercel-internals/types';
|
||||
import Client from '../../util/client';
|
||||
import { emoji, prependEmoji } from '../../util/emoji';
|
||||
import confirm from '../../util/input/confirm';
|
||||
@@ -19,6 +23,7 @@ import {
|
||||
createEnvObject,
|
||||
} from '../../util/env/diff-env-files';
|
||||
import { isErrnoException } from '@vercel/error-utils';
|
||||
import { addToGitIgnore } from '../../util/link/add-to-gitignore';
|
||||
|
||||
const CONTENTS_PREFIX = '# Created by Vercel CLI\n';
|
||||
|
||||
@@ -51,6 +56,7 @@ function tryReadHeadSync(path: string, length: number) {
|
||||
|
||||
export default async function pull(
|
||||
client: Client,
|
||||
link: ProjectLinked,
|
||||
project: Project,
|
||||
environment: ProjectEnvTarget,
|
||||
opts: Partial<Options>,
|
||||
@@ -67,7 +73,7 @@ export default async function pull(
|
||||
}
|
||||
|
||||
// handle relative or absolute filename
|
||||
const [filename = '.env'] = args;
|
||||
const [filename = '.env.local'] = args;
|
||||
const fullPath = resolve(cwd, filename);
|
||||
const skipConfirmation = opts['--yes'];
|
||||
const gitBranch = opts['--git-branch'];
|
||||
@@ -122,8 +128,9 @@ export default async function pull(
|
||||
|
||||
const contents =
|
||||
CONTENTS_PREFIX +
|
||||
Object.entries(records)
|
||||
.map(([key, value]) => `${key}="${escapeValue(value)}"`)
|
||||
Object.keys(records)
|
||||
.sort()
|
||||
.map(key => `${key}="${escapeValue(records[key])}"`)
|
||||
.join('\n') +
|
||||
'\n';
|
||||
|
||||
@@ -135,11 +142,22 @@ export default async function pull(
|
||||
output.log('No changes found.');
|
||||
}
|
||||
|
||||
let isGitIgnoreUpdated = false;
|
||||
if (filename === '.env.local') {
|
||||
// When the file is `.env.local`, we also add it to `.gitignore`
|
||||
// to avoid accidentally committing it to git.
|
||||
// We use '.env*.local' to match the default .gitignore from
|
||||
// create-next-app template. See:
|
||||
// https://github.com/vercel/next.js/blob/06abd634899095b6cc28e6e8315b1e8b9c8df939/packages/create-next-app/templates/app/js/gitignore#L28
|
||||
const rootPath = link.repoRoot ?? cwd;
|
||||
isGitIgnoreUpdated = await addToGitIgnore(rootPath, '.env*.local');
|
||||
}
|
||||
|
||||
output.print(
|
||||
`${prependEmoji(
|
||||
`${exists ? 'Updated' : 'Created'} ${chalk.bold(
|
||||
filename
|
||||
)} file ${chalk.gray(pullStamp())}`,
|
||||
`${exists ? 'Updated' : 'Created'} ${chalk.bold(filename)} file ${
|
||||
isGitIgnoreUpdated ? 'and added it to .gitignore' : ''
|
||||
} ${chalk.gray(pullStamp())}`,
|
||||
emoji('success')
|
||||
)}\n`
|
||||
);
|
||||
|
||||
@@ -16,7 +16,6 @@ import {
|
||||
parseRepoUrl,
|
||||
printRemoteUrls,
|
||||
} from '../../util/git/connect-git-provider';
|
||||
import validatePaths from '../../util/validate-paths';
|
||||
|
||||
interface GitRepoCheckParams {
|
||||
client: Client;
|
||||
@@ -56,7 +55,7 @@ export default async function connect(
|
||||
project: Project | undefined,
|
||||
org: Org | undefined
|
||||
) {
|
||||
const { output } = client;
|
||||
const { cwd, output } = client;
|
||||
const confirm = Boolean(argv['--yes']);
|
||||
const repoArg = argv._[1];
|
||||
|
||||
@@ -77,19 +76,11 @@ export default async function connect(
|
||||
return 1;
|
||||
}
|
||||
|
||||
let paths = [process.cwd()];
|
||||
|
||||
const validate = await validatePaths(client, paths);
|
||||
if (!validate.valid) {
|
||||
return validate.exitCode;
|
||||
}
|
||||
const { path } = validate;
|
||||
|
||||
const gitProviderLink = project.link;
|
||||
client.config.currentTeam = org.type === 'team' ? org.id : undefined;
|
||||
|
||||
// get project from .git
|
||||
const gitConfigPath = join(path, '.git/config');
|
||||
const gitConfigPath = join(cwd, '.git/config');
|
||||
const gitConfig = await parseGitConfig(gitConfigPath, output);
|
||||
|
||||
if (repoArg) {
|
||||
@@ -116,7 +107,7 @@ export default async function connect(
|
||||
confirm,
|
||||
org,
|
||||
project,
|
||||
repoInfo: repoArg,
|
||||
repoInfo: parsedUrlArg,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ import getInvalidSubcommand from '../../util/get-invalid-subcommand';
|
||||
import handleError from '../../util/handle-error';
|
||||
import logo from '../../util/output/logo';
|
||||
import { getPkgName } from '../../util/pkg-name';
|
||||
import validatePaths from '../../util/validate-paths';
|
||||
import connect from './connect';
|
||||
import disconnect from './disconnect';
|
||||
|
||||
@@ -81,16 +80,9 @@ export default async function main(client: Client) {
|
||||
subcommand = argv._[0];
|
||||
const args = argv._.slice(1);
|
||||
const autoConfirm = Boolean(argv['--yes']);
|
||||
const { output } = client;
|
||||
const { cwd, output } = client;
|
||||
|
||||
let paths = [process.cwd()];
|
||||
const pathValidation = await validatePaths(client, paths);
|
||||
if (!pathValidation.valid) {
|
||||
return pathValidation.exitCode;
|
||||
}
|
||||
const { path } = pathValidation;
|
||||
|
||||
const linkedProject = await ensureLink('git', client, path, { autoConfirm });
|
||||
const linkedProject = await ensureLink('git', client, cwd, { autoConfirm });
|
||||
if (typeof linkedProject === 'number') {
|
||||
return linkedProject;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,9 @@ export default new Map([
|
||||
['ls', 'list'],
|
||||
['project', 'project'],
|
||||
['projects', 'project'],
|
||||
['promote', 'promote'],
|
||||
['pull', 'pull'],
|
||||
['redeploy', 'redeploy'],
|
||||
['remove', 'remove'],
|
||||
['rm', 'remove'],
|
||||
['rollback', 'rollback'],
|
||||
|
||||
@@ -52,7 +52,7 @@ export default async function main(client: Client) {
|
||||
try {
|
||||
argv = getArgs(client.argv.slice(2), {
|
||||
'--force': Boolean,
|
||||
'-f': Boolean,
|
||||
'-f': '--force',
|
||||
});
|
||||
args = getSubcommand(argv._.slice(1), COMMAND_CONFIG).args;
|
||||
} catch (err) {
|
||||
|
||||
@@ -35,7 +35,7 @@ export default async function init(
|
||||
) {
|
||||
const { output } = client;
|
||||
const [name, dir] = args;
|
||||
const force = opts['-f'] || opts['--force'];
|
||||
const force = opts['--force'];
|
||||
|
||||
const examples = await fetchExampleList(client);
|
||||
|
||||
|
||||
@@ -2,8 +2,10 @@ import chalk from 'chalk';
|
||||
import Client from '../../util/client';
|
||||
import getArgs from '../../util/get-args';
|
||||
import logo from '../../util/output/logo';
|
||||
import cmd from '../../util/output/cmd';
|
||||
import { getPkgName } from '../../util/pkg-name';
|
||||
import { ensureLink } from '../../util/link/ensure-link';
|
||||
import { ensureRepoLink } from '../../util/link/repo';
|
||||
|
||||
const help = () => {
|
||||
console.log(`
|
||||
@@ -12,6 +14,7 @@ const help = () => {
|
||||
${chalk.dim('Options:')}
|
||||
|
||||
-h, --help Output usage information
|
||||
-r, --repo Link multiple projects based on Git repository (alpha)
|
||||
-A ${chalk.bold.underline('FILE')}, --local-config=${chalk.bold.underline(
|
||||
'FILE'
|
||||
)} Path to the local ${'`vercel.json`'} file
|
||||
@@ -42,7 +45,14 @@ const help = () => {
|
||||
|
||||
${chalk.gray('–')} Link a specific directory to a Vercel Project
|
||||
|
||||
${chalk.cyan(`$ ${getPkgName()} link /usr/src/project`)}
|
||||
${chalk.cyan(`$ ${getPkgName()} link --cwd /path/to/project`)}
|
||||
|
||||
${chalk.gray('–')} ${chalk.yellow(
|
||||
'(alpha)'
|
||||
)} Link to the current Git repository, allowing for multiple
|
||||
Vercel Projects to be linked simultaneously (useful for monorepos)
|
||||
|
||||
${chalk.cyan(`$ ${getPkgName()} link --repo`)}
|
||||
`);
|
||||
};
|
||||
|
||||
@@ -52,6 +62,8 @@ export default async function main(client: Client) {
|
||||
'-y': '--yes',
|
||||
'--project': String,
|
||||
'-p': '--project',
|
||||
'--repo': Boolean,
|
||||
'-r': '--repo',
|
||||
|
||||
// deprecated
|
||||
'--confirm': Boolean,
|
||||
@@ -68,17 +80,36 @@ export default async function main(client: Client) {
|
||||
argv['--yes'] = argv['--confirm'];
|
||||
}
|
||||
|
||||
const cwd = argv._[1] || process.cwd();
|
||||
const yes = !!argv['--yes'];
|
||||
|
||||
const link = await ensureLink('link', client, cwd, {
|
||||
autoConfirm: !!argv['--yes'],
|
||||
forceDelete: true,
|
||||
projectName: argv['--project'],
|
||||
successEmoji: 'success',
|
||||
});
|
||||
|
||||
if (typeof link === 'number') {
|
||||
return link;
|
||||
let cwd = argv._[1];
|
||||
if (cwd) {
|
||||
client.output.warn(
|
||||
`The ${cmd('vc link <directory>')} syntax is deprecated, please use ${cmd(
|
||||
`vc link --cwd ${cwd}`
|
||||
)} instead`
|
||||
);
|
||||
} else {
|
||||
cwd = client.cwd;
|
||||
}
|
||||
|
||||
if (argv['--repo']) {
|
||||
client.output.warn(
|
||||
`The ${cmd('--repo')} flag is in alpha, please report issues`
|
||||
);
|
||||
await ensureRepoLink(client, cwd, yes);
|
||||
} else {
|
||||
const link = await ensureLink('link', client, cwd, {
|
||||
autoConfirm: yes,
|
||||
forceDelete: true,
|
||||
projectName: argv['--project'],
|
||||
successEmoji: 'success',
|
||||
});
|
||||
|
||||
if (typeof link === 'number') {
|
||||
return link;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ import getCommandFlags from '../util/get-command-flags';
|
||||
import { getPkgName, getCommandName } from '../util/pkg-name';
|
||||
import Client from '../util/client';
|
||||
import { Deployment } from '@vercel/client';
|
||||
import validatePaths from '../util/validate-paths';
|
||||
import { getLinkedProject } from '../util/projects/link';
|
||||
import { ensureLink } from '../util/link/ensure-link';
|
||||
import getScope from '../util/get-scope';
|
||||
@@ -94,7 +93,7 @@ export default async function main(client: Client) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
const { output, config } = client;
|
||||
const { cwd, output, config } = client;
|
||||
|
||||
if ('--confirm' in argv) {
|
||||
output.warn('`--confirm` is deprecated, please use `--yes` instead');
|
||||
@@ -115,19 +114,10 @@ export default async function main(client: Client) {
|
||||
|
||||
const autoConfirm = !!argv['--yes'];
|
||||
const prod = argv['--prod'] || false;
|
||||
|
||||
const meta = parseMeta(argv['--meta']);
|
||||
|
||||
let paths = [process.cwd()];
|
||||
const pathValidation = await validatePaths(client, paths);
|
||||
if (!pathValidation.valid) {
|
||||
return pathValidation.exitCode;
|
||||
}
|
||||
|
||||
const { path } = pathValidation;
|
||||
|
||||
// retrieve `project` and `org` from .vercel
|
||||
let link = await getLinkedProject(client, path);
|
||||
let link = await getLinkedProject(client, cwd);
|
||||
|
||||
if (link.status === 'error') {
|
||||
return link.exitCode;
|
||||
@@ -146,7 +136,7 @@ export default async function main(client: Client) {
|
||||
// If there's no linked project and user doesn't pass `app` arg,
|
||||
// prompt to link their current directory.
|
||||
if (status === 'not_linked' && !app) {
|
||||
const linkedProject = await ensureLink('list', client, path, {
|
||||
const linkedProject = await ensureLink('list', client, cwd, {
|
||||
autoConfirm,
|
||||
link,
|
||||
});
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user