Compare commits

..

46 Commits

Author SHA1 Message Date
Vercel Release Bot
7582571d94 Version Packages (#10913)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-12-11 10:39:34 -06:00
John Pham
e6aaf79d04 Update Next.js screenshot preview (#10921)
This new screenshot matches the template. It removes the version number
so this screenshot will not go stale.
2023-12-08 11:25:42 -08:00
Ethan Arrowood
a1df25a197 [cli] Clean up project ls --deprecate (#10926)
Follow up to #10919

Removes console.log statements and changes log into warning.
2023-12-08 17:55:24 +00:00
Ethan Arrowood
dfe47f6e6c [cli] add --deprecated option to vc project ls command (#10919)
Adds a `--deprecated` option to the `vc project ls` command that will only show projects currently running on a soon-to-be-deprecated Node.js version.

It also adds additional output providing more information to the user about what versions and a link to our documentation so they can learn more.

Example:

<img width="836" alt="Screenshot 2023-12-07 at 15 01 22" src="https://github.com/vercel/vercel/assets/16144158/3b7f7b13-802e-4af1-a76e-a158a477beb4">
2023-12-08 17:09:18 +00:00
Vercel Release Bot
3a58431695 [examples][tests] Upgrade Next.js to version 14.0.4 (#10923)
This auto-generated PR updates 7 packages to Next.js version 14.0.4
2023-12-08 11:17:39 +01:00
Vercel Release Bot
204c3592c7 [remix] Update @remix-run/dev to v2.3.1 (#10908)
This auto-generated PR updates `@remix-run/dev` to version 2.3.1.
2023-12-07 01:29:54 +00:00
Nathan Rajlich
3cede43ca7 [ruby] Remove VERCEL_ALLOW_RUBY32 env var check (#10910) 2023-12-07 01:28:17 +00:00
Nathan Rajlich
1dbb22bb6d [ruby] Use Ruby 3.2 in test fixtures (#10909) 2023-12-07 00:57:10 +00:00
Matt Straka
f124779b35 Update README.md (#10898) 2023-12-02 14:23:03 -05:00
Vercel Release Bot
371c7a08f2 Version Packages (#10896) 2023-12-01 11:43:49 -08:00
Ethan Arrowood
447c20fb99 Add GitHub Runner Image Version to turbo-cache-key.json (#10887)
Add GitHub Runner Image Version to turbo-cache-key.json
2023-12-01 19:39:07 +00:00
Nathan Rajlich
0fe8c07194 [cli] Revert "forbids globally installed @vercel/speed-insights and @vercel/analytics (#10848)" (#10895)
This reverts commit 6afdd7fb0b.
2023-12-01 19:35:04 +00:00
Vercel Release Bot
78d1d548d9 Version Packages (#10865) 2023-11-30 11:01:27 -08:00
Trek Glowacki
c41ff450c0 [cli] Fix behavior for combination of northstar user + team scope provided to cli as an argument. (#10884)
Fixes a neat little bug with the intersection of northstar users, teams, and the behavior of `Array#find_index`:

When selecting an org for various cli actions _non_ northstar users will see a select list with their user in the 0th position, and their teams in the 1..nth positions, like so:

```
// user: Logan
// teams: [Avengers, X-Men]
○ Logan
○ Avengers
○ X-Men
``` 

We'd like to preselect either a team referenced in `client.config.currentTeam` or if said team cannot be found in the collection of a user's teams, preselect the user. So if `X-Men` is `currentTeam`, we find that item (element `1` in the teams array) and increment that value by `1` to account for the user being element `0` in the list of choices:

```
// currentTeam: X-Men
// user: Logan
// teams: [Avengers, X-Men]
○ Logan
○ Avengers
● X-Men
``` 

If we _can't_ find the `currentTeam` in the list of teams (or one isn't provided), `Array#find_index` returns `-1`, which we increment to by `1` to get the 0th element in the list of choices:

```
// currentTeam: undefined
// user: Logan
// teams: [Avengers, X-Men]
● Logan
○ Avengers
○ X-Men
``` 

Neat trick!

However, Northstar users _don't_ use the user account as the 0th element in the list of choices. Northstar users will in fact have a team that represents a hidden default team with the same name as their `user.name` and this will be the 0th element in their teams:

```
// user: Logan
// teams: [Logan, Avengers, X-Men]
○ Logan
○ Avengers
○ X-Men
``` 

This of course means the trick of `+1` to index of the team selects the wrong item _and_ can result in `undefined` in cases where the `currentTeam` references the last team.

```
// currentTeam: X-Men
// user: Logan
// teams: [Logan, Avengers, X-Men]
○ Logan
○ Avengers
○ X-Men
``` 

● how'd we get out here?!?! 👀 

To address the issue this PR:
1. calls `findIndex` on the array of _choices_ checking for matches to `currentTeam`
2. wraps that in `Math.max` to set to `0` if `find_index` returns `-1` when a `currentTeam` can't be found.
2023-11-29 14:15:17 +00:00
Chris Barber
ca2cbf06fb [remix] Resolve static dir using non-parent publicPath segments (#10685) 2023-11-28 17:22:36 -06:00
Trek Glowacki
2d86a2d4ba [tests] tidy and make select-org tests more realistic (#10882)
Tracking down a bug with "northstar" users and have a little prefactor that 

a) isolates setup code so it's less repeated
b) makes the "northstar" tests more reflective of actual execution.

Northstar users will always have a `currentTeam` value on their `client.config`:

aa0f3d712b/packages/cli/src/util/get-scope.ts (L18-L20)

And finally c) add tests for the case of a non-northstar users where a team scope is supplied.

The final hypothetical matching group (northstart users with team scope provided) is the bug that I'll fix with a refactor.
2023-11-28 23:21:32 +00:00
Nathan Rajlich
4edfcd74b6 [remix] Fix issue where npm install was not properly injecting forked compiler (#10819)
User reported a scenario in which npm was ignoring the second `npm install` command to replace the Remix compiler with our forked version. This seems like a bug in npm. Workaround that seems to work is to remove `@remix-run/dev` entirely and install our forked version as a "standard" dependency (instead of using the `npm:` syntax). The `bin` entry for `remix` should at that point be our forked compiler.
2023-11-28 22:41:39 +00:00
Nathan Rajlich
c52bdf7758 [go] Set Lambda runtime to "provided.al2" behind env var (#10880)
This is a re-land of https://github.com/vercel/vercel/pull/10856, but with the addition of the env var check so that we can feature flag this change.
2023-11-28 22:38:37 +00:00
Nathan Rajlich
bc5ac1ec50 [static-build] Add yarn.lock and force jsdom@22 to fix "umi-v2" test fixture (#10881)
`jsdom@23` does not work with Node 16, but UmiJS v2 does not work with Node 18. So use the lower common denominator and force a older version of jsdom that still works with 16.x.
2023-11-28 18:49:02 +00:00
Lee Robinson
aa0f3d712b chore: update Nuxt example (#10869)
This updates the default Nuxt example to start with a static route, plus
updates dependencies with the latest version.

Demo: https://nuxt-vercel-inky.vercel.app/

---------

Co-authored-by: Trek Glowacki <trek.glowacki@vercel.com>
2023-11-27 19:40:30 -06:00
Csaba Palfi
e02212ae80 Fix changeset lint for forks (#10737) 2023-11-27 16:38:02 -08:00
Lee Robinson
a8934da623 Update placeholder for Nuxt to be correct command. (#10873)
Co-authored-by: Trek Glowacki <trek.glowacki@vercel.com>
2023-11-27 10:54:49 -06:00
Vercel Release Bot
0e9bb30fd2 [tests] Update Gatsby fixture versions (#10875)
Automatically generated PR to update Gatsby fixture versions in `@vercel/static-build`
2023-11-27 14:56:18 +00:00
Damien Simonin Feugas
6afdd7fb0b [cli] forbids globally installed @vercel/speed-insights and @vercel/analytics (#10848) 2023-11-22 09:29:40 +01:00
Vercel Release Bot
fdef0339f2 Version Packages (#10861) 2023-11-21 13:59:05 -08:00
Nathan Rajlich
4636ae54c6 [ruby] Enable ruby3.2 runtime (#10859)
Allows for Ruby 3.2 Serverless Functions to be created.

**Note:** New test fixtures will be added after this is deployed to production.
2023-11-21 21:57:23 +00:00
Nathan Rajlich
61a23f1382 Revert "[go] Set Lambda runtime to provided.al2" (#10864)
This reverts commit 4b8b4992c4.

We'll re-land this after Thanksgiving.
2023-11-21 21:13:24 +00:00
Nathan Rajlich
4b8b4992c4 [go] Set Lambda runtime to "provided.al2" (#10856)
Migrate from the deprecated `go1.x` runtime to the `provided.al2` runtime, [as suggested by AWS in their migration guide](https://aws.amazon.com/blogs/compute/migrating-aws-lambda-functions-from-the-go1-x-runtime-to-the-custom-runtime-on-amazon-linux-2/).
2023-11-21 19:29:53 +00:00
Zack Tanner
611fbdd5ac Revert "[cli][tests] Work around Yarn + Corepack issue in tests" (#10860) 2023-11-21 10:21:56 -06:00
Zack Tanner
ffd2f34c6c [next] ensure function configs apply to route groups (#10855)
`getSourceFilePathFromPage` attempts to match patterns found in `vercel.json` with source files. However, the `page` argument to this function is stripped of route groups, so these files are erroneously skipped and function settings are not applied. 

For app-dir routes which might contain route groups, this checks an internal mapping which maps the "normalized" paths (e.g. `app/dashboard/[slug]/page.js`) to the file-system path (e.g. `app/dashboard/[slug]/(group)/page.js`)
2023-11-21 00:44:46 +00:00
Nathan Rajlich
8feaa9c3b3 [cli][tests] Work around Yarn + Corepack issue in tests (#10858)
CI started failing on corepack related tests with error:

```
error This project's package.json defines "packageManager": "yarn@npm@8.1.0". However the current global version of Yarn is 1.22.21.
```

This appears to be a bug in the Yarn v1.22.21, which was released a week ago: https://github.com/yarnpkg/yarn/releases/tag/v1.22.21

Setting the `SKIP_YARN_COREPACK_CHECK` env var disables this new check which fixes the issue for us.

**NOTE:** Review with [whitespace changes disabled](https://github.com/vercel/vercel/pull/10858/files?w=1) for an easier view.
2023-11-20 21:47:39 +00:00
Vercel Release Bot
31daff66af [examples][tests] Upgrade Next.js to version 14.0.3 (#10847) 2023-11-19 10:54:04 -08:00
Simon H
48c6b2dcc3 [docs] mention nodejs20.x in LambdaRuntime (#10849)
The error message when trying to deploy with an invalid runtime value
leads you there, where `nodejs20.x` is missing currently
2023-11-18 22:43:16 -06:00
Vercel Release Bot
6f3ae1a0ed Version Packages (#10836)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-11-15 23:19:35 -06:00
Nathan Rajlich
88da7463ce [build-utils] Remove Node v20 env var check (#10834)
It's safe to remove this env var check, because #10822 makes it explicit on which versions of Node are actually present in the build environment.
2023-11-15 22:04:36 +00:00
Ethan Arrowood
142aa55a5d Add .node-version file (#10820)
This a small QOL change. Essentially if you have a tool like `fnm` on your machine for using multiple versions of Node.js, they will look for files like this one and automatically switch your terminal session node version to the value in it. 

The `vercel/front` repo uses this too
2023-11-15 20:12:05 +00:00
Vercel Release Bot
7bc8b65d13 Version Packages (#10832)
This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.


# Releases
## @vercel/build-utils@7.2.4

### Patch Changes

-   Select Node.js version based on what's available in build-container ([#10822](https://github.com/vercel/vercel/pull/10822))

## vercel@32.5.4

### Patch Changes

-   Updated dependencies \[[`65dec5b7e`](65dec5b7e7)]:
    -   @vercel/build-utils@7.2.4
    -   @vercel/node@3.0.10
    -   @vercel/static-build@2.0.11

## @vercel/client@13.0.8

### Patch Changes

-   Updated dependencies \[[`65dec5b7e`](65dec5b7e7)]:
    -   @vercel/build-utils@7.2.4

## @vercel/gatsby-plugin-vercel-builder@2.0.10

### Patch Changes

-   Updated dependencies \[[`65dec5b7e`](65dec5b7e7)]:
    -   @vercel/build-utils@7.2.4

## @vercel/node@3.0.10

### Patch Changes

-   Updated dependencies \[[`65dec5b7e`](65dec5b7e7)]:
    -   @vercel/build-utils@7.2.4

## @vercel/static-build@2.0.11

### Patch Changes

-   Updated dependencies \[]:
    -   @vercel/gatsby-plugin-vercel-builder@2.0.10

## @vercel-internals/types@1.0.15

### Patch Changes

-   Updated dependencies \[[`65dec5b7e`](65dec5b7e7)]:
    -   @vercel/build-utils@7.2.4
2023-11-15 00:45:19 +00:00
Nathan Rajlich
65dec5b7e7 [build-utils] Select Node.js version based on what's available in build-container (#10822)
Makes `getLatestNodeVersion()` and `getSupportedNodeVersion()` (and thus by extension - `getNodeVersion()`) be aware of the available Node.js versions when running inside the build-container. This is to address the situation with the new AL2023 build-container image which has different Node versions installed compared to the existing AL2 build image.

### Project Settings `20.x` with package.json `"engines": "18.x"`

If the Project Settings Node Version is set to `20.x`, but the package.json has `"engines": "18.x"`, then the build will fail like so, because Node 18 is not present on the AL2023 build image:

<img width="1044" alt="Screenshot 2023-11-09 at 1 25 41 PM" src="https://github.com/vercel/vercel/assets/71256/572c544b-6574-4eb1-98f7-787075a60000">

### Project Settings `18.x` with package.json `"engines": "20.x"`

If the Project Settings Node Version is set to `18.x`, but the package.json has `"engines": "20.x"`, then the build will fail like so, because Node 20 is not present on the AL2 build image:

<img width="1042" alt="Screenshot 2023-11-09 at 1 34 43 PM" src="https://github.com/vercel/vercel/assets/71256/c6a2d955-9453-4ef5-a99d-b49a6d9af766">

### Project Settings `18.x` with no package.json `"engines"`

If Project Settings Node Version is set to `18.x`, but the package.json has no "engines" (and thus wants "latest"), then the latest available Node version in the build-container, which would be Node 18.
2023-11-14 23:08:27 +00:00
Brooks Lybrand
f3b62d8ea2 chore: Update Remix example README (#10830)
Not sure the best spot to put this command in the Readme, but I thought having a `create-remix` command might be useful for people trying to get going.

If there's a more preferred way to scaffold this project on your machine, I'm open to that, just using what I know
2023-11-13 20:10:57 +00:00
Wyatt Johnson
9472c22bf7 [next] Added more PPR tests (#10823)
This adds additional regression tests for PPR support for Next.js.
2023-11-09 23:45:35 +00:00
Vercel Release Bot
493185709a Version Packages (#10809)
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and the packages will
be published to npm automatically. If you're not ready to do a release
yet, that's fine, whenever you add more changesets to main, this PR will
be updated.


# Releases
## vercel@32.5.3

### Patch Changes

- Handle `TooManyProjects` error in places where projects are created
([#10807](https://github.com/vercel/vercel/pull/10807))

- Updated dependencies
\[[`89c1e0323`](89c1e03233),
[`fd29b966d`](fd29b966d3)]:
    -   @vercel/node@3.0.9
    -   @vercel/next@4.0.14

## @vercel/next@4.0.14

### Patch Changes

- Fixed headers for static routes when PPR is enabled
([#10808](https://github.com/vercel/vercel/pull/10808))

## @vercel/node@3.0.9

### Patch Changes

- Replace usage of `fetch` with `undici.request`
([#10767](https://github.com/vercel/vercel/pull/10767))

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-11-08 10:36:37 -07:00
Ethan Arrowood
89c1e03233 [node] swap undici.fetch for undici.request in serverless-handler.mts (#10767)
In a recent undici update, setting the `host` header for fetch requests became invalid (https://github.com/nodejs/undici/pull/2322). 

We relied on this in order to proxy serverless dev server requests via `@vercel/node`. 

This PR replaces the usage of `undici.fetch` with `undici.request`. 

It is blocked by an `undici` type change: https://github.com/nodejs/undici/pull/2373
2023-11-08 17:31:03 +00:00
Zach Ward
ebd7e3ac39 Project limits error handling (#10807)
This PR adds improved error handling for the 200 project limit error
that will start being returned for free tier teams/accounts. The
following changes have been made:
- improve error message format by using `client.output.prettyError` so
that the docs link
(https://vercel.com/docs/limits/overview#general-limits) returned with
the error response is included with the error message
- add explicit error handling of this error from any places where
`createProject` is called, which includes the following commands:
  - `vc project add`
  - `vc link` (indirectly called via `ensureLink`)
  - `vc list` (indirectly called via `ensureLink`)
  - `vc git connect` (indirectly called via `ensureLink`)

### Testing
- sign in to a vercel account that is associated with your work email
(ends in `@vercel.com`), this is necessary for creating a team with the
proper conditions to artificially trigger the error message
- create a Pro Trial team and make sure to prefix the name with:
`vtest314 too many projects `, for example `vtest314 too many projects
test 1`
- check out this branch and cd to `vercel/vercel/packages/cli`
- run: `pnpm dev add [project-name] --cwd=/path/to/some/project`
- the project should fail to be created and you should see the expected
error message (screenshot below) in the terminal output

**Screenshot of error message when attempting to add project from cli**
<img width="798" alt="image"
src="https://github.com/vercel/vercel/assets/14896430/43e6ac2c-ae1c-4367-8d57-0aeb7fbddf33">

---------

Co-authored-by: Nathan Rajlich <n@n8.io>
2023-11-08 11:48:12 -05:00
Wyatt Johnson
fd29b966d3 tests: added tests for PPR (#10808)
This adds some tests to the PPR implementation for Next.js. This also
fixes a bug where the static pages were incorrectly generating a header
that falsly indicated that it postponed.
2023-11-08 09:21:51 -07:00
Vercel Release Bot
2bd9216403 Version Packages (#10805)
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and the packages will
be published to npm automatically. If you're not ready to do a release
yet, that's fine, whenever you add more changesets to main, this PR will
be updated.


# Releases
## vercel@32.5.2

### Patch Changes

- Updated dependencies
\[[`c94a082f6`](c94a082f6b)]:
    -   @vercel/next@4.0.13

## @vercel/next@4.0.13

### Patch Changes

- Added `getRequestHandlerWithMetadata` export
([#10753](https://github.com/vercel/vercel/pull/10753))

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-11-07 12:20:58 -07:00
Wyatt Johnson
c94a082f6b Added getRequestHandlerWithMetadata export (#10753)
This adds a new `getRequestHandlerWithMetadata` export if enabled and
available to the exported method.

---------

Co-authored-by: Joe Haddad <timer@vercel.com>
Co-authored-by: JJ Kasper <jj@jjsweb.site>
2023-11-07 10:32:03 -08:00
255 changed files with 40457 additions and 5064 deletions

View File

@@ -28,7 +28,8 @@ jobs:
with: with:
fetch-depth: 0 fetch-depth: 0
ref: main ref: main
- run: git checkout ${{ github.event.pull_request.head.ref }} - run: git fetch origin ${{ github.event.pull_request.head.sha }}:pr-${{ github.event.pull_request.number }}
- run: git checkout pr-${{ github.event.pull_request.number }}
- name: install pnpm@8.3.1 - name: install pnpm@8.3.1
run: npm i -g pnpm@8.3.1 run: npm i -g pnpm@8.3.1
- run: pnpm install - run: pnpm install

View File

@@ -70,6 +70,11 @@ jobs:
if: matrix.runner == 'macos-latest' if: matrix.runner == 'macos-latest'
run: curl -L -O https://github.com/gohugoio/hugo/releases/download/v0.56.0/hugo_0.56.0_macOS-64bit.tar.gz && tar -xzf hugo_0.56.0_macOS-64bit.tar.gz && mv ./hugo packages/cli/test/dev/fixtures/08-hugo/ run: curl -L -O https://github.com/gohugoio/hugo/releases/download/v0.56.0/hugo_0.56.0_macOS-64bit.tar.gz && tar -xzf hugo_0.56.0_macOS-64bit.tar.gz && mv ./hugo packages/cli/test/dev/fixtures/08-hugo/
# yarn 1.22.21 introduced a Corepack bug when running tests.
# this can be removed once https://github.com/yarnpkg/yarn/issues/9015 is resolved
- name: install yarn@1.22.19
run: npm i -g yarn@1.22.19
- name: install pnpm@8.3.1 - name: install pnpm@8.3.1
run: npm i -g pnpm@8.3.1 run: npm i -g pnpm@8.3.1

1
.node_version Normal file
View File

@@ -0,0 +1 @@
v16.20.2

1
.nvmrc Normal file
View File

@@ -0,0 +1 @@
16.20.2

View File

@@ -385,15 +385,16 @@ This is a [class](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refere
This is an abstract enumeration type that is implemented by one of the following possible `String` values: This is an abstract enumeration type that is implemented by one of the following possible `String` values:
- `nodejs20.x`
- `nodejs18.x` - `nodejs18.x`
- `nodejs16.x` - `nodejs16.x`
- `go1.x`
- `java11` - `java11`
- `python3.9` - `python3.9`
- `dotnet6` - `dotnet6`
- `dotnetcore3.1` - `dotnetcore3.1`
- `ruby2.7` - `ruby2.7`
- `provided.al2` - `provided.al2`
- `provided.al2023`
## `@vercel/build-utils` Helper Functions ## `@vercel/build-utils` Helper Functions

View File

@@ -19,7 +19,7 @@
## Vercel ## Vercel
Vercel's frontend cloud gives developers frameworks, workflows, and infrastructure to build a faster, more personalized web. Vercels Frontend Cloud provides the developer experience and infrastructure to build, scale, and secure a faster, more personalized Web.
## Deploy ## Deploy

View File

@@ -4,4 +4,10 @@
### Patch Changes ### Patch Changes
- chore: update Nuxt example ([#10869](https://github.com/vercel/vercel/pull/10869))
## null
### Patch Changes
- update examples to use at least node@16 ([#10395](https://github.com/vercel/vercel/pull/10395)) - update examples to use at least node@16 ([#10395](https://github.com/vercel/vercel/pull/10395))

View File

@@ -87,7 +87,7 @@ export default function Home() {
</span> </span>
</h2> </h2>
<p className={`m-0 max-w-[30ch] text-sm opacity-50`}> <p className={`m-0 max-w-[30ch] text-sm opacity-50`}>
Explore the Next.js 13 playground. Explore starter templates for Next.js.
</p> </p>
</a> </a>

View File

@@ -8,7 +8,7 @@
"name": "nextjs", "name": "nextjs",
"version": "0.1.0", "version": "0.1.0",
"dependencies": { "dependencies": {
"next": "14.0.0", "next": "14.0.4",
"react": "^18", "react": "^18",
"react-dom": "^18" "react-dom": "^18"
}, },
@@ -16,11 +16,11 @@
"@types/node": "^20", "@types/node": "^20",
"@types/react": "^18", "@types/react": "^18",
"@types/react-dom": "^18", "@types/react-dom": "^18",
"autoprefixer": "^10", "autoprefixer": "^10.0.1",
"eslint": "^8", "eslint": "^8",
"eslint-config-next": "14.0.0", "eslint-config-next": "14.0.4",
"postcss": "^8", "postcss": "^8",
"tailwindcss": "^3", "tailwindcss": "^3.3.0",
"typescript": "^5" "typescript": "^5"
} }
}, },
@@ -46,9 +46,9 @@
} }
}, },
"node_modules/@babel/runtime": { "node_modules/@babel/runtime": {
"version": "7.23.2", "version": "7.23.5",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.2.tgz", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.5.tgz",
"integrity": "sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==", "integrity": "sha512-NdUTHcPe4C99WxPub+K9l9tK5/lV4UXIoaHSYgzco9BCyjKAAwzdBI+wWtYqHt7LJdbo74ZjRPJgzVweq1sz0w==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"regenerator-runtime": "^0.14.0" "regenerator-runtime": "^0.14.0"
@@ -82,9 +82,9 @@
} }
}, },
"node_modules/@eslint/eslintrc": { "node_modules/@eslint/eslintrc": {
"version": "2.1.2", "version": "2.1.4",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz",
"integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"ajv": "^6.12.4", "ajv": "^6.12.4",
@@ -105,9 +105,9 @@
} }
}, },
"node_modules/@eslint/js": { "node_modules/@eslint/js": {
"version": "8.52.0", "version": "8.55.0",
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.52.0.tgz", "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.55.0.tgz",
"integrity": "sha512-mjZVbpaeMZludF2fsWLD0Z9gCref1Tk4i9+wddjRvpUNqqcndPkBD09N/Mapey0b3jaXbLm2kICwFv2E64QinA==", "integrity": "sha512-qQfo2mxH5yVom1kacMtZZJFVdW+E70mqHMJvVg6WTLo+VBuQJ4TojZlfWBjK0ve5BdEeNAVxOsl/nvNMpJOaJA==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0" "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -195,23 +195,23 @@
} }
}, },
"node_modules/@next/env": { "node_modules/@next/env": {
"version": "14.0.0", "version": "14.0.4",
"resolved": "https://registry.npmjs.org/@next/env/-/env-14.0.0.tgz", "resolved": "https://registry.npmjs.org/@next/env/-/env-14.0.4.tgz",
"integrity": "sha512-cIKhxkfVELB6hFjYsbtEeTus2mwrTC+JissfZYM0n+8Fv+g8ucUfOlm3VEDtwtwydZ0Nuauv3bl0qF82nnCAqA==" "integrity": "sha512-irQnbMLbUNQpP1wcE5NstJtbuA/69kRfzBrpAD7Gsn8zm/CY6YQYc3HQBz8QPxwISG26tIm5afvvVbu508oBeQ=="
}, },
"node_modules/@next/eslint-plugin-next": { "node_modules/@next/eslint-plugin-next": {
"version": "14.0.0", "version": "14.0.4",
"resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.0.0.tgz", "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.0.4.tgz",
"integrity": "sha512-Ye37nNI09V3yt7pzuzSQtwlvuJ2CGzFszHXkcTHHZgNr7EhTMFLipn3VSJChy+e5+ahTdNApPphc3qCPUsn10A==", "integrity": "sha512-U3qMNHmEZoVmHA0j/57nRfi3AscXNvkOnxDmle/69Jz/G0o/gWjXTDdlgILZdrxQ0Lw/jv2mPW8PGy0EGIHXhQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"glob": "7.1.7" "glob": "7.1.7"
} }
}, },
"node_modules/@next/swc-darwin-arm64": { "node_modules/@next/swc-darwin-arm64": {
"version": "14.0.0", "version": "14.0.4",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.0.0.tgz", "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.0.4.tgz",
"integrity": "sha512-HQKi159jCz4SRsPesVCiNN6tPSAFUkOuSkpJsqYTIlbHLKr1mD6be/J0TvWV6fwJekj81bZV9V/Tgx3C2HO9lA==", "integrity": "sha512-mF05E/5uPthWzyYDyptcwHptucf/jj09i2SXBPwNzbgBNc+XnwzrL0U6BmPjQeOL+FiB+iG1gwBeq7mlDjSRPg==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -224,9 +224,9 @@
} }
}, },
"node_modules/@next/swc-darwin-x64": { "node_modules/@next/swc-darwin-x64": {
"version": "14.0.0", "version": "14.0.4",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.0.0.tgz", "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.0.4.tgz",
"integrity": "sha512-4YyQLMSaCgX/kgC1jjF3s3xSoBnwHuDhnF6WA1DWNEYRsbOOPWjcYhv8TKhRe2ApdOam+VfQSffC4ZD+X4u1Cg==", "integrity": "sha512-IZQ3C7Bx0k2rYtrZZxKKiusMTM9WWcK5ajyhOZkYYTCc8xytmwSzR1skU7qLgVT/EY9xtXDG0WhY6fyujnI3rw==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -239,9 +239,9 @@
} }
}, },
"node_modules/@next/swc-linux-arm64-gnu": { "node_modules/@next/swc-linux-arm64-gnu": {
"version": "14.0.0", "version": "14.0.4",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.0.0.tgz", "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.0.4.tgz",
"integrity": "sha512-io7fMkJ28Glj7SH8yvnlD6naIhRDnDxeE55CmpQkj3+uaA2Hko6WGY2pT5SzpQLTnGGnviK85cy8EJ2qsETj/g==", "integrity": "sha512-VwwZKrBQo/MGb1VOrxJ6LrKvbpo7UbROuyMRvQKTFKhNaXjUmKTu7wxVkIuCARAfiI8JpaWAnKR+D6tzpCcM4w==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -254,9 +254,9 @@
} }
}, },
"node_modules/@next/swc-linux-arm64-musl": { "node_modules/@next/swc-linux-arm64-musl": {
"version": "14.0.0", "version": "14.0.4",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.0.0.tgz", "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.0.4.tgz",
"integrity": "sha512-nC2h0l1Jt8LEzyQeSs/BKpXAMe0mnHIMykYALWaeddTqCv5UEN8nGO3BG8JAqW/Y8iutqJsaMe2A9itS0d/r8w==", "integrity": "sha512-8QftwPEW37XxXoAwsn+nXlodKWHfpMaSvt81W43Wh8dv0gkheD+30ezWMcFGHLI71KiWmHK5PSQbTQGUiidvLQ==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -269,9 +269,9 @@
} }
}, },
"node_modules/@next/swc-linux-x64-gnu": { "node_modules/@next/swc-linux-x64-gnu": {
"version": "14.0.0", "version": "14.0.4",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.0.0.tgz", "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.0.4.tgz",
"integrity": "sha512-Wf+WjXibJQ7hHXOdNOmSMW5bxeJHVf46Pwb3eLSD2L76NrytQlif9NH7JpHuFlYKCQGfKfgSYYre5rIfmnSwQw==", "integrity": "sha512-/s/Pme3VKfZAfISlYVq2hzFS8AcAIOTnoKupc/j4WlvF6GQ0VouS2Q2KEgPuO1eMBwakWPB1aYFIA4VNVh667A==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -284,9 +284,9 @@
} }
}, },
"node_modules/@next/swc-linux-x64-musl": { "node_modules/@next/swc-linux-x64-musl": {
"version": "14.0.0", "version": "14.0.4",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.0.0.tgz", "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.0.4.tgz",
"integrity": "sha512-WTZb2G7B+CTsdigcJVkRxfcAIQj7Lf0ipPNRJ3vlSadU8f0CFGv/ST+sJwF5eSwIe6dxKoX0DG6OljDBaad+rg==", "integrity": "sha512-m8z/6Fyal4L9Bnlxde5g2Mfa1Z7dasMQyhEhskDATpqr+Y0mjOBZcXQ7G5U+vgL22cI4T7MfvgtrM2jdopqWaw==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -299,9 +299,9 @@
} }
}, },
"node_modules/@next/swc-win32-arm64-msvc": { "node_modules/@next/swc-win32-arm64-msvc": {
"version": "14.0.0", "version": "14.0.4",
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.0.0.tgz", "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.0.4.tgz",
"integrity": "sha512-7R8/x6oQODmNpnWVW00rlWX90sIlwluJwcvMT6GXNIBOvEf01t3fBg0AGURNKdTJg2xNuP7TyLchCL7Lh2DTiw==", "integrity": "sha512-7Wv4PRiWIAWbm5XrGz3D8HUkCVDMMz9igffZG4NB1p4u1KoItwx9qjATHz88kwCEal/HXmbShucaslXCQXUM5w==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -314,9 +314,9 @@
} }
}, },
"node_modules/@next/swc-win32-ia32-msvc": { "node_modules/@next/swc-win32-ia32-msvc": {
"version": "14.0.0", "version": "14.0.4",
"resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.0.0.tgz", "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.0.4.tgz",
"integrity": "sha512-RLK1nELvhCnxaWPF07jGU4x3tjbyx2319q43loZELqF0+iJtKutZ+Lk8SVmf/KiJkYBc7Cragadz7hb3uQvz4g==", "integrity": "sha512-zLeNEAPULsl0phfGb4kdzF/cAVIfaC7hY+kt0/d+y9mzcZHsMS3hAS829WbJ31DkSlVKQeHEjZHIdhN+Pg7Gyg==",
"cpu": [ "cpu": [
"ia32" "ia32"
], ],
@@ -329,9 +329,9 @@
} }
}, },
"node_modules/@next/swc-win32-x64-msvc": { "node_modules/@next/swc-win32-x64-msvc": {
"version": "14.0.0", "version": "14.0.4",
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.0.0.tgz", "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.0.4.tgz",
"integrity": "sha512-g6hLf1SUko+hnnaywQQZzzb3BRecQsoKkF3o/C+F+dOA4w/noVAJngUVkfwF0+2/8FzNznM7ofM6TGZO9svn7w==", "integrity": "sha512-yEh2+R8qDlDCjxVpzOTEpBLQTEFAcP2A8fUFLaWNap9GitYKkKv1//y2S6XY6zsR4rCOPRpU7plYDR+az2n30A==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -379,9 +379,9 @@
} }
}, },
"node_modules/@rushstack/eslint-patch": { "node_modules/@rushstack/eslint-patch": {
"version": "1.5.1", "version": "1.6.0",
"resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.5.1.tgz", "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.6.0.tgz",
"integrity": "sha512-6i/8UoL0P5y4leBIGzvkZdS85RDMG9y1ihZzmTZQ5LdHUYmZ7pKFoj8X0236s3lusPs1Fa5HTQUpwI+UfTcmeA==", "integrity": "sha512-2/U3GXA6YiPYQDLGwtGlnNgKYBSwCFIHf8Y9LUY5VATHdtbLlU0Y1R3QoBnT0aB4qv/BEiVVsj7LJXoQCgJ2vA==",
"dev": true "dev": true
}, },
"node_modules/@swc/helpers": { "node_modules/@swc/helpers": {
@@ -399,24 +399,24 @@
"dev": true "dev": true
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "20.8.9", "version": "20.10.4",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.9.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.4.tgz",
"integrity": "sha512-UzykFsT3FhHb1h7yD4CA4YhBHq545JC0YnEz41xkipN88eKQtL6rSgocL5tbAP6Ola9Izm/Aw4Ora8He4x0BHg==", "integrity": "sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"undici-types": "~5.26.4" "undici-types": "~5.26.4"
} }
}, },
"node_modules/@types/prop-types": { "node_modules/@types/prop-types": {
"version": "15.7.9", "version": "15.7.11",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.9.tgz", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz",
"integrity": "sha512-n1yyPsugYNSmHgxDFjicaI2+gCNjsBck8UX9kuofAKlc0h1bL+20oSF72KeNaW2DUlesbEVCFgyV2dPGTiY42g==", "integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==",
"dev": true "dev": true
}, },
"node_modules/@types/react": { "node_modules/@types/react": {
"version": "18.2.33", "version": "18.2.42",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.33.tgz", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.42.tgz",
"integrity": "sha512-v+I7S+hu3PIBoVkKGpSYYpiBT1ijqEzWpzQD62/jm4K74hPpSP7FF9BnKG6+fg2+62weJYkkBWDJlZt5JO/9hg==", "integrity": "sha512-c1zEr96MjakLYus/wPnuWDo1/zErfdU9rNsIGmE+NV71nx88FG9Ttgo5dqorXTu/LImX2f63WBP986gJkMPNbA==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@types/prop-types": "*", "@types/prop-types": "*",
@@ -425,30 +425,30 @@
} }
}, },
"node_modules/@types/react-dom": { "node_modules/@types/react-dom": {
"version": "18.2.14", "version": "18.2.17",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.14.tgz", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.17.tgz",
"integrity": "sha512-V835xgdSVmyQmI1KLV2BEIUgqEuinxp9O4G6g3FqO/SqLac049E53aysv0oEFD2kHfejeKU+ZqL2bcFWj9gLAQ==", "integrity": "sha512-rvrT/M7Df5eykWFxn6MYt5Pem/Dbyc1N8Y0S9Mrkw2WFCRiqUgw9P7ul2NpwsXCSM1DVdENzdG9J5SreqfAIWg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@types/react": "*" "@types/react": "*"
} }
}, },
"node_modules/@types/scheduler": { "node_modules/@types/scheduler": {
"version": "0.16.5", "version": "0.16.8",
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.5.tgz", "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz",
"integrity": "sha512-s/FPdYRmZR8SjLWGMCuax7r3qCWQw9QKHzXVukAuuIJkXkDRwp+Pu5LMIVFi0Fxbav35WURicYr8u1QsoybnQw==", "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==",
"dev": true "dev": true
}, },
"node_modules/@typescript-eslint/parser": { "node_modules/@typescript-eslint/parser": {
"version": "6.9.0", "version": "6.13.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.9.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.13.2.tgz",
"integrity": "sha512-GZmjMh4AJ/5gaH4XF2eXA8tMnHWP+Pm1mjQR2QN4Iz+j/zO04b9TOvJYOX2sCNIQHtRStKTxRY1FX7LhpJT4Gw==", "integrity": "sha512-MUkcC+7Wt/QOGeVlM8aGGJZy1XV5YKjTpq9jK6r6/iLsGXhBVaGP5N0UYvFsu9BFlSpwY9kMretzdBH01rkRXg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/scope-manager": "6.9.0", "@typescript-eslint/scope-manager": "6.13.2",
"@typescript-eslint/types": "6.9.0", "@typescript-eslint/types": "6.13.2",
"@typescript-eslint/typescript-estree": "6.9.0", "@typescript-eslint/typescript-estree": "6.13.2",
"@typescript-eslint/visitor-keys": "6.9.0", "@typescript-eslint/visitor-keys": "6.13.2",
"debug": "^4.3.4" "debug": "^4.3.4"
}, },
"engines": { "engines": {
@@ -468,13 +468,13 @@
} }
}, },
"node_modules/@typescript-eslint/scope-manager": { "node_modules/@typescript-eslint/scope-manager": {
"version": "6.9.0", "version": "6.13.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.9.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.13.2.tgz",
"integrity": "sha512-1R8A9Mc39n4pCCz9o79qRO31HGNDvC7UhPhv26TovDsWPBDx+Sg3rOZdCELIA3ZmNoWAuxaMOT7aWtGRSYkQxw==", "integrity": "sha512-CXQA0xo7z6x13FeDYCgBkjWzNqzBn8RXaE3QVQVIUm74fWJLkJkaHmHdKStrxQllGh6Q4eUGyNpMe0b1hMkXFA==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/types": "6.9.0", "@typescript-eslint/types": "6.13.2",
"@typescript-eslint/visitor-keys": "6.9.0" "@typescript-eslint/visitor-keys": "6.13.2"
}, },
"engines": { "engines": {
"node": "^16.0.0 || >=18.0.0" "node": "^16.0.0 || >=18.0.0"
@@ -485,9 +485,9 @@
} }
}, },
"node_modules/@typescript-eslint/types": { "node_modules/@typescript-eslint/types": {
"version": "6.9.0", "version": "6.13.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.9.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.13.2.tgz",
"integrity": "sha512-+KB0lbkpxBkBSiVCuQvduqMJy+I1FyDbdwSpM3IoBS7APl4Bu15lStPjgBIdykdRqQNYqYNMa8Kuidax6phaEw==", "integrity": "sha512-7sxbQ+EMRubQc3wTfTsycgYpSujyVbI1xw+3UMRUcrhSy+pN09y/lWzeKDbvhoqcRbHdc+APLs/PWYi/cisLPg==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": "^16.0.0 || >=18.0.0" "node": "^16.0.0 || >=18.0.0"
@@ -498,13 +498,13 @@
} }
}, },
"node_modules/@typescript-eslint/typescript-estree": { "node_modules/@typescript-eslint/typescript-estree": {
"version": "6.9.0", "version": "6.13.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.9.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.13.2.tgz",
"integrity": "sha512-NJM2BnJFZBEAbCfBP00zONKXvMqihZCrmwCaik0UhLr0vAgb6oguXxLX1k00oQyD+vZZ+CJn3kocvv2yxm4awQ==", "integrity": "sha512-SuD8YLQv6WHnOEtKv8D6HZUzOub855cfPnPMKvdM/Bh1plv1f7Q/0iFUDLKKlxHcEstQnaUU4QZskgQq74t+3w==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/types": "6.9.0", "@typescript-eslint/types": "6.13.2",
"@typescript-eslint/visitor-keys": "6.9.0", "@typescript-eslint/visitor-keys": "6.13.2",
"debug": "^4.3.4", "debug": "^4.3.4",
"globby": "^11.1.0", "globby": "^11.1.0",
"is-glob": "^4.0.3", "is-glob": "^4.0.3",
@@ -525,12 +525,12 @@
} }
}, },
"node_modules/@typescript-eslint/visitor-keys": { "node_modules/@typescript-eslint/visitor-keys": {
"version": "6.9.0", "version": "6.13.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.9.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.13.2.tgz",
"integrity": "sha512-dGtAfqjV6RFOtIP8I0B4ZTBRrlTT8NHHlZZSchQx3qReaoDeXhYM++M4So2AgFK9ZB0emRPA6JI1HkafzA2Ibg==", "integrity": "sha512-OGznFs0eAQXJsp+xSd6k/O1UbFi/K/L7WjqeRoFE7vadjAF9y0uppXhYNQNEqygjou782maGClOoZwPqF0Drlw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/types": "6.9.0", "@typescript-eslint/types": "6.13.2",
"eslint-visitor-keys": "^3.4.1" "eslint-visitor-keys": "^3.4.1"
}, },
"engines": { "engines": {
@@ -548,9 +548,9 @@
"dev": true "dev": true
}, },
"node_modules/acorn": { "node_modules/acorn": {
"version": "8.11.0", "version": "8.11.2",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.0.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz",
"integrity": "sha512-hNiSyky+cuYVALBrsjB7f9gMN9P4u09JyAiMNMLaVfsmkDJuH84M1T/0pfDX/OJfGWcobd2A7ecXYzygn8wibA==", "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==",
"dev": true, "dev": true,
"bin": { "bin": {
"acorn": "bin/acorn" "acorn": "bin/acorn"
@@ -779,9 +779,9 @@
} }
}, },
"node_modules/ast-types-flow": { "node_modules/ast-types-flow": {
"version": "0.0.7", "version": "0.0.8",
"resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz",
"integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==", "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==",
"dev": true "dev": true
}, },
"node_modules/asynciterator.prototype": { "node_modules/asynciterator.prototype": {
@@ -843,9 +843,9 @@
} }
}, },
"node_modules/axe-core": { "node_modules/axe-core": {
"version": "4.8.2", "version": "4.7.0",
"resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.8.2.tgz", "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.7.0.tgz",
"integrity": "sha512-/dlp0fxyM3R8YW7MFzaHWXrf4zzbr0vaYb23VBFCl83R7nWNPg/yaQw2Dc8jzCMmDVLhSdzH8MjrsuIUuvX+6g==", "integrity": "sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": ">=4" "node": ">=4"
@@ -898,9 +898,9 @@
} }
}, },
"node_modules/browserslist": { "node_modules/browserslist": {
"version": "4.22.1", "version": "4.22.2",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz",
"integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {
@@ -917,9 +917,9 @@
} }
], ],
"dependencies": { "dependencies": {
"caniuse-lite": "^1.0.30001541", "caniuse-lite": "^1.0.30001565",
"electron-to-chromium": "^1.4.535", "electron-to-chromium": "^1.4.601",
"node-releases": "^2.0.13", "node-releases": "^2.0.14",
"update-browserslist-db": "^1.0.13" "update-browserslist-db": "^1.0.13"
}, },
"bin": { "bin": {
@@ -973,9 +973,9 @@
} }
}, },
"node_modules/caniuse-lite": { "node_modules/caniuse-lite": {
"version": "1.0.30001554", "version": "1.0.30001566",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001554.tgz", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001566.tgz",
"integrity": "sha512-A2E3U//MBwbJVzebddm1YfNp7Nud5Ip+IPn4BozBmn4KqVX7AvluoIDFWjsv5OkGnKUXQVmMSoMKLa3ScCblcQ==", "integrity": "sha512-ggIhCsTxmITBAMmK8yZjEhCO5/47jKXPu6Dha/wuCS4JePVL+3uiDEBuhu2aIoT+bqTOR8L76Ip1ARL9xYsEJA==",
"funding": [ "funding": [
{ {
"type": "opencollective", "type": "opencollective",
@@ -1111,9 +1111,9 @@
} }
}, },
"node_modules/csstype": { "node_modules/csstype": {
"version": "3.1.2", "version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
"dev": true "dev": true
}, },
"node_modules/damerau-levenshtein": { "node_modules/damerau-levenshtein": {
@@ -1222,9 +1222,9 @@
} }
}, },
"node_modules/electron-to-chromium": { "node_modules/electron-to-chromium": {
"version": "1.4.567", "version": "1.4.608",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.567.tgz", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.608.tgz",
"integrity": "sha512-8KR114CAYQ4/r5EIEsOmOMqQ9j0MRbJZR3aXD/KFA8RuKzyoUB4XrUCg+l8RUGqTVQgKNIgTpjaG8YHRPAbX2w==", "integrity": "sha512-J2f/3iIIm3Mo0npneITZ2UPe4B1bg8fTNrFjD8715F/k1BvbviRuqYGkET1PgprrczXYTHFvotbBOmUp6KE0uA==",
"dev": true "dev": true
}, },
"node_modules/emoji-regex": { "node_modules/emoji-regex": {
@@ -1383,15 +1383,15 @@
} }
}, },
"node_modules/eslint": { "node_modules/eslint": {
"version": "8.52.0", "version": "8.55.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.52.0.tgz", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.55.0.tgz",
"integrity": "sha512-zh/JHnaixqHZsolRB/w9/02akBk9EPrOs9JwcTP2ek7yL5bVvXuRariiaAjjoJ5DvuwQ1WAE/HsMz+w17YgBCg==", "integrity": "sha512-iyUUAM0PCKj5QpwGfmCAG9XXbZCWsqP/eWAWrG/W0umvjuLRBECwSFdt+rCntju0xEH7teIABPwXpahftIaTdA==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.6.1", "@eslint-community/regexpp": "^4.6.1",
"@eslint/eslintrc": "^2.1.2", "@eslint/eslintrc": "^2.1.4",
"@eslint/js": "8.52.0", "@eslint/js": "8.55.0",
"@humanwhocodes/config-array": "^0.11.13", "@humanwhocodes/config-array": "^0.11.13",
"@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/module-importer": "^1.0.1",
"@nodelib/fs.walk": "^1.2.8", "@nodelib/fs.walk": "^1.2.8",
@@ -1438,12 +1438,12 @@
} }
}, },
"node_modules/eslint-config-next": { "node_modules/eslint-config-next": {
"version": "14.0.0", "version": "14.0.4",
"resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-14.0.0.tgz", "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-14.0.4.tgz",
"integrity": "sha512-jtXeE+/pGQ3h9n11QyyuPN50kO13GO5XvjU5ZRq6W+XTpOMjyobWmK2s7aowy0FtzA49krJzYzEU9s1RMwoJ6g==", "integrity": "sha512-9/xbOHEQOmQtqvQ1UsTQZpnA7SlDMBtuKJ//S4JnoyK3oGLhILKXdBgu/UO7lQo/2xOykQULS1qQ6p2+EpHgAQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@next/eslint-plugin-next": "14.0.0", "@next/eslint-plugin-next": "14.0.4",
"@rushstack/eslint-patch": "^1.3.3", "@rushstack/eslint-patch": "^1.3.3",
"@typescript-eslint/parser": "^5.4.2 || ^6.0.0", "@typescript-eslint/parser": "^5.4.2 || ^6.0.0",
"eslint-import-resolver-node": "^0.3.6", "eslint-import-resolver-node": "^0.3.6",
@@ -1596,27 +1596,27 @@
} }
}, },
"node_modules/eslint-plugin-jsx-a11y": { "node_modules/eslint-plugin-jsx-a11y": {
"version": "6.7.1", "version": "6.8.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.7.1.tgz", "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.8.0.tgz",
"integrity": "sha512-63Bog4iIethyo8smBklORknVjB0T2dwB8Mr/hIC+fBS0uyHdYYpzM/Ed+YC8VxTjlXHEWFOdmgwcDn1U2L9VCA==", "integrity": "sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@babel/runtime": "^7.20.7", "@babel/runtime": "^7.23.2",
"aria-query": "^5.1.3", "aria-query": "^5.3.0",
"array-includes": "^3.1.6", "array-includes": "^3.1.7",
"array.prototype.flatmap": "^1.3.1", "array.prototype.flatmap": "^1.3.2",
"ast-types-flow": "^0.0.7", "ast-types-flow": "^0.0.8",
"axe-core": "^4.6.2", "axe-core": "=4.7.0",
"axobject-query": "^3.1.1", "axobject-query": "^3.2.1",
"damerau-levenshtein": "^1.0.8", "damerau-levenshtein": "^1.0.8",
"emoji-regex": "^9.2.2", "emoji-regex": "^9.2.2",
"has": "^1.0.3", "es-iterator-helpers": "^1.0.15",
"jsx-ast-utils": "^3.3.3", "hasown": "^2.0.0",
"language-tags": "=1.0.5", "jsx-ast-utils": "^3.3.5",
"language-tags": "^1.0.9",
"minimatch": "^3.1.2", "minimatch": "^3.1.2",
"object.entries": "^1.1.6", "object.entries": "^1.1.7",
"object.fromentries": "^2.0.6", "object.fromentries": "^2.0.7"
"semver": "^6.3.0"
}, },
"engines": { "engines": {
"node": ">=4.0" "node": ">=4.0"
@@ -1625,15 +1625,6 @@
"eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8"
} }
}, },
"node_modules/eslint-plugin-jsx-a11y/node_modules/semver": {
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"dev": true,
"bin": {
"semver": "bin/semver.js"
}
},
"node_modules/eslint-plugin-react": { "node_modules/eslint-plugin-react": {
"version": "7.33.2", "version": "7.33.2",
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz", "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz",
@@ -1808,9 +1799,9 @@
"dev": true "dev": true
}, },
"node_modules/fast-glob": { "node_modules/fast-glob": {
"version": "3.3.1", "version": "3.3.2",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
"integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.stat": "^2.0.2",
@@ -1897,9 +1888,9 @@
} }
}, },
"node_modules/flat-cache": { "node_modules/flat-cache": {
"version": "3.1.1", "version": "3.2.0",
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.1.tgz", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz",
"integrity": "sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==", "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"flatted": "^3.2.9", "flatted": "^3.2.9",
@@ -1907,7 +1898,7 @@
"rimraf": "^3.0.2" "rimraf": "^3.0.2"
}, },
"engines": { "engines": {
"node": ">=12.0.0" "node": "^10.12.0 || >=12.0.0"
} }
}, },
"node_modules/flatted": { "node_modules/flatted": {
@@ -2147,15 +2138,6 @@
"integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
"dev": true "dev": true
}, },
"node_modules/has": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz",
"integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==",
"dev": true,
"engines": {
"node": ">= 0.4.0"
}
},
"node_modules/has-bigints": { "node_modules/has-bigints": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
@@ -2238,9 +2220,9 @@
} }
}, },
"node_modules/ignore": { "node_modules/ignore": {
"version": "5.2.4", "version": "5.3.0",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz",
"integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": ">= 4" "node": ">= 4"
@@ -2653,9 +2635,9 @@
} }
}, },
"node_modules/jiti": { "node_modules/jiti": {
"version": "1.20.0", "version": "1.21.0",
"resolved": "https://registry.npmjs.org/jiti/-/jiti-1.20.0.tgz", "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz",
"integrity": "sha512-3TV69ZbrvV6U5DfQimop50jE9Dl6J8O1ja1dvBbMba/sZ3YBEQqJ2VZRoQPVnhlzjNtU1vaXRZVrVjU4qtm8yA==", "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==",
"dev": true, "dev": true,
"bin": { "bin": {
"jiti": "bin/jiti.js" "jiti": "bin/jiti.js"
@@ -2739,12 +2721,15 @@
"dev": true "dev": true
}, },
"node_modules/language-tags": { "node_modules/language-tags": {
"version": "1.0.5", "version": "1.0.9",
"resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz", "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz",
"integrity": "sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==", "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"language-subtag-registry": "~0.3.2" "language-subtag-registry": "^0.3.20"
},
"engines": {
"node": ">=0.10"
} }
}, },
"node_modules/levn": { "node_modules/levn": {
@@ -2880,9 +2865,9 @@
} }
}, },
"node_modules/nanoid": { "node_modules/nanoid": {
"version": "3.3.6", "version": "3.3.7",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
"integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
"funding": [ "funding": [
{ {
"type": "github", "type": "github",
@@ -2903,14 +2888,15 @@
"dev": true "dev": true
}, },
"node_modules/next": { "node_modules/next": {
"version": "14.0.0", "version": "14.0.4",
"resolved": "https://registry.npmjs.org/next/-/next-14.0.0.tgz", "resolved": "https://registry.npmjs.org/next/-/next-14.0.4.tgz",
"integrity": "sha512-J0jHKBJpB9zd4+c153sair0sz44mbaCHxggs8ryVXSFBuBqJ8XdE9/ozoV85xGh2VnSjahwntBZZgsihL9QznA==", "integrity": "sha512-qbwypnM7327SadwFtxXnQdGiKpkuhaRLE2uq62/nRul9cj9KhQ5LhHmlziTNqUidZotw/Q1I9OjirBROdUJNgA==",
"dependencies": { "dependencies": {
"@next/env": "14.0.0", "@next/env": "14.0.4",
"@swc/helpers": "0.5.2", "@swc/helpers": "0.5.2",
"busboy": "1.6.0", "busboy": "1.6.0",
"caniuse-lite": "^1.0.30001406", "caniuse-lite": "^1.0.30001406",
"graceful-fs": "^4.2.11",
"postcss": "8.4.31", "postcss": "8.4.31",
"styled-jsx": "5.1.1", "styled-jsx": "5.1.1",
"watchpack": "2.4.0" "watchpack": "2.4.0"
@@ -2922,15 +2908,15 @@
"node": ">=18.17.0" "node": ">=18.17.0"
}, },
"optionalDependencies": { "optionalDependencies": {
"@next/swc-darwin-arm64": "14.0.0", "@next/swc-darwin-arm64": "14.0.4",
"@next/swc-darwin-x64": "14.0.0", "@next/swc-darwin-x64": "14.0.4",
"@next/swc-linux-arm64-gnu": "14.0.0", "@next/swc-linux-arm64-gnu": "14.0.4",
"@next/swc-linux-arm64-musl": "14.0.0", "@next/swc-linux-arm64-musl": "14.0.4",
"@next/swc-linux-x64-gnu": "14.0.0", "@next/swc-linux-x64-gnu": "14.0.4",
"@next/swc-linux-x64-musl": "14.0.0", "@next/swc-linux-x64-musl": "14.0.4",
"@next/swc-win32-arm64-msvc": "14.0.0", "@next/swc-win32-arm64-msvc": "14.0.4",
"@next/swc-win32-ia32-msvc": "14.0.0", "@next/swc-win32-ia32-msvc": "14.0.4",
"@next/swc-win32-x64-msvc": "14.0.0" "@next/swc-win32-x64-msvc": "14.0.4"
}, },
"peerDependencies": { "peerDependencies": {
"@opentelemetry/api": "^1.1.0", "@opentelemetry/api": "^1.1.0",
@@ -2947,10 +2933,37 @@
} }
} }
}, },
"node_modules/next/node_modules/postcss": {
"version": "8.4.31",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
"integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
},
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/postcss"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"dependencies": {
"nanoid": "^3.3.6",
"picocolors": "^1.0.0",
"source-map-js": "^1.0.2"
},
"engines": {
"node": "^10 || ^12 || >=14"
}
},
"node_modules/node-releases": { "node_modules/node-releases": {
"version": "2.0.13", "version": "2.0.14",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz",
"integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==",
"dev": true "dev": true
}, },
"node_modules/normalize-path": { "node_modules/normalize-path": {
@@ -3008,13 +3021,13 @@
} }
}, },
"node_modules/object.assign": { "node_modules/object.assign": {
"version": "4.1.4", "version": "4.1.5",
"resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz",
"integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"call-bind": "^1.0.2", "call-bind": "^1.0.5",
"define-properties": "^1.1.4", "define-properties": "^1.2.1",
"has-symbols": "^1.0.3", "has-symbols": "^1.0.3",
"object-keys": "^1.1.1" "object-keys": "^1.1.1"
}, },
@@ -3244,9 +3257,10 @@
} }
}, },
"node_modules/postcss": { "node_modules/postcss": {
"version": "8.4.31", "version": "8.4.32",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.32.tgz",
"integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", "integrity": "sha512-D/kj5JNu6oo2EIy+XL/26JEDTlIbB8hw85G8StOE6L74RQAVVP5rej6wxCNqyMbR4RkPfqvezVbPw81Ngd6Kcw==",
"dev": true,
"funding": [ "funding": [
{ {
"type": "opencollective", "type": "opencollective",
@@ -3262,7 +3276,7 @@
} }
], ],
"dependencies": { "dependencies": {
"nanoid": "^3.3.6", "nanoid": "^3.3.7",
"picocolors": "^1.0.0", "picocolors": "^1.0.0",
"source-map-js": "^1.0.2" "source-map-js": "^1.0.2"
}, },
@@ -3307,21 +3321,27 @@
} }
}, },
"node_modules/postcss-load-config": { "node_modules/postcss-load-config": {
"version": "4.0.1", "version": "4.0.2",
"resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.1.tgz", "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz",
"integrity": "sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==", "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==",
"dev": true, "dev": true,
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"dependencies": { "dependencies": {
"lilconfig": "^2.0.5", "lilconfig": "^3.0.0",
"yaml": "^2.1.1" "yaml": "^2.3.4"
}, },
"engines": { "engines": {
"node": ">= 14" "node": ">= 14"
}, },
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
},
"peerDependencies": { "peerDependencies": {
"postcss": ">=8.0.9", "postcss": ">=8.0.9",
"ts-node": ">=9.0.0" "ts-node": ">=9.0.0"
@@ -3335,6 +3355,15 @@
} }
} }
}, },
"node_modules/postcss-load-config/node_modules/lilconfig": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.0.0.tgz",
"integrity": "sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==",
"dev": true,
"engines": {
"node": ">=14"
}
},
"node_modules/postcss-nested": { "node_modules/postcss-nested": {
"version": "6.0.1", "version": "6.0.1",
"resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz", "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz",
@@ -3394,9 +3423,9 @@
} }
}, },
"node_modules/punycode": { "node_modules/punycode": {
"version": "2.3.0", "version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
"integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": ">=6" "node": ">=6"
@@ -3929,9 +3958,9 @@
} }
}, },
"node_modules/tailwindcss": { "node_modules/tailwindcss": {
"version": "3.3.5", "version": "3.3.6",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.5.tgz", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.6.tgz",
"integrity": "sha512-5SEZU4J7pxZgSkv7FP1zY8i2TIAOooNZ1e/OGtxIEv6GltpoiXUqWvLy89+a10qYTB1N5Ifkuw9lqQkN9sscvA==", "integrity": "sha512-AKjF7qbbLvLaPieoKeTjG1+FyNZT6KaJMJPFeQyLfIp7l82ggH1fbHJSsYIvnbTFQOlkh+gBYpyby5GT1LIdLw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@alloc/quick-lru": "^5.2.0", "@alloc/quick-lru": "^5.2.0",
@@ -4138,9 +4167,9 @@
} }
}, },
"node_modules/typescript": { "node_modules/typescript": {
"version": "5.2.2", "version": "5.3.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz",
"integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==",
"dev": true, "dev": true,
"bin": { "bin": {
"tsc": "bin/tsc", "tsc": "bin/tsc",
@@ -4332,9 +4361,9 @@
"dev": true "dev": true
}, },
"node_modules/yaml": { "node_modules/yaml": {
"version": "2.3.3", "version": "2.3.4",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.3.tgz", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz",
"integrity": "sha512-zw0VAJxgeZ6+++/su5AFoqBbZbrEakwu+X0M5HmcwUiBL7AzcuPKjj5we4xfQLp78LkEMpD0cOnUhmgOVy3KdQ==", "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": ">= 14" "node": ">= 14"

View File

@@ -11,17 +11,17 @@
"dependencies": { "dependencies": {
"react": "^18", "react": "^18",
"react-dom": "^18", "react-dom": "^18",
"next": "14.0.0" "next": "14.0.4"
}, },
"devDependencies": { "devDependencies": {
"typescript": "^5", "typescript": "^5",
"@types/node": "^20", "@types/node": "^20",
"@types/react": "^18", "@types/react": "^18",
"@types/react-dom": "^18", "@types/react-dom": "^18",
"autoprefixer": "^10", "autoprefixer": "^10.0.1",
"postcss": "^8", "postcss": "^8",
"tailwindcss": "^3", "tailwindcss": "^3.3.0",
"eslint": "^8", "eslint": "^8",
"eslint-config-next": "14.0.0" "eslint-config-next": "14.0.4"
} }
} }

View File

@@ -2,4 +2,4 @@
<div> <div>
<NuxtWelcome /> <NuxtWelcome />
</div> </div>
</template> </template>

View File

@@ -1,5 +1,8 @@
export default { // https://nuxt.com/docs/api/configuration/nuxt-config
nitro: { export default defineNuxtConfig({
preset: 'vercel-edge', devtools: { enabled: true },
routeRules: {
// prerender index route by default
'/': { prerender: true },
}, },
}; });

View File

@@ -1,5 +1,6 @@
{ {
"private": true, "private": true,
"type": "module",
"scripts": { "scripts": {
"build": "nuxt build", "build": "nuxt build",
"dev": "nuxt dev", "dev": "nuxt dev",
@@ -8,6 +9,9 @@
"postinstall": "nuxt prepare" "postinstall": "nuxt prepare"
}, },
"devDependencies": { "devDependencies": {
"nuxt": "^3.0.0" "@nuxt/devtools": "^1.0.3",
"nuxt": "^3.8.2",
"vue": "^3.3.8",
"vue-router": "^4.2.5"
} }
} }

6100
examples/nuxtjs/pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@@ -0,0 +1,3 @@
{
"extends": "../.nuxt/tsconfig.server.json"
}

View File

@@ -1,4 +1,4 @@
{ {
// https://v3.nuxtjs.org/concepts/typescript // https://nuxt.com/docs/guide/concepts/typescript
"extends": "./.nuxt/tsconfig.json" "extends": "./.nuxt/tsconfig.json"
} }

File diff suppressed because it is too large Load Diff

View File

@@ -9,7 +9,7 @@
}, },
"devDependencies": { "devDependencies": {
"@types/jest": "27.4.1", "@types/jest": "27.4.1",
"@vercel/frameworks": "2.0.3" "@vercel/frameworks": "2.0.5"
}, },
"version": null "version": null
} }

View File

@@ -2,6 +2,12 @@
This directory is a brief example of a [Remix](https://remix.run/docs) site that can be deployed to Vercel with zero configuration. This directory is a brief example of a [Remix](https://remix.run/docs) site that can be deployed to Vercel with zero configuration.
To get started, run the Remix cli with this template
```sh
npx create-remix@latest --template vercel/vercel/examples/remix
```
## Deploy Your Own ## Deploy Your Own
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/vercel/vercel/tree/main/examples/remix&template=remix) [![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/vercel/vercel/tree/main/examples/remix&template=remix)

View File

@@ -1,5 +1,26 @@
# @vercel-internals/types # @vercel-internals/types
## 1.0.17
### Patch Changes
- Updated dependencies [[`dfe47f6e6`](https://github.com/vercel/vercel/commit/dfe47f6e6c1d395ae24d802f4b7c98e39b9f90f4)]:
- @vercel/build-utils@7.3.0
## 1.0.16
### Patch Changes
- Updated dependencies [[`88da7463c`](https://github.com/vercel/vercel/commit/88da7463ce12df91d49fbde85cb617030d55f558)]:
- @vercel/build-utils@7.2.5
## 1.0.15
### Patch Changes
- Updated dependencies [[`65dec5b7e`](https://github.com/vercel/vercel/commit/65dec5b7e752f4da8fe0ffdb25215170453f6f8b)]:
- @vercel/build-utils@7.2.4
## 1.0.14 ## 1.0.14
### Patch Changes ### Patch Changes

View File

@@ -428,7 +428,8 @@ export type ProjectLinkedError = {
| 'TEAM_DELETED' | 'TEAM_DELETED'
| 'PATH_IS_FILE' | 'PATH_IS_FILE'
| 'INVALID_ROOT_DIRECTORY' | 'INVALID_ROOT_DIRECTORY'
| 'MISSING_PROJECT_SETTINGS'; | 'MISSING_PROJECT_SETTINGS'
| 'TOO_MANY_PROJECTS';
}; };
export type ProjectLinkResult = export type ProjectLinkResult =

View File

@@ -1,7 +1,7 @@
{ {
"private": true, "private": true,
"name": "@vercel-internals/types", "name": "@vercel-internals/types",
"version": "1.0.14", "version": "1.0.17",
"types": "index.d.ts", "types": "index.d.ts",
"main": "index.d.ts", "main": "index.d.ts",
"files": [ "files": [
@@ -10,7 +10,7 @@
"dependencies": { "dependencies": {
"@types/node": "14.14.31", "@types/node": "14.14.31",
"@vercel-internals/constants": "1.0.4", "@vercel-internals/constants": "1.0.4",
"@vercel/build-utils": "7.2.3", "@vercel/build-utils": "7.3.0",
"@vercel/routing-utils": "3.1.0" "@vercel/routing-utils": "3.1.0"
}, },
"devDependencies": { "devDependencies": {

View File

@@ -1,5 +1,23 @@
# @vercel/build-utils # @vercel/build-utils
## 7.3.0
### Minor Changes
- [cli] add `--deprecated` option to `vc project ls` command ([#10919](https://github.com/vercel/vercel/pull/10919))
## 7.2.5
### Patch Changes
- Remove Node.js v20 env var check ([#10834](https://github.com/vercel/vercel/pull/10834))
## 7.2.4
### Patch Changes
- Select Node.js version based on what's available in build-container ([#10822](https://github.com/vercel/vercel/pull/10822))
## 7.2.3 ## 7.2.3
### Patch Changes ### Patch Changes

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vercel/build-utils", "name": "@vercel/build-utils",
"version": "7.2.3", "version": "7.3.0",
"license": "Apache-2.0", "license": "Apache-2.0",
"main": "./dist/index.js", "main": "./dist/index.js",
"types": "./dist/index.d.js", "types": "./dist/index.d.js",

View File

@@ -1,60 +1,88 @@
import { statSync } from 'fs';
import { intersects, validRange } from 'semver'; import { intersects, validRange } from 'semver';
import { NodeVersion } from '../types'; import { NodeVersion } from '../types';
import { NowBuildError } from '../errors'; import { NowBuildError } from '../errors';
import debug from '../debug'; import debug from '../debug';
export type NodeVersionMajor = ReturnType<typeof getOptions>[number]['major'];
export const NODE_VERSIONS: NodeVersion[] = [
{ major: 20, range: '20.x', runtime: 'nodejs20.x' },
{ major: 18, range: '18.x', runtime: 'nodejs18.x' },
{
major: 16,
range: '16.x',
runtime: 'nodejs16.x',
discontinueDate: new Date('2024-02-06'),
},
{
major: 14,
range: '14.x',
runtime: 'nodejs14.x',
discontinueDate: new Date('2023-08-15'),
},
{
major: 12,
range: '12.x',
runtime: 'nodejs12.x',
discontinueDate: new Date('2022-10-03'),
},
{
major: 10,
range: '10.x',
runtime: 'nodejs10.x',
discontinueDate: new Date('2021-04-20'),
},
{
major: 8,
range: '8.10.x',
runtime: 'nodejs8.10',
discontinueDate: new Date('2020-01-06'),
},
];
function getOptions() { function getOptions() {
const options = [ return NODE_VERSIONS;
{ major: 18, range: '18.x', runtime: 'nodejs18.x' },
{
major: 16,
range: '16.x',
runtime: 'nodejs16.x',
discontinueDate: new Date('2024-02-06'),
},
{
major: 14,
range: '14.x',
runtime: 'nodejs14.x',
discontinueDate: new Date('2023-08-15'),
},
{
major: 12,
range: '12.x',
runtime: 'nodejs12.x',
discontinueDate: new Date('2022-10-03'),
},
{
major: 10,
range: '10.x',
runtime: 'nodejs10.x',
discontinueDate: new Date('2021-04-20'),
},
{
major: 8,
range: '8.10.x',
runtime: 'nodejs8.10',
discontinueDate: new Date('2020-01-06'),
},
] as const;
if (process.env.VERCEL_ALLOW_NODEJS20 === '1') {
return [
{ major: 20, range: '20.x', runtime: 'nodejs20.x' },
...options,
] as const;
}
return options;
} }
function getHint(isAuto = false) { function isNodeVersionAvailable(version: NodeVersion): boolean {
const { major, range } = getLatestNodeVersion(); try {
return statSync(`/node${version.major}`).isDirectory();
} catch {
// ENOENT, or any other error, we don't care about
}
return false;
}
export function getAvailableNodeVersions(): NodeVersionMajor[] {
return getOptions()
.filter(isNodeVersionAvailable)
.map(n => n.major);
}
function getHint(isAuto = false, availableVersions?: NodeVersionMajor[]) {
const { major, range } = getLatestNodeVersion(availableVersions);
return isAuto return isAuto
? `Please set Node.js Version to ${range} in your Project Settings to use Node.js ${major}.` ? `Please set Node.js Version to ${range} in your Project Settings to use Node.js ${major}.`
: `Please set "engines": { "node": "${range}" } in your \`package.json\` file to use Node.js ${major}.`; : `Please set "engines": { "node": "${range}" } in your \`package.json\` file to use Node.js ${major}.`;
} }
export function getLatestNodeVersion() { export function getLatestNodeVersion(availableVersions?: NodeVersionMajor[]) {
return getOptions()[0]; const all = getOptions();
if (availableVersions) {
// Return the first node version that is definitely
// available in the build-container.
for (const version of all) {
for (const major of availableVersions) {
if (version.major === major) {
return version;
}
}
}
}
// As a fallback for local `vc build` and the tests,
// return the first node version if none is found.
return all[0];
} }
export function getDiscontinuedNodeVersions(): NodeVersion[] { export function getDiscontinuedNodeVersions(): NodeVersion[] {
@@ -63,9 +91,10 @@ export function getDiscontinuedNodeVersions(): NodeVersion[] {
export async function getSupportedNodeVersion( export async function getSupportedNodeVersion(
engineRange: string | undefined, engineRange: string | undefined,
isAuto = false isAuto = false,
availableVersions?: NodeVersionMajor[]
): Promise<NodeVersion> { ): Promise<NodeVersion> {
let selection: NodeVersion = getLatestNodeVersion(); let selection: NodeVersion | undefined;
if (engineRange) { if (engineRange) {
const found = const found =
@@ -74,19 +103,29 @@ export async function getSupportedNodeVersion(
// the array is already in order so return the first // the array is already in order so return the first
// match which will be the newest version of node // match which will be the newest version of node
selection = o; selection = o;
return intersects(o.range, engineRange); return (
intersects(o.range, engineRange) &&
(availableVersions?.length
? availableVersions.includes(o.major)
: true)
);
}); });
if (!found) { if (!found) {
throw new NowBuildError({ throw new NowBuildError({
code: 'BUILD_UTILS_NODE_VERSION_INVALID', code: 'BUILD_UTILS_NODE_VERSION_INVALID',
link: 'http://vercel.link/node-version', link: 'http://vercel.link/node-version',
message: `Found invalid Node.js Version: "${engineRange}". ${getHint( message: `Found invalid Node.js Version: "${engineRange}". ${getHint(
isAuto isAuto,
availableVersions
)}`, )}`,
}); });
} }
} }
if (!selection) {
selection = getLatestNodeVersion(availableVersions);
}
if (isDiscontinued(selection)) { if (isDiscontinued(selection)) {
const intro = `Node.js Version "${selection.range}" is discontinued and must be upgraded.`; const intro = `Node.js Version "${selection.range}" is discontinued and must be upgraded.`;
throw new NowBuildError({ throw new NowBuildError({

View File

@@ -9,7 +9,11 @@ import { deprecate } from 'util';
import debug from '../debug'; import debug from '../debug';
import { NowBuildError } from '../errors'; import { NowBuildError } from '../errors';
import { Meta, PackageJson, NodeVersion, Config } from '../types'; import { Meta, PackageJson, NodeVersion, Config } from '../types';
import { getSupportedNodeVersion, getLatestNodeVersion } from './node-version'; import {
getSupportedNodeVersion,
getLatestNodeVersion,
getAvailableNodeVersions,
} from './node-version';
import { readConfigFile } from './read-config-file'; import { readConfigFile } from './read-config-file';
import { cloneEnv } from '../clone-env'; import { cloneEnv } from '../clone-env';
@@ -238,9 +242,10 @@ export async function getNodeVersion(
destPath: string, destPath: string,
nodeVersionFallback = process.env.VERCEL_PROJECT_SETTINGS_NODE_VERSION, nodeVersionFallback = process.env.VERCEL_PROJECT_SETTINGS_NODE_VERSION,
config: Config = {}, config: Config = {},
meta: Meta = {} meta: Meta = {},
availableVersions = getAvailableNodeVersions()
): Promise<NodeVersion> { ): Promise<NodeVersion> {
const latest = getLatestNodeVersion(); const latest = getLatestNodeVersion(availableVersions);
if (meta.isDev) { if (meta.isDev) {
// Use the system-installed version of `node` in PATH for `vercel dev` // Use the system-installed version of `node` in PATH for `vercel dev`
return { ...latest, runtime: 'nodejs' }; return { ...latest, runtime: 'nodejs' };
@@ -266,7 +271,7 @@ export async function getNodeVersion(
nodeVersion = node; nodeVersion = node;
isAuto = false; isAuto = false;
} }
return getSupportedNodeVersion(nodeVersion, isAuto); return getSupportedNodeVersion(nodeVersion, isAuto, availableVersions);
} }
export async function scanParentDirs( export async function scanParentDirs(

View File

@@ -104,3 +104,5 @@ export * from './should-serve';
export * from './schemas'; export * from './schemas';
export * from './types'; export * from './types';
export * from './errors'; export * from './errors';
export { NODE_VERSIONS } from './fs/node-version';

View File

@@ -60,7 +60,7 @@ it('should only match supported node versions, otherwise throw an error', async
); );
const autoMessage = const autoMessage =
'Please set Node.js Version to 18.x in your Project Settings to use Node.js 18.'; 'Please set Node.js Version to 20.x in your Project Settings to use Node.js 20.';
await expectBuilderError( await expectBuilderError(
getSupportedNodeVersion('8.11.x', true), getSupportedNodeVersion('8.11.x', true),
autoMessage autoMessage
@@ -80,7 +80,7 @@ it('should only match supported node versions, otherwise throw an error', async
); );
const foundMessage = const foundMessage =
'Please set "engines": { "node": "18.x" } in your `package.json` file to use Node.js 18.'; 'Please set "engines": { "node": "20.x" } in your `package.json` file to use Node.js 20.';
await expectBuilderError( await expectBuilderError(
getSupportedNodeVersion('8.11.x', false), getSupportedNodeVersion('8.11.x', false),
foundMessage foundMessage
@@ -101,8 +101,8 @@ it('should match all semver ranges', async () => {
// See https://docs.npmjs.com/files/package.json#engines // See https://docs.npmjs.com/files/package.json#engines
expect(await getSupportedNodeVersion('16.0.0')).toHaveProperty('major', 16); expect(await getSupportedNodeVersion('16.0.0')).toHaveProperty('major', 16);
expect(await getSupportedNodeVersion('16.x')).toHaveProperty('major', 16); expect(await getSupportedNodeVersion('16.x')).toHaveProperty('major', 16);
expect(await getSupportedNodeVersion('>=10')).toHaveProperty('major', 18); expect(await getSupportedNodeVersion('>=10')).toHaveProperty('major', 20);
expect(await getSupportedNodeVersion('>=10.3.0')).toHaveProperty('major', 18); expect(await getSupportedNodeVersion('>=10.3.0')).toHaveProperty('major', 20);
expect(await getSupportedNodeVersion('16.5.0 - 16.9.0')).toHaveProperty( expect(await getSupportedNodeVersion('16.5.0 - 16.9.0')).toHaveProperty(
'major', 'major',
16 16
@@ -120,11 +120,33 @@ it('should match all semver ranges', async () => {
}); });
it('should allow nodejs18.x', async () => { it('should allow nodejs18.x', async () => {
expect(getLatestNodeVersion()).toHaveProperty('major', 18);
expect(await getSupportedNodeVersion('18.x')).toHaveProperty('major', 18); expect(await getSupportedNodeVersion('18.x')).toHaveProperty('major', 18);
expect(await getSupportedNodeVersion('18')).toHaveProperty('major', 18); expect(await getSupportedNodeVersion('18')).toHaveProperty('major', 18);
expect(await getSupportedNodeVersion('18.1.0')).toHaveProperty('major', 18); expect(await getSupportedNodeVersion('18.1.0')).toHaveProperty('major', 18);
expect(await getSupportedNodeVersion('>=16')).toHaveProperty('major', 18); });
it('should allow nodejs20.x', async () => {
expect(getLatestNodeVersion()).toHaveProperty('major', 20);
expect(await getSupportedNodeVersion('20.x')).toHaveProperty('major', 20);
expect(await getSupportedNodeVersion('20')).toHaveProperty('major', 20);
expect(await getSupportedNodeVersion('20.1.0')).toHaveProperty('major', 20);
expect(await getSupportedNodeVersion('>=18')).toHaveProperty('major', 20);
});
it('should not allow nodejs20.x when not available', async () => {
// Simulates AL2 build-container
await expect(
getSupportedNodeVersion('20.x', true, [14, 16, 18])
).rejects.toThrow(
'Found invalid Node.js Version: "20.x". Please set Node.js Version to 18.x in your Project Settings to use Node.js 18.'
);
});
it('should not allow nodejs18.x when not available', async () => {
// Simulates AL2023 build-container
await expect(getSupportedNodeVersion('18.x', true, [20])).rejects.toThrow(
'Found invalid Node.js Version: "18.x". Please set Node.js Version to 20.x in your Project Settings to use Node.js 20.'
);
}); });
it('should ignore node version in vercel dev getNodeVersion()', async () => { it('should ignore node version in vercel dev getNodeVersion()', async () => {
@@ -193,7 +215,7 @@ it('should warn when package.json engines is greater than', async () => {
{}, {},
{} {}
) )
).toHaveProperty('range', '18.x'); ).toHaveProperty('range', '20.x');
expect(warningMessages).toStrictEqual([ expect(warningMessages).toStrictEqual([
'Warning: Detected "engines": { "node": ">=16" } in your `package.json` that will automatically upgrade when a new major Node.js Version is released. Learn More: http://vercel.link/node-version', 'Warning: Detected "engines": { "node": ">=16" } in your `package.json` that will automatically upgrade when a new major Node.js Version is released. Learn More: http://vercel.link/node-version',
]); ]);
@@ -232,7 +254,17 @@ it('should not warn when package.json engines matches project setting from confi
}); });
it('should get latest node version', async () => { it('should get latest node version', async () => {
expect(getLatestNodeVersion()).toHaveProperty('major', 18); expect(getLatestNodeVersion()).toHaveProperty('major', 20);
});
it('should get latest node version with Node 18.x in build-container', async () => {
// Simulates AL2 build-container
expect(getLatestNodeVersion([14, 16, 18])).toHaveProperty('major', 18);
});
it('should get latest node version with Node 20.x in build-container', async () => {
// Simulates AL2023 build-container
expect(getLatestNodeVersion([20])).toHaveProperty('major', 20);
}); });
it('should throw for discontinued versions', async () => { it('should throw for discontinued versions', async () => {
@@ -300,36 +332,19 @@ it('should warn for deprecated versions, soon to be discontinued', async () => {
16 16
); );
expect(warningMessages).toStrictEqual([ expect(warningMessages).toStrictEqual([
'Error: Node.js version 10.x has reached End-of-Life. Deployments created on or after 2021-04-20 will fail to build. Please set "engines": { "node": "18.x" } in your `package.json` file to use Node.js 18.', 'Error: Node.js version 10.x has reached End-of-Life. Deployments created on or after 2021-04-20 will fail to build. Please set "engines": { "node": "20.x" } in your `package.json` file to use Node.js 20.',
'Error: Node.js version 10.x has reached End-of-Life. Deployments created on or after 2021-04-20 will fail to build. Please set Node.js Version to 18.x in your Project Settings to use Node.js 18.', 'Error: Node.js version 10.x has reached End-of-Life. Deployments created on or after 2021-04-20 will fail to build. Please set Node.js Version to 20.x in your Project Settings to use Node.js 20.',
'Error: Node.js version 12.x has reached End-of-Life. Deployments created on or after 2022-10-03 will fail to build. Please set "engines": { "node": "18.x" } in your `package.json` file to use Node.js 18.', 'Error: Node.js version 12.x has reached End-of-Life. Deployments created on or after 2022-10-03 will fail to build. Please set "engines": { "node": "20.x" } in your `package.json` file to use Node.js 20.',
'Error: Node.js version 12.x has reached End-of-Life. Deployments created on or after 2022-10-03 will fail to build. Please set Node.js Version to 18.x in your Project Settings to use Node.js 18.', 'Error: Node.js version 12.x has reached End-of-Life. Deployments created on or after 2022-10-03 will fail to build. Please set Node.js Version to 20.x in your Project Settings to use Node.js 20.',
'Error: Node.js version 14.x has reached End-of-Life. Deployments created on or after 2023-08-15 will fail to build. Please set "engines": { "node": "18.x" } in your `package.json` file to use Node.js 18.', 'Error: Node.js version 14.x has reached End-of-Life. Deployments created on or after 2023-08-15 will fail to build. Please set "engines": { "node": "20.x" } in your `package.json` file to use Node.js 20.',
'Error: Node.js version 14.x has reached End-of-Life. Deployments created on or after 2023-08-15 will fail to build. Please set Node.js Version to 18.x in your Project Settings to use Node.js 18.', 'Error: Node.js version 14.x has reached End-of-Life. Deployments created on or after 2023-08-15 will fail to build. Please set Node.js Version to 20.x in your Project Settings to use Node.js 20.',
'Error: Node.js version 16.x has reached End-of-Life. Deployments created on or after 2024-02-06 will fail to build. Please set "engines": { "node": "18.x" } in your `package.json` file to use Node.js 18.', 'Error: Node.js version 16.x has reached End-of-Life. Deployments created on or after 2024-02-06 will fail to build. Please set "engines": { "node": "20.x" } in your `package.json` file to use Node.js 20.',
'Error: Node.js version 16.x has reached End-of-Life. Deployments created on or after 2024-02-06 will fail to build. Please set Node.js Version to 18.x in your Project Settings to use Node.js 18.', 'Error: Node.js version 16.x has reached End-of-Life. Deployments created on or after 2024-02-06 will fail to build. Please set Node.js Version to 20.x in your Project Settings to use Node.js 20.',
]); ]);
global.Date.now = realDateNow; global.Date.now = realDateNow;
}); });
it('should only allow nodejs20.x when env var is set', async () => {
try {
expect(getLatestNodeVersion()).toHaveProperty('major', 18);
await expect(getSupportedNodeVersion('20.x')).rejects.toThrow();
process.env.VERCEL_ALLOW_NODEJS20 = '1';
expect(getLatestNodeVersion()).toHaveProperty('major', 20);
expect(await getSupportedNodeVersion('20.x')).toHaveProperty('major', 20);
expect(await getSupportedNodeVersion('20')).toHaveProperty('major', 20);
expect(await getSupportedNodeVersion('20.1.0')).toHaveProperty('major', 20);
expect(await getSupportedNodeVersion('>=16')).toHaveProperty('major', 20);
} finally {
delete process.env.VERCEL_ALLOW_NODEJS20;
}
});
it('should support initialHeaders and initialStatus correctly', async () => { it('should support initialHeaders and initialStatus correctly', async () => {
new Prerender({ new Prerender({
expiration: 1, expiration: 1,

View File

@@ -1,5 +1,86 @@
# vercel # vercel
## 32.7.0
### Minor Changes
- [cli] add `--deprecated` option to `vc project ls` command ([#10919](https://github.com/vercel/vercel/pull/10919))
### Patch Changes
- Remove some debug statements and make log into warning ([#10926](https://github.com/vercel/vercel/pull/10926))
- Updated dependencies [[`3cede43ca`](https://github.com/vercel/vercel/commit/3cede43ca7ea3aec3ff33864b7d33da57891ddb2), [`dfe47f6e6`](https://github.com/vercel/vercel/commit/dfe47f6e6c1d395ae24d802f4b7c98e39b9f90f4), [`1dbb22bb6`](https://github.com/vercel/vercel/commit/1dbb22bb6d33657faa78376f527fe350188c5257), [`204c3592c`](https://github.com/vercel/vercel/commit/204c3592c78fc544e62f0210b0e7e1e4cd382a0c)]:
- @vercel/ruby@2.0.4
- @vercel/build-utils@7.3.0
- @vercel/remix-builder@2.0.13
- @vercel/node@3.0.12
- @vercel/static-build@2.0.14
## 32.6.1
### Patch Changes
- Revert "forbids globally installed @vercel/speed-insights and @vercel/analytics (#10848)" ([#10895](https://github.com/vercel/vercel/pull/10895))
## 32.6.0
### Minor Changes
- forbids globally installed @vercel/speed-insights and @vercel/analytics ([#10848](https://github.com/vercel/vercel/pull/10848))
### Patch Changes
- [cli] Fix behavior for combination of northstar user + team scope provided to cli as an argument. ([#10884](https://github.com/vercel/vercel/pull/10884))
- Updated dependencies [[`4edfcd74b`](https://github.com/vercel/vercel/commit/4edfcd74b6dfd8e9cbc05a71d47578051a2a7d63), [`0e9bb30fd`](https://github.com/vercel/vercel/commit/0e9bb30fd285492beadc365bece2ab1df67b387b), [`ca2cbf06f`](https://github.com/vercel/vercel/commit/ca2cbf06fbf252e23aff6e007d0df5ffc243b56e), [`c52bdf775`](https://github.com/vercel/vercel/commit/c52bdf77585dfa41b25cabe2f9403827d0964169)]:
- @vercel/remix-builder@2.0.12
- @vercel/static-build@2.0.13
- @vercel/go@3.0.4
## 32.5.6
### Patch Changes
- Updated dependencies [[`ffd2f34c6`](https://github.com/vercel/vercel/commit/ffd2f34c6c3d53bbb673aa3241845abc50e67c5e), [`4636ae54c`](https://github.com/vercel/vercel/commit/4636ae54c6c17709c1a058169cdca19c3df73ddb)]:
- @vercel/next@4.0.15
- @vercel/ruby@2.0.3
## 32.5.5
### Patch Changes
- Updated dependencies [[`88da7463c`](https://github.com/vercel/vercel/commit/88da7463ce12df91d49fbde85cb617030d55f558)]:
- @vercel/build-utils@7.2.5
- @vercel/node@3.0.11
- @vercel/static-build@2.0.12
## 32.5.4
### Patch Changes
- Updated dependencies [[`65dec5b7e`](https://github.com/vercel/vercel/commit/65dec5b7e752f4da8fe0ffdb25215170453f6f8b)]:
- @vercel/build-utils@7.2.4
- @vercel/node@3.0.10
- @vercel/static-build@2.0.11
## 32.5.3
### Patch Changes
- Handle `TooManyProjects` error in places where projects are created ([#10807](https://github.com/vercel/vercel/pull/10807))
- Updated dependencies [[`89c1e0323`](https://github.com/vercel/vercel/commit/89c1e032335d9ec0fcfc84fe499cf004fe73fafc), [`fd29b966d`](https://github.com/vercel/vercel/commit/fd29b966d39776318b0e11a53909edb43d1fc5f2)]:
- @vercel/node@3.0.9
- @vercel/next@4.0.14
## 32.5.2
### Patch Changes
- Updated dependencies [[`c94a082f6`](https://github.com/vercel/vercel/commit/c94a082f6bb1b84eaf420ac47ea83640dc83668e)]:
- @vercel/next@4.0.13
## 32.5.1 ## 32.5.1
### Patch Changes ### Patch Changes

View File

@@ -1,6 +1,6 @@
{ {
"name": "vercel", "name": "vercel",
"version": "32.5.1", "version": "32.7.0",
"preferGlobal": true, "preferGlobal": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"description": "The command-line interface for Vercel", "description": "The command-line interface for Vercel",
@@ -31,17 +31,17 @@
"node": ">= 16" "node": ">= 16"
}, },
"dependencies": { "dependencies": {
"@vercel/build-utils": "7.2.3", "@vercel/build-utils": "7.3.0",
"@vercel/fun": "1.1.0", "@vercel/fun": "1.1.0",
"@vercel/go": "3.0.3", "@vercel/go": "3.0.4",
"@vercel/hydrogen": "1.0.1", "@vercel/hydrogen": "1.0.1",
"@vercel/next": "4.0.12", "@vercel/next": "4.0.15",
"@vercel/node": "3.0.8", "@vercel/node": "3.0.12",
"@vercel/python": "4.1.0", "@vercel/python": "4.1.0",
"@vercel/redwood": "2.0.5", "@vercel/redwood": "2.0.5",
"@vercel/remix-builder": "2.0.11", "@vercel/remix-builder": "2.0.13",
"@vercel/ruby": "2.0.2", "@vercel/ruby": "2.0.4",
"@vercel/static-build": "2.0.10", "@vercel/static-build": "2.0.14",
"chokidar": "3.3.1" "chokidar": "3.3.1"
}, },
"devDependencies": { "devDependencies": {
@@ -88,11 +88,11 @@
"@types/yauzl-promise": "2.1.0", "@types/yauzl-promise": "2.1.0",
"@vercel-internals/constants": "1.0.4", "@vercel-internals/constants": "1.0.4",
"@vercel-internals/get-package-json": "1.0.0", "@vercel-internals/get-package-json": "1.0.0",
"@vercel-internals/types": "1.0.14", "@vercel-internals/types": "1.0.17",
"@vercel/client": "13.0.7", "@vercel/client": "13.0.10",
"@vercel/error-utils": "2.0.2", "@vercel/error-utils": "2.0.2",
"@vercel/frameworks": "2.0.3", "@vercel/frameworks": "2.0.5",
"@vercel/fs-detectors": "5.1.3", "@vercel/fs-detectors": "5.1.5",
"@vercel/routing-utils": "3.1.0", "@vercel/routing-utils": "3.1.0",
"ajv": "6.12.2", "ajv": "6.12.2",
"alpha-sort": "2.0.1", "alpha-sort": "2.0.1",

View File

@@ -3,6 +3,7 @@ import ms from 'ms';
import Client from '../../util/client'; import Client from '../../util/client';
import { isAPIError } from '../../util/errors-ts'; import { isAPIError } from '../../util/errors-ts';
import { getCommandName } from '../../util/pkg-name'; import { getCommandName } from '../../util/pkg-name';
import createProject from '../../util/projects/create-project';
export default async function add( export default async function add(
client: Client, client: Client,
@@ -32,12 +33,14 @@ export default async function add(
const start = Date.now(); const start = Date.now();
const [name] = args; const [name] = args;
try { try {
await client.fetch('/projects', { await createProject(client, { name });
method: 'POST',
body: { name },
});
} catch (err: unknown) { } catch (err: unknown) {
if (isAPIError(err) && err.code === 'too_many_projects') {
output.prettyError(err);
return 1;
}
if (isAPIError(err) && err.status === 409) { if (isAPIError(err) && err.status === 409) {
// project already exists, so we can // project already exists, so we can
// show a success message // show a success message

View File

@@ -15,7 +15,17 @@ export const projectCommand: Command = {
name: 'ls', name: 'ls',
description: 'Show all projects in the selected scope', description: 'Show all projects in the selected scope',
arguments: [], arguments: [],
options: [], options: [
{
name: 'deprecated',
description: 'A list of projects affected by a deprecation',
argument: 'deprecated',
shorthand: null,
type: 'boolean',
deprecated: false,
multi: false,
},
],
examples: [], examples: [],
}, },
{ {

View File

@@ -23,6 +23,7 @@ export default async function main(client: Client) {
argv = getArgs(client.argv.slice(2), { argv = getArgs(client.argv.slice(2), {
'--next': Number, '--next': Number,
'-N': '--next', '-N': '--next',
'--deprecated': Boolean,
}); });
} catch (error) { } catch (error) {
handleError(error); handleError(error);

View File

@@ -6,6 +6,7 @@ import Client from '../../util/client';
import getCommandFlags from '../../util/get-command-flags'; import getCommandFlags from '../../util/get-command-flags';
import { getCommandName } from '../../util/pkg-name'; import { getCommandName } from '../../util/pkg-name';
import strlen from '../../util/strlen'; import strlen from '../../util/strlen';
import { NODE_VERSIONS } from '@vercel/build-utils';
export default async function list( export default async function list(
client: Client, client: Client,
@@ -34,7 +35,9 @@ export default async function list(
projectsUrl += `&until=${next}`; projectsUrl += `&until=${next}`;
} }
const { const deprecated = argv['--deprecated'] || false;
let {
projects: projectList, projects: projectList,
pagination, pagination,
}: { }: {
@@ -48,10 +51,37 @@ export default async function list(
const elapsed = ms(Date.now() - start); const elapsed = ms(Date.now() - start);
if (deprecated) {
const upcomingDeprecationVersions = NODE_VERSIONS.filter(
nodeVersion =>
nodeVersion.discontinueDate &&
nodeVersion.discontinueDate.valueOf() > Date.now()
);
const upcomingDeprecationVersionsList = upcomingDeprecationVersions.map(
nodeVersion => nodeVersion.range
);
projectList = projectList.filter(
project =>
project.nodeVersion &&
upcomingDeprecationVersionsList.includes(project.nodeVersion)
);
output.warn(
`The following Node.js versions will be deprecated soon: ${upcomingDeprecationVersionsList.join(
', '
)}. Upgrade your projects immediately.`
);
output.log(
`For more information visit: https://vercel.com/docs/functions/serverless-functions/runtimes/node-js#node.js-version`
);
}
output.log( output.log(
`${ `${
projectList.length > 0 ? 'Projects' : 'No projects' projectList.length > 0 ? 'Projects' : 'No projects'
} found under ${chalk.bold(contextName)} ${chalk.gray(`[${elapsed}]`)}` } found under ${chalk.bold(contextName)} ${
deprecated ? 'that are using a deprecated Node.js version' : '\b'
} ${chalk.gray(`[${elapsed}]`)}`
); );
if (projectList.length > 0) { if (projectList.length > 0) {

View File

@@ -43,10 +43,13 @@ export default async function selectOrg(
})), })),
]; ];
const defaultOrgIndex = teams.findIndex(team => team.id === currentTeam) + 1; const defaultChoiceIndex = Math.max(
choices.findIndex(choice => choice.value.id === currentTeam),
0
);
if (autoConfirm) { if (autoConfirm) {
return choices[defaultOrgIndex].value; return choices[defaultChoiceIndex].value;
} }
const answers = await client.prompt({ const answers = await client.prompt({
@@ -54,7 +57,7 @@ export default async function selectOrg(
name: 'org', name: 'org',
message: question, message: question,
choices, choices,
default: defaultOrgIndex, default: defaultChoiceIndex,
}); });
const org = answers.org; const org = answers.org;

View File

@@ -21,6 +21,7 @@ import createProject from '../projects/create-project';
import { detectProjects } from '../projects/detect-projects'; import { detectProjects } from '../projects/detect-projects';
import { repoInfoToUrl } from '../git/repo-info-to-url'; import { repoInfoToUrl } from '../git/repo-info-to-url';
import { connectGitProvider, parseRepoUrl } from '../git/connect-git-provider'; import { connectGitProvider, parseRepoUrl } from '../git/connect-git-provider';
import { isAPIError } from '../errors-ts';
const home = homedir(); const home = homedir();
@@ -283,24 +284,31 @@ export async function ensureRepoLink(
output.spinner(`Creating new Project: ${orgAndName}`); output.spinner(`Creating new Project: ${orgAndName}`);
delete selection.newProject; delete selection.newProject;
if (!selection.rootDirectory) delete selection.rootDirectory; if (!selection.rootDirectory) delete selection.rootDirectory;
const project = (selected[i] = await createProject(client, { try {
...selection, const project = (selected[i] = await createProject(client, {
framework: selection.framework.slug, ...selection,
})); framework: selection.framework.slug,
await connectGitProvider( }));
client, await connectGitProvider(
org, client,
project.id, org,
parsedRepoUrl.provider, project.id,
`${parsedRepoUrl.org}/${parsedRepoUrl.repo}` parsedRepoUrl.provider,
); `${parsedRepoUrl.org}/${parsedRepoUrl.repo}`
output.log( );
`Created new Project: ${output.link( output.log(
orgAndName, `Created new Project: ${output.link(
`https://vercel.com/${orgAndName}`, orgAndName,
{ fallback: false } `https://vercel.com/${orgAndName}`,
)}` { fallback: false }
); )}`
);
} catch (err) {
if (isAPIError(err) && err.code === 'too_many_projects') {
output.prettyError(err);
return;
}
}
} }
repoConfig = { repoConfig = {

View File

@@ -263,6 +263,10 @@ export default async function setupAndLink(
return { status: 'linked', org, project }; return { status: 'linked', org, project };
} catch (err) { } catch (err) {
if (isAPIError(err) && err.code === 'too_many_projects') {
output.prettyError(err);
return { status: 'error', exitCode: 1, reason: 'TOO_MANY_PROJECTS' };
}
handleError(err); handleError(err);
return { status: 'error', exitCode: 1 }; return { status: 'error', exitCode: 1 };

View File

@@ -238,51 +238,59 @@ test('[vc build] should build project with corepack and select npm@8.1.0', async
}); });
test('[vc build] should build project with corepack and select pnpm@7.1.0', async () => { test('[vc build] should build project with corepack and select pnpm@7.1.0', async () => {
process.env.ENABLE_EXPERIMENTAL_COREPACK = '1'; try {
const directory = await setupE2EFixture('vc-build-corepack-pnpm'); process.env.ENABLE_EXPERIMENTAL_COREPACK = '1';
const before = await exec(directory, 'pnpm', ['--version']); const directory = await setupE2EFixture('vc-build-corepack-pnpm');
const output = await execCli(binaryPath, ['build'], { cwd: directory }); const before = await exec(directory, 'pnpm', ['--version']);
expect(output.exitCode, formatOutput(output)).toBe(0); const output = await execCli(binaryPath, ['build'], { cwd: directory });
expect(output.stderr).toMatch(/Build Completed/gm); expect(output.exitCode, formatOutput(output)).toBe(0);
const after = await exec(directory, 'pnpm', ['--version']); expect(output.stderr).toMatch(/Build Completed/gm);
// Ensure global pnpm didn't change const after = await exec(directory, 'pnpm', ['--version']);
expect(before.stdout).toBe(after.stdout); // Ensure global pnpm didn't change
// Ensure version is correct expect(before.stdout).toBe(after.stdout);
expect( // Ensure version is correct
await fs.readFile( expect(
path.join(directory, '.vercel/output/static/index.txt'), await fs.readFile(
'utf8' path.join(directory, '.vercel/output/static/index.txt'),
) 'utf8'
).toBe('7.1.0\n'); )
// Ensure corepack will be cached ).toBe('7.1.0\n');
const contents = fs.readdirSync( // Ensure corepack will be cached
path.join(directory, '.vercel/cache/corepack') const contents = fs.readdirSync(
); path.join(directory, '.vercel/cache/corepack')
expect(contents).toEqual(['home', 'shim']); );
expect(contents).toEqual(['home', 'shim']);
} finally {
delete process.env.ENABLE_EXPERIMENTAL_COREPACK;
}
}); });
test('[vc build] should build project with corepack and select yarn@2.4.3', async () => { test('[vc build] should build project with corepack and select yarn@2.4.3', async () => {
process.env.ENABLE_EXPERIMENTAL_COREPACK = '1'; try {
const directory = await setupE2EFixture('vc-build-corepack-yarn'); process.env.ENABLE_EXPERIMENTAL_COREPACK = '1';
const before = await exec(directory, 'yarn', ['--version']); const directory = await setupE2EFixture('vc-build-corepack-yarn');
const output = await execCli(binaryPath, ['build'], { cwd: directory }); const before = await exec(directory, 'yarn', ['--version']);
expect(output.exitCode, formatOutput(output)).toBe(0); const output = await execCli(binaryPath, ['build'], { cwd: directory });
expect(output.stderr).toMatch(/Build Completed/gm); expect(output.exitCode, formatOutput(output)).toBe(0);
const after = await exec(directory, 'yarn', ['--version']); expect(output.stderr).toMatch(/Build Completed/gm);
// Ensure global yarn didn't change const after = await exec(directory, 'yarn', ['--version']);
expect(before.stdout).toBe(after.stdout); // Ensure global yarn didn't change
// Ensure version is correct expect(before.stdout).toBe(after.stdout);
expect( // Ensure version is correct
await fs.readFile( expect(
path.join(directory, '.vercel/output/static/index.txt'), await fs.readFile(
'utf8' path.join(directory, '.vercel/output/static/index.txt'),
) 'utf8'
).toBe('2.4.3\n'); )
// Ensure corepack will be cached ).toBe('2.4.3\n');
const contents = fs.readdirSync( // Ensure corepack will be cached
path.join(directory, '.vercel/cache/corepack') const contents = fs.readdirSync(
); path.join(directory, '.vercel/cache/corepack')
expect(contents).toEqual(['home', 'shim']); );
expect(contents).toEqual(['home', 'shim']);
} finally {
delete process.env.ENABLE_EXPERIMENTAL_COREPACK;
}
}); });
test('[vc dev] should print help from `vc develop --help`', async () => { test('[vc dev] should print help from `vc develop --help`', async () => {

View File

@@ -353,11 +353,11 @@ export function useProject(
}); });
client.scenario.get(`/v4/projects`, (req, res) => { client.scenario.get(`/v4/projects`, (req, res) => {
res.json({ res.json({
projects: [defaultProject], projects: [project],
pagination: null, pagination: null,
}); });
}); });
client.scenario.post(`/projects`, (req, res) => { client.scenario.post(`/v1/projects`, (req, res) => {
const { name } = req.body; const { name } = req.body;
if (name === project.name) { if (name === project.name) {
res.json(project); res.json(project);

View File

@@ -5,10 +5,7 @@ import { useTeams } from '../../mocks/team';
import { defaultProject, useProject } from '../../mocks/project'; import { defaultProject, useProject } from '../../mocks/project';
import { client } from '../../mocks/client'; import { client } from '../../mocks/client';
import type { Project } from '@vercel-internals/types'; import type { Project } from '@vercel-internals/types';
import { import { parseSpacedTableRow } from '../../helpers/parse-table';
pluckIdentifiersFromDeploymentList,
parseSpacedTableRow,
} from '../../helpers/parse-table';
describe('project', () => { describe('project', () => {
describe('list', () => { describe('list', () => {
@@ -28,8 +25,7 @@ describe('project', () => {
expect(line.value).toEqual(`Fetching projects in ${user.username}`); expect(line.value).toEqual(`Fetching projects in ${user.username}`);
line = await lines.next(); line = await lines.next();
const { org } = pluckIdentifiersFromDeploymentList(line.value!); expect(line.value).toContain(user.username);
expect(org).toEqual(user.username);
// empty line // empty line
line = await lines.next(); line = await lines.next();
@@ -49,6 +45,55 @@ describe('project', () => {
expect(data).toEqual([project.project.name, 'https://foobar.com']); expect(data).toEqual([project.project.name, 'https://foobar.com']);
}); });
it('should list projects running on an soon-to-be-deprecated Node.js version', async () => {
jest.useFakeTimers().setSystemTime(new Date('2023-12-08'));
const user = useUser();
useTeams('team_dummy');
const project = useProject({
...defaultProject,
nodeVersion: '16.x',
});
client.setArgv('project', 'ls', '--deprecated');
await projects(client);
const lines = createLineIterator(client.stderr);
let line = await lines.next();
expect(line.value).toEqual(`Fetching projects in ${user.username}`);
line = await lines.next();
expect(line.value).toEqual(
'WARN! The following Node.js versions will be deprecated soon: 16.x. Upgrade your projects immediately.'
);
line = await lines.next();
expect(line.value).toEqual(
'> For more information visit: https://vercel.com/docs/functions/serverless-functions/runtimes/node-js#node.js-version'
);
line = await lines.next();
expect(line.value).toContain(user.username);
// empty line
line = await lines.next();
expect(line.value).toEqual('');
line = await lines.next();
const header = parseSpacedTableRow(line.value!);
expect(header).toEqual([
'Project Name',
'Latest Production URL',
'Updated',
]);
line = await lines.next();
const data = parseSpacedTableRow(line.value!);
data.pop();
expect(data).toEqual([project.project.name, 'https://foobar.com']);
jest.clearAllTimers();
});
it('should list projects when there is no production deployment', async () => { it('should list projects when there is no production deployment', async () => {
const user = useUser(); const user = useUser();
useTeams('team_dummy'); useTeams('team_dummy');
@@ -66,8 +111,7 @@ describe('project', () => {
expect(line.value).toEqual(`Fetching projects in ${user.username}`); expect(line.value).toEqual(`Fetching projects in ${user.username}`);
line = await lines.next(); line = await lines.next();
const { org } = pluckIdentifiersFromDeploymentList(line.value!); expect(line.value).toContain(user.username);
expect(org).toEqual(user.username);
// empty line // empty line
line = await lines.next(); line = await lines.next();

View File

@@ -4,10 +4,19 @@ import { useTeams } from '../../../mocks/team';
import { useUser } from '../../../mocks/user'; import { useUser } from '../../../mocks/user';
describe('selectOrg', () => { describe('selectOrg', () => {
let user;
let team;
beforeEach(() => {
team = useTeams()[0];
});
describe('non-northstar', () => { describe('non-northstar', () => {
beforeEach(() => {
user = useUser();
});
it('should allow selecting user', async () => { it('should allow selecting user', async () => {
const user = useUser();
useTeams();
const selectOrgPromise = selectOrg(client, 'Select the scope'); const selectOrgPromise = selectOrg(client, 'Select the scope');
await expect(client.stderr).toOutput(user.name); await expect(client.stderr).toOutput(user.name);
client.stdin.write('\r'); // Return key client.stdin.write('\r'); // Return key
@@ -15,26 +24,71 @@ describe('selectOrg', () => {
}); });
it('should allow selecting team', async () => { it('should allow selecting team', async () => {
useUser();
const team = useTeams()[0];
const selectOrgPromise = selectOrg(client, 'Select the scope'); const selectOrgPromise = selectOrg(client, 'Select the scope');
await expect(client.stderr).toOutput('Select the scope'); await expect(client.stderr).toOutput('Select the scope');
client.stdin.write('\x1B[B'); // Down arrow client.stdin.write('\x1B[B'); // Down arrow
client.stdin.write('\r'); // Return key client.stdin.write('\r'); // Return key
await expect(selectOrgPromise).resolves.toHaveProperty('id', team.id); await expect(selectOrgPromise).resolves.toHaveProperty('id', team.id);
}); });
it('automatically selects the correct scope when autoconfirm flag is passed', async () => {
const selectOrgPromise = selectOrg(client, 'Select the scope', true);
await expect(selectOrgPromise).resolves.toHaveProperty('id', user.id);
});
describe('with a selected team scope', () => {
beforeEach(() => {
client.config.currentTeam = team.id;
});
afterEach(() => {
delete client.config.currentTeam;
});
it('should allow selecting user', async () => {
const selectOrgPromise = selectOrg(client, 'Select the scope');
await expect(client.stderr).toOutput(user.name);
client.stdin.write('\r'); // Return key
await expect(selectOrgPromise).resolves.toHaveProperty('id', team.id);
});
it('should allow selecting team', async () => {
const selectOrgPromise = selectOrg(client, 'Select the scope');
await expect(client.stderr).toOutput('Select the scope');
client.stdin.write('\x1B[B'); // Down arrow
client.stdin.write('\r'); // Return key
await expect(selectOrgPromise).resolves.toHaveProperty('id', user.id);
});
it('automatically selects the correct scope when autoconfirm flag is passed', async () => {
const selectOrgPromise = selectOrg(client, 'Select the scope', true);
await expect(selectOrgPromise).resolves.toHaveProperty('id', team.id);
});
});
}); });
describe('northstar', () => { describe('northstar', () => {
it('should not allow selecting user', async () => { beforeEach(() => {
const user = useUser({ user = useUser({
version: 'northstar', version: 'northstar',
}); });
const team = useTeams()[0]; client.config.currentTeam = team.id;
});
afterEach(() => {
delete client.config.currentTeam;
});
it('should not allow selecting user', async () => {
const selectOrgPromise = selectOrg(client, 'Select the scope'); const selectOrgPromise = selectOrg(client, 'Select the scope');
await expect(client.stderr).not.toOutput(user.name); await expect(client.stderr).not.toOutput(user.name);
client.stdin.write('\r'); // Return key client.stdin.write('\r'); // Return key
await expect(selectOrgPromise).resolves.toHaveProperty('id', team.id); await expect(selectOrgPromise).resolves.toHaveProperty('id', team.id);
}); });
it('automatically selects the correct scope when autoconfirm flag is passed', async () => {
const selectOrgPromise = selectOrg(client, 'Select the scope', true);
await expect(selectOrgPromise).resolves.toHaveProperty('id', team.id);
});
}); });
}); });

View File

@@ -1,5 +1,26 @@
# @vercel/client # @vercel/client
## 13.0.10
### Patch Changes
- Updated dependencies [[`dfe47f6e6`](https://github.com/vercel/vercel/commit/dfe47f6e6c1d395ae24d802f4b7c98e39b9f90f4)]:
- @vercel/build-utils@7.3.0
## 13.0.9
### Patch Changes
- Updated dependencies [[`88da7463c`](https://github.com/vercel/vercel/commit/88da7463ce12df91d49fbde85cb617030d55f558)]:
- @vercel/build-utils@7.2.5
## 13.0.8
### Patch Changes
- Updated dependencies [[`65dec5b7e`](https://github.com/vercel/vercel/commit/65dec5b7e752f4da8fe0ffdb25215170453f6f8b)]:
- @vercel/build-utils@7.2.4
## 13.0.7 ## 13.0.7
### Patch Changes ### Patch Changes

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vercel/client", "name": "@vercel/client",
"version": "13.0.7", "version": "13.0.10",
"main": "dist/index.js", "main": "dist/index.js",
"typings": "dist/index.d.ts", "typings": "dist/index.d.ts",
"homepage": "https://vercel.com", "homepage": "https://vercel.com",
@@ -37,7 +37,7 @@
"typescript": "4.9.5" "typescript": "4.9.5"
}, },
"dependencies": { "dependencies": {
"@vercel/build-utils": "7.2.3", "@vercel/build-utils": "7.3.0",
"@vercel/routing-utils": "3.1.0", "@vercel/routing-utils": "3.1.0",
"@zeit/fetch": "5.2.0", "@zeit/fetch": "5.2.0",
"async-retry": "1.2.3", "async-retry": "1.2.3",

View File

@@ -1,5 +1,17 @@
# @vercel/frameworks # @vercel/frameworks
## 2.0.5
### Patch Changes
- This new screenshot matches the template. It removes the version number so this screenshot will not go stale. ([#10921](https://github.com/vercel/vercel/pull/10921))
## 2.0.4
### Patch Changes
- Update placeholder for Nuxt to be correct command. ([#10873](https://github.com/vercel/vercel/pull/10873))
## 2.0.3 ## 2.0.3
### Patch Changes ### Patch Changes

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vercel/frameworks", "name": "@vercel/frameworks",
"version": "2.0.3", "version": "2.0.5",
"main": "./dist/frameworks.js", "main": "./dist/frameworks.js",
"types": "./dist/frameworks.d.ts", "types": "./dist/frameworks.d.ts",
"files": [ "files": [

View File

@@ -66,7 +66,7 @@ export const frameworks = [
darkModeLogo: darkModeLogo:
'https://api-frameworks.vercel.sh/framework-logos/next-dark.svg', 'https://api-frameworks.vercel.sh/framework-logos/next-dark.svg',
screenshot: screenshot:
'https://assets.vercel.com/image/upload/v1673027027/front/import/nextjs.png', 'https://assets.vercel.com/image/upload/v1701461207/front/import/nextjs.png',
tagline: tagline:
'Next.js makes you productive with React instantly — whether you want to build static or dynamic sites.', 'Next.js makes you productive with React instantly — whether you want to build static or dynamic sites.',
description: 'A Next.js app and a Serverless Function API.', description: 'A Next.js app and a Serverless Function API.',
@@ -1456,8 +1456,8 @@ export const frameworks = [
'`yarn install`, `pnpm install`, `npm install`, or `bun install`', '`yarn install`, `pnpm install`, `npm install`, or `bun install`',
}, },
buildCommand: { buildCommand: {
placeholder: '`npm run build` or `nuxt generate`', placeholder: '`npm run build` or `nuxt build`',
value: 'nuxt generate', value: 'nuxt build',
}, },
devCommand: { devCommand: {
value: 'nuxt', value: 'nuxt',

View File

@@ -1,5 +1,19 @@
# @vercel/fs-detectors # @vercel/fs-detectors
## 5.1.5
### Patch Changes
- Updated dependencies [[`e6aaf79d0`](https://github.com/vercel/vercel/commit/e6aaf79d04fafd032d9a28143b02d28766add415)]:
- @vercel/frameworks@2.0.5
## 5.1.4
### Patch Changes
- Updated dependencies [[`a8934da62`](https://github.com/vercel/vercel/commit/a8934da6232b66a98e9ce43ebf5342eac664d40d)]:
- @vercel/frameworks@2.0.4
## 5.1.3 ## 5.1.3
### Patch Changes ### Patch Changes

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vercel/fs-detectors", "name": "@vercel/fs-detectors",
"version": "5.1.3", "version": "5.1.5",
"description": "Vercel filesystem detectors", "description": "Vercel filesystem detectors",
"main": "./dist/index.js", "main": "./dist/index.js",
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
@@ -22,7 +22,7 @@
}, },
"dependencies": { "dependencies": {
"@vercel/error-utils": "2.0.2", "@vercel/error-utils": "2.0.2",
"@vercel/frameworks": "2.0.3", "@vercel/frameworks": "2.0.5",
"@vercel/routing-utils": "3.1.0", "@vercel/routing-utils": "3.1.0",
"glob": "8.0.3", "glob": "8.0.3",
"js-yaml": "4.1.0", "js-yaml": "4.1.0",
@@ -37,7 +37,7 @@
"@types/minimatch": "3.0.5", "@types/minimatch": "3.0.5",
"@types/node": "14.18.33", "@types/node": "14.18.33",
"@types/semver": "7.3.10", "@types/semver": "7.3.10",
"@vercel/build-utils": "7.2.3", "@vercel/build-utils": "7.3.0",
"jest-junit": "16.0.0", "jest-junit": "16.0.0",
"typescript": "4.9.5" "typescript": "4.9.5"
} }

View File

@@ -1,5 +1,26 @@
# @vercel/gatsby-plugin-vercel-builder # @vercel/gatsby-plugin-vercel-builder
## 2.0.12
### Patch Changes
- Updated dependencies [[`dfe47f6e6`](https://github.com/vercel/vercel/commit/dfe47f6e6c1d395ae24d802f4b7c98e39b9f90f4)]:
- @vercel/build-utils@7.3.0
## 2.0.11
### Patch Changes
- Updated dependencies [[`88da7463c`](https://github.com/vercel/vercel/commit/88da7463ce12df91d49fbde85cb617030d55f558)]:
- @vercel/build-utils@7.2.5
## 2.0.10
### Patch Changes
- Updated dependencies [[`65dec5b7e`](https://github.com/vercel/vercel/commit/65dec5b7e752f4da8fe0ffdb25215170453f6f8b)]:
- @vercel/build-utils@7.2.4
## 2.0.9 ## 2.0.9
### Patch Changes ### Patch Changes

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vercel/gatsby-plugin-vercel-builder", "name": "@vercel/gatsby-plugin-vercel-builder",
"version": "2.0.9", "version": "2.0.12",
"main": "dist/index.js", "main": "dist/index.js",
"files": [ "files": [
"dist", "dist",
@@ -20,7 +20,7 @@
}, },
"dependencies": { "dependencies": {
"@sinclair/typebox": "0.25.24", "@sinclair/typebox": "0.25.24",
"@vercel/build-utils": "7.2.3", "@vercel/build-utils": "7.3.0",
"@vercel/routing-utils": "3.1.0", "@vercel/routing-utils": "3.1.0",
"esbuild": "0.14.47", "esbuild": "0.14.47",
"etag": "1.8.1", "etag": "1.8.1",

View File

@@ -1,5 +1,11 @@
# @vercel/go # @vercel/go
## 3.0.4
### Patch Changes
- Set Lambda runtime to "provided.al2" ([#10880](https://github.com/vercel/vercel/pull/10880))
## 3.0.3 ## 3.0.3
### Patch Changes ### Patch Changes

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vercel/go", "name": "@vercel/go",
"version": "3.0.3", "version": "3.0.4",
"license": "Apache-2.0", "license": "Apache-2.0",
"main": "./dist/index", "main": "./dist/index",
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/go", "homepage": "https://vercel.com/docs/runtimes#official-runtimes/go",
@@ -29,7 +29,7 @@
"@types/node-fetch": "^2.3.0", "@types/node-fetch": "^2.3.0",
"@types/tar": "6.1.5", "@types/tar": "6.1.5",
"@types/yauzl-promise": "2.1.0", "@types/yauzl-promise": "2.1.0",
"@vercel/build-utils": "7.2.3", "@vercel/build-utils": "7.3.0",
"async-retry": "1.3.3", "async-retry": "1.3.3",
"execa": "^1.0.0", "execa": "^1.0.0",
"fs-extra": "^7.0.0", "fs-extra": "^7.0.0",

View File

@@ -50,7 +50,7 @@ export { shouldServe };
// we need our `main.go` to be called something else // we need our `main.go` to be called something else
const MAIN_GO_FILENAME = 'main__vc__go__.go'; const MAIN_GO_FILENAME = 'main__vc__go__.go';
const HANDLER_FILENAME = `handler${OUT_EXTENSION}`; const HANDLER_FILENAME = `bootstrap${OUT_EXTENSION}`;
interface PortInfo { interface PortInfo {
port: number; port: number;
@@ -249,10 +249,14 @@ export async function build({
await buildHandlerWithGoMod(buildOptions); await buildHandlerWithGoMod(buildOptions);
} }
const runtime =
process.env.VERCEL_USE_GO_PROVIDED_RUNTIME === '1'
? 'provided.al2'
: 'go1.x';
const lambda = new Lambda({ const lambda = new Lambda({
files: { ...(await glob('**', outDir)), ...includedFiles }, files: { ...(await glob('**', outDir)), ...includedFiles },
handler: HANDLER_FILENAME, handler: HANDLER_FILENAME,
runtime: 'go1.x', runtime,
supportsWrapper: true, supportsWrapper: true,
environment: {}, environment: {},
}); });

View File

@@ -26,7 +26,7 @@
"devDependencies": { "devDependencies": {
"@types/jest": "27.5.1", "@types/jest": "27.5.1",
"@types/node": "14.18.33", "@types/node": "14.18.33",
"@vercel/build-utils": "7.2.3", "@vercel/build-utils": "7.3.0",
"execa": "3.2.0", "execa": "3.2.0",
"fs-extra": "11.1.0", "fs-extra": "11.1.0",
"jest-junit": "16.0.0" "jest-junit": "16.0.0"

View File

@@ -1,5 +1,23 @@
# @vercel/next # @vercel/next
## 4.0.15
### Patch Changes
- ensure function configs work for paths inside of route groups ([#10855](https://github.com/vercel/vercel/pull/10855))
## 4.0.14
### Patch Changes
- Fixed headers for static routes when PPR is enabled ([#10808](https://github.com/vercel/vercel/pull/10808))
## 4.0.13
### Patch Changes
- Added `getRequestHandlerWithMetadata` export ([#10753](https://github.com/vercel/vercel/pull/10753))
## 4.0.12 ## 4.0.12
### Patch Changes ### Patch Changes

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vercel/next", "name": "@vercel/next",
"version": "4.0.12", "version": "4.0.15",
"license": "Apache-2.0", "license": "Apache-2.0",
"main": "./dist/index", "main": "./dist/index",
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/next-js", "homepage": "https://vercel.com/docs/runtimes#official-runtimes/next-js",
@@ -40,7 +40,7 @@
"@types/semver": "6.0.0", "@types/semver": "6.0.0",
"@types/text-table": "0.2.1", "@types/text-table": "0.2.1",
"@types/webpack-sources": "3.2.0", "@types/webpack-sources": "3.2.0",
"@vercel/build-utils": "7.2.3", "@vercel/build-utils": "7.3.0",
"@vercel/routing-utils": "3.1.0", "@vercel/routing-utils": "3.1.0",
"async-sema": "3.0.1", "async-sema": "3.0.1",
"buffer-crc32": "0.2.13", "buffer-crc32": "0.2.13",

View File

@@ -1605,6 +1605,7 @@ export const build: BuildV2 = async ({
// internal pages are already referenced in traces for serverless // internal pages are already referenced in traces for serverless
// like builds // like builds
internalPages: [], internalPages: [],
experimentalPPRRoutes: undefined,
}); });
const initialApiLambdaGroups = await getPageLambdaGroups({ const initialApiLambdaGroups = await getPageLambdaGroups({
@@ -1620,6 +1621,7 @@ export const build: BuildV2 = async ({
initialPseudoLayerUncompressed: 0, initialPseudoLayerUncompressed: 0,
lambdaCompressedByteLimit, lambdaCompressedByteLimit,
internalPages: [], internalPages: [],
experimentalPPRRoutes: undefined,
}); });
for (const group of initialApiLambdaGroups) { for (const group of initialApiLambdaGroups) {
@@ -2108,6 +2110,7 @@ export const build: BuildV2 = async ({
static404Page, static404Page,
pageLambdaMap, pageLambdaMap,
lambdas, lambdas,
experimentalStreamingLambdaPaths: undefined,
isServerMode, isServerMode,
prerenders, prerenders,
entryDirectory, entryDirectory,
@@ -2141,20 +2144,41 @@ export const build: BuildV2 = async ({
[ [
...Object.entries(prerenderManifest.fallbackRoutes), ...Object.entries(prerenderManifest.fallbackRoutes),
...Object.entries(prerenderManifest.blockingFallbackRoutes), ...Object.entries(prerenderManifest.blockingFallbackRoutes),
].forEach(([, { dataRouteRegex, dataRoute }]) => { ].forEach(
if (!dataRoute || !dataRouteRegex) return; ([
,
{
dataRouteRegex,
dataRoute,
prefetchDataRouteRegex,
prefetchDataRoute,
},
]) => {
if (!dataRoute || !dataRouteRegex) return;
dataRoutes.push({ dataRoutes.push({
// Next.js provided data route regex // Next.js provided data route regex
src: dataRouteRegex.replace( src: dataRouteRegex.replace(
/^\^/, /^\^/,
`^${appMountPrefixNoTrailingSlash}` `^${appMountPrefixNoTrailingSlash}`
), ),
// Location of lambda in builder output // Location of lambda in builder output
dest: path.posix.join(entryDirectory, dataRoute), dest: path.posix.join(entryDirectory, dataRoute),
check: true, check: true,
}); });
});
if (!prefetchDataRoute || !prefetchDataRouteRegex) return;
dataRoutes.push({
src: prefetchDataRouteRegex.replace(
/^\^/,
`^${appMountPrefixNoTrailingSlash}`
),
dest: path.posix.join(entryDirectory, prefetchDataRoute),
check: true,
});
}
);
} }
} }

View File

@@ -14,6 +14,7 @@ import {
Files, Files,
Flag, Flag,
BuildResultV2Typical as BuildResult, BuildResultV2Typical as BuildResult,
NodejsLambda,
} from '@vercel/build-utils'; } from '@vercel/build-utils';
import { Route, RouteWithHandle } from '@vercel/routing-utils'; import { Route, RouteWithHandle } from '@vercel/routing-utils';
import { MAX_AGE_ONE_YEAR } from '.'; import { MAX_AGE_ONE_YEAR } from '.';
@@ -50,6 +51,7 @@ import {
RSC_CONTENT_TYPE, RSC_CONTENT_TYPE,
RSC_PREFETCH_SUFFIX, RSC_PREFETCH_SUFFIX,
normalizePrefetches, normalizePrefetches,
CreateLambdaFromPseudoLayersOptions,
} from './utils'; } from './utils';
import { import {
nodeFileTrace, nodeFileTrace,
@@ -182,6 +184,10 @@ export async function serverBuild({
} }
} }
const experimental = {
ppr: requiredServerFilesManifest.config.experimental?.ppr === true,
};
let appRscPrefetches: UnwrapPromise<ReturnType<typeof glob>> = {}; let appRscPrefetches: UnwrapPromise<ReturnType<typeof glob>> = {};
let appBuildTraces: UnwrapPromise<ReturnType<typeof glob>> = {}; let appBuildTraces: UnwrapPromise<ReturnType<typeof glob>> = {};
let appDir: string | null = null; let appDir: string | null = null;
@@ -189,7 +195,11 @@ export async function serverBuild({
if (appPathRoutesManifest) { if (appPathRoutesManifest) {
appDir = path.join(pagesDir, '../app'); appDir = path.join(pagesDir, '../app');
appBuildTraces = await glob('**/*.js.nft.json', appDir); appBuildTraces = await glob('**/*.js.nft.json', appDir);
appRscPrefetches = await glob(`**/*${RSC_PREFETCH_SUFFIX}`, appDir);
// TODO: maybe?
appRscPrefetches = experimental.ppr
? {}
: await glob(`**/*${RSC_PREFETCH_SUFFIX}`, appDir);
const rscContentTypeHeader = const rscContentTypeHeader =
routesManifest?.rsc?.contentTypeHeader || RSC_CONTENT_TYPE; routesManifest?.rsc?.contentTypeHeader || RSC_CONTENT_TYPE;
@@ -295,6 +305,18 @@ export async function serverBuild({
internalPages.push('404.js'); internalPages.push('404.js');
} }
const experimentalPPRRoutes = new Set<string>();
for (const [route, { experimentalPPR }] of [
...Object.entries(prerenderManifest.staticRoutes),
...Object.entries(prerenderManifest.blockingFallbackRoutes),
...Object.entries(prerenderManifest.fallbackRoutes),
]) {
if (!experimentalPPR) continue;
experimentalPPRRoutes.add(route);
}
const prerenderRoutes = new Set<string>([ const prerenderRoutes = new Set<string>([
...(canUsePreviewMode ? omittedPrerenderRoutes : []), ...(canUsePreviewMode ? omittedPrerenderRoutes : []),
...Object.keys(prerenderManifest.blockingFallbackRoutes), ...Object.keys(prerenderManifest.blockingFallbackRoutes),
@@ -305,6 +327,8 @@ export async function serverBuild({
}), }),
]); ]);
const experimentalStreamingLambdaPaths = new Map<string, string>();
if (hasLambdas) { if (hasLambdas) {
const initialTracingLabel = 'Traced Next.js server files in'; const initialTracingLabel = 'Traced Next.js server files in';
@@ -619,8 +643,8 @@ export async function serverBuild({
); );
let launcher = launcherData let launcher = launcherData
.replace( .replace(
'conf: __NEXT_CONFIG__', 'const conf = __NEXT_CONFIG__',
`conf: ${JSON.stringify({ `const conf = ${JSON.stringify({
...requiredServerFilesManifest.config, ...requiredServerFilesManifest.config,
distDir: path.relative( distDir: path.relative(
projectDir, projectDir,
@@ -823,6 +847,7 @@ export async function serverBuild({
prerenderRoutes, prerenderRoutes,
pageTraces, pageTraces,
compressedPages, compressedPages,
experimentalPPRRoutes: undefined,
tracedPseudoLayer: tracedPseudoLayer.pseudoLayer, tracedPseudoLayer: tracedPseudoLayer.pseudoLayer,
initialPseudoLayer, initialPseudoLayer,
lambdaCompressedByteLimit, lambdaCompressedByteLimit,
@@ -843,12 +868,14 @@ export async function serverBuild({
prerenderRoutes, prerenderRoutes,
pageTraces, pageTraces,
compressedPages, compressedPages,
experimentalPPRRoutes,
tracedPseudoLayer: tracedPseudoLayer.pseudoLayer, tracedPseudoLayer: tracedPseudoLayer.pseudoLayer,
initialPseudoLayer, initialPseudoLayer,
lambdaCompressedByteLimit, lambdaCompressedByteLimit,
initialPseudoLayerUncompressed: uncompressedInitialSize, initialPseudoLayerUncompressed: uncompressedInitialSize,
internalPages, internalPages,
pageExtensions, pageExtensions,
inversedAppPathManifest,
}); });
const appRouteHandlersLambdaGroups = await getPageLambdaGroups({ const appRouteHandlersLambdaGroups = await getPageLambdaGroups({
@@ -859,16 +886,18 @@ export async function serverBuild({
prerenderRoutes, prerenderRoutes,
pageTraces, pageTraces,
compressedPages, compressedPages,
experimentalPPRRoutes: undefined,
tracedPseudoLayer: tracedPseudoLayer.pseudoLayer, tracedPseudoLayer: tracedPseudoLayer.pseudoLayer,
initialPseudoLayer, initialPseudoLayer,
lambdaCompressedByteLimit, lambdaCompressedByteLimit,
initialPseudoLayerUncompressed: uncompressedInitialSize, initialPseudoLayerUncompressed: uncompressedInitialSize,
internalPages, internalPages,
pageExtensions, pageExtensions,
inversedAppPathManifest,
}); });
for (const group of appRouterLambdaGroups) { for (const group of appRouterLambdaGroups) {
if (!group.isPrerenders) { if (!group.isPrerenders || group.isExperimentalPPR) {
group.isStreaming = true; group.isStreaming = true;
} }
group.isAppRouter = true; group.isAppRouter = true;
@@ -890,6 +919,7 @@ export async function serverBuild({
prerenderRoutes, prerenderRoutes,
pageTraces, pageTraces,
compressedPages, compressedPages,
experimentalPPRRoutes: undefined,
tracedPseudoLayer: tracedPseudoLayer.pseudoLayer, tracedPseudoLayer: tracedPseudoLayer.pseudoLayer,
initialPseudoLayer, initialPseudoLayer,
initialPseudoLayerUncompressed: uncompressedInitialSize, initialPseudoLayerUncompressed: uncompressedInitialSize,
@@ -1025,7 +1055,7 @@ export async function serverBuild({
}; };
const operationType = getOperationType({ group, prerenderManifest }); const operationType = getOperationType({ group, prerenderManifest });
const lambda = await createLambdaFromPseudoLayers({ const options: CreateLambdaFromPseudoLayersOptions = {
files: { files: {
...launcherFiles, ...launcherFiles,
...updatedManifestFiles, ...updatedManifestFiles,
@@ -1041,7 +1071,30 @@ export async function serverBuild({
maxDuration: group.maxDuration, maxDuration: group.maxDuration,
isStreaming: group.isStreaming, isStreaming: group.isStreaming,
nextVersion, nextVersion,
}); };
const lambda = await createLambdaFromPseudoLayers(options);
// This is a PPR lambda if it's an App Page with the PPR experimental flag
// enabled.
const isPPR =
experimental.ppr && group.isAppRouter && !group.isAppRouteHandler;
// If PPR is enabled and this is an App Page, create the non-streaming
// lambda for the page for revalidation.
let revalidate: NodejsLambda | undefined;
if (isPPR) {
if (isPPR && !options.isStreaming) {
throw new Error("Invariant: PPR lambda isn't streaming");
}
// Create the non-streaming version of the same Lambda, this will be
// used for revalidation.
revalidate = await createLambdaFromPseudoLayers({
...options,
isStreaming: false,
});
}
for (const page of group.pages) { for (const page of group.pages) {
const pageNoExt = page.replace(/\.js$/, ''); const pageNoExt = page.replace(/\.js$/, '');
@@ -1057,11 +1110,35 @@ export async function serverBuild({
}); });
} }
const outputName = normalizeIndexOutput( let outputName = normalizeIndexOutput(
path.posix.join(entryDirectory, pageNoExt), path.posix.join(entryDirectory, pageNoExt),
true true
); );
// If this is a PPR page, then we should prefix the output name.
if (isPPR) {
if (!revalidate) {
throw new Error("Invariant: PPR lambda isn't set");
}
// Get the get the base path prefixed route, without the index
// normalization.
outputName = path.posix.join(entryDirectory, pageNoExt);
lambdas[outputName] = revalidate;
const pprOutputName = path.posix.join(
entryDirectory,
'/_next/postponed/resume',
pageNoExt
);
lambdas[pprOutputName] = lambda;
// We want to add the `experimentalStreamingLambdaPath` to this
// output.
experimentalStreamingLambdaPaths.set(outputName, pprOutputName);
continue;
}
// we add locale prefixed outputs for SSR pages, // we add locale prefixed outputs for SSR pages,
// this is handled in onPrerenderRoute for SSG pages // this is handled in onPrerenderRoute for SSG pages
if ( if (
@@ -1096,6 +1173,7 @@ export async function serverBuild({
pagesDir, pagesDir,
pageLambdaMap: {}, pageLambdaMap: {},
lambdas, lambdas,
experimentalStreamingLambdaPaths,
prerenders, prerenders,
entryDirectory, entryDirectory,
routesManifest, routesManifest,
@@ -1111,23 +1189,32 @@ export async function serverBuild({
isEmptyAllowQueryForPrendered, isEmptyAllowQueryForPrendered,
}); });
Object.keys(prerenderManifest.staticRoutes).forEach(route => await Promise.all(
prerenderRoute(route, {}) Object.keys(prerenderManifest.staticRoutes).map(route =>
prerenderRoute(route, {})
)
); );
Object.keys(prerenderManifest.fallbackRoutes).forEach(route => await Promise.all(
prerenderRoute(route, { isFallback: true }) Object.keys(prerenderManifest.fallbackRoutes).map(route =>
prerenderRoute(route, { isFallback: true })
)
); );
Object.keys(prerenderManifest.blockingFallbackRoutes).forEach(route => await Promise.all(
prerenderRoute(route, { isBlocking: true }) Object.keys(prerenderManifest.blockingFallbackRoutes).map(route =>
prerenderRoute(route, { isBlocking: true })
)
); );
if (static404Page && canUsePreviewMode) { if (static404Page && canUsePreviewMode) {
omittedPrerenderRoutes.forEach(route => { await Promise.all(
prerenderRoute(route, { isOmitted: true }); [...omittedPrerenderRoutes].map(route => {
}); return prerenderRoute(route, { isOmitted: true });
})
);
} }
prerenderRoutes.forEach(route => { prerenderRoutes.forEach(route => {
if (experimentalPPRRoutes.has(route)) return;
if (routesManifest?.i18n) { if (routesManifest?.i18n) {
route = normalizeLocalePath(route, routesManifest.i18n.locales).pathname; route = normalizeLocalePath(route, routesManifest.i18n.locales).pathname;
} }
@@ -1164,7 +1251,8 @@ export async function serverBuild({
canUsePreviewMode, canUsePreviewMode,
prerenderManifest.bypassToken || '', prerenderManifest.bypassToken || '',
true, true,
middleware.dynamicRouteMap middleware.dynamicRouteMap,
experimental.ppr
).then(arr => ).then(arr =>
localizeDynamicRoutes( localizeDynamicRoutes(
arr, arr,
@@ -1329,22 +1417,24 @@ export async function serverBuild({
// __rsc__ header is present // __rsc__ header is present
const edgeFunctions = middleware.edgeFunctions; const edgeFunctions = middleware.edgeFunctions;
for (let route of Object.values(appPathRoutesManifest)) { for (const route of Object.values(appPathRoutesManifest)) {
const ogRoute = inversedAppPathManifest[route]; const ogRoute = inversedAppPathManifest[route];
if (ogRoute.endsWith('/route')) { if (ogRoute.endsWith('/route')) {
continue; continue;
} }
route = normalizeIndexOutput(
const pathname = normalizeIndexOutput(
path.posix.join('./', entryDirectory, route === '/' ? '/index' : route), path.posix.join('./', entryDirectory, route === '/' ? '/index' : route),
true true
); );
if (lambdas[route]) { if (lambdas[pathname]) {
lambdas[`${route}.rsc`] = lambdas[route]; lambdas[`${pathname}.rsc`] = lambdas[pathname];
} }
if (edgeFunctions[route]) {
edgeFunctions[`${route}.rsc`] = edgeFunctions[route]; if (edgeFunctions[pathname]) {
edgeFunctions[`${pathname}.rsc`] = edgeFunctions[pathname];
} }
} }
} }
@@ -1364,6 +1454,10 @@ export async function serverBuild({
})) }))
: []; : [];
if (experimental.ppr && !rscPrefetchHeader) {
throw new Error("Invariant: cannot use PPR without 'rsc.prefetchHeader'");
}
return { return {
wildcard: wildcardConfig, wildcard: wildcardConfig,
images: getImagesConfig(imagesManifest), images: getImagesConfig(imagesManifest),
@@ -1718,7 +1812,7 @@ export async function serverBuild({
] ]
: []), : []),
...(rscPrefetchHeader ...(rscPrefetchHeader && !experimental.ppr
? [ ? [
{ {
src: path.posix.join( src: path.posix.join(
@@ -1742,7 +1836,11 @@ export async function serverBuild({
entryDirectory, entryDirectory,
`/(.+?)${RSC_PREFETCH_SUFFIX}(?:/)?$` `/(.+?)${RSC_PREFETCH_SUFFIX}(?:/)?$`
)}`, )}`,
dest: path.posix.join('/', entryDirectory, '/$1.rsc'), dest: path.posix.join(
'/',
entryDirectory,
`/$1${experimental.ppr ? RSC_PREFETCH_SUFFIX : '.rsc'}`
),
has: [ has: [
{ {
type: 'header', type: 'header',
@@ -1955,8 +2053,6 @@ export async function serverBuild({
important: true, important: true,
}, },
// TODO: remove below workaround when `/` is allowed to be output
// different than `/index`
{ {
src: path.posix.join('/', entryDirectory, '/index'), src: path.posix.join('/', entryDirectory, '/index'),
headers: { headers: {

View File

@@ -22,25 +22,44 @@ if (process.env.NODE_ENV !== 'production' && region !== 'dev1') {
// eslint-disable-next-line // eslint-disable-next-line
const NextServer = require('__NEXT_SERVER_PATH__').default; const NextServer = require('__NEXT_SERVER_PATH__').default;
// __NEXT_CONFIG__ value is injected
declare const __NEXT_CONFIG__: any;
const conf = __NEXT_CONFIG__;
const nextServer = new NextServer({ const nextServer = new NextServer({
// @ts-ignore __NEXT_CONFIG__ value is injected conf,
conf: __NEXT_CONFIG__,
dir: '.', dir: '.',
minimalMode: true, minimalMode: true,
customServer: false, customServer: false,
}); });
const requestHandler = nextServer.getRequestHandler(); // Returns a wrapped handler that will crash the lambda if an error isn't
// caught.
const serve =
(handler: any) => async (req: IncomingMessage, res: ServerResponse) => {
try {
// @preserve entryDirectory handler
await handler(req, res);
} catch (err) {
console.error(err);
// crash the lambda immediately to clean up any bad module state,
// this was previously handled in ___vc_bridge on an unhandled rejection
// but we can do this quicker by triggering here
process.exit(1);
}
};
module.exports = async (req: IncomingMessage, res: ServerResponse) => { // The default handler method should be exported as a function on the module.
try { module.exports = serve(nextServer.getRequestHandler());
// @preserve entryDirectory handler
await requestHandler(req, res); // If available, add `getRequestHandlerWithMetadata` to the export if it's
} catch (err) { // required by the configuration.
console.error(err); if (
// crash the lambda immediately to clean up any bad module state, conf.experimental?.ppr &&
// this was previously handled in ___vc_bridge on an unhandled rejection 'getRequestHandlerWithMetadata' in nextServer &&
// but we can do this quicker by triggering here typeof nextServer.getRequestHandlerWithMetadata === 'function'
process.exit(1); ) {
} module.exports.getRequestHandlerWithMetadata = (metadata: any) =>
}; serve(nextServer.getRequestHandlerWithMetadata(metadata));
}

View File

@@ -15,6 +15,7 @@ import {
NodejsLambda, NodejsLambda,
EdgeFunction, EdgeFunction,
Images, Images,
File,
} from '@vercel/build-utils'; } from '@vercel/build-utils';
import { NodeFileTraceReasons } from '@vercel/nft'; import { NodeFileTraceReasons } from '@vercel/nft';
import type { import type {
@@ -244,6 +245,7 @@ type RoutesManifestOld = {
header: string; header: string;
varyHeader: string; varyHeader: string;
prefetchHeader?: string; prefetchHeader?: string;
didPostponeHeader?: string;
contentTypeHeader: string; contentTypeHeader: string;
}; };
skipMiddlewareUrlNormalize?: boolean; skipMiddlewareUrlNormalize?: boolean;
@@ -312,7 +314,8 @@ export async function getDynamicRoutes(
canUsePreviewMode?: boolean, canUsePreviewMode?: boolean,
bypassToken?: string, bypassToken?: string,
isServerMode?: boolean, isServerMode?: boolean,
dynamicMiddlewareRouteMap?: Map<string, RouteWithSrc> dynamicMiddlewareRouteMap?: Map<string, RouteWithSrc>,
experimentalPPR?: boolean
): Promise<RouteWithSrc[]> { ): Promise<RouteWithSrc[]> {
if (routesManifest) { if (routesManifest) {
switch (routesManifest.version) { switch (routesManifest.version) {
@@ -385,6 +388,24 @@ export async function getDynamicRoutes(
}, },
]; ];
} }
if (experimentalPPR) {
let dest = route.dest?.replace(/($|\?)/, '.prefetch.rsc$1');
if (page === '/' || page === '/index') {
dest = dest?.replace(/([^/]+\.prefetch\.rsc(\?.*|$))/, '__$1');
}
routes.push({
...route,
src: route.src.replace(
new RegExp(escapeStringRegexp('(?:/)?$')),
'(?:\\.prefetch\\.rsc)(?:/)?$'
),
dest,
});
}
routes.push({ routes.push({
...route, ...route,
src: route.src.replace( src: route.src.replace(
@@ -395,8 +416,8 @@ export async function getDynamicRoutes(
}); });
routes.push(route); routes.push(route);
continue;
} }
return routes; return routes;
} }
default: { default: {
@@ -778,7 +799,8 @@ export async function createPseudoLayer(files: {
return { pseudoLayer, pseudoLayerBytes }; return { pseudoLayer, pseudoLayerBytes };
} }
interface CreateLambdaFromPseudoLayersOptions extends LambdaOptionsWithFiles { export interface CreateLambdaFromPseudoLayersOptions
extends LambdaOptionsWithFiles {
layers: PseudoLayer[]; layers: PseudoLayer[];
isStreaming?: boolean; isStreaming?: boolean;
nextVersion?: string; nextVersion?: string;
@@ -858,10 +880,12 @@ export type NextPrerenderedRoutes = {
[route: string]: { [route: string]: {
initialRevalidate: number | false; initialRevalidate: number | false;
dataRoute: string | null; dataRoute: string | null;
prefetchDataRoute?: string | null;
srcRoute: string | null; srcRoute: string | null;
initialStatus?: number; initialStatus?: number;
initialHeaders?: Record<string, string>; initialHeaders?: Record<string, string>;
experimentalBypassFor?: HasField; experimentalBypassFor?: HasField;
experimentalPPR?: boolean;
}; };
}; };
@@ -870,7 +894,10 @@ export type NextPrerenderedRoutes = {
routeRegex: string; routeRegex: string;
dataRoute: string | null; dataRoute: string | null;
dataRouteRegex: string | null; dataRouteRegex: string | null;
prefetchDataRoute?: string | null;
prefetchDataRouteRegex?: string | null;
experimentalBypassFor?: HasField; experimentalBypassFor?: HasField;
experimentalPPR?: boolean;
}; };
}; };
@@ -880,7 +907,10 @@ export type NextPrerenderedRoutes = {
routeRegex: string; routeRegex: string;
dataRoute: string | null; dataRoute: string | null;
dataRouteRegex: string | null; dataRouteRegex: string | null;
prefetchDataRoute?: string | null;
prefetchDataRouteRegex?: string | null;
experimentalBypassFor?: HasField; experimentalBypassFor?: HasField;
experimentalPPR?: boolean;
}; };
}; };
@@ -889,7 +919,10 @@ export type NextPrerenderedRoutes = {
routeRegex: string; routeRegex: string;
dataRoute: string | null; dataRoute: string | null;
dataRouteRegex: string | null; dataRouteRegex: string | null;
prefetchDataRoute: string | null | undefined;
prefetchDataRouteRegex: string | null | undefined;
experimentalBypassFor?: HasField; experimentalBypassFor?: HasField;
experimentalPPR?: boolean;
}; };
}; };
@@ -1091,9 +1124,11 @@ export async function getPrerenderManifest(
initialRevalidateSeconds: number | false; initialRevalidateSeconds: number | false;
srcRoute: string | null; srcRoute: string | null;
dataRoute: string | null; dataRoute: string | null;
prefetchDataRoute: string | null | undefined;
initialStatus?: number; initialStatus?: number;
initialHeaders?: Record<string, string>; initialHeaders?: Record<string, string>;
experimentalBypassFor?: HasField; experimentalBypassFor?: HasField;
experimentalPPR?: boolean;
}; };
}; };
dynamicRoutes: { dynamicRoutes: {
@@ -1102,7 +1137,10 @@ export async function getPrerenderManifest(
fallback: string | false; fallback: string | false;
dataRoute: string | null; dataRoute: string | null;
dataRouteRegex: string | null; dataRouteRegex: string | null;
prefetchDataRoute: string | null | undefined;
prefetchDataRouteRegex: string | null | undefined;
experimentalBypassFor?: HasField; experimentalBypassFor?: HasField;
experimentalPPR?: boolean;
}; };
}; };
preview: { preview: {
@@ -1189,11 +1227,15 @@ export async function getPrerenderManifest(
let initialStatus: undefined | number; let initialStatus: undefined | number;
let initialHeaders: undefined | Record<string, string>; let initialHeaders: undefined | Record<string, string>;
let experimentalBypassFor: undefined | HasField; let experimentalBypassFor: undefined | HasField;
let experimentalPPR: undefined | boolean;
let prefetchDataRoute: undefined | string | null;
if (manifest.version === 4) { if (manifest.version === 4) {
initialStatus = manifest.routes[route].initialStatus; initialStatus = manifest.routes[route].initialStatus;
initialHeaders = manifest.routes[route].initialHeaders; initialHeaders = manifest.routes[route].initialHeaders;
experimentalBypassFor = manifest.routes[route].experimentalBypassFor; experimentalBypassFor = manifest.routes[route].experimentalBypassFor;
experimentalPPR = manifest.routes[route].experimentalPPR;
prefetchDataRoute = manifest.routes[route].prefetchDataRoute;
} }
ret.staticRoutes[route] = { ret.staticRoutes[route] = {
@@ -1202,10 +1244,12 @@ export async function getPrerenderManifest(
? false ? false
: Math.max(1, initialRevalidateSeconds), : Math.max(1, initialRevalidateSeconds),
dataRoute, dataRoute,
prefetchDataRoute,
srcRoute, srcRoute,
initialStatus, initialStatus,
initialHeaders, initialHeaders,
experimentalBypassFor, experimentalBypassFor,
experimentalPPR,
}; };
}); });
@@ -1213,35 +1257,52 @@ export async function getPrerenderManifest(
const { routeRegex, fallback, dataRoute, dataRouteRegex } = const { routeRegex, fallback, dataRoute, dataRouteRegex } =
manifest.dynamicRoutes[lazyRoute]; manifest.dynamicRoutes[lazyRoute];
let experimentalBypassFor: undefined | HasField; let experimentalBypassFor: undefined | HasField;
let experimentalPPR: undefined | boolean;
let prefetchDataRoute: undefined | string | null;
let prefetchDataRouteRegex: undefined | string | null;
if (manifest.version === 4) { if (manifest.version === 4) {
experimentalBypassFor = experimentalBypassFor =
manifest.dynamicRoutes[lazyRoute].experimentalBypassFor; manifest.dynamicRoutes[lazyRoute].experimentalBypassFor;
experimentalPPR = manifest.dynamicRoutes[lazyRoute].experimentalPPR;
prefetchDataRoute =
manifest.dynamicRoutes[lazyRoute].prefetchDataRoute;
prefetchDataRouteRegex =
manifest.dynamicRoutes[lazyRoute].prefetchDataRouteRegex;
} }
if (typeof fallback === 'string') { if (typeof fallback === 'string') {
ret.fallbackRoutes[lazyRoute] = { ret.fallbackRoutes[lazyRoute] = {
experimentalBypassFor, experimentalBypassFor,
experimentalPPR,
routeRegex, routeRegex,
fallback, fallback,
dataRoute, dataRoute,
dataRouteRegex, dataRouteRegex,
prefetchDataRoute,
prefetchDataRouteRegex,
}; };
} else if (fallback === null) { } else if (fallback === null) {
ret.blockingFallbackRoutes[lazyRoute] = { ret.blockingFallbackRoutes[lazyRoute] = {
experimentalBypassFor, experimentalBypassFor,
experimentalPPR,
routeRegex, routeRegex,
dataRoute, dataRoute,
dataRouteRegex, dataRouteRegex,
prefetchDataRoute,
prefetchDataRouteRegex,
}; };
} else { } else {
// Fallback behavior is disabled, all routes would've been provided // Fallback behavior is disabled, all routes would've been provided
// in the top-level `routes` key (`staticRoutes`). // in the top-level `routes` key (`staticRoutes`).
ret.omittedRoutes[lazyRoute] = { ret.omittedRoutes[lazyRoute] = {
experimentalBypassFor, experimentalBypassFor,
experimentalPPR,
routeRegex, routeRegex,
dataRoute, dataRoute,
dataRouteRegex, dataRouteRegex,
prefetchDataRoute,
prefetchDataRouteRegex,
}; };
} }
}); });
@@ -1417,6 +1478,7 @@ export type LambdaGroup = {
isAppRouteHandler?: boolean; isAppRouteHandler?: boolean;
isStreaming?: boolean; isStreaming?: boolean;
isPrerenders?: boolean; isPrerenders?: boolean;
isExperimentalPPR?: boolean;
isPages?: boolean; isPages?: boolean;
isApiLambda: boolean; isApiLambda: boolean;
pseudoLayer: PseudoLayer; pseudoLayer: PseudoLayer;
@@ -1430,6 +1492,7 @@ export async function getPageLambdaGroups({
functionsConfigManifest, functionsConfigManifest,
pages, pages,
prerenderRoutes, prerenderRoutes,
experimentalPPRRoutes,
pageTraces, pageTraces,
compressedPages, compressedPages,
tracedPseudoLayer, tracedPseudoLayer,
@@ -1438,12 +1501,14 @@ export async function getPageLambdaGroups({
lambdaCompressedByteLimit, lambdaCompressedByteLimit,
internalPages, internalPages,
pageExtensions, pageExtensions,
inversedAppPathManifest,
}: { }: {
entryPath: string; entryPath: string;
config: Config; config: Config;
functionsConfigManifest?: FunctionsConfigManifestV1; functionsConfigManifest?: FunctionsConfigManifestV1;
pages: string[]; pages: string[];
prerenderRoutes: Set<string>; prerenderRoutes: Set<string>;
experimentalPPRRoutes: Set<string> | undefined;
pageTraces: { pageTraces: {
[page: string]: { [page: string]: {
[key: string]: FileFsRef; [key: string]: FileFsRef;
@@ -1458,6 +1523,7 @@ export async function getPageLambdaGroups({
lambdaCompressedByteLimit: number; lambdaCompressedByteLimit: number;
internalPages: string[]; internalPages: string[];
pageExtensions?: string[]; pageExtensions?: string[];
inversedAppPathManifest?: Record<string, string>;
}) { }) {
const groups: Array<LambdaGroup> = []; const groups: Array<LambdaGroup> = [];
@@ -1465,6 +1531,7 @@ export async function getPageLambdaGroups({
const newPages = [...internalPages, page]; const newPages = [...internalPages, page];
const routeName = normalizePage(page.replace(/\.js$/, '')); const routeName = normalizePage(page.replace(/\.js$/, ''));
const isPrerenderRoute = prerenderRoutes.has(routeName); const isPrerenderRoute = prerenderRoutes.has(routeName);
const isExperimentalPPR = experimentalPPRRoutes?.has(routeName) ?? false;
let opts: { memory?: number; maxDuration?: number } = {}; let opts: { memory?: number; maxDuration?: number } = {};
@@ -1476,9 +1543,15 @@ export async function getPageLambdaGroups({
} }
if (config && config.functions) { if (config && config.functions) {
// `pages` are normalized without route groups (e.g., /app/(group)/page.js).
// we keep track of that mapping in `inversedAppPathManifest`
// `getSourceFilePathFromPage` needs to use the path from source to properly match the config
const pageFromManifest = inversedAppPathManifest?.[routeName];
const sourceFile = await getSourceFilePathFromPage({ const sourceFile = await getSourceFilePathFromPage({
workPath: entryPath, workPath: entryPath,
page, // since this function is used by both `pages` and `app`, the manifest might not be provided
// so fallback to normal behavior of just checking the `page`.
page: pageFromManifest ?? page,
pageExtensions, pageExtensions,
}); });
@@ -1494,7 +1567,8 @@ export async function getPageLambdaGroups({
const matches = const matches =
group.maxDuration === opts.maxDuration && group.maxDuration === opts.maxDuration &&
group.memory === opts.memory && group.memory === opts.memory &&
group.isPrerenders === isPrerenderRoute; group.isPrerenders === isPrerenderRoute &&
group.isExperimentalPPR === isExperimentalPPR;
if (matches) { if (matches) {
let newTracedFilesSize = group.pseudoLayerBytes; let newTracedFilesSize = group.pseudoLayerBytes;
@@ -1533,6 +1607,7 @@ export async function getPageLambdaGroups({
pages: [page], pages: [page],
...opts, ...opts,
isPrerenders: isPrerenderRoute, isPrerenders: isPrerenderRoute,
isExperimentalPPR,
isApiLambda: !!isApiPage(page), isApiLambda: !!isApiPage(page),
pseudoLayerBytes: initialPseudoLayer.pseudoLayerBytes, pseudoLayerBytes: initialPseudoLayer.pseudoLayerBytes,
pseudoLayerUncompressedBytes: initialPseudoLayerUncompressed, pseudoLayerUncompressedBytes: initialPseudoLayerUncompressed,
@@ -1831,7 +1906,8 @@ type OnPrerenderRouteArgs = {
isServerMode: boolean; isServerMode: boolean;
canUsePreviewMode: boolean; canUsePreviewMode: boolean;
lambdas: { [key: string]: Lambda }; lambdas: { [key: string]: Lambda };
prerenders: { [key: string]: Prerender | FileFsRef }; experimentalStreamingLambdaPaths: Map<string, string> | undefined;
prerenders: { [key: string]: Prerender | File };
pageLambdaMap: { [key: string]: string }; pageLambdaMap: { [key: string]: string };
routesManifest?: RoutesManifest; routesManifest?: RoutesManifest;
isCorrectNotFoundRoutes?: boolean; isCorrectNotFoundRoutes?: boolean;
@@ -1841,7 +1917,7 @@ let prerenderGroup = 1;
export const onPrerenderRoute = export const onPrerenderRoute =
(prerenderRouteArgs: OnPrerenderRouteArgs) => (prerenderRouteArgs: OnPrerenderRouteArgs) =>
( async (
routeKey: string, routeKey: string,
{ {
isBlocking, isBlocking,
@@ -1866,6 +1942,7 @@ export const onPrerenderRoute =
isServerMode, isServerMode,
canUsePreviewMode, canUsePreviewMode,
lambdas, lambdas,
experimentalStreamingLambdaPaths,
prerenders, prerenders,
pageLambdaMap, pageLambdaMap,
routesManifest, routesManifest,
@@ -1926,9 +2003,11 @@ export const onPrerenderRoute =
let initialRevalidate: false | number; let initialRevalidate: false | number;
let srcRoute: string | null; let srcRoute: string | null;
let dataRoute: string | null; let dataRoute: string | null;
let prefetchDataRoute: string | null | undefined;
let initialStatus: number | undefined; let initialStatus: number | undefined;
let initialHeaders: Record<string, string> | undefined; let initialHeaders: Record<string, string> | undefined;
let experimentalBypassFor: HasField | undefined; let experimentalBypassFor: HasField | undefined;
let experimentalPPR: boolean | undefined;
if (isFallback || isBlocking) { if (isFallback || isBlocking) {
const pr = isFallback const pr = isFallback
@@ -1946,12 +2025,18 @@ export const onPrerenderRoute =
srcRoute = null; srcRoute = null;
dataRoute = pr.dataRoute; dataRoute = pr.dataRoute;
experimentalBypassFor = pr.experimentalBypassFor; experimentalBypassFor = pr.experimentalBypassFor;
experimentalPPR = pr.experimentalPPR;
prefetchDataRoute = pr.prefetchDataRoute;
} else if (isOmitted) { } else if (isOmitted) {
initialRevalidate = false; initialRevalidate = false;
srcRoute = routeKey; srcRoute = routeKey;
dataRoute = prerenderManifest.omittedRoutes[routeKey].dataRoute; dataRoute = prerenderManifest.omittedRoutes[routeKey].dataRoute;
experimentalBypassFor = experimentalBypassFor =
prerenderManifest.omittedRoutes[routeKey].experimentalBypassFor; prerenderManifest.omittedRoutes[routeKey].experimentalBypassFor;
experimentalPPR =
prerenderManifest.omittedRoutes[routeKey].experimentalPPR;
prefetchDataRoute =
prerenderManifest.omittedRoutes[routeKey].prefetchDataRoute;
} else { } else {
const pr = prerenderManifest.staticRoutes[routeKey]; const pr = prerenderManifest.staticRoutes[routeKey];
({ ({
@@ -1961,19 +2046,71 @@ export const onPrerenderRoute =
initialHeaders, initialHeaders,
initialStatus, initialStatus,
experimentalBypassFor, experimentalBypassFor,
experimentalPPR,
prefetchDataRoute,
} = pr); } = pr);
} }
let isAppPathRoute = false; let isAppPathRoute = false;
// TODO: leverage manifest to determine app paths more accurately // TODO: leverage manifest to determine app paths more accurately
if (appDir && srcRoute && (!dataRoute || dataRoute?.endsWith('.rsc'))) { if (appDir && srcRoute && (!dataRoute || dataRoute?.endsWith('.rsc'))) {
isAppPathRoute = true; isAppPathRoute = true;
} }
const isOmittedOrNotFound = isOmitted || isNotFound; const isOmittedOrNotFound = isOmitted || isNotFound;
let htmlFsRef: FileFsRef | null; let htmlFsRef: File | null;
if (appDir && !dataRoute && isAppPathRoute && !(isBlocking || isFallback)) { // If enabled, try to get the postponed route information from the file
// system and use it to assemble the prerender.
let prerender: string | undefined;
if (experimentalPPR && appDir) {
const htmlPath = path.join(appDir, `${routeFileNoExt}.html`);
const metaPath = path.join(appDir, `${routeFileNoExt}.meta`);
if (fs.existsSync(htmlPath) && fs.existsSync(metaPath)) {
const meta = JSON.parse(await fs.readFile(metaPath, 'utf8'));
if ('postponed' in meta && typeof meta.postponed === 'string') {
prerender = meta.postponed;
// Assign the headers Content-Type header to the prerendered type.
initialHeaders ??= {};
initialHeaders[
'content-type'
] = `application/x-nextjs-pre-render; state-length=${meta.postponed.length}`;
// Read the HTML file and append it to the prerendered content.
const html = await fs.readFileSync(htmlPath, 'utf8');
prerender += html;
}
}
if (!dataRoute?.endsWith('.rsc')) {
throw new Error(
`Invariant: unexpected output path for ${dataRoute} and PPR`
);
}
if (!prefetchDataRoute?.endsWith('.prefetch.rsc')) {
throw new Error(
`Invariant: unexpected output path for ${prefetchDataRoute} and PPR`
);
}
}
if (prerender) {
const contentType = initialHeaders?.['content-type'];
if (!contentType) {
throw new Error("Invariant: contentType can't be undefined");
}
// Assemble the prerendered file.
htmlFsRef = new FileBlob({ contentType, data: prerender });
} else if (
appDir &&
!dataRoute &&
isAppPathRoute &&
!(isBlocking || isFallback)
) {
const contentType = initialHeaders?.['content-type']; const contentType = initialHeaders?.['content-type'];
htmlFsRef = new FileFsRef({ htmlFsRef = new FileFsRef({
fsPath: path.join(appDir, `${routeFileNoExt}.body`), fsPath: path.join(appDir, `${routeFileNoExt}.body`),
@@ -2023,7 +2160,7 @@ export const onPrerenderRoute =
? addLocaleOrDefault('/404.html', routesManifest, locale) ? addLocaleOrDefault('/404.html', routesManifest, locale)
: '/404.html' : '/404.html'
: isAppPathRoute : isAppPathRoute
? dataRoute ? prefetchDataRoute || dataRoute
: routeFileNoExt + '.json' : routeFileNoExt + '.json'
}` }`
), ),
@@ -2054,13 +2191,12 @@ export const onPrerenderRoute =
); );
let lambda: undefined | Lambda; let lambda: undefined | Lambda;
let outputPathData: null | string = null;
if (dataRoute) { function normalizeDataRoute(route: string) {
outputPathData = path.posix.join(entryDirectory, dataRoute); let normalized = path.posix.join(entryDirectory, route);
if (nonDynamicSsg || isFallback || isOmitted) { if (nonDynamicSsg || isFallback || isOmitted) {
outputPathData = outputPathData.replace( normalized = normalized.replace(
new RegExp(`${escapeStringRegexp(origRouteFileNoExt)}.json$`), new RegExp(`${escapeStringRegexp(origRouteFileNoExt)}.json$`),
// ensure we escape "$" correctly while replacing as "$" is a special // ensure we escape "$" correctly while replacing as "$" is a special
// character, we need to do double escaping as first is for the initial // character, we need to do double escaping as first is for the initial
@@ -2068,8 +2204,32 @@ export const onPrerenderRoute =
`${routeFileNoExt.replace(/\$/g, '$$$$')}.json` `${routeFileNoExt.replace(/\$/g, '$$$$')}.json`
); );
} }
return normalized;
} }
let outputPathData: null | string = null;
if (dataRoute) {
outputPathData = normalizeDataRoute(dataRoute);
}
let outputPathPrefetchData: null | string = null;
if (prefetchDataRoute) {
if (!experimentalPPR) {
throw new Error(
"Invariant: prefetchDataRoute can't be set without PPR"
);
}
outputPathPrefetchData = normalizeDataRoute(prefetchDataRoute);
} else if (experimentalPPR) {
throw new Error('Invariant: expected to find prefetch data route PPR');
}
// When the prefetch data path is available, use it for the prerender,
// otherwise use the data path.
const outputPrerenderPathData = outputPathPrefetchData || outputPathData;
if (isSharedLambdas) { if (isSharedLambdas) {
const outputSrcPathPage = normalizeIndexOutput( const outputSrcPathPage = normalizeIndexOutput(
path.join( path.join(
@@ -2117,8 +2277,8 @@ export const onPrerenderRoute =
htmlFsRef.contentType = htmlContentType; htmlFsRef.contentType = htmlContentType;
prerenders[outputPathPage] = htmlFsRef; prerenders[outputPathPage] = htmlFsRef;
if (outputPathData) { if (outputPrerenderPathData) {
prerenders[outputPathData] = jsonFsRef; prerenders[outputPrerenderPathData] = jsonFsRef;
} }
} }
} }
@@ -2188,12 +2348,32 @@ export const onPrerenderRoute =
'RSC, Next-Router-State-Tree, Next-Router-Prefetch'; 'RSC, Next-Router-State-Tree, Next-Router-Prefetch';
const rscContentTypeHeader = const rscContentTypeHeader =
routesManifest?.rsc?.contentTypeHeader || RSC_CONTENT_TYPE; routesManifest?.rsc?.contentTypeHeader || RSC_CONTENT_TYPE;
const rscDidPostponeHeader = routesManifest?.rsc?.didPostponeHeader;
let sourcePath: string | undefined; let sourcePath: string | undefined;
if (`/${outputPathPage}` !== srcRoute && srcRoute) { if (`/${outputPathPage}` !== srcRoute && srcRoute) {
sourcePath = srcRoute; sourcePath = srcRoute;
} }
// The `experimentalStreamingLambdaPaths` stores the page without the
// leading `/` and with the `/` rewritten to be `index`. We should
// normalize the key so that it matches that key in the map.
let key = srcRoute || routeKey;
if (key === '/') {
key = 'index';
} else {
if (!key.startsWith('/')) {
throw new Error("Invariant: key doesn't start with /");
}
key = key.substring(1);
}
key = path.posix.join(entryDirectory, key);
const experimentalStreamingLambdaPath =
experimentalStreamingLambdaPaths?.get(key);
prerenders[outputPathPage] = new Prerender({ prerenders[outputPathPage] = new Prerender({
expiration: initialRevalidate, expiration: initialRevalidate,
lambda, lambda,
@@ -2205,6 +2385,7 @@ export const onPrerenderRoute =
initialStatus, initialStatus,
initialHeaders, initialHeaders,
sourcePath, sourcePath,
experimentalStreamingLambdaPath,
...(isNotFound ...(isNotFound
? { ? {
@@ -2222,8 +2403,21 @@ export const onPrerenderRoute =
: {}), : {}),
}); });
if (outputPathData) { if (outputPrerenderPathData) {
prerenders[outputPathData] = new Prerender({ let normalizedPathData = outputPrerenderPathData;
if (
(srcRoute === '/' || srcRoute == '/index') &&
outputPrerenderPathData.endsWith(RSC_PREFETCH_SUFFIX)
) {
delete lambdas[normalizedPathData];
normalizedPathData = normalizedPathData.replace(
/([^/]+\.prefetch\.rsc)$/,
'__$1'
);
}
prerenders[normalizedPathData] = new Prerender({
expiration: initialRevalidate, expiration: initialRevalidate,
lambda, lambda,
allowQuery, allowQuery,
@@ -2243,6 +2437,10 @@ export const onPrerenderRoute =
initialHeaders: { initialHeaders: {
'content-type': rscContentTypeHeader, 'content-type': rscContentTypeHeader,
vary: rscVaryHeader, vary: rscVaryHeader,
// If it contains a pre-render, then it was postponed.
...(prerender && rscDidPostponeHeader
? { [rscDidPostponeHeader]: '1' }
: {}),
}, },
} }
: {}), : {}),

View File

@@ -11,7 +11,7 @@ describe(`${__dirname.split(path.sep).pop()}`, () => {
afterAll(() => fs.remove(fixtureDir)); afterAll(() => fs.remove(fixtureDir));
it('should deploy and pass probe checks', async () => { it('should deploy and pass probe checks', async () => {
await fs.copy(path.join(__dirname, '../00-app-dir'), fixtureDir); await fs.copy(path.join(__dirname, '../00-app-dir-no-ppr'), fixtureDir);
const nextConfigPath = path.join(fixtureDir, 'next.config.js'); const nextConfigPath = path.join(fixtureDir, 'next.config.js');
await fs.writeFile( await fs.writeFile(

View File

@@ -0,0 +1,4 @@
export const GET = req => {
console.log(req.url);
return new Response('hello world');
};

View File

@@ -0,0 +1,11 @@
export default function Page({params}) {
return (
<>
<p>
Catch All Page. Params:{' '}
<span id="catch-all-page-params">{JSON.stringify(params)}</span>
</p>
{children}
</>
);
}

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