mirror of
https://github.com/LukeHagar/vercel.git
synced 2025-12-29 19:00:09 +00:00
Compare commits
33 Commits
loopless-4
...
@vercel/ne
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
421be5d738 | ||
|
|
b8eaf10974 | ||
|
|
92a4bf27cf | ||
|
|
2672838b64 | ||
|
|
1c96071ddc | ||
|
|
71cdf759da | ||
|
|
93ebd213de | ||
|
|
a32ba8f214 | ||
|
|
d416f70a6e | ||
|
|
ba9e1dd0ba | ||
|
|
d513f74b70 | ||
|
|
47f92f8f14 | ||
|
|
9aa669d735 | ||
|
|
99cab6f34a | ||
|
|
547e7dccf7 | ||
|
|
dce9a89407 | ||
|
|
c1cdddd974 | ||
|
|
4bce77dd4b | ||
|
|
3a79810944 | ||
|
|
5b3fbdddb3 | ||
|
|
25e9ecb5a2 | ||
|
|
415515840c | ||
|
|
9ba14be12e | ||
|
|
f1321946c5 | ||
|
|
230b69abf4 | ||
|
|
0d96f80ac8 | ||
|
|
178f5e7f00 | ||
|
|
dbfdf20c9d | ||
|
|
a80ed4ec9b | ||
|
|
833c3d7c01 | ||
|
|
19d0db7270 | ||
|
|
041e8cc601 | ||
|
|
b118e461b1 |
@@ -34,3 +34,6 @@ packages/now-node-bridge/bridge.*
|
||||
|
||||
# now-static-build
|
||||
packages/now-static-build/test/fixtures
|
||||
|
||||
# redwood
|
||||
packages/redwood/test/fixtures
|
||||
|
||||
10
examples/redwoodjs/.editorconfig
Normal file
10
examples/redwoodjs/.editorconfig
Normal file
@@ -0,0 +1,10 @@
|
||||
# editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_size = 2
|
||||
indent_style = space
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
7
examples/redwoodjs/.env.defaults
Normal file
7
examples/redwoodjs/.env.defaults
Normal file
@@ -0,0 +1,7 @@
|
||||
# These environment variables will be used by default if you do not create any
|
||||
# yourself in .env. This file should be safe to check into your version control
|
||||
# system. Any custom values should go in .env and .env should *not* be checked
|
||||
# into version control.
|
||||
|
||||
DATABASE_URL=file:./dev.db
|
||||
BINARY_TARGET=native
|
||||
10
examples/redwoodjs/.gitignore
vendored
Normal file
10
examples/redwoodjs/.gitignore
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
.DS_Store
|
||||
.env
|
||||
.netlify
|
||||
dev.db
|
||||
dist
|
||||
dist-babel
|
||||
node_modules
|
||||
yarn-error.log
|
||||
|
||||
.vercel
|
||||
1
examples/redwoodjs/.nvmrc
Normal file
1
examples/redwoodjs/.nvmrc
Normal file
@@ -0,0 +1 @@
|
||||
lts/*
|
||||
21
examples/redwoodjs/LICENSE
Normal file
21
examples/redwoodjs/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 Redwood
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
29
examples/redwoodjs/README.md
Normal file
29
examples/redwoodjs/README.md
Normal file
@@ -0,0 +1,29 @@
|
||||

|
||||
|
||||
# RedwoodJS Example
|
||||
|
||||
This directory is a brief example of a [RedwoodJS](https://redwoodjs.com) app with [Serverless Functions](https://vercel.com/docs/v2/serverless-functions/introduction) that can be deployed with Vercel and zero configuration.
|
||||
|
||||
## Deploy Your Own
|
||||
|
||||
Deploy your own RedwoodJS project, along with Serverless Functions, with Vercel.
|
||||
|
||||
[](https://vercel.com/import/project?template=https://github.com/vercel/vercel/tree/master/examples/redwoodjs)
|
||||
|
||||
_Live Example: https://redwoodjs.now-examples.now.sh_
|
||||
|
||||
### How We Created This Example
|
||||
|
||||
To get started with RedwoodJS on Vercel, you can [use Yarn to initialize](https://redwoodjs.com/tutorial/installation-starting-development) the project:
|
||||
|
||||
```shell
|
||||
$ yarn create redwood-app ./my-redwood-app
|
||||
```
|
||||
|
||||
### Deploying From Your Terminal
|
||||
|
||||
You can deploy your new RedwoodJS project, along with [Serverless Functions](https://vercel.com/docs/v2/serverless-functions/introduction), with a single command from your terminal using [Vercel CLI](https://vercel.com/download):
|
||||
|
||||
```shell
|
||||
$ vercel
|
||||
```
|
||||
1
examples/redwoodjs/api/.babelrc.js
Normal file
1
examples/redwoodjs/api/.babelrc.js
Normal file
@@ -0,0 +1 @@
|
||||
module.exports = { extends: '../babel.config.js' }
|
||||
9
examples/redwoodjs/api/jsconfig.json
Normal file
9
examples/redwoodjs/api/jsconfig.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"src/*": ["./src/*"]
|
||||
}
|
||||
},
|
||||
"include": ["src/**/*"]
|
||||
}
|
||||
8
examples/redwoodjs/api/package.json
Normal file
8
examples/redwoodjs/api/package.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "api",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@redwoodjs/api": "0.15.0"
|
||||
}
|
||||
}
|
||||
18
examples/redwoodjs/api/prisma/schema.prisma
Normal file
18
examples/redwoodjs/api/prisma/schema.prisma
Normal file
@@ -0,0 +1,18 @@
|
||||
datasource DS {
|
||||
provider = "sqlite"
|
||||
url = env("DATABASE_URL")
|
||||
}
|
||||
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
binaryTargets = env("BINARY_TARGET")
|
||||
}
|
||||
|
||||
// Define your own datamodels here and run `yarn redwood db save` to create
|
||||
// migrations for them.
|
||||
// TODO: Please remove the following example:
|
||||
model UserExample {
|
||||
id Int @id @default(autoincrement())
|
||||
email String @unique
|
||||
name String?
|
||||
}
|
||||
26
examples/redwoodjs/api/prisma/seeds.js
Normal file
26
examples/redwoodjs/api/prisma/seeds.js
Normal file
@@ -0,0 +1,26 @@
|
||||
/* eslint-disable no-console */
|
||||
const { PrismaClient } = require('@prisma/client')
|
||||
const dotenv = require('dotenv')
|
||||
|
||||
dotenv.config()
|
||||
const db = new PrismaClient()
|
||||
|
||||
async function main() {
|
||||
// Seed data is database data that needs to exist for your app to run.
|
||||
// Ideally this file should be idempotent: running it multiple times
|
||||
// will result in the same database state (usually by checking for the
|
||||
// existence of a record before trying to create it). For example:
|
||||
//
|
||||
// const existing = await db.user.findMany({ where: { email: 'admin@email.com' }})
|
||||
// if (!existing.length) {
|
||||
// await db.user.create({ data: { name: 'Admin', email: 'admin@email.com' }})
|
||||
// }
|
||||
|
||||
console.info('No data to seed. See api/prisma/seeds.js for info.')
|
||||
}
|
||||
|
||||
main()
|
||||
.catch((e) => console.error(e))
|
||||
.finally(async () => {
|
||||
await db.disconnect()
|
||||
})
|
||||
19
examples/redwoodjs/api/src/functions/graphql.js
Normal file
19
examples/redwoodjs/api/src/functions/graphql.js
Normal file
@@ -0,0 +1,19 @@
|
||||
import {
|
||||
createGraphQLHandler,
|
||||
makeMergedSchema,
|
||||
makeServices,
|
||||
} from '@redwoodjs/api'
|
||||
import importAll from '@redwoodjs/api/importAll.macro'
|
||||
|
||||
import { db } from 'src/lib/db'
|
||||
|
||||
const schemas = importAll('api', 'graphql')
|
||||
const services = importAll('api', 'services')
|
||||
|
||||
export const handler = createGraphQLHandler({
|
||||
schema: makeMergedSchema({
|
||||
schemas,
|
||||
services: makeServices({ services }),
|
||||
}),
|
||||
db,
|
||||
})
|
||||
0
examples/redwoodjs/api/src/graphql/.keep
Normal file
0
examples/redwoodjs/api/src/graphql/.keep
Normal file
6
examples/redwoodjs/api/src/lib/db.js
Normal file
6
examples/redwoodjs/api/src/lib/db.js
Normal file
@@ -0,0 +1,6 @@
|
||||
// See https://github.com/prisma/prisma2/blob/master/docs/prisma-client-js/api.md#constructor
|
||||
// for options.
|
||||
|
||||
import { PrismaClient } from '@prisma/client'
|
||||
|
||||
export const db = new PrismaClient()
|
||||
0
examples/redwoodjs/api/src/services/.keep
Normal file
0
examples/redwoodjs/api/src/services/.keep
Normal file
3
examples/redwoodjs/babel.config.js
Normal file
3
examples/redwoodjs/babel.config.js
Normal file
@@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
presets: ['@redwoodjs/core/config/babel-preset'],
|
||||
}
|
||||
19
examples/redwoodjs/package.json
Normal file
19
examples/redwoodjs/package.json
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"private": true,
|
||||
"workspaces": {
|
||||
"packages": [
|
||||
"api",
|
||||
"web"
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@redwoodjs/core": "0.15.0"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": "@redwoodjs/eslint-config"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12",
|
||||
"yarn": ">=1.15"
|
||||
}
|
||||
}
|
||||
9
examples/redwoodjs/prettier.config.js
Normal file
9
examples/redwoodjs/prettier.config.js
Normal file
@@ -0,0 +1,9 @@
|
||||
// https://prettier.io/docs/en/options.html
|
||||
module.exports = {
|
||||
trailingComma: 'es5',
|
||||
bracketSpacing: true,
|
||||
tabWidth: 2,
|
||||
semi: false,
|
||||
singleQuote: true,
|
||||
arrowParens: 'always',
|
||||
}
|
||||
7
examples/redwoodjs/redwood.toml
Normal file
7
examples/redwoodjs/redwood.toml
Normal file
@@ -0,0 +1,7 @@
|
||||
[web]
|
||||
port = 8910
|
||||
apiProxyPath = "/api"
|
||||
[api]
|
||||
port = 8911
|
||||
[browser]
|
||||
open = false
|
||||
1
examples/redwoodjs/web/.babelrc.js
Normal file
1
examples/redwoodjs/web/.babelrc.js
Normal file
@@ -0,0 +1 @@
|
||||
module.exports = { extends: '../babel.config.js' }
|
||||
10
examples/redwoodjs/web/jsconfig.json
Normal file
10
examples/redwoodjs/web/jsconfig.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"src/*": ["./src/*"]
|
||||
},
|
||||
"jsx": "preserve"
|
||||
},
|
||||
"include": ["src/**/*"]
|
||||
}
|
||||
15
examples/redwoodjs/web/package.json
Normal file
15
examples/redwoodjs/web/package.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "web",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"browserslist": [
|
||||
"defaults"
|
||||
],
|
||||
"dependencies": {
|
||||
"@redwoodjs/router": "0.15.0",
|
||||
"@redwoodjs/web": "0.15.0",
|
||||
"prop-types": "^15.7.2",
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1"
|
||||
}
|
||||
}
|
||||
36
examples/redwoodjs/web/public/README.md
Normal file
36
examples/redwoodjs/web/public/README.md
Normal file
@@ -0,0 +1,36 @@
|
||||
# Static Assets
|
||||
Use this folder to add static files directly to your app. All included files and folders will be copied directly into the `/dist` folder (created when Webpack builds for production). They will also be available during development when you run `yarn rw dev`.
|
||||
>Note: files will *not* hot reload while the development server is running. You'll need to manually stop/start to access file changes.
|
||||
|
||||
### Example Use
|
||||
A file like `favicon.png` will be copied to `/dist/favicon.png`. A folder containing a file such as `static-files/my-logo.jpg` will be copied to `/dist/static-files/my-logo.jpg`. These can be referenced in your code directly without any special handling, e.g.
|
||||
```
|
||||
<link rel="icon" type="image/png" href="/favicon.png" />
|
||||
```
|
||||
and
|
||||
```
|
||||
<img src="/static-files/my-logo.jpg"> alt="Logo" />
|
||||
```
|
||||
|
||||
Behind the scenes, we are using Webpack's ["copy-webpack-plugin"](https://github.com/webpack-contrib/copy-webpack-plugin).
|
||||
|
||||
## Best Practices
|
||||
Because assets in this folder are bypassing the javascript module system, **this folder should be used sparingly** for assets such as favicons, robots.txt, manifests, libraries incompatible with Webpack, etc.
|
||||
|
||||
In general, it's best to import files directly into a template, page, or component. This allows Webpack to include that file in the bundle, which ensures Webpack will correctly process and move assets into the distribution folder, providing error checks and correct paths along the way.
|
||||
|
||||
### Example Asset Import with Webpack
|
||||
Instead of handling our logo image as a static file per the example above, we can do the following:
|
||||
```
|
||||
import React from "react"
|
||||
import logo from "./my-logo.jpg"
|
||||
|
||||
|
||||
function Header() {
|
||||
return <img src={logo} alt="Logo" />
|
||||
}
|
||||
|
||||
export default Header
|
||||
```
|
||||
|
||||
Behind the scenes, we are using Webpack's ["file-loader"](https://webpack.js.org/loaders/file-loader/) and ["url-loader](https://webpack.js.org/loaders/url-loader/) (for files smaller than 10kb).
|
||||
BIN
examples/redwoodjs/web/public/favicon.png
Normal file
BIN
examples/redwoodjs/web/public/favicon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.8 KiB |
2
examples/redwoodjs/web/public/robots.txt
Normal file
2
examples/redwoodjs/web/public/robots.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
User-agent: *
|
||||
Disallow:
|
||||
22
examples/redwoodjs/web/src/Routes.js
Normal file
22
examples/redwoodjs/web/src/Routes.js
Normal file
@@ -0,0 +1,22 @@
|
||||
// In this file, all Page components from 'src/pages` are auto-imported. Nested
|
||||
// directories are supported, and should be uppercase. Each subdirectory will be
|
||||
// prepended onto the component name.
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// 'src/pages/HomePage/HomePage.js' -> HomePage
|
||||
// 'src/pages/Admin/BooksPage/BooksPage.js' -> AdminBooksPage
|
||||
|
||||
import { Router, Route } from '@redwoodjs/router'
|
||||
|
||||
const Routes = () => {
|
||||
return (
|
||||
<Router>
|
||||
<Route path="/" page={HomePage} name="home" />
|
||||
<Route path="/about" page={AboutPage} name="about" />
|
||||
<Route notfound page={NotFoundPage} />
|
||||
</Router>
|
||||
)
|
||||
}
|
||||
|
||||
export default Routes
|
||||
0
examples/redwoodjs/web/src/components/.keep
Normal file
0
examples/redwoodjs/web/src/components/.keep
Normal file
0
examples/redwoodjs/web/src/index.css
Normal file
0
examples/redwoodjs/web/src/index.css
Normal file
12
examples/redwoodjs/web/src/index.html
Normal file
12
examples/redwoodjs/web/src/index.html
Normal file
@@ -0,0 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="icon" type="image/png" href="/favicon.png" />
|
||||
<title><%= htmlWebpackPlugin.options.title %></title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="redwood-app"></div>
|
||||
</body>
|
||||
</html>
|
||||
16
examples/redwoodjs/web/src/index.js
Normal file
16
examples/redwoodjs/web/src/index.js
Normal file
@@ -0,0 +1,16 @@
|
||||
import ReactDOM from 'react-dom'
|
||||
import { RedwoodProvider, FatalErrorBoundary } from '@redwoodjs/web'
|
||||
import FatalErrorPage from 'src/pages/FatalErrorPage'
|
||||
|
||||
import Routes from 'src/Routes'
|
||||
|
||||
import './index.css'
|
||||
|
||||
ReactDOM.render(
|
||||
<FatalErrorBoundary page={FatalErrorPage}>
|
||||
<RedwoodProvider>
|
||||
<Routes />
|
||||
</RedwoodProvider>
|
||||
</FatalErrorBoundary>,
|
||||
document.getElementById('redwood-app')
|
||||
)
|
||||
0
examples/redwoodjs/web/src/layouts/.keep
Normal file
0
examples/redwoodjs/web/src/layouts/.keep
Normal file
44
examples/redwoodjs/web/src/pages/AboutPage/AboutPage.js
Normal file
44
examples/redwoodjs/web/src/pages/AboutPage/AboutPage.js
Normal file
@@ -0,0 +1,44 @@
|
||||
export default () => (
|
||||
<main>
|
||||
<style
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: `
|
||||
html, body {
|
||||
margin: 0;
|
||||
}
|
||||
html * {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
main {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif;
|
||||
text-align: center;
|
||||
background-color: #E2E8F0;
|
||||
height: 100vh;
|
||||
}
|
||||
section {
|
||||
background-color: white;
|
||||
border-radius: 0.25rem;
|
||||
width: 32rem;
|
||||
padding: 1rem;
|
||||
margin: 0 auto;
|
||||
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
h1 {
|
||||
font-size: 2rem;
|
||||
margin: 0;
|
||||
font-weight: 500;
|
||||
line-height: 1;
|
||||
color: #2D3748;
|
||||
}
|
||||
`,
|
||||
}}
|
||||
/>
|
||||
<section>
|
||||
<h1>
|
||||
<span>About RedwoodJS</span>
|
||||
</h1>
|
||||
</section>
|
||||
</main>
|
||||
)
|
||||
@@ -0,0 +1,53 @@
|
||||
// This page will be rendered when an error makes it all the way to the top of the
|
||||
// application without being handled by a Javascript catch statement or React error
|
||||
// boundary.
|
||||
//
|
||||
// You can modify this page as you wish, but it is important to keep things simple to
|
||||
// avoid the possibility that it will cause its own error. If it does, Redwood will
|
||||
// still render a generic error page, but your users will prefer something a bit more
|
||||
// thoughtful. =)
|
||||
|
||||
export default () => (
|
||||
<main>
|
||||
<style
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: `
|
||||
html, body {
|
||||
margin: 0;
|
||||
}
|
||||
html * {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
main {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif;
|
||||
text-align: center;
|
||||
background-color: #E2E8F0;
|
||||
height: 100vh;
|
||||
}
|
||||
section {
|
||||
background-color: white;
|
||||
border-radius: 0.25rem;
|
||||
width: 32rem;
|
||||
padding: 1rem;
|
||||
margin: 0 auto;
|
||||
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
h1 {
|
||||
font-size: 2rem;
|
||||
margin: 0;
|
||||
font-weight: 500;
|
||||
line-height: 1;
|
||||
color: #2D3748;
|
||||
}
|
||||
`,
|
||||
}}
|
||||
/>
|
||||
<section>
|
||||
<h1>
|
||||
<span>Something went wrong</span>
|
||||
</h1>
|
||||
</section>
|
||||
</main>
|
||||
)
|
||||
44
examples/redwoodjs/web/src/pages/HomePage/HomePage.js
Normal file
44
examples/redwoodjs/web/src/pages/HomePage/HomePage.js
Normal file
@@ -0,0 +1,44 @@
|
||||
export default () => (
|
||||
<main>
|
||||
<style
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: `
|
||||
html, body {
|
||||
margin: 0;
|
||||
}
|
||||
html * {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
main {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif;
|
||||
text-align: center;
|
||||
background-color: #E2E8F0;
|
||||
height: 100vh;
|
||||
}
|
||||
section {
|
||||
background-color: white;
|
||||
border-radius: 0.25rem;
|
||||
width: 32rem;
|
||||
padding: 1rem;
|
||||
margin: 0 auto;
|
||||
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
h1 {
|
||||
font-size: 2rem;
|
||||
margin: 0;
|
||||
font-weight: 500;
|
||||
line-height: 1;
|
||||
color: #2D3748;
|
||||
}
|
||||
`,
|
||||
}}
|
||||
/>
|
||||
<section>
|
||||
<h1>
|
||||
<span>Welcome to RedwoodJS!</span>
|
||||
</h1>
|
||||
</section>
|
||||
</main>
|
||||
)
|
||||
@@ -0,0 +1,44 @@
|
||||
export default () => (
|
||||
<main>
|
||||
<style
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: `
|
||||
html, body {
|
||||
margin: 0;
|
||||
}
|
||||
html * {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
main {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif;
|
||||
text-align: center;
|
||||
background-color: #E2E8F0;
|
||||
height: 100vh;
|
||||
}
|
||||
section {
|
||||
background-color: white;
|
||||
border-radius: 0.25rem;
|
||||
width: 32rem;
|
||||
padding: 1rem;
|
||||
margin: 0 auto;
|
||||
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
h1 {
|
||||
font-size: 2rem;
|
||||
margin: 0;
|
||||
font-weight: 500;
|
||||
line-height: 1;
|
||||
color: #2D3748;
|
||||
}
|
||||
`,
|
||||
}}
|
||||
/>
|
||||
<section>
|
||||
<h1>
|
||||
<span>404 Page Not Found</span>
|
||||
</h1>
|
||||
</section>
|
||||
</main>
|
||||
)
|
||||
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';
|
||||
|
||||
|
||||
@@ -682,6 +682,34 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "RedwoodJS",
|
||||
"slug": "redwoodjs",
|
||||
"demo": "https://redwoodjs.now-examples.now.sh",
|
||||
"logo": "https://raw.githubusercontent.com/vercel/vercel/master/packages/frameworks/logos/redwood.svg",
|
||||
"tagline": "RedwoodJS is a full-stack framework for the Jamstack.",
|
||||
"description": "A RedwoodJS app, bootstraped with create-redwood-app.",
|
||||
"website": "https://redwoodjs.com",
|
||||
"detectors": {
|
||||
"every": [
|
||||
{
|
||||
"path": "package.json",
|
||||
"matchContent": "\"(dev)?(d|D)ependencies\":\\s*{[^}]*\"@redwoodjs\\/core\":\\s*\".+?\"[^}]*}"
|
||||
}
|
||||
]
|
||||
},
|
||||
"settings": {
|
||||
"buildCommand": {
|
||||
"value": "yarn rw db up --no-db-client --auto-approve && yarn rw build"
|
||||
},
|
||||
"devCommand": {
|
||||
"value": "yarn rw dev --fwd=\"--port=$PORT --open=false\""
|
||||
},
|
||||
"outputDirectory": {
|
||||
"value": "RedwoodJS default"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Hugo",
|
||||
"slug": "hugo",
|
||||
@@ -804,7 +832,7 @@
|
||||
"description": "No framework or a unoptimized framework.",
|
||||
"settings": {
|
||||
"buildCommand": {
|
||||
"placeholder": "`npm run now-build` or `npm run build`"
|
||||
"placeholder": "`npm run vercel-build` or `npm run build`"
|
||||
},
|
||||
"devCommand": {
|
||||
"placeholder": "None"
|
||||
|
||||
1
packages/frameworks/logos/redwood.svg
Normal file
1
packages/frameworks/logos/redwood.svg
Normal file
@@ -0,0 +1 @@
|
||||
<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>
|
||||
|
After Width: | Height: | Size: 3.0 KiB |
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/frameworks",
|
||||
"version": "0.0.17",
|
||||
"version": "0.0.18-canary.2",
|
||||
"main": "frameworks.json",
|
||||
"license": "UNLICENSED",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/build-utils",
|
||||
"version": "2.4.2",
|
||||
"version": "2.4.3-canary.2",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.js",
|
||||
|
||||
@@ -309,6 +309,13 @@ export async function detectBuilders(
|
||||
options
|
||||
);
|
||||
|
||||
if (frontendBuilder && framework === 'redwoodjs') {
|
||||
// RedwoodJS uses the /api directory differently so we must
|
||||
// clear any existing builders and only use `@vercel/redwood`.
|
||||
builders.length = 0;
|
||||
builders.push(frontendBuilder);
|
||||
}
|
||||
|
||||
return {
|
||||
warnings,
|
||||
builders: builders.length ? builders : null,
|
||||
@@ -468,6 +475,10 @@ function detectFrontBuilder(
|
||||
return { src: 'package.json', use: `@vercel/next${withTag}`, config };
|
||||
}
|
||||
|
||||
if (framework === 'redwoodjs') {
|
||||
return { src: 'package.json', use: `@vercel/redwood${withTag}`, config };
|
||||
}
|
||||
|
||||
// Entrypoints for other frameworks
|
||||
// TODO - What if just a build script is provided, but no entrypoint.
|
||||
const entrypoints = new Set([
|
||||
|
||||
@@ -15,7 +15,9 @@ async function readFileOrNull(file: string) {
|
||||
return null;
|
||||
}
|
||||
|
||||
export async function readConfigFile<T>(files: string | string[]) {
|
||||
export async function readConfigFile<T>(
|
||||
files: string | string[]
|
||||
): Promise<T | null> {
|
||||
files = Array.isArray(files) ? files : [files];
|
||||
|
||||
for (const name of files) {
|
||||
@@ -24,11 +26,11 @@ export async function readConfigFile<T>(files: string | string[]) {
|
||||
if (data) {
|
||||
const str = data.toString('utf8');
|
||||
if (name.endsWith('.json')) {
|
||||
return JSON.parse(str);
|
||||
return JSON.parse(str) as T;
|
||||
} else if (name.endsWith('.toml')) {
|
||||
return (toml.parse(str) as unknown) as T;
|
||||
} else if (name.endsWith('.yaml') || name.endsWith('.yml')) {
|
||||
return yaml.safeLoad(str, { filename: name });
|
||||
return yaml.safeLoad(str, { filename: name }) as T;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1808,6 +1808,36 @@ describe('Test `detectBuilders` with `featHandleMiss=true`', () => {
|
||||
expect((errorRoutes![0] as Source).status).toBe(404);
|
||||
});
|
||||
|
||||
it('RedwoodJS should only use redwood builder', async () => {
|
||||
const files = [
|
||||
'package.json',
|
||||
'web/index.html',
|
||||
'api/one.js',
|
||||
'api/two.js',
|
||||
];
|
||||
const projectSettings = {
|
||||
framework: 'redwoodjs',
|
||||
};
|
||||
|
||||
const { builders, errorRoutes } = await detectBuilders(files, null, {
|
||||
projectSettings,
|
||||
featHandleMiss,
|
||||
});
|
||||
|
||||
expect(builders).toEqual([
|
||||
{
|
||||
use: '@vercel/redwood',
|
||||
src: 'package.json',
|
||||
config: {
|
||||
zeroConfig: true,
|
||||
framework: 'redwoodjs',
|
||||
},
|
||||
},
|
||||
]);
|
||||
expect(errorRoutes!.length).toBe(1);
|
||||
expect((errorRoutes![0] as Source).status).toBe(404);
|
||||
});
|
||||
|
||||
it('No framework, only package.json', async () => {
|
||||
const files = ['package.json'];
|
||||
const pkg = {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "vercel",
|
||||
"version": "20.0.0-canary.1",
|
||||
"version": "20.0.0-canary.10",
|
||||
"preferGlobal": true,
|
||||
"license": "Apache-2.0",
|
||||
"description": "The command-line interface for Vercel",
|
||||
@@ -62,13 +62,14 @@
|
||||
"node": ">= 10"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vercel/build-utils": "2.4.2",
|
||||
"@vercel/build-utils": "2.4.3-canary.2",
|
||||
"@vercel/go": "1.1.5-canary.0",
|
||||
"@vercel/next": "2.6.14-canary.1",
|
||||
"@vercel/node": "1.7.4-canary.0",
|
||||
"@vercel/next": "2.6.17",
|
||||
"@vercel/node": "1.7.5-canary.0",
|
||||
"@vercel/python": "1.2.2",
|
||||
"@vercel/redwood": "0.0.2-canary.3",
|
||||
"@vercel/ruby": "1.2.3",
|
||||
"@vercel/static-build": "0.17.7-canary.0",
|
||||
"@vercel/static-build": "0.17.7-canary.1",
|
||||
"update-notifier": "4.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -669,7 +669,7 @@ export default async function main(
|
||||
}
|
||||
|
||||
if (err instanceof BuildError) {
|
||||
output.error('Build failed');
|
||||
output.error(err.message || 'Build failed');
|
||||
output.error(
|
||||
`Check your logs at https://${now.url}/_logs or run ${getCommandName(
|
||||
`logs ${now.url}`,
|
||||
|
||||
@@ -118,7 +118,16 @@ export async function devRouter(
|
||||
continue;
|
||||
}
|
||||
|
||||
if (routeConfig.check && devServer && nowConfig && phase !== 'hit') {
|
||||
// if the destination is an external URL (rewrite or redirect)
|
||||
const isDestUrl = isURL(destPath);
|
||||
|
||||
if (
|
||||
routeConfig.check &&
|
||||
devServer &&
|
||||
nowConfig &&
|
||||
phase !== 'hit' &&
|
||||
!isDestUrl
|
||||
) {
|
||||
const { pathname = '/' } = url.parse(destPath);
|
||||
const hasDestFile = await devServer.hasFilesystem(
|
||||
pathname,
|
||||
@@ -156,7 +165,6 @@ export async function devRouter(
|
||||
}
|
||||
}
|
||||
|
||||
const isDestUrl = isURL(destPath);
|
||||
if (isDestUrl) {
|
||||
result = {
|
||||
found: true,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { join, basename } from 'path';
|
||||
import chalk from 'chalk';
|
||||
import { remove } from 'fs-extra';
|
||||
import { NowContext, ProjectLinkResult } from '../../types';
|
||||
import { NowContext, ProjectLinkResult, ProjectSettings } from '../../types';
|
||||
import { NowConfig } from '../dev/types';
|
||||
import { Output } from '../output';
|
||||
import {
|
||||
@@ -142,69 +142,75 @@ export default async function setupAndLink(
|
||||
if (ctx.localConfig && !(ctx.localConfig instanceof Error)) {
|
||||
localConfig = ctx.localConfig;
|
||||
}
|
||||
|
||||
client.currentTeam = org.type === 'team' ? org.id : undefined;
|
||||
const now = new Now({
|
||||
apiUrl,
|
||||
token,
|
||||
debug,
|
||||
currentTeam: client.currentTeam,
|
||||
});
|
||||
let deployment = null;
|
||||
const isZeroConfig = !localConfig.builds || localConfig.builds.length === 0;
|
||||
|
||||
try {
|
||||
const createArgs: any = {
|
||||
name: newProjectName,
|
||||
env: {},
|
||||
build: { env: {} },
|
||||
forceNew: undefined,
|
||||
withCache: undefined,
|
||||
quiet,
|
||||
wantsPublic: localConfig.public,
|
||||
isFile,
|
||||
type: null,
|
||||
nowConfig: localConfig,
|
||||
regions: undefined,
|
||||
meta: {},
|
||||
deployStamp: stamp(),
|
||||
target: undefined,
|
||||
skipAutoDetectionConfirmation: false,
|
||||
};
|
||||
let settings: ProjectSettings = {};
|
||||
|
||||
deployment = await createDeploy(
|
||||
output,
|
||||
now,
|
||||
client.currentTeam || 'current user',
|
||||
[sourcePath],
|
||||
createArgs,
|
||||
org,
|
||||
!isFile,
|
||||
path
|
||||
);
|
||||
if (isZeroConfig) {
|
||||
const now = new Now({
|
||||
apiUrl,
|
||||
token,
|
||||
debug,
|
||||
currentTeam: client.currentTeam,
|
||||
});
|
||||
const createArgs: any = {
|
||||
name: newProjectName,
|
||||
env: {},
|
||||
build: { env: {} },
|
||||
forceNew: undefined,
|
||||
withCache: undefined,
|
||||
quiet,
|
||||
wantsPublic: localConfig.public,
|
||||
isFile,
|
||||
type: null,
|
||||
nowConfig: localConfig,
|
||||
regions: undefined,
|
||||
meta: {},
|
||||
deployStamp: stamp(),
|
||||
target: undefined,
|
||||
skipAutoDetectionConfirmation: false,
|
||||
};
|
||||
|
||||
if (
|
||||
!deployment ||
|
||||
!('code' in deployment) ||
|
||||
deployment.code !== 'missing_project_settings'
|
||||
) {
|
||||
output.error('Failed to detect project settings. Please try again.');
|
||||
if (output.isDebugEnabled()) {
|
||||
console.log(deployment);
|
||||
const deployment = await createDeploy(
|
||||
output,
|
||||
now,
|
||||
client.currentTeam || 'current user',
|
||||
[sourcePath],
|
||||
createArgs,
|
||||
org,
|
||||
!isFile,
|
||||
path
|
||||
);
|
||||
|
||||
if (
|
||||
!deployment ||
|
||||
!('code' in deployment) ||
|
||||
deployment.code !== 'missing_project_settings'
|
||||
) {
|
||||
output.error('Failed to detect project settings. Please try again.');
|
||||
if (output.isDebugEnabled()) {
|
||||
console.log(deployment);
|
||||
}
|
||||
return { status: 'error', exitCode: 1 };
|
||||
}
|
||||
return { status: 'error', exitCode: 1 };
|
||||
}
|
||||
|
||||
const { projectSettings, framework } = deployment;
|
||||
const { projectSettings, framework } = deployment;
|
||||
|
||||
settings = await editProjectSettings(
|
||||
output,
|
||||
projectSettings,
|
||||
framework,
|
||||
autoConfirm
|
||||
);
|
||||
}
|
||||
|
||||
if (rootDirectory) {
|
||||
projectSettings.rootDirectory = rootDirectory;
|
||||
settings.rootDirectory = rootDirectory;
|
||||
}
|
||||
|
||||
const settings = await editProjectSettings(
|
||||
output,
|
||||
projectSettings,
|
||||
framework,
|
||||
autoConfirm
|
||||
);
|
||||
const project = await createProject(client, newProjectName);
|
||||
await updateProject(client, project.id, settings);
|
||||
Object.assign(project, settings);
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"version": 2,
|
||||
"rewrites": [
|
||||
{ "source": "/rewrite", "destination": "https://vercel.com/robots.txt" }
|
||||
],
|
||||
"redirects": [
|
||||
{ "source": "/redirect", "destination": "https://vercel.com/robots.txt" },
|
||||
{
|
||||
"source": "/tempRedirect",
|
||||
"destination": "https://vercel.com/robots.txt",
|
||||
"permanent": false
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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();
|
||||
@@ -111,7 +113,7 @@ async function exec(directory, args = []) {
|
||||
}
|
||||
|
||||
async function runNpmInstall(fixturePath) {
|
||||
if (await fs.exists(join(fixturePath, 'package.json'))) {
|
||||
if (await fs.pathExists(join(fixturePath, 'package.json'))) {
|
||||
await execa('yarn', ['install'], {
|
||||
cwd: fixturePath,
|
||||
shell: true,
|
||||
@@ -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);
|
||||
@@ -817,6 +843,20 @@ test(
|
||||
})
|
||||
);
|
||||
|
||||
test(
|
||||
'[vercel dev] test rewrites and redirects serve correct external content',
|
||||
testFixtureStdio('test-external-rewrites-and-redirects', async testPath => {
|
||||
const vcRobots = `https://vercel.com/robots.txt`;
|
||||
await testPath(200, '/rewrite', /User-Agent: \*/m);
|
||||
await testPath(308, '/redirect', `Redirecting to ${vcRobots} (308)`, {
|
||||
Location: vcRobots,
|
||||
});
|
||||
await testPath(307, '/tempRedirect', `Redirecting to ${vcRobots} (307)`, {
|
||||
Location: vcRobots,
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
test(
|
||||
'[vercel dev] test rewrites and redirects is case sensitive',
|
||||
testFixtureStdio('test-routing-case-sensitive', async testPath => {
|
||||
@@ -1135,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/);
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ const getConfigFile = builds =>
|
||||
]
|
||||
}`
|
||||
: `{
|
||||
"version": 2
|
||||
"version": 1
|
||||
}`;
|
||||
|
||||
const getIndexHTMLFile = session => `
|
||||
@@ -500,14 +500,21 @@ CMD ["node", "index.js"]`,
|
||||
},
|
||||
}),
|
||||
},
|
||||
'project-link': {
|
||||
'package.json': JSON.stringify({}),
|
||||
'project-link-deploy': {
|
||||
'package.json': '{}',
|
||||
},
|
||||
'project-link-zeroconf': {
|
||||
'package.json': '{}',
|
||||
},
|
||||
'project-link-confirm': {
|
||||
'package.json': JSON.stringify({}),
|
||||
'package.json': '{}',
|
||||
},
|
||||
'project-link-dev': {
|
||||
'package.json': JSON.stringify({}),
|
||||
'package.json': '{}',
|
||||
},
|
||||
'project-link-legacy': {
|
||||
'index.html': 'Hello',
|
||||
'vercel.json': '{"builds":[{"src":"*.html","use":"@vercel/static"}]}',
|
||||
},
|
||||
'dev-proxy-headers-and-env': {
|
||||
'package.json': JSON.stringify({}),
|
||||
|
||||
71
packages/now-cli/test/integration.js
vendored
71
packages/now-cli/test/integration.js
vendored
@@ -2321,7 +2321,11 @@ test('render build errors', async t => {
|
||||
console.log(output.exitCode);
|
||||
|
||||
t.is(output.exitCode, 1, formatOutput(output));
|
||||
t.regex(output.stderr, /Build failed/gm, formatOutput(output));
|
||||
t.regex(
|
||||
output.stderr,
|
||||
/Command "yarn run build" exited with 1/gm,
|
||||
formatOutput(output)
|
||||
);
|
||||
});
|
||||
|
||||
test('invalid deployment, projects and alias names', async t => {
|
||||
@@ -2657,9 +2661,9 @@ test('ensure `github` and `scope` are not sent to the API', async t => {
|
||||
t.is(output.exitCode, 0, formatOutput(output));
|
||||
});
|
||||
|
||||
test('should show prompts to set up project', async t => {
|
||||
const directory = fixture('project-link');
|
||||
const projectName = `project-link-${
|
||||
test('should show prompts to set up project during first deploy', async t => {
|
||||
const directory = fixture('project-link-deploy');
|
||||
const projectName = `project-link-deploy-${
|
||||
Math.random().toString(36).split('.')[1]
|
||||
}`;
|
||||
|
||||
@@ -3284,8 +3288,8 @@ test('reject deploying with wrong team .vercel config', async t => {
|
||||
});
|
||||
|
||||
test('[vc link] should show prompts to set up project', async t => {
|
||||
const dir = fixture('project-link');
|
||||
const projectName = `project-link-${
|
||||
const dir = fixture('project-link-zeroconf');
|
||||
const projectName = `project-link-zeroconf-${
|
||||
Math.random().toString(36).split('.')[1]
|
||||
}`;
|
||||
|
||||
@@ -3494,6 +3498,61 @@ test('[vc dev] should show prompts to set up project', async t => {
|
||||
}
|
||||
});
|
||||
|
||||
test('[vc link] should show project prompts but not framework when `builds` defined', async t => {
|
||||
const dir = fixture('project-link-legacy');
|
||||
const projectName = `project-link-legacy-${
|
||||
Math.random().toString(36).split('.')[1]
|
||||
}`;
|
||||
|
||||
// remove previously linked project if it exists
|
||||
await remove(path.join(dir, '.vercel'));
|
||||
|
||||
const vc = execa(binaryPath, ['link', ...defaultArgs], { cwd: dir });
|
||||
|
||||
await waitForPrompt(vc, chunk => /Set up [^?]+\?/.test(chunk));
|
||||
vc.stdin.write('yes\n');
|
||||
|
||||
await waitForPrompt(vc, chunk =>
|
||||
chunk.includes('Which scope should contain your project?')
|
||||
);
|
||||
vc.stdin.write('\n');
|
||||
|
||||
await waitForPrompt(vc, chunk => chunk.includes('Link to existing project?'));
|
||||
vc.stdin.write('no\n');
|
||||
|
||||
await waitForPrompt(vc, chunk =>
|
||||
chunk.includes('What’s your project’s name?')
|
||||
);
|
||||
vc.stdin.write(`${projectName}\n`);
|
||||
|
||||
await waitForPrompt(vc, chunk =>
|
||||
chunk.includes('In which directory is your code located?')
|
||||
);
|
||||
vc.stdin.write('\n');
|
||||
|
||||
await waitForPrompt(vc, chunk => chunk.includes('Linked to'));
|
||||
|
||||
const output = await vc;
|
||||
|
||||
// Ensure the exit code is right
|
||||
t.is(output.exitCode, 0, formatOutput(output));
|
||||
|
||||
// Ensure .gitignore is created
|
||||
t.is((await readFile(path.join(dir, '.gitignore'))).toString(), '.vercel');
|
||||
|
||||
// Ensure .vercel/project.json and .vercel/README.txt are created
|
||||
t.is(
|
||||
await exists(path.join(dir, '.vercel', 'project.json')),
|
||||
true,
|
||||
'project.json should be created'
|
||||
);
|
||||
t.is(
|
||||
await exists(path.join(dir, '.vercel', 'README.txt')),
|
||||
true,
|
||||
'README.txt should be created'
|
||||
);
|
||||
});
|
||||
|
||||
test('[vc dev] should send the platform proxy request headers to frontend dev server ', async t => {
|
||||
const dir = fixture('dev-proxy-headers-and-env');
|
||||
const port = 58353;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/client",
|
||||
"version": "8.2.2-canary.0",
|
||||
"version": "8.2.2-canary.4",
|
||||
"main": "dist/index.js",
|
||||
"typings": "dist/index.d.ts",
|
||||
"homepage": "https://vercel.com",
|
||||
@@ -38,7 +38,7 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@vercel/build-utils": "2.4.2",
|
||||
"@vercel/build-utils": "2.4.3-canary.2",
|
||||
"@zeit/fetch": "5.2.0",
|
||||
"async-retry": "1.2.3",
|
||||
"async-sema": "3.0.0",
|
||||
|
||||
@@ -80,7 +80,11 @@ export default function buildCreateDeployment(version: number) {
|
||||
rootFiles = [path];
|
||||
}
|
||||
|
||||
let fileList = await buildFileTree(path, clientOptions.isDirectory, debug);
|
||||
let { fileList } = await buildFileTree(
|
||||
path,
|
||||
clientOptions.isDirectory,
|
||||
debug
|
||||
);
|
||||
|
||||
let configPath: string | undefined;
|
||||
if (!nowConfig) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import buildCreateDeployment from './create-deployment';
|
||||
|
||||
export { getVercelIgnore } from './utils/index';
|
||||
export { getVercelIgnore, buildFileTree } from './utils/index';
|
||||
export const createDeployment = buildCreateDeployment(2);
|
||||
export const createLegacyDeployment = buildCreateDeployment(1);
|
||||
export * from './errors';
|
||||
|
||||
@@ -35,7 +35,7 @@ const EVENTS_ARRAY = [
|
||||
'canceled',
|
||||
] as const;
|
||||
|
||||
export type DeploymentEventType = (typeof EVENTS_ARRAY)[number];
|
||||
export type DeploymentEventType = typeof EVENTS_ARRAY[number];
|
||||
export const EVENTS = new Set(EVENTS_ARRAY);
|
||||
|
||||
export function getApiDeploymentsUrl(
|
||||
@@ -69,7 +69,7 @@ export async function parseVercelConfig(filePath?: string): Promise<NowConfig> {
|
||||
}
|
||||
}
|
||||
|
||||
const maybeRead = async function<T>(path: string, default_: T) {
|
||||
const maybeRead = async function <T>(path: string, default_: T) {
|
||||
try {
|
||||
return await readFile(path, 'utf8');
|
||||
} catch (err) {
|
||||
@@ -81,19 +81,26 @@ export async function buildFileTree(
|
||||
path: string | string[],
|
||||
isDirectory: boolean,
|
||||
debug: Debug
|
||||
): Promise<string[]> {
|
||||
): Promise<{ fileList: string[]; ignoreList: string[] }> {
|
||||
const ignoreList: string[] = [];
|
||||
let fileList: string[];
|
||||
let { ig } = await getVercelIgnore(path);
|
||||
let { ig, ignores } = await getVercelIgnore(path);
|
||||
|
||||
debug(`Found ${ig.ignores.length} rules in .vercelignore`);
|
||||
debug(`Found ${ignores.length} rules in .vercelignore`);
|
||||
debug('Building file tree...');
|
||||
|
||||
if (isDirectory && !Array.isArray(path)) {
|
||||
// Directory path
|
||||
const cwd = process.cwd();
|
||||
const ignores = (absPath: string) => ig.ignores(relative(cwd, absPath));
|
||||
const ignores = (absPath: string) => {
|
||||
const rel = relative(path, absPath);
|
||||
const ignored = ig.ignores(rel);
|
||||
if (ignored) {
|
||||
ignoreList.push(rel);
|
||||
}
|
||||
return ignored;
|
||||
};
|
||||
fileList = await readdir(path, [ignores]);
|
||||
debug(`Read ${fileList.length} files in the specified directory`);
|
||||
debug(`Found ${fileList.length} files in the specified directory`);
|
||||
} else if (Array.isArray(path)) {
|
||||
// Array of file paths
|
||||
fileList = path;
|
||||
@@ -104,7 +111,7 @@ export async function buildFileTree(
|
||||
debug(`Deploying the provided path as single file`);
|
||||
}
|
||||
|
||||
return fileList;
|
||||
return { fileList, ignoreList };
|
||||
}
|
||||
|
||||
export async function getVercelIgnore(
|
||||
|
||||
@@ -14,18 +14,30 @@ const normalizeWindowsPaths = (files: string[]) => {
|
||||
const toAbsolutePaths = (cwd: string, files: string[]) =>
|
||||
files.map(p => join(cwd, p));
|
||||
|
||||
describe('buildFileTree', () => {
|
||||
describe('buildFileTree()', () => {
|
||||
it('should exclude files using `.nowignore` blocklist', async () => {
|
||||
const cwd = fixture('nowignore');
|
||||
const expected = toAbsolutePaths(cwd, ['.nowignore', 'index.txt']);
|
||||
const actual = await buildFileTree(cwd, true, noop);
|
||||
expect(normalizeWindowsPaths(expected).sort()).toEqual(
|
||||
normalizeWindowsPaths(actual).sort()
|
||||
const { fileList, ignoreList } = await buildFileTree(cwd, true, noop);
|
||||
|
||||
const expectedFileList = toAbsolutePaths(cwd, ['.nowignore', 'index.txt']);
|
||||
expect(normalizeWindowsPaths(expectedFileList).sort()).toEqual(
|
||||
normalizeWindowsPaths(fileList).sort()
|
||||
);
|
||||
|
||||
const expectedIgnoreList = [
|
||||
'ignore.txt',
|
||||
'folder/ignore.txt',
|
||||
'node_modules/ignore.txt',
|
||||
];
|
||||
expect(normalizeWindowsPaths(expectedIgnoreList).sort()).toEqual(
|
||||
normalizeWindowsPaths(ignoreList).sort()
|
||||
);
|
||||
});
|
||||
|
||||
it('should include the node_modules using `.vercelignore` allowlist', async () => {
|
||||
const cwd = fixture('vercelignore-allow-nodemodules');
|
||||
const { fileList, ignoreList } = await buildFileTree(cwd, true, noop);
|
||||
|
||||
const expected = toAbsolutePaths(cwd, [
|
||||
'node_modules/one.txt',
|
||||
'sub/node_modules/two.txt',
|
||||
@@ -33,9 +45,13 @@ describe('buildFileTree', () => {
|
||||
'.vercelignore',
|
||||
'hello.txt',
|
||||
]);
|
||||
const actual = await buildFileTree(cwd, true, noop);
|
||||
expect(normalizeWindowsPaths(expected).sort()).toEqual(
|
||||
normalizeWindowsPaths(actual).sort()
|
||||
normalizeWindowsPaths(fileList).sort()
|
||||
);
|
||||
|
||||
const expectedIgnoreList = ['.env.local', 'exclude.txt'];
|
||||
expect(normalizeWindowsPaths(expectedIgnoreList).sort()).toEqual(
|
||||
normalizeWindowsPaths(ignoreList).sort()
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/next",
|
||||
"version": "2.6.14-canary.1",
|
||||
"version": "2.6.17",
|
||||
"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.0",
|
||||
"@zeit/node-file-trace": "0.8.1",
|
||||
"async-sema": "3.0.1",
|
||||
"buffer-crc32": "0.2.13",
|
||||
"escape-string-regexp": "3.0.0",
|
||||
|
||||
@@ -235,7 +235,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 +331,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 +349,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) {
|
||||
@@ -880,7 +888,13 @@ export const build = async ({
|
||||
!prerenderManifest.fallbackRoutes[route] &&
|
||||
!prerenderManifest.legacyBlockingRoutes[route]
|
||||
) {
|
||||
nonLambdaSsgPages.add(route);
|
||||
// if the 404 page used getStaticProps we need to update static404Page
|
||||
// since it wasn't populated from the staticPages group
|
||||
if (route === '/404') {
|
||||
static404Page = path.join(entryDirectory, '404');
|
||||
}
|
||||
|
||||
nonLambdaSsgPages.add(route === '/' ? '/index' : route);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
"builds": [{ "src": "package.json", "use": "@vercel/next" }],
|
||||
"probes": [
|
||||
{
|
||||
"path": "/_next/static/testing-build-id/pages/index.js",
|
||||
"path": "/_next/__NEXT_SCRIPT__(/)",
|
||||
"responseHeaders": {
|
||||
"cache-control": "public,max-age=31536000,immutable"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/_next/static/invalid-build-id/pages/index.js",
|
||||
"path": "/_next/static/invalid-build-id/pages/non-existent.js",
|
||||
"notResponseHeaders": {
|
||||
"cache-control": "public,max-age=31536000,immutable"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"next": "latest",
|
||||
"next": "canary",
|
||||
"react": "^16.8.6",
|
||||
"react-dom": "^16.8.6"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"next": "^9.1.2-canary.8",
|
||||
"next": "canary",
|
||||
"react": "^16.8.6",
|
||||
"react-dom": "^16.8.6"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"next": "9.2.1-canary.3",
|
||||
"next": "canary",
|
||||
"react": "^16.8.6",
|
||||
"react-dom": "^16.8.6"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"next": "latest",
|
||||
"next": "canary",
|
||||
"react": "^16.8.6",
|
||||
"react-dom": "^16.8.6"
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"build": "next build"
|
||||
},
|
||||
"dependencies": {
|
||||
"next": "^9.1.2-canary.8",
|
||||
"next": "canary",
|
||||
"react": "^16.8.6",
|
||||
"react-dom": "^16.8.6"
|
||||
}
|
||||
|
||||
5
packages/now-next/test/fixtures/25-index-routes/next.config.js
vendored
Normal file
5
packages/now-next/test/fixtures/25-index-routes/next.config.js
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
module.exports = {
|
||||
generateBuildId() {
|
||||
return 'testing-build-id';
|
||||
},
|
||||
};
|
||||
42
packages/now-next/test/fixtures/25-index-routes/now.json
vendored
Normal file
42
packages/now-next/test/fixtures/25-index-routes/now.json
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"version": 2,
|
||||
"builds": [{ "src": "package.json", "use": "@now/next" }],
|
||||
"probes": [
|
||||
{
|
||||
"path": "/",
|
||||
"mustContain": "hello from index"
|
||||
},
|
||||
{
|
||||
"path": "/index",
|
||||
"mustContain": "hello from index"
|
||||
},
|
||||
{
|
||||
"path": "/nested-index/index",
|
||||
"mustContain": "hello from nested index"
|
||||
},
|
||||
{
|
||||
"path": "/sub",
|
||||
"mustContain": "hello from sub index"
|
||||
},
|
||||
{
|
||||
"path": "/sub/index",
|
||||
"mustContain": "hello from sub id"
|
||||
},
|
||||
{
|
||||
"path": "/sub/another",
|
||||
"mustContain": "hello from sub id"
|
||||
},
|
||||
{
|
||||
"path": "/api/sub",
|
||||
"mustContain": "hi from sub index"
|
||||
},
|
||||
{
|
||||
"path": "/api/sub/index",
|
||||
"mustContain": "hi from sub id"
|
||||
},
|
||||
{
|
||||
"path": "/api/sub/another",
|
||||
"mustContain": "hi from sub id"
|
||||
}
|
||||
]
|
||||
}
|
||||
7
packages/now-next/test/fixtures/25-index-routes/package.json
vendored
Normal file
7
packages/now-next/test/fixtures/25-index-routes/package.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"next": "latest",
|
||||
"react": "^16.8.6",
|
||||
"react-dom": "^16.8.6"
|
||||
}
|
||||
}
|
||||
1
packages/now-next/test/fixtures/25-index-routes/pages/api/sub/[id].js
vendored
Normal file
1
packages/now-next/test/fixtures/25-index-routes/pages/api/sub/[id].js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export default (req, res) => res.end('hi from sub id')
|
||||
1
packages/now-next/test/fixtures/25-index-routes/pages/api/sub/index.js
vendored
Normal file
1
packages/now-next/test/fixtures/25-index-routes/pages/api/sub/index.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export default (req, res) => res.end('hi from sub index');
|
||||
2
packages/now-next/test/fixtures/25-index-routes/pages/index.js
vendored
Normal file
2
packages/now-next/test/fixtures/25-index-routes/pages/index.js
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
const page = () => 'hello from index';
|
||||
export default page;
|
||||
1
packages/now-next/test/fixtures/25-index-routes/pages/nested-index/index/index.js
vendored
Normal file
1
packages/now-next/test/fixtures/25-index-routes/pages/nested-index/index/index.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export default () => 'hello from nested index';
|
||||
3
packages/now-next/test/fixtures/25-index-routes/pages/sub/[id].js
vendored
Normal file
3
packages/now-next/test/fixtures/25-index-routes/pages/sub/[id].js
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
const page = () => "hello from sub id"
|
||||
page.getInitialProps = () => ({ hello: 'hi' })
|
||||
export default page
|
||||
3
packages/now-next/test/fixtures/25-index-routes/pages/sub/index.js
vendored
Normal file
3
packages/now-next/test/fixtures/25-index-routes/pages/sub/index.js
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
const page = () => 'hello from sub index';
|
||||
page.getInitialProps = () => ({ hello: 'hi' });
|
||||
export default page;
|
||||
5
packages/now-next/test/fixtures/29-ssg-all-static-custom-404/next.config.js
vendored
Normal file
5
packages/now-next/test/fixtures/29-ssg-all-static-custom-404/next.config.js
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
module.exports = {
|
||||
generateBuildId() {
|
||||
return 'testing-build-id';
|
||||
},
|
||||
};
|
||||
113
packages/now-next/test/fixtures/29-ssg-all-static-custom-404/now.json
vendored
Normal file
113
packages/now-next/test/fixtures/29-ssg-all-static-custom-404/now.json
vendored
Normal file
@@ -0,0 +1,113 @@
|
||||
{
|
||||
"version": 2,
|
||||
"uploadNowJson": true,
|
||||
"builds": [{ "src": "package.json", "use": "@vercel/next" }],
|
||||
"probes": [
|
||||
{
|
||||
"path": "/forever",
|
||||
"status": 200,
|
||||
"mustContain": "hello"
|
||||
},
|
||||
{
|
||||
"path": "/blog/post-1",
|
||||
"status": 200,
|
||||
"mustContain": "post-1"
|
||||
},
|
||||
{
|
||||
"path": "/blog/post-2",
|
||||
"status": 200,
|
||||
"mustContain": "post-2"
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/blog/post-1.json",
|
||||
"status": 200,
|
||||
"mustContain": "post-1"
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/blog/post-2.json",
|
||||
"status": 200,
|
||||
"mustContain": "post-2"
|
||||
},
|
||||
|
||||
{
|
||||
"path": "/blog/post-1/comment-1",
|
||||
"status": 200,
|
||||
"mustContain": "comment-1"
|
||||
},
|
||||
{
|
||||
"path": "/blog/post-2/comment-2",
|
||||
"status": 200,
|
||||
"mustContain": "comment-2"
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/blog/post-1/comment-1.json",
|
||||
"status": 200,
|
||||
"mustContain": "comment-1"
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/blog/post-2/comment-2.json",
|
||||
"status": 200,
|
||||
"mustContain": "comment-2"
|
||||
},
|
||||
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/forever.json",
|
||||
"status": 200,
|
||||
"mustContain": "world"
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/another2.json",
|
||||
"status": 200,
|
||||
"mustContain": "world"
|
||||
},
|
||||
{
|
||||
"path": "/nofallback/one",
|
||||
"status": 200,
|
||||
"mustContain": "one"
|
||||
},
|
||||
{
|
||||
"path": "/nofallback/two",
|
||||
"status": 200,
|
||||
"mustContain": "two"
|
||||
},
|
||||
{
|
||||
"path": "/nofallback/nope",
|
||||
"status": 404,
|
||||
"mustContain": "page not <!-- -->found"
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/nofallback/one.json",
|
||||
"status": 200,
|
||||
"mustContain": "one"
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/nofallback/two.json",
|
||||
"status": 200,
|
||||
"mustContain": "two"
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/nofallback/nope.json",
|
||||
"status": 404
|
||||
},
|
||||
{
|
||||
"path": "/404",
|
||||
"status": 404,
|
||||
"mustContain": "page not <!-- -->found"
|
||||
},
|
||||
{
|
||||
"logMustNotContain": "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"
|
||||
}
|
||||
]
|
||||
}
|
||||
7
packages/now-next/test/fixtures/29-ssg-all-static-custom-404/package.json
vendored
Normal file
7
packages/now-next/test/fixtures/29-ssg-all-static-custom-404/package.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"next": "canary",
|
||||
"react": "^16.8.6",
|
||||
"react-dom": "^16.8.6"
|
||||
}
|
||||
}
|
||||
11
packages/now-next/test/fixtures/29-ssg-all-static-custom-404/pages/404.js
vendored
Normal file
11
packages/now-next/test/fixtures/29-ssg-all-static-custom-404/pages/404.js
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
export default function Page({ found }) {
|
||||
return <p>page not {found}</p>;
|
||||
}
|
||||
|
||||
export const getStaticProps = () => {
|
||||
return {
|
||||
props: {
|
||||
found: 'found',
|
||||
},
|
||||
};
|
||||
};
|
||||
22
packages/now-next/test/fixtures/29-ssg-all-static-custom-404/pages/another.js
vendored
Normal file
22
packages/now-next/test/fixtures/29-ssg-all-static-custom-404/pages/another.js
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
import React from 'react';
|
||||
|
||||
// eslint-disable-next-line camelcase
|
||||
export async function getStaticProps() {
|
||||
return {
|
||||
props: {
|
||||
world: 'world',
|
||||
random: Math.random(),
|
||||
time: new Date().getTime(),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default ({ world, time, random }) => {
|
||||
return (
|
||||
<>
|
||||
<p id="hello">hello: {world}</p>
|
||||
<span id="time">time: {time}</span>
|
||||
<span id="random">random: {random}</span>
|
||||
</>
|
||||
);
|
||||
};
|
||||
20
packages/now-next/test/fixtures/29-ssg-all-static-custom-404/pages/another2.js
vendored
Normal file
20
packages/now-next/test/fixtures/29-ssg-all-static-custom-404/pages/another2.js
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
import React from 'react';
|
||||
|
||||
// eslint-disable-next-line camelcase
|
||||
export async function getStaticProps() {
|
||||
return {
|
||||
props: {
|
||||
world: 'world',
|
||||
time: new Date().getTime(),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default ({ world, time }) => {
|
||||
return (
|
||||
<>
|
||||
<p>hello: {world}</p>
|
||||
<span>time: {time}</span>
|
||||
</>
|
||||
);
|
||||
};
|
||||
39
packages/now-next/test/fixtures/29-ssg-all-static-custom-404/pages/blog/[post]/[comment].js
vendored
Normal file
39
packages/now-next/test/fixtures/29-ssg-all-static-custom-404/pages/blog/[post]/[comment].js
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
import React from 'react';
|
||||
|
||||
// eslint-disable-next-line camelcase
|
||||
export async function getStaticPaths() {
|
||||
return {
|
||||
paths: [
|
||||
'/blog/post-1/comment-1',
|
||||
{ params: { post: 'post-2', comment: 'comment-2' } },
|
||||
'/blog/post-1337/comment-1337',
|
||||
'/blog/post-123/comment-321',
|
||||
],
|
||||
fallback: false,
|
||||
};
|
||||
}
|
||||
|
||||
// eslint-disable-next-line camelcase
|
||||
export async function getStaticProps({ params }) {
|
||||
return {
|
||||
props: {
|
||||
post: params.post,
|
||||
random: Math.random(),
|
||||
comment: params.comment,
|
||||
time: new Date().getTime(),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default ({ post, comment, time, random }) => {
|
||||
if (!post) return <p>loading...</p>;
|
||||
|
||||
return (
|
||||
<>
|
||||
<p id="post">Post: {post}</p>
|
||||
<p id="comment">Comment: {comment}</p>
|
||||
<span id="time">time: {time}</span>
|
||||
<span id="random">random: {random}</span>
|
||||
</>
|
||||
);
|
||||
};
|
||||
38
packages/now-next/test/fixtures/29-ssg-all-static-custom-404/pages/blog/[post]/index.js
vendored
Normal file
38
packages/now-next/test/fixtures/29-ssg-all-static-custom-404/pages/blog/[post]/index.js
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
import React from 'react';
|
||||
|
||||
// eslint-disable-next-line camelcase
|
||||
export async function getStaticPaths() {
|
||||
return {
|
||||
paths: ['/blog/post-1', { params: { post: 'post-2' } }, '/blog/post-123'],
|
||||
fallback: false,
|
||||
};
|
||||
}
|
||||
|
||||
// eslint-disable-next-line camelcase
|
||||
export async function getStaticProps({ params }) {
|
||||
if (params.post === 'post-10') {
|
||||
await new Promise(resolve => {
|
||||
setTimeout(() => resolve(), 1000);
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
props: {
|
||||
post: params.post,
|
||||
random: Math.random(),
|
||||
time: (await import('perf_hooks')).performance.now(),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default ({ post, time, random }) => {
|
||||
if (!post) return <p>loading...</p>;
|
||||
|
||||
return (
|
||||
<>
|
||||
<p id="post">Post: {post}</p>
|
||||
<span id="time">time: {time}</span>
|
||||
<span id="random">random: {random}</span>
|
||||
</>
|
||||
);
|
||||
};
|
||||
21
packages/now-next/test/fixtures/29-ssg-all-static-custom-404/pages/forever.js
vendored
Normal file
21
packages/now-next/test/fixtures/29-ssg-all-static-custom-404/pages/forever.js
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
import React from 'react';
|
||||
|
||||
// eslint-disable-next-line camelcase
|
||||
export async function getStaticProps() {
|
||||
return {
|
||||
props: {
|
||||
world: 'world',
|
||||
time: new Date().getTime(),
|
||||
},
|
||||
revalidate: false,
|
||||
};
|
||||
}
|
||||
|
||||
export default ({ world, time }) => {
|
||||
return (
|
||||
<>
|
||||
<p>hello: {world}</p>
|
||||
<span>time: {time}</span>
|
||||
</>
|
||||
);
|
||||
};
|
||||
9
packages/now-next/test/fixtures/29-ssg-all-static-custom-404/pages/index.js
vendored
Normal file
9
packages/now-next/test/fixtures/29-ssg-all-static-custom-404/pages/index.js
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
export default () => 'Hi';
|
||||
|
||||
export const getStaticProps = () => {
|
||||
return {
|
||||
props: {
|
||||
hello: 'world',
|
||||
},
|
||||
};
|
||||
};
|
||||
30
packages/now-next/test/fixtures/29-ssg-all-static-custom-404/pages/nofallback/[slug].js
vendored
Normal file
30
packages/now-next/test/fixtures/29-ssg-all-static-custom-404/pages/nofallback/[slug].js
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
import React from 'react';
|
||||
|
||||
// eslint-disable-next-line camelcase
|
||||
export async function getStaticPaths() {
|
||||
return {
|
||||
paths: ['/nofallback/one', { params: { slug: 'two' } }],
|
||||
fallback: false,
|
||||
};
|
||||
}
|
||||
|
||||
// eslint-disable-next-line camelcase
|
||||
export async function getStaticProps({ params }) {
|
||||
return {
|
||||
props: {
|
||||
slug: params.slug,
|
||||
time: (await import('perf_hooks')).performance.now(),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default ({ slug, time }) => {
|
||||
return (
|
||||
<>
|
||||
<p>
|
||||
Slug ({slug.length}): {slug}
|
||||
</p>
|
||||
<span>time: {time}</span>
|
||||
</>
|
||||
);
|
||||
};
|
||||
9
packages/now-next/test/fixtures/29-ssg-all-static/pages/another-index/index.js
vendored
Normal file
9
packages/now-next/test/fixtures/29-ssg-all-static/pages/another-index/index.js
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
export default () => 'Hi';
|
||||
|
||||
export const getStaticProps = () => {
|
||||
return {
|
||||
props: {
|
||||
hello: 'world',
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -1 +1,9 @@
|
||||
export default () => 'Hi';
|
||||
|
||||
export const getStaticProps = () => {
|
||||
return {
|
||||
props: {
|
||||
hello: 'world',
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
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
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/node",
|
||||
"version": "1.7.4-canary.0",
|
||||
"version": "1.7.5-canary.0",
|
||||
"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.0",
|
||||
"@zeit/node-file-trace": "0.8.1",
|
||||
"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",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user