mirror of
https://github.com/LukeHagar/vercel.git
synced 2025-12-26 03:39:11 +00:00
Compare commits
37 Commits
@vercel/no
...
@vercel/cl
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
23dce48b23 | ||
|
|
d7d308ca09 | ||
|
|
0e412361ad | ||
|
|
d563a99fb8 | ||
|
|
6ce4c2e182 | ||
|
|
e31d6d4062 | ||
|
|
f2f421b494 | ||
|
|
46836e12b5 | ||
|
|
3fc2611bf0 | ||
|
|
b4d8c411bd | ||
|
|
82b7d6980c | ||
|
|
895b233605 | ||
|
|
d9e6b5348b | ||
|
|
1934a64864 | ||
|
|
c412642668 | ||
|
|
793fe9aee1 | ||
|
|
ddc54d2ca4 | ||
|
|
39e5f0a364 | ||
|
|
43ed9ec859 | ||
|
|
8ba44fca79 | ||
|
|
27dbefaecf | ||
|
|
b4a13913c7 | ||
|
|
f842266b2e | ||
|
|
ad0cc858ed | ||
|
|
4bb7180de9 | ||
|
|
7a4faa480d | ||
|
|
421be5d738 | ||
|
|
b8eaf10974 | ||
|
|
92a4bf27cf | ||
|
|
2672838b64 | ||
|
|
1c96071ddc | ||
|
|
71cdf759da | ||
|
|
93ebd213de | ||
|
|
a32ba8f214 | ||
|
|
d416f70a6e | ||
|
|
ba9e1dd0ba | ||
|
|
d513f74b70 |
2
.github/workflows/cancel.yml
vendored
2
.github/workflows/cancel.yml
vendored
@@ -11,7 +11,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 2
|
||||
steps:
|
||||
- uses: styfle/cancel-workflow-action@0.3.2
|
||||
- uses: styfle/cancel-workflow-action@0.4.1
|
||||
with:
|
||||
workflow_id: 849295, 849296, 849297, 849298
|
||||
access_token: ${{ github.token }}
|
||||
|
||||
1
.github/workflows/test-integration-cli.yml
vendored
1
.github/workflows/test-integration-cli.yml
vendored
@@ -22,6 +22,7 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
- run: git fetch origin master --depth=10
|
||||
- run: git fetch origin ${{ github.ref }} --depth=10
|
||||
- run: git diff origin/master...HEAD --name-only
|
||||
- run: yarn install
|
||||
- run: yarn run build
|
||||
- uses: actions/setup-node@v1
|
||||
|
||||
1
.github/workflows/test-integration-dev.yml
vendored
1
.github/workflows/test-integration-dev.yml
vendored
@@ -22,6 +22,7 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
- run: git fetch origin master --depth=10
|
||||
- run: git fetch origin ${{ github.ref }} --depth=10
|
||||
- run: git diff origin/master...HEAD --name-only
|
||||
- name: Install Hugo
|
||||
if: matrix.os == 'macos-latest'
|
||||
run: curl -L -O https://github.com/gohugoio/hugo/releases/download/v0.56.0/hugo_0.56.0_macOS-64bit.tar.gz && tar -xzf hugo_0.56.0_macOS-64bit.tar.gz && mv ./hugo packages/now-cli/test/dev/fixtures/08-hugo/
|
||||
|
||||
1
.github/workflows/test-integration-once.yml
vendored
1
.github/workflows/test-integration-once.yml
vendored
@@ -17,6 +17,7 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
- run: git fetch origin master --depth=10
|
||||
- run: git fetch origin ${{ github.ref }} --depth=10
|
||||
- run: git diff origin/master...HEAD --name-only
|
||||
- run: yarn install
|
||||
- run: yarn run build
|
||||
- run: yarn test-integration-once --clean false
|
||||
|
||||
1
.github/workflows/test-unit.yml
vendored
1
.github/workflows/test-unit.yml
vendored
@@ -22,6 +22,7 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
- run: git fetch origin master --depth=10
|
||||
- run: git fetch origin ${{ github.ref }} --depth=10
|
||||
- run: git diff origin/master...HEAD --name-only
|
||||
- uses: actions/setup-node@v1
|
||||
- run: yarn install
|
||||
- run: yarn run build
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,5 +1,4 @@
|
||||
node_modules
|
||||
package-lock.json
|
||||
dist
|
||||
.vscode
|
||||
npm-debug.log
|
||||
|
||||
@@ -15,7 +15,7 @@ _Live Example: https://ionic-angular.now-examples.now.sh_
|
||||
To get started with Ionic Angular deployed with Vercel, you can use the [Ionic CLI](https://ionicframework.com/docs/cli) to initialize the project:
|
||||
|
||||
```shell
|
||||
$ npx ionic start [project-name] conference --type angular && cd [project-name]
|
||||
$ npx @ionic/cli start [project-name] conference --type angular && cd [project-name]
|
||||
```
|
||||
|
||||
### Deploying From Your Terminal
|
||||
|
||||
13585
examples/ionic-angular/package-lock.json
generated
Normal file
13585
examples/ionic-angular/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -31,7 +31,7 @@
|
||||
"@ionic-native/in-app-browser": "5.0.0-beta.15",
|
||||
"@ionic-native/splash-screen": "5.0.0-beta.15",
|
||||
"@ionic-native/status-bar": "5.0.0-beta.15",
|
||||
"@ionic/angular": "^5.0.6",
|
||||
"@ionic/angular": "^5.1.1",
|
||||
"@ionic/storage": "^2.1.3",
|
||||
"cordova-android": "^8.1.0",
|
||||
"cordova-ios": "^5.1.1",
|
||||
|
||||
14
examples/nextjs/.gitignore
vendored
14
examples/nextjs/.gitignore
vendored
@@ -11,20 +11,24 @@
|
||||
# next.js
|
||||
/.next/
|
||||
/out/
|
||||
!public/
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
.env*
|
||||
*.pem
|
||||
|
||||
# debug
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Environment Variables
|
||||
.env
|
||||
.env.build
|
||||
# local env files
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
# vercel
|
||||
.vercel
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/zeit/next.js/tree/canary/packages/create-next-app).
|
||||
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
|
||||
|
||||
## Getting Started
|
||||
|
||||
@@ -21,7 +21,7 @@ To learn more about Next.js, take a look at the following resources:
|
||||
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
|
||||
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
|
||||
|
||||
You can check out [the Next.js GitHub repository](https://github.com/zeit/next.js) - your feedback and contributions are welcome!
|
||||
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
|
||||
|
||||
## Deploy on Vercel
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
"start": "next start"
|
||||
},
|
||||
"dependencies": {
|
||||
"next": "^9.3.3",
|
||||
"react": "^16.13.0",
|
||||
"react-dom": "^16.13.0"
|
||||
"next": "9.5.1",
|
||||
"react": "16.13.1",
|
||||
"react-dom": "16.13.1"
|
||||
}
|
||||
}
|
||||
|
||||
7
examples/nextjs/pages/_app.js
Normal file
7
examples/nextjs/pages/_app.js
Normal file
@@ -0,0 +1,7 @@
|
||||
import '../styles/globals.css'
|
||||
|
||||
function MyApp({ Component, pageProps }) {
|
||||
return <Component {...pageProps} />
|
||||
}
|
||||
|
||||
export default MyApp
|
||||
6
examples/nextjs/pages/api/hello.js
Normal file
6
examples/nextjs/pages/api/hello.js
Normal file
@@ -0,0 +1,6 @@
|
||||
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
|
||||
|
||||
export default (req, res) => {
|
||||
res.statusCode = 200
|
||||
res.json({ name: 'John Doe' })
|
||||
}
|
||||
@@ -1,203 +1,65 @@
|
||||
import Head from 'next/head'
|
||||
import styles from '../styles/Home.module.css'
|
||||
|
||||
const Home = () => (
|
||||
<div className="container">
|
||||
<Head>
|
||||
<title>Create Next App</title>
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
</Head>
|
||||
export default function Home() {
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<Head>
|
||||
<title>Create Next App</title>
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
</Head>
|
||||
|
||||
<main>
|
||||
<h1 className="title">
|
||||
Welcome to <a href="https://nextjs.org">Next.js!</a>
|
||||
</h1>
|
||||
<main className={styles.main}>
|
||||
<h1 className={styles.title}>
|
||||
Welcome to <a href="https://nextjs.org">Next.js!</a>
|
||||
</h1>
|
||||
|
||||
<p className="description">
|
||||
Get started by editing <code>pages/index.js</code>
|
||||
</p>
|
||||
<p className={styles.description}>
|
||||
Get started by editing{' '}
|
||||
<code className={styles.code}>pages/index.js</code>
|
||||
</p>
|
||||
|
||||
<div className="grid">
|
||||
<a href="https://nextjs.org/docs" className="card">
|
||||
<h3>Documentation →</h3>
|
||||
<p>Find in-depth information about Next.js features and API.</p>
|
||||
</a>
|
||||
<div className={styles.grid}>
|
||||
<a href="https://nextjs.org/docs" className={styles.card}>
|
||||
<h3>Documentation →</h3>
|
||||
<p>Find in-depth information about Next.js features and API.</p>
|
||||
</a>
|
||||
|
||||
<a href="https://nextjs.org/learn" className="card">
|
||||
<h3>Learn →</h3>
|
||||
<p>Learn about Next.js in an interactive course with quizzes!</p>
|
||||
</a>
|
||||
<a href="https://nextjs.org/learn" className={styles.card}>
|
||||
<h3>Learn →</h3>
|
||||
<p>Learn about Next.js in an interactive course with quizzes!</p>
|
||||
</a>
|
||||
|
||||
<a
|
||||
href="https://github.com/vercel/next.js/tree/master/examples"
|
||||
className={styles.card}
|
||||
>
|
||||
<h3>Examples →</h3>
|
||||
<p>Discover and deploy boilerplate example Next.js projects.</p>
|
||||
</a>
|
||||
|
||||
<a
|
||||
href="https://vercel.com/import?filter=next.js&utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
|
||||
className={styles.card}
|
||||
>
|
||||
<h3>Deploy →</h3>
|
||||
<p>
|
||||
Instantly deploy your Next.js site to a public URL with Vercel.
|
||||
</p>
|
||||
</a>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<footer className={styles.footer}>
|
||||
<a
|
||||
href="https://github.com/zeit/next.js/tree/master/examples"
|
||||
className="card"
|
||||
href="https://vercel.com?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<h3>Examples →</h3>
|
||||
<p>Discover and deploy boilerplate example Next.js projects.</p>
|
||||
Powered by{' '}
|
||||
<img src="/vercel.svg" alt="Vercel Logo" className={styles.logo} />
|
||||
</a>
|
||||
|
||||
<a
|
||||
href="https://vercel.com/new?filter=next.js&utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
|
||||
className="card"
|
||||
>
|
||||
<h3>Deploy →</h3>
|
||||
<p>
|
||||
Instantly deploy your Next.js site to a public URL with Vercel.
|
||||
</p>
|
||||
</a>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
<a
|
||||
href="https://vercel.com?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Powered by <img src="/vercel.svg" alt="Vercel Logo" />
|
||||
</a>
|
||||
</footer>
|
||||
|
||||
<style jsx>{`
|
||||
.container {
|
||||
min-height: 100vh;
|
||||
padding: 0 0.5rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
main {
|
||||
padding: 5rem 0;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
footer {
|
||||
width: 100%;
|
||||
height: 100px;
|
||||
border-top: 1px solid #eaeaea;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
footer img {
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
|
||||
footer a {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.title a {
|
||||
color: #0070f3;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.title a:hover,
|
||||
.title a:focus,
|
||||
.title a:active {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.title {
|
||||
margin: 0;
|
||||
line-height: 1.15;
|
||||
font-size: 4rem;
|
||||
}
|
||||
|
||||
.title,
|
||||
.description {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.description {
|
||||
line-height: 1.5;
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
code {
|
||||
background: #fafafa;
|
||||
border-radius: 5px;
|
||||
padding: 0.75rem;
|
||||
font-size: 1.1rem;
|
||||
font-family: Menlo, Monaco, Lucida Console, Liberation Mono,
|
||||
DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace;
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
|
||||
max-width: 800px;
|
||||
margin-top: 3rem;
|
||||
}
|
||||
|
||||
.card {
|
||||
margin: 1rem;
|
||||
flex-basis: 45%;
|
||||
padding: 1.5rem;
|
||||
text-align: left;
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
border: 1px solid #eaeaea;
|
||||
border-radius: 10px;
|
||||
transition: color 0.15s ease, border-color 0.15s ease;
|
||||
}
|
||||
|
||||
.card:hover,
|
||||
.card:focus,
|
||||
.card:active {
|
||||
color: #0070f3;
|
||||
border-color: #0070f3;
|
||||
}
|
||||
|
||||
.card h3 {
|
||||
margin: 0 0 1rem 0;
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.card p {
|
||||
margin: 0;
|
||||
font-size: 1.25rem;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.grid {
|
||||
width: 100%;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
`}</style>
|
||||
|
||||
<style jsx global>{`
|
||||
html,
|
||||
body {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
|
||||
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
)
|
||||
|
||||
export default Home
|
||||
</footer>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
<svg width="70" height="16" viewBox="0 0 70 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M9.255.05l9.108 15.753H.148L9.255.05zM39.434 8.418c0-2.535-1.87-4.307-4.554-4.307-2.683 0-4.554 1.772-4.554 4.307 0 2.487 2.019 4.308 4.8 4.308 1.526 0 2.905-.566 3.79-1.6l-1.673-.96c-.517.517-1.28.837-2.117.837-1.23 0-2.29-.665-2.658-1.674l-.074-.172h6.966a3.76 3.76 0 00.074-.739zm-7.065-.738l.05-.148c.32-1.058 1.255-1.698 2.436-1.698 1.207 0 2.117.64 2.437 1.698l.05.148h-4.973zM65.945 8.418c0-2.535-1.871-4.307-4.554-4.307-2.683 0-4.554 1.772-4.554 4.307 0 2.487 2.018 4.308 4.8 4.308 1.526 0 2.904-.566 3.79-1.6l-1.673-.96c-.517.517-1.28.837-2.117.837-1.23 0-2.29-.665-2.659-1.674l-.073-.172h6.966a3.76 3.76 0 00.074-.739zM58.88 7.68l.05-.148c.32-1.058 1.255-1.698 2.436-1.698 1.206 0 2.117.64 2.437 1.698l.05.148H58.88zM54.13 7.015l1.673-.96c-.788-1.23-2.19-1.92-3.89-1.92-2.682 0-4.553 1.773-4.553 4.308 0 2.536 1.87 4.308 4.554 4.308 1.698 0 3.101-.69 3.89-1.92l-1.675-.96c-.443.738-1.23 1.157-2.215 1.157-1.55 0-2.585-1.034-2.585-2.585 0-1.55 1.034-2.585 2.585-2.585.96 0 1.772.419 2.215 1.157zM69.637 1.428h-1.97v11.077h1.97V1.428zM31.779 1.428h-2.265L25.182 8.91l-4.333-7.483H18.56l6.622 11.421 6.597-11.421zM45.71 6.4c.222 0 .444.025.665.074V4.382c-1.673.049-3.249.984-3.249 2.141V4.382h-1.97v8.123h1.97v-3.52c0-1.527 1.059-2.585 2.585-2.585z" fill="#000"/>
|
||||
</svg>
|
||||
<svg width="283" height="64" viewBox="0 0 283 64" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M141.04 16c-11.04 0-19 7.2-19 18s8.96 18 20 18c6.67 0 12.55-2.64 16.19-7.09l-7.65-4.42c-2.02 2.21-5.09 3.5-8.54 3.5-4.79 0-8.86-2.5-10.37-6.5h28.02c.22-1.12.35-2.28.35-3.5 0-10.79-7.96-17.99-19-17.99zm-9.46 14.5c1.25-3.99 4.67-6.5 9.45-6.5 4.79 0 8.21 2.51 9.45 6.5h-18.9zM248.72 16c-11.04 0-19 7.2-19 18s8.96 18 20 18c6.67 0 12.55-2.64 16.19-7.09l-7.65-4.42c-2.02 2.21-5.09 3.5-8.54 3.5-4.79 0-8.86-2.5-10.37-6.5h28.02c.22-1.12.35-2.28.35-3.5 0-10.79-7.96-17.99-19-17.99zm-9.45 14.5c1.25-3.99 4.67-6.5 9.45-6.5 4.79 0 8.21 2.51 9.45 6.5h-18.9zM200.24 34c0 6 3.92 10 10 10 4.12 0 7.21-1.87 8.8-4.92l7.68 4.43c-3.18 5.3-9.14 8.49-16.48 8.49-11.05 0-19-7.2-19-18s7.96-18 19-18c7.34 0 13.29 3.19 16.48 8.49l-7.68 4.43c-1.59-3.05-4.68-4.92-8.8-4.92-6.07 0-10 4-10 10zm82.48-29v46h-9V5h9zM36.95 0L73.9 64H0L36.95 0zm92.38 5l-27.71 48L73.91 5H84.3l17.32 30 17.32-30h10.39zm58.91 12v9.69c-1-.29-2.06-.49-3.2-.49-5.81 0-10 4-10 10V51h-9V17h9v9.2c0-5.08 5.91-9.2 13.2-9.2z" fill="#000"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.1 KiB |
123
examples/nextjs/styles/Home.module.css
Normal file
123
examples/nextjs/styles/Home.module.css
Normal file
@@ -0,0 +1,123 @@
|
||||
.container {
|
||||
min-height: 100vh;
|
||||
padding: 0 0.5rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.main {
|
||||
padding: 5rem 0;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.footer {
|
||||
width: 100%;
|
||||
height: 100px;
|
||||
border-top: 1px solid #eaeaea;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.footer img {
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
|
||||
.footer a {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.title a {
|
||||
color: #0070f3;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.title a:hover,
|
||||
.title a:focus,
|
||||
.title a:active {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.title {
|
||||
margin: 0;
|
||||
line-height: 1.15;
|
||||
font-size: 4rem;
|
||||
}
|
||||
|
||||
.title,
|
||||
.description {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.description {
|
||||
line-height: 1.5;
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.code {
|
||||
background: #fafafa;
|
||||
border-radius: 5px;
|
||||
padding: 0.75rem;
|
||||
font-size: 1.1rem;
|
||||
font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono,
|
||||
Bitstream Vera Sans Mono, Courier New, monospace;
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
|
||||
max-width: 800px;
|
||||
margin-top: 3rem;
|
||||
}
|
||||
|
||||
.card {
|
||||
margin: 1rem;
|
||||
flex-basis: 45%;
|
||||
padding: 1.5rem;
|
||||
text-align: left;
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
border: 1px solid #eaeaea;
|
||||
border-radius: 10px;
|
||||
transition: color 0.15s ease, border-color 0.15s ease;
|
||||
}
|
||||
|
||||
.card:hover,
|
||||
.card:focus,
|
||||
.card:active {
|
||||
color: #0070f3;
|
||||
border-color: #0070f3;
|
||||
}
|
||||
|
||||
.card h3 {
|
||||
margin: 0 0 1rem 0;
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.card p {
|
||||
margin: 0;
|
||||
font-size: 1.25rem;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.logo {
|
||||
height: 1em;
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.grid {
|
||||
width: 100%;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
16
examples/nextjs/styles/globals.css
Normal file
16
examples/nextjs/styles/globals.css
Normal file
@@ -0,0 +1,16 @@
|
||||
html,
|
||||
body {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
|
||||
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||

|
||||

|
||||
|
||||
# RedwoodJS Example
|
||||
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@redwoodjs/api": "0.14.0"
|
||||
"@redwoodjs/api": "0.15.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@redwoodjs/core": "0.14.0"
|
||||
"@redwoodjs/core": "0.15.0"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": "@redwoodjs/eslint-config"
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
"defaults"
|
||||
],
|
||||
"dependencies": {
|
||||
"@redwoodjs/router": "0.14.0",
|
||||
"@redwoodjs/web": "0.14.0",
|
||||
"@redwoodjs/router": "0.15.0",
|
||||
"@redwoodjs/web": "0.15.0",
|
||||
"prop-types": "^15.7.2",
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1"
|
||||
|
||||
14339
examples/redwoodjs/yarn.lock
Normal file
14339
examples/redwoodjs/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
@@ -2,17 +2,17 @@
|
||||
"name": "svelte-app",
|
||||
"version": "1.0.0",
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-commonjs": "^13.0.0",
|
||||
"@rollup/plugin-node-resolve": "^8.1.0",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"rollup": "^1.10.1",
|
||||
"rollup-plugin-commonjs": "^9.3.4",
|
||||
"rollup": "^2.18.0",
|
||||
"rollup-plugin-livereload": "^1.0.0",
|
||||
"rollup-plugin-node-resolve": "^4.2.3",
|
||||
"rollup-plugin-svelte": "^5.0.3",
|
||||
"rollup-plugin-terser": "^4.0.4",
|
||||
"rollup-plugin-terser": "^6.1.0",
|
||||
"svelte": "^3.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"sirv-cli": "^0.4.4"
|
||||
"sirv-cli": "^1.0.1"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "rollup -c",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import svelte from 'rollup-plugin-svelte';
|
||||
import resolve from 'rollup-plugin-node-resolve';
|
||||
import commonjs from 'rollup-plugin-commonjs';
|
||||
import resolve from '@rollup/plugin-node-resolve';
|
||||
import commonjs from '@rollup/plugin-commonjs';
|
||||
import livereload from 'rollup-plugin-livereload';
|
||||
import { terser } from 'rollup-plugin-terser';
|
||||
|
||||
|
||||
@@ -686,7 +686,7 @@
|
||||
"name": "RedwoodJS",
|
||||
"slug": "redwoodjs",
|
||||
"demo": "https://redwoodjs.now-examples.now.sh",
|
||||
"logo": "https://raw.githubusercontent.com/vercel/vercel/master/packages/frameworks/logos/redwood.svg",
|
||||
"logo": "https://raw.githubusercontent.com/vercel/vercel/master/packages/frameworks/logos/redwoodjs.svg",
|
||||
"tagline": "RedwoodJS is a full-stack framework for the Jamstack.",
|
||||
"description": "A RedwoodJS app, bootstraped with create-redwood-app.",
|
||||
"website": "https://redwoodjs.com",
|
||||
@@ -703,7 +703,7 @@
|
||||
"value": "yarn rw db up --no-db-client --auto-approve && yarn rw build"
|
||||
},
|
||||
"devCommand": {
|
||||
"value": "yarn rw dev"
|
||||
"value": "yarn rw dev --fwd=\"--port=$PORT --open=false\""
|
||||
},
|
||||
"outputDirectory": {
|
||||
"value": "RedwoodJS default"
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
<svg fill="none" height="1000" viewBox="0 0 917 1000" width="917" xmlns="http://www.w3.org/2000/svg"><path clip-rule="evenodd" d="m249.557 144.582 194.171 132.54c4.383 2.918 9.502 4.516 14.755 4.606 5.261-.038 10.394-1.641 14.755-4.606l194.319-132.986c7.55-5.406 11.714-14.418 10.957-23.717-.757-9.298-6.322-17.507-14.646-21.6024l-194.171-96.13614c-7.366-3.573948-15.947-3.573948-23.313 0l-193.581 96.13614c-8.474 4.1174-14.113 12.4854-14.783 21.9354-.67 9.451 3.73 18.541 11.537 23.83zm274.879 174.144c.016 8.789 4.318 17.01 11.509 21.991l155.662 106.389c9.965 6.87 23.298 6.012 32.313-2.081l130.579-116.789c5.819-5.199 9.051-12.729 8.823-20.56s-3.892-15.158-10.004-20.005l-124.677-99.702c-9.062-7.199-21.704-7.68-31.28-1.189l-161.416 110.401c-7.064 4.89-11.35 12.914-11.509 21.545zm-387.163 144.724c6.292 5.652 9.526 13.988 8.706 22.437-.817 8.499-5.726 16.052-13.132 20.208l-92.9545 55.72c-9.4227 5.633-21.32 4.82-29.90183-2.041-8.5818-6.861-12.06543-18.346-8.75546-28.865l34.37839-108.172c2.6969-8.57 9.5328-15.175 18.1483-17.533 8.609-2.505 17.8924-.309 24.4928 5.795zm504.168 11.293-168.056-115.007c-8.931-6.01-20.578-6.01-29.509 0l-168.056 115.007c-6.684 4.626-10.919 12.061-11.509 20.208-.435 8.203 2.816 16.169 8.853 21.693l167.909 150.222c4.842 4.319 11.089 6.698 17.558 6.687 6.465-.002 12.708-2.38 17.558-6.687l167.908-150.222c6.056-5.501 9.265-13.5 8.705-21.693-.469-8.146-4.666-15.612-11.361-20.208zm-448.247-29.718-130.4316-116.79c-5.8687-5.331-9.1073-12.995-8.8528-20.95.1419-7.841 3.7705-15.204 9.8856-20.06l124.6768-100.296c9.126-7.179 21.793-7.658 31.428-1.189l161.269 110.401c7.484 4.908 11.998 13.293 11.998 22.288 0 8.994-4.514 17.38-11.998 22.288l-155.515 106.388c-10.025 6.841-23.376 5.985-32.46-2.08zm669.715 167.756-132.792-79.495c-9.862-5.943-22.415-4.739-30.985 2.972l-162.301 144.873c-6.846 6.114-10.062 15.362-8.499 24.441 1.563 9.08 7.681 16.698 16.171 20.135l225.157 91.233c3.088 1.283 6.397 1.939 9.738 1.932 10.449.033 19.936-6.142 24.197-15.751l69.79-156.314c5.68-12.37 1.157-27.062-10.476-34.026zm18.443-190.043 34.379 108.171h-.295c2.542 8.091 1.097 16.919-3.889 23.761-4.986 6.841-12.915 10.876-21.342 10.86-4.728.016-9.37-1.269-13.427-3.715l-93.102-55.72c-7.254-4.243-11.992-11.789-12.689-20.208-.87-8.456 2.373-16.814 8.705-22.436l59.019-52.6c6.668-5.976 15.881-8.156 24.493-5.795 8.609 2.459 15.423 9.098 18.148 17.682zm-492.511 282.761c1.587-9.042-1.597-18.266-8.41-24.368l-162.302-144.873c-8.57-7.711-21.123-8.915-30.985-2.972l-132.7921 79.495c-11.4977 6.995-16.0467 21.502-10.6233 33.878l69.9374 156.314c5.794 13.034 20.774 19.134 33.936 13.818l225.009-91.232c8.492-3.407 14.632-10.995 16.23-20.06zm79.675 44.577 180.598 73.105c8.83 3.779 14.93 12.084 15.935 21.694 1.143 9.729-3.178 19.291-11.214 24.814l-180.745 125.556c-4.331 3.043-9.473 4.7-14.754 4.755-5.277-.082-10.411-1.737-14.755-4.755l-180.597-125.556c-8.066-5.508-12.439-15.061-11.362-24.814 1.206-9.71 7.526-18.006 16.526-21.694l180.597-73.105c6.351-2.532 13.421-2.532 19.771 0z" fill="#bf4722" fill-rule="evenodd"/></svg>
|
||||
|
Before Width: | Height: | Size: 3.0 KiB |
1
packages/frameworks/logos/redwoodjs.svg
Normal file
1
packages/frameworks/logos/redwoodjs.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg fill="none" width="48" height="48" viewBox="0 0 917 1000" xmlns="http://www.w3.org/2000/svg"><path clip-rule="evenodd" d="m249.557 144.582 194.171 132.54c4.383 2.918 9.502 4.516 14.755 4.606 5.261-.038 10.394-1.641 14.755-4.606l194.319-132.986c7.55-5.406 11.714-14.418 10.957-23.717-.757-9.298-6.322-17.507-14.646-21.6024l-194.171-96.13614c-7.366-3.573948-15.947-3.573948-23.313 0l-193.581 96.13614c-8.474 4.1174-14.113 12.4854-14.783 21.9354-.67 9.451 3.73 18.541 11.537 23.83zm274.879 174.144c.016 8.789 4.318 17.01 11.509 21.991l155.662 106.389c9.965 6.87 23.298 6.012 32.313-2.081l130.579-116.789c5.819-5.199 9.051-12.729 8.823-20.56s-3.892-15.158-10.004-20.005l-124.677-99.702c-9.062-7.199-21.704-7.68-31.28-1.189l-161.416 110.401c-7.064 4.89-11.35 12.914-11.509 21.545zm-387.163 144.724c6.292 5.652 9.526 13.988 8.706 22.437-.817 8.499-5.726 16.052-13.132 20.208l-92.9545 55.72c-9.4227 5.633-21.32 4.82-29.90183-2.041-8.5818-6.861-12.06543-18.346-8.75546-28.865l34.37839-108.172c2.6969-8.57 9.5328-15.175 18.1483-17.533 8.609-2.505 17.8924-.309 24.4928 5.795zm504.168 11.293-168.056-115.007c-8.931-6.01-20.578-6.01-29.509 0l-168.056 115.007c-6.684 4.626-10.919 12.061-11.509 20.208-.435 8.203 2.816 16.169 8.853 21.693l167.909 150.222c4.842 4.319 11.089 6.698 17.558 6.687 6.465-.002 12.708-2.38 17.558-6.687l167.908-150.222c6.056-5.501 9.265-13.5 8.705-21.693-.469-8.146-4.666-15.612-11.361-20.208zm-448.247-29.718-130.4316-116.79c-5.8687-5.331-9.1073-12.995-8.8528-20.95.1419-7.841 3.7705-15.204 9.8856-20.06l124.6768-100.296c9.126-7.179 21.793-7.658 31.428-1.189l161.269 110.401c7.484 4.908 11.998 13.293 11.998 22.288 0 8.994-4.514 17.38-11.998 22.288l-155.515 106.388c-10.025 6.841-23.376 5.985-32.46-2.08zm669.715 167.756-132.792-79.495c-9.862-5.943-22.415-4.739-30.985 2.972l-162.301 144.873c-6.846 6.114-10.062 15.362-8.499 24.441 1.563 9.08 7.681 16.698 16.171 20.135l225.157 91.233c3.088 1.283 6.397 1.939 9.738 1.932 10.449.033 19.936-6.142 24.197-15.751l69.79-156.314c5.68-12.37 1.157-27.062-10.476-34.026zm18.443-190.043 34.379 108.171h-.295c2.542 8.091 1.097 16.919-3.889 23.761-4.986 6.841-12.915 10.876-21.342 10.86-4.728.016-9.37-1.269-13.427-3.715l-93.102-55.72c-7.254-4.243-11.992-11.789-12.689-20.208-.87-8.456 2.373-16.814 8.705-22.436l59.019-52.6c6.668-5.976 15.881-8.156 24.493-5.795 8.609 2.459 15.423 9.098 18.148 17.682zm-492.511 282.761c1.587-9.042-1.597-18.266-8.41-24.368l-162.302-144.873c-8.57-7.711-21.123-8.915-30.985-2.972l-132.7921 79.495c-11.4977 6.995-16.0467 21.502-10.6233 33.878l69.9374 156.314c5.794 13.034 20.774 19.134 33.936 13.818l225.009-91.232c8.492-3.407 14.632-10.995 16.23-20.06zm79.675 44.577 180.598 73.105c8.83 3.779 14.93 12.084 15.935 21.694 1.143 9.729-3.178 19.291-11.214 24.814l-180.745 125.556c-4.331 3.043-9.473 4.7-14.754 4.755-5.277-.082-10.411-1.737-14.755-4.755l-180.597-125.556c-8.066-5.508-12.439-15.061-11.362-24.814 1.206-9.71 7.526-18.006 16.526-21.694l180.597-73.105c6.351-2.532 13.421-2.532 19.771 0z" fill="#bf4722" fill-rule="evenodd"/></svg>
|
||||
|
After Width: | Height: | Size: 3.0 KiB |
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/frameworks",
|
||||
"version": "0.0.18-canary.1",
|
||||
"version": "0.0.18-canary.3",
|
||||
"main": "frameworks.json",
|
||||
"license": "UNLICENSED",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/build-utils",
|
||||
"version": "2.4.3-canary.2",
|
||||
"version": "2.4.3-canary.3",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.js",
|
||||
|
||||
@@ -450,7 +450,7 @@ function detectFrontBuilder(
|
||||
config.outputDirectory = projectSettings.outputDirectory;
|
||||
}
|
||||
|
||||
if (pkg) {
|
||||
if (pkg && framework !== null) {
|
||||
const deps: PackageJson['dependencies'] = {
|
||||
...pkg.dependencies,
|
||||
...pkg.devDependencies,
|
||||
|
||||
@@ -1080,6 +1080,51 @@ describe('Test `detectBuilders` with `featHandleMiss=true`', () => {
|
||||
expect(errorRoutes).toStrictEqual([]);
|
||||
});
|
||||
|
||||
it('Using "Other" framework with Storybook should NOT autodetect Next.js', async () => {
|
||||
const pkg = {
|
||||
scripts: {
|
||||
dev: 'next dev',
|
||||
build: 'next build',
|
||||
storybook: 'start-storybook -p 6006',
|
||||
'build-storybook': 'build-storybook',
|
||||
},
|
||||
dependencies: {
|
||||
next: '9.3.5',
|
||||
react: '16.13.1',
|
||||
'react-dom': '16.13.1',
|
||||
},
|
||||
devDependencies: {
|
||||
'@babel/core': '7.9.0',
|
||||
'@storybook/addon-links': '5.3.18',
|
||||
'@storybook/addons': '5.3.18',
|
||||
'@storybook/react': '5.3.18',
|
||||
},
|
||||
};
|
||||
const files = ['package.json', 'pages/api/foo.js', 'index.html'];
|
||||
const projectSettings = {
|
||||
framework: null, // Selected "Other" framework
|
||||
buildCommand: 'yarn build-storybook',
|
||||
};
|
||||
|
||||
const { builders, errorRoutes } = await detectBuilders(files, pkg, {
|
||||
projectSettings,
|
||||
featHandleMiss,
|
||||
});
|
||||
|
||||
expect(builders).toEqual([
|
||||
{
|
||||
use: '@vercel/static-build',
|
||||
src: 'package.json',
|
||||
config: {
|
||||
zeroConfig: true,
|
||||
buildCommand: projectSettings.buildCommand,
|
||||
},
|
||||
},
|
||||
]);
|
||||
expect(errorRoutes!.length).toBe(1);
|
||||
expect((errorRoutes![0] as Source).status).toBe(404);
|
||||
});
|
||||
|
||||
it('api + raw static', async () => {
|
||||
const files = ['api/endpoint.js', 'index.html', 'favicon.ico'];
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "vercel",
|
||||
"version": "20.0.0-canary.7",
|
||||
"version": "20.0.0-canary.15",
|
||||
"preferGlobal": true,
|
||||
"license": "Apache-2.0",
|
||||
"description": "The command-line interface for Vercel",
|
||||
@@ -62,14 +62,14 @@
|
||||
"node": ">= 10"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vercel/build-utils": "2.4.3-canary.2",
|
||||
"@vercel/build-utils": "2.4.3-canary.3",
|
||||
"@vercel/go": "1.1.5-canary.0",
|
||||
"@vercel/next": "2.6.15",
|
||||
"@vercel/node": "1.7.4",
|
||||
"@vercel/next": "2.6.20-canary.0",
|
||||
"@vercel/node": "1.7.5-canary.1",
|
||||
"@vercel/python": "1.2.2",
|
||||
"@vercel/redwood": "0.0.2-canary.1",
|
||||
"@vercel/redwood": "0.0.2-canary.3",
|
||||
"@vercel/ruby": "1.2.3",
|
||||
"@vercel/static-build": "0.17.7-canary.1",
|
||||
"@vercel/static-build": "0.17.7-canary.3",
|
||||
"update-notifier": "4.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -7,7 +7,7 @@ import * as ERRORS from '../../util/errors-ts';
|
||||
import { Output } from '../../util/output';
|
||||
import deleteCertById from '../../util/certs/delete-cert-by-id';
|
||||
import getCertById from '../../util/certs/get-cert-by-id';
|
||||
import getCertsForDomain from '../../util/certs/get-certs-for-domain';
|
||||
import { getCustomCertsForDomain } from '../../util/certs/get-custom-certs-for-domain';
|
||||
import Client from '../../util/client';
|
||||
import getScope from '../../util/get-scope';
|
||||
import stamp from '../../util/output/stamp';
|
||||
@@ -66,9 +66,17 @@ async function rm(
|
||||
}
|
||||
|
||||
if (certs.length === 0) {
|
||||
output.error(
|
||||
`No certificates found by id "${id}" under ${chalk.bold(contextName)}`
|
||||
);
|
||||
if (id.includes('.')) {
|
||||
output.error(
|
||||
`No custom certificates found for "${id}" under ${chalk.bold(
|
||||
contextName
|
||||
)}`
|
||||
);
|
||||
} else {
|
||||
output.error(
|
||||
`No certificates found by id "${id}" under ${chalk.bold(contextName)}`
|
||||
);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -101,7 +109,7 @@ async function getCertsToDelete(
|
||||
) {
|
||||
const cert = await getCertById(client, id);
|
||||
if (cert instanceof ERRORS.CertNotFound) {
|
||||
const certs = await getCertsForDomain(output, client, contextName, id);
|
||||
const certs = await getCustomCertsForDomain(client, contextName, id);
|
||||
if (certs instanceof ERRORS.CertsPermissionDenied) {
|
||||
return certs;
|
||||
}
|
||||
@@ -125,12 +133,7 @@ function readConfirmation(output: Output, msg: string, certs: Cert[]) {
|
||||
process.stdin
|
||||
.on('data', d => {
|
||||
process.stdin.pause();
|
||||
resolve(
|
||||
d
|
||||
.toString()
|
||||
.trim()
|
||||
.toLowerCase() === 'y'
|
||||
);
|
||||
resolve(d.toString().trim().toLowerCase() === 'y');
|
||||
})
|
||||
.resume();
|
||||
});
|
||||
|
||||
@@ -128,7 +128,7 @@ export default async function add(
|
||||
return 1;
|
||||
}
|
||||
|
||||
const domainConfig = await getDomainConfig(client, contextName, domainName);
|
||||
const domainConfig = await getDomainConfig(client, domainName);
|
||||
|
||||
if (domainConfig.misconfigured) {
|
||||
output.warn(
|
||||
@@ -142,7 +142,7 @@ export default async function add(
|
||||
);
|
||||
output.print(
|
||||
` ${chalk.grey('b)')} ` +
|
||||
`Change your domain nameservers to the intended set`
|
||||
`Change your Domains's nameservers to the intended set`
|
||||
);
|
||||
output.print(
|
||||
`\n${formatNSTable(
|
||||
|
||||
@@ -71,8 +71,9 @@ export default async function buy(
|
||||
|
||||
const availableStamp = stamp();
|
||||
const domainPrice = await getDomainPrice(client, domainName);
|
||||
if (domainPrice instanceof ERRORS.UnsupportedTLD) {
|
||||
output.error(`The TLD for ${param(domainName)} is not supported.`);
|
||||
|
||||
if (domainPrice instanceof Error) {
|
||||
output.prettyError(domainPrice);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ import inspect from './inspect';
|
||||
import ls from './ls';
|
||||
import rm from './rm';
|
||||
import move from './move';
|
||||
import verify from './verify';
|
||||
import { getPkgName } from '../../util/pkg-name';
|
||||
|
||||
const help = () => {
|
||||
@@ -81,6 +82,7 @@ const COMMAND_CONFIG = {
|
||||
move: ['move'],
|
||||
rm: ['rm', 'remove'],
|
||||
transferIn: ['transfer-in'],
|
||||
verify: ['verify'],
|
||||
};
|
||||
|
||||
export default async function main(ctx: NowContext) {
|
||||
@@ -119,6 +121,8 @@ export default async function main(ctx: NowContext) {
|
||||
return rm(ctx, argv, args, output);
|
||||
case 'transferIn':
|
||||
return transferIn(ctx, argv, args, output);
|
||||
case 'verify':
|
||||
return verify(ctx, argv, args, output);
|
||||
default:
|
||||
return ls(ctx, argv, args, output);
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@ import getDomainPrice from '../../util/domains/get-domain-price';
|
||||
import { getCommandName } from '../../util/pkg-name';
|
||||
import { getDomainConfig } from '../../util/domains/get-domain-config';
|
||||
import code from '../../util/output/code';
|
||||
import wait from '../../util/output/wait';
|
||||
import { getDomainRegistrar } from '../../util/domains/get-domain-registrar';
|
||||
|
||||
type Options = {
|
||||
'--debug': boolean;
|
||||
@@ -67,38 +69,26 @@ export default async function inspect(
|
||||
}
|
||||
|
||||
output.debug(`Fetching domain info`);
|
||||
const [domain, renewalPrice] = await Promise.all([
|
||||
getDomainByName(client, contextName, domainName),
|
||||
getDomainPrice(client, domainName, 'renewal')
|
||||
.then(res => (res instanceof Error ? null : res.price))
|
||||
.catch(() => null),
|
||||
]);
|
||||
if (!domain || domain instanceof DomainNotFound) {
|
||||
output.error(
|
||||
`Domain not found by "${domainName}" under ${chalk.bold(contextName)}`
|
||||
);
|
||||
output.log(`Run ${getCommandName(`domains ls`)} to see your domains.`);
|
||||
return 1;
|
||||
|
||||
const cancelWait = wait(
|
||||
`Fetching domain ${domainName} under ${chalk.bold(contextName)}`
|
||||
);
|
||||
|
||||
const information = await fetchInformation({
|
||||
output,
|
||||
client,
|
||||
contextName,
|
||||
domainName,
|
||||
cancelWait,
|
||||
}).finally(() => {
|
||||
cancelWait();
|
||||
});
|
||||
|
||||
if (typeof information === 'number') {
|
||||
return information;
|
||||
}
|
||||
|
||||
if (domain instanceof DomainPermissionDenied) {
|
||||
output.error(
|
||||
`You don't have access to the domain ${domainName} under ${chalk.bold(
|
||||
contextName
|
||||
)}`
|
||||
);
|
||||
output.log(`Run ${getCommandName(`domains ls`)} to see your domains.`);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const projects = await findProjectsForDomain(client, domainName);
|
||||
|
||||
if (projects instanceof Error) {
|
||||
output.prettyError(projects);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const domainConfig = await getDomainConfig(client, contextName, domainName);
|
||||
const { domain, projects, renewalPrice, domainConfig } = information;
|
||||
|
||||
output.log(
|
||||
`Domain ${domainName} found under ${chalk.bold(contextName)} ${chalk.gray(
|
||||
@@ -108,46 +98,27 @@ export default async function inspect(
|
||||
output.print('\n');
|
||||
output.print(chalk.bold(' General\n\n'));
|
||||
output.print(` ${chalk.cyan('Name')}\t\t\t${domain.name}\n`);
|
||||
output.print(` ${chalk.cyan('Service Type')}\t\t${domain.serviceType}\n`);
|
||||
output.print(
|
||||
` ${chalk.cyan('Ordered At')}\t\t\t${formatDate(domain.orderedAt)}\n`
|
||||
);
|
||||
output.print(
|
||||
` ${chalk.cyan('Transfer Started At')}\t\t${formatDate(
|
||||
domain.transferStartedAt
|
||||
)}\n`
|
||||
);
|
||||
output.print(
|
||||
` ${chalk.cyan('Created At')}\t\t\t${formatDate(domain.createdAt)}\n`
|
||||
);
|
||||
output.print(
|
||||
` ${chalk.cyan('Bought At')}\t\t\t${formatDate(domain.boughtAt)}\n`
|
||||
);
|
||||
output.print(
|
||||
` ${chalk.cyan('Transferred At')}\t\t${formatDate(
|
||||
domain.transferredAt
|
||||
)}\n`
|
||||
` ${chalk.cyan('Registrar')}\t\t\t${getDomainRegistrar(domain)}\n`
|
||||
);
|
||||
output.print(
|
||||
` ${chalk.cyan('Expires At')}\t\t\t${formatDate(domain.expiresAt)}\n`
|
||||
);
|
||||
output.print(
|
||||
` ${chalk.cyan('NS Verified At')}\t\t${formatDate(
|
||||
domain.nsVerifiedAt
|
||||
)}\n`
|
||||
);
|
||||
output.print(
|
||||
` ${chalk.cyan('TXT Verified At')}\t\t${formatDate(
|
||||
domain.txtVerifiedAt
|
||||
)}\n`
|
||||
);
|
||||
output.print(` ${chalk.cyan('Edge Network')}\t\t${true}\n`);
|
||||
|
||||
if (renewalPrice && domain.boughtAt) {
|
||||
output.print(
|
||||
` ${chalk.cyan('Renewal Price')}\t\t$${renewalPrice} USD\n`
|
||||
);
|
||||
}
|
||||
output.print(` ${chalk.cyan('CDN Enabled')}\t\t\t${true}\n`);
|
||||
|
||||
output.print(
|
||||
` ${chalk.cyan('Creator')}\t\t\t${domain.creator.username}\n`
|
||||
);
|
||||
output.print(
|
||||
` ${chalk.cyan('Created At')}\t\t\t${formatDate(domain.createdAt)}\n`
|
||||
);
|
||||
|
||||
output.print('\n');
|
||||
|
||||
output.print(chalk.bold(' Nameservers\n\n'));
|
||||
@@ -158,26 +129,6 @@ export default async function inspect(
|
||||
);
|
||||
output.print('\n');
|
||||
|
||||
if (domainConfig.misconfigured) {
|
||||
output.warn(
|
||||
`This domain is not configured properly. To configure it you should either:`
|
||||
);
|
||||
output.print(
|
||||
` ${chalk.grey('a)')} ` +
|
||||
`Set the following record on your DNS provider to continue: ` +
|
||||
`${code(`A ${domainName} 76.76.21.21`)} ` +
|
||||
`${chalk.grey('[recommended]')}\n`
|
||||
);
|
||||
output.print(
|
||||
` ${chalk.grey('b)')} ` +
|
||||
`Change your domain nameservers to the intended set detailed above.\n\n`
|
||||
);
|
||||
output.print(
|
||||
` We will run a verification for you and you will receive an email upon completion.\n`
|
||||
);
|
||||
output.print(' Read more: https://vercel.link/domain-configuration\n\n');
|
||||
}
|
||||
|
||||
if (Array.isArray(projects) && projects.length > 0) {
|
||||
output.print(chalk.bold(' Projects\n'));
|
||||
|
||||
@@ -208,8 +159,109 @@ export default async function inspect(
|
||||
.join('\n')
|
||||
);
|
||||
|
||||
output.print('\n\n');
|
||||
output.print('\n');
|
||||
}
|
||||
|
||||
if (domainConfig.misconfigured) {
|
||||
output.warn(
|
||||
`This domain is not configured properly. To configure it you should either:`,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
{
|
||||
boxen: {
|
||||
margin: {
|
||||
left: 2,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
top: 0,
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
output.print(
|
||||
` ${chalk.grey('a)')} ` +
|
||||
`Set the following record on your DNS provider to continue: ` +
|
||||
`${code(`A ${domainName} 76.76.21.21`)} ` +
|
||||
`${chalk.grey('[recommended]')}\n`
|
||||
);
|
||||
output.print(
|
||||
` ${chalk.grey('b)')} ` +
|
||||
`Change your Domains's nameservers to the intended set detailed above.\n\n`
|
||||
);
|
||||
output.print(
|
||||
` We will run a verification for you and you will receive an email upon completion.\n`
|
||||
);
|
||||
|
||||
const contextNameConst = contextName;
|
||||
const projectNames = Array.from(
|
||||
new Set(projects.map(project => project.name))
|
||||
);
|
||||
|
||||
if (projectNames.length) {
|
||||
projectNames.forEach((name, index) => {
|
||||
const prefix = index === 0 ? ' Read more:' : ' '.repeat(12);
|
||||
output.print(
|
||||
`${prefix} https://vercel.com/${contextNameConst}/${name}/settings/domains\n`
|
||||
);
|
||||
});
|
||||
} else {
|
||||
output.print(` Read more: https://vercel.link/domain-configuration\n`);
|
||||
}
|
||||
|
||||
output.print('\n');
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
async function fetchInformation({
|
||||
output,
|
||||
client,
|
||||
contextName,
|
||||
domainName,
|
||||
cancelWait,
|
||||
}: {
|
||||
output: Output;
|
||||
client: Client;
|
||||
contextName: string;
|
||||
domainName: string;
|
||||
cancelWait: () => void;
|
||||
}) {
|
||||
const [domain, renewalPrice] = await Promise.all([
|
||||
getDomainByName(client, contextName, domainName, { ignoreWait: true }),
|
||||
getDomainPrice(client, domainName, 'renewal')
|
||||
.then(res => (res instanceof Error ? null : res.price))
|
||||
.catch(() => null),
|
||||
]);
|
||||
|
||||
if (domain instanceof DomainNotFound) {
|
||||
cancelWait();
|
||||
output.prettyError(domain);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (domain instanceof DomainPermissionDenied) {
|
||||
cancelWait();
|
||||
output.prettyError(domain);
|
||||
output.log(`Run ${getCommandName(`domains ls`)} to see your domains.`);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const projects = await findProjectsForDomain(client, domainName);
|
||||
|
||||
if (projects instanceof Error) {
|
||||
cancelWait();
|
||||
output.prettyError(projects);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const domainConfig = await getDomainConfig(client, domainName);
|
||||
|
||||
return {
|
||||
domain,
|
||||
projects,
|
||||
renewalPrice,
|
||||
domainConfig,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import ms from 'ms';
|
||||
import psl from 'psl';
|
||||
import chalk from 'chalk';
|
||||
import plural from 'pluralize';
|
||||
|
||||
import wait from '../../util/output/wait';
|
||||
import Client from '../../util/client';
|
||||
import getDomains from '../../util/domains/get-domains';
|
||||
import getScope from '../../util/get-scope';
|
||||
@@ -10,28 +10,17 @@ import stamp from '../../util/output/stamp';
|
||||
import { Output } from '../../util/output';
|
||||
import formatTable from '../../util/format-table';
|
||||
import { formatDateWithoutTime } from '../../util/format-date';
|
||||
import { Domain, Project, NowContext } from '../../types';
|
||||
import { getProjectsWithDomains } from '../../util/projects/get-projects-with-domains';
|
||||
import { Domain, NowContext } from '../../types';
|
||||
import getCommandFlags from '../../util/get-command-flags';
|
||||
import { getCommandName } from '../../util/pkg-name';
|
||||
import isDomainExternal from '../../util/domains/is-domain-external';
|
||||
import { isPublicSuffix } from '../../util/domains/is-public-suffix';
|
||||
import { getDomainRegistrar } from '../../util/domains/get-domain-registrar';
|
||||
|
||||
type Options = {
|
||||
'--debug': boolean;
|
||||
'--next': number;
|
||||
};
|
||||
|
||||
interface DomainInfo {
|
||||
domain: string;
|
||||
apexDomain: string;
|
||||
projectName: string | null;
|
||||
dns: 'Vercel' | 'External';
|
||||
configured: boolean;
|
||||
expiresAt: number | null;
|
||||
createdAt: number | null;
|
||||
}
|
||||
|
||||
export default async function ls(
|
||||
ctx: NowContext,
|
||||
opts: Options,
|
||||
@@ -75,29 +64,21 @@ export default async function ls(
|
||||
return 1;
|
||||
}
|
||||
|
||||
const [{ domains, pagination }, projects] = await Promise.all([
|
||||
getDomains(client, contextName),
|
||||
getProjectsWithDomains(client),
|
||||
] as const);
|
||||
const cancelWait = wait(`Fetching domains under ${chalk.bold(contextName)}`);
|
||||
|
||||
if (projects instanceof Error) {
|
||||
output.prettyError(projects);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const domainsInfo = createDomainsInfo(domains, projects);
|
||||
const { domains, pagination } = await getDomains(client).finally(() => {
|
||||
cancelWait();
|
||||
});
|
||||
|
||||
output.log(
|
||||
`${plural(
|
||||
'project domain',
|
||||
domainsInfo.length,
|
||||
true
|
||||
)} found under ${chalk.bold(contextName)} ${chalk.gray(lsStamp())}`
|
||||
`${plural('Domain', domains.length, true)} found under ${chalk.bold(
|
||||
contextName
|
||||
)} ${chalk.gray(lsStamp())}`
|
||||
);
|
||||
|
||||
if (domainsInfo.length > 0) {
|
||||
if (domains.length > 0) {
|
||||
output.print(
|
||||
formatDomainsTable(domainsInfo).replace(/^(.*)/gm, `${' '.repeat(3)}$1`)
|
||||
formatDomainsTable(domains).replace(/^(.*)/gm, `${' '.repeat(1)}$1`)
|
||||
);
|
||||
output.print('\n\n');
|
||||
}
|
||||
@@ -105,7 +86,7 @@ export default async function ls(
|
||||
if (pagination && pagination.count === 20) {
|
||||
const flags = getCommandFlags(opts, ['_', '--next']);
|
||||
output.log(
|
||||
`To display the next page run ${getCommandName(
|
||||
`To display the next page, run ${getCommandName(
|
||||
`domains ls${flags} --next ${pagination.next}`
|
||||
)}`
|
||||
);
|
||||
@@ -114,92 +95,26 @@ export default async function ls(
|
||||
return 0;
|
||||
}
|
||||
|
||||
function createDomainsInfo(domains: Domain[], projects: Project[]) {
|
||||
const info = new Map<string, DomainInfo>();
|
||||
|
||||
domains.forEach(domain => {
|
||||
info.set(domain.name, {
|
||||
domain: domain.name,
|
||||
apexDomain: domain.name,
|
||||
projectName: null,
|
||||
expiresAt: domain.expiresAt || null,
|
||||
createdAt: domain.createdAt,
|
||||
configured: Boolean(domain.verified),
|
||||
dns: isDomainExternal(domain) ? 'External' : 'Vercel',
|
||||
});
|
||||
|
||||
projects.forEach(project => {
|
||||
(project.alias || []).forEach(target => {
|
||||
if (!target.domain.endsWith(domain.name)) return;
|
||||
|
||||
info.set(target.domain, {
|
||||
domain: target.domain,
|
||||
apexDomain: domain.name,
|
||||
projectName: project.name,
|
||||
expiresAt: domain.expiresAt || null,
|
||||
createdAt: domain.createdAt || target.createdAt || null,
|
||||
configured: Boolean(domain.verified),
|
||||
dns: isDomainExternal(domain) ? 'External' : 'Vercel',
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
projects.forEach(project => {
|
||||
(project.alias || []).forEach(target => {
|
||||
if (info.has(target.domain)) return;
|
||||
|
||||
const { domain: apexDomain } = psl.parse(
|
||||
target.domain
|
||||
) as psl.ParsedDomain;
|
||||
|
||||
info.set(target.domain, {
|
||||
domain: target.domain,
|
||||
apexDomain: apexDomain || target.domain,
|
||||
projectName: project.name,
|
||||
expiresAt: null,
|
||||
createdAt: target.createdAt || null,
|
||||
configured: isPublicSuffix(target.domain),
|
||||
dns: isPublicSuffix(target.domain) ? 'Vercel' : 'External',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
const list = Array.from(info.values());
|
||||
|
||||
return list.sort((a, b) => {
|
||||
if (a.apexDomain === b.apexDomain) {
|
||||
if (a.apexDomain === a.domain) return -1;
|
||||
if (b.apexDomain === b.domain) return 1;
|
||||
return a.domain.localeCompare(b.domain);
|
||||
}
|
||||
|
||||
return a.apexDomain.localeCompare(b.apexDomain);
|
||||
});
|
||||
}
|
||||
|
||||
function formatDomainsTable(domainsInfo: DomainInfo[]) {
|
||||
function formatDomainsTable(domains: Domain[]) {
|
||||
const current = Date.now();
|
||||
|
||||
const rows: string[][] = domainsInfo.map(info => {
|
||||
const expiration = formatDateWithoutTime(info.expiresAt);
|
||||
const age = info.createdAt ? ms(current - info.createdAt) : '-';
|
||||
const rows: string[][] = domains.map(domain => {
|
||||
const expiration = formatDateWithoutTime(domain.expiresAt);
|
||||
const age = domain.createdAt ? ms(current - domain.createdAt) : '-';
|
||||
|
||||
return [
|
||||
info.domain,
|
||||
info.projectName || '-',
|
||||
info.dns,
|
||||
domain.name,
|
||||
getDomainRegistrar(domain),
|
||||
isDomainExternal(domain) ? 'Third Party' : 'Vercel',
|
||||
expiration,
|
||||
info.configured.toString(),
|
||||
domain.creator.username,
|
||||
chalk.gray(age),
|
||||
];
|
||||
});
|
||||
|
||||
const table = formatTable(
|
||||
['domain', 'project', 'dns', 'expiration', 'configured', 'age'],
|
||||
return formatTable(
|
||||
['Domain', 'Registrar', 'Nameservers', 'Expiration', 'Creator', 'Age'],
|
||||
['l', 'l', 'l', 'l', 'l', 'l'],
|
||||
[{ rows }]
|
||||
);
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
@@ -71,8 +71,8 @@ export default async function transferIn(
|
||||
checkTransfer(client, domainName),
|
||||
]);
|
||||
|
||||
if (domainPrice instanceof ERRORS.UnsupportedTLD) {
|
||||
output.error(`The TLD for ${param(domainName)} is not supported.`);
|
||||
if (domainPrice instanceof Error) {
|
||||
output.prettyError(domainPrice);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
33
packages/now-cli/src/commands/domains/verify.ts
Normal file
33
packages/now-cli/src/commands/domains/verify.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import { NowContext } from '../../types';
|
||||
import { Output } from '../../util/output';
|
||||
import { NowBuildError } from '@vercel/build-utils';
|
||||
import { getCommandName } from '../../util/pkg-name';
|
||||
|
||||
export default async function verify(
|
||||
_ctx: NowContext,
|
||||
_opts: {},
|
||||
args: string[],
|
||||
output: Output
|
||||
) {
|
||||
const [domainName] = args;
|
||||
|
||||
if (!domainName) {
|
||||
output.error(
|
||||
`${getCommandName(`domains verify <domain>`)} expects one argument`
|
||||
);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
const error = new NowBuildError({
|
||||
code: 'domains_verify_command_deprecated',
|
||||
message: `It's not necessary to verify Domains anymore. Instead, you can run ${getCommandName(
|
||||
`domains inspect ${domainName}`
|
||||
)} to see what you need to do in order to configure it properly.`,
|
||||
link: 'https://vercel.link/domain-verification-via-cli',
|
||||
});
|
||||
|
||||
output.prettyError(error);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -640,6 +640,11 @@ const main = async argv_ => {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (err.code === 'NOT_AUTHORIZED' || err.code === 'TEAM_DELETED') {
|
||||
output.prettyError(err);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (err instanceof APIError && 400 <= err.status && err.status <= 499) {
|
||||
err.message = err.serverMessage;
|
||||
output.prettyError(err);
|
||||
|
||||
@@ -6,7 +6,7 @@ export default async function deleteCertById(
|
||||
client: Client,
|
||||
id: string
|
||||
) {
|
||||
return client.fetch(`/v3/now/certs/${id}`, {
|
||||
method: 'DELETE'
|
||||
return client.fetch(`/v5/now/certs/${id}`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import * as ERRORS from '../errors-ts';
|
||||
|
||||
export default async function getCertById(client: Client, id: string) {
|
||||
try {
|
||||
return await client.fetch<Cert>(`/v3/now/certs/${id}`);
|
||||
return await client.fetch<Cert>(`/v5/now/certs/${id}`);
|
||||
} catch (error) {
|
||||
if (error.code === 'cert_not_found') {
|
||||
return new ERRORS.CertNotFound(id);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { stringify } from 'querystring';
|
||||
import { Cert } from '../../types';
|
||||
import { Output } from '../output';
|
||||
import * as ERRORS from '../errors-ts';
|
||||
import Client from '../client';
|
||||
|
||||
@@ -8,15 +7,14 @@ type Response = {
|
||||
certs: Cert[];
|
||||
};
|
||||
|
||||
export default async function getCertsForDomain(
|
||||
output: Output,
|
||||
export async function getCustomCertsForDomain(
|
||||
client: Client,
|
||||
context: string,
|
||||
domain: string
|
||||
) {
|
||||
try {
|
||||
const { certs } = await client.fetch<Response>(
|
||||
`/v3/now/certs?${stringify({ domain })}`
|
||||
`/v5/now/certs?${stringify({ domain, custom: true })}`
|
||||
);
|
||||
return certs;
|
||||
} catch (error) {
|
||||
@@ -1578,6 +1578,13 @@ export default class DevServer {
|
||||
debug(
|
||||
`Checking build result's ${buildResult.routes.length} \`routes\` to match ${newUrl}`
|
||||
);
|
||||
for (const r of buildResult.routes) {
|
||||
// This replace is necessary for `@vercel/redwood` but might be relevant
|
||||
// for builders that wish to return routes and work with zero config.
|
||||
if (r.dest) {
|
||||
r.dest = r.dest.replace(/\$PORT/g, `${this.devProcessPort}`);
|
||||
}
|
||||
}
|
||||
const matchedRoute = await devRouter(
|
||||
newUrl,
|
||||
req.method,
|
||||
|
||||
@@ -4,6 +4,8 @@ import { Output } from '../output';
|
||||
import Client from '../client';
|
||||
import getDomainDNSRecords from './get-domain-dns-records';
|
||||
import getDomains from '../domains/get-domains';
|
||||
import wait from '../output/wait';
|
||||
import chalk from 'chalk';
|
||||
|
||||
export type DomainRecordsItem = {
|
||||
domainName: string;
|
||||
@@ -58,6 +60,11 @@ async function getDomainNames(
|
||||
contextName: string,
|
||||
next?: number
|
||||
) {
|
||||
const { domains, pagination } = await getDomains(client, contextName, next);
|
||||
return { domainNames: domains.map(domain => domain.name), pagination };
|
||||
const cancelWait = wait(`Fetching domains under ${chalk.bold(contextName)}`);
|
||||
try {
|
||||
const { domains, pagination } = await getDomains(client, next);
|
||||
return { domainNames: domains.map(domain => domain.name), pagination };
|
||||
} finally {
|
||||
cancelWait();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ export default async function importZonefile(
|
||||
} catch (error) {
|
||||
cancelWait();
|
||||
if (error.code === 'not_found') {
|
||||
return new DomainNotFound(domain);
|
||||
return new DomainNotFound(domain, contextName);
|
||||
}
|
||||
|
||||
if (error.code === 'invalid_domain') {
|
||||
|
||||
@@ -8,24 +8,26 @@ type Response = {
|
||||
domain: Domain;
|
||||
};
|
||||
|
||||
async function getDomainByName(
|
||||
export default async function getDomainByName(
|
||||
client: Client,
|
||||
contextName: string,
|
||||
domainName: string
|
||||
domainName: string,
|
||||
options: {
|
||||
ignoreWait?: boolean;
|
||||
} = {}
|
||||
) {
|
||||
const cancelWait = wait(
|
||||
`Fetching domain ${domainName} under ${chalk.bold(contextName)}`
|
||||
);
|
||||
const cancelWait = options.ignoreWait
|
||||
? null
|
||||
: wait(`Fetching domain ${domainName} under ${chalk.bold(contextName)}`);
|
||||
try {
|
||||
const { domain } = await client.fetch<Response>(
|
||||
`/v4/domains/${encodeURIComponent(domainName)}`
|
||||
);
|
||||
cancelWait();
|
||||
|
||||
return domain;
|
||||
} catch (error) {
|
||||
cancelWait();
|
||||
if (error.status === 404) {
|
||||
return new DomainNotFound(domainName);
|
||||
return new DomainNotFound(domainName, contextName);
|
||||
}
|
||||
|
||||
if (error.status === 403) {
|
||||
@@ -33,7 +35,7 @@ async function getDomainByName(
|
||||
}
|
||||
|
||||
throw error;
|
||||
} finally {
|
||||
cancelWait?.();
|
||||
}
|
||||
}
|
||||
|
||||
export default getDomainByName;
|
||||
|
||||
@@ -1,16 +1,7 @@
|
||||
import chalk from 'chalk';
|
||||
import Client from '../client';
|
||||
import wait from '../output/wait';
|
||||
import { DomainConfig } from '../../types';
|
||||
|
||||
export async function getDomainConfig(
|
||||
client: Client,
|
||||
contextName: string,
|
||||
domainName: string
|
||||
) {
|
||||
const cancelWait = wait(
|
||||
`Fetching domain config ${domainName} under ${chalk.bold(contextName)}`
|
||||
);
|
||||
export async function getDomainConfig(client: Client, domainName: string) {
|
||||
try {
|
||||
const config = await client.fetch<DomainConfig>(
|
||||
`/v4/domains/${domainName}/config`
|
||||
@@ -23,7 +14,5 @@ export async function getDomainConfig(
|
||||
}
|
||||
|
||||
throw error;
|
||||
} finally {
|
||||
cancelWait();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,11 @@ export default async function getDomainPrice(
|
||||
if (error.code === 'unsupported_tld') {
|
||||
return new UnsupportedTLD(name);
|
||||
}
|
||||
|
||||
if (error.status < 500) {
|
||||
return error;
|
||||
}
|
||||
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
15
packages/now-cli/src/util/domains/get-domain-registrar.ts
Normal file
15
packages/now-cli/src/util/domains/get-domain-registrar.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { Domain } from '../../types';
|
||||
|
||||
export type DomainRegistrar = 'Vercel' | 'Purchase in Process' | 'Third Party';
|
||||
|
||||
export function getDomainRegistrar(domain: Domain): DomainRegistrar {
|
||||
if (domain.boughtAt) {
|
||||
return 'Vercel';
|
||||
}
|
||||
|
||||
if (typeof domain.orderedAt === 'number' && !domain.boughtAt) {
|
||||
return 'Purchase in Process';
|
||||
}
|
||||
|
||||
return 'Third Party';
|
||||
}
|
||||
@@ -1,24 +1,15 @@
|
||||
import chalk from 'chalk';
|
||||
import { Domain, PaginationOptions } from '../../types';
|
||||
import Client from '../client';
|
||||
import wait from '../output/wait';
|
||||
|
||||
type Response = {
|
||||
domains: Domain[];
|
||||
pagination: PaginationOptions;
|
||||
};
|
||||
|
||||
export default async function getDomains(
|
||||
client: Client,
|
||||
contextName: string,
|
||||
next?: number
|
||||
) {
|
||||
export default async function getDomains(client: Client, next?: number) {
|
||||
let domainUrl = `/v5/domains?limit=20`;
|
||||
if (next) {
|
||||
domainUrl += `&until=${next}`;
|
||||
}
|
||||
const cancelWait = wait(`Fetching domains under ${chalk.bold(contextName)}`);
|
||||
const domains = await client.fetch<Response>(domainUrl);
|
||||
cancelWait();
|
||||
return domains;
|
||||
return await client.fetch<Response>(domainUrl);
|
||||
}
|
||||
|
||||
@@ -30,12 +30,19 @@ export default async function purchaseDomainIfAvailable(
|
||||
}
|
||||
|
||||
output.debug(`Domain ${domain} is available to be purchased`);
|
||||
const domainPrice = await getDomainPrice(client, domain);
|
||||
cancelWait();
|
||||
|
||||
const domainPrice = await getDomainPrice(client, domain).finally(() => {
|
||||
cancelWait();
|
||||
});
|
||||
|
||||
if (domainPrice instanceof ERRORS.UnsupportedTLD) {
|
||||
return domainPrice;
|
||||
}
|
||||
|
||||
if (domainPrice instanceof Error) {
|
||||
throw domainPrice;
|
||||
}
|
||||
|
||||
const { price, period } = domainPrice;
|
||||
output.log(
|
||||
`Domain not found, but you can buy it under ${chalk.bold(
|
||||
@@ -68,6 +75,5 @@ export default async function purchaseDomainIfAvailable(
|
||||
}
|
||||
|
||||
output.debug(`Domain ${domain} is not available to be purchased`);
|
||||
cancelWait();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import { NowBuildError } from '@vercel/build-utils';
|
||||
import { NowError } from './now-error';
|
||||
import code from './output/code';
|
||||
import { getCommandName } from './pkg-name';
|
||||
import chalk from 'chalk';
|
||||
|
||||
/**
|
||||
* This error is thrown when there is an API error with a payload. The error
|
||||
@@ -68,7 +69,9 @@ export class InvalidToken extends NowError<'NOT_AUTHORIZED', {}> {
|
||||
constructor() {
|
||||
super({
|
||||
code: `NOT_AUTHORIZED`,
|
||||
message: `The specified token is not valid`,
|
||||
message: `The specified token is not valid. Use ${getCommandName(
|
||||
`login`
|
||||
)} to generate a new token.`,
|
||||
meta: {},
|
||||
});
|
||||
}
|
||||
@@ -183,11 +186,13 @@ export class DomainNotFound extends NowError<
|
||||
'DOMAIN_NOT_FOUND',
|
||||
{ domain: string }
|
||||
> {
|
||||
constructor(domain: string) {
|
||||
constructor(domain: string, contextName?: string) {
|
||||
super({
|
||||
code: 'DOMAIN_NOT_FOUND',
|
||||
meta: { domain },
|
||||
message: `The domain ${domain} can't be found.`,
|
||||
message: `Domain not found by "${domain}"${
|
||||
contextName ? ` under ${chalk.bold(contextName)}` : ''
|
||||
}.`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,6 @@ export default `.hg
|
||||
npm-debug.log
|
||||
config.gypi
|
||||
node_modules
|
||||
__pycache__/
|
||||
venv/
|
||||
__pycache__
|
||||
venv
|
||||
CVS`;
|
||||
|
||||
@@ -28,15 +28,11 @@ export default function createOutput({ debug: debugEnabled = false } = {}) {
|
||||
str: string,
|
||||
slug: string | null = null,
|
||||
link: string | null = null,
|
||||
action: string = 'Learn More'
|
||||
) {
|
||||
const prevTerm = process.env.TERM;
|
||||
|
||||
if (!prevTerm) {
|
||||
// workaround for https://github.com/sindresorhus/term-size/issues/13
|
||||
process.env.TERM = 'xterm';
|
||||
action: string | null = 'Learn More',
|
||||
options?: {
|
||||
boxen?: boxen.Options;
|
||||
}
|
||||
|
||||
) {
|
||||
const details = slug ? `https://err.sh/now/${slug}` : link;
|
||||
|
||||
print(
|
||||
@@ -52,12 +48,11 @@ export default function createOutput({ debug: debugEnabled = false } = {}) {
|
||||
right: 1,
|
||||
},
|
||||
borderColor: 'yellow',
|
||||
...options?.boxen,
|
||||
}
|
||||
)
|
||||
);
|
||||
print('\n');
|
||||
|
||||
process.env.TERM = prevTerm;
|
||||
}
|
||||
|
||||
function note(str: string) {
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import chalk from 'chalk';
|
||||
import Client from '../client';
|
||||
import wait from '../output/wait';
|
||||
import { Project } from '../../types';
|
||||
import { URLSearchParams } from 'url';
|
||||
|
||||
@@ -8,9 +6,6 @@ export async function findProjectsForDomain(
|
||||
client: Client,
|
||||
domainName: string
|
||||
): Promise<Project[] | Error> {
|
||||
const cancelWait = wait(
|
||||
`Searching project for domain ${chalk.bold(domainName)}`
|
||||
);
|
||||
try {
|
||||
const limit = 50;
|
||||
let result: Project[] = [];
|
||||
@@ -30,7 +25,7 @@ export async function findProjectsForDomain(
|
||||
}
|
||||
|
||||
const [latest] = response.sort((a, b) => b.updatedAt - a.updatedAt);
|
||||
query.append('from', latest.updatedAt.toString());
|
||||
query.set('from', latest.updatedAt.toString());
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -40,7 +35,5 @@ export async function findProjectsForDomain(
|
||||
}
|
||||
|
||||
throw err;
|
||||
} finally {
|
||||
cancelWait();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
import Client from '../client';
|
||||
import wait from '../output/wait';
|
||||
import { Project } from '../../types';
|
||||
import { URLSearchParams } from 'url';
|
||||
|
||||
export async function getProjectsWithDomains(
|
||||
client: Client
|
||||
): Promise<Project[] | Error> {
|
||||
const cancelWait = wait(`Fetching projects with domains`);
|
||||
try {
|
||||
const limit = 50;
|
||||
let result: Project[] = [];
|
||||
|
||||
const query = new URLSearchParams({
|
||||
hasProductionDomains: '1',
|
||||
limit: limit.toString(),
|
||||
});
|
||||
|
||||
for (let i = 0; i < 1000; i++) {
|
||||
const response = await client.fetch<Project[]>(`/v2/projects/?${query}`);
|
||||
result.push(...response);
|
||||
|
||||
const [latest] = response.sort((a, b) => b.updatedAt - a.updatedAt);
|
||||
query.append('from', latest.updatedAt.toString());
|
||||
|
||||
if (response.length !== limit) break;
|
||||
}
|
||||
|
||||
return result;
|
||||
} catch (err) {
|
||||
if (err.status < 500) {
|
||||
return err;
|
||||
}
|
||||
|
||||
throw err;
|
||||
} finally {
|
||||
cancelWait();
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import { join } from 'path';
|
||||
import fs from 'fs';
|
||||
import os from 'os';
|
||||
import { ensureDir } from 'fs-extra';
|
||||
import { promisify } from 'util';
|
||||
import getProjectByIdOrName from '../projects/get-project-by-id-or-name';
|
||||
@@ -226,14 +227,12 @@ export async function linkFolderToProject(
|
||||
|
||||
await writeFile(
|
||||
join(path, VERCEL_DIR, VERCEL_DIR_PROJECT),
|
||||
JSON.stringify(projectLink),
|
||||
{ encoding: 'utf8' }
|
||||
JSON.stringify(projectLink)
|
||||
);
|
||||
|
||||
await writeFile(
|
||||
join(path, VERCEL_DIR, VERCEL_DIR_README),
|
||||
await readFile(join(__dirname, 'VERCEL_DIR_README.txt'), 'utf-8'),
|
||||
{ encoding: 'utf-8' }
|
||||
await readFile(join(__dirname, 'VERCEL_DIR_README.txt'), 'utf8')
|
||||
);
|
||||
|
||||
// update .gitignore
|
||||
@@ -241,14 +240,15 @@ export async function linkFolderToProject(
|
||||
try {
|
||||
const gitIgnorePath = join(path, '.gitignore');
|
||||
|
||||
const gitIgnore = await readFile(gitIgnorePath)
|
||||
.then(buf => buf.toString())
|
||||
.catch(() => null);
|
||||
const gitIgnore = await readFile(gitIgnorePath, 'utf8').catch(() => null);
|
||||
const EOL = gitIgnore && gitIgnore.includes('\r\n') ? '\r\n' : os.EOL;
|
||||
|
||||
if (!gitIgnore || !gitIgnore.split('\n').includes(VERCEL_DIR)) {
|
||||
if (!gitIgnore || !gitIgnore.split(EOL).includes(VERCEL_DIR)) {
|
||||
await writeFile(
|
||||
gitIgnorePath,
|
||||
gitIgnore ? `${gitIgnore}\n${VERCEL_DIR}` : VERCEL_DIR
|
||||
gitIgnore
|
||||
? `${gitIgnore}${EOL}${VERCEL_DIR}${EOL}`
|
||||
: `${VERCEL_DIR}${EOL}`
|
||||
);
|
||||
isGitIgnoreUpdated = true;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ let port = 3000;
|
||||
const binaryPath = resolve(__dirname, `../../scripts/start.js`);
|
||||
const fixture = name => join('test', 'dev', 'fixtures', name);
|
||||
const fixtureAbsolute = name => join(__dirname, 'fixtures', name);
|
||||
const exampleAbsolute = name =>
|
||||
join(__dirname, '..', '..', '..', '..', 'examples', name);
|
||||
|
||||
let processCounter = 0;
|
||||
const processList = new Map();
|
||||
@@ -127,9 +129,10 @@ async function testPath(
|
||||
path,
|
||||
expectedText,
|
||||
headers = {},
|
||||
method = 'GET'
|
||||
method = 'GET',
|
||||
body = undefined
|
||||
) {
|
||||
const opts = { redirect: 'manual-dont-change', method };
|
||||
const opts = { redirect: 'manual-dont-change', method, body };
|
||||
const url = `${origin}${path}`;
|
||||
const res = await fetch(url, opts);
|
||||
const msg = `Testing response from ${method} ${url}`;
|
||||
@@ -230,10 +233,18 @@ async function testFixture(directory, opts = {}, args = []) {
|
||||
function testFixtureStdio(
|
||||
directory,
|
||||
fn,
|
||||
{ expectedCode = 0, skipDeploy } = {}
|
||||
{ expectedCode = 0, skipDeploy, isExample } = {}
|
||||
) {
|
||||
return async t => {
|
||||
const cwd = fixtureAbsolute(directory);
|
||||
const nodeMajor = Number(process.versions.node.split('.')[0]);
|
||||
if (isExample && nodeMajor < 12) {
|
||||
console.log(`Skipping ${directory} on Node ${process.version}`);
|
||||
t.pass();
|
||||
return;
|
||||
}
|
||||
const cwd = isExample
|
||||
? exampleAbsolute(directory)
|
||||
: fixtureAbsolute(directory);
|
||||
const token = await fetchTokenWithRetry();
|
||||
let deploymentUrl;
|
||||
|
||||
@@ -369,6 +380,21 @@ test.afterEach(async () => {
|
||||
);
|
||||
});
|
||||
|
||||
test(
|
||||
'[vercel dev] redwoodjs example',
|
||||
testFixtureStdio(
|
||||
'redwoodjs',
|
||||
async testPath => {
|
||||
await testPath(200, '/', /<div id="redwood-app">/m);
|
||||
await testPath(200, '/about', /<div id="redwood-app">/m);
|
||||
const reqBody = '{"query":"{redwood{version}}"}';
|
||||
const resBody = '{"data":{"redwood":{"version":"0.15.0"}}}';
|
||||
await testPath(200, '/api/graphql', resBody, {}, 'POST', reqBody);
|
||||
},
|
||||
{ isExample: true }
|
||||
)
|
||||
);
|
||||
|
||||
test('[vercel dev] prints `npm install` errors', async t => {
|
||||
const dir = fixture('runtime-not-installed');
|
||||
const result = await exec(dir);
|
||||
@@ -1149,7 +1175,8 @@ test(
|
||||
await testPath(200, '/api/date', new RegExp(new Date().getFullYear()));
|
||||
await testPath(200, '/contact', /Contact Page/);
|
||||
await testPath(200, '/support', /Contact Page/);
|
||||
await testPath(404, '/nothing', /Custom Next 404/);
|
||||
// TODO: Fix this test assertion that fails intermittently
|
||||
// await testPath(404, '/nothing', /Custom Next 404/);
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
43
packages/now-cli/test/integration.js
vendored
43
packages/now-cli/test/integration.js
vendored
@@ -2621,39 +2621,6 @@ test('assign a domain to a project', async t => {
|
||||
t.is(removeResponse.exitCode, 0, formatOutput(removeResponse));
|
||||
});
|
||||
|
||||
test('list project domains', async t => {
|
||||
const domain = `project-domain.${contextName}.now.sh`;
|
||||
const directory = fixture('static-deployment');
|
||||
|
||||
const deploymentOutput = await execute([directory, '--public', '--confirm']);
|
||||
t.is(deploymentOutput.exitCode, 0, formatOutput(deploymentOutput));
|
||||
|
||||
const host = deploymentOutput.stdout.trim().replace('https://', '');
|
||||
const deployment = await apiFetch(
|
||||
`/v10/now/deployments/unknown?url=${host}`
|
||||
).then(resp => resp.json());
|
||||
|
||||
t.is(typeof deployment.name, 'string', JSON.stringify(deployment, null, 2));
|
||||
const project = deployment.name;
|
||||
|
||||
const addOutput = await execute([
|
||||
'domains',
|
||||
'add',
|
||||
domain,
|
||||
project,
|
||||
'--force',
|
||||
]);
|
||||
t.is(addOutput.exitCode, 0, formatOutput(addOutput));
|
||||
|
||||
const output = await execute(['domains', 'ls']);
|
||||
t.is(output.exitCode, 0, formatOutput(output));
|
||||
t.regex(output.stderr, new RegExp(domain), formatOutput(output));
|
||||
t.regex(output.stderr, new RegExp(project), formatOutput(output));
|
||||
|
||||
const removeResponse = await execute(['rm', project, '-y']);
|
||||
t.is(removeResponse.exitCode, 0, formatOutput(removeResponse));
|
||||
});
|
||||
|
||||
test('ensure `github` and `scope` are not sent to the API', async t => {
|
||||
const directory = fixture('github-and-scope-config');
|
||||
const output = await execute([directory, '--confirm']);
|
||||
@@ -2734,7 +2701,7 @@ test('should show prompts to set up project during first deploy', async t => {
|
||||
// Ensure .gitignore is created
|
||||
t.is(
|
||||
(await readFile(path.join(directory, '.gitignore'))).toString(),
|
||||
'.vercel'
|
||||
'.vercel\n'
|
||||
);
|
||||
|
||||
// Ensure .vercel/project.json and .vercel/README.txt are created
|
||||
@@ -3354,7 +3321,7 @@ test('[vc link] should show prompts to set up project', async t => {
|
||||
t.is(output.exitCode, 0, formatOutput(output));
|
||||
|
||||
// Ensure .gitignore is created
|
||||
t.is((await readFile(path.join(dir, '.gitignore'))).toString(), '.vercel');
|
||||
t.is((await readFile(path.join(dir, '.gitignore'))).toString(), '.vercel\n');
|
||||
|
||||
// Ensure .vercel/project.json and .vercel/README.txt are created
|
||||
t.is(
|
||||
@@ -3388,7 +3355,7 @@ test('[vc link --confirm] should not show prompts and autolink', async t => {
|
||||
t.regex(stderr, /Linked to /m);
|
||||
|
||||
// Ensure .gitignore is created
|
||||
t.is((await readFile(path.join(dir, '.gitignore'))).toString(), '.vercel');
|
||||
t.is((await readFile(path.join(dir, '.gitignore'))).toString(), '.vercel\n');
|
||||
|
||||
// Ensure .vercel/project.json and .vercel/README.txt are created
|
||||
t.is(
|
||||
@@ -3472,7 +3439,7 @@ test('[vc dev] should show prompts to set up project', async t => {
|
||||
await waitForPrompt(dev, chunk => chunk.includes('Linked to'));
|
||||
|
||||
// Ensure .gitignore is created
|
||||
t.is((await readFile(path.join(dir, '.gitignore'))).toString(), '.vercel');
|
||||
t.is((await readFile(path.join(dir, '.gitignore'))).toString(), '.vercel\n');
|
||||
|
||||
// Ensure .vercel/project.json and .vercel/README.txt are created
|
||||
t.is(
|
||||
@@ -3538,7 +3505,7 @@ test('[vc link] should show project prompts but not framework when `builds` defi
|
||||
t.is(output.exitCode, 0, formatOutput(output));
|
||||
|
||||
// Ensure .gitignore is created
|
||||
t.is((await readFile(path.join(dir, '.gitignore'))).toString(), '.vercel');
|
||||
t.is((await readFile(path.join(dir, '.gitignore'))).toString(), '.vercel\n');
|
||||
|
||||
// Ensure .vercel/project.json and .vercel/README.txt are created
|
||||
t.is(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/client",
|
||||
"version": "8.2.2-canary.4",
|
||||
"version": "8.2.2-canary.6",
|
||||
"main": "dist/index.js",
|
||||
"typings": "dist/index.d.ts",
|
||||
"homepage": "https://vercel.com",
|
||||
@@ -38,7 +38,7 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@vercel/build-utils": "2.4.3-canary.2",
|
||||
"@vercel/build-utils": "2.4.3-canary.3",
|
||||
"@zeit/fetch": "5.2.0",
|
||||
"async-retry": "1.2.3",
|
||||
"async-sema": "3.0.0",
|
||||
|
||||
@@ -76,7 +76,8 @@ export async function* upload(
|
||||
const uploadList: { [key: string]: Promise<any> } = {};
|
||||
debug('Building an upload list...');
|
||||
|
||||
const semaphore = new Sema(700, { capacity: 700 });
|
||||
const semaphore = new Sema(50, { capacity: 50 });
|
||||
const agent = new Agent({ keepAlive: true });
|
||||
|
||||
shas.map((sha: string): void => {
|
||||
uploadList[sha] = retry(
|
||||
@@ -102,7 +103,7 @@ export async function* upload(
|
||||
API_FILES,
|
||||
token,
|
||||
{
|
||||
agent: new Agent({ keepAlive: true }),
|
||||
agent,
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/octet-stream',
|
||||
|
||||
@@ -118,14 +118,14 @@ export async function getVercelIgnore(
|
||||
cwd: string | string[]
|
||||
): Promise<{ ig: Ignore; ignores: string[] }> {
|
||||
const ignores: string[] = [
|
||||
'.hg/',
|
||||
'.git/',
|
||||
'.hg',
|
||||
'.git',
|
||||
'.gitmodules',
|
||||
'.svn/',
|
||||
'.svn',
|
||||
'.cache',
|
||||
'.next/',
|
||||
'.now/',
|
||||
'.vercel/',
|
||||
'.next',
|
||||
'.now',
|
||||
'.vercel',
|
||||
'.npmignore',
|
||||
'.dockerignore',
|
||||
'.gitignore',
|
||||
@@ -138,9 +138,9 @@ export async function getVercelIgnore(
|
||||
'.venv',
|
||||
'npm-debug.log',
|
||||
'config.gypi',
|
||||
'node_modules/',
|
||||
'__pycache__/',
|
||||
'venv/',
|
||||
'node_modules',
|
||||
'__pycache__',
|
||||
'venv',
|
||||
'CVS',
|
||||
];
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# literally dont ignore the node_modules directory
|
||||
# so basically include the node_modules directory recursively
|
||||
!node_modules/
|
||||
!node_modules
|
||||
|
||||
# ignore this file in addition to the defaults
|
||||
exclude.txt
|
||||
|
||||
@@ -27,7 +27,7 @@ describe('buildFileTree()', () => {
|
||||
const expectedIgnoreList = [
|
||||
'ignore.txt',
|
||||
'folder/ignore.txt',
|
||||
'node_modules/ignore.txt',
|
||||
'node_modules',
|
||||
];
|
||||
expect(normalizeWindowsPaths(expectedIgnoreList).sort()).toEqual(
|
||||
normalizeWindowsPaths(ignoreList).sort()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/next",
|
||||
"version": "2.6.15",
|
||||
"version": "2.6.20-canary.0",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index",
|
||||
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/next-js",
|
||||
@@ -26,7 +26,7 @@
|
||||
"@types/resolve-from": "5.0.1",
|
||||
"@types/semver": "6.0.0",
|
||||
"@types/yazl": "2.4.1",
|
||||
"@zeit/node-file-trace": "0.8.1",
|
||||
"@zeit/node-file-trace": "0.8.2",
|
||||
"async-sema": "3.0.1",
|
||||
"buffer-crc32": "0.2.13",
|
||||
"escape-string-regexp": "3.0.0",
|
||||
|
||||
@@ -1,20 +1,3 @@
|
||||
import buildUtils from './build-utils';
|
||||
import url from 'url';
|
||||
const {
|
||||
createLambda,
|
||||
debug,
|
||||
download,
|
||||
getLambdaOptionsFromFunction,
|
||||
getNodeVersion,
|
||||
getSpawnOptions,
|
||||
getScriptName,
|
||||
glob,
|
||||
runNpmInstall,
|
||||
runPackageJsonScript,
|
||||
execCommand,
|
||||
getNodeBinPath,
|
||||
} = buildUtils;
|
||||
|
||||
import {
|
||||
BuildOptions,
|
||||
Config,
|
||||
@@ -34,13 +17,17 @@ import {
|
||||
convertRewrites,
|
||||
} from '@vercel/routing-utils/dist/superstatic';
|
||||
import { nodeFileTrace, NodeFileTraceReasons } from '@zeit/node-file-trace';
|
||||
import { Sema } from 'async-sema';
|
||||
import { ChildProcess, fork } from 'child_process';
|
||||
import escapeStringRegexp from 'escape-string-regexp';
|
||||
import findUp from 'find-up';
|
||||
import { lstat, pathExists, readFile, remove, writeFile } from 'fs-extra';
|
||||
import os from 'os';
|
||||
import path from 'path';
|
||||
import resolveFrom from 'resolve-from';
|
||||
import semver from 'semver';
|
||||
import url from 'url';
|
||||
import buildUtils from './build-utils';
|
||||
import createServerlessConfig from './create-serverless-config';
|
||||
import nextLegacyVersions from './legacy-versions';
|
||||
import {
|
||||
@@ -66,8 +53,20 @@ import {
|
||||
syncEnvVars,
|
||||
validateEntrypoint,
|
||||
} from './utils';
|
||||
import findUp from 'find-up';
|
||||
import { Sema } from 'async-sema';
|
||||
const {
|
||||
createLambda,
|
||||
debug,
|
||||
download,
|
||||
getLambdaOptionsFromFunction,
|
||||
getNodeVersion,
|
||||
getSpawnOptions,
|
||||
getScriptName,
|
||||
glob,
|
||||
runNpmInstall,
|
||||
runPackageJsonScript,
|
||||
execCommand,
|
||||
getNodeBinPath,
|
||||
} = buildUtils;
|
||||
|
||||
interface BuildParamsMeta {
|
||||
isDev: boolean | undefined;
|
||||
@@ -235,7 +234,7 @@ export const build = async ({
|
||||
|
||||
await download(files, workPath, meta);
|
||||
|
||||
const pkg = await readPackageJson(entryPath);
|
||||
let pkg = await readPackageJson(entryPath);
|
||||
const nextVersionRange = await getNextVersionRange(entryPath);
|
||||
const nodeVersion = await getNodeVersion(entryPath, undefined, config, meta);
|
||||
const spawnOpts = getSpawnOptions(meta, nodeVersion);
|
||||
@@ -331,17 +330,17 @@ export const build = async ({
|
||||
]);
|
||||
|
||||
debug('Normalizing package.json');
|
||||
const packageJson = normalizePackageJson(pkg);
|
||||
debug('Normalized package.json result: ', packageJson);
|
||||
await writePackageJson(entryPath, packageJson);
|
||||
pkg = normalizePackageJson(pkg);
|
||||
debug('Normalized package.json result: ', pkg);
|
||||
await writePackageJson(entryPath, pkg);
|
||||
}
|
||||
|
||||
const buildScriptName = getScriptName(pkg, [
|
||||
let buildScriptName = getScriptName(pkg, [
|
||||
'vercel-build',
|
||||
'now-build',
|
||||
'build',
|
||||
]);
|
||||
let { buildCommand } = config;
|
||||
const { buildCommand } = config;
|
||||
|
||||
if (!buildScriptName && !buildCommand) {
|
||||
console.log(
|
||||
@@ -349,7 +348,15 @@ export const build = async ({
|
||||
'If you need to define a different build step, please create a `vercel-build` script in your `package.json` ' +
|
||||
'(e.g. `{ "scripts": { "vercel-build": "npm run prepare && next build" } }`).'
|
||||
);
|
||||
buildCommand = 'next build';
|
||||
|
||||
await writePackageJson(entryPath, {
|
||||
...pkg,
|
||||
scripts: {
|
||||
'vercel-build': 'next build',
|
||||
...pkg.scripts,
|
||||
},
|
||||
});
|
||||
buildScriptName = 'vercel-build';
|
||||
}
|
||||
|
||||
if (process.env.NPM_AUTH_TOKEN) {
|
||||
@@ -438,7 +445,7 @@ export const build = async ({
|
||||
for (const dataRoute of routesManifest.dataRoutes) {
|
||||
const ssgDataRoute =
|
||||
prerenderManifest.fallbackRoutes[dataRoute.page] ||
|
||||
prerenderManifest.legacyBlockingRoutes[dataRoute.page];
|
||||
prerenderManifest.blockingFallbackRoutes[dataRoute.page];
|
||||
|
||||
// we don't need to add routes for non-lazy SSG routes since
|
||||
// they have outputs which would override the routes anyways
|
||||
@@ -878,7 +885,7 @@ export const build = async ({
|
||||
initialRevalidate === false &&
|
||||
!canUsePreviewMode &&
|
||||
!prerenderManifest.fallbackRoutes[route] &&
|
||||
!prerenderManifest.legacyBlockingRoutes[route]
|
||||
!prerenderManifest.blockingFallbackRoutes[route]
|
||||
) {
|
||||
// if the 404 page used getStaticProps we need to update static404Page
|
||||
// since it wasn't populated from the staticPages group
|
||||
@@ -1123,7 +1130,7 @@ export const build = async ({
|
||||
src: `^${escapeStringRegexp(outputName).replace(
|
||||
/\/index$/,
|
||||
'(/|/index|)'
|
||||
)}$`,
|
||||
)}/?$`,
|
||||
dest: `${path.join('/', currentLambdaGroup.lambdaIdentifier)}`,
|
||||
headers: {
|
||||
'x-nextjs-page': outputName,
|
||||
@@ -1303,7 +1310,7 @@ export const build = async ({
|
||||
if (!toRender) {
|
||||
try {
|
||||
const { pathname } = url.parse(req.url)
|
||||
toRender = pathname
|
||||
toRender = pathname.replace(/\\/$/, '')
|
||||
} catch (_) {
|
||||
// handle failing to parse url
|
||||
res.statusCode = 400
|
||||
@@ -1458,7 +1465,7 @@ export const build = async ({
|
||||
if (isFallback || isBlocking) {
|
||||
const pr = isFallback
|
||||
? prerenderManifest.fallbackRoutes[routeKey]
|
||||
: prerenderManifest.legacyBlockingRoutes[routeKey];
|
||||
: prerenderManifest.blockingFallbackRoutes[routeKey];
|
||||
initialRevalidate = 1; // TODO: should Next.js provide this default?
|
||||
// @ts-ignore
|
||||
if (initialRevalidate === false) {
|
||||
@@ -1549,7 +1556,7 @@ export const build = async ({
|
||||
Object.keys(prerenderManifest.fallbackRoutes).forEach(route =>
|
||||
onPrerenderRoute(route, { isBlocking: false, isFallback: true })
|
||||
);
|
||||
Object.keys(prerenderManifest.legacyBlockingRoutes).forEach(route =>
|
||||
Object.keys(prerenderManifest.blockingFallbackRoutes).forEach(route =>
|
||||
onPrerenderRoute(route, { isBlocking: true, isFallback: false })
|
||||
);
|
||||
|
||||
@@ -1559,7 +1566,7 @@ export const build = async ({
|
||||
// Dynamic pages for lazy routes should be handled by the lambda flow.
|
||||
[
|
||||
...Object.entries(prerenderManifest.fallbackRoutes),
|
||||
...Object.entries(prerenderManifest.legacyBlockingRoutes),
|
||||
...Object.entries(prerenderManifest.blockingFallbackRoutes),
|
||||
].forEach(([, { dataRouteRegex, dataRoute }]) => {
|
||||
dataRoutes.push({
|
||||
// Next.js provided data route regex
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import zlib from 'zlib';
|
||||
import path from 'path';
|
||||
import { FileFsRef, Files } from '@vercel/build-utils';
|
||||
import { NowHeader, NowRewrite, Route, Source } from '@vercel/routing-utils';
|
||||
import { Sema } from 'async-sema';
|
||||
import crc32 from 'buffer-crc32';
|
||||
import fs from 'fs-extra';
|
||||
import path from 'path';
|
||||
import resolveFrom from 'resolve-from';
|
||||
import semver from 'semver';
|
||||
import { ZipFile } from 'yazl';
|
||||
import crc32 from 'buffer-crc32';
|
||||
import { Sema } from 'async-sema';
|
||||
import resolveFrom from 'resolve-from';
|
||||
import zlib from 'zlib';
|
||||
import buildUtils from './build-utils';
|
||||
const { streamToBuffer, Lambda, NowBuildError, isSymbolicLink } = buildUtils;
|
||||
import { Files, FileFsRef } from '@vercel/build-utils';
|
||||
import { Route, Source, NowHeader, NowRewrite } from '@vercel/routing-utils';
|
||||
|
||||
type stringMap = { [key: string]: string };
|
||||
|
||||
@@ -198,7 +198,7 @@ async function getRoutes(
|
||||
// If default pages dir isn't found check for `src/pages`
|
||||
if (
|
||||
!pagesDir &&
|
||||
fileKeys.some((file) =>
|
||||
fileKeys.some(file =>
|
||||
file.startsWith(path.join(entryDirectory, 'src/pages'))
|
||||
)
|
||||
) {
|
||||
@@ -260,7 +260,7 @@ async function getRoutes(
|
||||
entryDirectory,
|
||||
dynamicPages,
|
||||
true
|
||||
).then((arr) =>
|
||||
).then(arr =>
|
||||
arr.map((route: Source) => {
|
||||
// convert to make entire RegExp match as one group
|
||||
route.src = route.src
|
||||
@@ -287,7 +287,7 @@ async function getRoutes(
|
||||
};
|
||||
|
||||
// Only add the route if a page is not already using it
|
||||
if (!routes.some((r) => (r as Source).src === route.src)) {
|
||||
if (!routes.some(r => (r as Source).src === route.src)) {
|
||||
routes.push(route);
|
||||
}
|
||||
}
|
||||
@@ -420,7 +420,7 @@ export async function getDynamicRoutes(
|
||||
dest: `${!isDev ? path.join('/', entryDirectory, page) : page}${
|
||||
routeKeys
|
||||
? `?${Object.keys(routeKeys)
|
||||
.map((key) => `${routeKeys[key]}=$${key}`)
|
||||
.map(key => `${routeKeys[key]}=$${key}`)
|
||||
.join('&')}`
|
||||
: ''
|
||||
}`,
|
||||
@@ -479,13 +479,13 @@ export async function getDynamicRoutes(
|
||||
});
|
||||
}
|
||||
|
||||
const pageMatchers = getSortedRoutes(dynamicPages).map((pageName) => ({
|
||||
const pageMatchers = getSortedRoutes(dynamicPages).map(pageName => ({
|
||||
pageName,
|
||||
matcher: getRouteRegex && getRouteRegex(pageName).re,
|
||||
}));
|
||||
|
||||
const routes: Source[] = [];
|
||||
pageMatchers.forEach((pageMatcher) => {
|
||||
pageMatchers.forEach(pageMatcher => {
|
||||
// in `vercel dev` we don't need to prefix the destination
|
||||
const dest = !isDev
|
||||
? path.join('/', entryDirectory, pageMatcher.pageName)
|
||||
@@ -693,7 +693,7 @@ export type NextPrerenderedRoutes = {
|
||||
};
|
||||
};
|
||||
|
||||
legacyBlockingRoutes: {
|
||||
blockingFallbackRoutes: {
|
||||
[route: string]: {
|
||||
routeRegex: string;
|
||||
dataRoute: string;
|
||||
@@ -797,7 +797,7 @@ export async function getPrerenderManifest(
|
||||
if (!hasManifest) {
|
||||
return {
|
||||
staticRoutes: {},
|
||||
legacyBlockingRoutes: {},
|
||||
blockingFallbackRoutes: {},
|
||||
fallbackRoutes: {},
|
||||
bypassToken: null,
|
||||
omittedRoutes: [],
|
||||
@@ -855,14 +855,14 @@ export async function getPrerenderManifest(
|
||||
|
||||
const ret: NextPrerenderedRoutes = {
|
||||
staticRoutes: {},
|
||||
legacyBlockingRoutes: {},
|
||||
blockingFallbackRoutes: {},
|
||||
fallbackRoutes: {},
|
||||
bypassToken:
|
||||
(manifest.preview && manifest.preview.previewModeId) || null,
|
||||
omittedRoutes: [],
|
||||
};
|
||||
|
||||
routes.forEach((route) => {
|
||||
routes.forEach(route => {
|
||||
const {
|
||||
initialRevalidateSeconds,
|
||||
dataRoute,
|
||||
@@ -878,7 +878,7 @@ export async function getPrerenderManifest(
|
||||
};
|
||||
});
|
||||
|
||||
lazyRoutes.forEach((lazyRoute) => {
|
||||
lazyRoutes.forEach(lazyRoute => {
|
||||
const {
|
||||
routeRegex,
|
||||
fallback,
|
||||
@@ -894,7 +894,7 @@ export async function getPrerenderManifest(
|
||||
dataRouteRegex,
|
||||
};
|
||||
} else {
|
||||
ret.legacyBlockingRoutes[lazyRoute] = {
|
||||
ret.blockingFallbackRoutes[lazyRoute] = {
|
||||
routeRegex,
|
||||
dataRoute,
|
||||
dataRouteRegex,
|
||||
@@ -910,13 +910,13 @@ export async function getPrerenderManifest(
|
||||
|
||||
const ret: NextPrerenderedRoutes = {
|
||||
staticRoutes: {},
|
||||
legacyBlockingRoutes: {},
|
||||
blockingFallbackRoutes: {},
|
||||
fallbackRoutes: {},
|
||||
bypassToken: manifest.preview.previewModeId,
|
||||
omittedRoutes: [],
|
||||
};
|
||||
|
||||
routes.forEach((route) => {
|
||||
routes.forEach(route => {
|
||||
const {
|
||||
initialRevalidateSeconds,
|
||||
dataRoute,
|
||||
@@ -932,7 +932,7 @@ export async function getPrerenderManifest(
|
||||
};
|
||||
});
|
||||
|
||||
lazyRoutes.forEach((lazyRoute) => {
|
||||
lazyRoutes.forEach(lazyRoute => {
|
||||
const {
|
||||
routeRegex,
|
||||
fallback,
|
||||
@@ -940,19 +940,24 @@ export async function getPrerenderManifest(
|
||||
dataRouteRegex,
|
||||
} = manifest.dynamicRoutes[lazyRoute];
|
||||
|
||||
if (!fallback) {
|
||||
if (typeof fallback === 'string') {
|
||||
ret.fallbackRoutes[lazyRoute] = {
|
||||
routeRegex,
|
||||
fallback,
|
||||
dataRoute,
|
||||
dataRouteRegex,
|
||||
};
|
||||
} else if (fallback === null) {
|
||||
ret.blockingFallbackRoutes[lazyRoute] = {
|
||||
routeRegex,
|
||||
dataRoute,
|
||||
dataRouteRegex,
|
||||
};
|
||||
} else {
|
||||
// Fallback behavior is disabled, all routes would've been provided
|
||||
// in the top-level `routes` key (`staticRoutes`).
|
||||
ret.omittedRoutes.push(lazyRoute);
|
||||
return;
|
||||
}
|
||||
|
||||
ret.fallbackRoutes[lazyRoute] = {
|
||||
routeRegex,
|
||||
fallback,
|
||||
dataRoute,
|
||||
dataRouteRegex,
|
||||
};
|
||||
});
|
||||
|
||||
return ret;
|
||||
@@ -960,7 +965,7 @@ export async function getPrerenderManifest(
|
||||
default: {
|
||||
return {
|
||||
staticRoutes: {},
|
||||
legacyBlockingRoutes: {},
|
||||
blockingFallbackRoutes: {},
|
||||
fallbackRoutes: {},
|
||||
bypassToken: null,
|
||||
omittedRoutes: [],
|
||||
|
||||
@@ -1 +1,6 @@
|
||||
module.exports = { trailingSlash: true };
|
||||
module.exports = {
|
||||
generateBuildId() {
|
||||
return 'testing-build-id';
|
||||
},
|
||||
trailingSlash: true,
|
||||
};
|
||||
|
||||
@@ -33,6 +33,48 @@
|
||||
"path": "/test.txt",
|
||||
"status": 200,
|
||||
"mustContain": "this is a file"
|
||||
},
|
||||
{
|
||||
"fetchOptions": { "redirect": "manual" },
|
||||
"path": "/blog/post-1",
|
||||
"status": 308,
|
||||
"responseHeaders": {
|
||||
"refresh": "/url=/blog/post-1/$/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"fetchOptions": { "redirect": "manual" },
|
||||
"path": "/blog/post-1/",
|
||||
"status": 200,
|
||||
"mustContain": "post: <!-- -->post-1"
|
||||
},
|
||||
{
|
||||
"fetchOptions": { "redirect": "manual" },
|
||||
"path": "/_next/data/testing-build-id/blog/post-1.json/",
|
||||
"status": 308,
|
||||
"responseHeaders": {
|
||||
"refresh": "/url=/_next/data/testing-build-id/blog/post-1.json$/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"fetchOptions": { "redirect": "manual" },
|
||||
"path": "/_next/data/testing-build-id/blog/post-1.json",
|
||||
"status": 200,
|
||||
"mustContain": "\"post-1\""
|
||||
},
|
||||
{
|
||||
"fetchOptions": { "redirect": "manual" },
|
||||
"path": "/api/hello",
|
||||
"status": 308,
|
||||
"responseHeaders": {
|
||||
"refresh": "/url=/api/hello/$/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"fetchOptions": { "redirect": "manual" },
|
||||
"path": "/api/hello/",
|
||||
"status": 200,
|
||||
"mustContain": "hello from API"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
export default function Page() {
|
||||
return <p>nested page</p>;
|
||||
}
|
||||
|
||||
export const getServerSideProps = () => {
|
||||
return {
|
||||
props: {
|
||||
hello: 'world',
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
3
packages/now-next/test/fixtures/00-trailing-slash-add/pages/api/hello.js
vendored
Normal file
3
packages/now-next/test/fixtures/00-trailing-slash-add/pages/api/hello.js
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
export default (req, res) => {
|
||||
res.end('hello from API');
|
||||
};
|
||||
11
packages/now-next/test/fixtures/00-trailing-slash-add/pages/blog/[post].js
vendored
Normal file
11
packages/now-next/test/fixtures/00-trailing-slash-add/pages/blog/[post].js
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
export default function Page({ post }) {
|
||||
return <p>post: {post}</p>;
|
||||
}
|
||||
|
||||
export const getServerSideProps = ({ params }) => {
|
||||
return {
|
||||
props: {
|
||||
post: params.post,
|
||||
},
|
||||
};
|
||||
};
|
||||
108
packages/now-next/test/fixtures/30-monorepo-no-script/.gitignore
vendored
Normal file
108
packages/now-next/test/fixtures/30-monorepo-no-script/.gitignore
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# TypeScript v1 declaration files
|
||||
typings/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
.env.test
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
|
||||
# Next.js build output
|
||||
.next
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
dist
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
# Comment in the public line in if your project uses Gatsby and *not* Next.js
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
# public
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
# IDEA
|
||||
.idea/
|
||||
*.iml
|
||||
7
packages/now-next/test/fixtures/30-monorepo-no-script/babel.config.js
vendored
Normal file
7
packages/now-next/test/fixtures/30-monorepo-no-script/babel.config.js
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
module.exports = api => {
|
||||
api.cache(true);
|
||||
|
||||
const presets = [require.resolve('next/babel')];
|
||||
|
||||
return { presets, plugins: [] };
|
||||
};
|
||||
31
packages/now-next/test/fixtures/30-monorepo-no-script/now.json
vendored
Normal file
31
packages/now-next/test/fixtures/30-monorepo-no-script/now.json
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"version": 2,
|
||||
"uploadNowJson": true,
|
||||
"builds": [{ "src": "packages/www/package.json", "use": "@vercel/next" }],
|
||||
"routes": [{ "src": "/(.*)", "dest": "/packages/www/$1" }],
|
||||
"probes": [
|
||||
{
|
||||
"path": "/",
|
||||
"status": 200,
|
||||
"mustContain": "Hello World"
|
||||
},
|
||||
{
|
||||
"logMustContain": "Your application is being built using `next build`"
|
||||
},
|
||||
{
|
||||
"logMustContain": "WARNING: your application is being opted out of @vercel/next's optimized lambdas mode due to legacy routes"
|
||||
},
|
||||
{
|
||||
"logMustNotContain": "WARNING: Your application is being opted out of \"@vercel/next\" optimized lambdas mode due to `functions` config"
|
||||
},
|
||||
{
|
||||
"logMustNotContain": "Traced Next.js serverless functions for external files in"
|
||||
},
|
||||
{
|
||||
"logMustNotContain": "All serverless functions created in"
|
||||
},
|
||||
{
|
||||
"logMustNotContain": "Compressed shared serverless function files"
|
||||
}
|
||||
]
|
||||
}
|
||||
11
packages/now-next/test/fixtures/30-monorepo-no-script/package.json
vendored
Normal file
11
packages/now-next/test/fixtures/30-monorepo-no-script/package.json
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"private": true,
|
||||
"workspaces": [
|
||||
"packages/*"
|
||||
],
|
||||
"dependencies": {
|
||||
"next": "9.5.1",
|
||||
"react": "16.13.1",
|
||||
"react-dom": "16.13.1"
|
||||
}
|
||||
}
|
||||
8
packages/now-next/test/fixtures/30-monorepo-no-script/packages/www/next.config.js
vendored
Normal file
8
packages/now-next/test/fixtures/30-monorepo-no-script/packages/www/next.config.js
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
module.exports = {
|
||||
poweredByHeader: false,
|
||||
|
||||
webpack: (config, { defaultLoaders }) => {
|
||||
defaultLoaders.babel.options.rootMode = 'upward';
|
||||
return config;
|
||||
},
|
||||
};
|
||||
6
packages/now-next/test/fixtures/30-monorepo-no-script/packages/www/package.json
vendored
Normal file
6
packages/now-next/test/fixtures/30-monorepo-no-script/packages/www/package.json
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"name": "@vercel-crash-demo/www",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"sideEffects": false
|
||||
}
|
||||
7
packages/now-next/test/fixtures/30-monorepo-no-script/packages/www/pages/index.jsx
vendored
Normal file
7
packages/now-next/test/fixtures/30-monorepo-no-script/packages/www/pages/index.jsx
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
import React from 'react';
|
||||
|
||||
const HelloWorld = () => (
|
||||
<h1>Hello World</h1>
|
||||
);
|
||||
|
||||
export default HelloWorld;
|
||||
5516
packages/now-next/test/fixtures/30-monorepo-no-script/yarn.lock
vendored
Normal file
5516
packages/now-next/test/fixtures/30-monorepo-no-script/yarn.lock
vendored
Normal file
File diff suppressed because it is too large
Load Diff
54
packages/now-next/test/fixtures/31-blocking-fallback/additional.js
vendored
Normal file
54
packages/now-next/test/fixtures/31-blocking-fallback/additional.js
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
/* eslint-env jest */
|
||||
const fetch = require('node-fetch');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
module.exports = function (ctx) {
|
||||
it('should revalidate content properly from dynamic pathname', async () => {
|
||||
// wait for revalidation to expire
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
const res = await fetch(`${ctx.deploymentUrl}/regenerated/blue`);
|
||||
expect(res.status).toBe(200);
|
||||
|
||||
let $ = cheerio.load(await res.text());
|
||||
const initialTime = $('#time').text();
|
||||
expect($('#slug').text()).toBe('blue');
|
||||
|
||||
// wait for revalidation to occur
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
const res2 = await fetch(`${ctx.deploymentUrl}/regenerated/blue`);
|
||||
expect(res2.status).toBe(200);
|
||||
|
||||
$ = cheerio.load(await res2.text());
|
||||
expect($('#slug').text()).toBe('blue');
|
||||
expect(initialTime).not.toBe($('#time').text());
|
||||
});
|
||||
|
||||
it('should revalidate content properly from /_next/data dynamic pathname', async () => {
|
||||
// wait for revalidation to expire
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
const res = await fetch(
|
||||
`${ctx.deploymentUrl}/_next/data/testing-build-id/regenerated/blue.json`
|
||||
);
|
||||
expect(res.status).toBe(200);
|
||||
|
||||
const { pageProps: data } = await res.json();
|
||||
const initialTime = data.time;
|
||||
expect(data.slug).toBe('blue');
|
||||
expect(isNaN(initialTime)).toBe(false);
|
||||
|
||||
// wait for revalidation to occur
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
const res2 = await fetch(
|
||||
`${ctx.deploymentUrl}/_next/data/testing-build-id/regenerated/blue.json`
|
||||
);
|
||||
expect(res2.status).toBe(200);
|
||||
|
||||
const { pageProps: data2 } = await res2.json();
|
||||
expect(data2.slug).toBe('blue');
|
||||
expect(initialTime).not.toBe(data2.time);
|
||||
});
|
||||
};
|
||||
5
packages/now-next/test/fixtures/31-blocking-fallback/next.config.js
vendored
Normal file
5
packages/now-next/test/fixtures/31-blocking-fallback/next.config.js
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
module.exports = {
|
||||
generateBuildId() {
|
||||
return 'testing-build-id';
|
||||
},
|
||||
};
|
||||
62
packages/now-next/test/fixtures/31-blocking-fallback/now.json
vendored
Normal file
62
packages/now-next/test/fixtures/31-blocking-fallback/now.json
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
{
|
||||
"version": 2,
|
||||
"builds": [
|
||||
{
|
||||
"src": "package.json",
|
||||
"use": "@vercel/next"
|
||||
}
|
||||
],
|
||||
"probes": [
|
||||
{
|
||||
"path": "/fixed/yellow",
|
||||
"status": 200,
|
||||
"mustContain": "yellow"
|
||||
},
|
||||
{ "delay": 2000 },
|
||||
{
|
||||
"path": "/fixed/yellow",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-vercel-cache": "HIT"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/fixed/yellow.json",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-vercel-cache": "HIT"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/fixed/yellow",
|
||||
"status": 200,
|
||||
"mustContain": "yellow"
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/fixed/yellow.json",
|
||||
"status": 200,
|
||||
"mustContain": "yellow"
|
||||
},
|
||||
|
||||
{
|
||||
"path": "/regenerated/blue",
|
||||
"status": 200,
|
||||
"mustContain": "blue"
|
||||
},
|
||||
{ "delay": 2000 },
|
||||
{
|
||||
"path": "/regenerated/blue",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-vercel-cache": "/HIT|STALE/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/regenerated/blue.json",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-vercel-cache": "/HIT|STALE/"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
7
packages/now-next/test/fixtures/31-blocking-fallback/package.json
vendored
Normal file
7
packages/now-next/test/fixtures/31-blocking-fallback/package.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"next": "canary",
|
||||
"react": "^16.8.6",
|
||||
"react-dom": "^16.8.6"
|
||||
}
|
||||
}
|
||||
23
packages/now-next/test/fixtures/31-blocking-fallback/pages/fixed/[slug].js
vendored
Normal file
23
packages/now-next/test/fixtures/31-blocking-fallback/pages/fixed/[slug].js
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
export default function TestPage({ slug, time }) {
|
||||
return (
|
||||
<>
|
||||
Slug: <div id="slug">{slug}</div>
|
||||
<br />
|
||||
Time: <div id="time">{time}</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export function getStaticProps({ params }) {
|
||||
return {
|
||||
props: {
|
||||
slug: params.slug,
|
||||
time: new Date().getTime(),
|
||||
},
|
||||
revalidate: false,
|
||||
};
|
||||
}
|
||||
|
||||
export function getStaticPaths() {
|
||||
return { paths: [], fallback: 'unstable_blocking' };
|
||||
}
|
||||
23
packages/now-next/test/fixtures/31-blocking-fallback/pages/regenerated/[slug].js
vendored
Normal file
23
packages/now-next/test/fixtures/31-blocking-fallback/pages/regenerated/[slug].js
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
export default function TestPage({ slug, time }) {
|
||||
return (
|
||||
<>
|
||||
Slug: <div id="slug">{slug}</div>
|
||||
<br />
|
||||
Time: <div id="time">{time}</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export function getStaticProps({ params }) {
|
||||
return {
|
||||
props: {
|
||||
slug: params.slug,
|
||||
time: new Date().getTime(),
|
||||
},
|
||||
revalidate: true,
|
||||
};
|
||||
}
|
||||
|
||||
export function getStaticPaths() {
|
||||
return { paths: [], fallback: 'unstable_blocking' };
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/node",
|
||||
"version": "1.7.4",
|
||||
"version": "1.7.5-canary.1",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index",
|
||||
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/node-js",
|
||||
@@ -33,7 +33,7 @@
|
||||
"@types/etag": "1.8.0",
|
||||
"@types/test-listen": "1.1.0",
|
||||
"@zeit/ncc": "0.20.4",
|
||||
"@zeit/node-file-trace": "0.8.1",
|
||||
"@zeit/node-file-trace": "0.8.2",
|
||||
"content-type": "1.0.4",
|
||||
"cookie": "0.4.0",
|
||||
"etag": "1.8.1",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/routing-utils",
|
||||
"version": "1.8.3",
|
||||
"version": "1.8.4-canary.0",
|
||||
"description": "Vercel routing utilities",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
|
||||
@@ -218,18 +218,42 @@ function replaceSegments(
|
||||
return destination;
|
||||
}
|
||||
|
||||
function safelyCompile(str: string, indexes: { [k: string]: string }): string {
|
||||
if (!str) {
|
||||
return str;
|
||||
function safelyCompile(
|
||||
value: string,
|
||||
indexes: { [k: string]: string }
|
||||
): string {
|
||||
if (!value) {
|
||||
return value;
|
||||
}
|
||||
// path-to-regexp cannot compile question marks
|
||||
return str
|
||||
.split('?')
|
||||
.map(part => {
|
||||
const compiler = compile(part);
|
||||
return compiler(indexes);
|
||||
})
|
||||
.join('?');
|
||||
|
||||
for (const key of Object.keys(indexes)) {
|
||||
if (value.includes(`:${key}`)) {
|
||||
value = value
|
||||
.replace(
|
||||
new RegExp(`:${key}\\*`, 'g'),
|
||||
`:${key}--ESCAPED_PARAM_ASTERISK`
|
||||
)
|
||||
.replace(
|
||||
new RegExp(`:${key}\\?`, 'g'),
|
||||
`:${key}--ESCAPED_PARAM_QUESTION`
|
||||
)
|
||||
.replace(new RegExp(`:${key}\\+`, 'g'), `:${key}--ESCAPED_PARAM_PLUS`)
|
||||
.replace(
|
||||
new RegExp(`:${key}(?!\\w)`, 'g'),
|
||||
`--ESCAPED_PARAM_COLON${key}`
|
||||
);
|
||||
}
|
||||
}
|
||||
value = value
|
||||
.replace(/(:|\*|\?|\+|\(|\)|\{|\})/g, '\\$1')
|
||||
.replace(/--ESCAPED_PARAM_PLUS/g, '+')
|
||||
.replace(/--ESCAPED_PARAM_COLON/g, ':')
|
||||
.replace(/--ESCAPED_PARAM_QUESTION/g, '?')
|
||||
.replace(/--ESCAPED_PARAM_ASTERISK/g, '*');
|
||||
|
||||
// the value needs to start with a forward-slash to be compiled
|
||||
// correctly
|
||||
return compile(`/${value}`, { validate: false })(indexes).substr(1);
|
||||
}
|
||||
|
||||
function toSegmentDest(index: number): string {
|
||||
|
||||
@@ -508,6 +508,60 @@ test('convertHeaders', () => {
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
source: '/like/params/:path',
|
||||
headers: [
|
||||
{
|
||||
key: 'x-path',
|
||||
value: ':path',
|
||||
},
|
||||
{
|
||||
key: 'some:path',
|
||||
value: 'hi',
|
||||
},
|
||||
{
|
||||
key: 'x-test',
|
||||
value: 'some:value*',
|
||||
},
|
||||
{
|
||||
key: 'x-test-2',
|
||||
value: 'value*',
|
||||
},
|
||||
{
|
||||
key: 'x-test-3',
|
||||
value: ':value?',
|
||||
},
|
||||
{
|
||||
key: 'x-test-4',
|
||||
value: ':value+',
|
||||
},
|
||||
{
|
||||
key: 'x-test-5',
|
||||
value: 'something https:',
|
||||
},
|
||||
{
|
||||
key: 'x-test-6',
|
||||
value: ':hello(world)',
|
||||
},
|
||||
{
|
||||
key: 'x-test-7',
|
||||
value: 'hello(world)',
|
||||
},
|
||||
{
|
||||
key: 'x-test-8',
|
||||
value: 'hello{1,}',
|
||||
},
|
||||
{
|
||||
key: 'x-test-9',
|
||||
value: ':hello{1,2}',
|
||||
},
|
||||
{
|
||||
key: 'content-security-policy',
|
||||
value:
|
||||
"default-src 'self'; img-src *; media-src media1.com media2.com; script-src userscripts.example.com/:path",
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
||||
const expected = [
|
||||
@@ -526,6 +580,25 @@ test('convertHeaders', () => {
|
||||
headers: { 'on-blog': '$1', $1: 'blog' },
|
||||
continue: true,
|
||||
},
|
||||
{
|
||||
continue: true,
|
||||
headers: {
|
||||
'content-security-policy':
|
||||
"default-src 'self'; img-src *; media-src media1.com media2.com; script-src userscripts.example.com/$1",
|
||||
some$1: 'hi',
|
||||
'x-path': '$1',
|
||||
'x-test': 'some:value*',
|
||||
'x-test-2': 'value*',
|
||||
'x-test-3': ':value?',
|
||||
'x-test-4': ':value+',
|
||||
'x-test-5': 'something https:',
|
||||
'x-test-6': ':hello(world)',
|
||||
'x-test-7': 'hello(world)',
|
||||
'x-test-8': 'hello{1,}',
|
||||
'x-test-9': ':hello{1,2}',
|
||||
},
|
||||
src: '^\\/like\\/params(?:\\/([^\\/]+?))$',
|
||||
},
|
||||
];
|
||||
|
||||
deepEqual(actual, expected);
|
||||
@@ -534,12 +607,14 @@ test('convertHeaders', () => {
|
||||
['hello/world/file.eot', 'another/font.ttf', 'dir/arial.font.css'],
|
||||
['404.html'],
|
||||
['/blog/first-post', '/blog/another/one'],
|
||||
['/like/params/first', '/like/params/second'],
|
||||
];
|
||||
|
||||
const mustNotMatch = [
|
||||
['hello/file.jpg', 'hello/font-css', 'dir/arial.font-css'],
|
||||
['403.html', '500.html'],
|
||||
['/blogg', '/random'],
|
||||
['/non-match', '/like/params', '/like/params/'],
|
||||
];
|
||||
|
||||
assertRegexMatches(actual, mustMatch, mustNotMatch);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/static-build",
|
||||
"version": "0.17.7-canary.1",
|
||||
"version": "0.17.7-canary.3",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index",
|
||||
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/static-builds",
|
||||
|
||||
@@ -125,7 +125,27 @@ const frameworkList: Framework[] = [
|
||||
},
|
||||
defaultRoutes: [
|
||||
{
|
||||
src: '^/[^./]+\\.[0-9a-f]{8}\\.(css|js)',
|
||||
src: '^/[^./]+\\.[0-9a-f]{8}\\.(css|js)$',
|
||||
headers: { 'cache-control': 'max-age=31536000, immutable' },
|
||||
continue: true,
|
||||
},
|
||||
{
|
||||
src: '^/assets/images/[^/]+-[0-9a-f]{32}\\.(ico|svg|jpg|jpeg|png|gif|webp)$',
|
||||
headers: { 'cache-control': 'max-age=31536000, immutable' },
|
||||
continue: true,
|
||||
},
|
||||
{
|
||||
src: '^/assets/medias/[^/]+-[0-9a-f]{32}\\.(ogv|wav|mp3|m4a|aac|oga|flac)$',
|
||||
headers: { 'cache-control': 'max-age=31536000, immutable' },
|
||||
continue: true,
|
||||
},
|
||||
{
|
||||
src: '^/assets/files/[^/]+-[0-9a-f]{32}\\.(pdf|doc|docx|xls|xlsx|zip|rar)$',
|
||||
headers: { 'cache-control': 'max-age=31536000, immutable' },
|
||||
continue: true,
|
||||
},
|
||||
{
|
||||
src: '^/ideal-img/[^/]+\\.[0-9a-f]{7}\\.\\d+\\.(png|jpe?g|gif)$',
|
||||
headers: { 'cache-control': 'max-age=31536000, immutable' },
|
||||
continue: true,
|
||||
},
|
||||
|
||||
@@ -33,7 +33,6 @@ const {
|
||||
NowBuildError,
|
||||
} = buildUtils;
|
||||
import { Route, Source } from '@vercel/routing-utils';
|
||||
import { getVercelIgnore } from '@vercel/client';
|
||||
|
||||
const sleep = (n: number) => new Promise(resolve => setTimeout(resolve, n));
|
||||
|
||||
@@ -484,17 +483,17 @@ export async function build({
|
||||
}
|
||||
|
||||
let ignore: string[] = [];
|
||||
if (config.zeroConfig) {
|
||||
const result = await getVercelIgnore(distPath);
|
||||
ignore = result.ignores
|
||||
.map(file => (file.endsWith('/') ? `${file}**` : file))
|
||||
.concat([
|
||||
'.env',
|
||||
'.env.*',
|
||||
'yarn.lock',
|
||||
'package-lock.json',
|
||||
'package.json',
|
||||
]);
|
||||
if (config.zeroConfig && config.outputDirectory === '.') {
|
||||
ignore = [
|
||||
'.env',
|
||||
'.env.*',
|
||||
'.git/**',
|
||||
'.vercel/**',
|
||||
'node_modules/**',
|
||||
'yarn.lock',
|
||||
'package-lock.json',
|
||||
'package.json',
|
||||
];
|
||||
debug(`Using ignore: ${JSON.stringify(ignore)}`);
|
||||
}
|
||||
output = await glob('**', { cwd: distPath, ignore }, mountpoint);
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
# Contributing to the Ionic Conference Application
|
||||
|
||||
Thank you for taking the time to contribute! :tada::+1:
|
||||
|
||||
The following is a set of guidelines for contributing to the conference app. These are just guidelines, not rules, use your best judgment and feel free to propose changes to this document in a pull request.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [How To Contribute](#how-to-contribute)
|
||||
- [Reporting Issues](#reporting-issues)
|
||||
- [Before Submitting an Issue](#before-submitting-an-issue)
|
||||
- [Determining the Repository](#determining-the-repository)
|
||||
- [Submitting the Issue](#submitting-the-issue)
|
||||
- [Submitting a Pull Request](#submitting-a-pull-request)
|
||||
- [Guidelines for Submitting](#guidelines-for-submitting)
|
||||
- [Code Style](#code-style)
|
||||
|
||||
## How To Contribute
|
||||
|
||||
### Reporting Issues
|
||||
|
||||
Before submitting an issue, please go through [the list below](#before-submitting-an-issue) as you might find a solution to your issue.
|
||||
|
||||
#### Before Submitting an Issue
|
||||
|
||||
- Make sure you get the latest version of the code and run through the [Getting Started](https://github.com/ionic-team/ionic-conference-app#getting-started) steps to see if this resolves your issue.
|
||||
- Check the [forum](https://forum.ionicframework.com) for similar questions and answers.
|
||||
- Go through [all issues](https://github.com/ionic-team/ionic-conference-app/issues?utf8=%E2%9C%93&q=is%3Aissue) on this repository to see if the issue has already been created. It could have been closed with a resolution, so check closed issues, too.
|
||||
- Chat with us in the [#ionic-v2](https://ionic-worldwide.slack.com/messages/ionic-v2/) channel on [Slack](http://ionicworldwide.herokuapp.com/) to see if we can find a solution to the problem!
|
||||
- [Determine which repository](#determining-the-repository) the problem should be reported in.
|
||||
|
||||
#### Determining the Repository
|
||||
|
||||
There are several repositories being used for Ionic, which makes it difficult to determine which one to report an issue to. Don't worry if you aren't sure, we can always move it!
|
||||
|
||||
- The [Ionic repository](https://github.com/ionic-team/ionic) is a repository for all things related to the Ionic Framework. If you are able to reproduce the issue in any of the Ionic starters (or an existing project), you'll want to submit the issue [here](http://ionicframework.com/submit-issue/).
|
||||
- The [Ionic CLI repository](https://github.com/ionic-team/ionic-cli) contains all of the code that allows you to run `ionic` commands from a terminal window. It is safe to put any issues [here](https://github.com/ionic-team/ionic-cli/issues) that relate to running an `ionic` command.
|
||||
- [This repository](https://github.com/ionic-team/ionic-conference-app) is a demo of the Ionic Framework. If you find an issue with this app that does not occur on [a new app](http://ionicframework.com/docs/v2/getting-started/installation/), please submit the issue [here](https://github.com/ionic-team/ionic-conference-app/issues).
|
||||
|
||||
#### Submitting the Issue
|
||||
|
||||
- **Use a clear and descriptive title** for the issue to identify the problem. This makes it easier for others to find.
|
||||
- **Describe the exact steps to reproduce the problem** with as many details as needed.
|
||||
- **Provide your configuration** by running `ionic info` in a terminal from _within_ the project folder and pasting this information in the issue.
|
||||
|
||||
### Submitting a Pull Request
|
||||
|
||||
#### Guidelines for Submitting
|
||||
|
||||
When in doubt, keep your pull requests small. To give a PR the best chance of getting accepted, do not bundle more than one "feature" or bug fix per PR. Doing so makes it very hard to accept it if one of the fixes has issues.
|
||||
|
||||
It's always best to create two smaller PRs than one big one.
|
||||
|
||||
Talk to us before creating a PR that refactors the code or directory structure of the project. This project is constantly changing to reflect the latest version of Ionic Framework so sometimes it will be in the process of getting fixed.
|
||||
|
||||
#### Code Style
|
||||
|
||||
Make sure to follow the existing code style as much as possible.
|
||||
|
||||
- No underscores prefixing JS functions.
|
||||
- Use flat Sass.
|
||||
- **Don't** use [BEM conventions](https://css-tricks.com/bem-101/).
|
||||
- Avoid nesting selectors. This is done to make it easier for users without Sass experience to understand and read.
|
||||
@@ -1,41 +0,0 @@
|
||||
<!--
|
||||
IF YOU DON'T FILL OUT THE FOLLOWING INFORMATION WE MIGHT CLOSE YOUR ISSUE WITHOUT INVESTIGATING
|
||||
|
||||
If you are having problems formatting your issue please refer to this article on using markdown in Github: https://guides.github.com/features/mastering-markdown/
|
||||
-->
|
||||
|
||||
**I'm submitting a ...** (check one with "x")
|
||||
[ ] bug report
|
||||
[ ] feature request
|
||||
[ ] support request => Please do not submit support requests here, use one of these channels: https://forum.ionicframework.com/ or http://ionicworldwide.herokuapp.com/
|
||||
|
||||
**Current behavior:**
|
||||
|
||||
<!-- Describe how the bug manifests. -->
|
||||
|
||||
**Expected behavior:**
|
||||
|
||||
<!-- Describe what the behavior would be without the bug. -->
|
||||
|
||||
**Steps to reproduce:**
|
||||
|
||||
<!-- If you are able to illustrate the bug or feature request with an example, please provide steps to reproduce and if possible a demo using the following template:
|
||||
|
||||
http://plnkr.co/edit/GJte2b?p=preview
|
||||
-->
|
||||
|
||||
**Related code:**
|
||||
|
||||
```
|
||||
insert any relevant code here
|
||||
```
|
||||
|
||||
**Other information:**
|
||||
|
||||
<!-- List any other information that is relevant to your issue. Stack traces, related issues, suggestions on how to fix, Stack Overflow links, forum links, etc. -->
|
||||
|
||||
**Ionic info:** (run `ionic info` from a terminal/cmd prompt and paste output below):
|
||||
|
||||
```
|
||||
insert the output from ionic info here
|
||||
```
|
||||
@@ -1,133 +0,0 @@
|
||||
triage:
|
||||
label: triage
|
||||
removeLabelWhenProjectAssigned: true
|
||||
dryRun: false
|
||||
|
||||
closeAndLock:
|
||||
labels:
|
||||
- label: "ionitron: support"
|
||||
message: >
|
||||
Thanks for the issue! This issue appears to be a support request. We use this issue tracker exclusively for
|
||||
bug reports and feature requests. Please use our [forum](https://forum.ionicframework.com) or our
|
||||
[slack channel](https://ionicworldwide.herokuapp.com/) for questions about the framework.
|
||||
|
||||
|
||||
Thank you for using Ionic!
|
||||
- label: "ionitron: ionic pro"
|
||||
message: >
|
||||
Thanks for the issue! This issue appears to be related to Ionic Pro. We use this issue tracker exclusively for
|
||||
bug reports and feature requests. Please use the [Ionic Pro Support Forum](https://ionic.zendesk.com/hc/en-us/requests/new)
|
||||
to report this issue.
|
||||
|
||||
|
||||
Thank you for using Ionic!
|
||||
- label: "ionitron: missing template"
|
||||
message: >
|
||||
Thanks for the issue! It appears that you have not filled out the provided issue template. We use this issue
|
||||
template in order to gather more information and further assist you. Please create a new issue and ensure the
|
||||
template is fully filled out.
|
||||
|
||||
|
||||
Thank you for using Ionic!
|
||||
close: true
|
||||
lock: true
|
||||
dryRun: false
|
||||
|
||||
lockClosed:
|
||||
days: 30
|
||||
maxIssuesPerRun: 100
|
||||
message: >
|
||||
Thanks for the issue! This issue is being locked to prevent comments that are not relevant to the original issue.
|
||||
If this is still an issue with the latest version of the Ionic Conference App, please create a new issue and ensure
|
||||
the template is fully filled out.
|
||||
dryRun: false
|
||||
|
||||
stale:
|
||||
days: 365
|
||||
maxIssuesPerRun: 100
|
||||
exemptLabels:
|
||||
- good first issue
|
||||
- triage
|
||||
exemptAssigned: true
|
||||
exemptProjects: true
|
||||
exemptMilestones: true
|
||||
label: "ionitron: stale issue"
|
||||
message: >
|
||||
Thanks for the issue! This issue is being closed due to inactivity. If this is still
|
||||
an issue with the latest version of the Ionic Conference App, please create a new issue
|
||||
and ensure the template is fully filled out.
|
||||
|
||||
|
||||
Thank you for using Ionic!
|
||||
close: true
|
||||
lock: true
|
||||
dryRun: false
|
||||
|
||||
noReply:
|
||||
days: 30
|
||||
maxIssuesPerRun: 100
|
||||
label: needs reply
|
||||
responseLabel: triage
|
||||
exemptProjects: true
|
||||
exemptMilestones: true
|
||||
message: >
|
||||
Thanks for the issue! This issue is being closed due to the lack of a reply. If this is still
|
||||
an issue with the latest version of the Ionic Conference App, please create a new issue
|
||||
and ensure the template is fully filled out.
|
||||
|
||||
|
||||
Thank you for using Ionic!
|
||||
close: true
|
||||
lock: true
|
||||
dryRun: false
|
||||
|
||||
wrongRepo:
|
||||
repos:
|
||||
- label: "ionitron: ionic"
|
||||
repo: ionic
|
||||
message: >
|
||||
Thanks for the issue! We use this issue tracker exclusively for bug reports and feature requests
|
||||
associated with the Ionic Conference App. It appears that this issue is associated with the Ionic Framework.
|
||||
I am moving this issue to the Ionic Framework repository. Please track this issue over there.
|
||||
|
||||
|
||||
Thank you for using Ionic!
|
||||
- label: "ionitron: cli"
|
||||
repo: ionic-cli
|
||||
message: >
|
||||
Thanks for the issue! We use this issue tracker exclusively for bug reports and feature requests
|
||||
associated with the Ionic Conference App. It appears that this issue is associated with the Ionic CLI.
|
||||
I am moving this issue to the Ionic CLI repository. Please track this issue over there.
|
||||
|
||||
|
||||
Thank you for using Ionic!
|
||||
- label: "ionitron: docs"
|
||||
repo: ionic-docs
|
||||
message: >
|
||||
Thanks for the issue! We use this issue tracker exclusively for bug reports and feature requests
|
||||
associated with the Ionic Conference App. It appears that this issue is associated with the Ionic Documentation.
|
||||
I am moving this issue to the Ionic Docs repository. Please track this issue over there.
|
||||
|
||||
|
||||
Thank you for using Ionic!
|
||||
- label: "ionitron: stencil"
|
||||
repo: stencil
|
||||
message: >
|
||||
Thanks for the issue! We use this issue tracker exclusively for bug reports and feature requests
|
||||
associated with the Ionic Conference App. It appears that this issue is associated with Stencil.
|
||||
I am moving this issue to the Stencil repository. Please track this issue over there.
|
||||
|
||||
|
||||
Thank you for using Ionic!
|
||||
- label: "ionitron: native"
|
||||
repo: ionic-native
|
||||
message: >
|
||||
Thanks for the issue! We use this issue tracker exclusively for bug reports and feature requests
|
||||
associated with the Ionic Conference App. It appears that this issue is associated with Ionic Native.
|
||||
I am moving this issue to the Ionic Native repository. Please track this issue over there.
|
||||
|
||||
|
||||
Thank you for using Ionic!
|
||||
close: true
|
||||
lock: true
|
||||
dryRun: false
|
||||
@@ -1,33 +0,0 @@
|
||||
# GitHub Actions docs
|
||||
# https://help.github.com/en/articles/about-github-actions
|
||||
# https://help.github.com/en/articles/workflow-syntax-for-github-actions
|
||||
|
||||
name: Install Dependencies, Lint, Build and Test
|
||||
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: Test on node ${{ matrix.node_version }} and ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
node_version: [12]
|
||||
os: [windows-latest, macOS-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Use Node.js ${{ matrix.node_version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node_version }}
|
||||
- name: Install Dependencies
|
||||
run: npm ci
|
||||
- name: Lint
|
||||
run: npm run lint
|
||||
- name: Build
|
||||
run: npm run build -- --prod
|
||||
- name: Test
|
||||
run: npm test -- --configuration=ci
|
||||
- name: E2E
|
||||
run: npm run e2e -- --configuration=ci
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user