Compare commits

...

34 Commits

Author SHA1 Message Date
Andy Bitz
a585969dd3 Publish Stable
- @vercel/build-utils@6.2.0
 - vercel@28.15.1
 - @vercel/client@12.3.6
 - @vercel/fs-detectors@3.7.9
 - @vercel/gatsby-plugin-vercel-builder@1.1.1
 - @vercel/go@2.3.2
 - @vercel/hydrogen@0.0.48
 - @vercel/next@3.4.0
 - @vercel/node@2.9.1
 - @vercel/python@3.1.44
 - @vercel/redwood@1.1.0
 - @vercel/remix@1.2.11
 - @vercel/ruby@1.3.60
 - @vercel/static-build@1.3.3
2023-02-06 17:24:54 +01:00
Andy
35eca33b44 [redwood] Consider all Lambda options (#9386) 2023-02-06 15:46:18 +01:00
Andy
d608153961 [next][build-utils] Add support for cron to vercel.json (#9374) 2023-02-06 12:28:41 +01:00
Bishal Shrestha
a4cfc5f943 [docs] Add troubleshooting step for no serverless pages error (#9333) 2023-02-03 15:23:20 -08:00
chloetedder
2eef3e3ddb [fs-detectors] Add fix for if monorepo and proj at root (#9353)
If there is a monorepo that has one project at the root level we want to
return commands without the relative to root prefixes

---------

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

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

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

To reproduce:

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

Will fail.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Results:

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

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -4,14 +4,17 @@ import fs from 'fs-extra';
import { strict as assert } from 'assert';
import { getSupportedNodeVersion } from '../src/fs/node-version';
import {
FileBlob,
getNodeVersion,
getLatestNodeVersion,
getDiscontinuedNodeVersions,
rename,
runNpmInstall,
runPackageJsonScript,
scanParentDirs,
Prerender,
} from '../src';
import type { Files } from '../src';
jest.setTimeout(10 * 1000);
@@ -135,13 +138,25 @@ it('should ignore node version in vercel dev getNodeVersion()', async () => {
).toHaveProperty('runtime', 'nodejs');
});
it('should select project setting from config when no package.json is found', async () => {
it('should select project setting from config when no package.json is found and fallback undefined', async () => {
expect(
await getNodeVersion('/tmp', undefined, { nodeVersion: '16.x' }, {})
).toHaveProperty('range', '16.x');
expect(warningMessages).toStrictEqual([]);
});
it('should select project setting from config when no package.json is found and fallback is null', async () => {
expect(
await getNodeVersion('/tmp', null as any, { nodeVersion: '16.x' }, {})
).toHaveProperty('range', '16.x');
expect(warningMessages).toStrictEqual([]);
});
it('should select project setting from fallback when no package.json is found', async () => {
expect(await getNodeVersion('/tmp', '16.x')).toHaveProperty('range', '16.x');
expect(warningMessages).toStrictEqual([]);
});
it('should prefer package.json engines over project setting from config and warn', async () => {
expect(
await getNodeVersion(
@@ -451,3 +466,18 @@ it('should retry npm install when peer deps invalid and npm@8 on node@16', async
'Warning: Retrying "Install Command" with `--legacy-peer-deps` which may accept a potentially broken dependency and slow install time.',
]);
});
describe('rename', () => {
it('should rename keys of files map', () => {
const before: Files = {};
const toUpper = (s: string) => s.toUpperCase();
for (let i = 97; i <= 122; i++) {
const key = String.fromCharCode(i);
before[key] = new FileBlob({ contentType: 'text/plain', data: key });
}
const after = rename(before, toUpper);
expect(Object.keys(after)).toEqual('ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split(''));
});
});

View File

@@ -1,6 +1,6 @@
{
"name": "vercel",
"version": "28.13.2",
"version": "28.15.1",
"preferGlobal": true,
"license": "Apache-2.0",
"description": "The command-line interface for Vercel",
@@ -41,16 +41,16 @@
"node": ">= 14"
},
"dependencies": {
"@vercel/build-utils": "6.0.0",
"@vercel/go": "2.2.31",
"@vercel/hydrogen": "0.0.45",
"@vercel/next": "3.3.19",
"@vercel/node": "2.8.16",
"@vercel/python": "3.1.41",
"@vercel/redwood": "1.0.52",
"@vercel/remix": "1.2.8",
"@vercel/ruby": "1.3.57",
"@vercel/static-build": "1.2.1"
"@vercel/build-utils": "6.2.0",
"@vercel/go": "2.3.2",
"@vercel/hydrogen": "0.0.48",
"@vercel/next": "3.4.0",
"@vercel/node": "2.9.1",
"@vercel/python": "3.1.44",
"@vercel/redwood": "1.1.0",
"@vercel/remix": "1.2.11",
"@vercel/ruby": "1.3.60",
"@vercel/static-build": "1.3.3"
},
"devDependencies": {
"@alex_neo/jest-expect-message": "1.0.5",
@@ -93,10 +93,10 @@
"@types/which": "1.3.2",
"@types/write-json-file": "2.2.1",
"@types/yauzl-promise": "2.1.0",
"@vercel/client": "12.3.3",
"@vercel/client": "12.3.6",
"@vercel/error-utils": "1.0.8",
"@vercel/frameworks": "1.3.0",
"@vercel/fs-detectors": "3.7.6",
"@vercel/fs-detectors": "3.7.9",
"@vercel/fun": "1.0.4",
"@vercel/ncc": "0.24.0",
"@vercel/routing-utils": "2.1.8",

View File

@@ -212,10 +212,15 @@ export default async function main(client: Client): Promise<number> {
}
// Delete output directory from potential previous build
const defaultOutputDir = join(cwd, OUTPUT_DIR);
const outputDir = argv['--output']
? resolve(argv['--output'])
: join(cwd, OUTPUT_DIR);
await fs.remove(outputDir);
: defaultOutputDir;
await Promise.all([
fs.remove(outputDir),
// Also delete `.vercel/output`, in case the script is targeting Build Output API directly
outputDir !== defaultOutputDir ? fs.remove(defaultOutputDir) : undefined,
]);
const buildsJson: BuildsManifest = {
'//': 'This file was generated by the `vercel build` command. It is not part of the Build Output API.',
@@ -471,6 +476,22 @@ async function doBuild(
try {
const { builder, pkg: builderPkg } = builderWithPkg;
for (const key of [
'buildCommand',
'installCommand',
'outputDirectory',
'nodeVersion',
] as const) {
const value = projectSettings[key];
if (typeof value === 'string') {
const envKey =
`VERCEL_PROJECT_SETTINGS_` +
key.replace(/[A-Z]/g, letter => `_${letter}`).toUpperCase();
process.env[envKey] = value;
output.debug(`Setting env ${envKey} to "${value}"`);
}
}
const buildConfig: Config = isZeroConfig
? {
outputDirectory: projectSettings.outputDirectory ?? undefined,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,7 @@
export const config = {
runtime: 'edge',
};
export default async function Edge(req, res) {
res.json({ edge: 1 });
}

View File

@@ -0,0 +1,3 @@
export default async function Edge(req, res) {
res.json({ serverless: 1 });
}

View File

@@ -0,0 +1,185 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
"@next/env@13.1.6":
version "13.1.6"
resolved "https://registry.yarnpkg.com/@next/env/-/env-13.1.6.tgz#c4925609f16142ded1a5cb833359ab17359b7a93"
integrity sha512-s+W9Fdqh5MFk6ECrbnVmmAOwxKQuhGMT7xXHrkYIBMBcTiOqNWhv5KbJIboKR5STXxNXl32hllnvKaffzFaWQg==
"@next/swc-android-arm-eabi@13.1.6":
version "13.1.6"
resolved "https://registry.yarnpkg.com/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-13.1.6.tgz#d766dfc10e27814d947b20f052067c239913dbcc"
integrity sha512-F3/6Z8LH/pGlPzR1AcjPFxx35mPqjE5xZcf+IL+KgbW9tMkp7CYi1y7qKrEWU7W4AumxX/8OINnDQWLiwLasLQ==
"@next/swc-android-arm64@13.1.6":
version "13.1.6"
resolved "https://registry.yarnpkg.com/@next/swc-android-arm64/-/swc-android-arm64-13.1.6.tgz#f37a98d5f18927d8c9970d750d516ac779465176"
integrity sha512-cMwQjnB8vrYkWyK/H0Rf2c2pKIH4RGjpKUDvbjVAit6SbwPDpmaijLio0LWFV3/tOnY6kvzbL62lndVA0mkYpw==
"@next/swc-darwin-arm64@13.1.6":
version "13.1.6"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.1.6.tgz#ec1b90fd9bf809d8b81004c5182e254dced4ad96"
integrity sha512-KKRQH4DDE4kONXCvFMNBZGDb499Hs+xcFAwvj+rfSUssIDrZOlyfJNy55rH5t2Qxed1e4K80KEJgsxKQN1/fyw==
"@next/swc-darwin-x64@13.1.6":
version "13.1.6"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-13.1.6.tgz#e869ac75d16995eee733a7d1550322d9051c1eb4"
integrity sha512-/uOky5PaZDoaU99ohjtNcDTJ6ks/gZ5ykTQDvNZDjIoCxFe3+t06bxsTPY6tAO6uEAw5f6vVFX5H5KLwhrkZCA==
"@next/swc-freebsd-x64@13.1.6":
version "13.1.6"
resolved "https://registry.yarnpkg.com/@next/swc-freebsd-x64/-/swc-freebsd-x64-13.1.6.tgz#84a7b2e423a2904afc2edca21c2f1ba6b53fa4c1"
integrity sha512-qaEALZeV7to6weSXk3Br80wtFQ7cFTpos/q+m9XVRFggu+8Ib895XhMWdJBzew6aaOcMvYR6KQ6JmHA2/eMzWw==
"@next/swc-linux-arm-gnueabihf@13.1.6":
version "13.1.6"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-13.1.6.tgz#980eed1f655ff8a72187d8a6ef9e73ac39d20d23"
integrity sha512-OybkbC58A1wJ+JrJSOjGDvZzrVEQA4sprJejGqMwiZyLqhr9Eo8FXF0y6HL+m1CPCpPhXEHz/2xKoYsl16kNqw==
"@next/swc-linux-arm64-gnu@13.1.6":
version "13.1.6"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.1.6.tgz#87a71db21cded3f7c63d1d19079845c59813c53d"
integrity sha512-yCH+yDr7/4FDuWv6+GiYrPI9kcTAO3y48UmaIbrKy8ZJpi7RehJe3vIBRUmLrLaNDH3rY1rwoHi471NvR5J5NQ==
"@next/swc-linux-arm64-musl@13.1.6":
version "13.1.6"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.1.6.tgz#c5aac8619331b9fd030603bbe2b36052011e11de"
integrity sha512-ECagB8LGX25P9Mrmlc7Q/TQBb9rGScxHbv/kLqqIWs2fIXy6Y/EiBBiM72NTwuXUFCNrWR4sjUPSooVBJJ3ESQ==
"@next/swc-linux-x64-gnu@13.1.6":
version "13.1.6"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.1.6.tgz#9513d36d540bbfea575576746736054c31aacdea"
integrity sha512-GT5w2mruk90V/I5g6ScuueE7fqj/d8Bui2qxdw6lFxmuTgMeol5rnzAv4uAoVQgClOUO/MULilzlODg9Ib3Y4Q==
"@next/swc-linux-x64-musl@13.1.6":
version "13.1.6"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.1.6.tgz#d61fc6884899f5957251f4ce3f522e34a2c479b7"
integrity sha512-keFD6KvwOPzmat4TCnlnuxJCQepPN+8j3Nw876FtULxo8005Y9Ghcl7ACcR8GoiKoddAq8gxNBrpjoxjQRHeAQ==
"@next/swc-win32-arm64-msvc@13.1.6":
version "13.1.6"
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.1.6.tgz#fac2077a8ae9768e31444c9ae90807e64117cda7"
integrity sha512-OwertslIiGQluFvHyRDzBCIB07qJjqabAmINlXUYt7/sY7Q7QPE8xVi5beBxX/rxTGPIbtyIe3faBE6Z2KywhQ==
"@next/swc-win32-ia32-msvc@13.1.6":
version "13.1.6"
resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.1.6.tgz#498bc11c91b4c482a625bf4b978f98ae91111e46"
integrity sha512-g8zowiuP8FxUR9zslPmlju7qYbs2XBtTLVSxVikPtUDQedhcls39uKYLvOOd1JZg0ehyhopobRoH1q+MHlIN/w==
"@next/swc-win32-x64-msvc@13.1.6":
version "13.1.6"
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.1.6.tgz#17ed919c723426b7d0ce1cd73d40ce3dcd342089"
integrity sha512-Ls2OL9hi3YlJKGNdKv8k3X/lLgc3VmLG3a/DeTkAd+lAituJp8ZHmRmm9f9SL84fT3CotlzcgbdaCDfFwFA6bA==
"@swc/helpers@0.4.14":
version "0.4.14"
resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.4.14.tgz#1352ac6d95e3617ccb7c1498ff019654f1e12a74"
integrity sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw==
dependencies:
tslib "^2.4.0"
caniuse-lite@^1.0.30001406:
version "1.0.30001450"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001450.tgz#022225b91200589196b814b51b1bbe45144cf74f"
integrity sha512-qMBmvmQmFXaSxexkjjfMvD5rnDL0+m+dUMZKoDYsGG8iZN29RuYh9eRoMvKsT6uMAWlyUUGDEQGJJYjzCIO9ew==
client-only@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1"
integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==
"js-tokens@^3.0.0 || ^4.0.0":
version "4.0.0"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
loose-envify@^1.1.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
dependencies:
js-tokens "^3.0.0 || ^4.0.0"
nanoid@^3.3.4:
version "3.3.4"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab"
integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==
next@latest:
version "13.1.6"
resolved "https://registry.yarnpkg.com/next/-/next-13.1.6.tgz#054babe20b601f21f682f197063c9b0b32f1a27c"
integrity sha512-hHlbhKPj9pW+Cymvfzc15lvhaOZ54l+8sXDXJWm3OBNBzgrVj6hwGPmqqsXg40xO1Leq+kXpllzRPuncpC0Phw==
dependencies:
"@next/env" "13.1.6"
"@swc/helpers" "0.4.14"
caniuse-lite "^1.0.30001406"
postcss "8.4.14"
styled-jsx "5.1.1"
optionalDependencies:
"@next/swc-android-arm-eabi" "13.1.6"
"@next/swc-android-arm64" "13.1.6"
"@next/swc-darwin-arm64" "13.1.6"
"@next/swc-darwin-x64" "13.1.6"
"@next/swc-freebsd-x64" "13.1.6"
"@next/swc-linux-arm-gnueabihf" "13.1.6"
"@next/swc-linux-arm64-gnu" "13.1.6"
"@next/swc-linux-arm64-musl" "13.1.6"
"@next/swc-linux-x64-gnu" "13.1.6"
"@next/swc-linux-x64-musl" "13.1.6"
"@next/swc-win32-arm64-msvc" "13.1.6"
"@next/swc-win32-ia32-msvc" "13.1.6"
"@next/swc-win32-x64-msvc" "13.1.6"
picocolors@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
postcss@8.4.14:
version "8.4.14"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.14.tgz#ee9274d5622b4858c1007a74d76e42e56fd21caf"
integrity sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==
dependencies:
nanoid "^3.3.4"
picocolors "^1.0.0"
source-map-js "^1.0.2"
react-dom@latest:
version "18.2.0"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d"
integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==
dependencies:
loose-envify "^1.1.0"
scheduler "^0.23.0"
react@latest:
version "18.2.0"
resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"
integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==
dependencies:
loose-envify "^1.1.0"
scheduler@^0.23.0:
version "0.23.0"
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe"
integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==
dependencies:
loose-envify "^1.1.0"
source-map-js@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
styled-jsx@5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.1.1.tgz#839a1c3aaacc4e735fed0781b8619ea5d0009d1f"
integrity sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==
dependencies:
client-only "0.0.1"
tslib@^2.4.0:
version "2.5.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf"
integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/node",
"version": "2.8.16",
"version": "2.9.1",
"license": "MIT",
"main": "./dist/index",
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/node-js",
@@ -31,9 +31,9 @@
"dependencies": {
"@edge-runtime/vm": "2.0.0",
"@types/node": "14.18.33",
"@vercel/build-utils": "6.0.0",
"@vercel/build-utils": "6.2.0",
"@vercel/node-bridge": "3.1.10",
"@vercel/static-config": "2.0.11",
"@vercel/static-config": "2.0.12",
"edge-runtime": "2.0.0",
"esbuild": "0.14.47",
"exit-hook": "2.2.1",

View File

@@ -413,9 +413,16 @@ export const build: BuildV3 = async ({
)} (must be one of: ${JSON.stringify(ALLOWED_RUNTIMES)})`
);
}
if (staticConfig.runtime === 'nodejs') {
console.log(
`Detected unused static config runtime "nodejs" in "${entrypointPath}"`
);
}
isEdgeFunction = isEdgeRuntime(staticConfig.runtime);
}
const cron = staticConfig?.cron;
debug('Tracing input files...');
const traceTime = Date.now();
const { preparedFiles, shouldAddSourcemapSupport } = await compile(
@@ -465,6 +472,7 @@ export const build: BuildV3 = async ({
// TODO: remove - these two properties should not be required
name: outputPath,
deploymentTarget: 'v8-worker',
cron,
});
} else {
// "nodejs" runtime is the default
@@ -483,6 +491,7 @@ export const build: BuildV3 = async ({
shouldAddSourcemapSupport,
awsLambdaHandler,
experimentalResponseStreaming,
cron,
});
}

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/python",
"version": "3.1.41",
"version": "3.1.44",
"main": "./dist/index.js",
"license": "MIT",
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/python",
@@ -23,7 +23,7 @@
"@types/execa": "^0.9.0",
"@types/jest": "27.4.1",
"@types/node": "14.18.33",
"@vercel/build-utils": "6.0.0",
"@vercel/build-utils": "6.2.0",
"@vercel/ncc": "0.24.0",
"execa": "^1.0.0",
"typescript": "4.3.4"

View File

@@ -0,0 +1,14 @@
async def app(scope, receive, send):
assert scope["type"] == "http"
await send(
{
"type": "http.response.start",
"status": 200,
}
)
await send(
{
"type": "http.response.body",
"body": b"hello world"
}
)

View File

@@ -0,0 +1,18 @@
const execa = require('execa');
module.exports = async function ({ deploymentUrl, fetch }) {
const probeUrl = `https://${deploymentUrl}`;
const result = await execa('curl', [
probeUrl,
'-s',
'-H',
'foo: bar',
'-H',
'foo: bar',
]);
if (result.stdout.includes('FUNCTION_INVOCATION_FAILED')) {
throw new Error(
'Duplicate headers should not cause a function invocation failure'
);
}
};

View File

@@ -0,0 +1,9 @@
{
"version": 2,
"builds": [
{
"src": "*.py",
"use": "@vercel/python"
}
]
}

View File

@@ -276,6 +276,14 @@ elif 'app' in __vc_variables:
query = url.query.encode()
path = url.path
headers_encoded = []
for k, v in headers.items():
# Cope with repeated headers in the encoding.
if isinstance(v, list):
headers_encoded.append([k.lower().encode(), [i.encode() for i in v]])
else:
headers_encoded.append([k.lower().encode(), v.encode()])
scope = {
'server': (headers.get('host', 'lambda'), headers.get('x-forwarded-port', 80)),
'client': (headers.get(
@@ -285,7 +293,7 @@ elif 'app' in __vc_variables:
'scheme': headers.get('x-forwarded-proto', 'http'),
'root_path': '',
'query_string': query,
'headers': [[k.lower().encode(), v.encode()] for k, v in headers.items()],
'headers': headers_encoded,
'type': 'http',
'http_version': '1.1',
'method': payload['method'],

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/redwood",
"version": "1.0.52",
"version": "1.1.0",
"main": "./dist/index.js",
"license": "MIT",
"homepage": "https://vercel.com/docs",
@@ -27,7 +27,7 @@
"@types/aws-lambda": "8.10.19",
"@types/node": "14.18.33",
"@types/semver": "6.0.0",
"@vercel/build-utils": "6.0.0",
"@vercel/build-utils": "6.2.0",
"execa": "3.2.0",
"fs-extra": "11.1.0",
"typescript": "4.3.4"

View File

@@ -256,7 +256,7 @@ export const build: BuildV2 = async ({
lambdaFiles[relative(workPath, fileFsRef.fsPath)] = fileFsRef;
const { memory, maxDuration } = await getLambdaOptionsFromFunction({
const lambdaOptions = await getLambdaOptionsFromFunction({
sourceFile,
config,
});
@@ -265,11 +265,10 @@ export const build: BuildV2 = async ({
files: lambdaFiles,
handler: relativeEntrypoint,
runtime: nodeVersion.runtime,
memory,
maxDuration,
shouldAddHelpers: false,
shouldAddSourcemapSupport: false,
awsLambdaHandler,
...lambdaOptions,
});
lambdaOutputs[outputName] = lambda;
}

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/remix",
"version": "1.2.8",
"version": "1.2.11",
"license": "MIT",
"main": "./dist/index.js",
"homepage": "https://vercel.com/docs",
@@ -24,7 +24,7 @@
"devDependencies": {
"@types/jest": "27.5.1",
"@types/node": "14.18.33",
"@vercel/build-utils": "6.0.0",
"@vercel/build-utils": "6.2.0",
"typescript": "4.9.4"
}
}

View File

@@ -1,4 +1,5 @@
import { promises as fs } from 'fs';
import { runInContext, createContext } from 'vm';
import { dirname, join, relative } from 'path';
import {
debug,
@@ -23,8 +24,9 @@ import type {
PackageJson,
} from '@vercel/build-utils';
import { nodeFileTrace } from '@vercel/nft';
import type { AppConfig } from './types';
import { findConfig } from './utils';
import type { AppConfig, RemixBuildManifest } from './types';
import type { BuildResultV2Typical } from '@vercel/build-utils';
// Name of the Remix runtime adapter npm package for Vercel
const REMIX_RUNTIME_ADAPTER_NAME = '@remix-run/vercel';
@@ -205,7 +207,7 @@ export const build: BuildV2 = async ({
if (err.code !== 'MODULE_NOT_FOUND') throw err;
}
const [staticFiles, renderFunction] = await Promise.all([
const [staticFiles, renderFunction, ssrRoutes] = await Promise.all([
glob('**', join(entrypointFsDirname, 'public')),
createRenderFunction(
entrypointFsDirname,
@@ -214,8 +216,17 @@ export const build: BuildV2 = async ({
needsHandler,
nodeVersion
),
getSsrRoutes(entrypointFsDirname),
]);
const output: BuildResultV2Typical['output'] = staticFiles;
for (const path of ssrRoutes) {
output[path] = renderFunction;
}
// Add a 404 path for not found pages to be server-side rendered by Remix
output['404'] = renderFunction;
return {
routes: [
{
@@ -228,13 +239,10 @@ export const build: BuildV2 = async ({
},
{
src: '/(.*)',
dest: '/render',
dest: '/404',
},
],
output: {
render: renderFunction,
...staticFiles,
},
output,
};
};
@@ -287,3 +295,30 @@ async function createRenderFunction(
return lambda;
}
async function getSsrRoutes(entrypointDir: string): Promise<string[]> {
// Find the name of the manifest file
const buildDir = join(entrypointDir, 'public/build');
const manifestFileName = (await fs.readdir(buildDir)).find(n =>
n.startsWith('manifest-')
);
if (!manifestFileName) {
throw new Error(`Failed to find manifest file in "${buildDir}"`);
}
const context: { window: { __remixManifest?: RemixBuildManifest } } = {
window: {},
};
createContext(context);
const code = await fs.readFile(join(buildDir, manifestFileName), 'utf8');
runInContext(code, context);
const routes = context.window.__remixManifest?.routes || {};
return Object.keys(routes)
.filter(id => id !== 'root')
.map(id => {
return routes[id].path || 'index';
});
}

View File

@@ -5,3 +5,11 @@ export interface AppConfig {
serverBuildPath?: string;
serverBuildTarget?: string;
}
export interface RemixBuildManifest {
routes: {
[id: string]: {
path: string;
};
};
}

View File

@@ -0,0 +1,7 @@
export default function B() {
return (
<div style={{ fontFamily: "system-ui, sans-serif", lineHeight: "1.4" }}>
<h1>B page</h1>
</div>
);
}

View File

@@ -0,0 +1,7 @@
export default function Another() {
return (
<div style={{ fontFamily: "system-ui, sans-serif", lineHeight: "1.4" }}>
<h1>Nested another page</h1>
</div>
);
}

View File

@@ -0,0 +1,7 @@
export default function Nested() {
return (
<div style={{ fontFamily: "system-ui, sans-serif", lineHeight: "1.4" }}>
<h1>Nested index page</h1>
</div>
);
}

View File

@@ -9,5 +9,12 @@
}
}
],
"probes": [{ "path": "/", "mustContain": "Welcome to Remix" }]
"probes": [
{ "path": "/", "mustContain": "Welcome to Remix" },
{ "path": "/b", "mustContain": "B page" },
{ "path": "/nested", "mustContain": "Nested index page" },
{ "path": "/nested/another", "mustContain": "Nested another page" },
{ "path": "/nested/index", "mustContain": "Not Found" },
{ "path": "/asdf", "mustContain": "Not Found" }
]
}

View File

@@ -1,7 +1,7 @@
{
"name": "@vercel/ruby",
"author": "Nathan Cahill <nathan@nathancahill.com>",
"version": "1.3.57",
"version": "1.3.60",
"license": "MIT",
"main": "./dist/index",
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/ruby",
@@ -22,7 +22,7 @@
"devDependencies": {
"@types/fs-extra": "8.0.0",
"@types/semver": "6.0.0",
"@vercel/build-utils": "6.0.0",
"@vercel/build-utils": "6.2.0",
"@vercel/ncc": "0.24.0",
"execa": "2.0.4",
"fs-extra": "^7.0.1",

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/static-build",
"version": "1.2.1",
"version": "1.3.3",
"license": "MIT",
"main": "./dist/index",
"homepage": "https://vercel.com/docs/build-step",
@@ -15,7 +15,7 @@
"scripts": {
"build": "node build",
"test": "jest --env node --verbose --bail --runInBand",
"test-unit": "pnpm test test/build.test.ts test/gatsby.test.js test/prepare-cache.test.ts",
"test-unit": "pnpm test test/build.test.ts test/gatsby.test.ts test/prepare-cache.test.ts",
"test-integration-once": "pnpm test test/integration-*.test.js"
},
"jest": {
@@ -28,6 +28,10 @@
}
}
},
"dependencies": {
"@vercel/gatsby-plugin-vercel-analytics": "1.0.7",
"@vercel/gatsby-plugin-vercel-builder": "1.1.1"
},
"devDependencies": {
"@types/aws-lambda": "8.10.64",
"@types/cross-spawn": "6.0.0",
@@ -38,14 +42,12 @@
"@types/node-fetch": "2.5.4",
"@types/promise-timeout": "1.3.0",
"@types/semver": "7.3.13",
"@vercel/build-utils": "6.0.0",
"@vercel/build-utils": "6.2.0",
"@vercel/frameworks": "1.3.0",
"@vercel/fs-detectors": "3.7.6",
"@vercel/gatsby-plugin-vercel-analytics": "1.0.7",
"@vercel/gatsby-plugin-vercel-builder": "1.0.1",
"@vercel/fs-detectors": "3.7.9",
"@vercel/ncc": "0.24.0",
"@vercel/routing-utils": "2.1.8",
"@vercel/static-config": "2.0.11",
"@vercel/static-config": "2.0.12",
"execa": "3.2.0",
"fs-extra": "10.0.0",
"get-port": "5.0.0",

View File

@@ -43,9 +43,7 @@ import type { ImagesConfig, BuildConfig } from './utils/_shared';
import treeKill from 'tree-kill';
import {
detectFrameworkRecord,
detectFramework,
LocalFileSystemDetector,
packageManagers,
} from '@vercel/fs-detectors';
const sleep = (n: number) => new Promise(resolve => setTimeout(resolve, n));
@@ -391,20 +389,7 @@ export const build: BuildV2 = async ({
}
if (framework.slug === 'gatsby') {
const injectedPlugins = await GatsbyUtils.injectPlugins(
detectedVersion,
entrypointDir
);
if (injectedPlugins) {
const packageManager = await detectFramework({
fs: localFileSystemDetector,
frameworkList: packageManagers,
});
if (packageManager === 'pnpm') {
await execCommand('pnpm install --lockfile-only');
}
}
await GatsbyUtils.injectPlugins(detectedVersion, entrypointDir);
}
if (process.env.VERCEL_ANALYTICS_ID) {
@@ -526,6 +511,10 @@ export const build: BuildV2 = async ({
}
}
if (framework?.slug === 'gatsby') {
await GatsbyUtils.createPluginSymlinks(entrypointDir);
}
let gemHome: string | undefined = undefined;
const pathList = [];
@@ -636,32 +625,38 @@ export const build: BuildV2 = async ({
debug(`Executing "${buildCommand}"`);
}
const found =
typeof buildCommand === 'string'
? await execCommand(buildCommand, {
...spawnOpts,
try {
const found =
typeof buildCommand === 'string'
? await execCommand(buildCommand, {
...spawnOpts,
// Yarn v2 PnP mode may be activated, so force
// "node-modules" linker style
env: {
YARN_NODE_LINKER: 'node-modules',
...spawnOpts.env,
},
// Yarn v2 PnP mode may be activated, so force
// "node-modules" linker style
env: {
YARN_NODE_LINKER: 'node-modules',
...spawnOpts.env,
},
cwd: entrypointDir,
})
: await runPackageJsonScript(
entrypointDir,
['vercel-build', 'now-build', 'build'],
spawnOpts
);
cwd: entrypointDir,
})
: await runPackageJsonScript(
entrypointDir,
['vercel-build', 'now-build', 'build'],
spawnOpts
);
if (!found) {
throw new Error(
`Missing required "${
buildCommand || 'vercel-build'
}" script in "${entrypoint}"`
);
if (!found) {
throw new Error(
`Missing required "${
buildCommand || 'vercel-build'
}" script in "${entrypoint}"`
);
}
} finally {
if (framework?.slug === 'gatsby') {
await GatsbyUtils.cleanupGatsbyFiles(entrypointDir);
}
}
const outputDirPrefix = path.join(workPath, path.dirname(entrypoint));

View File

@@ -1,16 +1,7 @@
import { PackageJson } from '@vercel/build-utils';
import { promises as fs } from 'fs';
import fs from 'fs-extra';
import * as path from 'path';
import semver from 'semver';
import { URL } from 'url';
import {
fileExists,
readPackageJson,
DeepWriteable,
writePackageJson,
} from './_shared';
const { VERCEL_CLI_VERSION } = process.env;
import { fileExists } from './_shared';
const PLUGINS = [
'@vercel/gatsby-plugin-vercel-analytics',
@@ -21,13 +12,24 @@ type PluginName = typeof PLUGINS[number];
const GATSBY_CONFIG_FILE = 'gatsby-config';
const GATSBY_NODE_FILE = 'gatsby-node';
const PLUGIN_PATHS: Record<PluginName, string> = {
'@vercel/gatsby-plugin-vercel-analytics': path.dirname(
eval('require').resolve(
`@vercel/gatsby-plugin-vercel-analytics/package.json`
)
),
'@vercel/gatsby-plugin-vercel-builder': path.dirname(
eval('require').resolve(`@vercel/gatsby-plugin-vercel-builder/package.json`)
),
};
export async function injectPlugins(
detectedVersion: string | null,
dir: string
) {
const plugins = new Set<PluginName>();
if (process.env.VERCEL_GATSBY_BUILDER_PLUGIN && detectedVersion) {
if (process.env.VERCEL_GATSBY_BUILDER_PLUGIN === '1' && detectedVersion) {
const version = semver.coerce(detectedVersion);
if (version && semver.satisfies(version, '>=4.0.0')) {
plugins.add('@vercel/gatsby-plugin-vercel-builder');
@@ -43,7 +45,17 @@ export async function injectPlugins(
return false;
}
const ops = [addGatsbyPackage(dir, plugins)];
let pluginsStr = 'plugin';
if (plugins.size > 1) {
pluginsStr += 's';
}
console.log(
`Injecting Gatsby.js ${pluginsStr} ${Array.from(plugins)
.map(p => `"${p}"`)
.join(', ')}`
);
const ops = [];
if (plugins.has('@vercel/gatsby-plugin-vercel-analytics')) {
ops.push(
@@ -60,76 +72,30 @@ export async function injectPlugins(
return true;
}
function printInjectingPlugins(
plugins: Iterable<PluginName>,
configPath: string
) {
const pluginsArray = Array.from(plugins);
let pluginsStr = 'plugin';
if (pluginsArray.length > 1) {
pluginsStr += 's';
}
console.log(
`Injecting Gatsby.js ${pluginsStr} ${pluginsArray
.map(p => `"${p}"`)
.join(', ')} to \`${configPath}\``
);
}
async function addGatsbyPackage(
dir: string,
plugins: Iterable<PluginName>
): Promise<void> {
const pkgJson = (await readPackageJson(dir)) as DeepWriteable<PackageJson>;
if (!pkgJson.dependencies) {
pkgJson.dependencies = {};
}
for (const plugin of plugins) {
if (!pkgJson.dependencies[plugin]) {
console.log(`Adding "${plugin}" to \`package.json\` "dependencies"`);
let version = 'latest';
// Use the tarball URL for E2E tests
if (VERCEL_CLI_VERSION?.startsWith('https://')) {
version = new URL(`./${plugin}.tgz`, VERCEL_CLI_VERSION).href;
}
pkgJson.dependencies[plugin] = version;
}
}
await writePackageJson(dir, pkgJson);
}
async function updateGatsbyConfig(dir: string, plugins: Iterable<PluginName>) {
async function updateGatsbyConfig(dir: string, plugins: string[]) {
const gatsbyConfigPathTs = path.join(dir, `${GATSBY_CONFIG_FILE}.ts`);
const gatsbyConfigPathMjs = path.join(dir, `${GATSBY_CONFIG_FILE}.mjs`);
const gatsbyConfigPathJs = path.join(dir, `${GATSBY_CONFIG_FILE}.js`);
if (await fileExists(gatsbyConfigPathTs)) {
printInjectingPlugins(plugins, gatsbyConfigPathTs);
await updateGatsbyConfigTs(gatsbyConfigPathTs, plugins);
} else if (await fileExists(gatsbyConfigPathMjs)) {
printInjectingPlugins(plugins, gatsbyConfigPathMjs);
await updateGatsbyConfigMjs(gatsbyConfigPathMjs, plugins);
} else if (await fileExists(gatsbyConfigPathJs)) {
await updateGatsbyConfigJs(gatsbyConfigPathJs, plugins);
} else {
printInjectingPlugins(plugins, gatsbyConfigPathJs);
if (await fileExists(gatsbyConfigPathJs)) {
await updateGatsbyConfigJs(gatsbyConfigPathJs, plugins);
} else {
await fs.writeFile(
gatsbyConfigPathJs,
`module.exports = ${JSON.stringify({
plugins: Array.from(plugins),
})}`
);
}
await fs.writeFile(
gatsbyConfigPathJs,
`${GENERATED_FILE_COMMENT}
module.exports = ${JSON.stringify({ plugins })}`
);
}
}
const GENERATED_FILE_COMMENT = `// This file was generated by @vercel/static-build`;
async function updateGatsbyConfigTs(
configPath: string,
plugins: Iterable<PluginName>
plugins: string[]
): Promise<void> {
const renamedPath = `${configPath}.__vercel_builder_backup__.ts`;
if (!(await fileExists(renamedPath))) {
@@ -138,7 +104,8 @@ async function updateGatsbyConfigTs(
await fs.writeFile(
configPath,
`import userConfig from "./gatsby-config.ts.__vercel_builder_backup__.ts";
`${GENERATED_FILE_COMMENT}
import userConfig from "./gatsby-config.ts.__vercel_builder_backup__.ts";
import type { PluginRef } from "gatsby";
const preferDefault = (m: any) => (m && m.default) || m;
@@ -152,7 +119,7 @@ if (!vercelConfig.plugins) {
vercelConfig.plugins = [];
}
for (const plugin of ${JSON.stringify(Array.from(plugins))}) {
for (const plugin of ${JSON.stringify(plugins)}) {
const hasPlugin = vercelConfig.plugins.find(
(p: PluginRef) =>
p && (p === plugin || p.resolve === plugin)
@@ -171,7 +138,7 @@ export default vercelConfig;
async function updateGatsbyConfigMjs(
configPath: string,
plugins: Iterable<PluginName>
plugins: string[]
): Promise<void> {
const renamedPath = `${configPath}.__vercel_builder_backup__.mjs`;
if (!(await fileExists(renamedPath))) {
@@ -180,7 +147,8 @@ async function updateGatsbyConfigMjs(
await fs.writeFile(
configPath,
`import userConfig from "./gatsby-config.mjs.__vercel_builder_backup__.mjs";
`${GENERATED_FILE_COMMENT}
import userConfig from "./gatsby-config.mjs.__vercel_builder_backup__.mjs";
const preferDefault = (m) => (m && m.default) || m;
@@ -188,11 +156,12 @@ const vercelConfig = Object.assign(
{},
preferDefault(userConfig)
);
if (!vercelConfig.plugins) {
vercelConfig.plugins = [];
}
for (const plugin of ${JSON.stringify(Array.from(plugins))}) {
for (const plugin of ${JSON.stringify(plugins)}) {
const hasPlugin = vercelConfig.plugins.find(
(p) => p && (p === plugin || p.resolve === plugin)
);
@@ -210,7 +179,7 @@ export default vercelConfig;
async function updateGatsbyConfigJs(
configPath: string,
plugins: Iterable<PluginName>
plugins: string[]
): Promise<void> {
const renamedPath = `${configPath}.__vercel_builder_backup__.js`;
if (!(await fileExists(renamedPath))) {
@@ -219,7 +188,8 @@ async function updateGatsbyConfigJs(
await fs.writeFile(
configPath,
`const userConfig = require("./gatsby-config.js.__vercel_builder_backup__.js");
`${GENERATED_FILE_COMMENT}
const userConfig = require("./gatsby-config.js.__vercel_builder_backup__.js");
const preferDefault = m => (m && m.default) || m;
@@ -227,11 +197,12 @@ const vercelConfig = Object.assign(
{},
preferDefault(userConfig)
);
if (!vercelConfig.plugins) {
vercelConfig.plugins = [];
}
for (const plugin of ${JSON.stringify(Array.from(plugins))}) {
for (const plugin of ${JSON.stringify(plugins)}) {
const hasPlugin = vercelConfig.plugins.find(
(p) => p && (p === plugin || p.resolve === plugin)
);
@@ -259,7 +230,8 @@ async function updateGatsbyNode(dir: string) {
} else {
await fs.writeFile(
gatsbyNodePathJs,
`module.exports = require('@vercel/gatsby-plugin-vercel-builder/gatsby-node.js');`
`${GENERATED_FILE_COMMENT}
module.exports = require('@vercel/gatsby-plugin-vercel-builder/gatsby-node.js');`
);
}
}
@@ -272,7 +244,8 @@ async function updateGatsbyNodeTs(configPath: string) {
await fs.writeFile(
configPath,
`import type { GatsbyNode } from 'gatsby';
`${GENERATED_FILE_COMMENT}
import type { GatsbyNode } from 'gatsby';
import * as vercelBuilder from '@vercel/gatsby-plugin-vercel-builder/gatsby-node.js';
import * as gatsbyNode from './gatsby-node.ts.__vercel_builder_backup__.ts';
@@ -296,7 +269,8 @@ async function updateGatsbyNodeMjs(configPath: string) {
await fs.writeFile(
configPath,
`import * as vercelBuilder from '@vercel/gatsby-plugin-vercel-builder/gatsby-node.js';
`${GENERATED_FILE_COMMENT}
import * as vercelBuilder from '@vercel/gatsby-plugin-vercel-builder/gatsby-node.js';
import * as gatsbyNode from './gatsby-node.mjs.__vercel_builder_backup__.mjs';
export * from './gatsby-node.mjs.__vercel_builder_backup__.mjs';
@@ -319,7 +293,8 @@ async function updateGatsbyNodeJs(configPath: string) {
await fs.writeFile(
configPath,
`const vercelBuilder = require('@vercel/gatsby-plugin-vercel-builder/gatsby-node.js');
`${GENERATED_FILE_COMMENT}
const vercelBuilder = require('@vercel/gatsby-plugin-vercel-builder/gatsby-node.js');
const gatsbyNode = require('./gatsby-node.js.__vercel_builder_backup__.js');
const origOnPostBuild = gatsbyNode.onPostBuild;
@@ -335,3 +310,46 @@ module.exports = gatsbyNode;
`
);
}
export async function cleanupGatsbyFiles(dir: string) {
const backup = '.__vercel_builder_backup__';
const fileEndings = ['.js', '.ts', '.mjs'];
for (const fileName of [GATSBY_CONFIG_FILE, GATSBY_NODE_FILE]) {
for (const fileEnding of fileEndings) {
const baseFile = `${fileName}${fileEnding}`;
const baseFilePath = path.join(dir, baseFile);
const backupFile = `${baseFile}${backup}${fileEnding}`;
const backupFilePath = path.join(dir, backupFile);
const [baseFileContent, backupFileContent] = await Promise.all([
fs.readFile(baseFilePath, 'utf-8').catch(() => null),
fs.readFile(backupFilePath, 'utf-8').catch(() => null),
]);
if (
baseFileContent &&
baseFileContent.startsWith(GENERATED_FILE_COMMENT)
) {
await fs.rm(baseFilePath);
}
if (backupFileContent) {
await fs.rename(backupFilePath, baseFilePath);
}
}
}
}
export async function createPluginSymlinks(dir: string) {
const nodeModulesDir = path.join(dir, 'node_modules');
await fs.ensureDir(path.join(nodeModulesDir, '@vercel'));
await Promise.all(
PLUGINS.map(name => fs.remove(path.join(nodeModulesDir, name)))
);
await Promise.all(
PLUGINS.map(name =>
fs.symlink(PLUGIN_PATHS[name], path.join(nodeModulesDir, name))
)
);
}

View File

@@ -25,6 +25,10 @@
{
"path": "/asset.txt",
"mustContain": "asset that was added in `onPostBuild`"
},
{
"path": "/api/hello",
"mustContain": "{\"message\":\"A ok!\"}"
}
]
}

View File

@@ -0,0 +1,4 @@
export default function handler(req, res) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.status(200).json({ message: 'A ok!' });
}

View File

@@ -1,4 +1,8 @@
import { injectPlugins } from '../src/utils/gatsby';
import {
injectPlugins,
createPluginSymlinks,
cleanupGatsbyFiles,
} from '../src/utils/gatsby';
import path from 'path';
import {
detectFrameworkRecord,
@@ -58,22 +62,13 @@ describe('gatsby utilities', () => {
const fixture = await prepareFixture(path.join(fixturesPath, 'gatsby-v3'));
const version = await detectVersion(fixture);
await injectPlugins(version, fixture);
const [packageJSON, gatsbyConfig] = await Promise.all([
fs.readFile(path.join(fixture, 'package.json'), 'utf-8'),
const [gatsbyConfig] = await Promise.all([
fs.readFile(path.join(fixture, 'gatsby-config.js'), 'utf-8'),
]);
expect(packageJSON).toMatchInlineSnapshot(`
"{
\\"dependencies\\": {
\\"gatsby\\": \\"3.0.0\\",
\\"@vercel/gatsby-plugin-vercel-analytics\\": \\"latest\\"
}
}
"
expect(gatsbyConfig).toMatchInlineSnapshot(`
"// This file was generated by @vercel/static-build
module.exports = {\\"plugins\\":[\\"@vercel/gatsby-plugin-vercel-analytics\\"]}"
`);
expect(gatsbyConfig).toMatchInlineSnapshot(
`"module.exports = {\\"plugins\\":[\\"@vercel/gatsby-plugin-vercel-analytics\\"]}"`
);
});
it('should inject plugins and create gatsby-node.js and gatsby-config.js', async () => {
@@ -82,27 +77,18 @@ describe('gatsby utilities', () => {
const fixture = await prepareFixture(path.join(fixturesPath, 'gatsby-v4'));
const version = await detectVersion(fixture);
await injectPlugins(version, fixture);
const [packageJSON, gatsbyNode, gatsbyConfig] = await Promise.all([
fs.readFile(path.join(fixture, 'package.json'), 'utf-8'),
const [gatsbyNode, gatsbyConfig] = await Promise.all([
fs.readFile(path.join(fixture, 'gatsby-node.js'), 'utf-8'),
fs.readFile(path.join(fixture, 'gatsby-config.js'), 'utf-8'),
]);
expect(packageJSON).toMatchInlineSnapshot(`
"{
\\"dependencies\\": {
\\"gatsby\\": \\"4.25.2\\",
\\"@vercel/gatsby-plugin-vercel-builder\\": \\"latest\\",
\\"@vercel/gatsby-plugin-vercel-analytics\\": \\"latest\\"
}
}
"
expect(gatsbyNode).toMatchInlineSnapshot(`
"// This file was generated by @vercel/static-build
module.exports = require('@vercel/gatsby-plugin-vercel-builder/gatsby-node.js');"
`);
expect(gatsbyConfig).toMatchInlineSnapshot(`
"// This file was generated by @vercel/static-build
module.exports = {\\"plugins\\":[\\"@vercel/gatsby-plugin-vercel-analytics\\"]}"
`);
expect(gatsbyNode).toMatchInlineSnapshot(
`"module.exports = require('@vercel/gatsby-plugin-vercel-builder/gatsby-node.js');"`
);
expect(gatsbyConfig).toMatchInlineSnapshot(
`"module.exports = {\\"plugins\\":[\\"@vercel/gatsby-plugin-vercel-analytics\\"]}"`
);
});
it('should inject builder plugin and update gatsby-node.js and gatsby-config.js', async () => {
@@ -113,37 +99,22 @@ describe('gatsby utilities', () => {
);
const version = await detectVersion(fixture);
await injectPlugins(version, fixture);
const [
packageJSON,
gatsbyNode,
gatsbyNodeBackup,
gatsbyConfig,
gatsbyConfigBackup,
] = await Promise.all([
fs.readFile(path.join(fixture, 'package.json'), 'utf-8'),
fs.readFile(path.join(fixture, 'gatsby-node.js'), 'utf-8'),
fs.readFile(
path.join(fixture, 'gatsby-node.js.__vercel_builder_backup__.js'),
'utf-8'
),
fs.readFile(path.join(fixture, 'gatsby-config.js'), 'utf-8'),
fs.readFile(
path.join(fixture, 'gatsby-config.js.__vercel_builder_backup__.js'),
'utf-8'
),
]);
expect(packageJSON).toMatchInlineSnapshot(`
"{
\\"dependencies\\": {
\\"gatsby\\": \\"4.25.2\\",
\\"@vercel/gatsby-plugin-vercel-builder\\": \\"latest\\",
\\"@vercel/gatsby-plugin-vercel-analytics\\": \\"latest\\"
}
}
"
`);
const [gatsbyNode, gatsbyNodeBackup, gatsbyConfig, gatsbyConfigBackup] =
await Promise.all([
fs.readFile(path.join(fixture, 'gatsby-node.js'), 'utf-8'),
fs.readFile(
path.join(fixture, 'gatsby-node.js.__vercel_builder_backup__.js'),
'utf-8'
),
fs.readFile(path.join(fixture, 'gatsby-config.js'), 'utf-8'),
fs.readFile(
path.join(fixture, 'gatsby-config.js.__vercel_builder_backup__.js'),
'utf-8'
),
]);
expect(gatsbyNode).toMatchInlineSnapshot(`
"const vercelBuilder = require('@vercel/gatsby-plugin-vercel-builder/gatsby-node.js');
"// This file was generated by @vercel/static-build
const vercelBuilder = require('@vercel/gatsby-plugin-vercel-builder/gatsby-node.js');
const gatsbyNode = require('./gatsby-node.js.__vercel_builder_backup__.js');
const origOnPostBuild = gatsbyNode.onPostBuild;
@@ -163,7 +134,8 @@ describe('gatsby utilities', () => {
"
`);
expect(gatsbyConfig).toMatchInlineSnapshot(`
"const userConfig = require(\\"./gatsby-config.js.__vercel_builder_backup__.js\\");
"// This file was generated by @vercel/static-build
const userConfig = require(\\"./gatsby-config.js.__vercel_builder_backup__.js\\");
const preferDefault = m => (m && m.default) || m;
@@ -171,6 +143,7 @@ describe('gatsby utilities', () => {
{},
preferDefault(userConfig)
);
if (!vercelConfig.plugins) {
vercelConfig.plugins = [];
}
@@ -202,37 +175,22 @@ describe('gatsby utilities', () => {
);
const version = await detectVersion(fixture);
await injectPlugins(version, fixture);
const [
packageJSON,
gatsbyNode,
gatsbyNodeBackup,
gatsbyConfig,
gatsbyConfigBackup,
] = await Promise.all([
fs.readFile(path.join(fixture, 'package.json'), 'utf-8'),
fs.readFile(path.join(fixture, 'gatsby-node.ts'), 'utf-8'),
fs.readFile(
path.join(fixture, 'gatsby-node.ts.__vercel_builder_backup__.ts'),
'utf-8'
),
fs.readFile(path.join(fixture, 'gatsby-config.ts'), 'utf-8'),
fs.readFile(
path.join(fixture, 'gatsby-config.ts.__vercel_builder_backup__.ts'),
'utf-8'
),
]);
expect(packageJSON).toMatchInlineSnapshot(`
"{
\\"dependencies\\": {
\\"gatsby\\": \\"4.25.2\\",
\\"@vercel/gatsby-plugin-vercel-builder\\": \\"latest\\",
\\"@vercel/gatsby-plugin-vercel-analytics\\": \\"latest\\"
}
}
"
`);
const [gatsbyNode, gatsbyNodeBackup, gatsbyConfig, gatsbyConfigBackup] =
await Promise.all([
fs.readFile(path.join(fixture, 'gatsby-node.ts'), 'utf-8'),
fs.readFile(
path.join(fixture, 'gatsby-node.ts.__vercel_builder_backup__.ts'),
'utf-8'
),
fs.readFile(path.join(fixture, 'gatsby-config.ts'), 'utf-8'),
fs.readFile(
path.join(fixture, 'gatsby-config.ts.__vercel_builder_backup__.ts'),
'utf-8'
),
]);
expect(gatsbyNode).toMatchInlineSnapshot(`
"import type { GatsbyNode } from 'gatsby';
"// This file was generated by @vercel/static-build
import type { GatsbyNode } from 'gatsby';
import * as vercelBuilder from '@vercel/gatsby-plugin-vercel-builder/gatsby-node.js';
import * as gatsbyNode from './gatsby-node.ts.__vercel_builder_backup__.ts';
@@ -251,7 +209,8 @@ describe('gatsby utilities', () => {
"
`);
expect(gatsbyConfig).toMatchInlineSnapshot(`
"import userConfig from \\"./gatsby-config.ts.__vercel_builder_backup__.ts\\";
"// This file was generated by @vercel/static-build
import userConfig from \\"./gatsby-config.ts.__vercel_builder_backup__.ts\\";
import type { PluginRef } from \\"gatsby\\";
const preferDefault = (m: any) => (m && m.default) || m;
@@ -294,37 +253,22 @@ describe('gatsby utilities', () => {
);
const version = await detectVersion(fixture);
await injectPlugins(version, fixture);
const [
packageJSON,
gatsbyNode,
gatsbyNodeBackup,
gatsbyConfig,
gatsbyConfigBackup,
] = await Promise.all([
fs.readFile(path.join(fixture, 'package.json'), 'utf-8'),
fs.readFile(path.join(fixture, 'gatsby-node.mjs'), 'utf-8'),
fs.readFile(
path.join(fixture, 'gatsby-node.mjs.__vercel_builder_backup__.mjs'),
'utf-8'
),
fs.readFile(path.join(fixture, 'gatsby-config.mjs'), 'utf-8'),
fs.readFile(
path.join(fixture, 'gatsby-config.mjs.__vercel_builder_backup__.mjs'),
'utf-8'
),
]);
expect(packageJSON).toMatchInlineSnapshot(`
"{
\\"dependencies\\": {
\\"gatsby\\": \\"4.25.2\\",
\\"@vercel/gatsby-plugin-vercel-builder\\": \\"latest\\",
\\"@vercel/gatsby-plugin-vercel-analytics\\": \\"latest\\"
}
}
"
`);
const [gatsbyNode, gatsbyNodeBackup, gatsbyConfig, gatsbyConfigBackup] =
await Promise.all([
fs.readFile(path.join(fixture, 'gatsby-node.mjs'), 'utf-8'),
fs.readFile(
path.join(fixture, 'gatsby-node.mjs.__vercel_builder_backup__.mjs'),
'utf-8'
),
fs.readFile(path.join(fixture, 'gatsby-config.mjs'), 'utf-8'),
fs.readFile(
path.join(fixture, 'gatsby-config.mjs.__vercel_builder_backup__.mjs'),
'utf-8'
),
]);
expect(gatsbyNode).toMatchInlineSnapshot(`
"import * as vercelBuilder from '@vercel/gatsby-plugin-vercel-builder/gatsby-node.js';
"// This file was generated by @vercel/static-build
import * as vercelBuilder from '@vercel/gatsby-plugin-vercel-builder/gatsby-node.js';
import * as gatsbyNode from './gatsby-node.mjs.__vercel_builder_backup__.mjs';
export * from './gatsby-node.mjs.__vercel_builder_backup__.mjs';
@@ -342,7 +286,8 @@ describe('gatsby utilities', () => {
"
`);
expect(gatsbyConfig).toMatchInlineSnapshot(`
"import userConfig from \\"./gatsby-config.mjs.__vercel_builder_backup__.mjs\\";
"// This file was generated by @vercel/static-build
import userConfig from \\"./gatsby-config.mjs.__vercel_builder_backup__.mjs\\";
const preferDefault = (m) => (m && m.default) || m;
@@ -350,6 +295,7 @@ describe('gatsby utilities', () => {
{},
preferDefault(userConfig)
);
if (!vercelConfig.plugins) {
vercelConfig.plugins = [];
}
@@ -373,4 +319,89 @@ describe('gatsby utilities', () => {
"
`);
});
describe(`createPluginSymlinks()`, () => {
it('should add symlinks for Gatsby plugins', async () => {
const fixture = await prepareFixture(
path.join(fixturesPath, 'gatsby-v4-existing-files-mjs')
);
await createPluginSymlinks(fixture);
const analytics = require(path.join(
fixture,
'node_modules/@vercel/gatsby-plugin-vercel-analytics'
));
expect(typeof analytics).toEqual('object');
const builder = require(path.join(
fixture,
'node_modules/@vercel/gatsby-plugin-vercel-builder/gatsby-node.js'
));
expect(typeof builder.onPostBuild).toEqual('function');
});
});
describe('cleanupGatsbyFiles()', () => {
it('should delete base files starting with the generated comment', async () => {
const files = [
'gatsby-node.js',
'gatsby-config.js',
'gatsby-node.mjs',
'gatsby-config.mjs',
'gatsby-node.ts',
'gatsby-config.ts',
];
const dir = await fs.mkdtemp(path.join(os.tmpdir(), 'cleanup-test'));
await Promise.all(
files.map(file =>
fs.writeFile(
path.join(dir, file),
`// This file was generated by @vercel/static-build\nconsole.log('Hello, World!');`
)
)
);
expect((await fs.readdir(dir)).length).toBe(6);
await cleanupGatsbyFiles(dir);
expect((await fs.readdir(dir)).length).toBe(0);
});
});
it('should restore backups', async () => {
const files = [
'gatsby-node.js',
'gatsby-config.js',
'gatsby-node.mjs',
'gatsby-config.mjs',
'gatsby-node.ts',
'gatsby-config.ts',
];
const dir = await fs.mkdtemp(path.join(os.tmpdir(), 'cleanup-test'));
await Promise.all(
files.flatMap(file => [
fs.writeFile(
path.join(dir, file),
`// This file was generated by @vercel/static-build\nconsole.log('Hello, World!');`
),
fs.writeFile(
path.join(
dir,
`${file}.__vercel_builder_backup__${path.extname(file)}`
),
`console.log('Hello, World!');`
),
])
);
expect((await fs.readdir(dir)).length).toBe(12);
await cleanupGatsbyFiles(dir);
const afterDelete = await fs.readdir(dir);
expect(afterDelete.length).toBe(6);
expect(afterDelete.sort()).toEqual(files.sort());
});
});

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