Compare commits

...

37 Commits

Author SHA1 Message Date
JJ Kasper
c1c8b454cc Publish Stable
- @vercel/build-utils@6.2.1
 - vercel@28.15.2
 - @vercel/client@12.3.7
 - @vercel/fs-detectors@3.7.10
 - @vercel/gatsby-plugin-vercel-builder@1.1.2
 - @vercel/go@2.3.3
 - @vercel/hydrogen@0.0.49
 - @vercel/next@3.4.1
 - @vercel/node@2.9.2
 - @vercel/python@3.1.45
 - @vercel/redwood@1.1.1
 - @vercel/remix@1.2.12
 - @vercel/ruby@1.3.61
 - @vercel/static-build@1.3.4
2023-02-07 11:51:17 -08:00
JJ Kasper
e2105e47b5 [build-utils] Add passQuery field to Prerender (#9388) 2023-02-06 16:57:17 -08:00
최지민(Jeemin Choi)
76d58673fc [cli] Add --no-color mode (#8826)
Co-authored-by: Sean Massa <EndangeredMassa@gmail.com>
Co-authored-by: Chris Barber <chris.barber@vercel.com>
2023-02-06 16:45:17 -06:00
Andy Bitz
a585969dd3 Publish Stable
- @vercel/build-utils@6.2.0
 - vercel@28.15.1
 - @vercel/client@12.3.6
 - @vercel/fs-detectors@3.7.9
 - @vercel/gatsby-plugin-vercel-builder@1.1.1
 - @vercel/go@2.3.2
 - @vercel/hydrogen@0.0.48
 - @vercel/next@3.4.0
 - @vercel/node@2.9.1
 - @vercel/python@3.1.44
 - @vercel/redwood@1.1.0
 - @vercel/remix@1.2.11
 - @vercel/ruby@1.3.60
 - @vercel/static-build@1.3.3
2023-02-06 17:24:54 +01:00
Andy
35eca33b44 [redwood] Consider all Lambda options (#9386) 2023-02-06 15:46:18 +01:00
Andy
d608153961 [next][build-utils] Add support for cron to vercel.json (#9374) 2023-02-06 12:28:41 +01:00
Bishal Shrestha
a4cfc5f943 [docs] Add troubleshooting step for no serverless pages error (#9333) 2023-02-03 15:23:20 -08:00
chloetedder
2eef3e3ddb [fs-detectors] Add fix for if monorepo and proj at root (#9353)
If there is a monorepo that has one project at the root level we want to
return commands without the relative to root prefixes

---------

Co-authored-by: Chris Barber <chris.barber@vercel.com>
2023-02-03 16:56:22 -06:00
Swarnava Sengupta
8120fd3d7a [examples] Update Astro example to v2 (#9371) 2023-02-03 14:12:29 -05:00
Andy McKay
ba498f3a8e [python] Cope with duplicate header values (#9205)
There are times when a request can arrive for a Python function with headers as a list. One of those examples is this header `x-vercel-proxied-for` which apparently is set twice. Example:

`[b'x-vercel-proxied-for', [b'207.81.134.243', b'172.71.147.74']]`

I took a quick scan through the other Python server implementations and I don't think any of them manipulate the value of the HTTP headers, the way the ASGI one does so I think we are good there.

To reproduce:

`curl https://..../ -H "foo: bar" -H "foo: bar"`

Will fail.

Fixes: https://github.com/vercel/vercel/issues/9132
2023-02-03 17:01:02 +00:00
Steven
b5a9408272 [node] Add log for unused config runtime (#9373)
Both `runtime: undefined` and `runtime: nodejs` have the same behavior
but we want to change that in the future.

The first step is to see if `runtime: nodejs` is currently used at all.
2023-02-03 10:46:18 -05:00
Nathan Rajlich
946f7f0bfc [remix] Remove render path (#9365)
Instead of outputting a single SSR function at `/render` path, scan the
build manifest file to determine the proper paths to output the SSR
function at.
2023-02-02 14:29:52 -08:00
Ethan Arrowood
804a3863e7 [cli] add charset to content-type headers for vc dev (#9364)
Adds `charset: utf8` to the `content-type` header
2023-02-02 01:07:08 +00:00
Andy Bitz
a4d16c681a Publish Stable
- @vercel/build-utils@6.1.0
 - vercel@28.15.0
 - @vercel/client@12.3.5
 - @vercel/fs-detectors@3.7.8
 - @vercel/gatsby-plugin-vercel-builder@1.1.0
 - @vercel/go@2.3.1
 - @vercel/hydrogen@0.0.47
 - @vercel/next@3.3.21
 - @vercel/node@2.9.0
 - @vercel/python@3.1.43
 - @vercel/redwood@1.0.54
 - @vercel/remix@1.2.10
 - @vercel/ruby@1.3.59
 - @vercel/static-build@1.3.2
 - @vercel/static-config@2.0.12
2023-02-01 23:26:52 +01:00
Andy
61bbd4f98b [cli] Add crons to build output (#9360)
Co-authored-by: George Karagkiaouris <gkaragkiaouris2@gmail.com>
Co-authored-by: Chris Barber <chris.barber@vercel.com>
Co-authored-by: Nathan Rajlich <n@n8.io>
2023-02-01 22:47:55 +01:00
Nathan Rajlich
fedf264862 [cli] Merge build output contents instead of copying (#9358)
When Root Directory setting is used, and/or `vc build --output` is used,
do an intelligent "merge" (move) operation rather than copying the
contents of the build output directory to the destination. This should
overall be faster and avoid disk space issues for larger projects.
2023-02-01 12:27:36 -08:00
Nathan Rajlich
6420e54b35 [gatsby-plugin-vercel-builder] Use pathPrefix from BuildArgs (#9362)
Instead of using `pathPrefix` from the Redux store, grab the value
directly from the "BuildArgs" passed to `onPostBuild()`. This value
seems to properly reflect whether or not `--prefix-path` mode was
enabled during the Gatsby build process.
2023-02-01 13:27:24 -07:00
Nathan Rajlich
aa6b957b23 [gatsby-plugin-vercel-builder] Move "public" dir instead of copying (#9356)
We are getting reports of some larger Gatsby projects running out of
disk space during build which seem to be the result of copying the
static directory multiple times.

So move instead of copying, which doesn't fully solve the problem, but
it does kick the can down the road a bit. Very large projects would
probably still hit the disk limit at some point. Anyways, moving is
faster than copying so this is still a net positive.
2023-02-01 11:05:45 -08:00
Nathan Rajlich
c6717a1492 [static-build] Add Gatsby GENERATED_FILE_COMMENT for non-existing config file cases (#9354)
Follow-up to #9312 which missed these two cases.
2023-01-31 18:57:06 -08:00
Steven
0b33c1c3e7 [tests] Remove actions/cache since its actually slower than no cache (#9359)
This PR removes `actions/cache` since it is actually **slower** than no cache.

## ubuntu-latest
- [with cache](https://github.com/vercel/vercel/actions/runs/4059017971/jobs/6986950123): 21s + 3s + 1m4s = 88s
- [without cache](https://github.com/vercel/vercel/actions/runs/4059216913/jobs/6987026470): 44s

## macos-latest
- [with cache](https://github.com/vercel/vercel/actions/runs/4059017971/jobs/6986950275): 2m55s + 8s + 3m20s = 383s
- [without cache](https://github.com/vercel/vercel/actions/runs/4059216913/jobs/6987026554): 2m21s = 141s

## windows-latest
- [with cache](https://github.com/vercel/vercel/actions/runs/4059017971/jobs/6986950359): 1m10s + 6s + 3m29s = 285s
- [without cache](https://github.com/vercel/vercel/actions/runs/4059216913/jobs/6987026661): 1m25s = 85s
2023-01-31 23:58:43 +00:00
Steven
dbea973546 [build-utils][cli] Add env vars for VERCEL_PROJECT_SETTINGS_ (#9332)
This PR adds a few new environment variables for project settings.

This allows frameworks targeting the [Build Output API](https://vercel.com/docs/build-output-api/v3) to read data that is normally only available in through the `config` object when developing a [Builder/Runtime](https://github.com/vercel/vercel/blob/main/DEVELOPING_A_RUNTIME.md).

This will also solve the problem of old Builders/Runtimes that never passed the `config` through to `getNodeVersion()`.

- Related to https://github.com/unjs/nitro/pull/879
2023-01-31 23:27:36 +00:00
Nathan Rajlich
8ac4814702 [cli] Remove .vercel/output during vc build --output (#9357)
The `.vercel/output` directory gets wiped away when `--output` is _not_ being used, but it should be deleted even when the flag is being used so that build scripts targeting Build Output API directly always start with a fresh slate.
2023-01-31 22:10:40 +00:00
github-actions[bot]
c84d6c4355 [examples] Upgrade Next.js to version 13.1.6 (#9334)
This auto-generated PR updates Next.js to version 13.1.6

Co-authored-by: vercel-release-bot <infra+release@vercel.com>
Co-authored-by: Steven <steven@ceriously.com>
2023-01-31 12:20:53 -05:00
Steven
61b6e87987 [tests] Add labels to cron-update-next (#9351)
See example PR: https://github.com/vercel/vercel/pull/9334
2023-01-31 17:06:44 +00:00
chloetedder
ada9a48d57 Publish Stable
- @vercel/build-utils@6.0.1
 - vercel@28.14.1
 - @vercel/client@12.3.4
 - @vercel/fs-detectors@3.7.7
 - @vercel/gatsby-plugin-vercel-builder@1.0.3
 - @vercel/go@2.3.0
 - @vercel/hydrogen@0.0.46
 - @vercel/next@3.3.20
 - @vercel/node@2.8.17
 - @vercel/python@3.1.42
 - @vercel/redwood@1.0.53
 - @vercel/remix@1.2.9
 - @vercel/ruby@1.3.58
 - @vercel/static-build@1.3.1
2023-01-30 15:19:54 -07:00
chloetedder
31f3daa5b4 [fs-detectors] getMonorepoDefaultSettings: Fix settings (#9315)
1. `commandForIgnoringBuildStep` should be run at the project directory level not the monorepo root level
2. Simplifying the `installCommand` because doesn't need the relative root unless it is `npm`
2023-01-30 18:35:42 +00:00
Steven
fdf7fd6784 [go] Add support for Go 1.19 (#9343)
![image](https://user-images.githubusercontent.com/229881/215526900-fef3e4e0-d1a6-4327-b68f-d8bb9068e2a0.png)
2023-01-30 17:08:10 +00:00
Bryan Eaton
db216f903f [tests] Fix github action restore cache timeout (#9342)
Github Action for actions/cache has an issue that could cause it to take
1 hour and then timeout while trying to restore the cache.

Since `actions/setup-node` is no longer used to restore the pnpm cache,
the `timeout-minutes: 5` doesn't do anything for this action.

Instead we need to put an env variable on the `actions/cache` Github
Action to actually set the restore cache timeout.

```
env:
  SEGMENT_DOWNLOAD_TIMEOUT_MINS: 5 # See https://github.com/actions/cache/issues/810
```

- See discussion here https://github.com/vercel/vercel/discussions/9340
- Related to actions/cache#810
- Follow up to #8639
2023-01-30 10:42:00 -05:00
Nathan Rajlich
40a55b11d5 [gatsby-plugin-vercel-builder] Downgrade esbuild to v0.14.47 (#9329)
So that there will only be one copy in the dependency tree between `@vercel/node` and `@vercel/gatsby-plugin-vercel-builder`
2023-01-28 17:03:27 +00:00
Nathan Rajlich
5da537124c [static-build] Add integration test for Gatsby Function (#9330) 2023-01-27 14:00:29 -08:00
JJ Kasper
54aaab83aa [docs] Replace references to @now/next in error docs (#9331)
It's been long enough I think we can change these to refer to
`@vercel/next` instead.

x-ref: [slack
thread](https://vercel.slack.com/archives/C03DQ3QFV7C/p1674849801196389)
2023-01-27 16:59:42 -05:00
Chris Barber
7110cb449b [go] Improved 'go build' error handling (#9320)
The `go` builder doesn't properly handle when `go build` fails. There are 2 failure scenarios:

1. The `go` binary is not found in the `PATH`. There is no message that the `go` executable was not found. Worse, the builder continues and fails trying to run the compiled executable:

![image](https://user-images.githubusercontent.com/97262/214765157-f5244467-7bc8-48e8-8fcf-385efc32b283.png)

The solution is to switch from `spawnSync()` to `execFileSync()` so that if `go` is not found, it will throw like this:

<img width="507" alt="image" src="https://user-images.githubusercontent.com/97262/214765388-792ce59a-79f5-4bc8-8088-472969729558.png">
Note: I temporarily changed the code to spawn `gooooo` to simulate `go` not being found. Either way, `execFileSync()` will throw and we get a helpful message.

2. The `go build` fails due to some actual build error. This should never happen, but better safe than sorry.

The solution here is to allow `go build` to inherit stdout/stderr and if `go build` should fail, we can see the output:

<img width="574" alt="image" src="https://user-images.githubusercontent.com/97262/214765614-c414f160-ad8e-4bd2-a628-b5a91dcc88d8.png">
2023-01-27 20:07:03 +00:00
Chris Barber
89a15681d5 [build-utils] Rewrite rename() to be more efficient (#9322)
Around 6 months ago, @styfle brought to my attention how `rename()` in build-utils used `reduce()` and could be written better. So, I rewrote it.

Before, the code would create a new `Files` object and copy the contents of the previous `Files` object. This caused heavy garbage collection and memory thrashing.

Instead, I created a single `Files` object, then add the files to it.

Results:

| # Files | Before | After |
|---|---|---|
| 1,000 | 75 ms | 1 ms |
| 10,000 | 10.6 s | 7 ms |
| 20,000 | 44.6 s | 16 ms |
| 30,000 | 105.5 s | 22 ms |
| 100,000 | Too long | 73 ms |
2023-01-27 18:21:59 +00:00
Ethan Arrowood
9317543c48 Publish Stable
- vercel@28.14.0
 - @vercel/gatsby-plugin-vercel-builder@1.0.2
 - @vercel/static-build@1.3.0
2023-01-27 10:12:32 -07:00
Nathan Rajlich
e3f326f714 [gatsby-plugin-vercel-builder] Don't delete .vercel/output (#9327)
`.vercel/output` is already made fresh when running `vc build`, so the
plugin should not be doing this. In fact, it makes the `builds.json`
file be wiped away, which we don't want to happen.
2023-01-27 09:08:22 -08:00
Ethan Arrowood
eed6a377f1 [static-build] Cleanup gatsby file changes after static-build completes (#9312)
Adds a new function that restores the user's `gatsby-config.(j|t|mj)s` and `gatsby-node.(j|t|mj)s` files
2023-01-27 16:23:02 +00:00
Nathan Rajlich
c16d9e6784 [static-build] Include Gatsby plugins as regular dependencies (#9313)
Right now, static-build will add the necessary Gatsby plugins to the project's `package.json` at build-time, which has been bothersome for package managers when using a frozen lockfile.

Another issue with it is that we install `latest` version of the plugin, so the version used becomes disjointed from the CLI version itself, which leads to unpredictability when trying to debug issues or help users roll back to a previous behavior if something breaks.

So instead of patching `package.json` directly, include the plugins as deps of static-build itself, and create symlinks to those paths into the project's `node_modules` directory.
2023-01-26 20:15:58 +00:00
130 changed files with 2379 additions and 2160 deletions

View File

@@ -39,16 +39,8 @@ jobs:
- name: Setup Node
if: ${{ steps.check-release.outputs.IS_RELEASE == 'true' }}
uses: actions/setup-node@v3
timeout-minutes: 5 # See https://github.com/actions/cache/issues/810
with:
node-version: 14
- name: Cache
if: ${{ steps.check-release.outputs.IS_RELEASE == 'true' }}
uses: actions/cache@v3
with:
path: '**/node_modules'
key: pnpm-${{ matrix.os }}-${{ matrix.node }}-${{ hashFiles('pnpm-lock.yaml') }}
restore-keys: pnpm-${{ matrix.os }}-${{ matrix.node }}
- name: install pnpm@7.24.2
run: npm i -g pnpm@7.24.2
- name: Install

View File

@@ -35,14 +35,8 @@ jobs:
with:
go-version: '1.18'
- uses: actions/setup-node@v3
timeout-minutes: 5 # See https://github.com/actions/cache/issues/810
with:
node-version: ${{ matrix.node }}
- uses: actions/cache@v3
with:
path: '**/node_modules'
key: pnpm-${{ matrix.os }}-${{ matrix.node }}-${{ hashFiles('pnpm-lock.yaml') }}
restore-keys: pnpm-${{ matrix.os }}-${{ matrix.node }}
- name: install pnpm@7.24.2
run: npm i -g pnpm@7.24.2
- run: pnpm install

View File

@@ -35,14 +35,8 @@ jobs:
with:
fetch-depth: 2
- uses: actions/setup-node@v3
timeout-minutes: 5 # See https://github.com/actions/cache/issues/810
with:
node-version: ${{ matrix.node }}
- uses: actions/cache@v3
with:
path: '**/node_modules'
key: pnpm-${{ matrix.os }}-${{ matrix.node }}-${{ hashFiles('pnpm-lock.yaml') }}
restore-keys: pnpm-${{ matrix.os }}-${{ matrix.node }}
- name: install pnpm@7.24.2
run: npm i -g pnpm@7.24.2
- run: pnpm install

View File

@@ -33,14 +33,8 @@ jobs:
with:
go-version: '1.13.15'
- uses: actions/setup-node@v3
timeout-minutes: 5 # See https://github.com/actions/cache/issues/810
with:
node-version: ${{ env.NODE_VERSION }}
- uses: actions/cache@v3
with:
path: '**/node_modules'
key: pnpm-${{ matrix.os }}-${{ matrix.node }}-${{ hashFiles('pnpm-lock.yaml') }}
restore-keys: pnpm-${{ matrix.os }}-${{ matrix.node }}
- name: install pnpm@7.24.2
run: npm i -g pnpm@7.24.2
- run: pnpm install
@@ -76,14 +70,8 @@ jobs:
with:
go-version: '1.13.15'
- uses: actions/setup-node@v3
timeout-minutes: 5 # See https://github.com/actions/cache/issues/810
with:
node-version: ${{ env.NODE_VERSION }}
- uses: actions/cache@v3
with:
path: '**/node_modules'
key: pnpm-${{ matrix.os }}-${{ matrix.node }}-${{ hashFiles('pnpm-lock.yaml') }}
restore-keys: pnpm-${{ matrix.os }}-${{ matrix.node }}
- name: Install Hugo
if: matrix.runner == 'macos-latest'

View File

@@ -1,8 +1,8 @@
# `@now/next` Legacy Mode
# `@vercel/next` Legacy Mode
#### Why This Warning Occurred
`@now/next` has two modes: `legacy` and `serverless`. You will always want to use the `serverless` mode. `legacy` is to provide backwards compatibility with previous `@now/next` versions.
`@vercel/next` has two modes: `legacy` and `serverless`. You will always want to use the `serverless` mode. `legacy` is to provide backwards compatibility with previous `@vercel/next` versions.
The differences:
@@ -63,7 +63,7 @@ module.exports = {
```js
{
"version": 2,
"builds": [{ "src": "package.json", "use": "@now/next" }]
"builds": [{ "src": "package.json", "use": "@vercel/next" }]
}
```

View File

@@ -1,4 +1,4 @@
# `@now/next` No Serverless Pages Built
# `@vercel/next` No Serverless Pages Built
#### Why This Error Occurred
@@ -24,7 +24,7 @@ npm install next --save
}
```
3. Add `target: 'serverless'` to `next.config.js`
3. Add `target: 'serverless'` to `next.config.js` [deprecated]
```js
module.exports = {
@@ -33,13 +33,15 @@ module.exports = {
};
```
4. Remove `distDir` from `next.config.js` as `@now/next` can't parse this file and expects your build output at `/.next`
4. Remove `distDir` from `next.config.js` as `@vercel/next` can't parse this file and expects your build output at `/.next`
5. Optionally make sure the `"src"` in `"builds"` points to your application `package.json`
```js
{
"version": 2,
"builds": [{ "src": "package.json", "use": "@now/next" }]
"builds": [{ "src": "package.json", "use": "@vercel/next" }]
}
```
6. Make sure you have the correct Node.js version selected for your build step in your project settings (`https://vercel.com/[username]/[project]/settings`)

View File

@@ -8,7 +8,7 @@
"astro": "astro"
},
"devDependencies": {
"astro": "^1.6.10",
"web-vitals": "^3.1.0"
"astro": "^2.0.6",
"web-vitals": "^3.1.1"
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -8,10 +8,10 @@
"name": "nextjs",
"version": "0.1.0",
"dependencies": {
"@next/font": "13.1.5",
"@next/font": "13.1.6",
"eslint": "8.32.0",
"eslint-config-next": "13.1.5",
"next": "13.1.5",
"eslint-config-next": "13.1.6",
"next": "13.1.6",
"react": "18.2.0",
"react-dom": "18.2.0"
}
@@ -80,27 +80,27 @@
"integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA=="
},
"node_modules/@next/env": {
"version": "13.1.5",
"resolved": "https://registry.npmjs.org/@next/env/-/env-13.1.5.tgz",
"integrity": "sha512-0Ry4NhJy6qLbXhvxPRUQ1H6RzgtryGdUto7hfgAK0Iw/bScgeVjwLZdfhm2iT7qsOS32apo9cWzLCxjc6iGPsA=="
"version": "13.1.6",
"resolved": "https://registry.npmjs.org/@next/env/-/env-13.1.6.tgz",
"integrity": "sha512-s+W9Fdqh5MFk6ECrbnVmmAOwxKQuhGMT7xXHrkYIBMBcTiOqNWhv5KbJIboKR5STXxNXl32hllnvKaffzFaWQg=="
},
"node_modules/@next/eslint-plugin-next": {
"version": "13.1.5",
"resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-13.1.5.tgz",
"integrity": "sha512-3kvLTX35bOWOCKU8KY74Ygczc55Qk/kB2TQy0tH7Rti6hzZ6Aij7WQ8zHdIVjmnlD0n/zXWXrIf5y56RKcLQkQ==",
"version": "13.1.6",
"resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-13.1.6.tgz",
"integrity": "sha512-o7cauUYsXjzSJkay8wKjpKJf2uLzlggCsGUkPu3lP09Pv97jYlekTC20KJrjQKmSv5DXV0R/uks2ZXhqjNkqAw==",
"dependencies": {
"glob": "7.1.7"
}
},
"node_modules/@next/font": {
"version": "13.1.5",
"resolved": "https://registry.npmjs.org/@next/font/-/font-13.1.5.tgz",
"integrity": "sha512-6M5R6yC3JkdJiqo/YJxDp6+0vDn0smXOAzl8uHt4qmDS2u53ji/19K0HM51d+5kg8xntDi+N2hw7YjaU9inkNA=="
"version": "13.1.6",
"resolved": "https://registry.npmjs.org/@next/font/-/font-13.1.6.tgz",
"integrity": "sha512-AITjmeb1RgX1HKMCiA39ztx2mxeAyxl4ljv2UoSBUGAbFFMg8MO7YAvjHCgFhD39hL7YTbFjol04e/BPBH5RzQ=="
},
"node_modules/@next/swc-android-arm-eabi": {
"version": "13.1.5",
"resolved": "https://registry.npmjs.org/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-13.1.5.tgz",
"integrity": "sha512-QAEf3YM9U0qWVQTxgF3Tsh4OeCN1i9Smsf6cVlwZsPzoLyj2nQ879joCoN+ONqDknkBgG6OG/ajefywL3jw9Cg==",
"version": "13.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-13.1.6.tgz",
"integrity": "sha512-F3/6Z8LH/pGlPzR1AcjPFxx35mPqjE5xZcf+IL+KgbW9tMkp7CYi1y7qKrEWU7W4AumxX/8OINnDQWLiwLasLQ==",
"cpu": [
"arm"
],
@@ -113,9 +113,9 @@
}
},
"node_modules/@next/swc-android-arm64": {
"version": "13.1.5",
"resolved": "https://registry.npmjs.org/@next/swc-android-arm64/-/swc-android-arm64-13.1.5.tgz",
"integrity": "sha512-ZmtGPTghRuT5YKL0nNcC2bBVSiG1O0is16eIZ2rWSP/hRW64ZCcAew6pxw2rihntNp22UfequjSTHd91WE/tyQ==",
"version": "13.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-android-arm64/-/swc-android-arm64-13.1.6.tgz",
"integrity": "sha512-cMwQjnB8vrYkWyK/H0Rf2c2pKIH4RGjpKUDvbjVAit6SbwPDpmaijLio0LWFV3/tOnY6kvzbL62lndVA0mkYpw==",
"cpu": [
"arm64"
],
@@ -128,9 +128,9 @@
}
},
"node_modules/@next/swc-darwin-arm64": {
"version": "13.1.5",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.1.5.tgz",
"integrity": "sha512-aeFXK+M/zmG/CNdMJ0tGNs0MWcLueUe7vZ2V6fa+2yz/ZgYJLI7fEfFvVh1p1yBMzupSbZDowvMuCSFTaeg3MA==",
"version": "13.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.1.6.tgz",
"integrity": "sha512-KKRQH4DDE4kONXCvFMNBZGDb499Hs+xcFAwvj+rfSUssIDrZOlyfJNy55rH5t2Qxed1e4K80KEJgsxKQN1/fyw==",
"cpu": [
"arm64"
],
@@ -143,9 +143,9 @@
}
},
"node_modules/@next/swc-darwin-x64": {
"version": "13.1.5",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.1.5.tgz",
"integrity": "sha512-6mPX0GNRg8NzjV70at8I8pD9YBnPHDpxJCoMuIqysdTjtQhd09Xk6GUhquNhp1kEJzzVk7OW5l2ch4XIJjtY3A==",
"version": "13.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.1.6.tgz",
"integrity": "sha512-/uOky5PaZDoaU99ohjtNcDTJ6ks/gZ5ykTQDvNZDjIoCxFe3+t06bxsTPY6tAO6uEAw5f6vVFX5H5KLwhrkZCA==",
"cpu": [
"x64"
],
@@ -158,9 +158,9 @@
}
},
"node_modules/@next/swc-freebsd-x64": {
"version": "13.1.5",
"resolved": "https://registry.npmjs.org/@next/swc-freebsd-x64/-/swc-freebsd-x64-13.1.5.tgz",
"integrity": "sha512-nR4a/SNblG0w8hhYRflTZjk4yD99ld18w/FCftw99ziw8sgciBlOXRICJIiRIaMRU8UH7QLSgBOQVnfNcVNKMA==",
"version": "13.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-freebsd-x64/-/swc-freebsd-x64-13.1.6.tgz",
"integrity": "sha512-qaEALZeV7to6weSXk3Br80wtFQ7cFTpos/q+m9XVRFggu+8Ib895XhMWdJBzew6aaOcMvYR6KQ6JmHA2/eMzWw==",
"cpu": [
"x64"
],
@@ -173,9 +173,9 @@
}
},
"node_modules/@next/swc-linux-arm-gnueabihf": {
"version": "13.1.5",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-13.1.5.tgz",
"integrity": "sha512-EzkltCVKg3gUzamoeKPhGeSgXTTLAhSzc7v/+g1Y+HQa7JKMrlzdRkrJf+H4LJXcz7lnxgNKHGRyZBSXnmJKJw==",
"version": "13.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-13.1.6.tgz",
"integrity": "sha512-OybkbC58A1wJ+JrJSOjGDvZzrVEQA4sprJejGqMwiZyLqhr9Eo8FXF0y6HL+m1CPCpPhXEHz/2xKoYsl16kNqw==",
"cpu": [
"arm"
],
@@ -188,9 +188,9 @@
}
},
"node_modules/@next/swc-linux-arm64-gnu": {
"version": "13.1.5",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.1.5.tgz",
"integrity": "sha512-E7HMkdoxStmTUJU4KzBUU4vZ5DHT4Gd327tC3KFZS5lda0NRerJAOCfsRg+fBj22FvCb1UWsX6XI+weL6xhyeQ==",
"version": "13.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.1.6.tgz",
"integrity": "sha512-yCH+yDr7/4FDuWv6+GiYrPI9kcTAO3y48UmaIbrKy8ZJpi7RehJe3vIBRUmLrLaNDH3rY1rwoHi471NvR5J5NQ==",
"cpu": [
"arm64"
],
@@ -203,9 +203,9 @@
}
},
"node_modules/@next/swc-linux-arm64-musl": {
"version": "13.1.5",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.1.5.tgz",
"integrity": "sha512-qlO0Fd3GQwJS6YpbF9NyL5NGHVZ43dKtZDC/jP4vdeMIYDtSu13HcY/nmA1NdW+RpMwDxSCpx4WKsCCEZGIX8Q==",
"version": "13.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.1.6.tgz",
"integrity": "sha512-ECagB8LGX25P9Mrmlc7Q/TQBb9rGScxHbv/kLqqIWs2fIXy6Y/EiBBiM72NTwuXUFCNrWR4sjUPSooVBJJ3ESQ==",
"cpu": [
"arm64"
],
@@ -218,9 +218,9 @@
}
},
"node_modules/@next/swc-linux-x64-gnu": {
"version": "13.1.5",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.1.5.tgz",
"integrity": "sha512-GftSBFAay2nocGl+KNqFsj6EVSvomaM/bp86hzezbKsTwQmu76PjOCVcejI1gE+4k7f5zPDgCuorF6F04BV0HQ==",
"version": "13.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.1.6.tgz",
"integrity": "sha512-GT5w2mruk90V/I5g6ScuueE7fqj/d8Bui2qxdw6lFxmuTgMeol5rnzAv4uAoVQgClOUO/MULilzlODg9Ib3Y4Q==",
"cpu": [
"x64"
],
@@ -233,9 +233,9 @@
}
},
"node_modules/@next/swc-linux-x64-musl": {
"version": "13.1.5",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.1.5.tgz",
"integrity": "sha512-UD+3lxU4yuAjd+uBkCDfBpAcbGAVfEcE8mX/efIxUGIImmzN0QzgTHYEpKFnY3Lxu02dIBcwQRT3Q5mfO4obng==",
"version": "13.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.1.6.tgz",
"integrity": "sha512-keFD6KvwOPzmat4TCnlnuxJCQepPN+8j3Nw876FtULxo8005Y9Ghcl7ACcR8GoiKoddAq8gxNBrpjoxjQRHeAQ==",
"cpu": [
"x64"
],
@@ -248,9 +248,9 @@
}
},
"node_modules/@next/swc-win32-arm64-msvc": {
"version": "13.1.5",
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.1.5.tgz",
"integrity": "sha512-uzsvkQY+K3EbL+97IUHPWZPwjsCmCkdH/O5Cf9wCnh0k0gaj7ob1mGKqr1vNNak+9U7HloGwuHcXnZpijWSP7w==",
"version": "13.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.1.6.tgz",
"integrity": "sha512-OwertslIiGQluFvHyRDzBCIB07qJjqabAmINlXUYt7/sY7Q7QPE8xVi5beBxX/rxTGPIbtyIe3faBE6Z2KywhQ==",
"cpu": [
"arm64"
],
@@ -263,9 +263,9 @@
}
},
"node_modules/@next/swc-win32-ia32-msvc": {
"version": "13.1.5",
"resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.1.5.tgz",
"integrity": "sha512-v0NaC1w8mPf620GlJaHBdEm3dm4G4AEQMasDqjzQvo0yCRrvtvzMgCIe8MocBxFHzaF6868NybMqvumxP5YxEg==",
"version": "13.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.1.6.tgz",
"integrity": "sha512-g8zowiuP8FxUR9zslPmlju7qYbs2XBtTLVSxVikPtUDQedhcls39uKYLvOOd1JZg0ehyhopobRoH1q+MHlIN/w==",
"cpu": [
"ia32"
],
@@ -278,9 +278,9 @@
}
},
"node_modules/@next/swc-win32-x64-msvc": {
"version": "13.1.5",
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.1.5.tgz",
"integrity": "sha512-IZHwvd649ccbWyLCfu92IXEpR250NpmBkaRelPV+WVm4jrd62FKRFCNdqdCXq6TrEg9wN8cK4YG8tm44uEZqLA==",
"version": "13.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.1.6.tgz",
"integrity": "sha512-Ls2OL9hi3YlJKGNdKv8k3X/lLgc3VmLG3a/DeTkAd+lAituJp8ZHmRmm9f9SL84fT3CotlzcgbdaCDfFwFA6bA==",
"cpu": [
"x64"
],
@@ -676,9 +676,9 @@
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001447",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001447.tgz",
"integrity": "sha512-bdKU1BQDPeEXe9A39xJnGtY0uRq/z5osrnXUw0TcK+EYno45Y+U7QU9HhHEyzvMDffpYadFXi3idnSNkcwLkTw==",
"version": "1.0.30001449",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001449.tgz",
"integrity": "sha512-CPB+UL9XMT/Av+pJxCKGhdx+yg1hzplvFJQlJ2n68PyQGMz9L/E2zCyLdOL8uasbouTUgnPl+y0tccI/se+BEw==",
"funding": [
{
"type": "opencollective",
@@ -1028,11 +1028,11 @@
}
},
"node_modules/eslint-config-next": {
"version": "13.1.5",
"resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-13.1.5.tgz",
"integrity": "sha512-7FqkjkvGCQfvYUiPTFRiRYPR1uI6Ew+4f4mVp16lLSWcaChtWoZxQCZHM5n0yxzKKVmuEg1aM4uvDQfSXSjTww==",
"version": "13.1.6",
"resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-13.1.6.tgz",
"integrity": "sha512-0cg7h5wztg/SoLAlxljZ0ZPUQ7i6QKqRiP4M2+MgTZtxWwNKb2JSwNc18nJ6/kXBI6xYvPraTbQSIhAuVw6czw==",
"dependencies": {
"@next/eslint-plugin-next": "13.1.5",
"@next/eslint-plugin-next": "13.1.6",
"@rushstack/eslint-patch": "^1.1.3",
"@typescript-eslint/parser": "^5.42.0",
"eslint-import-resolver-node": "^0.3.6",
@@ -2323,11 +2323,11 @@
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="
},
"node_modules/next": {
"version": "13.1.5",
"resolved": "https://registry.npmjs.org/next/-/next-13.1.5.tgz",
"integrity": "sha512-rmpYZFCxxWAi2nJCT9sSqMLGC3cu+Pf689hx9clcyP0KbVIhh/7Dus5QcKrVd/PrAd6AjsuogSRR1mCP7BoYRw==",
"version": "13.1.6",
"resolved": "https://registry.npmjs.org/next/-/next-13.1.6.tgz",
"integrity": "sha512-hHlbhKPj9pW+Cymvfzc15lvhaOZ54l+8sXDXJWm3OBNBzgrVj6hwGPmqqsXg40xO1Leq+kXpllzRPuncpC0Phw==",
"dependencies": {
"@next/env": "13.1.5",
"@next/env": "13.1.6",
"@swc/helpers": "0.4.14",
"caniuse-lite": "^1.0.30001406",
"postcss": "8.4.14",
@@ -2340,19 +2340,19 @@
"node": ">=14.6.0"
},
"optionalDependencies": {
"@next/swc-android-arm-eabi": "13.1.5",
"@next/swc-android-arm64": "13.1.5",
"@next/swc-darwin-arm64": "13.1.5",
"@next/swc-darwin-x64": "13.1.5",
"@next/swc-freebsd-x64": "13.1.5",
"@next/swc-linux-arm-gnueabihf": "13.1.5",
"@next/swc-linux-arm64-gnu": "13.1.5",
"@next/swc-linux-arm64-musl": "13.1.5",
"@next/swc-linux-x64-gnu": "13.1.5",
"@next/swc-linux-x64-musl": "13.1.5",
"@next/swc-win32-arm64-msvc": "13.1.5",
"@next/swc-win32-ia32-msvc": "13.1.5",
"@next/swc-win32-x64-msvc": "13.1.5"
"@next/swc-android-arm-eabi": "13.1.6",
"@next/swc-android-arm64": "13.1.6",
"@next/swc-darwin-arm64": "13.1.6",
"@next/swc-darwin-x64": "13.1.6",
"@next/swc-freebsd-x64": "13.1.6",
"@next/swc-linux-arm-gnueabihf": "13.1.6",
"@next/swc-linux-arm64-gnu": "13.1.6",
"@next/swc-linux-arm64-musl": "13.1.6",
"@next/swc-linux-x64-gnu": "13.1.6",
"@next/swc-linux-x64-musl": "13.1.6",
"@next/swc-win32-arm64-msvc": "13.1.6",
"@next/swc-win32-ia32-msvc": "13.1.6",
"@next/swc-win32-x64-msvc": "13.1.6"
},
"peerDependencies": {
"fibers": ">= 3.1.0",
@@ -3087,9 +3087,9 @@
}
},
"node_modules/tslib": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
"integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA=="
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz",
"integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg=="
},
"node_modules/tsutils": {
"version": "3.21.0",
@@ -3318,99 +3318,99 @@
"integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA=="
},
"@next/env": {
"version": "13.1.5",
"resolved": "https://registry.npmjs.org/@next/env/-/env-13.1.5.tgz",
"integrity": "sha512-0Ry4NhJy6qLbXhvxPRUQ1H6RzgtryGdUto7hfgAK0Iw/bScgeVjwLZdfhm2iT7qsOS32apo9cWzLCxjc6iGPsA=="
"version": "13.1.6",
"resolved": "https://registry.npmjs.org/@next/env/-/env-13.1.6.tgz",
"integrity": "sha512-s+W9Fdqh5MFk6ECrbnVmmAOwxKQuhGMT7xXHrkYIBMBcTiOqNWhv5KbJIboKR5STXxNXl32hllnvKaffzFaWQg=="
},
"@next/eslint-plugin-next": {
"version": "13.1.5",
"resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-13.1.5.tgz",
"integrity": "sha512-3kvLTX35bOWOCKU8KY74Ygczc55Qk/kB2TQy0tH7Rti6hzZ6Aij7WQ8zHdIVjmnlD0n/zXWXrIf5y56RKcLQkQ==",
"version": "13.1.6",
"resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-13.1.6.tgz",
"integrity": "sha512-o7cauUYsXjzSJkay8wKjpKJf2uLzlggCsGUkPu3lP09Pv97jYlekTC20KJrjQKmSv5DXV0R/uks2ZXhqjNkqAw==",
"requires": {
"glob": "7.1.7"
}
},
"@next/font": {
"version": "13.1.5",
"resolved": "https://registry.npmjs.org/@next/font/-/font-13.1.5.tgz",
"integrity": "sha512-6M5R6yC3JkdJiqo/YJxDp6+0vDn0smXOAzl8uHt4qmDS2u53ji/19K0HM51d+5kg8xntDi+N2hw7YjaU9inkNA=="
"version": "13.1.6",
"resolved": "https://registry.npmjs.org/@next/font/-/font-13.1.6.tgz",
"integrity": "sha512-AITjmeb1RgX1HKMCiA39ztx2mxeAyxl4ljv2UoSBUGAbFFMg8MO7YAvjHCgFhD39hL7YTbFjol04e/BPBH5RzQ=="
},
"@next/swc-android-arm-eabi": {
"version": "13.1.5",
"resolved": "https://registry.npmjs.org/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-13.1.5.tgz",
"integrity": "sha512-QAEf3YM9U0qWVQTxgF3Tsh4OeCN1i9Smsf6cVlwZsPzoLyj2nQ879joCoN+ONqDknkBgG6OG/ajefywL3jw9Cg==",
"version": "13.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-13.1.6.tgz",
"integrity": "sha512-F3/6Z8LH/pGlPzR1AcjPFxx35mPqjE5xZcf+IL+KgbW9tMkp7CYi1y7qKrEWU7W4AumxX/8OINnDQWLiwLasLQ==",
"optional": true
},
"@next/swc-android-arm64": {
"version": "13.1.5",
"resolved": "https://registry.npmjs.org/@next/swc-android-arm64/-/swc-android-arm64-13.1.5.tgz",
"integrity": "sha512-ZmtGPTghRuT5YKL0nNcC2bBVSiG1O0is16eIZ2rWSP/hRW64ZCcAew6pxw2rihntNp22UfequjSTHd91WE/tyQ==",
"version": "13.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-android-arm64/-/swc-android-arm64-13.1.6.tgz",
"integrity": "sha512-cMwQjnB8vrYkWyK/H0Rf2c2pKIH4RGjpKUDvbjVAit6SbwPDpmaijLio0LWFV3/tOnY6kvzbL62lndVA0mkYpw==",
"optional": true
},
"@next/swc-darwin-arm64": {
"version": "13.1.5",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.1.5.tgz",
"integrity": "sha512-aeFXK+M/zmG/CNdMJ0tGNs0MWcLueUe7vZ2V6fa+2yz/ZgYJLI7fEfFvVh1p1yBMzupSbZDowvMuCSFTaeg3MA==",
"version": "13.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.1.6.tgz",
"integrity": "sha512-KKRQH4DDE4kONXCvFMNBZGDb499Hs+xcFAwvj+rfSUssIDrZOlyfJNy55rH5t2Qxed1e4K80KEJgsxKQN1/fyw==",
"optional": true
},
"@next/swc-darwin-x64": {
"version": "13.1.5",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.1.5.tgz",
"integrity": "sha512-6mPX0GNRg8NzjV70at8I8pD9YBnPHDpxJCoMuIqysdTjtQhd09Xk6GUhquNhp1kEJzzVk7OW5l2ch4XIJjtY3A==",
"version": "13.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.1.6.tgz",
"integrity": "sha512-/uOky5PaZDoaU99ohjtNcDTJ6ks/gZ5ykTQDvNZDjIoCxFe3+t06bxsTPY6tAO6uEAw5f6vVFX5H5KLwhrkZCA==",
"optional": true
},
"@next/swc-freebsd-x64": {
"version": "13.1.5",
"resolved": "https://registry.npmjs.org/@next/swc-freebsd-x64/-/swc-freebsd-x64-13.1.5.tgz",
"integrity": "sha512-nR4a/SNblG0w8hhYRflTZjk4yD99ld18w/FCftw99ziw8sgciBlOXRICJIiRIaMRU8UH7QLSgBOQVnfNcVNKMA==",
"version": "13.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-freebsd-x64/-/swc-freebsd-x64-13.1.6.tgz",
"integrity": "sha512-qaEALZeV7to6weSXk3Br80wtFQ7cFTpos/q+m9XVRFggu+8Ib895XhMWdJBzew6aaOcMvYR6KQ6JmHA2/eMzWw==",
"optional": true
},
"@next/swc-linux-arm-gnueabihf": {
"version": "13.1.5",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-13.1.5.tgz",
"integrity": "sha512-EzkltCVKg3gUzamoeKPhGeSgXTTLAhSzc7v/+g1Y+HQa7JKMrlzdRkrJf+H4LJXcz7lnxgNKHGRyZBSXnmJKJw==",
"version": "13.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-13.1.6.tgz",
"integrity": "sha512-OybkbC58A1wJ+JrJSOjGDvZzrVEQA4sprJejGqMwiZyLqhr9Eo8FXF0y6HL+m1CPCpPhXEHz/2xKoYsl16kNqw==",
"optional": true
},
"@next/swc-linux-arm64-gnu": {
"version": "13.1.5",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.1.5.tgz",
"integrity": "sha512-E7HMkdoxStmTUJU4KzBUU4vZ5DHT4Gd327tC3KFZS5lda0NRerJAOCfsRg+fBj22FvCb1UWsX6XI+weL6xhyeQ==",
"version": "13.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.1.6.tgz",
"integrity": "sha512-yCH+yDr7/4FDuWv6+GiYrPI9kcTAO3y48UmaIbrKy8ZJpi7RehJe3vIBRUmLrLaNDH3rY1rwoHi471NvR5J5NQ==",
"optional": true
},
"@next/swc-linux-arm64-musl": {
"version": "13.1.5",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.1.5.tgz",
"integrity": "sha512-qlO0Fd3GQwJS6YpbF9NyL5NGHVZ43dKtZDC/jP4vdeMIYDtSu13HcY/nmA1NdW+RpMwDxSCpx4WKsCCEZGIX8Q==",
"version": "13.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.1.6.tgz",
"integrity": "sha512-ECagB8LGX25P9Mrmlc7Q/TQBb9rGScxHbv/kLqqIWs2fIXy6Y/EiBBiM72NTwuXUFCNrWR4sjUPSooVBJJ3ESQ==",
"optional": true
},
"@next/swc-linux-x64-gnu": {
"version": "13.1.5",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.1.5.tgz",
"integrity": "sha512-GftSBFAay2nocGl+KNqFsj6EVSvomaM/bp86hzezbKsTwQmu76PjOCVcejI1gE+4k7f5zPDgCuorF6F04BV0HQ==",
"version": "13.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.1.6.tgz",
"integrity": "sha512-GT5w2mruk90V/I5g6ScuueE7fqj/d8Bui2qxdw6lFxmuTgMeol5rnzAv4uAoVQgClOUO/MULilzlODg9Ib3Y4Q==",
"optional": true
},
"@next/swc-linux-x64-musl": {
"version": "13.1.5",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.1.5.tgz",
"integrity": "sha512-UD+3lxU4yuAjd+uBkCDfBpAcbGAVfEcE8mX/efIxUGIImmzN0QzgTHYEpKFnY3Lxu02dIBcwQRT3Q5mfO4obng==",
"version": "13.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.1.6.tgz",
"integrity": "sha512-keFD6KvwOPzmat4TCnlnuxJCQepPN+8j3Nw876FtULxo8005Y9Ghcl7ACcR8GoiKoddAq8gxNBrpjoxjQRHeAQ==",
"optional": true
},
"@next/swc-win32-arm64-msvc": {
"version": "13.1.5",
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.1.5.tgz",
"integrity": "sha512-uzsvkQY+K3EbL+97IUHPWZPwjsCmCkdH/O5Cf9wCnh0k0gaj7ob1mGKqr1vNNak+9U7HloGwuHcXnZpijWSP7w==",
"version": "13.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.1.6.tgz",
"integrity": "sha512-OwertslIiGQluFvHyRDzBCIB07qJjqabAmINlXUYt7/sY7Q7QPE8xVi5beBxX/rxTGPIbtyIe3faBE6Z2KywhQ==",
"optional": true
},
"@next/swc-win32-ia32-msvc": {
"version": "13.1.5",
"resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.1.5.tgz",
"integrity": "sha512-v0NaC1w8mPf620GlJaHBdEm3dm4G4AEQMasDqjzQvo0yCRrvtvzMgCIe8MocBxFHzaF6868NybMqvumxP5YxEg==",
"version": "13.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.1.6.tgz",
"integrity": "sha512-g8zowiuP8FxUR9zslPmlju7qYbs2XBtTLVSxVikPtUDQedhcls39uKYLvOOd1JZg0ehyhopobRoH1q+MHlIN/w==",
"optional": true
},
"@next/swc-win32-x64-msvc": {
"version": "13.1.5",
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.1.5.tgz",
"integrity": "sha512-IZHwvd649ccbWyLCfu92IXEpR250NpmBkaRelPV+WVm4jrd62FKRFCNdqdCXq6TrEg9wN8cK4YG8tm44uEZqLA==",
"version": "13.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.1.6.tgz",
"integrity": "sha512-Ls2OL9hi3YlJKGNdKv8k3X/lLgc3VmLG3a/DeTkAd+lAituJp8ZHmRmm9f9SL84fT3CotlzcgbdaCDfFwFA6bA==",
"optional": true
},
"@nodelib/fs.scandir": {
@@ -3674,9 +3674,9 @@
"integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="
},
"caniuse-lite": {
"version": "1.0.30001447",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001447.tgz",
"integrity": "sha512-bdKU1BQDPeEXe9A39xJnGtY0uRq/z5osrnXUw0TcK+EYno45Y+U7QU9HhHEyzvMDffpYadFXi3idnSNkcwLkTw=="
"version": "1.0.30001449",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001449.tgz",
"integrity": "sha512-CPB+UL9XMT/Av+pJxCKGhdx+yg1hzplvFJQlJ2n68PyQGMz9L/E2zCyLdOL8uasbouTUgnPl+y0tccI/se+BEw=="
},
"chalk": {
"version": "4.1.2",
@@ -3942,11 +3942,11 @@
}
},
"eslint-config-next": {
"version": "13.1.5",
"resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-13.1.5.tgz",
"integrity": "sha512-7FqkjkvGCQfvYUiPTFRiRYPR1uI6Ew+4f4mVp16lLSWcaChtWoZxQCZHM5n0yxzKKVmuEg1aM4uvDQfSXSjTww==",
"version": "13.1.6",
"resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-13.1.6.tgz",
"integrity": "sha512-0cg7h5wztg/SoLAlxljZ0ZPUQ7i6QKqRiP4M2+MgTZtxWwNKb2JSwNc18nJ6/kXBI6xYvPraTbQSIhAuVw6czw==",
"requires": {
"@next/eslint-plugin-next": "13.1.5",
"@next/eslint-plugin-next": "13.1.6",
"@rushstack/eslint-patch": "^1.1.3",
"@typescript-eslint/parser": "^5.42.0",
"eslint-import-resolver-node": "^0.3.6",
@@ -4860,24 +4860,24 @@
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="
},
"next": {
"version": "13.1.5",
"resolved": "https://registry.npmjs.org/next/-/next-13.1.5.tgz",
"integrity": "sha512-rmpYZFCxxWAi2nJCT9sSqMLGC3cu+Pf689hx9clcyP0KbVIhh/7Dus5QcKrVd/PrAd6AjsuogSRR1mCP7BoYRw==",
"version": "13.1.6",
"resolved": "https://registry.npmjs.org/next/-/next-13.1.6.tgz",
"integrity": "sha512-hHlbhKPj9pW+Cymvfzc15lvhaOZ54l+8sXDXJWm3OBNBzgrVj6hwGPmqqsXg40xO1Leq+kXpllzRPuncpC0Phw==",
"requires": {
"@next/env": "13.1.5",
"@next/swc-android-arm-eabi": "13.1.5",
"@next/swc-android-arm64": "13.1.5",
"@next/swc-darwin-arm64": "13.1.5",
"@next/swc-darwin-x64": "13.1.5",
"@next/swc-freebsd-x64": "13.1.5",
"@next/swc-linux-arm-gnueabihf": "13.1.5",
"@next/swc-linux-arm64-gnu": "13.1.5",
"@next/swc-linux-arm64-musl": "13.1.5",
"@next/swc-linux-x64-gnu": "13.1.5",
"@next/swc-linux-x64-musl": "13.1.5",
"@next/swc-win32-arm64-msvc": "13.1.5",
"@next/swc-win32-ia32-msvc": "13.1.5",
"@next/swc-win32-x64-msvc": "13.1.5",
"@next/env": "13.1.6",
"@next/swc-android-arm-eabi": "13.1.6",
"@next/swc-android-arm64": "13.1.6",
"@next/swc-darwin-arm64": "13.1.6",
"@next/swc-darwin-x64": "13.1.6",
"@next/swc-freebsd-x64": "13.1.6",
"@next/swc-linux-arm-gnueabihf": "13.1.6",
"@next/swc-linux-arm64-gnu": "13.1.6",
"@next/swc-linux-arm64-musl": "13.1.6",
"@next/swc-linux-x64-gnu": "13.1.6",
"@next/swc-linux-x64-musl": "13.1.6",
"@next/swc-win32-arm64-msvc": "13.1.6",
"@next/swc-win32-ia32-msvc": "13.1.6",
"@next/swc-win32-x64-msvc": "13.1.6",
"@swc/helpers": "0.4.14",
"caniuse-lite": "^1.0.30001406",
"postcss": "8.4.14",
@@ -5350,9 +5350,9 @@
}
},
"tslib": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
"integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA=="
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz",
"integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg=="
},
"tsutils": {
"version": "3.21.0",

View File

@@ -9,10 +9,10 @@
"lint": "next lint"
},
"dependencies": {
"@next/font": "13.1.5",
"@next/font": "13.1.6",
"eslint": "8.32.0",
"eslint-config-next": "13.1.5",
"next": "13.1.5",
"eslint-config-next": "13.1.6",
"next": "13.1.6",
"react": "18.2.0",
"react-dom": "18.2.0"
}

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/build-utils",
"version": "6.0.0",
"version": "6.2.1",
"license": "MIT",
"main": "./dist/index.js",
"types": "./dist/index.d.js",

View File

@@ -1,4 +1,4 @@
import type { Files } from './types';
import type { Cron, Files } from './types';
/**
* An Edge Functions output
@@ -41,6 +41,9 @@ export class EdgeFunction {
/** The regions where the edge function will be executed on */
regions?: string | string[];
/** Cronjob definition for the edge function */
cron?: Cron;
constructor(params: Omit<EdgeFunction, 'type'>) {
this.type = 'EdgeFunction';
this.name = params.name;
@@ -50,5 +53,6 @@ export class EdgeFunction {
this.envVarsInUse = params.envVarsInUse;
this.assets = params.assets;
this.regions = params.regions;
this.cron = params.cron;
}
}

View File

@@ -1,12 +1,17 @@
import { Files } from '../types';
type Delegate = (name: string) => string;
/**
* Renames the keys of a `Files` map.
*
* @param files A map of filenames to `File` instances
* @param delegate A function that returns the new filename
* @returns A new file map with the renamed filenames
*/
export default function rename(files: Files, delegate: Delegate): Files {
return Object.keys(files).reduce(
(newFiles, name) => ({
...newFiles,
[delegate(name)]: files[name],
}),
{}
);
const result: Files = {};
for (const [name, file] of Object.entries(files)) {
result[delegate(name)] = file;
}
return result;
}

View File

@@ -199,7 +199,7 @@ export function getSpawnOptions(
export async function getNodeVersion(
destPath: string,
_nodeVersion?: string,
nodeVersionFallback = process.env.VERCEL_PROJECT_SETTINGS_NODE_VERSION,
config: Config = {},
meta: Meta = {}
): Promise<NodeVersion> {
@@ -209,7 +209,7 @@ export async function getNodeVersion(
return { ...latest, runtime: 'nodejs' };
}
const { packageJson } = await scanParentDirs(destPath, true);
let { nodeVersion } = config;
let nodeVersion = config.nodeVersion || nodeVersionFallback;
let isAuto = true;
if (packageJson?.engines?.node) {
const { node } = packageJson.engines;

View File

@@ -5,7 +5,7 @@ import minimatch from 'minimatch';
import { readlink } from 'fs-extra';
import { isSymbolicLink, isDirectory } from './fs/download';
import streamToBuffer from './fs/stream-to-buffer';
import type { Files, Config } from './types';
import type { Files, Config, Cron } from './types';
interface Environment {
[key: string]: string;
@@ -25,6 +25,7 @@ export interface LambdaOptionsBase {
supportsWrapper?: boolean;
experimentalResponseStreaming?: boolean;
operationType?: string;
cron?: Cron;
}
export interface LambdaOptionsWithFiles extends LambdaOptionsBase {
@@ -62,6 +63,7 @@ export class Lambda {
environment: Environment;
allowQuery?: string[];
regions?: string[];
cron?: Cron;
/**
* @deprecated Use `await lambda.createZip()` instead.
*/
@@ -79,6 +81,7 @@ export class Lambda {
environment = {},
allowQuery,
regions,
cron,
supportsMultiPayloads,
supportsWrapper,
experimentalResponseStreaming,
@@ -132,6 +135,10 @@ export class Lambda {
);
}
if (cron !== undefined) {
assert(typeof cron === 'string', '"cron" is not a string');
}
this.type = 'Lambda';
this.operationType = operationType;
this.files = 'files' in opts ? opts.files : undefined;
@@ -142,6 +149,7 @@ export class Lambda {
this.environment = environment;
this.allowQuery = allowQuery;
this.regions = regions;
this.cron = cron;
this.zipBuffer = 'zipBuffer' in opts ? opts.zipBuffer : undefined;
this.supportsMultiPayloads = supportsMultiPayloads;
this.supportsWrapper = supportsWrapper;
@@ -220,7 +228,7 @@ export async function getLambdaOptionsFromFunction({
sourceFile,
config,
}: GetLambdaOptionsFromFunctionOptions): Promise<
Pick<LambdaOptions, 'memory' | 'maxDuration'>
Pick<LambdaOptions, 'memory' | 'maxDuration' | 'cron'>
> {
if (config?.functions) {
for (const [pattern, fn] of Object.entries(config.functions)) {
@@ -228,6 +236,7 @@ export async function getLambdaOptionsFromFunction({
return {
memory: fn.memory,
maxDuration: fn.maxDuration,
cron: fn.cron,
};
}
}

View File

@@ -10,6 +10,7 @@ interface PrerenderOptions {
allowQuery?: string[];
initialHeaders?: Record<string, string>;
initialStatus?: number;
passQuery?: boolean;
}
export class Prerender {
@@ -22,6 +23,7 @@ export class Prerender {
public allowQuery?: string[];
public initialHeaders?: Record<string, string>;
public initialStatus?: number;
public passQuery?: boolean;
constructor({
expiration,
@@ -32,6 +34,7 @@ export class Prerender {
allowQuery,
initialHeaders,
initialStatus,
passQuery,
}: PrerenderOptions) {
this.type = 'Prerender';
this.expiration = expiration;
@@ -52,6 +55,17 @@ export class Prerender {
}
this.group = group;
if (passQuery === true) {
this.passQuery = true;
} else if (
typeof passQuery !== 'boolean' &&
typeof passQuery !== 'undefined'
) {
throw new Error(
`The \`passQuery\` argument for \`Prerender\` must be a boolean.`
);
}
if (bypassToken == null) {
this.bypassToken = null;
} else if (typeof bypassToken === 'string') {

View File

@@ -31,6 +31,11 @@ export const functionsSchema = {
type: 'string',
maxLength: 256,
},
cron: {
type: 'string',
minLength: 9,
maxLength: 256,
},
},
},
},

View File

@@ -319,6 +319,7 @@ export interface BuilderFunctions {
runtime?: string;
includeFiles?: string;
excludeFiles?: string;
cron?: Cron;
};
}
@@ -410,6 +411,8 @@ export interface BuildResultBuildOutput {
buildOutputPath: string;
}
export type Cron = string;
/**
* When a Builder implements `version: 2`, the `build()` function is expected
* to return this type.

View File

@@ -4,14 +4,17 @@ import fs from 'fs-extra';
import { strict as assert } from 'assert';
import { getSupportedNodeVersion } from '../src/fs/node-version';
import {
FileBlob,
getNodeVersion,
getLatestNodeVersion,
getDiscontinuedNodeVersions,
rename,
runNpmInstall,
runPackageJsonScript,
scanParentDirs,
Prerender,
} from '../src';
import type { Files } from '../src';
jest.setTimeout(10 * 1000);
@@ -135,13 +138,25 @@ it('should ignore node version in vercel dev getNodeVersion()', async () => {
).toHaveProperty('runtime', 'nodejs');
});
it('should select project setting from config when no package.json is found', async () => {
it('should select project setting from config when no package.json is found and fallback undefined', async () => {
expect(
await getNodeVersion('/tmp', undefined, { nodeVersion: '16.x' }, {})
).toHaveProperty('range', '16.x');
expect(warningMessages).toStrictEqual([]);
});
it('should select project setting from config when no package.json is found and fallback is null', async () => {
expect(
await getNodeVersion('/tmp', null as any, { nodeVersion: '16.x' }, {})
).toHaveProperty('range', '16.x');
expect(warningMessages).toStrictEqual([]);
});
it('should select project setting from fallback when no package.json is found', async () => {
expect(await getNodeVersion('/tmp', '16.x')).toHaveProperty('range', '16.x');
expect(warningMessages).toStrictEqual([]);
});
it('should prefer package.json engines over project setting from config and warn', async () => {
expect(
await getNodeVersion(
@@ -303,6 +318,49 @@ it('should support initialHeaders and initialStatus correctly', async () => {
});
});
it('should support passQuery correctly', async () => {
new Prerender({
expiration: 1,
fallback: null,
group: 1,
bypassToken: 'some-long-bypass-token-to-make-it-work',
passQuery: true,
});
new Prerender({
expiration: 1,
fallback: null,
group: 1,
bypassToken: 'some-long-bypass-token-to-make-it-work',
passQuery: false,
});
new Prerender({
expiration: 1,
fallback: null,
group: 1,
bypassToken: 'some-long-bypass-token-to-make-it-work',
passQuery: undefined,
});
new Prerender({
expiration: 1,
fallback: null,
group: 1,
bypassToken: 'some-long-bypass-token-to-make-it-work',
});
expect(() => {
new Prerender({
expiration: 1,
fallback: null,
group: 1,
bypassToken: 'some-long-bypass-token-to-make-it-work',
// @ts-expect-error testing invalid field
passQuery: 'true',
});
}).toThrowError(
`The \`passQuery\` argument for \`Prerender\` must be a boolean.`
);
});
it('should support require by path for legacy builders', () => {
const index = require('../');
@@ -451,3 +509,18 @@ it('should retry npm install when peer deps invalid and npm@8 on node@16', async
'Warning: Retrying "Install Command" with `--legacy-peer-deps` which may accept a potentially broken dependency and slow install time.',
]);
});
describe('rename', () => {
it('should rename keys of files map', () => {
const before: Files = {};
const toUpper = (s: string) => s.toUpperCase();
for (let i = 97; i <= 122; i++) {
const key = String.fromCharCode(i);
before[key] = new FileBlob({ contentType: 'text/plain', data: key });
}
const after = rename(before, toUpper);
expect(Object.keys(after)).toEqual('ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split(''));
});
});

View File

@@ -1,6 +1,6 @@
{
"name": "vercel",
"version": "28.13.2",
"version": "28.15.2",
"preferGlobal": true,
"license": "Apache-2.0",
"description": "The command-line interface for Vercel",
@@ -41,16 +41,16 @@
"node": ">= 14"
},
"dependencies": {
"@vercel/build-utils": "6.0.0",
"@vercel/go": "2.2.31",
"@vercel/hydrogen": "0.0.45",
"@vercel/next": "3.3.19",
"@vercel/node": "2.8.16",
"@vercel/python": "3.1.41",
"@vercel/redwood": "1.0.52",
"@vercel/remix": "1.2.8",
"@vercel/ruby": "1.3.57",
"@vercel/static-build": "1.2.1"
"@vercel/build-utils": "6.2.1",
"@vercel/go": "2.3.3",
"@vercel/hydrogen": "0.0.49",
"@vercel/next": "3.4.1",
"@vercel/node": "2.9.2",
"@vercel/python": "3.1.45",
"@vercel/redwood": "1.1.1",
"@vercel/remix": "1.2.12",
"@vercel/ruby": "1.3.61",
"@vercel/static-build": "1.3.4"
},
"devDependencies": {
"@alex_neo/jest-expect-message": "1.0.5",
@@ -93,10 +93,10 @@
"@types/which": "1.3.2",
"@types/write-json-file": "2.2.1",
"@types/yauzl-promise": "2.1.0",
"@vercel/client": "12.3.3",
"@vercel/client": "12.3.7",
"@vercel/error-utils": "1.0.8",
"@vercel/frameworks": "1.3.0",
"@vercel/fs-detectors": "3.7.6",
"@vercel/fs-detectors": "3.7.10",
"@vercel/fun": "1.0.4",
"@vercel/ncc": "0.24.0",
"@vercel/routing-utils": "2.1.8",

View File

@@ -32,6 +32,7 @@ const help = () => {
'DIR'
)} Path to the global ${'`.vercel`'} directory
-d, --debug Debug mode [off]
--no-color No color mode [off]
-t ${chalk.bold.underline('TOKEN')}, --token=${chalk.bold.underline(
'TOKEN'
)} Login token

View File

@@ -33,6 +33,7 @@ const help = () => {
-h, --help Output usage information
-d, --debug Debug mode [off]
--no-color No color mode [off]
-b, --bad Known bad URL
-g, --good Known good URL
-o, --open Automatically open each URL in the browser

View File

@@ -118,6 +118,7 @@ const help = () => {
--output [path] Directory where built assets should be written to
--prod Build a production deployment
-d, --debug Debug mode [off]
--no-color No color mode [off]
-y, --yes Skip the confirmation prompt about pulling environment variables and project settings when not found locally
${chalk.dim('Examples:')}
@@ -212,10 +213,15 @@ export default async function main(client: Client): Promise<number> {
}
// Delete output directory from potential previous build
const defaultOutputDir = join(cwd, OUTPUT_DIR);
const outputDir = argv['--output']
? resolve(argv['--output'])
: join(cwd, OUTPUT_DIR);
await fs.remove(outputDir);
: defaultOutputDir;
await Promise.all([
fs.remove(outputDir),
// Also delete `.vercel/output`, in case the script is targeting Build Output API directly
outputDir !== defaultOutputDir ? fs.remove(defaultOutputDir) : undefined,
]);
const buildsJson: BuildsManifest = {
'//': 'This file was generated by the `vercel build` command. It is not part of the Build Output API.',
@@ -471,6 +477,22 @@ async function doBuild(
try {
const { builder, pkg: builderPkg } = builderWithPkg;
for (const key of [
'buildCommand',
'installCommand',
'outputDirectory',
'nodeVersion',
] as const) {
const value = projectSettings[key];
if (typeof value === 'string') {
const envKey =
`VERCEL_PROJECT_SETTINGS_` +
key.replace(/[A-Z]/g, letter => `_${letter}`).toUpperCase();
process.env[envKey] = value;
output.debug(`Setting env ${envKey} to "${value}"`);
}
}
const buildConfig: Config = isZeroConfig
? {
outputDirectory: projectSettings.outputDirectory ?? undefined,

View File

@@ -37,6 +37,7 @@ const help = () => {
'DIR'
)} Path to the global ${'`.vercel`'} directory
-d, --debug Debug mode [off]
--no-color No color mode [off]
-t ${chalk.bold.underline('TOKEN')}, --token=${chalk.bold.underline(
'TOKEN'
)} Login token

View File

@@ -53,6 +53,7 @@ export const help = () => `
'DIR'
)} Path to the global ${'`.vercel`'} directory
-d, --debug Debug mode [off]
--no-color No color mode [off]
-f, --force Force a new deployment even if nothing has changed
--with-cache Retain build cache when using "--force"
-t ${chalk.underline('TOKEN')}, --token=${chalk.underline(

View File

@@ -31,6 +31,7 @@ const help = () => {
-h, --help Output usage information
-d, --debug Debug mode [off]
--no-color No color mode [off]
-l, --listen [uri] Specify a URI endpoint on which to listen [0.0.0.0:3000]
-t, --token [token] Specify an Authorization Token
-y, --yes Skip questions when setting up new project using default scope and settings

View File

@@ -33,6 +33,7 @@ const help = () => {
'DIR'
)} Path to the global ${'`.vercel`'} directory
-d, --debug Debug mode [off]
--no-color No color mode [off]
-t ${chalk.bold.underline('TOKEN')}, --token=${chalk.bold.underline(
'TOKEN'
)} Login token

View File

@@ -33,6 +33,7 @@ const help = () => {
-h, --help Output usage information
-d, --debug Debug mode [off]
--no-color No color mode [off]
-f, --force Force a domain on a project and remove it from an existing one
-A ${chalk.bold.underline('FILE')}, --local-config=${chalk.bold.underline(
'FILE'

View File

@@ -40,6 +40,7 @@ const help = () => {
'DIR'
)} Path to the global ${'`.vercel`'} directory
-d, --debug Debug mode [off]
--no-color No color mode [off]
-t ${chalk.bold.underline('TOKEN')}, --token=${chalk.bold.underline(
'TOKEN'
)} Login token

View File

@@ -21,6 +21,7 @@ const help = () => {
-h, --help Output usage information
-d, --debug Debug mode [off]
--no-color No color mode [off]
-f, --force Overwrite destination directory if exists [off]
${chalk.dim('Examples:')}

View File

@@ -32,6 +32,7 @@ const help = () => {
'TOKEN'
)} Login token
-d, --debug Debug mode [off]
--no-color No color mode [off]
-S, --scope Set a custom scope
${chalk.dim('Examples:')}

View File

@@ -19,6 +19,7 @@ const help = () => {
'DIR'
)} Path to the global ${'`.vercel`'} directory
-d, --debug Debug mode [off]
--no-color No color mode [off]
-t ${chalk.bold.underline('TOKEN')}, --token=${chalk.bold.underline(
'TOKEN'
)} Login token

View File

@@ -36,6 +36,7 @@ const help = () => {
'DIR'
)} Path to the global ${'`.vercel`'} directory
-d, --debug Debug mode [off]
--no-color No color mode [off]
-y, --yes Skip questions when setting up new project using default scope and settings
-t ${chalk.bold.underline('TOKEN')}, --token=${chalk.bold.underline(
'TOKEN'

View File

@@ -23,6 +23,7 @@ const help = () => {
${chalk.dim('Options:')}
-h, --help Output usage information
--no-color No color mode [off]
-A ${chalk.bold.underline('FILE')}, --local-config=${chalk.bold.underline(
'FILE'
)} Path to the local ${'`vercel.json`'} file

View File

@@ -23,6 +23,7 @@ const help = () => {
'DIR'
)} Path to the global ${'`.vercel`'} directory
-d, --debug Debug mode [off]
--no-color No color mode [off]
-f, --follow Wait for additional data [off]
-n ${chalk.bold.underline(
'NUMBER'

View File

@@ -31,6 +31,7 @@ const help = () => {
'DIR'
)} Path to the global ${'`.vercel`'} directory
-d, --debug Debug mode [off]
--no-color No color mode [off]
--environment [environment] Deployment environment [development]
-y, --yes Skip questions when setting up new project using default scope and settings

View File

@@ -39,6 +39,7 @@ const help = () => {
'DIR'
)} Path to the global ${'`.vercel`'} directory
-d, --debug Debug mode [off]
--no-color No color mode [off]
-t ${chalk.bold.underline('TOKEN')}, --token=${chalk.bold.underline(
'TOKEN'
)} Login token

View File

@@ -28,6 +28,7 @@ const help = () => {
'DIR'
)} Path to the global ${'`.vercel`'} directory
-d, --debug Debug mode [off]
--no-color No color mode [off]
-t ${chalk.bold.underline('TOKEN')}, --token=${chalk.bold.underline(
'TOKEN'
)} Login token

View File

@@ -30,6 +30,7 @@ const help = () => {
'DIR'
)} Path to the global ${'`.vercel`'} directory
-d, --debug Debug mode [off]
--no-color No color mode [off]
-N, --next Show next page of results
${chalk.dim('Examples:')}

View File

@@ -19,6 +19,7 @@ const help = () => {
'DIR'
)} Path to the global ${'`.vercel`'} directory
-d, --debug Debug mode [off]
--no-color No color mode [off]
-t ${chalk.bold.underline('TOKEN')}, --token=${chalk.bold.underline(
'TOKEN'
)} Login token

View File

@@ -103,7 +103,12 @@ const main = async () => {
}
const isDebugging = argv['--debug'];
const output = new Output(process.stderr, { debug: isDebugging });
const isNoColor = argv['--no-color'];
const output = new Output(process.stderr, {
debug: isDebugging,
noColor: isNoColor,
});
debug = output.debug;

View File

@@ -8,6 +8,8 @@ const ARG_COMMON = {
'--debug': Boolean,
'-d': '--debug',
'--no-color': Boolean,
'--token': String,
'-t': '--token',

View File

@@ -0,0 +1,46 @@
import { join } from 'path';
import { isErrnoException } from '@vercel/error-utils';
import { stat, move, remove, rmdir, readdir } from 'fs-extra';
import type { Stats } from 'fs-extra';
/**
* Merge a directory into another directory. A `move` file operation is preferred,
* falling back to a recursive `move` of contents within the source directory.
*/
export async function merge(source: string, destination: string) {
const destStat: Stats | NodeJS.ErrnoException = await stat(destination).catch(
err => err
);
if (isErrnoException(destStat)) {
if (destStat.code === 'ENOENT') {
// Destination does not exist, so move directly
await move(source, destination);
return;
}
// Some other kind of error, bail
throw destStat;
} else if (destStat.isDirectory()) {
// Destination is already a directory, so merge contents recursively
const contents: string[] | NodeJS.ErrnoException = await readdir(
source
).catch(err => err);
if (isErrnoException(contents)) {
// If source is not a directory, then fall through to rm + move
if (contents.code !== 'ENOTDIR') {
// Any other error then bail
throw contents;
}
} else {
await Promise.all(
contents.map(name => merge(join(source, name), join(destination, name)))
);
// Source should be empty at this point
await rmdir(source);
return;
}
}
// Destination is not a directory, or dest is a dir + source is not, so overwrite
await remove(destination);
await move(source, destination);
}

View File

@@ -54,8 +54,12 @@ export async function setMonorepoDefaultSettings(
)} monorepo manager. Attempting to assign default settings.`
);
setCommand('buildCommand', commands.buildCommand);
setCommand('installCommand', commands.installCommand);
if (commands.buildCommand) {
setCommand('buildCommand', commands.buildCommand);
}
if (commands.installCommand) {
setCommand('installCommand', commands.installCommand);
}
if (commands.commandForIgnoringBuildStep) {
setCommand(
'commandForIgnoringBuildStep',

View File

@@ -13,6 +13,7 @@ import {
Builder,
BuildResultV2,
BuildResultV3,
Cron,
File,
FileFsRef,
BuilderV2,
@@ -28,6 +29,7 @@ import {
normalizePath,
} from '@vercel/build-utils';
import pipe from 'promisepipe';
import { merge } from './merge';
import { unzip } from './unzip';
import { VERCEL_DIR } from '../projects/link';
import { fileNameSymbol, VercelConfig } from '@vercel/client';
@@ -39,6 +41,7 @@ export const OUTPUT_DIR = join(VERCEL_DIR, 'output');
* An entry in the "functions" object in `vercel.json`.
*/
interface FunctionConfiguration {
cron?: Cron;
memory?: number;
maxDuration?: number;
}
@@ -369,12 +372,14 @@ async function writeLambda(
throw new Error('Malformed `Lambda` - no "files" present');
}
const cron = functionConfiguration?.cron ?? lambda.cron;
const memory = functionConfiguration?.memory ?? lambda.memory;
const maxDuration = functionConfiguration?.maxDuration ?? lambda.maxDuration;
const config = {
...lambda,
handler: normalizePath(lambda.handler),
cron,
memory,
maxDuration,
type: undefined,
@@ -426,7 +431,7 @@ async function mergeBuilderOutput(
// so no need to do anything
return;
}
await fs.copy(buildResult.buildOutputPath, outputDir);
await merge(buildResult.buildOutputPath, outputDir);
}
/**

View File

@@ -1,5 +1,5 @@
import { lookup as lookupMimeType } from 'mime-types';
import { contentType } from 'mime-types';
export default function getMimeType(fileName: string) {
return lookupMimeType(fileName) || 'application/octet-stream';
return contentType(fileName) || 'application/octet-stream';
}

View File

@@ -1129,10 +1129,10 @@ export default class DevServer {
});
body = `${json}\n`;
} else if (accept.includes('html')) {
res.setHeader('content-type', 'text/html');
res.setHeader('content-type', 'text/html; charset=utf-8');
body = redirectTemplate({ location, statusCode });
} else {
res.setHeader('content-type', 'text/plain');
res.setHeader('content-type', 'text/plain; charset=utf-8');
body = `Redirecting to ${location} (${statusCode})\n`;
}
res.end(body);

View File

@@ -1,4 +1,4 @@
export const emojiLabels = {
const emojiLabels = {
notice: '📝',
tip: '💡',
warning: '❗️',
@@ -8,6 +8,8 @@ export const emojiLabels = {
locked: '🔒',
} as const;
const stripEmojiRegex = new RegExp(Object.values(emojiLabels).join('|'), 'gi');
export type EmojiLabel = keyof typeof emojiLabels;
export function emoji(label: EmojiLabel) {
@@ -21,3 +23,9 @@ export function prependEmoji(message: string, emoji?: string): string {
return message;
}
export function removeEmoji(message: string): string {
const result = message.replace(stripEmojiRegex, '').trimStart();
return result;
}

View File

@@ -5,12 +5,14 @@ import renderLink from './link';
import wait, { StopSpinner } from './wait';
import type { WritableTTY } from '../../types';
import { errorToString } from '@vercel/error-utils';
import { removeEmoji } from '../emoji';
const IS_TEST = process.env.NODE_ENV === 'test';
export interface OutputOptions {
debug?: boolean;
supportsHyperlink?: boolean;
noColor?: boolean;
}
export interface LogOptions {
@@ -25,6 +27,7 @@ export class Output {
stream: WritableTTY;
debugEnabled: boolean;
supportsHyperlink: boolean;
colorDisabled: boolean;
private spinnerMessage: string;
private _spinner: StopSpinner | null;
@@ -33,6 +36,7 @@ export class Output {
{
debug: debugEnabled = false,
supportsHyperlink = detectSupportsHyperlink(stream),
noColor = false,
}: OutputOptions = {}
) {
this.stream = stream;
@@ -40,6 +44,11 @@ export class Output {
this.supportsHyperlink = supportsHyperlink;
this.spinnerMessage = '';
this._spinner = null;
this.colorDisabled = getNoColor(noColor);
if (this.colorDisabled) {
chalk.level = 0;
}
}
isDebugEnabled = () => {
@@ -47,6 +56,9 @@ export class Output {
};
print = (str: string) => {
if (this.colorDisabled) {
str = removeEmoji(str);
}
this.stopSpinner();
this.stream.write(str);
};
@@ -203,3 +215,14 @@ export class Output {
return ansiEscapes.link(chalk.cyan(text), url);
};
}
function getNoColor(noColorArg: boolean | undefined): boolean {
// FORCE_COLOR: the standard supported by chalk https://github.com/chalk/chalk#supportscolor
// NO_COLOR: the standard we want to support https://no-color.org/
// noColorArg: the `--no-color` arg passed to the CLI command
const noColor =
process.env.FORCE_COLOR === '0' ||
process.env.NO_COLOR === '1' ||
noColorArg;
return !!noColor;
}

View File

@@ -686,6 +686,7 @@ test('[vercel dev] should support static files with zero config', async () => {
expect(body).toEqual('bye:user');
res = await fetch(`http://localhost:${port}/`);
expect(res.headers.get('content-type')).toBe('text/html; charset=utf-8');
body = await res.text();
expect(body.startsWith('<h1>goodbye world</h1>')).toBeTruthy();
} finally {

View File

@@ -0,0 +1,11 @@
{
"orgId": ".",
"projectId": ".",
"settings": {
"nodeVersion": "18.x",
"buildCommand": "node build.cjs",
"installCommand": "",
"outputDirectory": "out",
"framework": null
}
}

View File

@@ -0,0 +1,4 @@
const fs = require('fs');
const { join } = require('path');
fs.mkdirSync(join(__dirname , 'out'), { recursive: true });
fs.writeFileSync(join(__dirname , 'out', 'env.json'), JSON.stringify(process.env));

View File

@@ -0,0 +1,7 @@
{
"orgId": ".",
"projectId": ".",
"settings": {
"framework": null
}
}

View File

@@ -0,0 +1,17 @@
export const config = {
runtime: 'edge',
cron: '* * * * *',
};
export default async function edge(request, event) {
const requestBody = await request.text();
return new Response(
JSON.stringify({
headerContentType: request.headers.get('content-type'),
url: request.url,
method: request.method,
body: requestBody,
})
);
}

View File

@@ -0,0 +1,3 @@
export default function (req, res) {
res.json('hello from the edge');
}

View File

@@ -0,0 +1,3 @@
export default function (req, res) {
res.end('serverless says hello');
}

View File

@@ -0,0 +1,7 @@
export default function (req, res) {
res.json({ memory: parseInt(process.env.AWS_LAMBDA_FUNCTION_MEMORY_SIZE) });
}
export const config = {
cron: '* * * * *',
};

View File

@@ -0,0 +1 @@
<h1>Vercel</h1>

View File

@@ -0,0 +1,10 @@
{
"functions": {
"api/overwrite/serverless.js": {
"cron": "0 10-20 * * *"
},
"api/overwrite/edge.js": {
"cron": "10 * * * *"
}
}
}

View File

@@ -132,6 +132,14 @@ export class MockClient extends Client {
setArgv(...argv: string[]) {
this.argv = [process.execPath, 'cli.js', ...argv];
this.output = new Output(this.stderr, {
debug: argv.includes('--debug') || argv.includes('-d'),
noColor: argv.includes('--no-color'),
});
}
resetOutput() {
this.output = new Output(this.stderr);
}
useScenario(scenario: Scenario) {

View File

@@ -1025,6 +1025,27 @@ describe('build', () => {
}
});
it('should set VERCEL_PROJECT_SETTINGS_ environment variables', async () => {
const cwd = fixture('project-settings-env-vars');
const output = join(cwd, '.vercel/output');
try {
process.chdir(cwd);
const exitCode = await build(client);
expect(exitCode).toEqual(0);
const contents = await fs.readJSON(join(output, 'static/env.json'));
expect(contents).toMatchObject({
VERCEL_PROJECT_SETTINGS_BUILD_COMMAND: `node build.cjs`,
VERCEL_PROJECT_SETTINGS_INSTALL_COMMAND: '',
VERCEL_PROJECT_SETTINGS_OUTPUT_DIRECTORY: 'out',
VERCEL_PROJECT_SETTINGS_NODE_VERSION: '18.x',
});
} finally {
process.chdir(originalCwd);
delete process.env.__VERCEL_BUILD_RUNNING;
}
});
it('should apply "images" configuration from `vercel.json`', async () => {
const cwd = fixture('images');
const output = join(cwd, '.vercel/output');
@@ -1081,6 +1102,40 @@ describe('build', () => {
}
});
it('should include crons property in build output', async () => {
const cwd = fixture('with-cron');
const output = join(cwd, '.vercel', 'output', 'functions', 'api');
try {
process.chdir(cwd);
const exitCode = await build(client);
expect(exitCode).toBe(0);
const edge = await fs.readJSON(
join(output, 'edge.func', '.vc-config.json')
);
expect(edge).toHaveProperty('cron', '* * * * *');
const serverless = await fs.readJSON(
join(output, 'serverless.func', '.vc-config.json')
);
expect(serverless).toHaveProperty('cron', '* * * * *');
const overwriteServerless = await fs.readJSON(
join(output, 'overwrite', 'serverless.func', '.vc-config.json')
);
expect(overwriteServerless).toHaveProperty('cron', '0 10-20 * * *');
const overwriteEdge = await fs.readJSON(
join(output, 'overwrite', 'edge.func', '.vc-config.json')
);
expect(overwriteEdge).toHaveProperty('cron', '10 * * * *');
} finally {
process.chdir(originalCwd);
delete process.env.__VERCEL_BUILD_RUNNING;
}
});
describe('should find packages with different main/module/browser keys', function () {
let output: string;
@@ -1229,13 +1284,13 @@ describe('build', () => {
turbo: {
name: 'Turbo',
buildCommand: 'cd ../.. && npx turbo run build --filter=app-1...',
installCommand: 'cd ../.. && yarn install',
ignoreCommand: 'cd ../.. && npx turbo-ignore',
installCommand: 'yarn install',
ignoreCommand: 'npx turbo-ignore',
},
nx: {
name: 'Nx',
buildCommand: 'cd ../.. && npx nx build app-1',
installCommand: 'cd ../.. && yarn install',
installCommand: 'yarn install',
},
// rush: {
// name: 'Rush',

View File

@@ -1,4 +1,5 @@
import login from '../../../src/commands/login';
import { emoji } from '../../../src/util/emoji';
import { client } from '../../mocks/client';
import { useUser } from '../../mocks/user';
@@ -45,5 +46,115 @@ describe('login', () => {
await expect(exitCodePromise).resolves.toEqual(0);
});
it('should allow the `--no-color` flag', async () => {
const user = useUser();
client.setArgv('login', '--no-color');
const exitCodePromise = login(client);
await expect(client.stderr).toOutput(`> Log in to Vercel`);
// Move down to "Email" option
client.stdin.write('\x1B[B'); // Down arrow
client.stdin.write('\x1B[B'); // Down arrow
client.stdin.write('\x1B[B'); // Down arrow
client.stdin.write('\r'); // Return key
await expect(client.stderr).toOutput('> Enter your email address:');
client.stdin.write(`${user.email}\n`);
await expect(client.stderr).toOutput(
`Success! Email authentication complete for ${user.email}`
);
await expect(client.stderr).not.toOutput(emoji('tip'));
await expect(exitCodePromise).resolves.toEqual(0);
});
describe('with NO_COLOR="1" env var', () => {
let previousNoColor: string | undefined;
beforeEach(() => {
previousNoColor = process.env.NO_COLOR;
process.env.NO_COLOR = '1';
});
afterEach(() => {
delete process.env.NO_COLOR;
if (previousNoColor) {
process.env.NO_COLOR = previousNoColor;
}
});
it('should remove emoji the `NO_COLOR` env var with 1', async () => {
client.resetOutput();
const user = useUser();
client.setArgv('login');
const exitCodePromise = login(client);
await expect(client.stderr).toOutput(`> Log in to Vercel`);
// Move down to "Email" option
client.stdin.write('\x1B[B'); // Down arrow
client.stdin.write('\x1B[B'); // Down arrow
client.stdin.write('\x1B[B'); // Down arrow
client.stdin.write('\r'); // Return key
await expect(client.stderr).toOutput('> Enter your email address:');
client.stdin.write(`${user.email}\n`);
await expect(client.stderr).toOutput(
`Success! Email authentication complete for ${user.email}`
);
await expect(client.stderr).not.toOutput(emoji('tip'));
await expect(exitCodePromise).resolves.toEqual(0);
});
});
describe('with FORCE_COLOR="0" env var', () => {
let previousForceColor: string | undefined;
beforeEach(() => {
previousForceColor = process.env.FORCE_COLOR;
process.env.FORCE_COLOR = '0';
});
afterEach(() => {
delete process.env.FORCE_COLOR;
if (previousForceColor) {
process.env.FORCE_COLOR = previousForceColor;
}
});
it('should remove emoji the `FORCE_COLOR` env var with 0', async () => {
client.resetOutput();
const user = useUser();
client.setArgv('login');
const exitCodePromise = login(client);
await expect(client.stderr).toOutput(`> Log in to Vercel`);
// Move down to "Email" option
client.stdin.write('\x1B[B'); // Down arrow
client.stdin.write('\x1B[B'); // Down arrow
client.stdin.write('\x1B[B'); // Down arrow
client.stdin.write('\r'); // Return key
await expect(client.stderr).toOutput('> Enter your email address:');
client.stdin.write(`${user.email}\n`);
await expect(client.stderr).toOutput(
`Success! Email authentication complete for ${user.email}`
);
await expect(client.stderr).not.toOutput(emoji('tip'));
await expect(exitCodePromise).resolves.toEqual(0);
});
});
});
});

View File

@@ -0,0 +1,71 @@
import { tmpdir } from 'os';
import { join } from 'path';
import { writeFile, readdir, mkdirp, stat, remove, readFile } from 'fs-extra';
import { merge } from '../../../../src/util/build/merge';
import { isErrnoException } from '@vercel/error-utils';
describe('merge()', () => {
it('should move source to non-existent destination', async () => {
const source = join(tmpdir(), 'src');
const dest = join(tmpdir(), 'dest');
try {
await mkdirp(source);
await writeFile(join(source, 'a.txt'), 'a');
await merge(source, dest);
const destContents = await readdir(dest);
expect(destContents.sort()).toEqual(['a.txt']);
const sourceStat: Error = await stat(source).then(
() => {},
err => err
);
expect(isErrnoException(sourceStat) && sourceStat.code).toEqual('ENOENT');
} finally {
await Promise.all([source, dest].map(p => remove(p)));
}
});
it('should merge source into existing destination', async () => {
const source = join(tmpdir(), 'src');
const dest = join(tmpdir(), 'dest');
try {
await mkdirp(source);
await mkdirp(dest);
await writeFile(join(source, 'a.txt'), 'a');
await writeFile(join(source, 'c.txt'), 'c');
await writeFile(join(dest, 'b.txt'), 'b');
await writeFile(join(dest, 'c.txt'), 'original');
await merge(source, dest);
const destContents = await readdir(dest);
expect(destContents.sort()).toEqual(['a.txt', 'b.txt', 'c.txt']);
const sourceStat: Error = await stat(source).then(
() => {},
err => err
);
expect(isErrnoException(sourceStat) && sourceStat.code).toEqual('ENOENT');
expect(await readFile(join(dest, 'c.txt'), 'utf8')).toEqual('c');
} finally {
await Promise.all([source, dest].map(p => remove(p)));
}
});
it('should overwrite dest directory when source is a file', async () => {
const source = join(tmpdir(), 'src');
const dest = join(tmpdir(), 'dest');
try {
await mkdirp(source);
await mkdirp(join(dest, 'a'));
await writeFile(join(source, 'a'), 'a');
await merge(source, dest);
const destContents = await readdir(dest);
expect(destContents.sort()).toEqual(['a']);
const sourceStat: Error = await stat(source).then(
() => {},
err => err
);
expect(isErrnoException(sourceStat) && sourceStat.code).toEqual('ENOENT');
expect(await readFile(join(dest, 'a'), 'utf8')).toEqual('a');
} finally {
await Promise.all([source, dest].map(p => remove(p)));
}
});
});

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/client",
"version": "12.3.3",
"version": "12.3.7",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
"homepage": "https://vercel.com",
@@ -43,7 +43,7 @@
]
},
"dependencies": {
"@vercel/build-utils": "6.0.0",
"@vercel/build-utils": "6.2.1",
"@vercel/routing-utils": "2.1.8",
"@zeit/fetch": "5.2.0",
"async-retry": "1.2.3",

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/fs-detectors",
"version": "3.7.6",
"version": "3.7.10",
"description": "Vercel filesystem detectors",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
@@ -35,7 +35,7 @@
"@types/minimatch": "3.0.5",
"@types/node": "14.18.33",
"@types/semver": "7.3.10",
"@vercel/build-utils": "6.0.0",
"@vercel/build-utils": "6.2.1",
"typescript": "4.3.4"
}
}

View File

@@ -21,12 +21,19 @@ export class MissingBuildTarget extends Error {
}
}
type MonorepoDefaultSettings = {
buildCommand?: string | null;
installCommand?: string | null;
commandForIgnoringBuildStep?: string;
monorepoManager: string;
} | null;
export async function getMonorepoDefaultSettings(
projectName: string,
projectPath: string,
relativeToRoot: string,
detectorFilesystem: DetectorFilesystem
) {
): Promise<MonorepoDefaultSettings> {
const [monorepoManager, packageManager] = await Promise.all([
detectFramework({
fs: detectorFilesystem,
@@ -64,11 +71,27 @@ export async function getMonorepoDefaultSettings(
throw new MissingBuildPipeline();
}
if (projectPath === '/') {
return {
monorepoManager: 'turbo',
buildCommand: 'npx turbo run build',
installCommand: packageManager ? `${packageManager} install` : null,
commandForIgnoringBuildStep: 'npx turbo-ignore',
};
}
return {
monorepoManager: 'turbo',
buildCommand: `cd ${relativeToRoot} && npx turbo run build --filter={${projectPath}}...`,
installCommand: `cd ${relativeToRoot} && ${packageManager} install`,
commandForIgnoringBuildStep: `cd ${relativeToRoot} && npx turbo-ignore`,
buildCommand: projectPath
? `cd ${relativeToRoot} && npx turbo run build --filter={${projectPath}}...`
: null,
installCommand:
packageManager === 'npm'
? `${packageManager} install --prefix=${relativeToRoot}`
: packageManager
? `${packageManager} install`
: null,
commandForIgnoringBuildStep: 'npx turbo-ignore',
};
} else if (monorepoManager === 'nx') {
// No ENOENT handling required here since conditional wouldn't be `true` unless `nx.json` was found.
@@ -108,10 +131,24 @@ export async function getMonorepoDefaultSettings(
}
}
if (projectPath === '/') {
return {
monorepoManager: 'nx',
buildCommand: 'npx nx build',
installCommand: packageManager ? `${packageManager} install` : null,
};
}
return {
monorepoManager: 'nx',
buildCommand: `cd ${relativeToRoot} && npx nx build ${projectName}`,
installCommand: `cd ${relativeToRoot} && ${packageManager} install`,
buildCommand: projectName
? `cd ${relativeToRoot} && npx nx build ${projectName}`
: null,
installCommand:
packageManager === 'npm'
? `${packageManager} install --prefix=${relativeToRoot}`
: packageManager
? `${packageManager} install`
: null,
};
}
// TODO (@Ethan-Arrowood) - Revisit rush support when we can test it better

View File

@@ -1,5 +1,5 @@
{
"name": "app-1",
"name": "app-11",
"version": "0.0.1",
"nx": {
"targets": {

View File

@@ -1,5 +1,5 @@
{
"name": "app-1",
"name": "app-10",
"version": "0.0.1",
"nx": {
"targets": {}

View File

@@ -1,5 +1,5 @@
{
"name": "app-1",
"name": "app-9",
"version": "0.0.1",
"nx": {
"targets": {

View File

@@ -1,4 +1,4 @@
{
"name": "app-1",
"name": "app-8",
"version": "0.0.1"
}

View File

@@ -1,4 +1,4 @@
{
"name": "app-1",
"name": "app-12",
"version": "0.0.1"
}

View File

@@ -0,0 +1,16 @@
{
"name": "app-root-proj",
"version": "1.0.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "app-root-proj",
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"next": "1.2.3"
}
}
}
}

View File

@@ -0,0 +1,5 @@
{
"dependencies": {
"next": "1.2.3"
}
}

View File

@@ -0,0 +1,19 @@
{
"$schema": "https://turborepo.org/schema.json",
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": [".next/**"]
},
"test": {
"dependsOn": ["^build"],
"outputs": []
},
"lint": {
"outputs": []
},
"dev": {
"cache": false
}
}
}

View File

@@ -0,0 +1 @@
{}

View File

@@ -0,0 +1,9 @@
{
"private": true,
"workspaces": [
"packages/*"
],
"devDependencies": {
"turbo": "1.6.3"
}
}

View File

@@ -0,0 +1,4 @@
{
"name": "app-15",
"version": "0.0.1"
}

View File

@@ -0,0 +1 @@
{ "pipeline": { "build": { "dependsOn": ["^build"], "outputs": ["dist/**"] } } }

View File

@@ -1,4 +1,4 @@
{
"name": "app-1",
"name": "app-13",
"version": "0.0.1"
}

View File

@@ -1,4 +1,4 @@
{
"name": "app-1",
"name": "app-14",
"version": "0.0.1"
}

View File

@@ -26,40 +26,56 @@ describe('getMonorepoDefaultSettings', () => {
});
test.each([
['turbo', 'turbo'],
['turbo-package-config', 'turbo'],
['nx', 'nx'],
['nx-package-config', 'nx'],
['nx-project-and-package-config-1', 'nx'],
['nx-project-and-package-config-2', 'nx'],
['nx-project-config', 'nx'],
])('fixture %s', async (fixture, expectedResultKey) => {
const expectedResultMap: Record<string, Record<string, string>> = {
turbo: {
monorepoManager: 'turbo',
buildCommand:
'cd ../.. && npx turbo run build --filter={packages/app-1}...',
installCommand: 'cd ../.. && yarn install',
commandForIgnoringBuildStep: 'cd ../.. && npx turbo-ignore',
},
nx: {
monorepoManager: 'nx',
buildCommand: 'cd ../.. && npx nx build app-1',
installCommand: 'cd ../.. && yarn install',
},
};
['turbo', 'turbo', false, 'app-14', false],
['turbo-package-config', 'turbo', false, 'app-13', false],
['turbo-npm', 'turbo', true, 'app-15', false],
['turbo-npm-root-proj', 'turbo', true, 'app-root-proj', true],
['nx', 'nx', false, 'app-12', false],
['nx-package-config', 'nx', false, 'app-11', false],
['nx-project-and-package-config-1', 'nx', false, 'app-10', false],
['nx-project-and-package-config-2', 'nx', false, 'app-9', false],
['nx-project-config', 'nx', false, 'app-8', false],
])(
'fixture %s',
async (fixture, expectedResultKey, isNpm, packageName, isRoot) => {
const expectedResultMap: Record<string, Record<string, string>> = {
turbo: {
monorepoManager: 'turbo',
buildCommand: isRoot
? 'npx turbo run build'
: 'cd ../.. && npx turbo run build --filter={packages/app-1}...',
installCommand:
isNpm && isRoot
? 'npm install'
: isNpm
? 'npm install --prefix=../..'
: 'yarn install',
commandForIgnoringBuildStep: 'npx turbo-ignore',
},
nx: {
monorepoManager: 'nx',
buildCommand: `cd ../.. && npx nx build ${packageName}`,
installCommand: 'yarn install',
},
};
const ffs = new FixtureFilesystem(
path.join(__dirname, 'fixtures', 'get-monorepo-default-settings', fixture)
);
const result = await getMonorepoDefaultSettings(
'app-1',
'packages/app-1',
'../..',
ffs
);
expect(result).toStrictEqual(expectedResultMap[expectedResultKey]);
});
const ffs = new FixtureFilesystem(
path.join(
__dirname,
'fixtures',
'get-monorepo-default-settings',
fixture
)
);
const result = await getMonorepoDefaultSettings(
packageName,
isRoot ? '/' : 'packages/app-1',
isRoot ? '/' : '../..',
ffs
);
expect(result).toStrictEqual(expectedResultMap[expectedResultKey]);
}
);
test('returns null when neither nx nor turbo is detected', async () => {
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'monorepo-test-'));

View File

@@ -1,28 +1,15 @@
import path from 'path';
import type { GatsbyNode } from 'gatsby';
// this gets built separately, so import from "dist" instead of "src"
import { generateVercelBuildOutputAPI3Output } from './dist';
export const pluginOptionsSchema: GatsbyNode['pluginOptionsSchema'] = ({
Joi,
export const onPostBuild: GatsbyNode['onPostBuild'] = async ({
pathPrefix,
store,
}) => {
return Joi.object({
exportPath: Joi.string().optional(),
});
};
export const onPostBuild: GatsbyNode['onPostBuild'] = async (
{ store },
pluginOptions
) => {
// validated by `pluginOptionSchema`
const exportPath = (pluginOptions?.exportPath ??
path.join('.vercel', 'output', 'config.json')) as string;
await generateVercelBuildOutputAPI3Output({
exportPath,
pathPrefix,
// validated by `pluginOptionSchema`
gatsbyStoreState: store.getState(),
});
};

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/gatsby-plugin-vercel-builder",
"version": "1.0.1",
"version": "1.1.2",
"main": "dist/index.js",
"files": [
"dist",
@@ -14,11 +14,11 @@
"build:src": "tsc -p tsconfig.src.json"
},
"dependencies": {
"@vercel/build-utils": "6.0.0",
"@vercel/node": "2.8.16",
"@vercel/build-utils": "6.2.1",
"@vercel/node": "2.9.2",
"@vercel/routing-utils": "2.1.8",
"ajv": "8.12.0",
"esbuild": "0.16.17",
"esbuild": "0.14.47",
"etag": "1.8.1",
"fs-extra": "11.1.0"
},

View File

@@ -1,5 +1,4 @@
import { join } from 'path';
import { getNodeVersion } from '@vercel/build-utils';
import { build } from 'esbuild';
import {
@@ -10,7 +9,6 @@ import {
writeFileSync,
ensureFileSync,
} from 'fs-extra';
import type {
NodejsServerlessFunctionConfig,
PrerenderFunctionConfig,
@@ -29,7 +27,7 @@ export const writeHandler = async ({
return await build({
entryPoints: [handlerFile],
loader: { '.ts': 'ts' },
outfile: join(outDir, './index.js'),
outfile: join(outDir, 'index.js'),
format: 'cjs',
target: `node${major}`,
platform: 'node',
@@ -60,7 +58,8 @@ export const writeVCConfig = async ({
shouldAddHelpers: true,
};
return writeJson(`${functionDir}/.vc-config.json`, config);
const configPath = join(functionDir, '.vc-config.json');
await writeJson(configPath, config);
};
export const writePrerenderConfig = (outputPath: string, group: number) => {
@@ -88,10 +87,6 @@ export async function copyFunctionLibs({
src: join('.cache', 'page-ssr'),
dest: join(functionDir, '.cache', 'page-ssr'),
},
// {
// src: join(functionDir, '.cache', 'query-engine', 'assets'),
// dest: join(functionDir, 'assets'),
// },
{
src: join('.cache', 'data', 'datastore'),
dest: join(functionDir, '.cache', 'data', 'datastore'),

View File

@@ -1,7 +1,8 @@
import { join } from 'path';
import { copy, ensureDir } from 'fs-extra';
import { join, dirname } from 'path';
import { copy, move, ensureDir } from 'fs-extra';
export async function createStaticDir(prefix?: string) {
const publicDir = join(process.cwd(), 'public');
const targetDir = join(
process.cwd(),
'.vercel',
@@ -9,6 +10,14 @@ export async function createStaticDir(prefix?: string) {
'static',
prefix ?? ''
);
await ensureDir(targetDir);
await copy(join(process.cwd(), 'public'), targetDir);
await ensureDir(dirname(targetDir));
try {
await move(publicDir, targetDir);
} catch (err: any) {
console.error(
`Failed to move "public" dir from "${publicDir}" to "${targetDir}". Copying instead.`,
err
);
await copy(publicDir, targetDir);
}
}

View File

@@ -1,6 +1,5 @@
import { join } from 'path';
import { getTransformedRoutes } from '@vercel/routing-utils';
import { writeJson, remove } from 'fs-extra';
import { writeJson } from 'fs-extra';
import { validateGatsbyState } from './schemas';
import {
createServerlessFunctions,
@@ -10,17 +9,17 @@ import { createStaticDir } from './helpers/static';
import type { Config } from './types';
export interface GenerateVercelBuildOutputAPI3OutputOptions {
exportPath: string;
pathPrefix: string;
gatsbyStoreState: {
pages: Map<string, unknown>;
redirects: unknown;
functions: unknown;
config: unknown;
};
[x: string]: unknown;
}
export async function generateVercelBuildOutputAPI3Output({
exportPath,
pathPrefix,
gatsbyStoreState,
}: GenerateVercelBuildOutputAPI3OutputOptions) {
const state = {
@@ -32,7 +31,6 @@ export async function generateVercelBuildOutputAPI3Output({
if (validateGatsbyState(state)) {
console.log('▲ Creating Vercel build output');
await remove(join('.vercel', 'output'));
const { pages, redirects, functions, config: gatsbyConfig } = state;
@@ -40,18 +38,21 @@ export async function generateVercelBuildOutputAPI3Output({
.map(p => p[1])
.filter(page => page.mode === 'SSR' || page.mode === 'DSG');
const ops: Promise<void>[] = [createStaticDir(gatsbyConfig.pathPrefix)];
const ops: Promise<void>[] = [];
if (functions.length > 0) {
ops.push(createAPIRoutes(functions, gatsbyConfig.pathPrefix));
ops.push(createAPIRoutes(functions, pathPrefix));
}
if (ssrRoutes.length > 0) {
ops.push(createServerlessFunctions(ssrRoutes, gatsbyConfig.pathPrefix));
ops.push(createServerlessFunctions(ssrRoutes, pathPrefix));
}
await Promise.all(ops);
// "static" directory needs to happen last since it moves "public"
await createStaticDir(pathPrefix);
let trailingSlash: boolean | undefined = undefined;
if (gatsbyConfig.trailingSlash === 'always') {
trailingSlash = true;
@@ -73,7 +74,7 @@ export async function generateVercelBuildOutputAPI3Output({
routes: routes || undefined,
};
await writeJson(exportPath, config);
await writeJson('.vercel/output/config.json', config);
console.log('Vercel output has been generated');
} else {
throw new Error(

View File

@@ -55,10 +55,7 @@ const GatsbyRedirectSchema: JSONSchemaType<GatsbyRedirect> = {
required: ['fromPath', 'toPath'],
} as const;
export type GatsbyConfig = Pick<
IGatsbyConfig,
'trailingSlash' | 'assetPrefix' | 'pathPrefix'
>;
export type GatsbyConfig = Pick<IGatsbyConfig, 'trailingSlash'>;
const GatsbyConfigSchema: JSONSchemaType<GatsbyConfig> = {
type: 'object',
@@ -68,14 +65,6 @@ const GatsbyConfigSchema: JSONSchemaType<GatsbyConfig> = {
enum: ['always', 'never', 'ignore', 'legacy'],
nullable: true,
},
assetPrefix: {
type: 'string',
nullable: true,
},
pathPrefix: {
type: 'string',
nullable: true,
},
},
} as const;

View File

@@ -6,6 +6,7 @@ import { join, delimiter } from 'path';
import stringArgv from 'string-argv';
import { debug } from '@vercel/build-utils';
const versionMap = new Map([
['1.19', '1.19.5'],
['1.18', '1.18.1'],
['1.17', '1.17.3'],
['1.16', '1.16.10'],

View File

@@ -1,7 +1,7 @@
import execa from 'execa';
import retry from 'async-retry';
import { homedir, tmpdir } from 'os';
import { spawn, spawnSync } from 'child_process';
import { execFileSync, spawn } from 'child_process';
import { Readable } from 'stream';
import once from '@tootallnate/once';
import { join, dirname, basename, normalize, sep } from 'path';
@@ -694,9 +694,10 @@ Learn more: https://vercel.com/docs/runtimes#official-runtimes/go`
}`;
debug(`SPAWNING go build -o ${executable} ./... CWD=${tmp}`);
spawnSync('go', ['build', '-o', executable, './...'], {
execFileSync('go', ['build', '-o', executable, './...'], {
cwd: tmp,
env,
stdio: 'inherit',
});
debug(`SPAWNING ${executable} CWD=${tmp}`);

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/go",
"version": "2.2.31",
"version": "2.3.3",
"license": "MIT",
"main": "./dist/index",
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/go",
@@ -36,7 +36,7 @@
"@types/node": "14.18.33",
"@types/node-fetch": "^2.3.0",
"@types/tar": "^4.0.0",
"@vercel/build-utils": "6.0.0",
"@vercel/build-utils": "6.2.1",
"@vercel/ncc": "0.24.0",
"async-retry": "1.3.1",
"execa": "^1.0.0",

View File

@@ -5,10 +5,10 @@
{ "src": "subdirectory/index.go", "use": "@vercel/go" }
],
"probes": [
{ "path": "/", "mustContain": "cow:go1.18.1:RANDOMNESS_PLACEHOLDER" },
{ "path": "/", "mustContain": "cow:go1.19.5:RANDOMNESS_PLACEHOLDER" },
{
"path": "/subdirectory",
"mustContain": "subcow:go1.18.1:RANDOMNESS_PLACEHOLDER"
"mustContain": "subcow:go1.19.5:RANDOMNESS_PLACEHOLDER"
}
]
}

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/hydrogen",
"version": "0.0.45",
"version": "0.0.49",
"license": "MIT",
"main": "./dist/index.js",
"homepage": "https://vercel.com/docs",
@@ -21,8 +21,8 @@
"devDependencies": {
"@types/jest": "27.5.1",
"@types/node": "14.18.33",
"@vercel/build-utils": "6.0.0",
"@vercel/static-config": "2.0.11",
"@vercel/build-utils": "6.2.1",
"@vercel/static-config": "2.0.12",
"execa": "3.2.0",
"fs-extra": "11.1.0",
"ts-morph": "12.0.0",

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/next",
"version": "3.3.19",
"version": "3.4.1",
"license": "MIT",
"main": "./dist/index",
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/next-js",
@@ -45,7 +45,7 @@
"@types/semver": "6.0.0",
"@types/text-table": "0.2.1",
"@types/webpack-sources": "3.2.0",
"@vercel/build-utils": "6.0.0",
"@vercel/build-utils": "6.2.1",
"@vercel/nft": "0.22.5",
"@vercel/routing-utils": "2.1.8",
"async-sema": "3.0.1",

View File

@@ -873,6 +873,7 @@ export async function serverBuild({
runtime: nodeVersion.runtime,
maxDuration: group.maxDuration,
isStreaming: group.isStreaming,
cron: group.cron,
});
for (const page of group.pages) {
@@ -967,6 +968,7 @@ export async function serverBuild({
});
const middleware = await getMiddlewareBundle({
config,
entryPath,
outputDirectory,
routesManifest,

View File

@@ -15,6 +15,7 @@ import {
NodejsLambda,
EdgeFunction,
Images,
Cron,
} from '@vercel/build-utils';
import { NodeFileTraceReasons } from '@vercel/nft';
import type {
@@ -1308,6 +1309,7 @@ export function addLocaleOrDefault(
export type LambdaGroup = {
pages: string[];
memory?: number;
cron?: Cron;
maxDuration?: number;
isStreaming?: boolean;
isPrerenders?: boolean;
@@ -1360,7 +1362,7 @@ export async function getPageLambdaGroups({
const routeName = normalizePage(page.replace(/\.js$/, ''));
const isPrerenderRoute = prerenderRoutes.has(routeName);
let opts: { memory?: number; maxDuration?: number } = {};
let opts: { memory?: number; maxDuration?: number; cron?: Cron } = {};
if (config && config.functions) {
const sourceFile = await getSourceFilePathFromPage({
@@ -1378,7 +1380,8 @@ export async function getPageLambdaGroups({
const matches =
group.maxDuration === opts.maxDuration &&
group.memory === opts.memory &&
group.isPrerenders === isPrerenderRoute;
group.isPrerenders === isPrerenderRoute &&
!opts.cron; // Functions with a cronjob must be on their own
if (matches) {
let newTracedFilesSize = group.pseudoLayerBytes;
@@ -2311,12 +2314,14 @@ interface EdgeFunctionMatcher {
}
export async function getMiddlewareBundle({
config = {},
entryPath,
outputDirectory,
routesManifest,
isCorrectMiddlewareOrder,
prerenderBypassToken,
}: {
config: Config;
entryPath: string;
outputDirectory: string;
prerenderBypassToken: string;
@@ -2372,6 +2377,21 @@ export async function getMiddlewareBundle({
edgeFunction.wasm
);
const edgeFunctionOptions: { cron?: Cron } = {};
if (config.functions) {
const sourceFile = await getSourceFilePathFromPage({
workPath: entryPath,
page: `${edgeFunction.page}.js`,
});
const opts = await getLambdaOptionsFromFunction({
sourceFile,
config,
});
edgeFunctionOptions.cron = opts.cron;
}
return {
type,
page: edgeFunction.page,
@@ -2416,6 +2436,7 @@ export async function getMiddlewareBundle({
);
return new EdgeFunction({
...edgeFunctionOptions,
deploymentTarget: 'v8-worker',
name: edgeFunction.name,
files: {

View File

@@ -0,0 +1,44 @@
const path = require('node:path');
const fs = require('fs-extra');
const { build } = require('../../dist');
function getFixture(name) {
return path.join(__dirname, 'fixtures', name);
}
const initialCorepackValue = process.env.COREPACK_ENABLE_STRICT;
beforeEach(() => {
process.env.COREPACK_ENABLE_STRICT = '0';
});
afterEach(() => {
process.env.COREPACK_ENABLE_STRICT = initialCorepackValue;
});
it('should include cron property from config', async () => {
const cwd = getFixture('03-with-api-routes');
await fs.remove(path.join(cwd, '.next'));
const result = await build({
workPath: cwd,
repoRootPath: cwd,
entrypoint: 'package.json',
config: {
functions: {
'pages/api/edge.js': {
cron: '* * * * *',
},
'pages/api/serverless.js': {
cron: '* * * * *',
},
},
},
meta: {
skipDownload: true,
},
});
expect(result.output['api/serverless']).toHaveProperty('cron', '* * * * *');
expect(result.output['api/edge']).toHaveProperty('cron', '* * * * *');
});

View File

@@ -0,0 +1,2 @@
.vercel
node_modules

View File

@@ -0,0 +1,5 @@
module.exports = {
generateBuildId() {
return 'testing-build-id';
},
};

View File

@@ -0,0 +1,13 @@
{
"name": "03-with-api-routes",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build"
},
"dependencies": {
"next": "latest",
"react": "latest",
"react-dom": "latest"
}
}

Some files were not shown because too many files have changed in this diff Show More