Compare commits

...

93 Commits

Author SHA1 Message Date
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
Steven
25f6595d36 Publish Stable
- @vercel/build-utils@6.0.0
 - vercel@28.13.2
 - @vercel/client@12.3.3
 - @vercel/edge@0.2.7
 - @vercel/frameworks@1.3.0
 - @vercel/fs-detectors@3.7.6
 - @vercel/gatsby-plugin-vercel-builder@1.0.1
 - @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
2023-01-26 11:19:03 -05:00
JJ Kasper
e8385566fa [next] Ensure we warn when leveraging next export (#9319)
We currently don't make it obvious when `next export` is being leveraged which de-opts features like `middleware`, `rewrites`, `redirects`, etc. so this adds a notice to let users know when we are using `next export` output.
2023-01-26 04:54:24 +00:00
Ethan Arrowood
52ca35252a [tests] add gatsby related unit tests to static-build (#9318)
Adds some unit tests for the gatsby injection logic. 

These are net new since we've heavily changed the injection logic. The tests and fixtures in `build-fixtures` and `builds.test.js` are seemingly not executed. We may delete those here too.
2023-01-26 03:33:18 +00:00
Steven
2004e3d734 [tests] Fix jest-haste-map: Haste module naming collision (#9317)
```
jest-haste-map: Haste module naming collision: app-three
The following files share their name; please adjust your hasteImpl:
  * <rootDir>/test/fixtures/33-hybrid-monorepo/backend/app-three/package.json
  * <rootDir>/test/fixtures/34-monorepo-no-workspaces/backend/app-three/package.json
```
2023-01-26 00:59:39 +00:00
Steven
49b4394c44 [next] Remove hardcoded NODE_OPTIONS (#9314)
The `NODE_OPTIONS` env var value is wrong here and we shouldn't be overriding the user's setting to begin with.

Typically, it will be assigned in a build container or project settings.
2023-01-25 22:53:06 +00:00
Steven
08cdfa2a05 [tests] Fix turbo config and bump to latest version (#9307)
We had Turborepo miscofigured. The `dependsOn: ["^build"]` means run all dependencies' build script, but it doesn't mean the package's build script will run first. For tests, it should always `dependsOn: ["build"]` (without the upcaret) instead to ensure its own build is complete before testing. I also learned that `outputs: []` can be dropped now since thats the default behavior.
2023-01-25 20:45:56 +00:00
Nathan Rajlich
f18fa8546f [static-build] Patch the gatsby-node config file to invoke @vercel/gatsby-plugin-vercel-builder (#9308)
We need to ensure that `@vercel/gatsby-plugin-vercel-builder` is executed as the very last plugin, which Gatsby itself doesn't really support in the plugins listing. So instead we'll patch the `gatsby-node` file to invoke the plugin in the project's own `onPostBuild()` hook, which does get executed last. The patching is similar to how is done with the `gatsby-config` file.
2023-01-25 19:07:04 +00:00
Swarnava Sengupta
025344c4a7 [examples] Update Parcel version to support Node 18 (#9310)
Looks like our Parcel examples are currently failing in Node 18.x.
Updating the version which also Support Node 18.x

<img width="814" alt="image"
src="https://user-images.githubusercontent.com/1162991/214491854-92dc39a4-d7b7-442a-a16c-88621b52621a.png">
2023-01-25 10:08:45 -05:00
Chris Swithinbank
8b036e97ea [frameworks] Add default immutable cache path for Astro v2 (#9305)
Astro v2 was released today. It includes [improved support for caching
all hashed build
assets](https://docs.astro.build/en/guides/upgrade-to/v2/#changed-_astro-folder-for-build-assets)
by gathering these all in a single `_astro` directory in build output
(previously these ended up in a number of different places).

This PR updates the Vercel frameworks config to provide out-of-the-box
immutable caching for these assets.

Co-authored-by: Steven <steven@ceriously.com>
2023-01-24 19:05:13 -05:00
Ethan Arrowood
a4240e89e1 [gatsby-plugin-vercel-builder] add support for pathPrefix (#9294)
This pr adds support for the gatsby `pathPrefix`  properties
2023-01-24 23:37:03 +00:00
Nathan Rajlich
0863ae0c6f [gatsby-plugin-vercel-builder] Get rid of the _ssr function (#9304)
Right now we create the SSR serverless function at path `_ssr`, and then symlink all the other pages to that function.

Instead just make the first page encountered be the "real" function, and symlink all the other pages to that endpoint.
2023-01-24 22:10:43 +00:00
github-actions[bot]
e09d3d5928 [examples] Upgrade Next.js to version 13.1.5 (#9288)
This auto-generated PR updates Next.js to version 13.1.5
2023-01-24 21:52:38 +00:00
Nathan Rajlich
f5f544ffd2 [gatsby-plugin-vercel-builder] Merge SSR and page-data into single Serverless Function (#9292)
Previously, the page-data Serverless Function and SSR Serverless Function were two distinct functions. They had almost identical file contents and just slightly different handler logic. So here we merge the handler logic into a single function and re-use the same Serverless Function for both page-data and SSR.

This simplifies the output quite a bit and deletes a good amount of code, and helps with build output size, cold boot times, etc.
2023-01-24 19:36:47 +00:00
Lee Robinson
4eb1ff8730 chore: Update Gatsby example README (#9300) 2023-01-24 18:48:04 +00:00
Chris Barber
d4b604f05c [tests] Added cron workflow to update turbo (#9301)
Linear: https://linear.app/vercel/issue/VCCLI-450/add-cron-update-turbo-workflow

Based on the Next.js update script, this PR adds a cron job that checks for the latest Turbo canary release, then updates the `package.json` and `pnpm-lock.yaml` files.
2023-01-24 18:17:39 +00:00
Sean Massa
a3cf05af06 [tests] Update CODEOWNERS (#9277) 2023-01-24 09:20:03 -06:00
Steven
df2bcec830 [edge] Add missing metadata to package.json (#9293)
I noticed this was missing when visiting https://www.npmjs.com/package/@vercel/edge
2023-01-24 09:11:14 +00:00
Nathan Rajlich
f5e81273af [static-build] Add Gatsby plugins as dev dependencies (#9298)
So that the test runs get invalidated by Turbo when code changes within one of the plugin files. This is to avoid a PR breaking something in a plugin, but we don't notice it because the static-build tests still "pass" due to cache hit.
2023-01-24 05:32:03 +00:00
Nathan Rajlich
e75d900eaf [static-build] Use tarball URLs for Gatsby plugin E2E tests (#9297)
When running the static-build integration tests, use the tarball URL for the Gatsby plugins, so that any changes made to the plugin(s) in the PR will be reflected in the test deployments without having to publish to npm first.

Example screenshots of a deployment's build logs before I removed the debugging:

<img width="1045" alt="Screenshot 2023-01-23 at 7 35 32 PM" src="https://user-images.githubusercontent.com/71256/214207250-24695a11-051d-4abb-a132-729ab0ab167a.png">
<img width="517" alt="Screenshot 2023-01-23 at 7 35 41 PM" src="https://user-images.githubusercontent.com/71256/214207254-74265e05-ed17-4fbb-b54d-9edc2234a3e4.png">
2023-01-24 04:43:07 +00:00
Chris Barber
1a4f185045 [build-utils] Removed unused execAsync() function (#9200)
This function can sometimes give a TypeScript error if @types/node says 'code' should be a `number | null` and yet the code is returns as a `number`:

```
@vercel/build-utils:build: src/fs/run-user-scripts.ts(140,13): error TS2322: Type 'number \| null' is not assignable to type 'number'.
@vercel/build-utils:build:   Type 'null' is not assignable to type 'number'.
```

I'm not sure if there are any other projects that depend on `@vercel/build-utils`, but it doesn't appear that the Vercel CLI nor the build container use this `execAsync()` function. If I'm mistaken, feel free to close this PR.

As this removal is a breaking change, setting the semver to major and not auto-merging unless others are in agreement.
2023-01-24 01:05:44 +00:00
Steven
35cc7db1a7 [cli] add missing deprecation warnings for builders/runtimes (#9289)
We used to print deprecations on the old build pipeline but this was lost when switching to `vercel build`.

This PR ensures that `vercel build` prints deprecation warnings if available.

## Example

https://npmjs.com/package/@now/node

<img width="751" alt="image" src="https://user-images.githubusercontent.com/229881/214143779-f71c88c8-6ee3-47ce-b459-a86154474991.png">
2023-01-23 23:51:58 +00:00
Nathan Rajlich
f535a20aad [gatsby-plugin-vercel-builder] Remove vercel.config.js file handling (#9290) 2023-01-23 21:31:49 +00:00
Ethan Arrowood
fcea36bf04 Publish Stable
- vercel@28.13.1
 - @vercel/gatsby-plugin-vercel-analytics@1.0.7
 - @vercel/gatsby-plugin-vercel-builder@1.0.0
2023-01-23 12:22:45 -07:00
Steven
93f5a4438b [cli] Improve error message when using legacy @now builders (#8677)
This PR adds a helpful error message when using a legacy `@now` builder.

This mimics the behavior of the build-container.
2023-01-23 17:49:24 +00:00
github-actions[bot]
72265aa9a1 [examples] Upgrade Next.js to version 13.1.4 (#9279)
This auto-generated PR updates Next.js to version 13.1.4

Co-authored-by: vercel-release-bot <infra+release@vercel.com>
2023-01-20 19:23:59 -05:00
Felix Haus
6ee5eb137b [examples] Restrict node version for gridsome example (#9275)
Gridsome was not updated for [more than 2 years](https://www.npmjs.com/package/gridsome) and still relies on Webpack 4 what makes it incompatible with >= Node.js 17.
To make the example still deployable on Vercel, this adds an engine restriction to the `package.json` for that example.

Same as #9007.
2023-01-20 23:32:04 +00:00
Ethan Arrowood
c4f1c2f5ed [gatsby-plugin-vercel-analytics] add build script (#9260)
Adds the previously omitted build script. Includes necessary changes to turbo.json too
2023-01-20 22:31:41 +00:00
Ethan Arrowood
f35a77c292 [gatsby-plugin-vercel-builder] support trailingSlash configuration (#9278)
Connects the gatsby trailingslash configuration property to our BOA3
trailingslash property
2023-01-20 14:15:58 -07:00
Andy McKay
4bf3c237ee [cli] Revert some tables back to stdout (#9227)
In https://github.com/vercel/vercel/pull/8735 some output was sent to `stderr`, this sends them `stdout` instead.
2023-01-20 20:58:28 +00:00
github-actions[bot]
62c991f25e [examples] Upgrade Next.js to version 13.1.3 (#9271)
This auto-generated PR updates Next.js to version 13.1.3
2023-01-20 20:39:26 +00:00
Nathan Rajlich
6ea2db4ae9 [gatsby-plugin-vercel-builder] Various fixes and refactoring (#9268)
* Sets a valid number of seconds for DSG expiration (10 minutes - do we want to make that configurable somehow?)
* Sets the `group` of DSG pages, so that the page-data and SSR pages are associated
* Outputs SSR/DSG pages with `/index.html` suffix so that those paths are accessible
* Updates SSR and page-data functions URL path parsing logic to handle querystrings and the `index.html` scenario
* Remove the unnecessary `rewrite` related to page-data URL paths
* Remove the page-data function static file fallback handling (they are accessible as just regular static files)
* Correct the path for the page-data endpoing when the root-level index page is SSR/DSG
2023-01-20 18:49:44 +00:00
Ethan Arrowood
1943b1ecc0 [gatsby-plugin-vercel-builder] add documentation to README (#9264)
Adds some basic documentation to the plugin
2023-01-20 18:07:25 +00:00
Ethan Arrowood
92f5b6e0c9 Publish Stable
- vercel@28.13.0
 - @vercel/gatsby-plugin-vercel-builder@0.1.2
 - @vercel/next@3.3.18
 - @vercel/node@2.8.15
 - @vercel/static-build@1.2.0
2023-01-20 10:27:31 -07:00
JJ Kasper
ed6ce1149a [next] Ensure outputDirectory is normalized (#9269)
This ensures we normalize an absolute `outputDirectory` passed into the Next.js builder as this can cause incorrect resolving. We should probably normalize this higher up as well but this is a starting point. 

Fixes: [slack thread](https://vercel.slack.com/archives/C0289CGVAR2/p1674176040821579?thread_ts=1674168748.257019&cid=C0289CGVAR2)
2023-01-20 17:08:32 +00:00
Ethan Arrowood
fc3611fb80 [static-build] add gatsby v5 fixture (#9267)
Adds a gatsby v5 fixture using ssr and dsg to demonstrate plugin works

Co-authored-by: Nathan Rajlich <n@n8.io>
2023-01-20 03:02:26 -08:00
Nathan Rajlich
ed33c2b27c [gatsby-plugin-vercel-builder] Remove some leftover console.log calls (#9265) 2023-01-19 16:05:48 -08:00
Nathan Rajlich
a7a5bf1a12 [tests] Pass in builder to runBuildLambda() (#9262)
Removes the need for `next`/`static-build` to be present in the root `package.json` file.
2023-01-19 15:10:06 -08:00
JJ Kasper
cc687b3880 [next] Correct RSC route for app dir with trailingSlash (#9263) 2023-01-19 15:03:58 -08:00
Nathan Rajlich
053ec92d5f [node] Add build logs probe for TypeScript usage messages (#9261)
Follow-up to https://github.com/vercel/vercel/pull/9258, even though that issue seemed to only happen when linked to the monorepo locally. In any case, this test will ensure those log messages are intact for any other change around that part of the codebase in the future.
2023-01-19 21:39:27 +00:00
Ethan Arrowood
4838dc336a [static-build] run pnpm install --lockfile-only after injecting gatsby plugins (#9259)
Fixes a bug where after injecting plugins and modifying the users package.json, pnpm would fail normal install
2023-01-19 20:07:53 +00:00
Nathan Rajlich
eae45f4019 [node] Fix TypeScript built-in compiler log message check (#9258)
This check started breaking probably after the pnpm switch, so switch to a simpler solution that doesn't require comparing the paths.
2023-01-19 13:12:31 +00:00
Ethan Arrowood
02feb564a7 [static-build][fs-detectors] add gatsby builder plugin injection (#9252)
Modifies the `@vercel/static-build` injection logic in order to now inject both the analytics and builder gatsby plugins.
2023-01-19 03:34:47 +00:00
Nathan Rajlich
e174a06673 Publish Stable
- vercel@28.12.8
 - @vercel/gatsby-plugin-vercel-builder@0.1.1
 - @vercel/next@3.3.17
 - @vercel/remix@1.2.7
2023-01-18 15:19:12 -08:00
Nathan Rajlich
de034943af [gatsby-plugin-vercel-builder] Fix turbo cache outputs configuration (#9257)
The published version on npm was missing the compiled code because Turbo
was not configured to cache them properly.
2023-01-18 15:10:28 -08:00
JJ Kasper
b3862271a5 [next] Fix normalize route with middleware and basePath (#9255)
This ensures we properly match the index route when normalizing routes with `x-nextjs-data` for middleware. 

x-ref: [slack thread](https://vercel.slack.com/archives/C03S8ED1DKM/p1674034533265989)
2023-01-18 21:30:30 +00:00
Steven
aaceeef604 [tests] Add test for ./examples/remix (#9251)
- Related to #9249
2023-01-18 19:13:55 +00:00
Steven
ad107ecf79 [tests] Split more dev tests (#9230)
This PR attempts to balance the tests so they run concurrently and therefore faster.

I also sorted the tests so they are deterministic when splitting/chunking.
2023-01-18 17:35:45 +00:00
Steven
79ef5c3724 Publish Stable
- vercel@28.12.7
 - @vercel/client@12.3.2
 - @vercel/gatsby-plugin-vercel-builder@0.1.0
 - @vercel/next@3.3.16
 - @vercel/node-bridge@3.1.10
 - @vercel/node@2.8.14
 - @vercel/remix@1.2.6
2023-01-18 08:39:44 -05:00
Nathan Rajlich
02ff265074 [remix] Fix config file dynamic import (#9249)
Follow-up to https://github.com/vercel/vercel/pull/8793, which breaks dynamic import of the config file, causing some issues for remix users: https://github.com/orgs/vercel/discussions/1282

The underlying error is `MODULE_NOT_FOUND`.

`import()` should work with `file://` URIs, however, since it's using typescript, the `import` gets compiled to `require()`, which does not support `file://` protocol scheme.

Supersedes https://github.com/vercel/vercel/pull/9248.
2023-01-18 11:24:42 +00:00
Ethan Arrowood
ae89b8b8be [gatsby-plugin-vercel-builder] Implement @vercel/gatsby-plugin-vercel-builder (#9218)
<picture data-single-emoji=":gatsby:" title=":gatsby:"><img class="emoji" src="https://single-emoji.vercel.app/api/emoji/eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIn0..Dli3tTuity9MEBnK.YyaiT9ASg3XvFmlx5q0Ovkdbkto2fgJGjIJhsLcraR_hqYG0DAC6CcBMiaARcI_hF0502EnqhkrHQLeYfEoxfomLi9iKk4WBAe-oSfsENsG9oAwzYdH4LA.VMtHCMaOXNOqpB2xvph3Kg" alt=":gatsby:" width="20" height="auto" align="absmiddle"></picture> 

Implement the Build Output API v3 Gatsby plugin for use within `@vercel/static-build`.

Supersedes https://github.com/vercel/vercel/pull/8259.
2023-01-18 02:24:32 +00:00
Steven
4ccdcde463 Publish Stable
- @vercel/build-utils@5.9.0
 - vercel@28.12.6
 - @vercel/client@12.3.1
 - @vercel/fs-detectors@3.7.5
 - @vercel/go@2.2.30
 - @vercel/hydrogen@0.0.44
 - @vercel/next@3.3.15
 - @vercel/node@2.8.13
 - @vercel/python@3.1.40
 - @vercel/redwood@1.0.51
 - @vercel/remix@1.2.5
 - @vercel/ruby@1.3.56
 - @vercel/static-build@1.1.7
2023-01-17 19:25:26 -05:00
Nathan Rajlich
22d3ee160b [build-utils] Add includeDirectories option to glob() (#9245)
Instead of always including empty directories in `glob()`, make it an
opt-in behavior because technically it's a breaking change to include
them by default.
2023-01-17 19:21:40 -05:00
Sean Massa
6d97e1673e Publish Stable
- vercel@28.12.5
 - @vercel/client@12.3.0
 - @vercel/node-bridge@3.1.9
 - @vercel/node@2.8.12
2023-01-17 13:46:58 -06:00
Nathan Rajlich
522565f6e5 [node-bridge] Add missing lazy dependencies (#9231)
These were missing from the compiled ncc build of `helpers.ts`, and thus causing an error at runtime because the deps are not available within the Serverless Function.
2023-01-14 01:41:50 +00:00
Steven
07bf81ab10 [client] Add sliding window delay when polling deployment complete (#9222)
The previous delay of 1500ms was causing some users to hit the API rate limits. This doesn't normally happen with a single deployment, but it can happen with several concurrent deployments (for example a monorepo with many projects).

We don't need to be polling so often, so this PR changed the polling delay to the following:

- During 0s-15s: check every 1 second
- During 15s-60s: check every 5 seconds
- During 1m-5m: check every 15 seconds
- During 5m-10m: check every 30 seconds
2023-01-14 00:27:14 +00:00
Steven
35024a4e3a [tests] Split up dev tests to increase concurrency (#9228)
This will speed up CI because we can run more tests concurrently.

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-01-13 18:53:57 -05:00
Sean Massa
c1df9bca19 [tests] skip private packages (#9229) 2023-01-13 17:24:50 -06:00
Nathan Rajlich
4c1cdd1f0f [client] Send empty directory entries to POST create deployment (#9118)
Update `@vercel/client` to send empty directory entries to the `POST` create deployment endpoint. This makes it so that CLI deployments will have empty directories re-populated in the build-container when doing `vc deploy`.

Follow-up to #9103.
2023-01-13 22:24:31 +00:00
Sean Massa
b5cdc82a1c Publish Stable
- @vercel/build-utils@5.8.3
 - vercel@28.12.4
 - @vercel/client@12.2.31
 - @vercel/edge@0.2.6
 - @vercel/error-utils@1.0.8
 - @vercel/frameworks@1.2.4
 - @vercel/fs-detectors@3.7.4
 - @vercel/gatsby-plugin-vercel-analytics@1.0.6
 - @vercel/go@2.2.29
 - @vercel/hydrogen@0.0.43
 - @vercel/next@3.3.14
 - @vercel/node-bridge@3.1.8
 - @vercel/node@2.8.11
 - @vercel/python@3.1.39
 - @vercel/redwood@1.0.50
 - @vercel/remix@1.2.4
 - @vercel/routing-utils@2.1.8
 - @vercel/ruby@1.3.55
 - @vercel/static-build@1.1.6
 - @vercel/static-config@2.0.11
2023-01-13 15:45:03 -06:00
Nathan Rajlich
c7851404b3 [*] Remove "workspace:" (#9225) 2023-01-13 15:42:29 -06:00
Sean Massa
e54da8a2e5 Publish Stable
- @vercel/build-utils@5.8.2
 - vercel@28.12.3
 - @vercel/client@12.2.30
 - @vercel/edge@0.2.5
 - @vercel/error-utils@1.0.7
 - @vercel/frameworks@1.2.3
 - @vercel/fs-detectors@3.7.3
 - @vercel/gatsby-plugin-vercel-analytics@1.0.5
 - @vercel/go@2.2.28
 - @vercel/hydrogen@0.0.42
 - @vercel/next@3.3.13
 - @vercel/node-bridge@3.1.7
 - @vercel/node@2.8.10
 - @vercel/python@3.1.38
 - @vercel/redwood@1.0.49
 - @vercel/remix@1.2.3
 - @vercel/routing-utils@2.1.7
 - @vercel/ruby@1.3.54
 - @vercel/static-build@1.1.5
 - @vercel/static-config@2.0.10
2023-01-13 15:06:45 -06:00
Sean Massa
a066bedf95 add the lockfile before commit 2023-01-13 15:06:16 -06:00
Sean Massa
09b23e53ba update lockfile because lerna did not do its job 2023-01-13 15:05:29 -06:00
Sean Massa
b793a67588 Publish Stable
- @vercel/build-utils@5.8.1
 - vercel@28.12.2
 - @vercel/client@12.2.29
 - @vercel/edge@0.2.4
 - @vercel/error-utils@1.0.6
 - @vercel/frameworks@1.2.2
 - @vercel/fs-detectors@3.7.2
 - @vercel/gatsby-plugin-vercel-analytics@1.0.4
 - @vercel/go@2.2.27
 - @vercel/hydrogen@0.0.41
 - @vercel/next@3.3.12
 - @vercel/node-bridge@3.1.6
 - @vercel/node@2.8.9
 - @vercel/python@3.1.37
 - @vercel/redwood@1.0.48
 - @vercel/remix@1.2.2
 - @vercel/routing-utils@2.1.6
 - @vercel/ruby@1.3.53
 - @vercel/static-build@1.1.4
 - @vercel/static-config@2.0.9
2023-01-13 15:01:55 -06:00
Sean Massa
31dd354b3a remove unnecessary checkout 2023-01-13 15:00:52 -06:00
Sean Massa
529ff3b2d7 add "version" lifecycle hook for lerna to update lockfile before commit 2023-01-13 14:59:49 -06:00
Sean Massa
e71d5638ee Publish Stable
- @vercel/build-utils@5.8.0
 - vercel@28.12.1
 - @vercel/client@12.2.28
 - @vercel/edge@0.2.3
 - @vercel/error-utils@1.0.5
 - @vercel/frameworks@1.2.1
 - @vercel/fs-detectors@3.7.1
 - @vercel/gatsby-plugin-vercel-analytics@1.0.3
 - @vercel/go@2.2.26
 - @vercel/hydrogen@0.0.40
 - @vercel/next@3.3.11
 - @vercel/node-bridge@3.1.5
 - @vercel/node@2.8.8
 - @vercel/python@3.1.36
 - @vercel/redwood@1.0.47
 - @vercel/remix@1.2.1
 - @vercel/routing-utils@2.1.5
 - @vercel/ruby@1.3.52
 - @vercel/static-build@1.1.3
 - @vercel/static-config@2.0.8
2023-01-13 14:47:25 -06:00
Ethan Arrowood
8c16e765ee [tests] adjust root and api deps to use worskpace:* (#9223) 2023-01-13 14:29:23 -06:00
Ethan Arrowood
a008c9c7fe [build-utils] Support empty directory entries for glob() and download() (#9164)
Reopening #9103 since it was reverted.
2023-01-13 12:01:37 -08:00
420 changed files with 82131 additions and 7096 deletions

View File

@@ -43,5 +43,8 @@ packages/static-build/test/cache-fixtures
# redwood
packages/redwood/test/fixtures
# remix
packages/remix/test/fixtures
# gatsby-plugin-vercel-analytics
packages/gatsby-plugin-vercel-analytics

3
.github/CODEOWNERS vendored
View File

@@ -3,9 +3,6 @@
* @TooTallNate @EndangeredMassa @styfle @cb1kenobi @Ethan-Arrowood
/.github/workflows @TooTallNate @EndangeredMassa @styfle @cb1kenobi @Ethan-Arrowood @ijjk
/packages/cli/src/commands/domains @mglagola @anatrajkovska
/packages/cli/src/commands/certs @mglagola @anatrajkovska
/packages/cli/src/commands/env @TooTallNate @EndangeredMassa @styfle @cb1kenobi @Ethan-Arrowood
/packages/fs-detectors @TooTallNate @EndangeredMassa @styfle @cb1kenobi @Ethan-Arrowood @agadzik @chloetedder
/packages/node-bridge @TooTallNate @EndangeredMassa @styfle @cb1kenobi @Ethan-Arrowood @ijjk
/packages/next @TooTallNate @EndangeredMassa @styfle @cb1kenobi @Ethan-Arrowood @ijjk

27
.github/workflows/cron-update-turbo.yml vendored Normal file
View File

@@ -0,0 +1,27 @@
name: Cron Update Turbo
on:
# Run every week https://crontab.guru/every-week
schedule:
- cron: '0 0 * * 0'
jobs:
create-pull-request:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
# 0 means fetch all commits so we can commit and push in the script below
with:
fetch-depth: 0
- name: install pnpm@7.26.0
run: npm i -g pnpm@7.26.0
- name: Create Pull Request
uses: actions/github-script@v6
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
# See https://github.com/actions/github-script#run-a-separate-file-with-an-async-function
with:
script: |
const script = require('./utils/update-turbo.js')
await script({ github, context })

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

@@ -4,8 +4,7 @@
"version": "0.0.0",
"description": "API for the vercel/vercel repo",
"main": "index.js",
"scripts": {
},
"scripts": {},
"dependencies": {
"@sentry/node": "5.11.1",
"got": "10.2.1",
@@ -17,7 +16,7 @@
"devDependencies": {
"@types/node": "16.18.11",
"@types/node-fetch": "2.5.4",
"@vercel/node": "workspace:2.8.6",
"@vercel/node": "*",
"typescript": "4.3.4"
}
}

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
@@ -33,13 +33,13 @@ 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" }]
}
```

View File

@@ -2,7 +2,7 @@
This directory is a brief example of a [Gatsby](https://www.gatsbyjs.org/) app that can be deployed to Vercel with zero configuration.
> **Note:** We do not currently support some Gatsby v5 features, including API Routes and DSG. We are actively working on adding support for these features.
> **Note:** SSR, DSG, and API Routes [are now supported](https://vercel.com/changelog/improved-support-for-gatsby-sites). We do not currently support some Gatsby v5 features, including Partial Hydration and the Slice API.
## Deploy Your Own

View File

@@ -9,5 +9,8 @@
},
"dependencies": {
"gridsome": "0.7.23"
},
"engines": {
"node": "<17"
}
}

View File

@@ -8,18 +8,18 @@
"name": "nextjs",
"version": "0.1.0",
"dependencies": {
"@next/font": "13.1.2",
"eslint": "8.31.0",
"eslint-config-next": "13.1.2",
"next": "13.1.2",
"@next/font": "13.1.6",
"eslint": "8.32.0",
"eslint-config-next": "13.1.6",
"next": "13.1.6",
"react": "18.2.0",
"react-dom": "18.2.0"
}
},
"node_modules/@babel/runtime": {
"version": "7.20.7",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.7.tgz",
"integrity": "sha512-UF0tvkUtxwAgZ5W/KrkHf0Rn0fdnLDU9ScxBrEVNUprE/MzirjK4MJUX1/BVDv00Sv8cljtukVK1aky++X1SjQ==",
"version": "7.20.13",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.13.tgz",
"integrity": "sha512-gt3PKXs0DBoL9xCvOIIZ2NEqAGZqHjAnmVbfQtB620V0uReIQutpel14KcneZuer7UioY8ALKZ7iocavvzTNFA==",
"dependencies": {
"regenerator-runtime": "^0.13.11"
},
@@ -80,27 +80,27 @@
"integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA=="
},
"node_modules/@next/env": {
"version": "13.1.2",
"resolved": "https://registry.npmjs.org/@next/env/-/env-13.1.2.tgz",
"integrity": "sha512-PpT4UZIX66VMTqXt4HKEJ+/PwbS+tWmmhZlazaws1a+dbUA5pPdjntQ46Jvj616i3ZKN9doS9LHx3y50RLjAWg=="
"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.2",
"resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-13.1.2.tgz",
"integrity": "sha512-WGaNVvIYphdriesP6r7jq/8l7u38tzotnVQuxc1RYKLqYYApSsrebti3OCPoT3Gx0pw2smPIFHH98RzcsgW5GQ==",
"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.2",
"resolved": "https://registry.npmjs.org/@next/font/-/font-13.1.2.tgz",
"integrity": "sha512-NXGXGFGiOKEnvBIHq9cdFTKbHO2/4B3Zd9K27M7j1DioIQVar7oVRqZMYs0h3XMVEZLwjjkdAtqRPCzzd3RtXg=="
"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.2",
"resolved": "https://registry.npmjs.org/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-13.1.2.tgz",
"integrity": "sha512-7mRz1owoGsbfIcdOJA3kk7KEwPZ+OvVT1z9DkR/yru4QdVLF69h/1SHy0vlUNQMxDRllabhxCfkoZCB34GOGAg==",
"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.2",
"resolved": "https://registry.npmjs.org/@next/swc-android-arm64/-/swc-android-arm64-13.1.2.tgz",
"integrity": "sha512-mgjZ2eJSayovQm1LcE54BLSI4jjnnnLtq5GY5g+DdPuUiCT644gKtjZ/w2BQvuIecCqqBO+Ph9yzo/wUTq7NLg==",
"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.2",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.1.2.tgz",
"integrity": "sha512-RikoQqy109r2222UJlyGs4dZw2BibkfPqpeFdW5JEGv+L2PStlHID8DwyVYbmHfQ0VIBGvbf/NAUtFakAWlhwg==",
"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.2",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.1.2.tgz",
"integrity": "sha512-JbDZjaTvL8gyPC5TAH6OnD4jmXPkyUxRYPvu08ZmhT/XAFBb/Cso0BdXyDax/BPCG70mimP9d3hXNKNq+A0VtQ==",
"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.2",
"resolved": "https://registry.npmjs.org/@next/swc-freebsd-x64/-/swc-freebsd-x64-13.1.2.tgz",
"integrity": "sha512-ax4j8VrdFQ/xc3W7Om0u1vnDxVApQHKsChBbAMynCrnycZmpbqK4MZu4ZkycT+mx2eccCiqZROpbzDbEdPosEw==",
"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.2",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-13.1.2.tgz",
"integrity": "sha512-NcRHTesnCxnUvSJa637PQJffBBkmqi5XS/xVWGY7dI6nyJ+pC96Oj7kd+mcjnFUQI5lHKbg39qBWKtOzbezc4w==",
"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.2",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.1.2.tgz",
"integrity": "sha512-AxJdjocLtPrsBY4P2COSBIc3crT5bpjgGenNuINoensOlXhBkYM0aRDYZdydwXOhG+kN2ngUvfgitop9pa204w==",
"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.2",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.1.2.tgz",
"integrity": "sha512-JmNimDkcCRq7P5zpkdqeaSZ69qKDntEPtyIaMNWqy5M0WUJxGim0Fs6Qzxayiyvuuh9Guxks4woQ/j/ZvX/c8Q==",
"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.2",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.1.2.tgz",
"integrity": "sha512-TsLsjZwUlgmvI42neTuIoD6K9RlXCUzqPtvIClgXxVO0um0DiZwK+M+0zX/uVXhMVphfPY2c5YeR1zFSIONY4A==",
"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.2",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.1.2.tgz",
"integrity": "sha512-eSkyXgCXydEFPTkcncQOGepafedPte6JT/OofB9uvruucrrMVBagCASOuPxodWEMrlfEKSXVnExMKIlfmQMD7A==",
"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.2",
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.1.2.tgz",
"integrity": "sha512-DmXFaRTgt2KrV9dmRLifDJE+cYiutHVFIw5/C9BtnwXH39uf3YbPxeD98vNrtqqqZVVLXY/1ySaSIwzYnqeY9g==",
"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.2",
"resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.1.2.tgz",
"integrity": "sha512-3+nBkuFs/wT+lmRVQNH5SyDT7I4vUlNPntosEaEP63FuYQdPLaxz0GvcR66MdFSFh2fsvazpe4wciOwVS4FItQ==",
"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.2",
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.1.2.tgz",
"integrity": "sha512-avsyveEvcvH42PvKjR4Pb8JlLttuGURr2H3ZhS2b85pHOiZ7yjH3rMUoGnNzuLMApyxYaCvd4MedPrLhnNhkog==",
"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"
],
@@ -362,13 +362,13 @@
"integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ=="
},
"node_modules/@typescript-eslint/parser": {
"version": "5.48.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.48.1.tgz",
"integrity": "sha512-4yg+FJR/V1M9Xoq56SF9Iygqm+r5LMXvheo6DQ7/yUWynQ4YfCRnsKuRgqH4EQ5Ya76rVwlEpw4Xu+TgWQUcdA==",
"version": "5.49.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.49.0.tgz",
"integrity": "sha512-veDlZN9mUhGqU31Qiv2qEp+XrJj5fgZpJ8PW30sHU+j/8/e5ruAhLaVDAeznS7A7i4ucb/s8IozpDtt9NqCkZg==",
"dependencies": {
"@typescript-eslint/scope-manager": "5.48.1",
"@typescript-eslint/types": "5.48.1",
"@typescript-eslint/typescript-estree": "5.48.1",
"@typescript-eslint/scope-manager": "5.49.0",
"@typescript-eslint/types": "5.49.0",
"@typescript-eslint/typescript-estree": "5.49.0",
"debug": "^4.3.4"
},
"engines": {
@@ -388,12 +388,12 @@
}
},
"node_modules/@typescript-eslint/scope-manager": {
"version": "5.48.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.48.1.tgz",
"integrity": "sha512-S035ueRrbxRMKvSTv9vJKIWgr86BD8s3RqoRZmsSh/s8HhIs90g6UlK8ZabUSjUZQkhVxt7nmZ63VJ9dcZhtDQ==",
"version": "5.49.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.49.0.tgz",
"integrity": "sha512-clpROBOiMIzpbWNxCe1xDK14uPZh35u4QaZO1GddilEzoCLAEz4szb51rBpdgurs5k2YzPtJeTEN3qVbG+LRUQ==",
"dependencies": {
"@typescript-eslint/types": "5.48.1",
"@typescript-eslint/visitor-keys": "5.48.1"
"@typescript-eslint/types": "5.49.0",
"@typescript-eslint/visitor-keys": "5.49.0"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -404,9 +404,9 @@
}
},
"node_modules/@typescript-eslint/types": {
"version": "5.48.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.48.1.tgz",
"integrity": "sha512-xHyDLU6MSuEEdIlzrrAerCGS3T7AA/L8Hggd0RCYBi0w3JMvGYxlLlXHeg50JI9Tfg5MrtsfuNxbS/3zF1/ATg==",
"version": "5.49.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.49.0.tgz",
"integrity": "sha512-7If46kusG+sSnEpu0yOz2xFv5nRz158nzEXnJFCGVEHWnuzolXKwrH5Bsf9zsNlOQkyZuk0BZKKoJQI+1JPBBg==",
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
@@ -416,12 +416,12 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
"version": "5.48.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.48.1.tgz",
"integrity": "sha512-Hut+Osk5FYr+sgFh8J/FHjqX6HFcDzTlWLrFqGoK5kVUN3VBHF/QzZmAsIXCQ8T/W9nQNBTqalxi1P3LSqWnRA==",
"version": "5.49.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.49.0.tgz",
"integrity": "sha512-PBdx+V7deZT/3GjNYPVQv1Nc0U46dAHbIuOG8AZ3on3vuEKiPDwFE/lG1snN2eUB9IhF7EyF7K1hmTcLztNIsA==",
"dependencies": {
"@typescript-eslint/types": "5.48.1",
"@typescript-eslint/visitor-keys": "5.48.1",
"@typescript-eslint/types": "5.49.0",
"@typescript-eslint/visitor-keys": "5.49.0",
"debug": "^4.3.4",
"globby": "^11.1.0",
"is-glob": "^4.0.3",
@@ -442,11 +442,11 @@
}
},
"node_modules/@typescript-eslint/visitor-keys": {
"version": "5.48.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.48.1.tgz",
"integrity": "sha512-Ns0XBwmfuX7ZknznfXozgnydyR8F6ev/KEGePP4i74uL3ArsKbEhJ7raeKr1JSa997DBDwol/4a0Y+At82c9dA==",
"version": "5.49.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.49.0.tgz",
"integrity": "sha512-v9jBMjpNWyn8B6k/Mjt6VbUS4J1GvUlR4x3Y+ibnP1z7y7V4n0WRz+50DY6+Myj0UaXVSuUlHohO+eZ8IJEnkg==",
"dependencies": {
"@typescript-eslint/types": "5.48.1",
"@typescript-eslint/types": "5.49.0",
"eslint-visitor-keys": "^3.3.0"
},
"engines": {
@@ -458,9 +458,9 @@
}
},
"node_modules/acorn": {
"version": "8.8.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz",
"integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==",
"version": "8.8.2",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz",
"integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==",
"bin": {
"acorn": "bin/acorn"
},
@@ -615,9 +615,9 @@
}
},
"node_modules/axe-core": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.6.2.tgz",
"integrity": "sha512-b1WlTV8+XKLj9gZy2DZXgQiyDp9xkkoe2a6U6UbYccScq2wgH/YwCeI2/Jq2mgo0HzQxqJOjWZBLeA/mqsk5Mg==",
"version": "4.6.3",
"resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.6.3.tgz",
"integrity": "sha512-/BQzOX780JhsxDnPpH4ZiyrJAzcd8AfzFPkv+89veFSr1rcMjuq2JDCwypKaPeB6ljHp9KjXhPpjgCvQlWYuqg==",
"engines": {
"node": ">=4"
}
@@ -676,9 +676,9 @@
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001443",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001443.tgz",
"integrity": "sha512-jUo8svymO8+Mkj3qbUbVjR8zv8LUGpGkUM/jKvc9SO2BvjCI980dp9fQbf/dyLs6RascPzgR4nhAKFA4OHeSaA==",
"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",
@@ -906,18 +906,19 @@
}
},
"node_modules/es-get-iterator": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.2.tgz",
"integrity": "sha512-+DTO8GYwbMCwbywjimwZMHp8AuYXOS2JZFWoi2AlPOS3ebnII9w/NLpNZtA7A0YLaVDw+O7KFCeoIV7OPvM7hQ==",
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz",
"integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==",
"dependencies": {
"call-bind": "^1.0.2",
"get-intrinsic": "^1.1.0",
"has-symbols": "^1.0.1",
"is-arguments": "^1.1.0",
"get-intrinsic": "^1.1.3",
"has-symbols": "^1.0.3",
"is-arguments": "^1.1.1",
"is-map": "^2.0.2",
"is-set": "^2.0.2",
"is-string": "^1.0.5",
"isarray": "^2.0.5"
"is-string": "^1.0.7",
"isarray": "^2.0.5",
"stop-iteration-iterator": "^1.0.0"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -972,9 +973,9 @@
}
},
"node_modules/eslint": {
"version": "8.31.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.31.0.tgz",
"integrity": "sha512-0tQQEVdmPZ1UtUKXjX7EMm9BlgJ08G90IhWh0PKDCb3ZLsgAOHI8fYSIzYVZej92zsgq+ft0FGsxhJ3xo2tbuA==",
"version": "8.32.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.32.0.tgz",
"integrity": "sha512-nETVXpnthqKPFyuY2FNjz/bEd6nbosRgKbkgS/y1C7LJop96gYHWpiguLecMHQ2XCPxn77DS0P+68WzG6vkZSQ==",
"dependencies": {
"@eslint/eslintrc": "^1.4.1",
"@humanwhocodes/config-array": "^0.11.8",
@@ -1027,11 +1028,11 @@
}
},
"node_modules/eslint-config-next": {
"version": "13.1.2",
"resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-13.1.2.tgz",
"integrity": "sha512-zdRAQOr8v69ZwJRtBrGqAqm160ONqKxU/pV1FB1KlgfyqveGsLZmlQ7l31otwtw763901J7xdiTVkj2y3YxXZA==",
"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.2",
"@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",
@@ -1147,13 +1148,13 @@
}
},
"node_modules/eslint-plugin-import": {
"version": "2.27.4",
"resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.27.4.tgz",
"integrity": "sha512-Z1jVt1EGKia1X9CnBCkpAOhWy8FgQ7OmJ/IblEkT82yrFU/xJaxwujaTzLWqigewwynRQ9mmHfX9MtAfhxm0sA==",
"version": "2.27.5",
"resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz",
"integrity": "sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==",
"dependencies": {
"array-includes": "^3.1.6",
"array.prototype.flat": "^1.3.1",
"array.prototype.flatmap": "^1.3.0",
"array.prototype.flatmap": "^1.3.1",
"debug": "^3.2.7",
"doctrine": "^2.1.0",
"eslint-import-resolver-node": "^0.3.7",
@@ -1239,9 +1240,9 @@
}
},
"node_modules/eslint-plugin-react": {
"version": "7.32.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.32.0.tgz",
"integrity": "sha512-vSBi1+SrPiLZCGvxpiZIa28fMEUaMjXtCplrvxcIxGzmFiYdsXQDwInEjuv5/i/2CTTxbkS87tE8lsQ0Qxinbw==",
"version": "7.32.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.32.1.tgz",
"integrity": "sha512-vOjdgyd0ZHBXNsmvU+785xY8Bfe57EFbTYYk8XrROzWpr9QBvpjITvAXt9xqcE6+8cjR/g1+mfumPToxsl1www==",
"dependencies": {
"array-includes": "^3.1.6",
"array.prototype.flatmap": "^1.3.1",
@@ -1558,9 +1559,9 @@
}
},
"node_modules/get-intrinsic": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz",
"integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==",
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz",
"integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==",
"dependencies": {
"function-bind": "^1.1.1",
"has": "^1.0.3",
@@ -2138,9 +2139,9 @@
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
},
"node_modules/js-sdsl": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.2.0.tgz",
"integrity": "sha512-dyBIzQBDkCqCu+0upx25Y2jGdbTGxE9fshMsCdK0ViOongpV+n5tXRcZY9v7CaVQ79AGS9KA1KHtojxiM7aXSQ==",
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz",
"integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/js-sdsl"
@@ -2322,11 +2323,11 @@
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="
},
"node_modules/next": {
"version": "13.1.2",
"resolved": "https://registry.npmjs.org/next/-/next-13.1.2.tgz",
"integrity": "sha512-Rdnnb2YH///w78FEOR/IQ6TXga+qpth4OqFSem48ng1PYYKr6XBsIk1XVaRcIGM3o6iiHnun0nJvkJHDf+ICyQ==",
"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.2",
"@next/env": "13.1.6",
"@swc/helpers": "0.4.14",
"caniuse-lite": "^1.0.30001406",
"postcss": "8.4.14",
@@ -2339,19 +2340,19 @@
"node": ">=14.6.0"
},
"optionalDependencies": {
"@next/swc-android-arm-eabi": "13.1.2",
"@next/swc-android-arm64": "13.1.2",
"@next/swc-darwin-arm64": "13.1.2",
"@next/swc-darwin-x64": "13.1.2",
"@next/swc-freebsd-x64": "13.1.2",
"@next/swc-linux-arm-gnueabihf": "13.1.2",
"@next/swc-linux-arm64-gnu": "13.1.2",
"@next/swc-linux-arm64-musl": "13.1.2",
"@next/swc-linux-x64-gnu": "13.1.2",
"@next/swc-linux-x64-musl": "13.1.2",
"@next/swc-win32-arm64-msvc": "13.1.2",
"@next/swc-win32-ia32-msvc": "13.1.2",
"@next/swc-win32-x64-msvc": "13.1.2"
"@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",
@@ -2659,9 +2660,9 @@
}
},
"node_modules/punycode": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.2.0.tgz",
"integrity": "sha512-LN6QV1IJ9ZhxWTNdktaPClrNfp8xdSAYS0Zk2ddX7XsXZAxckMHPCBcHRo0cTcEIgYPRiGEkmji3Idkh2yFtYw==",
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
"integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==",
"engines": {
"node": ">=6"
}
@@ -2897,6 +2898,17 @@
"node": ">=0.10.0"
}
},
"node_modules/stop-iteration-iterator": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz",
"integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==",
"dependencies": {
"internal-slot": "^1.0.4"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/string.prototype.matchall": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz",
@@ -3075,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",
@@ -3262,9 +3274,9 @@
},
"dependencies": {
"@babel/runtime": {
"version": "7.20.7",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.7.tgz",
"integrity": "sha512-UF0tvkUtxwAgZ5W/KrkHf0Rn0fdnLDU9ScxBrEVNUprE/MzirjK4MJUX1/BVDv00Sv8cljtukVK1aky++X1SjQ==",
"version": "7.20.13",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.13.tgz",
"integrity": "sha512-gt3PKXs0DBoL9xCvOIIZ2NEqAGZqHjAnmVbfQtB620V0uReIQutpel14KcneZuer7UioY8ALKZ7iocavvzTNFA==",
"requires": {
"regenerator-runtime": "^0.13.11"
}
@@ -3306,99 +3318,99 @@
"integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA=="
},
"@next/env": {
"version": "13.1.2",
"resolved": "https://registry.npmjs.org/@next/env/-/env-13.1.2.tgz",
"integrity": "sha512-PpT4UZIX66VMTqXt4HKEJ+/PwbS+tWmmhZlazaws1a+dbUA5pPdjntQ46Jvj616i3ZKN9doS9LHx3y50RLjAWg=="
"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.2",
"resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-13.1.2.tgz",
"integrity": "sha512-WGaNVvIYphdriesP6r7jq/8l7u38tzotnVQuxc1RYKLqYYApSsrebti3OCPoT3Gx0pw2smPIFHH98RzcsgW5GQ==",
"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.2",
"resolved": "https://registry.npmjs.org/@next/font/-/font-13.1.2.tgz",
"integrity": "sha512-NXGXGFGiOKEnvBIHq9cdFTKbHO2/4B3Zd9K27M7j1DioIQVar7oVRqZMYs0h3XMVEZLwjjkdAtqRPCzzd3RtXg=="
"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.2",
"resolved": "https://registry.npmjs.org/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-13.1.2.tgz",
"integrity": "sha512-7mRz1owoGsbfIcdOJA3kk7KEwPZ+OvVT1z9DkR/yru4QdVLF69h/1SHy0vlUNQMxDRllabhxCfkoZCB34GOGAg==",
"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.2",
"resolved": "https://registry.npmjs.org/@next/swc-android-arm64/-/swc-android-arm64-13.1.2.tgz",
"integrity": "sha512-mgjZ2eJSayovQm1LcE54BLSI4jjnnnLtq5GY5g+DdPuUiCT644gKtjZ/w2BQvuIecCqqBO+Ph9yzo/wUTq7NLg==",
"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.2",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.1.2.tgz",
"integrity": "sha512-RikoQqy109r2222UJlyGs4dZw2BibkfPqpeFdW5JEGv+L2PStlHID8DwyVYbmHfQ0VIBGvbf/NAUtFakAWlhwg==",
"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.2",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.1.2.tgz",
"integrity": "sha512-JbDZjaTvL8gyPC5TAH6OnD4jmXPkyUxRYPvu08ZmhT/XAFBb/Cso0BdXyDax/BPCG70mimP9d3hXNKNq+A0VtQ==",
"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.2",
"resolved": "https://registry.npmjs.org/@next/swc-freebsd-x64/-/swc-freebsd-x64-13.1.2.tgz",
"integrity": "sha512-ax4j8VrdFQ/xc3W7Om0u1vnDxVApQHKsChBbAMynCrnycZmpbqK4MZu4ZkycT+mx2eccCiqZROpbzDbEdPosEw==",
"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.2",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-13.1.2.tgz",
"integrity": "sha512-NcRHTesnCxnUvSJa637PQJffBBkmqi5XS/xVWGY7dI6nyJ+pC96Oj7kd+mcjnFUQI5lHKbg39qBWKtOzbezc4w==",
"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.2",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.1.2.tgz",
"integrity": "sha512-AxJdjocLtPrsBY4P2COSBIc3crT5bpjgGenNuINoensOlXhBkYM0aRDYZdydwXOhG+kN2ngUvfgitop9pa204w==",
"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.2",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.1.2.tgz",
"integrity": "sha512-JmNimDkcCRq7P5zpkdqeaSZ69qKDntEPtyIaMNWqy5M0WUJxGim0Fs6Qzxayiyvuuh9Guxks4woQ/j/ZvX/c8Q==",
"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.2",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.1.2.tgz",
"integrity": "sha512-TsLsjZwUlgmvI42neTuIoD6K9RlXCUzqPtvIClgXxVO0um0DiZwK+M+0zX/uVXhMVphfPY2c5YeR1zFSIONY4A==",
"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.2",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.1.2.tgz",
"integrity": "sha512-eSkyXgCXydEFPTkcncQOGepafedPte6JT/OofB9uvruucrrMVBagCASOuPxodWEMrlfEKSXVnExMKIlfmQMD7A==",
"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.2",
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.1.2.tgz",
"integrity": "sha512-DmXFaRTgt2KrV9dmRLifDJE+cYiutHVFIw5/C9BtnwXH39uf3YbPxeD98vNrtqqqZVVLXY/1ySaSIwzYnqeY9g==",
"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.2",
"resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.1.2.tgz",
"integrity": "sha512-3+nBkuFs/wT+lmRVQNH5SyDT7I4vUlNPntosEaEP63FuYQdPLaxz0GvcR66MdFSFh2fsvazpe4wciOwVS4FItQ==",
"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.2",
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.1.2.tgz",
"integrity": "sha512-avsyveEvcvH42PvKjR4Pb8JlLttuGURr2H3ZhS2b85pHOiZ7yjH3rMUoGnNzuLMApyxYaCvd4MedPrLhnNhkog==",
"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": {
@@ -3456,37 +3468,37 @@
"integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ=="
},
"@typescript-eslint/parser": {
"version": "5.48.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.48.1.tgz",
"integrity": "sha512-4yg+FJR/V1M9Xoq56SF9Iygqm+r5LMXvheo6DQ7/yUWynQ4YfCRnsKuRgqH4EQ5Ya76rVwlEpw4Xu+TgWQUcdA==",
"version": "5.49.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.49.0.tgz",
"integrity": "sha512-veDlZN9mUhGqU31Qiv2qEp+XrJj5fgZpJ8PW30sHU+j/8/e5ruAhLaVDAeznS7A7i4ucb/s8IozpDtt9NqCkZg==",
"requires": {
"@typescript-eslint/scope-manager": "5.48.1",
"@typescript-eslint/types": "5.48.1",
"@typescript-eslint/typescript-estree": "5.48.1",
"@typescript-eslint/scope-manager": "5.49.0",
"@typescript-eslint/types": "5.49.0",
"@typescript-eslint/typescript-estree": "5.49.0",
"debug": "^4.3.4"
}
},
"@typescript-eslint/scope-manager": {
"version": "5.48.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.48.1.tgz",
"integrity": "sha512-S035ueRrbxRMKvSTv9vJKIWgr86BD8s3RqoRZmsSh/s8HhIs90g6UlK8ZabUSjUZQkhVxt7nmZ63VJ9dcZhtDQ==",
"version": "5.49.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.49.0.tgz",
"integrity": "sha512-clpROBOiMIzpbWNxCe1xDK14uPZh35u4QaZO1GddilEzoCLAEz4szb51rBpdgurs5k2YzPtJeTEN3qVbG+LRUQ==",
"requires": {
"@typescript-eslint/types": "5.48.1",
"@typescript-eslint/visitor-keys": "5.48.1"
"@typescript-eslint/types": "5.49.0",
"@typescript-eslint/visitor-keys": "5.49.0"
}
},
"@typescript-eslint/types": {
"version": "5.48.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.48.1.tgz",
"integrity": "sha512-xHyDLU6MSuEEdIlzrrAerCGS3T7AA/L8Hggd0RCYBi0w3JMvGYxlLlXHeg50JI9Tfg5MrtsfuNxbS/3zF1/ATg=="
"version": "5.49.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.49.0.tgz",
"integrity": "sha512-7If46kusG+sSnEpu0yOz2xFv5nRz158nzEXnJFCGVEHWnuzolXKwrH5Bsf9zsNlOQkyZuk0BZKKoJQI+1JPBBg=="
},
"@typescript-eslint/typescript-estree": {
"version": "5.48.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.48.1.tgz",
"integrity": "sha512-Hut+Osk5FYr+sgFh8J/FHjqX6HFcDzTlWLrFqGoK5kVUN3VBHF/QzZmAsIXCQ8T/W9nQNBTqalxi1P3LSqWnRA==",
"version": "5.49.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.49.0.tgz",
"integrity": "sha512-PBdx+V7deZT/3GjNYPVQv1Nc0U46dAHbIuOG8AZ3on3vuEKiPDwFE/lG1snN2eUB9IhF7EyF7K1hmTcLztNIsA==",
"requires": {
"@typescript-eslint/types": "5.48.1",
"@typescript-eslint/visitor-keys": "5.48.1",
"@typescript-eslint/types": "5.49.0",
"@typescript-eslint/visitor-keys": "5.49.0",
"debug": "^4.3.4",
"globby": "^11.1.0",
"is-glob": "^4.0.3",
@@ -3495,18 +3507,18 @@
}
},
"@typescript-eslint/visitor-keys": {
"version": "5.48.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.48.1.tgz",
"integrity": "sha512-Ns0XBwmfuX7ZknznfXozgnydyR8F6ev/KEGePP4i74uL3ArsKbEhJ7raeKr1JSa997DBDwol/4a0Y+At82c9dA==",
"version": "5.49.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.49.0.tgz",
"integrity": "sha512-v9jBMjpNWyn8B6k/Mjt6VbUS4J1GvUlR4x3Y+ibnP1z7y7V4n0WRz+50DY6+Myj0UaXVSuUlHohO+eZ8IJEnkg==",
"requires": {
"@typescript-eslint/types": "5.48.1",
"@typescript-eslint/types": "5.49.0",
"eslint-visitor-keys": "^3.3.0"
}
},
"acorn": {
"version": "8.8.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz",
"integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA=="
"version": "8.8.2",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz",
"integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw=="
},
"acorn-jsx": {
"version": "5.3.2",
@@ -3613,9 +3625,9 @@
"integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw=="
},
"axe-core": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.6.2.tgz",
"integrity": "sha512-b1WlTV8+XKLj9gZy2DZXgQiyDp9xkkoe2a6U6UbYccScq2wgH/YwCeI2/Jq2mgo0HzQxqJOjWZBLeA/mqsk5Mg=="
"version": "4.6.3",
"resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.6.3.tgz",
"integrity": "sha512-/BQzOX780JhsxDnPpH4ZiyrJAzcd8AfzFPkv+89veFSr1rcMjuq2JDCwypKaPeB6ljHp9KjXhPpjgCvQlWYuqg=="
},
"axobject-query": {
"version": "3.1.1",
@@ -3662,9 +3674,9 @@
"integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="
},
"caniuse-lite": {
"version": "1.0.30001443",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001443.tgz",
"integrity": "sha512-jUo8svymO8+Mkj3qbUbVjR8zv8LUGpGkUM/jKvc9SO2BvjCI980dp9fQbf/dyLs6RascPzgR4nhAKFA4OHeSaA=="
"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",
@@ -3835,18 +3847,19 @@
}
},
"es-get-iterator": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.2.tgz",
"integrity": "sha512-+DTO8GYwbMCwbywjimwZMHp8AuYXOS2JZFWoi2AlPOS3ebnII9w/NLpNZtA7A0YLaVDw+O7KFCeoIV7OPvM7hQ==",
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz",
"integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==",
"requires": {
"call-bind": "^1.0.2",
"get-intrinsic": "^1.1.0",
"has-symbols": "^1.0.1",
"is-arguments": "^1.1.0",
"get-intrinsic": "^1.1.3",
"has-symbols": "^1.0.3",
"is-arguments": "^1.1.1",
"is-map": "^2.0.2",
"is-set": "^2.0.2",
"is-string": "^1.0.5",
"isarray": "^2.0.5"
"is-string": "^1.0.7",
"isarray": "^2.0.5",
"stop-iteration-iterator": "^1.0.0"
}
},
"es-set-tostringtag": {
@@ -3883,9 +3896,9 @@
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="
},
"eslint": {
"version": "8.31.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.31.0.tgz",
"integrity": "sha512-0tQQEVdmPZ1UtUKXjX7EMm9BlgJ08G90IhWh0PKDCb3ZLsgAOHI8fYSIzYVZej92zsgq+ft0FGsxhJ3xo2tbuA==",
"version": "8.32.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.32.0.tgz",
"integrity": "sha512-nETVXpnthqKPFyuY2FNjz/bEd6nbosRgKbkgS/y1C7LJop96gYHWpiguLecMHQ2XCPxn77DS0P+68WzG6vkZSQ==",
"requires": {
"@eslint/eslintrc": "^1.4.1",
"@humanwhocodes/config-array": "^0.11.8",
@@ -3929,11 +3942,11 @@
}
},
"eslint-config-next": {
"version": "13.1.2",
"resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-13.1.2.tgz",
"integrity": "sha512-zdRAQOr8v69ZwJRtBrGqAqm160ONqKxU/pV1FB1KlgfyqveGsLZmlQ7l31otwtw763901J7xdiTVkj2y3YxXZA==",
"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.2",
"@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",
@@ -4016,13 +4029,13 @@
}
},
"eslint-plugin-import": {
"version": "2.27.4",
"resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.27.4.tgz",
"integrity": "sha512-Z1jVt1EGKia1X9CnBCkpAOhWy8FgQ7OmJ/IblEkT82yrFU/xJaxwujaTzLWqigewwynRQ9mmHfX9MtAfhxm0sA==",
"version": "2.27.5",
"resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz",
"integrity": "sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==",
"requires": {
"array-includes": "^3.1.6",
"array.prototype.flat": "^1.3.1",
"array.prototype.flatmap": "^1.3.0",
"array.prototype.flatmap": "^1.3.1",
"debug": "^3.2.7",
"doctrine": "^2.1.0",
"eslint-import-resolver-node": "^0.3.7",
@@ -4091,9 +4104,9 @@
}
},
"eslint-plugin-react": {
"version": "7.32.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.32.0.tgz",
"integrity": "sha512-vSBi1+SrPiLZCGvxpiZIa28fMEUaMjXtCplrvxcIxGzmFiYdsXQDwInEjuv5/i/2CTTxbkS87tE8lsQ0Qxinbw==",
"version": "7.32.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.32.1.tgz",
"integrity": "sha512-vOjdgyd0ZHBXNsmvU+785xY8Bfe57EFbTYYk8XrROzWpr9QBvpjITvAXt9xqcE6+8cjR/g1+mfumPToxsl1www==",
"requires": {
"array-includes": "^3.1.6",
"array.prototype.flatmap": "^1.3.1",
@@ -4327,9 +4340,9 @@
"integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ=="
},
"get-intrinsic": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz",
"integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==",
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz",
"integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==",
"requires": {
"function-bind": "^1.1.1",
"has": "^1.0.3",
@@ -4709,9 +4722,9 @@
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
},
"js-sdsl": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.2.0.tgz",
"integrity": "sha512-dyBIzQBDkCqCu+0upx25Y2jGdbTGxE9fshMsCdK0ViOongpV+n5tXRcZY9v7CaVQ79AGS9KA1KHtojxiM7aXSQ=="
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz",
"integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ=="
},
"js-tokens": {
"version": "4.0.0",
@@ -4847,24 +4860,24 @@
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="
},
"next": {
"version": "13.1.2",
"resolved": "https://registry.npmjs.org/next/-/next-13.1.2.tgz",
"integrity": "sha512-Rdnnb2YH///w78FEOR/IQ6TXga+qpth4OqFSem48ng1PYYKr6XBsIk1XVaRcIGM3o6iiHnun0nJvkJHDf+ICyQ==",
"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.2",
"@next/swc-android-arm-eabi": "13.1.2",
"@next/swc-android-arm64": "13.1.2",
"@next/swc-darwin-arm64": "13.1.2",
"@next/swc-darwin-x64": "13.1.2",
"@next/swc-freebsd-x64": "13.1.2",
"@next/swc-linux-arm-gnueabihf": "13.1.2",
"@next/swc-linux-arm64-gnu": "13.1.2",
"@next/swc-linux-arm64-musl": "13.1.2",
"@next/swc-linux-x64-gnu": "13.1.2",
"@next/swc-linux-x64-musl": "13.1.2",
"@next/swc-win32-arm64-msvc": "13.1.2",
"@next/swc-win32-ia32-msvc": "13.1.2",
"@next/swc-win32-x64-msvc": "13.1.2",
"@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",
@@ -5061,9 +5074,9 @@
}
},
"punycode": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.2.0.tgz",
"integrity": "sha512-LN6QV1IJ9ZhxWTNdktaPClrNfp8xdSAYS0Zk2ddX7XsXZAxckMHPCBcHRo0cTcEIgYPRiGEkmji3Idkh2yFtYw=="
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
"integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA=="
},
"queue-microtask": {
"version": "1.2.3",
@@ -5207,6 +5220,14 @@
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
"integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw=="
},
"stop-iteration-iterator": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz",
"integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==",
"requires": {
"internal-slot": "^1.0.4"
}
},
"string.prototype.matchall": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz",
@@ -5329,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.2",
"eslint": "8.31.0",
"eslint-config-next": "13.1.2",
"next": "13.1.2",
"@next/font": "13.1.6",
"eslint": "8.32.0",
"eslint-config-next": "13.1.6",
"next": "13.1.6",
"react": "18.2.0",
"react-dom": "18.2.0"
}

View File

@@ -7,6 +7,6 @@
"build": "parcel build"
},
"devDependencies": {
"parcel": "^2.0.0"
"parcel": "^2.8.3"
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -11,9 +11,8 @@
"@types/node": "14.18.33",
"@typescript-eslint/eslint-plugin": "5.21.0",
"@typescript-eslint/parser": "5.21.0",
"@vercel/build-utils": "workspace:5.7.5",
"@vercel/build-utils": "*",
"@vercel/ncc": "0.24.0",
"@vercel/next": "workspace:3.3.9",
"async-retry": "1.2.3",
"buffer-replace": "1.0.0",
"create-svelte": "2.0.1",
@@ -33,10 +32,11 @@
"source-map-support": "0.5.12",
"ts-eager": "2.0.2",
"ts-jest": "28.0.5",
"turbo": "1.7.0-canary.9"
"turbo": "1.7.0"
},
"scripts": {
"lerna": "lerna",
"version": "pnpm install && git add pnpm-lock.yaml",
"bootstrap": "lerna bootstrap",
"publish-stable": "echo 'Run `pnpm changelog` for instructions'",
"publish-canary": "git checkout main && git pull && lerna version prerelease --preid canary --message \"Publish Canary\" --exact",

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/build-utils",
"version": "5.7.6",
"version": "6.1.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

@@ -2,7 +2,7 @@ import path from 'path';
import debug from '../debug';
import FileFsRef from '../file-fs-ref';
import { File, Files, Meta } from '../types';
import { remove, mkdirp, readlink, symlink } from 'fs-extra';
import { remove, mkdirp, readlink, symlink, chmod } from 'fs-extra';
import streamToBuffer from './stream-to-buffer';
export interface DownloadedFiles {
@@ -51,6 +51,12 @@ export async function downloadFile(
): Promise<FileFsRef> {
const { mode } = file;
if (isDirectory(mode)) {
await mkdirp(fsPath);
await chmod(fsPath, mode);
return FileFsRef.fromFsPath({ mode, fsPath });
}
// If the source is a symlink, try to create it instead of copying the file.
// Note: creating symlinks on Windows requires admin priviliges or symlinks
// enabled in the group policy. We may want to improve the error message.

View File

@@ -6,7 +6,9 @@ import { lstat, Stats } from 'fs-extra';
import { normalizePath } from './normalize-path';
import FileFsRef from '../file-fs-ref';
export type GlobOptions = vanillaGlob_.IOptions;
export interface GlobOptions extends vanillaGlob_.IOptions {
includeDirectories?: boolean;
}
const vanillaGlob = promisify(vanillaGlob_);
@@ -15,12 +17,7 @@ export default async function glob(
opts: GlobOptions | string,
mountpoint?: string
): Promise<Record<string, FileFsRef>> {
let options: GlobOptions;
if (typeof opts === 'string') {
options = { cwd: opts };
} else {
options = opts;
}
const options = typeof opts === 'string' ? { cwd: opts } : opts;
if (!options.cwd) {
throw new Error(
@@ -34,13 +31,18 @@ export default async function glob(
const results: Record<string, FileFsRef> = {};
const statCache: Record<string, Stats> = {};
const symlinks: Record<string, boolean | undefined> = {};
options.symlinks = {};
options.statCache = statCache;
options.stat = true;
options.dot = true;
const files = await vanillaGlob(pattern, {
...options,
symlinks,
statCache,
stat: true,
dot: true,
});
const files = await vanillaGlob(pattern, options);
const dirs = new Set<string>();
const dirsWithEntries = new Set<string>();
for (const relativePath of files) {
const fsPath = normalizePath(path.join(options.cwd, relativePath));
@@ -49,12 +51,20 @@ export default async function glob(
stat,
`statCache does not contain value for ${relativePath} (resolved to ${fsPath})`
);
const isSymlink = options.symlinks![fsPath];
if (isSymlink || stat.isFile()) {
const isSymlink = symlinks[fsPath];
if (isSymlink || stat.isFile() || stat.isDirectory()) {
if (isSymlink) {
stat = await lstat(fsPath);
}
// Some bookkeeping to track which directories already have entries within
const dirname = path.dirname(relativePath);
dirsWithEntries.add(dirname);
if (stat.isDirectory()) {
dirs.add(relativePath);
continue;
}
let finalPath = relativePath;
if (mountpoint) {
finalPath = path.join(mountpoint, finalPath);
@@ -64,5 +74,22 @@ export default async function glob(
}
}
// Add empty directory entries
if (options.includeDirectories) {
for (const relativePath of dirs) {
if (dirsWithEntries.has(relativePath)) continue;
let finalPath = relativePath;
if (mountpoint) {
finalPath = path.join(mountpoint, finalPath);
}
const fsPath = normalizePath(path.join(options.cwd, relativePath));
const stat = statCache[fsPath];
results[finalPath] = new FileFsRef({ mode: stat.mode, fsPath });
}
}
return results;
}

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

@@ -111,56 +111,6 @@ export function spawnAsync(
});
}
export function execAsync(
command: string,
args: string[],
opts: SpawnOptionsExtended = {}
) {
return new Promise<{ stdout: string; stderr: string; code: number }>(
(resolve, reject) => {
opts.stdio = 'pipe';
const stdoutList: Buffer[] = [];
const stderrList: Buffer[] = [];
const child = spawn(command, args, opts);
child.stderr!.on('data', data => {
stderrList.push(data);
});
child.stdout!.on('data', data => {
stdoutList.push(data);
});
child.on('error', reject);
child.on('close', (code, signal) => {
if (code === 0 || opts.ignoreNon0Exit) {
return resolve({
// ignoring the next line due to do some Node.js type issue when we removed hoisting of dependencies in https://github.com/vercel/vercel/pull/9198
// should eventually be fixed when this method is remove by https://github.com/vercel/vercel/pull/9200 or we update to Node 16
// @ts-ignore
code,
stdout: Buffer.concat(stdoutList).toString(),
stderr: Buffer.concat(stderrList).toString(),
});
}
const cmd = opts.prettyCommand
? `Command "${opts.prettyCommand}"`
: 'Command';
return reject(
new NowBuildError({
code: `BUILD_UTILS_EXEC_${code || signal}`,
message: `${cmd} exited with ${code || signal}`,
})
);
});
}
);
}
export function spawnCommand(command: string, options: SpawnOptions = {}) {
const opts = { ...options, prettyCommand: command };
if (process.platform === 'win32') {
@@ -249,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> {
@@ -259,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

@@ -8,12 +8,12 @@ import download, {
downloadFile,
DownloadedFiles,
isSymbolicLink,
isDirectory,
} from './fs/download';
import getWriteableDirectory from './fs/get-writable-directory';
import glob, { GlobOptions } from './fs/glob';
import rename from './fs/rename';
import {
execAsync,
spawnAsync,
execCommand,
spawnCommand,
@@ -58,7 +58,6 @@ export {
glob,
GlobOptions,
rename,
execAsync,
spawnAsync,
getScriptName,
installDependencies,
@@ -82,6 +81,7 @@ export {
streamToBuffer,
debug,
isSymbolicLink,
isDirectory,
getLambdaOptionsFromFunction,
scanParentDirs,
getIgnoreFilter,

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;

View File

@@ -410,6 +410,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

@@ -1,5 +1,5 @@
{
"name": "a",
"name": "a21",
"version": "1.0.0",
"description": "",
"main": "index.js",

View File

@@ -1,5 +1,5 @@
{
"name": "b",
"name": "b21",
"version": "1.0.0",
"description": "",
"main": "index.js",

View File

@@ -1,5 +1,5 @@
{
"name": "21-npm-workspaces",
"private": true,
"version": "1.0.0",
"workspaces": [
"a",

View File

@@ -1,14 +1,8 @@
{
"name": "22-pnpm",
"version": "1.0.0",
"description": "",
"main": "index.js",
"private": true,
"scripts": {
"build": "mkdir -p public && (printf \"pnpm version: \" && pnpm -v) > public/index.txt"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"once": "^1.4.0"
}

View File

@@ -1,5 +1,5 @@
{
"name": "c",
"name": "build-c23",
"license": "MIT",
"version": "0.1.0"
}

View File

@@ -1,5 +1,5 @@
{
"name": "d",
"name": "build-d23",
"license": "MIT",
"version": "0.1.0",
"devDependencies": {

View File

@@ -1,6 +1,5 @@
{
"private": "true",
"name": "24-pnpm-hoisted",
"private": true,
"scripts": {
"build": "ls -Al node_modules && node index.js"
},

View File

@@ -1,5 +1,5 @@
{
"name": "a",
"name": "build-a25",
"version": "1.0.0",
"description": "",
"main": "index.js",

View File

@@ -1,5 +1,5 @@
{
"name": "b",
"name": "build-b25",
"version": "1.0.0",
"description": "",
"main": "index.js",

View File

@@ -1,6 +1,5 @@
{
"private": "true",
"name": "25-multiple-lock-files-yarn",
"private": true,
"workspaces": [
"a",
"b"

View File

@@ -1,5 +1,5 @@
{
"name": "a",
"name": "build-a26",
"version": "1.0.0",
"description": "",
"main": "index.js",

View File

@@ -1,5 +1,5 @@
{
"name": "b",
"name": "build-b26",
"version": "1.0.0",
"description": "",
"main": "index.js",

View File

@@ -1,6 +1,5 @@
{
"private": "true",
"name": "26-multiple-lock-files-pnpm",
"private": true,
"workspaces": [
"a",
"b"

View File

@@ -0,0 +1,195 @@
import path from 'path';
import fs, { readlink } from 'fs-extra';
import { strict as assert, strictEqual } from 'assert';
import { download, glob, FileBlob } from '../src';
describe('download()', () => {
let warningMessages: string[];
const originalConsoleWarn = console.warn;
beforeEach(() => {
warningMessages = [];
console.warn = m => {
warningMessages.push(m);
};
});
afterEach(() => {
console.warn = originalConsoleWarn;
});
it('should re-create FileFsRef symlinks properly', async () => {
if (process.platform === 'win32') {
console.log('Skipping test on windows');
return;
}
const files = await glob('**', path.join(__dirname, 'symlinks'));
assert.equal(Object.keys(files).length, 4);
const outDir = path.join(__dirname, 'symlinks-out');
await fs.remove(outDir);
const files2 = await download(files, outDir);
assert.equal(Object.keys(files2).length, 4);
const [linkStat, linkDirStat, aStat] = await Promise.all([
fs.lstat(path.join(outDir, 'link.txt')),
fs.lstat(path.join(outDir, 'link-dir')),
fs.lstat(path.join(outDir, 'a.txt')),
]);
assert(linkStat.isSymbolicLink());
assert(linkDirStat.isSymbolicLink());
assert(aStat.isFile());
const [linkDirContents, linkTextContents] = await Promise.all([
readlink(path.join(outDir, 'link-dir')),
readlink(path.join(outDir, 'link.txt')),
]);
strictEqual(linkDirContents, 'dir');
strictEqual(linkTextContents, './a.txt');
});
it('should re-create FileBlob symlinks properly', async () => {
if (process.platform === 'win32') {
console.log('Skipping test on windows');
return;
}
const files = {
'a.txt': new FileBlob({
mode: 33188,
contentType: undefined,
data: 'a text',
}),
'dir/b.txt': new FileBlob({
mode: 33188,
contentType: undefined,
data: 'b text',
}),
'link-dir': new FileBlob({
mode: 41453,
contentType: undefined,
data: 'dir',
}),
'link.txt': new FileBlob({
mode: 41453,
contentType: undefined,
data: 'a.txt',
}),
};
strictEqual(Object.keys(files).length, 4);
const outDir = path.join(__dirname, 'symlinks-out');
await fs.remove(outDir);
const files2 = await download(files, outDir);
strictEqual(Object.keys(files2).length, 4);
const [linkStat, linkDirStat, aStat, dirStat] = await Promise.all([
fs.lstat(path.join(outDir, 'link.txt')),
fs.lstat(path.join(outDir, 'link-dir')),
fs.lstat(path.join(outDir, 'a.txt')),
fs.lstat(path.join(outDir, 'dir')),
]);
assert(linkStat.isSymbolicLink());
assert(linkDirStat.isSymbolicLink());
assert(aStat.isFile());
assert(dirStat.isDirectory());
const [linkDirContents, linkTextContents] = await Promise.all([
readlink(path.join(outDir, 'link-dir')),
readlink(path.join(outDir, 'link.txt')),
]);
strictEqual(linkDirContents, 'dir');
strictEqual(linkTextContents, 'a.txt');
});
it('should download symlinks even with incorrect file', async () => {
if (process.platform === 'win32') {
console.log('Skipping test on windows');
return;
}
const files = {
'dir/file.txt': new FileBlob({
mode: 33188,
contentType: undefined,
data: 'file text',
}),
linkdir: new FileBlob({
mode: 41453,
contentType: undefined,
data: 'dir',
}),
'linkdir/file.txt': new FileBlob({
mode: 33188,
contentType: undefined,
data: 'this file should be discarded',
}),
};
const outDir = path.join(__dirname, 'symlinks-out');
await fs.remove(outDir);
await fs.mkdirp(outDir);
await download(files, outDir);
const [dir, file, linkdir] = await Promise.all([
fs.lstat(path.join(outDir, 'dir')),
fs.lstat(path.join(outDir, 'dir/file.txt')),
fs.lstat(path.join(outDir, 'linkdir')),
]);
expect(dir.isFile()).toBe(false);
expect(dir.isSymbolicLink()).toBe(false);
expect(file.isFile()).toBe(true);
expect(file.isSymbolicLink()).toBe(false);
expect(linkdir.isSymbolicLink()).toBe(true);
expect(warningMessages).toEqual([
'Warning: file "linkdir/file.txt" is within a symlinked directory "linkdir" and will be ignored',
]);
});
it('should create empty directory entries', async () => {
const outDir = path.join(__dirname, 'symlinks-out');
await fs.remove(outDir);
const files = {
'empty-dir': new FileBlob({
mode: 16877, // drwxr-xr-x
contentType: undefined,
data: '',
}),
dir: new FileBlob({
mode: 16877,
contentType: undefined,
data: '',
}),
'dir/subdir': new FileBlob({
mode: 16877,
contentType: undefined,
data: '',
}),
'another/subdir': new FileBlob({
mode: 16895, // drwxrwxrwx
contentType: undefined,
data: '',
}),
};
await download(files, outDir);
for (const [p, f] of Object.entries(files)) {
const stat = await fs.lstat(path.join(outDir, p));
expect(stat.isDirectory()).toEqual(true);
if (process.platform !== 'win32') {
// Don't test Windows since it doesn't support the same permissions
expect(stat.mode).toEqual(f.mode);
}
}
});
});

View File

@@ -1,29 +0,0 @@
import { execAsync, NowBuildError } from '../src';
it('should execute a command', async () => {
const { code, stdout, stderr } = await execAsync('echo', ['hello']);
expect(code).toBe(0);
expect(stdout).toContain('hello');
expect(stderr).toBe('');
});
it('should throw if the command exits with non-0 code', async () => {
await expect(execAsync('find', ['unknown-file'])).rejects.toBeInstanceOf(
NowBuildError
);
});
it('should return if the command exits with non-0 code and ignoreNon0Exit=true', async () => {
const { code, stdout, stderr } = await execAsync('find', ['unknown-file'], {
ignoreNon0Exit: true,
});
expect(code).toBe(process.platform === 'win32' ? 2 : 1);
expect(stdout).toBe('');
expect(stderr).toContain(
process.platform === 'win32'
? 'Parameter format not correct'
: 'No such file or directory'
);
});

View File

@@ -0,0 +1,65 @@
import fs from 'fs-extra';
import { join } from 'path';
import { tmpdir } from 'os';
import { glob, isDirectory } from '../src';
describe('glob()', () => {
it('should not return entries for empty directories by default', async () => {
const dir = await fs.mkdtemp(join(tmpdir(), 'build-utils-test'));
try {
await Promise.all([
fs.writeFile(join(dir, 'root.txt'), 'file at the root'),
fs.mkdirp(join(dir, 'empty-dir')),
fs
.mkdirp(join(dir, 'dir-with-file'))
.then(() =>
fs.writeFile(join(dir, 'dir-with-file/data.json'), '{"a":"b"}')
),
fs.mkdirp(join(dir, 'another/subdir')),
]);
const files = await glob('**', dir);
const fileNames = Object.keys(files).sort();
expect(fileNames).toHaveLength(2);
expect(fileNames).toEqual(['dir-with-file/data.json', 'root.txt']);
expect(isDirectory(files['dir-with-file/data.json'].mode)).toEqual(false);
expect(isDirectory(files['root.txt'].mode)).toEqual(false);
expect(files['dir-with-file']).toBeUndefined();
expect(files['another/subdir']).toBeUndefined();
expect(files['empty-dir']).toBeUndefined();
} finally {
await fs.remove(dir);
}
});
it('should return entries for empty directories with `includeDirectories: true`', async () => {
const dir = await fs.mkdtemp(join(tmpdir(), 'build-utils-test'));
try {
await Promise.all([
fs.writeFile(join(dir, 'root.txt'), 'file at the root'),
fs.mkdirp(join(dir, 'empty-dir')),
fs
.mkdirp(join(dir, 'dir-with-file'))
.then(() =>
fs.writeFile(join(dir, 'dir-with-file/data.json'), '{"a":"b"}')
),
fs.mkdirp(join(dir, 'another/subdir')),
]);
const files = await glob('**', { cwd: dir, includeDirectories: true });
const fileNames = Object.keys(files).sort();
expect(fileNames).toHaveLength(4);
expect(fileNames).toEqual([
'another/subdir',
'dir-with-file/data.json',
'empty-dir',
'root.txt',
]);
expect(isDirectory(files['another/subdir'].mode)).toEqual(true);
expect(isDirectory(files['empty-dir'].mode)).toEqual(true);
expect(isDirectory(files['dir-with-file/data.json'].mode)).toEqual(false);
expect(isDirectory(files['root.txt'].mode)).toEqual(false);
expect(files['dir-with-file']).toBeUndefined();
} finally {
await fs.remove(dir);
}
});
});

View File

@@ -1,20 +1,20 @@
import ms from 'ms';
import path from 'path';
import fs, { readlink } from 'fs-extra';
import { strict as assert, strictEqual } from 'assert';
import fs from 'fs-extra';
import { strict as assert } from 'assert';
import { getSupportedNodeVersion } from '../src/fs/node-version';
import download from '../src/fs/download';
import {
glob,
FileBlob,
getNodeVersion,
getLatestNodeVersion,
getDiscontinuedNodeVersions,
rename,
runNpmInstall,
runPackageJsonScript,
scanParentDirs,
FileBlob,
Prerender,
} from '../src';
import type { Files } from '../src';
jest.setTimeout(10 * 1000);
@@ -49,143 +49,6 @@ afterEach(() => {
console.warn = originalConsoleWarn;
});
it('should re-create FileFsRef symlinks properly', async () => {
if (process.platform === 'win32') {
console.log('Skipping test on windows');
return;
}
const files = await glob('**', path.join(__dirname, 'symlinks'));
assert.equal(Object.keys(files).length, 4);
const outDir = path.join(__dirname, 'symlinks-out');
await fs.remove(outDir);
const files2 = await download(files, outDir);
assert.equal(Object.keys(files2).length, 4);
const [linkStat, linkDirStat, aStat] = await Promise.all([
fs.lstat(path.join(outDir, 'link.txt')),
fs.lstat(path.join(outDir, 'link-dir')),
fs.lstat(path.join(outDir, 'a.txt')),
]);
assert(linkStat.isSymbolicLink());
assert(linkDirStat.isSymbolicLink());
assert(aStat.isFile());
const [linkDirContents, linkTextContents] = await Promise.all([
readlink(path.join(outDir, 'link-dir')),
readlink(path.join(outDir, 'link.txt')),
]);
strictEqual(linkDirContents, 'dir');
strictEqual(linkTextContents, './a.txt');
});
it('should re-create FileBlob symlinks properly', async () => {
if (process.platform === 'win32') {
console.log('Skipping test on windows');
return;
}
const files = {
'a.txt': new FileBlob({
mode: 33188,
contentType: undefined,
data: 'a text',
}),
'dir/b.txt': new FileBlob({
mode: 33188,
contentType: undefined,
data: 'b text',
}),
'link-dir': new FileBlob({
mode: 41453,
contentType: undefined,
data: 'dir',
}),
'link.txt': new FileBlob({
mode: 41453,
contentType: undefined,
data: 'a.txt',
}),
};
strictEqual(Object.keys(files).length, 4);
const outDir = path.join(__dirname, 'symlinks-out');
await fs.remove(outDir);
const files2 = await download(files, outDir);
strictEqual(Object.keys(files2).length, 4);
const [linkStat, linkDirStat, aStat, dirStat] = await Promise.all([
fs.lstat(path.join(outDir, 'link.txt')),
fs.lstat(path.join(outDir, 'link-dir')),
fs.lstat(path.join(outDir, 'a.txt')),
fs.lstat(path.join(outDir, 'dir')),
]);
assert(linkStat.isSymbolicLink());
assert(linkDirStat.isSymbolicLink());
assert(aStat.isFile());
assert(dirStat.isDirectory());
const [linkDirContents, linkTextContents] = await Promise.all([
readlink(path.join(outDir, 'link-dir')),
readlink(path.join(outDir, 'link.txt')),
]);
strictEqual(linkDirContents, 'dir');
strictEqual(linkTextContents, 'a.txt');
});
it('should download symlinks even with incorrect file', async () => {
if (process.platform === 'win32') {
console.log('Skipping test on windows');
return;
}
const files = {
'dir/file.txt': new FileBlob({
mode: 33188,
contentType: undefined,
data: 'file text',
}),
linkdir: new FileBlob({
mode: 41453,
contentType: undefined,
data: 'dir',
}),
'linkdir/file.txt': new FileBlob({
mode: 33188,
contentType: undefined,
data: 'this file should be discarded',
}),
};
const outDir = path.join(__dirname, 'symlinks-out');
await fs.remove(outDir);
await fs.mkdirp(outDir);
await download(files, outDir);
const [dir, file, linkdir] = await Promise.all([
fs.lstat(path.join(outDir, 'dir')),
fs.lstat(path.join(outDir, 'dir/file.txt')),
fs.lstat(path.join(outDir, 'linkdir')),
]);
expect(dir.isFile()).toBe(false);
expect(dir.isSymbolicLink()).toBe(false);
expect(file.isFile()).toBe(true);
expect(file.isSymbolicLink()).toBe(false);
expect(linkdir.isSymbolicLink()).toBe(true);
expect(warningMessages).toEqual([
'Warning: file "linkdir/file.txt" is within a symlinked directory "linkdir" and will be ignored',
]);
});
it('should only match supported node versions, otherwise throw an error', async () => {
expect(await getSupportedNodeVersion('14.x', false)).toHaveProperty(
'major',
@@ -275,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(
@@ -591,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.12.0",
"version": "28.15.0",
"preferGlobal": true,
"license": "Apache-2.0",
"description": "The command-line interface for Vercel",
@@ -41,16 +41,16 @@
"node": ">= 14"
},
"dependencies": {
"@vercel/build-utils": "workspace:5.7.6",
"@vercel/go": "workspace:2.2.25",
"@vercel/hydrogen": "workspace:0.0.39",
"@vercel/next": "workspace:3.3.10",
"@vercel/node": "workspace:2.8.7",
"@vercel/python": "workspace:3.1.35",
"@vercel/redwood": "workspace:1.0.46",
"@vercel/remix": "workspace:1.2.0",
"@vercel/ruby": "workspace:1.3.51",
"@vercel/static-build": "workspace:1.1.2"
"@vercel/build-utils": "6.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"
},
"devDependencies": {
"@alex_neo/jest-expect-message": "1.0.5",
@@ -93,13 +93,13 @@
"@types/which": "1.3.2",
"@types/write-json-file": "2.2.1",
"@types/yauzl-promise": "2.1.0",
"@vercel/client": "workspace:12.2.27",
"@vercel/error-utils": "workspace:1.0.4",
"@vercel/frameworks": "workspace:1.2.0",
"@vercel/fs-detectors": "workspace:3.7.0",
"@vercel/client": "12.3.5",
"@vercel/error-utils": "1.0.8",
"@vercel/frameworks": "1.3.0",
"@vercel/fs-detectors": "3.7.8",
"@vercel/fun": "1.0.4",
"@vercel/ncc": "0.24.0",
"@vercel/routing-utils": "workspace:2.1.4",
"@vercel/routing-utils": "2.1.8",
"@zeit/source-map-support": "0.6.2",
"ajv": "6.12.2",
"alpha-sort": "2.0.1",
@@ -171,7 +171,7 @@
"tmp-promise": "1.0.3",
"tree-kill": "1.2.2",
"ts-node": "10.9.1",
"typescript": "4.7.4",
"typescript": "4.9.4",
"universal-analytics": "0.4.20",
"utility-types": "2.1.0",
"write-json-file": "2.2.0",

View File

@@ -51,7 +51,7 @@ export default async function ls(
...paginationOptions
);
output.log(`aliases found under ${chalk.bold(contextName)} ${lsStamp()}`);
output.log(printAliasTable(aliases));
client.stdout.write(printAliasTable(aliases));
if (pagination && pagination.count === 20) {
const flags = getCommandFlags(opts, ['_', '--next']);

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

@@ -55,7 +55,7 @@ async function ls(
);
if (certs.length > 0) {
output.log(formatCertsTable(certs));
client.stdout.write(formatCertsTable(certs));
}
if (pagination && pagination.count === 20) {

View File

@@ -70,7 +70,7 @@ export default async function ls(
records.length > 0 ? 'Records' : 'No records'
} found under ${chalk.bold(contextName)} ${chalk.gray(lsStamp())}`
);
output.log(getDNSRecordsTable([{ domainName, records }]));
client.stdout.write(getDNSRecordsTable([{ domainName, records }]));
if (pagination && pagination.count === 20) {
const flags = getCommandFlags(opts, ['_', '--next']);

View File

@@ -5,18 +5,14 @@ import { satisfies } from 'semver';
import { dirname, join } from 'path';
import { mkdirp, outputJSON, readJSON, symlink } from 'fs-extra';
import { isStaticRuntime } from '@vercel/fs-detectors';
import {
BuilderV2,
BuilderV3,
PackageJson,
spawnAsync,
} from '@vercel/build-utils';
import { BuilderV2, BuilderV3, PackageJson } from '@vercel/build-utils';
import execa from 'execa';
import * as staticBuilder from './static-builder';
import { VERCEL_DIR } from '../projects/link';
import { Output } from '../output';
import readJSONFile from '../read-json-file';
import { CantParseJSONFile } from '../errors-ts';
import { errorToString, isErrnoException, isError } from '@vercel/error-utils';
import { isErrnoException, isError } from '@vercel/error-utils';
import cmd from '../output/cmd';
import code from '../output/code';
@@ -213,32 +209,44 @@ async function installBuilders(
).join(', ')}`
);
try {
await spawnAsync(
const { stderr } = await execa(
'npm',
['install', '@vercel/build-utils', ...buildersToAdd],
{
cwd: buildersDir,
stdio: 'pipe',
reject: true,
}
);
stderr
.split('/\r?\n/')
.filter(line => line.includes('npm WARN deprecated'))
.forEach(line => {
output.warn(line);
});
} catch (err: unknown) {
if (isError(err)) {
(err as any).link =
'https://vercel.link/builder-dependencies-install-failed';
if (isErrnoException(err) && err.code === 'ENOENT') {
const execaMessage = err.message;
let message =
err && 'stderr' in err && typeof err.stderr === 'string'
? err.stderr
: execaMessage;
if (execaMessage.startsWith('Command failed with ENOENT')) {
// `npm` is not installed
err.message = `Please install ${cmd('npm')} before continuing`;
message = `Please install ${cmd('npm')} before continuing`;
} else {
const message = errorToString(err);
const notFound = /GET (.*) - Not found/.exec(message);
if (notFound) {
const url = new URL(notFound[1]);
const packageName = decodeURIComponent(url.pathname.slice(1));
err.message = `The package ${code(
message = `The package ${code(
packageName
)} is not published on the npm registry`;
}
}
err.message = message;
(err as any).link =
'https://vercel.link/builder-dependencies-install-failed';
}
throw err;
}

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

@@ -28,9 +28,10 @@ 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 { VercelConfig } from '@vercel/client';
import { fileNameSymbol, VercelConfig } from '@vercel/client';
const { normalize } = posix;
export const OUTPUT_DIR = join(VERCEL_DIR, 'output');
@@ -56,6 +57,7 @@ export async function writeBuildResult(
return writeBuildResultV2(
outputDir,
buildResult as BuildResultV2,
build,
vercelConfig
);
} else if (version === 3) {
@@ -107,6 +109,7 @@ function stripDuplicateSlashes(path: string): string {
async function writeBuildResultV2(
outputDir: string,
buildResult: BuildResultV2,
build: Builder,
vercelConfig: VercelConfig | null
) {
if ('buildOutputPath' in buildResult) {
@@ -114,6 +117,18 @@ async function writeBuildResultV2(
return;
}
// Some very old `@now` scoped Builders return `output` at the top-level.
// These Builders are no longer supported.
if (!buildResult.output) {
const configFile = vercelConfig?.[fileNameSymbol];
const updateMessage = build.use.startsWith('@now/')
? ` Please update from "@now" to "@vercel" in your \`${configFile}\` file.`
: '';
throw new Error(
`The build result from "${build.use}" is missing the "output" property.${updateMessage}`
);
}
const lambdas = new Map<Lambda, string>();
const overrides: Record<string, PathOverride> = {};
for (const [path, output] of Object.entries(buildResult.output)) {
@@ -412,7 +427,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,16 +1,5 @@
import { join } from 'path';
import ms from 'ms';
import fs, { mkdirp } from 'fs-extra';
const {
exec,
fetch,
fixture,
sleep,
testFixture,
testFixtureStdio,
validateResponseHeaders,
} = require('./utils.js');
import { isIP } from 'net';
const { exec, fixture, testFixture, testFixtureStdio } = require('./utils.js');
test('[vercel dev] validate redirects', async () => {
const directory = fixture('invalid-redirects');
@@ -124,260 +113,112 @@ test(
);
test(
'[vercel dev] test cleanUrls serve correct content',
testFixtureStdio('test-clean-urls', async (testPath: any) => {
await testPath(200, '/', 'Index Page');
await testPath(200, '/about', 'About Page');
await testPath(200, '/sub', 'Sub Index Page');
await testPath(200, '/sub/another', 'Sub Another Page');
await testPath(200, '/style.css', 'body { color: green }');
await testPath(308, '/index.html', 'Redirecting to / (308)', {
Location: '/',
});
await testPath(308, '/about.html', 'Redirecting to /about (308)', {
Location: '/about',
});
await testPath(308, '/sub/index.html', 'Redirecting to /sub (308)', {
Location: '/sub',
'[vercel dev] Use `@vercel/python` with Flask requirements.txt',
testFixtureStdio('python-flask', async (testPath: any) => {
const name = 'Alice';
const year = new Date().getFullYear();
await testPath(200, `/api/user?name=${name}`, new RegExp(`Hello ${name}`));
await testPath(200, `/api/date`, new RegExp(`Current date is ${year}`));
await testPath(200, `/api/date.py`, new RegExp(`Current date is ${year}`));
await testPath(200, `/api/headers`, (body: any, res: any) => {
// @ts-ignore
const { host } = new URL(res.url);
expect(body).toBe(host);
});
})
);
test(
'[vercel dev] Use custom runtime from the "functions" property',
testFixtureStdio('custom-runtime', async (testPath: any) => {
await testPath(200, `/api/user`, /Hello, from Bash!/m);
await testPath(200, `/api/user.sh`, /Hello, from Bash!/m);
})
);
test(
'[vercel dev] Should work with nested `tsconfig.json` files',
testFixtureStdio('nested-tsconfig', async (testPath: any) => {
await testPath(200, `/`, /Nested tsconfig.json test page/);
await testPath(200, `/api`, 'Nested `tsconfig.json` API endpoint');
})
);
test(
'[vercel dev] Should force `tsc` option "module: commonjs" for `startDevServer()`',
testFixtureStdio('force-module-commonjs', async (testPath: any) => {
await testPath(200, `/`, /Force &quot;module: commonjs&quot; test page/);
await testPath(
308,
'/sub/another.html',
'Redirecting to /sub/another (308)',
{ Location: '/sub/another' }
200,
`/api`,
'Force "module: commonjs" JavaScript with ES Modules API endpoint'
);
await testPath(
200,
`/api/ts`,
'Force "module: commonjs" TypeScript API endpoint'
);
})
);
test(
'[vercel dev] test cleanUrls serve correct content when using `outputDirectory`',
testFixtureStdio(
'test-clean-urls-with-output-directory',
async (testPath: any) => {
await testPath(200, '/', 'Index Page');
await testPath(200, '/about', 'About Page');
await testPath(200, '/sub', 'Sub Index Page');
await testPath(200, '/sub/another', 'Sub Another Page');
await testPath(200, '/style.css', 'body { color: green }');
await testPath(308, '/index.html', 'Redirecting to / (308)', {
Location: '/',
});
await testPath(308, '/about.html', 'Redirecting to /about (308)', {
Location: '/about',
});
await testPath(308, '/sub/index.html', 'Redirecting to /sub (308)', {
Location: '/sub',
});
await testPath(
308,
'/sub/another.html',
'Redirecting to /sub/another (308)',
{ Location: '/sub/another' }
);
}
)
);
test(
'[vercel dev] should serve custom 404 when `cleanUrls: true`',
testFixtureStdio('test-clean-urls-custom-404', async (testPath: any) => {
await testPath(200, '/', 'This is the home page');
await testPath(200, '/about', 'The about page');
await testPath(200, '/contact/me', 'Contact Me Subdirectory');
await testPath(404, '/nothing', 'Custom 404 Page');
await testPath(404, '/nothing/', 'Custom 404 Page');
'[vercel dev] should prioritize index.html over other file named index.*',
testFixtureStdio('index-html-priority', async (testPath: any) => {
await testPath(200, '/', 'This is index.html');
await testPath(200, '/index.css', 'This is index.css');
})
);
test(
'[vercel dev] test cleanUrls and trailingSlash serve correct content',
testFixtureStdio('test-clean-urls-trailing-slash', async (testPath: any) => {
await testPath(200, '/', 'Index Page');
await testPath(200, '/about/', 'About Page');
await testPath(200, '/sub/', 'Sub Index Page');
await testPath(200, '/sub/another/', 'Sub Another Page');
await testPath(200, '/style.css', 'body { color: green }');
//TODO: fix this test so that location is `/` instead of `//`
//await testPath(308, '/index.html', 'Redirecting to / (308)', { Location: '/' });
await testPath(308, '/about.html', 'Redirecting to /about/ (308)', {
Location: '/about/',
});
await testPath(308, '/sub/index.html', 'Redirecting to /sub/ (308)', {
Location: '/sub/',
});
'[vercel dev] Should support `*.go` API serverless functions',
testFixtureStdio('go', async (testPath: any) => {
await testPath(200, `/api`, 'This is the index page');
await testPath(200, `/api/index`, 'This is the index page');
await testPath(200, `/api/index.go`, 'This is the index page');
await testPath(200, `/api/another`, 'This is another page');
await testPath(200, '/api/another.go', 'This is another page');
await testPath(200, `/api/foo`, 'Req Path: /api/foo');
await testPath(200, `/api/bar`, 'Req Path: /api/bar');
})
);
test(
'[vercel dev] Should set the `ts-node` "target" to match Node.js version',
testFixtureStdio('node-ts-node-target', async (testPath: any) => {
await testPath(200, `/api/subclass`, '{"ok":true}');
await testPath(
308,
'/sub/another.html',
'Redirecting to /sub/another/ (308)',
{
Location: '/sub/another/',
}
200,
`/api/array`,
'{"months":[1,2,3,4,5,6,7,8,9,10,11,12]}'
);
})
);
test(
'[vercel dev] test cors headers work with OPTIONS',
testFixtureStdio('test-cors-routes', async (testPath: any) => {
const headers = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers':
'Content-Type, Authorization, Accept, Content-Length, Origin, User-Agent',
'Access-Control-Allow-Methods':
'GET, POST, OPTIONS, HEAD, PATCH, PUT, DELETE',
};
await testPath(200, '/', 'status api', headers, { method: 'GET' });
await testPath(200, '/', 'status api', headers, { method: 'POST' });
await testPath(200, '/api/status.js', 'status api', headers, {
method: 'GET',
});
await testPath(200, '/api/status.js', 'status api', headers, {
method: 'POST',
});
await testPath(204, '/', '', headers, { method: 'OPTIONS' });
await testPath(204, '/api/status.js', '', headers, { method: 'OPTIONS' });
})
);
await testPath(200, `/api/dump`, (body: any, res: any, isDev: any) => {
// @ts-ignore
const { host } = new URL(res.url);
const { env, headers } = JSON.parse(body);
test(
'[vercel dev] test trailingSlash true serve correct content',
testFixtureStdio('test-trailing-slash', async (testPath: any) => {
await testPath(200, '/', 'Index Page');
await testPath(200, '/index.html', 'Index Page');
await testPath(200, '/about.html', 'About Page');
await testPath(200, '/sub/', 'Sub Index Page');
await testPath(200, '/sub/index.html', 'Sub Index Page');
await testPath(200, '/sub/another.html', 'Sub Another Page');
await testPath(200, '/style.css', 'body { color: green }');
await testPath(308, '/about.html/', 'Redirecting to /about.html (308)', {
Location: '/about.html',
});
await testPath(308, '/style.css/', 'Redirecting to /style.css (308)', {
Location: '/style.css',
});
await testPath(308, '/sub', 'Redirecting to /sub/ (308)', {
Location: '/sub/',
});
})
);
// Test that the API endpoint receives the Vercel proxy request headers
expect(headers['x-forwarded-host']).toBe(host);
expect(headers['x-vercel-deployment-url']).toBe(host);
expect(isIP(headers['x-real-ip'])).toBeTruthy();
expect(isIP(headers['x-forwarded-for'])).toBeTruthy();
expect(isIP(headers['x-vercel-forwarded-for'])).toBeTruthy();
test(
'[vercel dev] should serve custom 404 when `trailingSlash: true`',
testFixtureStdio('test-trailing-slash-custom-404', async (testPath: any) => {
await testPath(200, '/', 'This is the home page');
await testPath(200, '/about.html', 'The about page');
await testPath(200, '/contact/', 'Contact Subdirectory');
await testPath(404, '/nothing/', 'Custom 404 Page');
})
);
test(
'[vercel dev] test trailingSlash false serve correct content',
testFixtureStdio('test-trailing-slash-false', async (testPath: any) => {
await testPath(200, '/', 'Index Page');
await testPath(200, '/index.html', 'Index Page');
await testPath(200, '/about.html', 'About Page');
await testPath(200, '/sub', 'Sub Index Page');
await testPath(200, '/sub/index.html', 'Sub Index Page');
await testPath(200, '/sub/another.html', 'Sub Another Page');
await testPath(200, '/style.css', 'body { color: green }');
await testPath(308, '/about.html/', 'Redirecting to /about.html (308)', {
Location: '/about.html',
});
await testPath(308, '/sub/', 'Redirecting to /sub (308)', {
Location: '/sub',
});
await testPath(
308,
'/sub/another.html/',
'Redirecting to /sub/another.html (308)',
{
Location: '/sub/another.html',
// Test that the API endpoint has the Vercel platform env vars defined.
expect(env.NOW_REGION).toMatch(/^[a-z]{3}\d$/);
if (isDev) {
// Only dev is tested because in production these are opt-in.
expect(env.VERCEL_URL).toBe(host);
expect(env.VERCEL_REGION).toBe('dev1');
}
);
});
})
);
test(
'[vercel dev] throw when invalid builder routes detected',
testFixtureStdio(
'invalid-builder-routes',
async (testPath: any) => {
await testPath(
500,
'/',
/Route at index 0 has invalid `src` regular expression/m
);
},
{ skipDeploy: true }
)
);
test(
'[vercel dev] support legacy `@now` scope runtimes',
testFixtureStdio('legacy-now-runtime', async (testPath: any) => {
await testPath(200, '/', /A simple deployment with the Vercel API!/m);
})
);
test(
'[vercel dev] 00-list-directory',
testFixtureStdio(
'00-list-directory',
async (testPath: any) => {
await testPath(200, '/', /Files within/m);
await testPath(200, '/', /test[0-3]\.txt/m);
await testPath(200, '/', /\.well-known/m);
await testPath(200, '/.well-known/keybase.txt', 'proof goes here');
},
{ projectSettings: { directoryListing: true } }
)
);
test(
'[vercel dev] 01-node',
testFixtureStdio('01-node', async (testPath: any) => {
await testPath(200, '/', /A simple deployment with the Vercel API!/m);
})
);
test(
'[vercel dev] add a `api/fn.ts` when `api` does not exist at startup`',
testFixtureStdio('no-api', async (_testPath: any, port: any) => {
const directory = fixture('no-api');
const apiDir = join(directory, 'api');
try {
{
const response = await fetch(`http://localhost:${port}/api/new-file`);
validateResponseHeaders(response);
expect(response.status).toBe(404);
}
const fileContents = `
export const config = {
runtime: 'edge'
}
export default async function edge(request, event) {
return new Response('from new file');
}
`;
await mkdirp(apiDir);
await fs.writeFile(join(apiDir, 'new-file.js'), fileContents);
// Wait until file events have been processed
await sleep(ms('1s'));
{
const response = await fetch(`http://localhost:${port}/api/new-file`);
validateResponseHeaders(response);
const body = await response.text();
expect(body.trim()).toBe('from new file');
}
} finally {
await fs.remove(apiDir);
}
'[vercel dev] Do not fail if `src` is missing',
testFixtureStdio('missing-src-property', async (testPath: any) => {
await testPath(200, '/', /hello:index.txt/m);
await testPath(404, '/i-do-not-exist');
})
);

View File

@@ -1,196 +1,15 @@
import ms from 'ms';
import fs from 'fs-extra';
import { isIP } from 'net';
import { join } from 'path';
import { Response } from 'node-fetch';
const {
fetch,
sleep,
fixture,
testFixture,
testFixtureStdio,
validateResponseHeaders,
} = require('./utils.js');
test(
'[vercel dev] temporary directory listing',
testFixtureStdio(
'temporary-directory-listing',
async (_testPath: any, port: any) => {
const directory = fixture('temporary-directory-listing');
await fs.unlink(join(directory, 'index.txt')).catch(() => null);
await sleep(ms('20s'));
const firstResponse = await fetch(`http://localhost:${port}`);
validateResponseHeaders(firstResponse);
const body = await firstResponse.text();
console.log(body);
expect(firstResponse.status).toBe(404);
await fs.writeFile(join(directory, 'index.txt'), 'hello');
for (let i = 0; i < 20; i++) {
const response = await fetch(`http://localhost:${port}`);
validateResponseHeaders(response);
if (response.status === 200) {
const body = await response.text();
expect(body).toBe('hello');
}
await sleep(ms('1s'));
}
},
{ skipDeploy: true }
)
);
test('[vercel dev] add a `package.json` to trigger `@vercel/static-build`', async () => {
const directory = fixture('trigger-static-build');
await fs.unlink(join(directory, 'package.json')).catch(() => null);
await fs.unlink(join(directory, 'public', 'index.txt')).catch(() => null);
await fs.rmdir(join(directory, 'public')).catch(() => null);
const tester = testFixtureStdio(
'trigger-static-build',
async (_testPath: any, port: any) => {
{
const response = await fetch(`http://localhost:${port}`);
validateResponseHeaders(response);
const body = await response.text();
expect(body.trim()).toBe('hello:index.txt');
}
const rnd = Math.random().toString();
const pkg = {
private: true,
scripts: { build: `mkdir -p public && echo ${rnd} > public/index.txt` },
};
await fs.writeFile(join(directory, 'package.json'), JSON.stringify(pkg));
// Wait until file events have been processed
await sleep(ms('2s'));
{
const response = await fetch(`http://localhost:${port}`);
validateResponseHeaders(response);
const body = await response.text();
expect(body.trim()).toBe(rnd);
}
},
{ skipDeploy: true }
);
await tester();
});
test('[vercel dev] no build matches warning', async () => {
const directory = fixture('no-build-matches');
const { dev } = await testFixture(directory, {
stdio: ['ignore', 'pipe', 'pipe'],
});
try {
// start `vercel dev` detached in child_process
dev.unref();
dev.stderr.setEncoding('utf8');
await new Promise<void>(resolve => {
dev.stderr.on('data', (str: string) => {
if (str.includes('did not match any source files')) {
resolve();
}
});
});
} finally {
await dev.kill();
}
});
test(
'[vercel dev] do not recursivly check the path',
testFixtureStdio('handle-filesystem-missing', async (testPath: any) => {
await testPath(200, '/', /hello/m);
await testPath(404, '/favicon.txt');
})
);
test('[vercel dev] render warning for empty cwd dir', async () => {
const directory = fixture('empty');
const { dev, port } = await testFixture(directory, {
stdio: ['ignore', 'pipe', 'pipe'],
});
try {
dev.unref();
// Monitor `stderr` for the warning
dev.stderr.setEncoding('utf8');
const msg = 'There are no files inside your deployment.';
await new Promise<void>(resolve => {
dev.stderr.on('data', (str: string) => {
if (str.includes(msg)) {
resolve();
}
});
});
// Issue a request to ensure a 404 response
await sleep(ms('3s'));
const response = await fetch(`http://localhost:${port}`);
validateResponseHeaders(response);
expect(response.status).toBe(404);
} finally {
await dev.kill();
}
});
test('[vercel dev] do not rebuild for changes in the output directory', async () => {
const directory = fixture('output-is-source');
const { dev, port } = await testFixture(directory, {
stdio: ['ignore', 'pipe', 'pipe'],
});
try {
dev.unref();
let stderr: any = [];
const start = Date.now();
dev.stderr.on('data', (str: any) => stderr.push(str));
while (stderr.join('').includes('Ready') === false) {
await sleep(ms('3s'));
if (Date.now() - start > ms('30s')) {
console.log('stderr:', stderr.join(''));
break;
}
}
const resp1 = await fetch(`http://localhost:${port}`);
const text1 = await resp1.text();
expect(text1.trim()).toBe('hello first');
await fs.writeFile(join(directory, 'public', 'index.html'), 'hello second');
await sleep(ms('3s'));
const resp2 = await fetch(`http://localhost:${port}`);
const text2 = await resp2.text();
expect(text2.trim()).toBe('hello second');
} finally {
await dev.kill();
}
});
test(
'[vercel dev] 25-nextjs-src-dir',
testFixtureStdio('25-nextjs-src-dir', async (testPath: any) => {
@@ -324,117 +143,6 @@ test(
})
);
test(
'[vercel dev] Use `@vercel/python` with Flask requirements.txt',
testFixtureStdio('python-flask', async (testPath: any) => {
const name = 'Alice';
const year = new Date().getFullYear();
await testPath(200, `/api/user?name=${name}`, new RegExp(`Hello ${name}`));
await testPath(200, `/api/date`, new RegExp(`Current date is ${year}`));
await testPath(200, `/api/date.py`, new RegExp(`Current date is ${year}`));
await testPath(200, `/api/headers`, (body: any, res: any) => {
// @ts-ignore
const { host } = new URL(res.url);
expect(body).toBe(host);
});
})
);
test(
'[vercel dev] Use custom runtime from the "functions" property',
testFixtureStdio('custom-runtime', async (testPath: any) => {
await testPath(200, `/api/user`, /Hello, from Bash!/m);
await testPath(200, `/api/user.sh`, /Hello, from Bash!/m);
})
);
test(
'[vercel dev] Should work with nested `tsconfig.json` files',
testFixtureStdio('nested-tsconfig', async (testPath: any) => {
await testPath(200, `/`, /Nested tsconfig.json test page/);
await testPath(200, `/api`, 'Nested `tsconfig.json` API endpoint');
})
);
test(
'[vercel dev] Should force `tsc` option "module: commonjs" for `startDevServer()`',
testFixtureStdio('force-module-commonjs', async (testPath: any) => {
await testPath(200, `/`, /Force &quot;module: commonjs&quot; test page/);
await testPath(
200,
`/api`,
'Force "module: commonjs" JavaScript with ES Modules API endpoint'
);
await testPath(
200,
`/api/ts`,
'Force "module: commonjs" TypeScript API endpoint'
);
})
);
test(
'[vercel dev] should prioritize index.html over other file named index.*',
testFixtureStdio('index-html-priority', async (testPath: any) => {
await testPath(200, '/', 'This is index.html');
await testPath(200, '/index.css', 'This is index.css');
})
);
test(
'[vercel dev] Should support `*.go` API serverless functions',
testFixtureStdio('go', async (testPath: any) => {
await testPath(200, `/api`, 'This is the index page');
await testPath(200, `/api/index`, 'This is the index page');
await testPath(200, `/api/index.go`, 'This is the index page');
await testPath(200, `/api/another`, 'This is another page');
await testPath(200, '/api/another.go', 'This is another page');
await testPath(200, `/api/foo`, 'Req Path: /api/foo');
await testPath(200, `/api/bar`, 'Req Path: /api/bar');
})
);
test(
'[vercel dev] Should set the `ts-node` "target" to match Node.js version',
testFixtureStdio('node-ts-node-target', async (testPath: any) => {
await testPath(200, `/api/subclass`, '{"ok":true}');
await testPath(
200,
`/api/array`,
'{"months":[1,2,3,4,5,6,7,8,9,10,11,12]}'
);
await testPath(200, `/api/dump`, (body: any, res: any, isDev: any) => {
// @ts-ignore
const { host } = new URL(res.url);
const { env, headers } = JSON.parse(body);
// Test that the API endpoint receives the Vercel proxy request headers
expect(headers['x-forwarded-host']).toBe(host);
expect(headers['x-vercel-deployment-url']).toBe(host);
expect(isIP(headers['x-real-ip'])).toBeTruthy();
expect(isIP(headers['x-forwarded-for'])).toBeTruthy();
expect(isIP(headers['x-vercel-forwarded-for'])).toBeTruthy();
// Test that the API endpoint has the Vercel platform env vars defined.
expect(env.NOW_REGION).toMatch(/^[a-z]{3}\d$/);
if (isDev) {
// Only dev is tested because in production these are opt-in.
expect(env.VERCEL_URL).toBe(host);
expect(env.VERCEL_REGION).toBe('dev1');
}
});
})
);
test(
'[vercel dev] Do not fail if `src` is missing',
testFixtureStdio('missing-src-property', async (testPath: any) => {
await testPath(200, '/', /hello:index.txt/m);
await testPath(404, '/i-do-not-exist');
})
);
test(
'[vercel dev] Middleware that returns a 200 response',
testFixtureStdio('middleware-response', async (testPath: any) => {

View File

@@ -0,0 +1,449 @@
import { join } from 'path';
import ms from 'ms';
import fs, { mkdirp } from 'fs-extra';
const {
fetch,
fixture,
sleep,
testFixture,
testFixtureStdio,
validateResponseHeaders,
} = require('./utils.js');
test(
'[vercel dev] temporary directory listing',
testFixtureStdio(
'temporary-directory-listing',
async (_testPath: any, port: any) => {
const directory = fixture('temporary-directory-listing');
await fs.unlink(join(directory, 'index.txt')).catch(() => null);
await sleep(ms('20s'));
const firstResponse = await fetch(`http://localhost:${port}`);
validateResponseHeaders(firstResponse);
const body = await firstResponse.text();
console.log(body);
expect(firstResponse.status).toBe(404);
await fs.writeFile(join(directory, 'index.txt'), 'hello');
for (let i = 0; i < 20; i++) {
const response = await fetch(`http://localhost:${port}`);
validateResponseHeaders(response);
if (response.status === 200) {
const body = await response.text();
expect(body).toBe('hello');
}
await sleep(ms('1s'));
}
},
{ skipDeploy: true }
)
);
test('[vercel dev] add a `package.json` to trigger `@vercel/static-build`', async () => {
const directory = fixture('trigger-static-build');
await fs.unlink(join(directory, 'package.json')).catch(() => null);
await fs.unlink(join(directory, 'public', 'index.txt')).catch(() => null);
await fs.rmdir(join(directory, 'public')).catch(() => null);
const tester = testFixtureStdio(
'trigger-static-build',
async (_testPath: any, port: any) => {
{
const response = await fetch(`http://localhost:${port}`);
validateResponseHeaders(response);
const body = await response.text();
expect(body.trim()).toBe('hello:index.txt');
}
const rnd = Math.random().toString();
const pkg = {
private: true,
scripts: { build: `mkdir -p public && echo ${rnd} > public/index.txt` },
};
await fs.writeFile(join(directory, 'package.json'), JSON.stringify(pkg));
// Wait until file events have been processed
await sleep(ms('2s'));
{
const response = await fetch(`http://localhost:${port}`);
validateResponseHeaders(response);
const body = await response.text();
expect(body.trim()).toBe(rnd);
}
},
{ skipDeploy: true }
);
await tester();
});
test('[vercel dev] no build matches warning', async () => {
const directory = fixture('no-build-matches');
const { dev } = await testFixture(directory, {
stdio: ['ignore', 'pipe', 'pipe'],
});
try {
// start `vercel dev` detached in child_process
dev.unref();
dev.stderr.setEncoding('utf8');
await new Promise<void>(resolve => {
dev.stderr.on('data', (str: string) => {
if (str.includes('did not match any source files')) {
resolve();
}
});
});
} finally {
await dev.kill();
}
});
test(
'[vercel dev] do not recursivly check the path',
testFixtureStdio('handle-filesystem-missing', async (testPath: any) => {
await testPath(200, '/', /hello/m);
await testPath(404, '/favicon.txt');
})
);
test('[vercel dev] render warning for empty cwd dir', async () => {
const directory = fixture('empty');
const { dev, port } = await testFixture(directory, {
stdio: ['ignore', 'pipe', 'pipe'],
});
try {
dev.unref();
// Monitor `stderr` for the warning
dev.stderr.setEncoding('utf8');
const msg = 'There are no files inside your deployment.';
await new Promise<void>(resolve => {
dev.stderr.on('data', (str: string) => {
if (str.includes(msg)) {
resolve();
}
});
});
// Issue a request to ensure a 404 response
await sleep(ms('3s'));
const response = await fetch(`http://localhost:${port}`);
validateResponseHeaders(response);
expect(response.status).toBe(404);
} finally {
await dev.kill();
}
});
test('[vercel dev] do not rebuild for changes in the output directory', async () => {
const directory = fixture('output-is-source');
const { dev, port } = await testFixture(directory, {
stdio: ['ignore', 'pipe', 'pipe'],
});
try {
dev.unref();
let stderr: any = [];
const start = Date.now();
dev.stderr.on('data', (str: any) => stderr.push(str));
while (stderr.join('').includes('Ready') === false) {
await sleep(ms('3s'));
if (Date.now() - start > ms('30s')) {
console.log('stderr:', stderr.join(''));
break;
}
}
const resp1 = await fetch(`http://localhost:${port}`);
const text1 = await resp1.text();
expect(text1.trim()).toBe('hello first');
await fs.writeFile(join(directory, 'public', 'index.html'), 'hello second');
await sleep(ms('3s'));
const resp2 = await fetch(`http://localhost:${port}`);
const text2 = await resp2.text();
expect(text2.trim()).toBe('hello second');
} finally {
await dev.kill();
}
});
test(
'[vercel dev] test cleanUrls serve correct content',
testFixtureStdio('test-clean-urls', async (testPath: any) => {
await testPath(200, '/', 'Index Page');
await testPath(200, '/about', 'About Page');
await testPath(200, '/sub', 'Sub Index Page');
await testPath(200, '/sub/another', 'Sub Another Page');
await testPath(200, '/style.css', 'body { color: green }');
await testPath(308, '/index.html', 'Redirecting to / (308)', {
Location: '/',
});
await testPath(308, '/about.html', 'Redirecting to /about (308)', {
Location: '/about',
});
await testPath(308, '/sub/index.html', 'Redirecting to /sub (308)', {
Location: '/sub',
});
await testPath(
308,
'/sub/another.html',
'Redirecting to /sub/another (308)',
{ Location: '/sub/another' }
);
})
);
test(
'[vercel dev] test cleanUrls serve correct content when using `outputDirectory`',
testFixtureStdio(
'test-clean-urls-with-output-directory',
async (testPath: any) => {
await testPath(200, '/', 'Index Page');
await testPath(200, '/about', 'About Page');
await testPath(200, '/sub', 'Sub Index Page');
await testPath(200, '/sub/another', 'Sub Another Page');
await testPath(200, '/style.css', 'body { color: green }');
await testPath(308, '/index.html', 'Redirecting to / (308)', {
Location: '/',
});
await testPath(308, '/about.html', 'Redirecting to /about (308)', {
Location: '/about',
});
await testPath(308, '/sub/index.html', 'Redirecting to /sub (308)', {
Location: '/sub',
});
await testPath(
308,
'/sub/another.html',
'Redirecting to /sub/another (308)',
{ Location: '/sub/another' }
);
}
)
);
test(
'[vercel dev] should serve custom 404 when `cleanUrls: true`',
testFixtureStdio('test-clean-urls-custom-404', async (testPath: any) => {
await testPath(200, '/', 'This is the home page');
await testPath(200, '/about', 'The about page');
await testPath(200, '/contact/me', 'Contact Me Subdirectory');
await testPath(404, '/nothing', 'Custom 404 Page');
await testPath(404, '/nothing/', 'Custom 404 Page');
})
);
test(
'[vercel dev] test cleanUrls and trailingSlash serve correct content',
testFixtureStdio('test-clean-urls-trailing-slash', async (testPath: any) => {
await testPath(200, '/', 'Index Page');
await testPath(200, '/about/', 'About Page');
await testPath(200, '/sub/', 'Sub Index Page');
await testPath(200, '/sub/another/', 'Sub Another Page');
await testPath(200, '/style.css', 'body { color: green }');
//TODO: fix this test so that location is `/` instead of `//`
//await testPath(308, '/index.html', 'Redirecting to / (308)', { Location: '/' });
await testPath(308, '/about.html', 'Redirecting to /about/ (308)', {
Location: '/about/',
});
await testPath(308, '/sub/index.html', 'Redirecting to /sub/ (308)', {
Location: '/sub/',
});
await testPath(
308,
'/sub/another.html',
'Redirecting to /sub/another/ (308)',
{
Location: '/sub/another/',
}
);
})
);
test(
'[vercel dev] test cors headers work with OPTIONS',
testFixtureStdio('test-cors-routes', async (testPath: any) => {
const headers = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers':
'Content-Type, Authorization, Accept, Content-Length, Origin, User-Agent',
'Access-Control-Allow-Methods':
'GET, POST, OPTIONS, HEAD, PATCH, PUT, DELETE',
};
await testPath(200, '/', 'status api', headers, { method: 'GET' });
await testPath(200, '/', 'status api', headers, { method: 'POST' });
await testPath(200, '/api/status.js', 'status api', headers, {
method: 'GET',
});
await testPath(200, '/api/status.js', 'status api', headers, {
method: 'POST',
});
await testPath(204, '/', '', headers, { method: 'OPTIONS' });
await testPath(204, '/api/status.js', '', headers, { method: 'OPTIONS' });
})
);
test(
'[vercel dev] test trailingSlash true serve correct content',
testFixtureStdio('test-trailing-slash', async (testPath: any) => {
await testPath(200, '/', 'Index Page');
await testPath(200, '/index.html', 'Index Page');
await testPath(200, '/about.html', 'About Page');
await testPath(200, '/sub/', 'Sub Index Page');
await testPath(200, '/sub/index.html', 'Sub Index Page');
await testPath(200, '/sub/another.html', 'Sub Another Page');
await testPath(200, '/style.css', 'body { color: green }');
await testPath(308, '/about.html/', 'Redirecting to /about.html (308)', {
Location: '/about.html',
});
await testPath(308, '/style.css/', 'Redirecting to /style.css (308)', {
Location: '/style.css',
});
await testPath(308, '/sub', 'Redirecting to /sub/ (308)', {
Location: '/sub/',
});
})
);
test(
'[vercel dev] should serve custom 404 when `trailingSlash: true`',
testFixtureStdio('test-trailing-slash-custom-404', async (testPath: any) => {
await testPath(200, '/', 'This is the home page');
await testPath(200, '/about.html', 'The about page');
await testPath(200, '/contact/', 'Contact Subdirectory');
await testPath(404, '/nothing/', 'Custom 404 Page');
})
);
test(
'[vercel dev] test trailingSlash false serve correct content',
testFixtureStdio('test-trailing-slash-false', async (testPath: any) => {
await testPath(200, '/', 'Index Page');
await testPath(200, '/index.html', 'Index Page');
await testPath(200, '/about.html', 'About Page');
await testPath(200, '/sub', 'Sub Index Page');
await testPath(200, '/sub/index.html', 'Sub Index Page');
await testPath(200, '/sub/another.html', 'Sub Another Page');
await testPath(200, '/style.css', 'body { color: green }');
await testPath(308, '/about.html/', 'Redirecting to /about.html (308)', {
Location: '/about.html',
});
await testPath(308, '/sub/', 'Redirecting to /sub (308)', {
Location: '/sub',
});
await testPath(
308,
'/sub/another.html/',
'Redirecting to /sub/another.html (308)',
{
Location: '/sub/another.html',
}
);
})
);
test(
'[vercel dev] throw when invalid builder routes detected',
testFixtureStdio(
'invalid-builder-routes',
async (testPath: any) => {
await testPath(
500,
'/',
/Route at index 0 has invalid `src` regular expression/m
);
},
{ skipDeploy: true }
)
);
test(
'[vercel dev] support legacy `@now` scope runtimes',
testFixtureStdio('legacy-now-runtime', async (testPath: any) => {
await testPath(200, '/', /A simple deployment with the Vercel API!/m);
})
);
test(
'[vercel dev] 00-list-directory',
testFixtureStdio(
'00-list-directory',
async (testPath: any) => {
await testPath(200, '/', /Files within/m);
await testPath(200, '/', /test[0-3]\.txt/m);
await testPath(200, '/', /\.well-known/m);
await testPath(200, '/.well-known/keybase.txt', 'proof goes here');
},
{ projectSettings: { directoryListing: true } }
)
);
test(
'[vercel dev] 01-node',
testFixtureStdio('01-node', async (testPath: any) => {
await testPath(200, '/', /A simple deployment with the Vercel API!/m);
})
);
test(
'[vercel dev] add a `api/fn.ts` when `api` does not exist at startup`',
testFixtureStdio('no-api', async (_testPath: any, port: any) => {
const directory = fixture('no-api');
const apiDir = join(directory, 'api');
try {
{
const response = await fetch(`http://localhost:${port}/api/new-file`);
validateResponseHeaders(response);
expect(response.status).toBe(404);
}
const fileContents = `
export const config = {
runtime: 'edge'
}
export default async function edge(request, event) {
return new Response('from new file');
}
`;
await mkdirp(apiDir);
await fs.writeFile(join(apiDir, 'new-file.js'), fileContents);
// Wait until file events have been processed
await sleep(ms('1s'));
{
const response = await fetch(`http://localhost:${port}/api/new-file`);
validateResponseHeaders(response);
const body = await response.text();
expect(body.trim()).toBe('from new file');
}
} finally {
await fs.remove(apiDir);
}
})
);

View File

@@ -0,0 +1,5 @@
{
"private": true,
"name": "cli-test-fixtures",
"description": "We created package.json here to avoid reading the monorepo package.json during testing"
}

View File

@@ -0,0 +1 @@
.vercel/builders

View File

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

View File

@@ -0,0 +1,4 @@
const { createServer } = require('http');
const handler = (_req, res) => res.end('hi');
const server = createServer(handler);
module.exports = server;

View File

@@ -0,0 +1,4 @@
{
"builds": [{ "src": "server.js", "use": "@now/node-server" }],
"routes": [{ "src": "/(.*)", "dest": "/server.js" }]
}

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,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

@@ -10,7 +10,7 @@ describe('alias', () => {
client.setArgv('alias', 'ls');
const exitCodePromise = alias(client);
await expect(exitCodePromise).resolves.toEqual(0);
await expect(client.stderr).toOutput('dummy-19.app');
await expect(client.stdout).toOutput('dummy-19.app');
});
it('should list up to 2 aliases', async () => {
@@ -19,6 +19,6 @@ describe('alias', () => {
client.setArgv('alias', 'ls', '--limit', '2');
const exitCodePromise = alias(client);
await expect(exitCodePromise).resolves.toEqual(0);
await expect(client.stderr).toOutput('dummy-1.app');
await expect(client.stdout).toOutput('dummy-1.app');
});
});

View File

@@ -834,6 +834,42 @@ describe('build', () => {
}
});
/* Skipping because this legacy builder is causing something to break with cwd
it('should error when builder returns result without "output" such as @now/node-server', async () => {
const cwd = join(os.tmpdir(), 'now-node-server');
const output = join(cwd, '.vercel/output');
try {
// Copy to a temp directory to avoid breaking other tests
await fs.copy(fixture('now-node-server'), cwd);
process.chdir(cwd);
const exitCode = await build(client);
expect(exitCode).toEqual(1);
// Error gets printed to the terminal
const message =
'The build result from "@now/node-server" is missing the "output" property. Please update from "@now" to "@vercel" in your `vercel.json` file.';
await expect(client.stderr).toOutput(message);
const builds = await fs.readJSON(join(output, 'builds.json'));
// top level "error" also contains the same error
expect(builds.error).toEqual({
name: 'Error',
message,
stack: expect.stringContaining(message),
});
// `config.json` contains `version`
const configJson = await fs.readJSON(join(output, 'config.json'));
expect(configJson.version).toBe(3);
} finally {
await fs.remove(cwd);
process.chdir(originalCwd);
delete process.env.__VERCEL_BUILD_RUNNING;
}
});
*/
it('should allow for missing "build" script', async () => {
const cwd = fixture('static-with-pkg');
const output = join(cwd, '.vercel/output');
@@ -989,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');
@@ -1045,6 +1102,30 @@ 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', '* * * * *');
} finally {
process.chdir(originalCwd);
delete process.env.__VERCEL_BUILD_RUNNING;
}
});
describe('should find packages with different main/module/browser keys', function () {
let output: string;
@@ -1193,13 +1274,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

@@ -9,7 +9,7 @@ describe('certs', () => {
useCert();
client.setArgv('certs', 'ls');
const exitCodePromise = certs(client);
await expect(client.stderr).toOutput('dummy-19.cert');
await expect(client.stdout).toOutput('dummy-19.cert');
await expect(exitCodePromise).resolves.toEqual(0);
});
@@ -18,7 +18,7 @@ describe('certs', () => {
useCert();
client.setArgv('certs', 'ls', '--limit', '2');
const exitCodePromise = certs(client);
await expect(client.stderr).toOutput('dummy-1.cert');
await expect(client.stdout).toOutput('dummy-1.cert');
await expect(exitCodePromise).resolves.toEqual(0);
});
});

View File

@@ -105,6 +105,7 @@ describe('importBuilders()', () => {
await expect(client.stderr).toOutput(
'> Installing Builder: @vercel/node'
);
await expect(client.stderr).not.toOutput('npm WARN deprecated');
} finally {
await remove(cwd);
}
@@ -146,6 +147,33 @@ describe('importBuilders()', () => {
}
});
it('should install and warn when Builder is deprecated', async () => {
if (process.platform === 'win32') {
// this test creates symlinks which require admin by default on Windows
console.log('Skipping test on Windows');
return;
}
const cwd = await getWriteableDirectory();
try {
const spec = '@now/node';
const specs = new Set([spec]);
const builders = await importBuilders(specs, cwd, client.output);
expect(builders.size).toEqual(1);
expect(builders.get(spec)?.pkg.name).toEqual('@now/node');
expect(builders.get(spec)?.pkg.version).toEqual('1.8.5');
expect(builders.get(spec)?.pkgPath).toEqual(
join(cwd, '.vercel/builders/node_modules/@now/node/package.json')
);
expect(typeof builders.get(spec)?.builder.build).toEqual('function');
await expect(client.stderr).toOutput(
'npm WARN deprecated @now/node@1.8.5: "@now/node" is deprecated and will stop receiving updates on December 31, 2020. Please use "@vercel/node" instead.'
);
} finally {
await remove(cwd);
}
});
it('should install and import legacy `@now/build-utils` Builders', async () => {
if (process.platform === 'win32') {
// this test creates symlinks which require admin by default on Windows

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.2.27",
"version": "12.3.5",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
"homepage": "https://vercel.com",
@@ -23,7 +23,7 @@
"node": ">= 14"
},
"devDependencies": {
"@types/async-retry": "1.4.1",
"@types/async-retry": "1.4.5",
"@types/fs-extra": "7.0.0",
"@types/jest": "27.4.1",
"@types/minimatch": "3.0.5",
@@ -43,8 +43,8 @@
]
},
"dependencies": {
"@vercel/build-utils": "workspace:5.7.6",
"@vercel/routing-utils": "workspace:2.1.4",
"@vercel/build-utils": "6.1.0",
"@vercel/routing-utils": "2.1.8",
"@zeit/fetch": "5.2.0",
"async-retry": "1.2.3",
"async-sema": "3.0.0",

View File

@@ -1,6 +1,6 @@
import sleep from 'sleep-promise';
import ms from 'ms';
import { fetch, getApiDeploymentsUrl } from './utils';
import { getPollingDelay } from './utils/get-polling-delay';
import {
isDone,
isReady,
@@ -47,6 +47,7 @@ export async function* checkDeploymentStatus(
// Build polling
debug('Waiting for builds and the deployment to complete...');
const finishedEvents = new Set();
const startTime = Date.now();
while (true) {
// Deployment polling
@@ -155,6 +156,8 @@ export async function* checkDeploymentStatus(
};
}
await sleep(ms('1.5s'));
const elapsed = Date.now() - startTime;
const duration = getPollingDelay(elapsed);
await sleep(duration);
}
}

View File

@@ -73,7 +73,7 @@ export default function buildCreateDeployment() {
debug(`Provided 'path' is a single file`);
}
let { fileList } = await buildFileTree(path, clientOptions, debug);
const { fileList } = await buildFileTree(path, clientOptions, debug);
// This is a useful warning because it prevents people
// from getting confused about a deployment that renders 404.

View File

@@ -1,4 +1,4 @@
import { DeploymentFile } from './utils/hashes';
import { FilesMap } from './utils/hashes';
import { generateQueryString } from './utils/query-string';
import { isReady, isAliasAssigned } from './utils/ready-state';
import { checkDeploymentStatus } from './check-deployment-status';
@@ -16,7 +16,7 @@ import {
} from './types';
async function* postDeployment(
files: Map<string, DeploymentFile>,
files: FilesMap,
clientOptions: VercelClientOptions,
deploymentOptions: DeploymentOptions
): AsyncIterableIterator<{
@@ -90,7 +90,7 @@ async function* postDeployment(
}
function getDefaultName(
files: Map<string, DeploymentFile>,
files: FilesMap,
clientOptions: VercelClientOptions
): string {
const debug = createDebug(clientOptions.debug);
@@ -109,7 +109,7 @@ function getDefaultName(
}
export async function* deploy(
files: Map<string, DeploymentFile>,
files: FilesMap,
clientOptions: VercelClientOptions,
deploymentOptions: DeploymentOptions
): AsyncIterableIterator<{ type: string; payload: any }> {

View File

@@ -5,7 +5,7 @@ import { EventEmitter } from 'events';
import retry from 'async-retry';
import { Sema } from 'async-sema';
import { DeploymentFile } from './utils/hashes';
import { DeploymentFile, FilesMap } from './utils/hashes';
import { fetch, API_FILES, createDebug } from './utils';
import { DeploymentError } from './errors';
import { deploy } from './deploy';
@@ -29,7 +29,7 @@ const isClientNetworkError = (err: Error) => {
};
export async function* upload(
files: Map<string, DeploymentFile>,
files: FilesMap,
clientOptions: VercelClientOptions,
deploymentOptions: DeploymentOptions
): AsyncIterableIterator<any> {
@@ -98,6 +98,10 @@ export async function* upload(
await semaphore.acquire();
const { data } = file;
if (typeof data === 'undefined') {
// Directories don't need to be uploaded
return;
}
uploadProgress.bytesUploaded = 0;

View File

@@ -0,0 +1,14 @@
import ms from 'ms';
export function getPollingDelay(elapsed: number): number {
if (elapsed <= ms('15s')) {
return ms('1s');
}
if (elapsed <= ms('1m')) {
return ms('5s');
}
if (elapsed <= ms('5m')) {
return ms('15s');
}
return ms('30s');
}

View File

@@ -4,10 +4,12 @@ import { Sema } from 'async-sema';
export interface DeploymentFile {
names: string[];
data: Buffer;
data?: Buffer;
mode: number;
}
export type FilesMap = Map<string | undefined, DeploymentFile>;
/**
* Computes a hash for the given buf.
*
@@ -23,14 +25,12 @@ export function hash(buf: Buffer): string {
* @param map with hashed files
* @return {object}
*/
export const mapToObject = (
map: Map<string, DeploymentFile>
): { [key: string]: DeploymentFile } => {
export const mapToObject = (map: FilesMap): Record<string, DeploymentFile> => {
const obj: { [key: string]: DeploymentFile } = {};
for (const [key, value] of map) {
if (typeof key === 'undefined') continue;
obj[key] = value;
}
return obj;
};
@@ -43,8 +43,8 @@ export const mapToObject = (
*/
export async function hashes(
files: string[],
map = new Map<string, DeploymentFile>()
): Promise<Map<string, DeploymentFile>> {
map = new Map<string | undefined, DeploymentFile>()
): Promise<FilesMap> {
const semaphore = new Sema(100);
await Promise.all(
@@ -54,15 +54,21 @@ export async function hashes(
const stat = await fs.lstat(name);
const mode = stat.mode;
let data: Buffer | null = null;
if (stat.isSymbolicLink()) {
const link = await fs.readlink(name);
data = Buffer.from(link, 'utf8');
} else {
data = await fs.readFile(name);
let data: Buffer | undefined;
const isDirectory = stat.isDirectory();
let h: string | undefined;
if (!isDirectory) {
if (stat.isSymbolicLink()) {
const link = await fs.readlink(name);
data = Buffer.from(link, 'utf8');
} else {
data = await fs.readFile(name);
}
h = hash(data);
}
const h = hash(data);
const entry = map.get(h);
if (entry) {

View File

@@ -1,4 +1,4 @@
import { DeploymentFile } from './hashes';
import { FilesMap } from './hashes';
import { FetchOptions } from '@zeit/fetch';
import { nodeFetch, zeitFetch } from './fetch';
import { join, sep, relative } from 'path';
@@ -256,15 +256,15 @@ export const fetch = async (
export interface PreparedFile {
file: string;
sha: string;
size: number;
sha?: string;
size?: number;
mode: number;
}
const isWin = process.platform.includes('win');
export const prepareFiles = (
files: Map<string, DeploymentFile>,
files: FilesMap,
clientOptions: VercelClientOptions
): PreparedFile[] => {
const preparedFiles: PreparedFile[] = [];
@@ -286,9 +286,9 @@ export const prepareFiles = (
preparedFiles.push({
file: isWin ? fileName.replace(/\\/g, '/') : fileName,
size: file.data.byteLength || file.data.length,
size: file.data?.byteLength || file.data?.length,
mode: file.mode,
sha,
sha: sha || undefined,
});
}
}

View File

@@ -87,6 +87,10 @@ export default function readdir(
if (stats.isDirectory()) {
readdir(filePath, ignores)
.then(function (res) {
if (res.length === 0) {
// Empty directories get returned
list.push(filePath);
}
list = list.concat(res);
pending -= 1;
if (!pending) {

View File

@@ -0,0 +1,41 @@
import { getPollingDelay } from '../src/utils/get-polling-delay';
describe('getPollingDelay()', () => {
it('should return 1 second', async () => {
expect(getPollingDelay(0)).toBe(1000);
expect(getPollingDelay(1000)).toBe(1000);
expect(getPollingDelay(3000)).toBe(1000);
expect(getPollingDelay(5000)).toBe(1000);
expect(getPollingDelay(8000)).toBe(1000);
expect(getPollingDelay(9000)).toBe(1000);
expect(getPollingDelay(10000)).toBe(1000);
expect(getPollingDelay(13000)).toBe(1000);
expect(getPollingDelay(15000)).toBe(1000);
});
it('should return 5 second', async () => {
expect(getPollingDelay(15001)).toBe(5000);
expect(getPollingDelay(16000)).toBe(5000);
expect(getPollingDelay(23000)).toBe(5000);
expect(getPollingDelay(36000)).toBe(5000);
expect(getPollingDelay(59000)).toBe(5000);
expect(getPollingDelay(60000)).toBe(5000);
});
it('should return 15 second', async () => {
expect(getPollingDelay(60001)).toBe(15000);
expect(getPollingDelay(80000)).toBe(15000);
expect(getPollingDelay(100000)).toBe(15000);
expect(getPollingDelay(200000)).toBe(15000);
expect(getPollingDelay(250000)).toBe(15000);
expect(getPollingDelay(300000)).toBe(15000);
});
it('should return 30 second', async () => {
expect(getPollingDelay(300001)).toBe(30000);
expect(getPollingDelay(400000)).toBe(30000);
expect(getPollingDelay(1400000)).toBe(30000);
expect(getPollingDelay(9400000)).toBe(30000);
expect(getPollingDelay(99400000)).toBe(30000);
});
});

View File

@@ -24,7 +24,11 @@ describe('buildFileTree()', () => {
noop
);
const expectedFileList = toAbsolutePaths(cwd, ['.nowignore', 'index.txt']);
const expectedFileList = toAbsolutePaths(cwd, [
'.nowignore',
'folder',
'index.txt',
]);
expect(normalizeWindowsPaths(expectedFileList).sort()).toEqual(
normalizeWindowsPaths(fileList).sort()
);
@@ -41,9 +45,14 @@ describe('buildFileTree()', () => {
it('should include symlinked files and directories', async () => {
const cwd = fixture('symlinks');
// Also add an empty directory to make sure it's included
await fs.mkdirp(join(cwd, 'empty'));
const { fileList } = await buildFileTree(cwd, { isDirectory: true }, noop);
const expectedFileList = toAbsolutePaths(cwd, [
'empty',
'folder-link',
'folder/text.txt',
'index.txt',

View File

@@ -12,7 +12,8 @@
"noUnusedLocals": true,
"noUnusedParameters": true,
"strict": true,
"target": "ES2020"
"target": "ES2020",
"skipLibCheck": true
},
"include": ["./src"]
}

View File

@@ -1,4 +1,4 @@
# `@vercel/edge`
A set of utilities to help you deploy any framework on the Edge using Vercel.
Please [follow the documentation](https://vercel.com/docs/concepts/functions/edge-functions/edge-functions-api#the-@vercel/edge-package) for examples and usage.
Please [follow the documentation](https://vercel.com/docs/concepts/functions/edge-functions/vercel-edge-package) for examples and usage.

View File

@@ -1,10 +1,19 @@
{
"name": "@vercel/edge",
"version": "0.2.2",
"version": "0.2.7",
"license": "MIT",
"main": "dist/index.js",
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
"homepage": "https://vercel.com/docs/concepts/functions/edge-functions/vercel-edge-package",
"files": [
"dist"
],
"repository": {
"type": "git",
"url": "https://github.com/vercel/vercel.git",
"directory": "packages/edge"
},
"scripts": {
"build": "tsup src/index.ts --dts --format esm,cjs",
"test": "jest --env node --verbose --runInBand --bail",

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/error-utils",
"version": "1.0.4",
"version": "1.0.8",
"description": "A collection of error utilities for vercel/vercel",
"main": "dist/index.js",
"types": "dist/index.d.ts",

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/frameworks",
"version": "1.2.0",
"version": "1.3.0",
"main": "./dist/frameworks.js",
"types": "./dist/frameworks.d.ts",
"files": [
@@ -21,7 +21,7 @@
"@types/js-yaml": "3.12.1",
"@types/node": "14.18.33",
"@types/node-fetch": "2.5.8",
"@vercel/routing-utils": "workspace:2.1.4",
"@vercel/routing-utils": "2.1.8",
"ajv": "6.12.2",
"typescript": "4.3.4"
}

View File

@@ -272,6 +272,11 @@ export const frameworks = [
headers: { 'cache-control': 'public, max-age=31536000, immutable' },
continue: true,
},
{
src: '^/_astro/(.*)$',
headers: { 'cache-control': 'public, max-age=31536000, immutable' },
continue: true,
},
],
},
{

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/fs-detectors",
"version": "3.7.0",
"version": "3.7.8",
"description": "Vercel filesystem detectors",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
@@ -19,9 +19,9 @@
"test-unit": "pnpm test"
},
"dependencies": {
"@vercel/error-utils": "workspace:1.0.4",
"@vercel/frameworks": "workspace:1.2.0",
"@vercel/routing-utils": "workspace:2.1.4",
"@vercel/error-utils": "1.0.8",
"@vercel/frameworks": "1.3.0",
"@vercel/routing-utils": "2.1.8",
"glob": "8.0.3",
"js-yaml": "4.1.0",
"json5": "2.2.2",
@@ -35,7 +35,7 @@
"@types/minimatch": "3.0.5",
"@types/node": "14.18.33",
"@types/semver": "7.3.10",
"@vercel/build-utils": "workspace:5.7.6",
"@vercel/build-utils": "6.1.0",
"typescript": "4.3.4"
}
}

View File

@@ -67,8 +67,11 @@ export async function getMonorepoDefaultSettings(
return {
monorepoManager: 'turbo',
buildCommand: `cd ${relativeToRoot} && npx turbo run build --filter={${projectPath}}...`,
installCommand: `cd ${relativeToRoot} && ${packageManager} install`,
commandForIgnoringBuildStep: `cd ${relativeToRoot} && npx turbo-ignore`,
installCommand:
packageManager === 'npm'
? `${packageManager} install --prefix=${relativeToRoot}`
: `${packageManager} install`,
commandForIgnoringBuildStep: `npx turbo-ignore`,
};
} else if (monorepoManager === 'nx') {
// No ENOENT handling required here since conditional wouldn't be `true` unless `nx.json` was found.
@@ -111,7 +114,10 @@ export async function getMonorepoDefaultSettings(
return {
monorepoManager: 'nx',
buildCommand: `cd ${relativeToRoot} && npx nx build ${projectName}`,
installCommand: `cd ${relativeToRoot} && ${packageManager} install`,
installCommand:
packageManager === 'npm'
? `${packageManager} install --prefix=${relativeToRoot}`
: `${packageManager} install`,
};
}
// TODO (@Ethan-Arrowood) - Revisit rush support when we can test it better

View File

@@ -1,5 +1,5 @@
{
"name": "a",
"name": "npm-workspace-a21",
"version": "1.0.0",
"description": "",
"main": "index.js",

View File

@@ -1,5 +1,5 @@
{
"name": "b",
"name": "npm-workspace-b21",
"version": "1.0.0",
"description": "",
"main": "index.js",

View File

@@ -1,6 +1,5 @@
{
"name": "21-npm-workspaces",
"version": "1.0.0",
"private": true,
"workspaces": [
"a",
"b"

View File

@@ -1,5 +1,5 @@
{
"name": "c",
"name": "fs-c23",
"license": "MIT",
"version": "0.1.0"
}

View File

@@ -1,5 +1,5 @@
{
"name": "d",
"name": "fs-d23",
"license": "MIT",
"version": "0.1.0",
"devDependencies": {

View File

@@ -1,6 +1,5 @@
{
"private": true,
"name": "23-pnpm-workspaces",
"license": "MIT",
"version": "1.0.0"
}

View File

@@ -1,6 +1,5 @@
{
"private": "true",
"name": "24-pnpm-hoisted",
"private": true,
"scripts": {
"build": "ls -Al node_modules && node index.js"
},

View File

@@ -1,5 +1,5 @@
{
"name": "a",
"name": "fs-a25",
"version": "1.0.0",
"description": "",
"main": "index.js",

View File

@@ -1,5 +1,5 @@
{
"name": "b",
"name": "fs-b25",
"version": "1.0.0",
"description": "",
"main": "index.js",

View File

@@ -1,6 +1,5 @@
{
"private": "true",
"name": "25-multiple-lock-files-yarn",
"private": true,
"workspaces": [
"a",
"b"

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