Compare commits

..

27 Commits

Author SHA1 Message Date
chloetedder
c236662fd8 Add "rush" workspace 2022-09-13 17:06:41 -05:00
Nathan Rajlich
cc7577a648 [cli] Use Builder importing logic from vc build in vc dev (#8485)
This makes `vc dev` utilize the same Builder installing and importing logic that `vc build` uses. So now the Builders will be installed locally on a per-project basis, rather than being installed to a shared global installation directory.
2022-09-13 21:35:01 +00:00
Nathan Rajlich
f3f3d7df5b [cli] Replace "0.0.0.0" with "localhost" in vc dev (#8547)
Instead of replacing "127.0.0.1" in `vc dev`, replace "0.0.0.0" when rendering the URL to access the `vc dev` server.

The thought here is that the IPv6 form is replacing the catch-all host name (`::`), but the IPv4 version is only replacing the explicit "127.0.0.1" version, so there's an inconsistency.

Considering the catch-all host names are not usually intended to be routable anyways, we will fix the inconsistency by only replacing the catch-all versions instead of localhost.

Also, since Node.js will default to binding to the catch-all address when not explicitly specifying a host, this replacement will only happen in that case. If the user is explicitly specifing a host to bind to (i.e. `vc dev -l 127.0.0.1:8080` or `vc dev -l tcp://[::1]:8080`) then it makes more sense to print explicitly what the user specified.
2022-09-13 18:38:42 +00:00
Steven
0bafea6d51 [tests] Fix tarball lookup with sha contains 0 (#8552)
This PR fixes an issue when the sha begins with `0` and causes [an error](https://vercel.com/vercel/vercel/EP7fVcXKsoodzWRy3fwG8AoeQcs6) when looking up the tarball:

> Error: ENOENT: no such file or directory, 
> copyfile '/vercel/path0/packages/build-utils/vercel-build-utils-v5.4.2-0251253.tgz' 
>  -> '/vercel/path0/public/tarballs/@vercel/build-utils.tgz'

The fix is to no longer rely on the exact tarball name because we can't guarantee the name from `yarn pack` and instead rely on a pattern for the tarball name.
2022-09-13 18:08:45 +00:00
Nathan Rajlich
5abb74eddd [cli] Use isStaticRuntime() helper function when importing Builders (#8551) 2022-09-13 12:40:06 +00:00
Steven
23d7eaccab [frameworks] Update framework logos to be file paths (#8546)
This removes the reliance on raw github hosting and instead relies on the Vercel deployment hosting the logo images.

Since we already have static files in each deployment (tarballs), it makes sense to start adding static images too.
2022-09-12 23:07:46 +00:00
Nathan Rajlich
2cb008e8ed [cli] Switch to npm and add more context to install errors during Builder import (#8545)
Before:

<img width="1012" alt="Screen Shot 2022-09-09 at 7 03 01 PM" src="https://user-images.githubusercontent.com/71256/189464732-8cf6398a-9432-423b-8509-a52bd714333e.png">

After:

<img width="579" alt="Screen Shot 2022-09-12 at 12 27 31 PM" src="https://user-images.githubusercontent.com/71256/189739091-86399428-d9b8-4d03-b0e6-7d27a1037bce.png">

This is a precursor to https://github.com/vercel/vercel/pull/8485, since the last remaining test failure there is related to specialized messaging we had for these same cases.
2022-09-12 22:05:38 +00:00
chloetedder
b5c3610113 Publish Stable
- vercel@28.2.5
 - @vercel/fs-detectors@3.2.0
2022-09-12 11:32:13 -05:00
chloetedder
f23c7fc4fc [fs-detectors] Add monorepo managers (#8534)
### Related Issues

Adding in Nx and Rush as monorepo managers.
This will allow to help with starting zero config for both the above managers.
I have added in unit tests for both Nx and Rush.

### 📋 Checklist

#### Tests

- [ ] The code changed/added as part of this PR has been covered with tests
- [ ] All tests pass locally with `yarn test-unit`

#### Code Review

- [ ] This PR has a concise title and thorough description useful to a reviewer
- [ ] Issue from task tracker has a link to this PR
2022-09-09 22:51:56 +00:00
Sean Massa
3dc1ad6437 [dev] consolidate dev server address parsing (#8538)
Consolidates parsing and access to `this.address` so that we don't have to `new URL(this.address)` all over the place.

---

Follow-up from: https://github.com/vercel/vercel/pull/8457#issuecomment-1238653904
2022-09-09 22:07:58 +00:00
github-actions[bot]
4dc0bef62b [examples] Upgrade Next.js to version 12.3.0 (#8537)
This auto-generated PR updates Next.js to version 12.3.0

Co-authored-by: Steven <steven@ceriously.com>
2022-09-09 17:41:41 -04:00
Sean Massa
8b3c52b9e8 Publish Stable
- vercel@28.2.4
 - @vercel/frameworks@1.1.5
 - @vercel/fs-detectors@3.1.0
 - @vercel/static-build@1.0.23
2022-09-09 16:28:36 -05:00
Sean Massa
fc74300ad0 [dev] fix middleware rewrites to relative paths that do not exist (#8535)
When using a `rewrite` in middleware to a relative path that does not exist, the logic gets confused and falls back to the original path.

This was caused by two changes that, in combination, caused this behavior.

1. `prevUrl` was created to keep track of route results that point to other routes, but falls back to `req.url` (`prevUrl`'s initial value): [#4033](40e4b69267 (diff-142c93a61d03a1718eb765cd25e5f18d07a95358bb27ce5d5d4da314ee2fa286R1283-R1284))
2. `prevUrl` was reassigned when handling middleware: [#7973](ee1211416f (diff-00ef6e7b63ed4cae298afc2a8c84f49247855a2506270f748e4d3e41da97ad99R1538))

Because `prevUrl` was reset back to `req.url` after the first `phase` (null) was run, the updated `prevUrl` value from middleware was lost. This only matters if the second `phase` ("filesystem") was going to be hit.

Further confusing matters, this was partially fixed by https://github.com/vercel/vercel/pull/8457 because it either returned a proxy pass (which doesn't have this problem) or assigned `req.url` to include the `rewritePath`, which meant that later when `prevUrl` would default to `req.url`, it still had come from `rewritePath`. So, this is fixed for the absolute URL case, but not the relative path case.

Given all that, I think the fix we need is to keep `prevUrl` at its current value when it's not being updated based on the `routeResult`.

---

So, I made that change here. I added a test that exercises this specific behavior.
2022-09-09 20:34:14 +00:00
Andrew Gadzik
28f8a38e00 [fs-detectors] Add the writeFile function to DetectorFilesystem (#8536)
Adds a `writeFile` function to `DetectorFilesystem` that will be used to update the various file cache maps.

**Why is this needed?**

When detecting npm7+ monorepos, we identified a performance improvement where the service can inspect the `package-lock.json` file for workspaces, and reuse the package information for each workspace in framework-detection.

The pseudo code in `vercel/api` will look something like this

For a given lockfile
```json
{
  ...,
  "packages": {
    "": {
      "name": "npm-workspaces",
      "version": "1.0.0",
      "license": "ISC",
      "workspaces": {
        "packages": [
          "apps/*"
        ]
      }
    },
    "apps/admin": {
      "version": "0.1.0",
      "dependencies": {
        "next": "12.2.5",
        "react": "18.2.0",
        "react-dom": "18.2.0"
      },
      "devDependencies": {
        "eslint": "8.23.0",
        "eslint-config-next": "12.2.5"
      }
    },
    ...,
}
```

```ts
// for each projectPath we detect in package-lock.json
// switch the cwd of the fs to the project directory
const projectFs = fs.chdir(projectPath);
// gets the package info from the lockfile
const projectPackageInfo = lockFile.packages[projectPath];
// insert this content into fs cache
await projectFs.writeFile('package.json', projectPackageInfo)
// call detectFramework, which should now have a cached "package.json" file 
const projectFramework = await detectFramework(projectFs);
```

### Related Issues

Related to https://linear.app/vercel/issue/HIT-57/monorepo-detection-api-prevent-rate-limits

### 📋 Checklist

<!--
  Please keep your PR as a Draft until the checklist is complete
-->

#### Tests

- [x] The code changed/added as part of this PR has been covered with tests
- [x] All tests pass locally with `yarn test-unit`

#### Code Review

- [x] This PR has a concise title and thorough description useful to a reviewer
- [x] Issue from task tracker has a link to this PR
2022-09-09 19:39:05 +00:00
Jacob Ford
c318ce9695 [frameworks] Detect Sanity v3 config (#8540)
Sanity v3 is currently in [developer preview](https://www.sanity.io/blog/sanity-studio-v3-developer-preview), and has deprecated `sanity.json` in the project root, replacing it with `sanity.config.js`. This should detect either.

All commands remain the same in both v2 and v3.

Co-authored-by: Steven <steven@ceriously.com>
2022-09-09 14:59:12 -04:00
Nathan Rajlich
5b36eaacff [cli] Poll the Dev Command server on both IPv4 and IPv6 in vc dev (#8542)
This change will allow the downstream Dev Command server be able to listen on either of `127.0.0.1` for IPv4 or `[::1]` for IPv6.

- Fixes #6639
- Fixes #8511
- Fixes #8121
- Closes #8512
- Closes #8384
2022-09-09 14:57:50 -04:00
Chris Barber
c9f7ca23a8 [tests] Skip tests that won't run on Windows due to 'mkdir -p' and symlinks (#8531)
Found a few tests that won't run on Windows. The project settings override test runs `mkdir -p` which errors. The other two build tests fail because they try to create symlinks.

#### Tests

- [x] The code changed/added as part of this PR has been covered with tests
- [x] All tests pass locally with `yarn test-unit`

#### Code Review

- [ ] This PR has a concise title and thorough description useful to a reviewer
- [ ] Issue from task tracker has a link to this PR
2022-09-08 14:26:30 +00:00
Sean Massa
57e0db0f65 [dev] allow middleware rewrites to change origin in vc dev (#8457)
Middleware rewrites in `vc dev` were not respecting changes to the origin. This PR implements that to match prodution.

---

Paired with: @TooTallNate
2022-09-07 20:30:10 +00:00
Steven
d5537500d8 Publish Stable
- @vercel/build-utils@5.4.2
 - vercel@28.2.3
 - @vercel/client@12.2.4
 - @vercel/frameworks@1.1.4
 - @vercel/fs-detectors@3.0.0
 - @vercel/go@2.2.5
 - @vercel/hydrogen@0.0.18
 - @vercel/next@3.1.25
 - @vercel/node@2.5.14
 - @vercel/python@3.1.14
 - @vercel/redwood@1.0.23
 - @vercel/remix@1.0.24
 - @vercel/ruby@1.3.31
 - @vercel/static-build@1.0.22
2022-09-07 15:39:47 -04:00
Andrew Gadzik
4b1736b2f2 [fs-detectors] optimize readdir for framework detection (#8497)
Adding the ability to explicitly set the `hasPath` and `isFile` caches via `readdir`

**Why is this needed?**

For framework detection, this allows us to fetch the contents of a directory (the root directory) of a git repo, and make assumptions about the existence of files,

```ts
import frameworks from "@vercel/frameworks";

// we can make the set of all file paths needed for framework detection like this
const setOfPaths = new Set(
  frameworks.frameworks
    .flatMap((f) => [
      ...(f.detectors?.every ?? []),
      ...(f.detectors?.some ?? []),
    ])
    .map((d) => d.path)
);

// then we can read the contents of the root directory of a git repo via the `DetectorFilesystem`
fs.readdir('./', { potentialFiles: [...setOfPaths] });

// The filesystem has been fully primed - any network calls from here will only happen if needed.
// This works because the logic of `detectFramework` calls `hasPath` and then `isFile` before 
// fetching file contents.  Since the filesystem knows this information, it doesn't have to make 
// any additional network calls 🙌 
const framework = detectFramework(fs);
```

### Related Issues

Related to [HIT-57](https://linear.app/vercel/issue/HIT-57/monorepo-detection-api-prevent-rate-limits)

### 📋 Checklist

<!--
  Please keep your PR as a Draft until the checklist is complete
-->

#### Tests

- [x] The code changed/added as part of this PR has been covered with tests
- [x] All tests pass locally with `yarn test-unit`

#### Code Review

- [x] This PR has a concise title and thorough description useful to a reviewer
- [x] Issue from task tracker has a link to this PR
2022-09-07 15:35:56 -04:00
Sean Massa
9da1c6fa66 [tests] set retry count to 0 when running tests locally (#8529)
When running tests locally that fail to make a fetch request, the retries add a lot of noise to debugging. This PR sets those retry counts to `0` locally, but keeps them at their current value for CI.
2022-09-07 18:47:09 +00:00
Jiachi Liu
a6c320846e [@vercel/next] Handle nextjs edge routes from app dir (#8524)
### Related Issues

Add handling for edge SSR in app dir, normalize the edge page routes
from app dir, like what we did for ones in `pages/`.

### 📋 Checklist

#### Tests

- [x] The code changed/added as part of this PR has been covered with
tests
- [x] All tests pass locally with `yarn test-unit`

#### Code Review

- [ ] This PR has a concise title and thorough description useful to a
reviewer
- [ ] Issue from task tracker has a link to this PR

Co-authored-by: JJ Kasper <jj@jjsweb.site>
2022-09-06 16:19:28 -07:00
Shu Uesugi
4973814978 [frameworks] Update Next.js Logos (#8505)
Update them to match the new logos. See: https://vercel.com/design/brands#next-js

<img width="869" alt="Screen Shot 2022-09-02 at 10 43 52 AM" src="https://user-images.githubusercontent.com/992008/188208956-aae10437-77ef-43c8-9bc1-c2499e509a7c.png">
2022-09-02 18:06:31 +00:00
Sean Massa
f1289ff263 [node] update middleware-no-response behavior to match production changes (#8500)
Production was updated to allow middleware without responses to pass through. This PR makes `vc dev` behave the same way. Tests were updated.
2022-09-01 22:19:10 +00:00
Steven
3ff93279cd Publish Stable
- vercel@28.2.2
 - @vercel/next@3.1.24
 - @vercel/node@2.5.13
 - @vercel/redwood@1.0.22
 - @vercel/remix@1.0.23
2022-09-01 16:42:27 -04:00
Steven
58f9d649a8 [next][node][remix][redwood] Bump @vercel/nft@0.22.1 (#8502)
Bump `@vercel/nft` to version [0.22.1](https://github.com/vercel/nft/releases/tag/0.22.1)
2022-09-01 16:41:30 -04:00
JJ Kasper
cadc082ad1 [next] Fix index app dir case (#8501)
### Related Issues

This ensures we properly normalize the `/` case from the `app-path-routes-manifest` as the outputs expect this to be normalized to `index`. 

### 📋 Checklist

<!--
  Please keep your PR as a Draft until the checklist is complete
-->

#### Tests

- [ ] The code changed/added as part of this PR has been covered with tests
- [ ] All tests pass locally with `yarn test-unit`

#### Code Review

- [ ] This PR has a concise title and thorough description useful to a reviewer
- [ ] Issue from task tracker has a link to this PR
2022-09-01 12:06:18 -07:00
76 changed files with 1127 additions and 1239 deletions

View File

@@ -1,6 +1,5 @@
import fs from 'fs/promises';
import { join, dirname } from 'path';
import execa from 'execa';
import { getExampleList } from '../examples/example-list';
import { mapOldToNew } from '../examples/map-old-to-new';
@@ -13,6 +12,12 @@ async function main() {
await fs.rm(pubDir, { recursive: true, force: true });
await fs.mkdir(pubDir);
await fs.cp(
join(repoRoot, 'packages', 'frameworks', 'logos'),
join(pubDir, 'framework-logos'),
{ recursive: true, force: true }
);
const examples = await getExampleList();
const pathListAll = join(pubDir, 'list-all.json');
await fs.writeFile(pathListAll, JSON.stringify(examples));
@@ -41,10 +46,6 @@ async function main() {
JSON.stringify([...existingExamples, ...oldExamples])
);
const { stdout: sha } = await execa('git', ['rev-parse', '--short', 'HEAD'], {
cwd: repoRoot,
});
const tarballsDir = join(pubDir, 'tarballs');
const packagesDir = join(repoRoot, 'packages');
const packages = await fs.readdir(packagesDir);
@@ -55,12 +56,21 @@ async function main() {
'utf-8'
);
const packageJson = JSON.parse(packageJsonRaw);
const tarballName = `${packageJson.name
.replace('@', '')
.replace('/', '-')}-v${packageJson.version}-${sha.trim()}.tgz`;
const files = await fs.readdir(fullDir);
const tarballName = files.find(f => /^vercel-.+\.tgz$/.test(f));
if (!tarballName) {
throw new Error(
`Expected vercel-*.tgz in ${fullDir} but found ${JSON.stringify(
files,
null,
2
)}`
);
}
const srcTarballPath = join(fullDir, tarballName);
const destTarballPath = join(tarballsDir, `${packageJson.name}.tgz`);
await fs.mkdir(dirname(destTarballPath), { recursive: true });
await fs.copyFile(join(fullDir, tarballName), destTarballPath);
await fs.copyFile(srcTarballPath, destTarballPath);
}
console.log('Completed building static frontend.');

View File

@@ -16,10 +16,6 @@ const frameworks = (_frameworks as Framework[])
defaultRoutes: undefined,
};
if (framework.logo) {
framework.logo = `https://assets.vercel.com/zeit-inc/image/fetch/${framework.logo}`;
}
return framework;
});

View File

@@ -9,12 +9,12 @@
"lint": "next lint"
},
"dependencies": {
"next": "12.2.5",
"next": "12.3.0",
"react": "18.2.0",
"react-dom": "18.2.0"
},
"devDependencies": {
"eslint": "8.22.0",
"eslint-config-next": "12.2.5"
"eslint": "8.23.0",
"eslint-config-next": "12.3.0"
}
}

View File

@@ -3,28 +3,28 @@
"@babel/runtime-corejs3@^7.10.2":
version "7.18.9"
resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.18.9.tgz#7bacecd1cb2dd694eacd32a91fcf7021c20770ae"
integrity sha512-qZEWeccZCrHA2Au4/X05QW5CMdm4VjUDCrGq5gf1ZDcM4hRqreKrtwAn7yci9zfgAS9apvnsFXiGBHBAxZdK9A==
version "7.19.0"
resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.19.0.tgz#0df75cb8e5ecba3ca9e658898694e5326d52397f"
integrity sha512-JyXXoCu1N8GLuKc2ii8y5RGma5FMpFeO2nAQIe0Yzrbq+rQnN+sFj47auLblR5ka6aHNGPDgv8G/iI2Grb0ldQ==
dependencies:
core-js-pure "^3.20.2"
regenerator-runtime "^0.13.4"
"@babel/runtime@^7.10.2", "@babel/runtime@^7.18.9":
version "7.18.9"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.18.9.tgz#b4fcfce55db3d2e5e080d2490f608a3b9f407f4a"
integrity sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw==
version "7.19.0"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.19.0.tgz#22b11c037b094d27a8a2504ea4dcff00f50e2259"
integrity sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA==
dependencies:
regenerator-runtime "^0.13.4"
"@eslint/eslintrc@^1.3.0":
version "1.3.0"
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.3.0.tgz#29f92c30bb3e771e4a2048c95fa6855392dfac4f"
integrity sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==
"@eslint/eslintrc@^1.3.1":
version "1.3.1"
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.3.1.tgz#de0807bfeffc37b964a7d0400e0c348ce5a2543d"
integrity sha512-OhSY22oQQdw3zgPOOwdoj01l/Dzl1Z+xyUP33tkSN+aqyEhymJCcPHyXt+ylW8FSe0TfRC2VG+ROQOapD0aZSQ==
dependencies:
ajv "^6.12.4"
debug "^4.3.2"
espree "^9.3.2"
espree "^9.4.0"
globals "^13.15.0"
ignore "^5.2.0"
import-fresh "^3.2.1"
@@ -46,87 +46,92 @@
resolved "https://registry.yarnpkg.com/@humanwhocodes/gitignore-to-minimatch/-/gitignore-to-minimatch-1.0.2.tgz#316b0a63b91c10e53f242efb4ace5c3b34e8728d"
integrity sha512-rSqmMJDdLFUsyxR6FMtD00nfQKKLFb1kv+qBbOVKqErvloEIJLo5bDTJTQNTYgeyp78JsA7u/NPi5jT1GR/MuA==
"@humanwhocodes/module-importer@^1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c"
integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==
"@humanwhocodes/object-schema@^1.2.1":
version "1.2.1"
resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45"
integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==
"@next/env@12.2.5":
version "12.2.5"
resolved "https://registry.yarnpkg.com/@next/env/-/env-12.2.5.tgz#d908c57b35262b94db3e431e869b72ac3e1ad3e3"
integrity sha512-vLPLV3cpPGjUPT3PjgRj7e3nio9t6USkuew3JE/jMeon/9Mvp1WyR18v3iwnCuX7eUAm1HmAbJHHLAbcu/EJcw==
"@next/env@12.3.0":
version "12.3.0"
resolved "https://registry.yarnpkg.com/@next/env/-/env-12.3.0.tgz#85f971fdc668cc312342761057c59cb8ab1abadf"
integrity sha512-PTJpjAFVbzBQ9xXpzMTroShvD5YDIIy46jQ7d4LrWpY+/5a8H90Tm8hE3Hvkc5RBRspVo7kvEOnqQms0A+2Q6w==
"@next/eslint-plugin-next@12.2.5":
version "12.2.5"
resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-12.2.5.tgz#4f3acccd2ed4f9300fbf9fd480cc8a0b261889a8"
integrity sha512-VBjVbmqEzGiOTBq4+wpeVXt/KgknnGB6ahvC/AxiIGnN93/RCSyXhFRI4uSfftM2Ba3w7ZO7076bfKasZsA0fw==
"@next/eslint-plugin-next@12.3.0":
version "12.3.0"
resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-12.3.0.tgz#302c1f03618d5001ce92ea6826c329268759128e"
integrity sha512-jVdq1qYTNDjUtulnE8/hkPv0pHILV4jMg5La99iaY/FFm20WxVnsAZtbNnMvlPbf8dc010oO304SX9yXbg5PAw==
dependencies:
glob "7.1.7"
"@next/swc-android-arm-eabi@12.2.5":
version "12.2.5"
resolved "https://registry.yarnpkg.com/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.2.5.tgz#903a5479ab4c2705d9c08d080907475f7bacf94d"
integrity sha512-cPWClKxGhgn2dLWnspW+7psl3MoLQUcNqJqOHk2BhNcou9ARDtC0IjQkKe5qcn9qg7I7U83Gp1yh2aesZfZJMA==
"@next/swc-android-arm-eabi@12.3.0":
version "12.3.0"
resolved "https://registry.yarnpkg.com/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.3.0.tgz#9a934904643591cb6f66eb09803a92d2b10ada13"
integrity sha512-/PuirPnAKsYBw93w/7Q9hqy+KGOU9mjYprZ/faxMUJh/dc6v3rYLxkZKNG9nFPIW4QKNTCnhP40xF9hLnxO+xg==
"@next/swc-android-arm64@12.2.5":
version "12.2.5"
resolved "https://registry.yarnpkg.com/@next/swc-android-arm64/-/swc-android-arm64-12.2.5.tgz#2f9a98ec4166c7860510963b31bda1f57a77c792"
integrity sha512-vMj0efliXmC5b7p+wfcQCX0AfU8IypjkzT64GiKJD9PgiA3IILNiGJr1fw2lyUDHkjeWx/5HMlMEpLnTsQslwg==
"@next/swc-android-arm64@12.3.0":
version "12.3.0"
resolved "https://registry.yarnpkg.com/@next/swc-android-arm64/-/swc-android-arm64-12.3.0.tgz#c1e3e24d0625efe88f45a2135c8f5c4dff594749"
integrity sha512-OaI+FhAM6P9B6Ybwbn0Zl8YwWido0lLwhDBi9WiYCh4RQmIXAyVIoIJPHo4fP05+mXaJ/k1trvDvuURvHOq2qw==
"@next/swc-darwin-arm64@12.2.5":
version "12.2.5"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.2.5.tgz#31b1c3c659d54be546120c488a1e1bad21c24a1d"
integrity sha512-VOPWbO5EFr6snla/WcxUKtvzGVShfs302TEMOtzYyWni6f9zuOetijJvVh9CCTzInnXAZMtHyNhefijA4HMYLg==
"@next/swc-darwin-arm64@12.3.0":
version "12.3.0"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.3.0.tgz#37a9f971b9ad620184af69f38243a36757126fb9"
integrity sha512-9s4d3Mhii+WFce8o8Jok7WC3Bawkr9wEUU++SJRptjU1L5tsfYJMrSYCACHLhZujziNDLyExe4Hwwsccps1sfg==
"@next/swc-darwin-x64@12.2.5":
version "12.2.5"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-12.2.5.tgz#2e44dd82b2b7fef88238d1bc4d3bead5884cedfd"
integrity sha512-5o8bTCgAmtYOgauO/Xd27vW52G2/m3i5PX7MUYePquxXAnX73AAtqA3WgPXBRitEB60plSKZgOTkcpqrsh546A==
"@next/swc-darwin-x64@12.3.0":
version "12.3.0"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-12.3.0.tgz#fb017f1066c8cf2b8da49ef3588c8731d8bf1bf3"
integrity sha512-2scC4MqUTwGwok+wpVxP+zWp7WcCAVOtutki2E1n99rBOTnUOX6qXkgxSy083yBN6GqwuC/dzHeN7hIKjavfRA==
"@next/swc-freebsd-x64@12.2.5":
version "12.2.5"
resolved "https://registry.yarnpkg.com/@next/swc-freebsd-x64/-/swc-freebsd-x64-12.2.5.tgz#e24e75d8c2581bfebc75e4f08f6ddbd116ce9dbd"
integrity sha512-yYUbyup1JnznMtEBRkK4LT56N0lfK5qNTzr6/DEyDw5TbFVwnuy2hhLBzwCBkScFVjpFdfiC6SQAX3FrAZzuuw==
"@next/swc-freebsd-x64@12.3.0":
version "12.3.0"
resolved "https://registry.yarnpkg.com/@next/swc-freebsd-x64/-/swc-freebsd-x64-12.3.0.tgz#e7955b016f41e0f95088e3459ff4197027871fbf"
integrity sha512-xAlruUREij/bFa+qsE1tmsP28t7vz02N4ZDHt2lh3uJUniE0Ne9idyIDLc1Ed0IF2RjfgOp4ZVunuS3OM0sngw==
"@next/swc-linux-arm-gnueabihf@12.2.5":
version "12.2.5"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.2.5.tgz#46d8c514d834d2b5f67086013f0bd5e3081e10b9"
integrity sha512-2ZE2/G921Acks7UopJZVMgKLdm4vN4U0yuzvAMJ6KBavPzqESA2yHJlm85TV/K9gIjKhSk5BVtauIUntFRP8cg==
"@next/swc-linux-arm-gnueabihf@12.3.0":
version "12.3.0"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.3.0.tgz#d2233267bffaa24378245b328f2f8a01a37eab29"
integrity sha512-jin2S4VT/cugc2dSZEUIabhYDJNgrUh7fufbdsaAezgcQzqfdfJqfxl4E9GuafzB4cbRPTaqA0V5uqbp0IyGkQ==
"@next/swc-linux-arm64-gnu@12.2.5":
version "12.2.5"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.2.5.tgz#91f725ac217d3a1f4f9f53b553615ba582fd3d9f"
integrity sha512-/I6+PWVlz2wkTdWqhlSYYJ1pWWgUVva6SgX353oqTh8njNQp1SdFQuWDqk8LnM6ulheVfSsgkDzxrDaAQZnzjQ==
"@next/swc-linux-arm64-gnu@12.3.0":
version "12.3.0"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.3.0.tgz#149a0cb877352ab63e81cf1dd53b37f382929d2a"
integrity sha512-RqJHDKe0WImeUrdR0kayTkRWgp4vD/MS7g0r6Xuf8+ellOFH7JAAJffDW3ayuVZeMYOa7RvgNFcOoWnrTUl9Nw==
"@next/swc-linux-arm64-musl@12.2.5":
version "12.2.5"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.2.5.tgz#e627e8c867920995810250303cd9b8e963598383"
integrity sha512-LPQRelfX6asXyVr59p5sTpx5l+0yh2Vjp/R8Wi4X9pnqcayqT4CUJLiHqCvZuLin3IsFdisJL0rKHMoaZLRfmg==
"@next/swc-linux-arm64-musl@12.3.0":
version "12.3.0"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.3.0.tgz#73ec7f121f56fd7cf99cf2b00cf41f62c4560e90"
integrity sha512-nvNWoUieMjvDjpYJ/4SQe9lQs2xMj6ZRs8N+bmTrVu9leY2Fg3WD6W9p/1uU9hGO8u+OdF13wc4iRShu/WYIHg==
"@next/swc-linux-x64-gnu@12.2.5":
version "12.2.5"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.2.5.tgz#83a5e224fbc4d119ef2e0f29d0d79c40cc43887e"
integrity sha512-0szyAo8jMCClkjNK0hknjhmAngUppoRekW6OAezbEYwHXN/VNtsXbfzgYOqjKWxEx3OoAzrT3jLwAF0HdX2MEw==
"@next/swc-linux-x64-gnu@12.3.0":
version "12.3.0"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.3.0.tgz#6812e52ef21bfd091810f271dd61da11d82b66b9"
integrity sha512-4ajhIuVU9PeQCMMhdDgZTLrHmjbOUFuIyg6J19hZqwEwDTSqQyrSLkbJs2Nd7IRiM6Ul/XyrtEFCpk4k+xD2+w==
"@next/swc-linux-x64-musl@12.2.5":
version "12.2.5"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.2.5.tgz#be700d48471baac1ec2e9539396625584a317e95"
integrity sha512-zg/Y6oBar1yVnW6Il1I/08/2ukWtOG6s3acdJdEyIdsCzyQi4RLxbbhkD/EGQyhqBvd3QrC6ZXQEXighQUAZ0g==
"@next/swc-linux-x64-musl@12.3.0":
version "12.3.0"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.3.0.tgz#c9e7ffb6d44da330961c1ce651c5b03a1becfe22"
integrity sha512-U092RBYbaGxoMAwpauePJEu2PuZSEoUCGJBvsptQr2/2XIMwAJDYM4c/M5NfYEsBr+yjvsYNsOpYfeQ88D82Yg==
"@next/swc-win32-arm64-msvc@12.2.5":
version "12.2.5"
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.2.5.tgz#a93e958133ad3310373fda33a79aa10af2a0aa97"
integrity sha512-3/90DRNSqeeSRMMEhj4gHHQlLhhKg5SCCoYfE3kBjGpE63EfnblYUqsszGGZ9ekpKL/R4/SGB40iCQr8tR5Jiw==
"@next/swc-win32-arm64-msvc@12.3.0":
version "12.3.0"
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.3.0.tgz#e0d9d26297f52b0d3b3c2f5138ddcce30601bc98"
integrity sha512-pzSzaxjDEJe67bUok9Nxf9rykbJfHXW0owICFsPBsqHyc+cr8vpF7g9e2APTCddtVhvjkga9ILoZJ9NxWS7Yiw==
"@next/swc-win32-ia32-msvc@12.2.5":
version "12.2.5"
resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.2.5.tgz#4f5f7ba0a98ff89a883625d4af0125baed8b2e19"
integrity sha512-hGLc0ZRAwnaPL4ulwpp4D2RxmkHQLuI8CFOEEHdzZpS63/hMVzv81g8jzYA0UXbb9pus/iTc3VRbVbAM03SRrw==
"@next/swc-win32-ia32-msvc@12.3.0":
version "12.3.0"
resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.3.0.tgz#37daeac1acc68537b8e76cd81fde96dce11f78b4"
integrity sha512-MQGUpMbYhQmTZ06a9e0hPQJnxFMwETo2WtyAotY3GEzbNCQVbCGhsvqEKcl+ZEHgShlHXUWvSffq1ZscY6gK7A==
"@next/swc-win32-x64-msvc@12.2.5":
version "12.2.5"
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.2.5.tgz#20fed129b04a0d3f632c6d0de135345bb623b1e4"
integrity sha512-7h5/ahY7NeaO2xygqVrSG/Y8Vs4cdjxIjowTZ5W6CKoTKn7tmnuxlUc2h74x06FKmbhAd9agOjr/AOKyxYYm9Q==
"@next/swc-win32-x64-msvc@12.3.0":
version "12.3.0"
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.3.0.tgz#c1b983316307f8f55fee491942b5d244bd2036e2"
integrity sha512-C/nw6OgQpEULWqs+wgMHXGvlJLguPRFFGqR2TAqWBerQ8J+Sg3z1ZTqwelkSi4FoqStGuZ2UdFHIDN1ySmR1xA==
"@nodelib/fs.scandir@2.1.5":
version "2.1.5"
@@ -154,10 +159,10 @@
resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.1.4.tgz#0c8b74c50f29ee44f423f7416829c0bf8bb5eb27"
integrity sha512-LwzQKA4vzIct1zNZzBmRKI9QuNpLgTQMEjsQLf3BXuGYb3QPTP4Yjf6mkdX+X1mYttZ808QpOwAzZjv28kq7DA==
"@swc/helpers@0.4.3":
version "0.4.3"
resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.4.3.tgz#16593dfc248c53b699d4b5026040f88ddb497012"
integrity sha512-6JrF+fdUK2zbGpJIlN7G3v966PQjyx/dPt1T9km2wj+EUBqgrxCk3uX4Kct16MIm9gGxfKRcfax2hVf5jvlTzA==
"@swc/helpers@0.4.11":
version "0.4.11"
resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.4.11.tgz#db23a376761b3d31c26502122f349a21b592c8de"
integrity sha512-rEUrBSGIoSFuYxwBYtlUFMlE2CwGhmW+w9355/5oduSw8e5h2+Tj4UrAGNNgP9915++wj5vkQo0UuOBqOAq4nw==
dependencies:
tslib "^2.4.0"
@@ -167,47 +172,47 @@
integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==
"@typescript-eslint/parser@^5.21.0":
version "5.34.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.34.0.tgz#ca710858ea85dbfd30c9b416a335dc49e82dbc07"
integrity sha512-SZ3NEnK4usd2CXkoV3jPa/vo1mWX1fqRyIVUQZR4As1vyp4fneknBNJj+OFtV8WAVgGf+rOHMSqQbs2Qn3nFZQ==
version "5.36.2"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.36.2.tgz#3ddf323d3ac85a25295a55fcb9c7a49ab4680ddd"
integrity sha512-qS/Kb0yzy8sR0idFspI9Z6+t7mqk/oRjnAYfewG+VN73opAUvmYL3oPIMmgOX6CnQS6gmVIXGshlb5RY/R22pA==
dependencies:
"@typescript-eslint/scope-manager" "5.34.0"
"@typescript-eslint/types" "5.34.0"
"@typescript-eslint/typescript-estree" "5.34.0"
"@typescript-eslint/scope-manager" "5.36.2"
"@typescript-eslint/types" "5.36.2"
"@typescript-eslint/typescript-estree" "5.36.2"
debug "^4.3.4"
"@typescript-eslint/scope-manager@5.34.0":
version "5.34.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.34.0.tgz#14efd13dc57602937e25f188fd911f118781e527"
integrity sha512-HNvASMQlah5RsBW6L6c7IJ0vsm+8Sope/wu5sEAf7joJYWNb1LDbJipzmdhdUOnfrDFE6LR1j57x1EYVxrY4ow==
"@typescript-eslint/scope-manager@5.36.2":
version "5.36.2"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.36.2.tgz#a75eb588a3879ae659514780831370642505d1cd"
integrity sha512-cNNP51L8SkIFSfce8B1NSUBTJTu2Ts4nWeWbFrdaqjmn9yKrAaJUBHkyTZc0cL06OFHpb+JZq5AUHROS398Orw==
dependencies:
"@typescript-eslint/types" "5.34.0"
"@typescript-eslint/visitor-keys" "5.34.0"
"@typescript-eslint/types" "5.36.2"
"@typescript-eslint/visitor-keys" "5.36.2"
"@typescript-eslint/types@5.34.0":
version "5.34.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.34.0.tgz#217bf08049e9e7b86694d982e88a2c1566330c78"
integrity sha512-49fm3xbbUPuzBIOcy2CDpYWqy/X7VBkxVN+DC21e0zIm3+61Z0NZi6J9mqPmSW1BDVk9FIOvuCFyUPjXz93sjA==
"@typescript-eslint/types@5.36.2":
version "5.36.2"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.36.2.tgz#a5066e500ebcfcee36694186ccc57b955c05faf9"
integrity sha512-9OJSvvwuF1L5eS2EQgFUbECb99F0mwq501w0H0EkYULkhFa19Qq7WFbycdw1PexAc929asupbZcgjVIe6OK/XQ==
"@typescript-eslint/typescript-estree@5.34.0":
version "5.34.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.34.0.tgz#ba7b83f4bf8ccbabf074bbf1baca7a58de3ccb9a"
integrity sha512-mXHAqapJJDVzxauEkfJI96j3D10sd567LlqroyCeJaHnu42sDbjxotGb3XFtGPYKPD9IyLjhsoULML1oI3M86A==
"@typescript-eslint/typescript-estree@5.36.2":
version "5.36.2"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.36.2.tgz#0c93418b36c53ba0bc34c61fe9405c4d1d8fe560"
integrity sha512-8fyH+RfbKc0mTspfuEjlfqA4YywcwQK2Amcf6TDOwaRLg7Vwdu4bZzyvBZp4bjt1RRjQ5MDnOZahxMrt2l5v9w==
dependencies:
"@typescript-eslint/types" "5.34.0"
"@typescript-eslint/visitor-keys" "5.34.0"
"@typescript-eslint/types" "5.36.2"
"@typescript-eslint/visitor-keys" "5.36.2"
debug "^4.3.4"
globby "^11.1.0"
is-glob "^4.0.3"
semver "^7.3.7"
tsutils "^3.21.0"
"@typescript-eslint/visitor-keys@5.34.0":
version "5.34.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.34.0.tgz#d0fb3e31033e82ddd5de048371ad39eb342b2d40"
integrity sha512-O1moYjOSrab0a2fUvFpsJe0QHtvTC+cR+ovYpgKrAVXzqQyc74mv76TgY6z+aEtjQE2vgZux3CQVtGryqdcOAw==
"@typescript-eslint/visitor-keys@5.36.2":
version "5.36.2"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.36.2.tgz#2f8f78da0a3bad3320d2ac24965791ac39dace5a"
integrity sha512-BtRvSR6dEdrNt7Net2/XDjbYKU5Ml6GqJgVfXT0CxTCJlnIqK7rAGreuWKMT2t8cFUT2Msv5oxw0GMRD7T5J7A==
dependencies:
"@typescript-eslint/types" "5.34.0"
"@typescript-eslint/types" "5.36.2"
eslint-visitor-keys "^3.3.0"
acorn-jsx@^5.3.2:
@@ -340,9 +345,9 @@ callsites@^3.0.0:
integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
caniuse-lite@^1.0.30001332:
version "1.0.30001382"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001382.tgz#4d37f0d0b6fffb826c8e5e1c0f4bf8ce592db949"
integrity sha512-2rtJwDmSZ716Pxm1wCtbPvHtbDWAreTPxXbkc5RkKglow3Ig/4GNGazDI9/BVnXbG/wnv6r3B5FEbkfg9OcTGg==
version "1.0.30001393"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001393.tgz#1aa161e24fe6af2e2ccda000fc2b94be0b0db356"
integrity sha512-N/od11RX+Gsk+1qY/jbPa0R6zJupEa0lxeBG598EbrtblxVCTJsQwbRBm6+V+rxpc5lHKdsXb9RY83cZIPLseA==
chalk@^4.0.0:
version "4.1.2"
@@ -370,9 +375,9 @@ concat-map@0.0.1:
integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
core-js-pure@^3.20.2:
version "3.24.1"
resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.24.1.tgz#8839dde5da545521bf282feb7dc6d0b425f39fd3"
integrity sha512-r1nJk41QLLPyozHUUPmILCEMtMw24NG4oWK6RbsDdjzQgg9ZvrUsPBj1MnG0wXXp1DCDU6j+wUvEmBSrtRbLXg==
version "3.25.1"
resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.25.1.tgz#79546518ae87cc362c991d9c2d211f45107991ee"
integrity sha512-7Fr74bliUDdeJCBMxkkIuQ4xfxn/SwrVg+HkJUAoNEXVqYLv55l6Af0dJ5Lq2YBUW9yKqSkLXaS5SYPK6MGa/A==
cross-spawn@^7.0.2:
version "7.0.3"
@@ -449,15 +454,15 @@ emoji-regex@^9.2.2:
integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==
es-abstract@^1.19.0, es-abstract@^1.19.1, es-abstract@^1.19.2, es-abstract@^1.19.5:
version "1.20.1"
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.20.1.tgz#027292cd6ef44bd12b1913b828116f54787d1814"
integrity sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==
version "1.20.2"
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.20.2.tgz#8495a07bc56d342a3b8ea3ab01bd986700c2ccb3"
integrity sha512-XxXQuVNrySBNlEkTYJoDNFe5+s2yIOpzq80sUHEdPdQr0S5nTLz4ZPPPswNIpKseDDUS5yghX1gfLIHQZ1iNuQ==
dependencies:
call-bind "^1.0.2"
es-to-primitive "^1.2.1"
function-bind "^1.1.1"
function.prototype.name "^1.1.5"
get-intrinsic "^1.1.1"
get-intrinsic "^1.1.2"
get-symbol-description "^1.0.0"
has "^1.0.3"
has-property-descriptors "^1.0.0"
@@ -469,9 +474,9 @@ es-abstract@^1.19.0, es-abstract@^1.19.1, es-abstract@^1.19.2, es-abstract@^1.19
is-shared-array-buffer "^1.0.2"
is-string "^1.0.7"
is-weakref "^1.0.2"
object-inspect "^1.12.0"
object-inspect "^1.12.2"
object-keys "^1.1.1"
object.assign "^4.1.2"
object.assign "^4.1.4"
regexp.prototype.flags "^1.4.3"
string.prototype.trimend "^1.0.5"
string.prototype.trimstart "^1.0.5"
@@ -498,12 +503,12 @@ escape-string-regexp@^4.0.0:
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
eslint-config-next@12.2.5:
version "12.2.5"
resolved "https://registry.yarnpkg.com/eslint-config-next/-/eslint-config-next-12.2.5.tgz#76ce83f18cc02f6f42ed407a127f83db54fabd3c"
integrity sha512-SOowilkqPzW6DxKp3a3SYlrfPi5Ajs9MIzp9gVfUDxxH9QFM5ElkR1hX5m/iICJuvCbWgQqFBiA3mCMozluniw==
eslint-config-next@12.3.0:
version "12.3.0"
resolved "https://registry.yarnpkg.com/eslint-config-next/-/eslint-config-next-12.3.0.tgz#d887ab2d143fe1a2b308e9321e932a613e610800"
integrity sha512-guHSkNyKnTBB8HU35COgAMeMV0E026BiYRYvyEVVaTOeFcnU3i1EI8/Da0Rl7H3Sgua5FEvoA0vYd2s8kdIUXg==
dependencies:
"@next/eslint-plugin-next" "12.2.5"
"@next/eslint-plugin-next" "12.3.0"
"@rushstack/eslint-patch" "^1.1.3"
"@typescript-eslint/parser" "^5.21.0"
eslint-import-resolver-node "^0.3.6"
@@ -583,9 +588,9 @@ eslint-plugin-react-hooks@^4.5.0:
integrity sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==
eslint-plugin-react@^7.29.4:
version "7.30.1"
resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.30.1.tgz#2be4ab23ce09b5949c6631413ba64b2810fd3e22"
integrity sha512-NbEvI9jtqO46yJA3wcRF9Mo0lF9T/jhdHqhCHXiXtD+Zcb98812wvokjWpU7Q4QH5edo6dmqrukxVvWWXHlsUg==
version "7.31.7"
resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.31.7.tgz#36fb1c611a7db5f757fce09cbbcc01682f8b0fbb"
integrity sha512-8NldBTeYp/kQoTV1uT0XF6HcmDqbgZ0lNPkN0wlRw8DJKXEnaWu+oh/6gt3xIhzvQ35wB2Y545fJhIbJSZ2NNw==
dependencies:
array-includes "^3.1.5"
array.prototype.flatmap "^1.3.0"
@@ -627,14 +632,15 @@ eslint-visitor-keys@^3.3.0:
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826"
integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==
eslint@8.22.0:
version "8.22.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.22.0.tgz#78fcb044196dfa7eef30a9d65944f6f980402c48"
integrity sha512-ci4t0sz6vSRKdmkOGmprBo6fmI4PrphDFMy5JEq/fNS0gQkJM3rLmrqcp8ipMcdobH3KtUP40KniAE9W19S4wA==
eslint@8.23.0:
version "8.23.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.23.0.tgz#a184918d288820179c6041bb3ddcc99ce6eea040"
integrity sha512-pBG/XOn0MsJcKcTRLr27S5HpzQo4kLr+HjLQIyK4EiCsijDl/TB+h5uEuJU6bQ8Edvwz1XWOjpaP2qgnXGpTcA==
dependencies:
"@eslint/eslintrc" "^1.3.0"
"@eslint/eslintrc" "^1.3.1"
"@humanwhocodes/config-array" "^0.10.4"
"@humanwhocodes/gitignore-to-minimatch" "^1.0.2"
"@humanwhocodes/module-importer" "^1.0.1"
ajv "^6.10.0"
chalk "^4.0.0"
cross-spawn "^7.0.2"
@@ -644,7 +650,7 @@ eslint@8.22.0:
eslint-scope "^7.1.1"
eslint-utils "^3.0.0"
eslint-visitor-keys "^3.3.0"
espree "^9.3.3"
espree "^9.4.0"
esquery "^1.4.0"
esutils "^2.0.2"
fast-deep-equal "^3.1.3"
@@ -670,12 +676,11 @@ eslint@8.22.0:
strip-ansi "^6.0.1"
strip-json-comments "^3.1.0"
text-table "^0.2.0"
v8-compile-cache "^2.0.3"
espree@^9.3.2, espree@^9.3.3:
version "9.3.3"
resolved "https://registry.yarnpkg.com/espree/-/espree-9.3.3.tgz#2dd37c4162bb05f433ad3c1a52ddf8a49dc08e9d"
integrity sha512-ORs1Rt/uQTqUKjDdGCyrtYxbazf5umATSf/K4qxjmZHORR6HJk+2s/2Pqe+Kk49HHINC/xNIrGfgh8sZcll0ng==
espree@^9.4.0:
version "9.4.0"
resolved "https://registry.yarnpkg.com/espree/-/espree-9.4.0.tgz#cd4bc3d6e9336c433265fc0aa016fc1aaf182f8a"
integrity sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==
dependencies:
acorn "^8.8.0"
acorn-jsx "^5.3.2"
@@ -803,7 +808,7 @@ functions-have-names@^1.2.2:
resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834"
integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==
get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1:
get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1, get-intrinsic@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.2.tgz#336975123e05ad0b7ba41f152ee4aadbea6cf598"
integrity sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==
@@ -1195,38 +1200,38 @@ natural-compare@^1.4.0:
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==
next@12.2.5:
version "12.2.5"
resolved "https://registry.yarnpkg.com/next/-/next-12.2.5.tgz#14fb5975e8841fad09553b8ef41fe1393602b717"
integrity sha512-tBdjqX5XC/oFs/6gxrZhjmiq90YWizUYU6qOWAfat7zJwrwapJ+BYgX2PmiacunXMaRpeVT4vz5MSPSLgNkrpA==
next@12.3.0:
version "12.3.0"
resolved "https://registry.yarnpkg.com/next/-/next-12.3.0.tgz#0e4c1ed0092544c7e8f4c998ca57cf6529e286cb"
integrity sha512-GpzI6me9V1+XYtfK0Ae9WD0mKqHyzQlGq1xH1rzNIYMASo4Tkl4rTe9jSqtBpXFhOS33KohXs9ZY38Akkhdciw==
dependencies:
"@next/env" "12.2.5"
"@swc/helpers" "0.4.3"
"@next/env" "12.3.0"
"@swc/helpers" "0.4.11"
caniuse-lite "^1.0.30001332"
postcss "8.4.14"
styled-jsx "5.0.4"
styled-jsx "5.0.6"
use-sync-external-store "1.2.0"
optionalDependencies:
"@next/swc-android-arm-eabi" "12.2.5"
"@next/swc-android-arm64" "12.2.5"
"@next/swc-darwin-arm64" "12.2.5"
"@next/swc-darwin-x64" "12.2.5"
"@next/swc-freebsd-x64" "12.2.5"
"@next/swc-linux-arm-gnueabihf" "12.2.5"
"@next/swc-linux-arm64-gnu" "12.2.5"
"@next/swc-linux-arm64-musl" "12.2.5"
"@next/swc-linux-x64-gnu" "12.2.5"
"@next/swc-linux-x64-musl" "12.2.5"
"@next/swc-win32-arm64-msvc" "12.2.5"
"@next/swc-win32-ia32-msvc" "12.2.5"
"@next/swc-win32-x64-msvc" "12.2.5"
"@next/swc-android-arm-eabi" "12.3.0"
"@next/swc-android-arm64" "12.3.0"
"@next/swc-darwin-arm64" "12.3.0"
"@next/swc-darwin-x64" "12.3.0"
"@next/swc-freebsd-x64" "12.3.0"
"@next/swc-linux-arm-gnueabihf" "12.3.0"
"@next/swc-linux-arm64-gnu" "12.3.0"
"@next/swc-linux-arm64-musl" "12.3.0"
"@next/swc-linux-x64-gnu" "12.3.0"
"@next/swc-linux-x64-musl" "12.3.0"
"@next/swc-win32-arm64-msvc" "12.3.0"
"@next/swc-win32-ia32-msvc" "12.3.0"
"@next/swc-win32-x64-msvc" "12.3.0"
object-assign@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==
object-inspect@^1.12.0, object-inspect@^1.9.0:
object-inspect@^1.12.2, object-inspect@^1.9.0:
version "1.12.2"
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea"
integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==
@@ -1236,7 +1241,7 @@ object-keys@^1.1.1:
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==
object.assign@^4.1.2, object.assign@^4.1.3:
object.assign@^4.1.3, object.assign@^4.1.4:
version "4.1.4"
resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f"
integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==
@@ -1569,10 +1574,10 @@ strip-json-comments@^3.1.0, strip-json-comments@^3.1.1:
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
styled-jsx@5.0.4:
version "5.0.4"
resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.0.4.tgz#5b1bd0b9ab44caae3dd1361295559706e044aa53"
integrity sha512-sDFWLbg4zR+UkNzfk5lPilyIgtpddfxXEULxhujorr5jtePTUqiPDc5BC0v1NRqTr/WaFBGQQUoYToGlF4B2KQ==
styled-jsx@5.0.6:
version "5.0.6"
resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.0.6.tgz#fa684790a9cc3badded14badea163418fe568f77"
integrity sha512-xOeROtkK5MGMDimBQ3J6iPId8q0t/BDoG5XN6oKkZClVz9ISF/hihN8OCn2LggMU6N32aXnrXBdn3auSqNS9fA==
supports-color@^7.1.0:
version "7.2.0"
@@ -1659,11 +1664,6 @@ use-sync-external-store@1.2.0:
resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a"
integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==
v8-compile-cache@^2.0.3:
version "2.3.0"
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee"
integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==
which-boxed-primitive@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6"

View File

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

View File

@@ -41,6 +41,7 @@ export interface Config {
devCommand?: string;
framework?: string | null;
nodeVersion?: string;
middleware?: boolean;
[key: string]: unknown;
}
@@ -341,6 +342,7 @@ export interface BuilderV2 {
version: 2;
build: BuildV2;
prepareCache?: PrepareCache;
shouldServe?: ShouldServe;
}
export interface BuilderV3 {

View File

@@ -1,6 +1,6 @@
{
"name": "vercel",
"version": "28.2.1",
"version": "28.2.5",
"preferGlobal": true,
"license": "Apache-2.0",
"description": "The command-line interface for Vercel",
@@ -41,16 +41,16 @@
"node": ">= 14"
},
"dependencies": {
"@vercel/build-utils": "5.4.1",
"@vercel/go": "2.2.4",
"@vercel/hydrogen": "0.0.17",
"@vercel/next": "3.1.23",
"@vercel/node": "2.5.12",
"@vercel/python": "3.1.13",
"@vercel/redwood": "1.0.21",
"@vercel/remix": "1.0.22",
"@vercel/ruby": "1.3.30",
"@vercel/static-build": "1.0.21",
"@vercel/build-utils": "5.4.2",
"@vercel/go": "2.2.5",
"@vercel/hydrogen": "0.0.18",
"@vercel/next": "3.1.25",
"@vercel/node": "2.5.14",
"@vercel/python": "3.1.14",
"@vercel/redwood": "1.0.23",
"@vercel/remix": "1.0.24",
"@vercel/ruby": "1.3.31",
"@vercel/static-build": "1.0.23",
"update-notifier": "5.1.0"
},
"devDependencies": {
@@ -95,9 +95,9 @@
"@types/which": "1.3.2",
"@types/write-json-file": "2.2.1",
"@types/yauzl-promise": "2.1.0",
"@vercel/client": "12.2.3",
"@vercel/frameworks": "1.1.3",
"@vercel/fs-detectors": "2.1.0",
"@vercel/client": "12.2.4",
"@vercel/frameworks": "1.1.5",
"@vercel/fs-detectors": "3.2.0",
"@vercel/fun": "1.0.4",
"@vercel/ncc": "0.24.0",
"@zeit/source-map-support": "0.6.2",

View File

@@ -2,7 +2,7 @@ import { resolve, join } from 'path';
import fs from 'fs-extra';
import DevServer from '../../util/dev/server';
import parseListen from '../../util/dev/parse-listen';
import { parseListen } from '../../util/dev/parse-listen';
import { ProjectEnvVariable } from '../../types';
import Client from '../../util/client';
import { getLinkedProject } from '../../util/projects/link';

View File

@@ -1,7 +1,10 @@
import { URL } from 'url';
import plural from 'pluralize';
import npa from 'npm-package-arg';
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,
@@ -13,6 +16,9 @@ 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 '../is-error';
import cmd from '../output/cmd';
import code from '../output/code';
export interface BuilderWithPkg {
path: string;
@@ -81,7 +87,7 @@ export async function resolveBuilders(
continue;
}
if (name === '@vercel/static' || name === '@now/static') {
if (isStaticRuntime(name)) {
// `@vercel/static` is a special-case built-in builder
builders.set(name, {
builder: staticBuilder,
@@ -201,15 +207,54 @@ async function installBuilders(
if (err.code !== 'EEXIST') throw err;
}
output.debug(`Installing Builders: ${Array.from(buildersToAdd).join(', ')}`);
await spawnAsync('yarn', ['add', '@vercel/build-utils', ...buildersToAdd], {
cwd: buildersDir,
});
output.log(
`Installing ${plural('Builder', buildersToAdd.size)}: ${Array.from(
buildersToAdd
).join(', ')}`
);
try {
await spawnAsync(
'npm',
['install', '@vercel/build-utils', ...buildersToAdd],
{
cwd: buildersDir,
stdio: 'pipe',
}
);
} catch (err: unknown) {
if (isError(err)) {
(err as any).link =
'https://vercel.link/builder-dependencies-install-failed';
if (isErrnoException(err) && err.code === 'ENOENT') {
// `npm` is not installed
err.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(
packageName
)} is not published on the npm registry`;
}
}
}
throw err;
}
// Symlink `@now/build-utils` -> `@vercel/build-utils` to support legacy Builders
const nowScopePath = join(buildersDir, 'node_modules/@now');
await mkdirp(nowScopePath);
await symlink('../@vercel/build-utils', join(nowScopePath, 'build-utils'));
try {
await symlink('../@vercel/build-utils', join(nowScopePath, 'build-utils'));
} catch (err: unknown) {
if (!isErrnoException(err) || err.code !== 'EEXIST') {
// Throw unless the error is due to the symlink already existing
throw err;
}
}
// Cross-reference any builderSpecs from the saved `package.json` file,
// in case they were installed from a URL

View File

@@ -1,5 +1,6 @@
import minimatch from 'minimatch';
import { BuildV2, Files } from '@vercel/build-utils';
import { shouldServe as defaultShouldServe } from '@vercel/build-utils';
import type { BuildV2, Files, ShouldServe } from '@vercel/build-utils';
export const version = 2;
@@ -39,3 +40,18 @@ export const build: BuildV2 = async ({ entrypoint, files, config }) => {
return { output };
};
export const shouldServe: ShouldServe = _opts => {
const opts = { ..._opts };
const {
config: { zeroConfig, outputDirectory },
} = opts;
// Add the output directory prefix
if (zeroConfig && outputDirectory) {
opts.entrypoint = `${outputDirectory}/${opts.entrypoint}`;
opts.requestPath = `${outputDirectory}/${opts.requestPath}`;
}
return defaultShouldServe(opts);
};

View File

@@ -1,412 +0,0 @@
import chalk from 'chalk';
import execa from 'execa';
import semver from 'semver';
import npa from 'npm-package-arg';
import pluralize from 'pluralize';
import { basename, join } from 'path';
import XDGAppPaths from 'xdg-app-paths';
import { mkdirp, readJSON, writeJSON } from 'fs-extra';
import { NowBuildError, PackageJson } from '@vercel/build-utils';
import cliPkg from '../pkg';
import cmd from '../output/cmd';
import { Output } from '../output';
import { NoBuilderCacheError } from '../errors-ts';
import * as staticBuilder from './static-builder';
import { BuilderWithPackage } from './types';
import { isErrnoException } from '../is-error';
const require_: typeof require = eval('require');
const registryTypes = new Set(['version', 'tag', 'range']);
const createStaticBuilder = (scope: string): BuilderWithPackage => {
return {
runInProcess: true,
requirePath: `${scope}/static`,
builder: Object.freeze(staticBuilder),
package: Object.freeze({ name: `@${scope}/static`, version: '' }),
};
};
const localBuilders: { [key: string]: BuilderWithPackage } = {
'@now/static': createStaticBuilder('now'),
'@vercel/static': createStaticBuilder('vercel'),
};
export const cacheDirPromise = prepareCacheDir();
export const builderDirPromise = prepareBuilderDir();
/**
* Prepare cache directory for installing Vercel runtimes.
*/
export async function prepareCacheDir() {
const designated = XDGAppPaths('com.vercel.cli').cache();
if (!designated) {
throw new NoBuilderCacheError();
}
const cacheDir = join(designated, 'dev');
await mkdirp(cacheDir);
return cacheDir;
}
export async function prepareBuilderDir() {
const builderDir = join(await cacheDirPromise, 'builders');
await mkdirp(builderDir);
// Create an empty `package.json` file, only if one does not already exist
try {
const buildersPkg = join(builderDir, 'package.json');
await writeJSON(buildersPkg, { private: true }, { flag: 'wx' });
} catch (err: unknown) {
if (!isErrnoException(err) || err.code !== 'EEXIST') {
throw err;
}
}
return builderDir;
}
function getNpmVersion(use = ''): string {
const parsed = npa(use);
if (registryTypes.has(parsed.type)) {
return parsed.fetchSpec || '';
}
return '';
}
export function getBuildUtils(packages: string[]): string {
const version = packages
.map(getNpmVersion)
.some(ver => ver.includes('canary'))
? 'canary'
: 'latest';
return `@vercel/build-utils@${version}`;
}
function parseVersionSafe(rawSpec: string) {
try {
return semver.parse(rawSpec);
} catch (e) {
return null;
}
}
export function filterPackage(
builderSpec: string,
buildersPkg: PackageJson,
cliPkg: Partial<PackageJson>
) {
if (builderSpec in localBuilders) return false;
const parsed = npa(builderSpec);
const parsedVersion = parseVersionSafe(parsed.rawSpec);
// Skip install of Runtimes that are part of Vercel CLI's `dependencies`
if (isBundledBuilder(parsed, cliPkg)) {
return false;
}
// Skip install of already installed Runtime with exact version match
if (
parsed.name &&
parsed.type === 'version' &&
parsedVersion &&
buildersPkg.dependencies &&
parsedVersion.version == buildersPkg.dependencies[parsed.name]
) {
return false;
}
return true;
}
/**
* Install a list of builders to the cache directory.
*/
export async function installBuilders(
packagesSet: Set<string>,
output: Output,
builderDir?: string
): Promise<void> {
const packages = Array.from(packagesSet);
if (
packages.length === 0 ||
(packages.length === 1 &&
Object.hasOwnProperty.call(localBuilders, packages[0]))
) {
// Static deployment, no builders to install
return;
}
if (!builderDir) {
builderDir = await builderDirPromise;
}
const buildersPkgPath = join(builderDir, 'package.json');
const buildersPkgBefore = await readJSON(buildersPkgPath);
const depsBefore = {
...buildersPkgBefore.devDependencies,
...buildersPkgBefore.dependencies,
};
// Filter out any packages that come packaged with Vercel CLI
const packagesToInstall = packages.filter(p =>
filterPackage(p, buildersPkgBefore, cliPkg)
);
if (packagesToInstall.length === 0) {
output.debug('No Runtimes need to be installed');
return;
}
packagesToInstall.push(getBuildUtils(packages));
await npmInstall(builderDir, output, packagesToInstall, false);
const updatedPackages: string[] = [];
const buildersPkgAfter = await readJSON(buildersPkgPath);
const depsAfter = {
...buildersPkgAfter.devDependencies,
...buildersPkgAfter.dependencies,
};
for (const [name, version] of Object.entries(depsAfter)) {
if (version !== depsBefore[name]) {
output.debug(`Runtime "${name}" updated to version \`${version}\``);
updatedPackages.push(name);
}
}
purgeRequireCache(updatedPackages, builderDir, output);
}
async function npmInstall(
cwd: string,
output: Output,
packagesToInstall: string[],
silent: boolean
) {
const sortedPackages = packagesToInstall.sort();
if (!silent) {
output.spinner(
`Installing ${pluralize(
'Runtime',
sortedPackages.length
)}: ${sortedPackages.join(', ')}`
);
}
output.debug(`Running npm install in ${cwd}`);
try {
const args = [
'install',
'--save-exact',
'--no-package-lock',
'--no-audit',
'--no-progress',
];
if (process.stderr.isTTY) {
// Force colors in the npm child process
// https://docs.npmjs.com/misc/config#color
args.push('--color=always');
}
args.push(...sortedPackages);
const result = await execa('npm', args, {
cwd,
reject: false,
stdio: output.isDebugEnabled() ? 'inherit' : 'pipe',
});
if (result.failed) {
output.stopSpinner();
if (result.stdout) {
console.log(result.stdout);
}
if (result.stderr) {
console.error(result.stderr);
}
throw new NowBuildError({
message:
(result as any).code === 'ENOENT'
? `Command not found: ${chalk.cyan(
'npm'
)}\nPlease ensure that ${cmd('npm')} is properly installed`
: 'Failed to install `vercel dev` dependencies',
code: 'NPM_INSTALL_ERROR',
link: 'https://vercel.link/npm-install-failed-dev',
});
}
} finally {
output.stopSpinner();
}
}
export async function updateBuilders(
packagesSet: Set<string>,
output: Output,
builderDir?: string
): Promise<string[]> {
if (!builderDir) {
builderDir = await builderDirPromise;
}
const updatedPackages: string[] = [];
const packages = Array.from(packagesSet);
const buildersPkgPath = join(builderDir, 'package.json');
const buildersPkgBefore = await readJSON(buildersPkgPath);
const depsBefore = {
...buildersPkgBefore.devDependencies,
...buildersPkgBefore.dependencies,
};
const packagesToUpdate = packages.filter(p => {
if (p in localBuilders) return false;
// If it's a builder that is part of Vercel CLI's
// `dependencies` then don't update it
if (isBundledBuilder(npa(p), cliPkg)) {
return false;
}
return true;
});
if (packagesToUpdate.length > 0) {
packagesToUpdate.push(getBuildUtils(packages));
await npmInstall(builderDir, output, packagesToUpdate, true);
const buildersPkgAfter = await readJSON(buildersPkgPath);
const depsAfter = {
...buildersPkgAfter.devDependencies,
...buildersPkgAfter.dependencies,
};
for (const [name, version] of Object.entries(depsAfter)) {
if (version !== depsBefore[name]) {
output.debug(`Runtime "${name}" updated to version \`${version}\``);
updatedPackages.push(name);
}
}
purgeRequireCache(updatedPackages, builderDir, output);
}
return updatedPackages;
}
/**
* Get a builder from the cache directory.
*/
export async function getBuilder(
builderPkg: string,
output: Output,
builderDir?: string,
isRetry = false
): Promise<BuilderWithPackage> {
let builderWithPkg: BuilderWithPackage = localBuilders[builderPkg];
if (!builderWithPkg) {
if (!builderDir) {
builderDir = await builderDirPromise;
}
let requirePath: string;
const parsed = npa(builderPkg);
// First check if it's a bundled Runtime in Vercel CLI's `node_modules`
const bundledBuilder = isBundledBuilder(parsed, cliPkg);
if (bundledBuilder && parsed.name) {
requirePath = parsed.name;
} else {
const buildersPkg = await readJSON(join(builderDir, 'package.json'));
const pkgName = getPackageName(parsed, buildersPkg) || builderPkg;
requirePath = join(builderDir, 'node_modules', pkgName);
}
try {
output.debug(`Requiring runtime: "${requirePath}"`);
const mod = require_(requirePath);
const pkg = require_(join(requirePath, 'package.json'));
builderWithPkg = {
requirePath,
builder: Object.freeze(mod),
package: Object.freeze(pkg),
};
} catch (err: unknown) {
if (
isErrnoException(err) &&
err.code === 'MODULE_NOT_FOUND' &&
!isRetry
) {
output.debug(
`Attempted to require ${requirePath}, but it is not installed`
);
const pkgSet = new Set([builderPkg]);
await installBuilders(pkgSet, output, builderDir);
// Run `getBuilder()` again now that the builder has been installed
return getBuilder(builderPkg, output, builderDir, true);
}
throw err;
}
// If it's a bundled builder, then cache the require call
if (bundledBuilder) {
localBuilders[builderPkg] = builderWithPkg;
}
}
return builderWithPkg;
}
export function isBundledBuilder(
parsed: npa.Result,
{ dependencies = {} }: PackageJson
): boolean {
if (!parsed.name) {
return false;
}
const inCliDependencyList = !!dependencies[parsed.name];
const inScope = parsed.scope === '@vercel';
const isVersionedReference = ['tag', 'version', 'range'].includes(
parsed.type
);
return inCliDependencyList && inScope && isVersionedReference;
}
function getPackageName(
parsed: npa.Result,
buildersPkg: PackageJson
): string | null {
if (registryTypes.has(parsed.type)) {
return parsed.name;
}
const deps: PackageJson.DependencyMap = {
...buildersPkg.devDependencies,
...buildersPkg.dependencies,
};
for (const [name, dep] of Object.entries(deps)) {
if (dep === parsed.raw || basename(dep) === basename(parsed.raw)) {
return name;
}
}
return null;
}
function purgeRequireCache(
packages: string[],
builderDir: string,
output: Output
) {
// The `require()` cache for the builder's assets must be purged
const packagesPaths = packages.map(b => join(builderDir, 'node_modules', b));
for (const id of Object.keys(require_.cache)) {
for (const path of packagesPaths) {
if (id.startsWith(path)) {
output.debug(`Purging require cache for "${id}"`);
delete require_.cache[id];
}
}
}
}

View File

@@ -15,7 +15,7 @@ import {
FileFsRef,
normalizePath,
} from '@vercel/build-utils';
import { isOfficialRuntime } from '@vercel/fs-detectors';
import { isStaticRuntime } from '@vercel/fs-detectors';
import plural from 'pluralize';
import minimatch from 'minimatch';
@@ -26,7 +26,6 @@ import { relative } from '../path-helpers';
import { LambdaSizeExceededError } from '../errors-ts';
import DevServer from './server';
import { getBuilder } from './builder-cache';
import {
VercelConfig,
BuildMatch,
@@ -41,6 +40,7 @@ import {
import { normalizeRoutes } from '@vercel/routing-utils';
import getUpdateCommand from '../get-update-command';
import { getTitleName } from '../pkg-name';
import { importBuilders } from '../build/import-builders';
interface BuildMessage {
type: string;
@@ -108,18 +108,18 @@ export async function executeBuild(
filesRemoved?: string[]
): Promise<void> {
const {
builderWithPkg: { runInProcess, requirePath, builder, package: pkg },
builderWithPkg: { path: requirePath, builder, pkg },
} = match;
const { entrypoint } = match;
const { entrypoint, use } = match;
const isStatic = isStaticRuntime(use);
const { envConfigs, cwd: workPath, devCacheDir } = devServer;
const debug = devServer.output.isDebugEnabled();
const startTime = Date.now();
const showBuildTimestamp =
!isOfficialRuntime('static', match.use) && (!isInitialBuild || debug);
const showBuildTimestamp = !isStatic && (!isInitialBuild || debug);
if (showBuildTimestamp) {
devServer.output.log(`Building ${match.use}:${entrypoint}`);
devServer.output.log(`Building ${use}:${entrypoint}`);
devServer.output.debug(
`Using \`${pkg.name}${pkg.version ? `@${pkg.version}` : ''}\``
);
@@ -130,7 +130,7 @@ export async function executeBuild(
let result: BuildResult;
let { buildProcess } = match;
if (!runInProcess && !buildProcess) {
if (!isStatic && !buildProcess) {
buildProcess = await createBuildProcess(
match,
envConfigs,
@@ -158,7 +158,7 @@ export async function executeBuild(
},
};
let buildResultOrOutputs: BuilderOutputs | BuildResult | BuildResultV3;
let buildResultOrOutputs;
if (buildProcess) {
buildProcess.send({
type: 'build',
@@ -198,16 +198,12 @@ export async function executeBuild(
}
// Sort out build result to builder v2 shape
if (!builder.version || builder.version === 1) {
if (!builder.version || (builder as any).version === 1) {
// `BuilderOutputs` map was returned (Now Builder v1 behavior)
result = {
output: buildResultOrOutputs as BuilderOutputs,
routes: [],
watch: [],
distPath:
typeof buildResultOrOutputs.distPath === 'string'
? buildResultOrOutputs.distPath
: undefined,
};
} else if (builder.version === 2) {
result = buildResultOrOutputs as BuildResult;
@@ -253,7 +249,7 @@ export async function executeBuild(
} else {
throw new Error(
`${getTitleName()} CLI does not support builder version ${
builder.version
(builder as any).version
}.\nPlease run \`${await getUpdateCommand()}\` to update to the latest CLI.`
);
}
@@ -383,7 +379,7 @@ export async function executeBuild(
if (showBuildTimestamp) {
const endTime = Date.now();
devServer.output.log(
`Built ${match.use}:${entrypoint} [${ms(endTime - startTime)}]`
`Built ${use}:${entrypoint} [${ms(endTime - startTime)}]`
);
}
}
@@ -405,6 +401,8 @@ export async function getBuildMatches(
const noMatches: Builder[] = [];
const builds = vercelConfig.builds || [{ src: '**', use: '@vercel/static' }];
const builderSpecs = new Set(builds.map(b => b.use).filter(Boolean));
const buildersWithPkgs = await importBuilders(builderSpecs, cwd, output);
for (const buildConfig of builds) {
let { src = '**', use, config = {} } = buildConfig;
@@ -439,6 +437,8 @@ export async function getBuildMatches(
for (const file of files) {
src = relative(cwd, file);
const entrypoint = mapToEntrypoint.get(src) || src;
// Remove the output directory prefix
if (config.zeroConfig && config.outputDirectory) {
const outputMatch = config.outputDirectory + '/';
@@ -447,11 +447,15 @@ export async function getBuildMatches(
}
}
const builderWithPkg = await getBuilder(use, output);
const builderWithPkg = buildersWithPkgs.get(use);
if (!builderWithPkg) {
throw new Error(`Failed to load Builder "${use}"`);
}
matches.push({
...buildConfig,
src,
entrypoint: mapToEntrypoint.get(src) || src,
entrypoint,
builderWithPkg,
buildOutput: {},
buildResults: new Map(),

View File

@@ -1,10 +1,7 @@
import { parse } from 'url';
import { ListenSpec } from './types';
export default function parseListen(
str: string,
defaultPort = 3000
): ListenSpec {
export function parseListen(str: string, defaultPort = 3000): ListenSpec {
let port = Number(str);
if (!isNaN(port)) {
@@ -50,3 +47,7 @@ export default function parseListen(
);
}
}
export function replaceLocalhost(address: string): string {
return address.replace('[::]', 'localhost').replace('0.0.0.0', 'localhost');
}

View File

@@ -1,4 +1,3 @@
import ms from 'ms';
import url, { URL } from 'url';
import http from 'http';
import fs from 'fs-extra';
@@ -62,11 +61,6 @@ import { devRouter, getRoutesTypes } from './router';
import getMimeType from './mime-type';
import { executeBuild, getBuildMatches, shutdownBuilder } from './builder';
import { generateErrorMessage, generateHttpStatusDescription } from './errors';
import {
installBuilders,
updateBuilders,
builderDirPromise,
} from './builder-cache';
// HTML templates
import errorTemplate from './templates/error';
@@ -101,7 +95,9 @@ import {
isError,
isSpawnError,
} from '../is-error';
import isURL from './is-url';
import { pickOverrides } from '../projects/project-settings';
import { replaceLocalhost } from './parse-listen';
const frontendRuntimeSet = new Set(
frameworkList.map(f => f.useRuntime?.use || '@vercel/static-build')
@@ -134,9 +130,18 @@ export default class DevServer {
public proxy: httpProxy;
public envConfigs: EnvConfigs;
public files: BuilderInputs;
public address: string;
public devCacheDir: string;
private _address: URL | undefined;
public get address(): URL {
if (!this._address) {
throw new Error(
'Invalid access to `address` because `start` has not yet populated `this.address`.'
);
}
return this._address;
}
public devCacheDir: string;
private currentDevCommand?: string;
private caseSensitive: boolean;
private apiDir: string | null;
@@ -152,7 +157,7 @@ export default class DevServer {
private filter: (path: string) => boolean;
private podId: string;
private devProcess?: ChildProcess;
private devProcessPort?: number;
private devProcessOrigin?: string;
private devServerPids: Set<number>;
private originalProjectSettings?: ProjectSettings;
private projectSettings?: ProjectSettings;
@@ -160,8 +165,6 @@ export default class DevServer {
private vercelConfigWarning: boolean;
private getVercelConfigPromise: Promise<VercelConfig> | null;
private blockingBuildsPromise: Promise<void> | null;
private updateBuildersPromise: Promise<void> | null;
private updateBuildersTimeout: NodeJS.Timeout | undefined;
private startPromise: Promise<void> | null;
private systemEnvValues: string[];
@@ -174,17 +177,22 @@ export default class DevServer {
this.systemEnvValues = options.systemEnvValues || [];
this.projectEnvs = options.projectEnvs || [];
this.files = {};
this.address = '';
this.originalProjectSettings = options.projectSettings;
this.projectSettings = options.projectSettings;
this.caseSensitive = false;
this.apiDir = null;
this.apiExtensions = new Set();
this.proxy = httpProxy.createProxyServer({
changeOrigin: true,
ws: true,
xfwd: true,
});
this.proxy.on('proxyRes', proxyRes => {
// override "server" header, like production
proxyRes.headers['server'] = 'Vercel';
});
this.server = http.createServer(this.devServerHandler);
this.server.timeout = 0; // Disable timeout
this.stopping = false;
@@ -195,7 +203,6 @@ export default class DevServer {
this.vercelConfigWarning = false;
this.getVercelConfigPromise = null;
this.blockingBuildsPromise = null;
this.updateBuildersPromise = null;
this.startPromise = null;
this.watchAggregationId = null;
@@ -477,33 +484,6 @@ export default class DevServer {
);
}
async invalidateBuildMatches(
vercelConfig: VercelConfig,
updatedBuilders: string[]
): Promise<void> {
if (updatedBuilders.length === 0) {
this.output.debug('No builders were updated');
return;
}
// Delete any build matches that have the old builder required already
for (const buildMatch of this.buildMatches.values()) {
const {
src,
builderWithPkg: { package: pkg },
} = buildMatch;
if (isOfficialRuntime('static', pkg.name)) continue;
if (pkg.name && updatedBuilders.includes(pkg.name)) {
shutdownBuilder(buildMatch, this.output);
this.buildMatches.delete(src);
this.output.debug(`Invalidated build match for "${src}"`);
}
}
// Re-add the build matches that were just removed, but with the new builder
await this.updateBuildMatches(vercelConfig);
}
async getLocalEnv(fileName: string, base?: Env): Promise<Env> {
// TODO: use the file watcher to only invalidate the env `dotfile`
// once a change to the `fileName` occurs
@@ -707,7 +687,7 @@ export default class DevServer {
this.projectEnvs || [],
this.systemEnvValues || [],
this.projectSettings?.autoExposeSystemEnvs,
new URL(this.address).host
this.address.host
);
allEnv = { ...cloudEnv };
@@ -842,7 +822,7 @@ export default class DevServer {
injectSystemValuesInDotenv(env: Env): Env {
for (const name of Object.keys(env)) {
if (name === 'VERCEL_URL') {
env['VERCEL_URL'] = new URL(this.address).host;
env['VERCEL_URL'] = this.address.host;
} else if (name === 'VERCEL_REGION') {
env['VERCEL_REGION'] = 'dev1';
}
@@ -915,9 +895,7 @@ export default class DevServer {
}
}
this.address = address
.replace('[::]', 'localhost')
.replace('127.0.0.1', 'localhost');
this._address = new URL(replaceLocalhost(address));
const vercelConfig = await this.getVercelConfig();
const devCommandPromise = this.runDevCommand();
@@ -934,30 +912,8 @@ export default class DevServer {
}
}
const builders = new Set<string>(
(vercelConfig.builds || [])
.filter((b: Builder) => b.use)
.map((b: Builder) => b.use)
);
await installBuilders(builders, this.output);
await this.updateBuildMatches(vercelConfig, true);
// Updating builders happens lazily, and any builders that were updated
// get their "build matches" invalidated so that the new version is used.
this.updateBuildersTimeout = setTimeout(() => {
this.updateBuildersPromise = updateBuilders(builders, this.output)
.then(updatedBuilders => {
this.updateBuildersPromise = null;
this.invalidateBuildMatches(vercelConfig, updatedBuilders);
})
.catch(err => {
this.updateBuildersPromise = null;
this.output.prettyError(err);
this.output.debug(err.stack);
});
}, ms('30s'));
// Builders that do not define a `shouldServe()` function need to be
// executed at boot-up time in order to get the initial assets and/or routes
// that can be served by the builder.
@@ -1007,37 +963,37 @@ export default class DevServer {
// Configure the server to forward WebSocket "upgrade" events to the proxy.
this.server.on('upgrade', async (req, socket, head) => {
await this.startPromise;
if (!this.devProcessPort) {
if (!this.devProcessOrigin) {
this.output.debug(
`Detected "upgrade" event, but closing socket because no frontend dev server is running`
);
socket.destroy();
return;
}
const target = `http://127.0.0.1:${this.devProcessPort}`;
const target = this.devProcessOrigin;
this.output.debug(`Detected "upgrade" event, proxying to ${target}`);
this.proxy.ws(req, socket, head, { target });
});
await devCommandPromise;
this.output.ready(`Available at ${link(this.address)}`);
let addressFormatted = this.address.toString();
if (this.address.pathname === '/' && this.address.protocol === 'http:') {
// log address without trailing slash to maintain backwards compatibility
addressFormatted = addressFormatted.replace(/\/$/, '');
}
this.output.ready(`Available at ${link(addressFormatted)}`);
}
/**
* Shuts down the `vercel dev` server, and cleans up any temporary resources.
*/
async stop(exitCode?: number): Promise<void> {
const { devProcess } = this;
const { debug } = this.output;
if (this.stopping) return;
this.stopping = true;
if (typeof this.updateBuildersTimeout !== 'undefined') {
clearTimeout(this.updateBuildersTimeout);
}
const { devProcess } = this;
const { debug } = this.output;
const ops: Promise<any>[] = [];
for (const match of this.buildMatches.values()) {
@@ -1055,18 +1011,10 @@ export default class DevServer {
ops.push(this.watcher.close());
}
if (this.updateBuildersPromise) {
debug(`Waiting for builders update to complete`);
ops.push(this.updateBuildersPromise);
}
for (const pid of this.devServerPids) {
ops.push(this.killBuilderDevServer(pid));
}
// Ensure that the builders module cache is created
ops.push(builderDirPromise);
try {
await Promise.all(ops);
} catch (err: unknown) {
@@ -1465,8 +1413,9 @@ export default class DevServer {
// the middleware server for every HTTP request?
const { envConfigs, files, devCacheDir, cwd: workPath } = this;
try {
startMiddlewareResult =
await middleware.builderWithPkg.builder.startDevServer?.({
const { builder } = middleware.builderWithPkg;
if (builder.version === 3) {
startMiddlewareResult = await builder.startDevServer?.({
files,
entrypoint: middleware.entrypoint,
workPath,
@@ -1480,6 +1429,7 @@ export default class DevServer {
buildEnv: { ...envConfigs.buildEnv },
},
});
}
if (startMiddlewareResult) {
const { port, pid } = startMiddlewareResult;
@@ -1560,15 +1510,34 @@ export default class DevServer {
}
if (rewritePath) {
// TODO: add validation?
debug(`Detected rewrite path from middleware: "${rewritePath}"`);
prevUrl = rewritePath;
// Retain orginal pathname, but override query parameters from the rewrite
const beforeRewriteUrl = req.url || '/';
const rewriteUrlParsed = url.parse(beforeRewriteUrl);
rewriteUrlParsed.search = url.parse(rewritePath).search;
req.url = url.format(rewriteUrlParsed);
if (isURL(rewritePath)) {
const rewriteUrlParsed = new URL(rewritePath);
// `this.address` already has localhost normalized from ip4 and ip6 values
if (this.address.origin === rewriteUrlParsed.origin) {
// remove origin, leaving the path
req.url =
rewritePath.slice(rewriteUrlParsed.origin.length) || '/';
prevUrl = req.url;
} else {
// Proxy to absolute URL with different origin
debug(`ProxyPass: ${rewritePath}`);
this.setResponseHeaders(res, requestId);
proxyPass(req, res, rewritePath, this, requestId);
return;
}
} else {
// Retain orginal pathname, but override query parameters from the rewrite
const rewriteUrlParsed = url.parse(beforeRewriteUrl);
rewriteUrlParsed.search = url.parse(rewritePath).search;
req.url = url.format(rewriteUrlParsed);
}
debug(
`Rewrote incoming HTTP URL from "${beforeRewriteUrl}" to "${req.url}"`
);
@@ -1617,12 +1586,16 @@ export default class DevServer {
missRoutes,
phase
);
prevUrl =
routeResult.continue && routeResult.dest
? getReqUrl(routeResult)
: req.url;
prevHeaders =
routeResult.continue && routeResult.headers ? routeResult.headers : {};
if (routeResult.continue) {
if (routeResult.dest) {
prevUrl = getReqUrl(routeResult);
}
if (routeResult.headers) {
prevHeaders = routeResult.headers;
}
}
if (routeResult.isDestUrl) {
// Mix the `routes` result dest query params into the req path
@@ -1795,8 +1768,8 @@ export default class DevServer {
if (!match) {
// If the dev command is started, then proxy to it
if (this.devProcessPort) {
const upstream = `http://127.0.0.1:${this.devProcessPort}`;
if (this.devProcessOrigin) {
const upstream = this.devProcessOrigin;
debug(`Proxying to frontend dev server: ${upstream}`);
// Add the Vercel platform proxy request headers
@@ -1869,8 +1842,8 @@ export default class DevServer {
// up a single-serve dev HTTP server that vercel dev will proxy this HTTP request
// to. Once the proxied request is finished, vercel dev shuts down the dev
// server child process.
const { builder, package: builderPkg } = match.builderWithPkg;
if (typeof builder.startDevServer === 'function') {
const { builder, pkg: builderPkg } = match.builderWithPkg;
if (builder.version === 3 && typeof builder.startDevServer === 'function') {
let devServerResult: StartDevServerResult = null;
try {
const { envConfigs, files, devCacheDir, cwd: workPath } = this;
@@ -1975,7 +1948,7 @@ export default class DevServer {
// - when there is no asset
// - when the asset is not a Lambda (the dev server must take care of all static files)
if (
this.devProcessPort &&
this.devProcessOrigin &&
(!foundAsset || (foundAsset && foundAsset.asset.type !== 'Lambda'))
) {
debug('Proxying to frontend dev server');
@@ -1987,14 +1960,7 @@ export default class DevServer {
}
this.setResponseHeaders(res, requestId);
return proxyPass(
req,
res,
`http://127.0.0.1:${this.devProcessPort}`,
this,
requestId,
false
);
return proxyPass(req, res, this.devProcessOrigin, this, requestId, false);
}
if (!foundAsset) {
@@ -2301,7 +2267,6 @@ export default class DevServer {
this.output.debug(`Spawning dev command: ${command}`);
const devPort = new URL(this.address).port;
const proxyPort = new RegExp(port.toString(), 'g');
const p = spawnCommand(command, {
stdio: ['inherit', 'pipe', 'pipe'],
@@ -2318,17 +2283,16 @@ export default class DevServer {
p.stdout.setEncoding('utf8');
p.stdout.on('data', (data: string) => {
process.stdout.write(data.replace(proxyPort, devPort));
process.stdout.write(data.replace(proxyPort, this.address.port));
});
p.on('exit', (code, signal) => {
this.output.debug(`Dev command exited with "${signal || code}"`);
this.devProcessPort = undefined;
this.devProcessOrigin = undefined;
});
await checkForPort(port, 1000 * 60 * 5);
this.devProcessPort = port;
const devProcessHost = await checkForPort(port, 1000 * 60 * 5);
this.devProcessOrigin = `http://${devProcessHost}:${port}`;
}
}
@@ -2616,15 +2580,29 @@ function needsBlockingBuild(buildMatch: BuildMatch): boolean {
return typeof builder.shouldServe !== 'function';
}
async function checkForPort(port: number, timeout: number): Promise<void> {
const opts = { host: '127.0.0.1' };
async function checkForPort(port: number, timeout: number): Promise<string> {
let host;
const start = Date.now();
while (!(await isPortReachable(port, opts))) {
while (!(host = await getReachableHostOnPort(port))) {
if (Date.now() - start > timeout) {
throw new Error(`Detecting port ${port} timed out after ${timeout}ms`);
break;
}
await sleep(100);
}
if (!host) {
throw new Error(`Detecting port ${port} timed out after ${timeout}ms`);
}
return host;
}
async function getReachableHostOnPort(port: number): Promise<string | false> {
const optsIpv4 = { host: '127.0.0.1' };
const optsIpv6 = { host: '::1' };
const results = await Promise.all([
isPortReachable(port, optsIpv6).then(r => r && `[${optsIpv6.host}]`),
isPortReachable(port, optsIpv4).then(r => r && optsIpv4.host),
]);
return results.find(Boolean) || false;
}
function filterFrontendBuilds(build: Builder) {

View File

@@ -1,42 +0,0 @@
import {
FileFsRef,
BuildOptions,
shouldServe as defaultShouldServe,
ShouldServeOptions,
} from '@vercel/build-utils';
import { BuildResult } from './types';
export const version = 2;
export function build({
files,
entrypoint,
config: { zeroConfig, outputDirectory },
}: BuildOptions): BuildResult {
const path =
zeroConfig && outputDirectory
? `${outputDirectory}/${entrypoint}`
: entrypoint;
return {
output: {
[entrypoint]: files[path] as FileFsRef,
},
routes: [],
watch: [path],
};
}
export function shouldServe(_opts: ShouldServeOptions) {
const opts = { ..._opts };
let {
config: { zeroConfig, outputDirectory },
} = opts;
// Add the output directory prefix
if (zeroConfig && outputDirectory) {
opts.entrypoint = `${outputDirectory}/${opts.entrypoint}`;
opts.requestPath = `${outputDirectory}/${opts.requestPath}`;
}
return defaultShouldServe(opts);
}

View File

@@ -12,12 +12,12 @@ import {
FileBlob,
FileFsRef,
Lambda,
PackageJson,
} from '@vercel/build-utils';
import { VercelConfig } from '@vercel/client';
import { HandleValue, Route } from '@vercel/routing-utils';
import { Output } from '../output';
import { ProjectEnvVariable, ProjectSettings } from '../../types';
import { BuilderWithPkg } from '../build/import-builders';
export { VercelConfig };
@@ -48,7 +48,7 @@ export interface EnvConfigs {
export interface BuildMatch extends BuildConfig {
entrypoint: string;
src: string;
builderWithPkg: BuilderWithPackage;
builderWithPkg: BuilderWithPkg;
buildOutput: BuilderOutputs;
buildResults: Map<string | null, BuildResult>;
buildTimestamp: number;
@@ -122,13 +122,6 @@ export interface BuildResultV4 {
distPath?: string;
}
export interface BuilderWithPackage {
runInProcess?: boolean;
requirePath: string;
builder: Readonly<Builder>;
package: Readonly<PackageJson>;
}
export interface HttpHeadersConfig {
[name: string]: string;
}

View File

@@ -0,0 +1,7 @@
export const config = {
runtime: 'experimental-edge',
};
export default async function edge(request: Request, event: Event) {
return new Response('heyo');
}

View File

@@ -0,0 +1 @@
<h1>Hello from Index</h1>

View File

@@ -0,0 +1,21 @@
export const config = {
runtime: 'experimental-edge',
};
export default async function edge(request: Request, event: Event) {
if (request.url.indexOf('/index.html') > -1) {
return new Response(null, {
headers: {
'x-middleware-rewrite': '/does-not-exist.html',
},
});
}
if (request.url.indexOf('/api/edge') > -1) {
return new Response(null, {
headers: {
'x-middleware-rewrite': '/api/does-not-exist',
},
});
}
}

View File

@@ -1,6 +1,15 @@
export default req => {
const url = new URL(req.url);
const rewriteTo = url.searchParams.get('to');
if (rewriteTo) {
return new Response(null, {
headers: {
'x-middleware-rewrite': rewriteTo,
},
});
}
if (url.pathname === '/') {
// Pass-through "index.html" page
return new Response(null, {

View File

@@ -1,7 +1,6 @@
{
"private": true,
"scripts": {
"dev": "vite --port $PORT",
"build": "vite build",
"serve": "vite preview"
},

View File

@@ -0,0 +1,3 @@
{
"devCommand": "vite --port $PORT --host ::1"
}

View File

@@ -3,6 +3,7 @@ import url from 'url';
import fs from 'fs-extra';
import { join } from 'path';
import listen from 'async-listen';
import stripAnsi from 'strip-ansi';
import { createServer } from 'http';
const {
@@ -723,12 +724,15 @@ test('[vercel dev] should support custom 404 routes', async () => {
test('[vercel dev] prints `npm install` errors', async () => {
const dir = fixture('runtime-not-installed');
const result = await exec(dir);
expect(result.stderr.includes('npm ERR! 404')).toBeTruthy();
expect(
result.stderr.includes('Failed to install `vercel dev` dependencies')
stripAnsi(result.stderr).includes(
'Error: The package `@vercel/does-not-exist` is not published on the npm registry'
)
).toBeTruthy();
expect(
result.stderr.includes('https://vercel.link/npm-install-failed-dev')
result.stderr.includes(
'https://vercel.link/builder-dependencies-install-failed'
)
).toBeTruthy();
});

View File

@@ -445,11 +445,7 @@ test(
test(
'[vercel dev] Middleware that has no response',
testFixtureStdio('middleware-no-response', async (testPath: any) => {
await testPath(
500,
'/api/hello',
'A server error has occurred\n\nEDGE_FUNCTION_INVOCATION_FAILED'
);
await testPath(200, '/api/hello', 'hello from a serverless function');
})
);
@@ -461,9 +457,42 @@ test(
await testPath(200, '/another', '<h1>Another</h1>');
await testPath(200, '/another.html', '<h1>Another</h1>');
await testPath(200, '/foo', '<h1>Another</h1>');
// different origin
await testPath(200, '?to=http://example.com', /Example Domain/);
})
);
test('[vercel dev] Middleware rewrites with same origin', async () => {
const directory = fixture('middleware-rewrite');
const { dev, port, readyResolver } = await testFixture(directory);
try {
dev.unref();
await readyResolver;
let response = await fetch(
`http://localhost:${port}?to=http://localhost:${port}`
);
validateResponseHeaders(response);
expect(response.status).toBe(200);
expect(await response.text()).toMatch(/<h1>Index<\/h1>/);
response = await fetch(
`http://localhost:${port}?to=http://127.0.0.1:${port}`
);
validateResponseHeaders(response);
expect(response.status).toBe(200);
expect(await response.text()).toMatch(/<h1>Index<\/h1>/);
response = await fetch(`http://localhost:${port}?to=http://[::1]:${port}`);
validateResponseHeaders(response);
expect(response.status).toBe(200);
expect(await response.text()).toMatch(/<h1>Index<\/h1>/);
} finally {
await dev.kill('SIGTERM');
}
});
test(
'[vercel dev] Middleware that rewrites with custom query params',
testFixtureStdio('middleware-rewrite-query', async (testPath: any) => {
@@ -481,6 +510,14 @@ test(
})
);
test(
'[vercel dev] Middleware that rewrites to 404s',
testFixtureStdio('middleware-rewrite-404', async (testPath: any) => {
await testPath(404, '/api/edge', /NOT_FOUND/);
await testPath(404, '/index.html', /NOT_FOUND/);
})
);
test(
'[vercel dev] Middleware that redirects',
testFixtureStdio('middleware-redirect', async (testPath: any) => {

View File

@@ -13,6 +13,7 @@ const {
jest.setTimeout(6 * 60 * 1000);
const isCI = !!process.env.CI;
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
const isCanary = () => getDistTag(cliVersion) === 'canary';
@@ -52,7 +53,7 @@ function fetchWithRetry(url, opts = {}) {
return res;
},
{
retries: opts.retries || 3,
retries: opts.retries ?? 3,
factor: 1,
}
);
@@ -150,9 +151,9 @@ async function testPath(
fetchOpts = {}
) {
const opts = {
retries: isCI ? 5 : 0,
...fetchOpts,
redirect: 'manual-dont-change',
retries: 5,
status,
};
const url = `${origin}${path}`;
@@ -330,7 +331,7 @@ function testFixtureStdio(
Authorization: `Bearer ${token}`,
},
body: JSON.stringify(projectSettings),
retries: 3,
retries: isCI ? 3 : 0,
status: 200,
}
);

View File

@@ -69,7 +69,7 @@ export function useDeploymentMissingProjectSettings() {
framework: {
name: 'Other',
slug: null,
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/other.svg',
logo: 'https://api-frameworks.vercel.sh/framework-logos/other.svg',
description: 'No framework or an unoptimized framework.',
settings: {
installCommand: {

View File

@@ -895,6 +895,12 @@ describe('build', () => {
});
it('should apply project settings overrides from "vercel.json"', async () => {
if (process.platform === 'win32') {
// this test runs a build command with `mkdir -p` which is unsupported on Windows
console.log('Skipping test on Windows');
return;
}
const cwd = fixture('project-settings-override');
const output = join(cwd, '.vercel/output');
try {

View File

@@ -28,24 +28,72 @@ describe('importBuilders()', () => {
});
it('should import 3rd party Builders', 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 = 'vercel-deno@2.0.1';
const specs = new Set([spec]);
const tarballSpec = 'https://test2020-h5hdll5dz-tootallnate.vercel.app';
const specs = new Set([spec, tarballSpec]);
const builders = await importBuilders(specs, cwd, client.output);
expect(builders.size).toEqual(1);
expect(builders.size).toEqual(2);
expect(builders.get(spec)?.pkg.name).toEqual('vercel-deno');
expect(builders.get(spec)?.pkg.version).toEqual('2.0.1');
expect(builders.get(spec)?.pkgPath).toEqual(
join(cwd, '.vercel/builders/node_modules/vercel-deno/package.json')
);
expect(typeof builders.get(spec)?.builder.build).toEqual('function');
expect(builders.get(tarballSpec)?.pkg.name).toEqual('vercel-bash');
expect(builders.get(tarballSpec)?.pkg.version).toEqual('4.1.0');
expect(builders.get(tarballSpec)?.pkgPath).toEqual(
join(cwd, '.vercel/builders/node_modules/vercel-bash/package.json')
);
expect(typeof builders.get(tarballSpec)?.builder.build).toEqual(
'function'
);
await expect(client.stderr).toOutput(
'> Installing Builders: vercel-deno@2.0.1, https://test2020-h5hdll5dz-tootallnate.vercel.app'
);
} finally {
await remove(cwd);
}
});
it('should throw when importing a Builder that is not on npm registry', async () => {
let err: Error | undefined;
const cwd = await getWriteableDirectory();
try {
const spec = '@vercel/does-not-exist@0.0.1';
const specs = new Set([spec]);
await importBuilders(specs, cwd, client.output);
} catch (_err) {
err = _err;
} finally {
await remove(cwd);
}
if (!err) {
throw new Error('Expected `err` to be defined');
}
expect(err.message).toEqual(
'The package `@vercel/does-not-exist` is not published on the npm registry'
);
expect((err as any).link).toEqual(
'https://vercel.link/builder-dependencies-install-failed'
);
});
it('should import legacy `@now/build-utils` Builders', 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 = '@frontity/now@1.2.0';

View File

@@ -1,235 +0,0 @@
import npa from 'npm-package-arg';
import {
filterPackage,
getBuildUtils,
isBundledBuilder,
} from '../../../../src/util/dev/builder-cache';
describe('filterPackage', () => {
const cliPkg = {
dependencies: {
'@vercel/build-utils': '0.0.1',
},
};
it('should filter package that does not appear in CLI package.json', () => {
const result = filterPackage('@vercel/other', {}, cliPkg);
expect(result).toEqual(true);
});
it('should not filter "latest", cached canary', () => {
const buildersPkg = {
dependencies: {
'@vercel/build-utils': '0.0.1-canary.0',
},
};
const result = filterPackage('@vercel/build-utils', buildersPkg, cliPkg);
expect(result).toEqual(false);
});
it('should filter install "canary", cached stable', () => {
const buildersPkg = {
dependencies: {
'@vercel/build-utils': '0.0.1',
},
};
const result = filterPackage(
'@vercel/build-utils@canary',
buildersPkg,
cliPkg
);
expect(result).toEqual(false);
});
it('should filter install "latest", cached stable', () => {
const buildersPkg = {
dependencies: {
'@vercel/build-utils': '0.0.1',
},
};
const result = filterPackage('@vercel/build-utils', buildersPkg, cliPkg);
expect(result).toEqual(false);
});
it('should filter install "canary", cached canary', () => {
const buildersPkg = {
dependencies: {
'@vercel/build-utils': '0.0.1-canary.0',
},
};
const result = filterPackage(
'@vercel/build-utils@canary',
buildersPkg,
cliPkg
);
expect(result).toEqual(false);
});
it('should filter install URL, cached stable', () => {
const buildersPkg = {
dependencies: {
'@vercel/build-utils': '0.0.1',
},
};
const result = filterPackage('https://tarball.now.sh', buildersPkg, cliPkg);
expect(result).toEqual(true);
});
it('should filter install URL, cached canary', () => {
const buildersPkg = {
dependencies: {
'@vercel/build-utils': '0.0.1-canary.0',
},
};
const result = filterPackage('https://tarball.now.sh', buildersPkg, cliPkg);
expect(result).toEqual(true);
});
it('should filter install "latest", cached URL - canary', () => {
const buildersPkg = {
dependencies: {
'@vercel/build-utils': 'https://tarball.now.sh',
},
};
const result = filterPackage('@vercel/build-utils', buildersPkg, cliPkg);
expect(result).toEqual(false);
});
it('should filter install not bundled version, cached same version', () => {
const buildersPkg = {
dependencies: {
'not-bundled-package': '0.0.1',
},
};
const result = filterPackage(
'not-bundled-package@0.0.1',
buildersPkg,
cliPkg
);
expect(result).toEqual(false);
});
it('should filter install not bundled version, cached different version', () => {
const buildersPkg = {
dependencies: {
'not-bundled-package': '0.0.9',
},
};
const result = filterPackage(
'not-bundled-package@0.0.1',
buildersPkg,
cliPkg
);
expect(result).toEqual(true);
});
it('should filter install not bundled stable, cached version', () => {
const buildersPkg = {
dependencies: {
'not-bundled-package': '0.0.1',
},
};
const result = filterPackage('not-bundled-package', buildersPkg, cliPkg);
expect(result).toEqual(true);
});
it('should filter install not bundled tagged, cached tagged', () => {
const buildersPkg = {
dependencies: {
'not-bundled-package': '16.9.0-alpha.0',
},
};
const result = filterPackage(
'not-bundled-package@alpha',
buildersPkg,
cliPkg
);
expect(result).toEqual(true);
});
});
describe('getBuildUtils', () => {
const tests: [string[], string][] = [
[['@vercel/static', '@vercel/node@canary'], 'canary'],
[['@vercel/static', '@vercel/node@0.7.4-canary.0'], 'canary'],
[['@vercel/static', '@vercel/node@0.8.0'], 'latest'],
[['@vercel/static', '@vercel/node'], 'latest'],
[['@vercel/static'], 'latest'],
[['@vercel/md@canary'], 'canary'],
[['custom-builder'], 'latest'],
[['custom-builder@canary'], 'canary'],
[['canary-bird'], 'latest'],
[['canary-bird@4.0.0'], 'latest'],
[['canary-bird@canary'], 'canary'],
[['@canary/bird'], 'latest'],
[['@canary/bird@0.1.0'], 'latest'],
[['@canary/bird@canary'], 'canary'],
[['https://example.com'], 'latest'],
[[''], 'latest'],
];
for (const [input, expected] of tests) {
it(`should install "${expected}" with input ${JSON.stringify(
input
)}`, () => {
const result = getBuildUtils(input);
expect(result).toEqual(`@vercel/build-utils@${expected}`);
});
}
});
describe('isBundledBuilder', () => {
const cliPkg = {
dependencies: {
'@vercel/node': '0.0.1',
},
};
it('should not detect when dependency does not appear in CLI package.json', () => {
const parsed = npa('@vercel/node');
const result = isBundledBuilder(parsed, {});
expect(result).toEqual(false);
});
it('should detect "canary" tagged releases', () => {
const parsed = npa('@vercel/node@canary');
const result = isBundledBuilder(parsed, cliPkg);
expect(result).toEqual(true);
});
it('should detect "canary" versioned releases', () => {
const parsed = npa('@vercel/node@1.6.1-canary.0');
const result = isBundledBuilder(parsed, cliPkg);
expect(result).toEqual(true);
});
it('should detect latest releases', () => {
const parsed = npa('@vercel/node');
const result = isBundledBuilder(parsed, cliPkg);
expect(result).toEqual(true);
});
it('should detect "latest" tagged releases', () => {
const parsed = npa('@vercel/node@latest');
const result = isBundledBuilder(parsed, cliPkg);
expect(result).toEqual(true);
});
it('should detect versioned releases', () => {
const parsed = npa('@vercel/node@1.6.1');
const result = isBundledBuilder(parsed, cliPkg);
expect(result).toEqual(true);
});
it('should NOT detect URL releases', () => {
const parsed = npa('https://example.com');
const result = isBundledBuilder(parsed, cliPkg);
expect(result).toEqual(false);
});
it('should NOT detect git url releases', () => {
const parsed = npa('git://example.com/repo.git');
const result = isBundledBuilder(parsed, cliPkg);
expect(result).toEqual(false);
});
});

View File

@@ -1,4 +1,7 @@
import parseListen from '../../../../src/util/dev/parse-listen';
import {
parseListen,
replaceLocalhost,
} from '../../../../src/util/dev/parse-listen';
const IS_WINDOWS = process.platform === 'win32';
@@ -69,3 +72,15 @@ describe('parseListen', () => {
expect(err.message).toEqual('Unknown `--listen` scheme (protocol): bad:');
});
});
describe('replaceLocalhost', () => {
test.each([
{ input: 'http://192.168.0.1:1234', output: 'http://192.168.0.1:1234' },
{ input: 'http://127.0.0.1:4000', output: 'http://127.0.0.1:4000' },
{ input: 'http://[::1]:3001', output: 'http://[::1]:3001' },
{ input: 'http://0.0.0.0:3000', output: 'http://localhost:3000' },
{ input: 'http://[::]:3002', output: 'http://localhost:3002' },
])('"$input" → "$output"', ({ input, output }) => {
expect(replaceLocalhost(input)).toEqual(output);
});
});

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/client",
"version": "12.2.3",
"version": "12.2.4",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
"homepage": "https://vercel.com",
@@ -43,7 +43,7 @@
]
},
"dependencies": {
"@vercel/build-utils": "5.4.1",
"@vercel/build-utils": "5.4.2",
"@vercel/routing-utils": "2.0.2",
"@zeit/fetch": "5.2.0",
"async-retry": "1.2.3",

View File

@@ -1 +1 @@
<svg width="48" height="48" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M22.428.013c-.103.01-.431.042-.727.066C14.883.693 8.497 4.37 4.453 10.024A23.754 23.754 0 0 0 .216 20.51C.023 21.828 0 22.217 0 24.005c0 1.787.023 2.177.216 3.495 1.304 9.012 7.718 16.584 16.417 19.39 1.558.501 3.2.844 5.068 1.05.727.08 3.87.08 4.598 0 3.224-.356 5.954-1.154 8.648-2.529.412-.21.492-.267.436-.314-.038-.028-1.797-2.388-3.909-5.24l-3.838-5.184-4.809-7.117c-2.646-3.913-4.824-7.112-4.842-7.112-.019-.005-.038 3.157-.047 7.018-.014 6.76-.019 7.033-.103 7.192-.122.23-.216.324-.413.427-.15.075-.282.09-.99.09h-.812l-.216-.137a.878.878 0 0 1-.314-.342l-.099-.211.01-9.407.014-9.41.145-.184c.075-.098.235-.225.347-.286.193-.094.268-.103 1.08-.103.957 0 1.116.038 1.365.31.07.075 2.674 3.997 5.79 8.721s7.376 11.175 9.469 14.342l3.8 5.756.192-.127c1.704-1.107 3.505-2.683 4.932-4.325a23.888 23.888 0 0 0 5.65-12.268c.192-1.319.215-1.708.215-3.495 0-1.788-.023-2.177-.216-3.495-1.304-9.013-7.718-16.584-16.417-19.39C29.832.623 28.199.28 26.369.074c-.45-.047-3.551-.099-3.94-.061zm9.825 14.515a.947.947 0 0 1 .474.554c.038.122.047 2.73.038 8.608l-.014 8.436-1.488-2.28-1.492-2.28v-6.132c0-3.964.019-6.193.047-6.3a.957.957 0 0 1 .465-.592c.192-.098.262-.108 1-.108.694 0 .816.01.97.094z" fill="#fff"/></svg>
<svg width="48" height="48" fill="none" xmlns="http://www.w3.org/2000/svg"><mask id="mask" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="48" height="48"><circle cx="24" cy="24" r="24" fill="#000"/></mask><g mask="url(#mask)"><circle cx="24" cy="24" r="23.2" fill="#000" stroke="#fff" stroke-width="1.6"/><path d="M39.8687 42.0055L18.4378 14.4H14.3999V33.592H17.6302V18.5023L37.333 43.9587C38.222 43.3637 39.069 42.7108 39.8687 42.0055Z" fill="url(#gradient0)"/><rect x="30.6667" y="14.4" width="3.2" height="19.2" fill="url(#gradient1)"/></g><defs><linearGradient id="gradient0" x1="29.0666" y1="31.0667" x2="38.5332" y2="42.8" gradientUnits="userSpaceOnUse"><stop stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><linearGradient id="gradient1" x1="32.2667" y1="14.4" x2="32.2132" y2="28.5001" gradientUnits="userSpaceOnUse"><stop stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient></defs></svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 997 B

View File

@@ -1 +1 @@
<svg width="48" height="48" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M22.428.013c-.103.01-.431.042-.727.066C14.883.693 8.497 4.37 4.453 10.024A23.754 23.754 0 0 0 .216 20.51C.023 21.828 0 22.217 0 24.005c0 1.787.023 2.177.216 3.495 1.304 9.012 7.718 16.584 16.417 19.39 1.558.501 3.2.844 5.068 1.05.727.08 3.87.08 4.598 0 3.224-.356 5.954-1.154 8.648-2.529.412-.21.492-.267.436-.314-.038-.028-1.797-2.388-3.909-5.24l-3.838-5.184-4.809-7.117c-2.646-3.913-4.824-7.112-4.842-7.112-.019-.005-.038 3.157-.047 7.018-.014 6.76-.019 7.033-.103 7.192-.122.23-.216.324-.413.427-.15.075-.282.09-.99.09h-.812l-.216-.137a.878.878 0 0 1-.314-.342l-.099-.211.01-9.407.014-9.41.145-.184c.075-.098.235-.225.347-.286.193-.094.268-.103 1.08-.103.957 0 1.116.038 1.365.31.07.075 2.674 3.997 5.79 8.721s7.376 11.175 9.469 14.342l3.8 5.756.192-.127c1.704-1.107 3.505-2.683 4.932-4.325a23.888 23.888 0 0 0 5.65-12.268c.192-1.319.215-1.708.215-3.495 0-1.788-.023-2.177-.216-3.495-1.304-9.013-7.718-16.584-16.417-19.39C29.832.623 28.199.28 26.369.074c-.45-.047-3.551-.099-3.94-.061zm9.825 14.515a.947.947 0 0 1 .474.554c.038.122.047 2.73.038 8.608l-.014 8.436-1.488-2.28-1.492-2.28v-6.132c0-3.964.019-6.193.047-6.3a.957.957 0 0 1 .465-.592c.192-.098.262-.108 1-.108.694 0 .816.01.97.094z" fill="#000"/></svg>
<svg width="48" height="48" fill="none" xmlns="http://www.w3.org/2000/svg"><mask id="mask" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="48" height="48"><circle cx="24" cy="24" r="24" fill="#000"/></mask><g mask="url(#mask)"><circle cx="24" cy="24" r="23.2" fill="#000" stroke="#000" stroke-width="1.6"/><path d="M39.8687 42.0055L18.4378 14.4H14.3999V33.592H17.6302V18.5023L37.333 43.9587C38.222 43.3637 39.069 42.7108 39.8687 42.0055Z" fill="url(#gradient0)"/><rect x="30.6667" y="14.4" width="3.2" height="19.2" fill="url(#gradient1)"/></g><defs><linearGradient id="gradient0" x1="29.0666" y1="31.0667" x2="38.5332" y2="42.8" gradientUnits="userSpaceOnUse"><stop stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><linearGradient id="gradient1" x1="32.2667" y1="14.4" x2="32.2132" y2="28.5001" gradientUnits="userSpaceOnUse"><stop stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient></defs></svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 997 B

View File

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

View File

@@ -21,7 +21,7 @@ export const frameworks = [
name: 'Blitz.js',
slug: 'blitzjs',
demo: 'https://blitz-template.vercel.app',
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/blitz.svg',
logo: 'https://api-frameworks.vercel.sh/framework-logos/blitz.svg',
tagline: 'Blitz.js: The Fullstack React Framework',
description:
'A brand new Blitz.js app - the result of running `npx blitz new`.',
@@ -58,9 +58,9 @@ export const frameworks = [
name: 'Next.js',
slug: 'nextjs',
demo: 'https://nextjs-template.vercel.app',
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/next.svg',
logo: 'https://api-frameworks.vercel.sh/framework-logos/next.svg',
darkModeLogo:
'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/next-dark.svg',
'https://api-frameworks.vercel.sh/framework-logos/next-dark.svg',
screenshot:
'https://assets.vercel.com/image/upload/v1647366075/front/import/nextjs.png',
tagline:
@@ -108,7 +108,7 @@ export const frameworks = [
name: 'Gatsby.js',
slug: 'gatsby',
demo: 'https://gatsby.vercel.app',
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/gatsby.svg',
logo: 'https://api-frameworks.vercel.sh/framework-logos/gatsby.svg',
tagline:
'Gatsby helps developers build blazing fast websites and apps with React.',
description: 'A Gatsby starter app with an API Route.',
@@ -195,7 +195,7 @@ export const frameworks = [
name: 'Remix',
slug: 'remix',
demo: 'https://remix-run-template.vercel.app',
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/remix-no-shadow.svg',
logo: 'https://api-frameworks.vercel.sh/framework-logos/remix-no-shadow.svg',
tagline: 'Build Better Websites',
description: 'A new Remix app — the result of running `npx create-remix`.',
website: 'https://remix.run',
@@ -232,9 +232,9 @@ export const frameworks = [
name: 'Astro',
slug: 'astro',
demo: 'https://astro-template.vercel.app',
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/astro.svg',
logo: 'https://api-frameworks.vercel.sh/framework-logos/astro.svg',
darkModeLogo:
'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/astro-dark.svg',
'https://api-frameworks.vercel.sh/framework-logos/astro-dark.svg',
tagline:
'Astro is a new kind of static site builder for the modern web. Powerful developer experience meets lightweight output.',
description: 'An Astro site, using the basics starter kit.',
@@ -286,7 +286,7 @@ export const frameworks = [
name: 'Hexo',
slug: 'hexo',
demo: 'https://hexo-template.vercel.app',
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/hexo.svg',
logo: 'https://api-frameworks.vercel.sh/framework-logos/hexo.svg',
tagline:
'Hexo is a fast, simple & powerful blog framework powered by Node.js.',
description: 'A Hexo site, created with the Hexo CLI.',
@@ -323,7 +323,7 @@ export const frameworks = [
name: 'Eleventy',
slug: 'eleventy',
demo: 'https://eleventy-template.vercel.app',
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/eleventy.svg',
logo: 'https://api-frameworks.vercel.sh/framework-logos/eleventy.svg',
tagline:
'11ty is a simpler static site generator written in JavaScript, created to be an alternative to Jekyll.',
description: 'An Eleventy site, created with npm init.',
@@ -361,7 +361,7 @@ export const frameworks = [
name: 'Docusaurus 2',
slug: 'docusaurus-2',
demo: 'https://docusaurus-2-template.vercel.app',
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/docusaurus.svg',
logo: 'https://api-frameworks.vercel.sh/framework-logos/docusaurus.svg',
tagline:
'Docusaurus makes it easy to maintain Open Source documentation websites.',
description:
@@ -449,7 +449,7 @@ export const frameworks = [
name: 'Docusaurus 1',
slug: 'docusaurus',
demo: 'https://docusaurus-template.vercel.app',
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/docusaurus.svg',
logo: 'https://api-frameworks.vercel.sh/framework-logos/docusaurus.svg',
tagline:
'Docusaurus makes it easy to maintain Open Source documentation websites.',
description:
@@ -501,7 +501,7 @@ export const frameworks = [
name: 'Preact',
slug: 'preact',
demo: 'https://preact-template.vercel.app',
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/preact.svg',
logo: 'https://api-frameworks.vercel.sh/framework-logos/preact.svg',
tagline:
'Preact is a fast 3kB alternative to React with the same modern API.',
description: 'A Preact app, created with the Preact CLI.',
@@ -547,7 +547,7 @@ export const frameworks = [
name: 'SolidStart',
slug: 'solidstart',
demo: 'https://solid-start-template.vercel.app',
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/solid.svg',
logo: 'https://api-frameworks.vercel.sh/framework-logos/solid.svg',
tagline: 'Simple and performant reactivity for building user interfaces.',
description: 'A Solid app, created with SolidStart.',
website: 'https://solidjs.com',
@@ -587,7 +587,7 @@ export const frameworks = [
name: 'Dojo',
slug: 'dojo',
demo: 'https://dojo-template.vercel.app',
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/dojo.png',
logo: 'https://api-frameworks.vercel.sh/framework-logos/dojo.png',
tagline: 'Dojo is a modern progressive, TypeScript first framework.',
description:
"A Dojo app, created with the Dojo CLI's cli-create-app command.",
@@ -649,7 +649,7 @@ export const frameworks = [
name: 'Ember.js',
slug: 'ember',
demo: 'https://ember-template.vercel.app',
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/ember.svg',
logo: 'https://api-frameworks.vercel.sh/framework-logos/ember.svg',
tagline:
'Ember.js helps webapp developers be more productive out of the box.',
description: 'An Ember app, created with the Ember CLI.',
@@ -695,7 +695,7 @@ export const frameworks = [
name: 'Vue.js',
slug: 'vue',
demo: 'https://vue-template.vercel.app',
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/vue.svg',
logo: 'https://api-frameworks.vercel.sh/framework-logos/vue.svg',
tagline:
'Vue.js is a versatile JavaScript framework that is as approachable as it is performant.',
description: 'A Vue.js app, created with the Vue CLI.',
@@ -752,7 +752,7 @@ export const frameworks = [
name: 'Scully',
slug: 'scully',
demo: 'https://scully-template.vercel.app',
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/scullyio-logo.png',
logo: 'https://api-frameworks.vercel.sh/framework-logos/scullyio-logo.png',
tagline: 'Scully is a static site generator for Angular.',
description: 'The Static Site Generator for Angular apps.',
website: 'https://github.com/scullyio/scully',
@@ -788,7 +788,7 @@ export const frameworks = [
name: 'Ionic Angular',
slug: 'ionic-angular',
demo: 'https://ionic-angular-template.vercel.app',
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/ionic.svg',
logo: 'https://api-frameworks.vercel.sh/framework-logos/ionic.svg',
tagline:
'Ionic Angular allows you to build mobile PWAs with Angular and the Ionic Framework.',
description: 'An Ionic Angular site, created with the Ionic CLI.',
@@ -833,7 +833,7 @@ export const frameworks = [
name: 'Angular',
slug: 'angular',
demo: 'https://angular-template.vercel.app',
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/angular.svg',
logo: 'https://api-frameworks.vercel.sh/framework-logos/angular.svg',
tagline:
'Angular is a TypeScript-based cross-platform framework from Google.',
description: 'An Angular app, created with the Angular CLI.',
@@ -893,7 +893,7 @@ export const frameworks = [
name: 'Polymer',
slug: 'polymer',
demo: 'https://polymer-template.vercel.app',
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/polymer.svg',
logo: 'https://api-frameworks.vercel.sh/framework-logos/polymer.svg',
tagline:
'Polymer is an open-source webapps library from Google, for building using Web Components.',
description: 'A Polymer app, created with the Polymer CLI.',
@@ -950,7 +950,7 @@ export const frameworks = [
name: 'Svelte',
slug: 'svelte',
demo: 'https://svelte.vercel.app',
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/svelte.svg',
logo: 'https://api-frameworks.vercel.sh/framework-logos/svelte.svg',
tagline:
'Svelte lets you write high performance reactive apps with significantly less boilerplate.',
description: 'A basic Svelte app using the default template.',
@@ -1001,7 +1001,7 @@ export const frameworks = [
name: 'SvelteKit',
slug: 'sveltekit',
demo: 'https://sveltekit-template.vercel.app',
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/svelte.svg',
logo: 'https://api-frameworks.vercel.sh/framework-logos/svelte.svg',
screenshot:
'https://assets.vercel.com/image/upload/v1647366075/front/import/sveltekit.png',
tagline:
@@ -1040,7 +1040,7 @@ export const frameworks = [
name: 'Ionic React',
slug: 'ionic-react',
demo: 'https://ionic-react-template.vercel.app',
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/ionic.svg',
logo: 'https://api-frameworks.vercel.sh/framework-logos/ionic.svg',
tagline:
'Ionic React allows you to build mobile PWAs with React and the Ionic Framework.',
description: 'An Ionic React site, created with the Ionic CLI.',
@@ -1101,7 +1101,7 @@ export const frameworks = [
name: 'Create React App',
slug: 'create-react-app',
demo: 'https://create-react-template.vercel.app',
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/react.svg',
logo: 'https://api-frameworks.vercel.sh/framework-logos/react.svg',
tagline: 'Create React App allows you to get going with React in no time.',
description: 'A client-side React app created with create-react-app.',
website: 'https://create-react-app.dev',
@@ -1168,7 +1168,7 @@ export const frameworks = [
name: 'Gridsome',
slug: 'gridsome',
demo: 'https://gridsome-template.vercel.app',
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/gridsome.svg',
logo: 'https://api-frameworks.vercel.sh/framework-logos/gridsome.svg',
tagline:
'Gridsome is a Vue.js-powered framework for building websites & apps that are fast by default.',
description: 'A Gridsome app, created with the Gridsome CLI.',
@@ -1205,7 +1205,7 @@ export const frameworks = [
name: 'UmiJS',
slug: 'umijs',
demo: 'https://umijs-template.vercel.app',
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/umi.svg',
logo: 'https://api-frameworks.vercel.sh/framework-logos/umi.svg',
tagline:
'UmiJS is an extensible enterprise-level React application framework.',
description: 'An UmiJS app, created using the Umi CLI.',
@@ -1251,7 +1251,7 @@ export const frameworks = [
name: 'Sapper',
slug: 'sapper',
demo: 'https://sapper-template.vercel.app',
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/svelte.svg',
logo: 'https://api-frameworks.vercel.sh/framework-logos/svelte.svg',
tagline:
'Sapper is a framework for building high-performance universal web apps with Svelte.',
description: 'A Sapper app, using the Sapper template.',
@@ -1288,7 +1288,7 @@ export const frameworks = [
name: 'Saber',
slug: 'saber',
demo: 'https://saber-template.vercel.app',
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/saber.svg',
logo: 'https://api-frameworks.vercel.sh/framework-logos/saber.svg',
tagline:
'Saber is a framework for building static sites in Vue.js that supports data from any source.',
description: 'A Saber site, created with npm init.',
@@ -1339,7 +1339,7 @@ export const frameworks = [
name: 'Stencil',
slug: 'stencil',
demo: 'https://stencil.vercel.app',
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/stencil.svg',
logo: 'https://api-frameworks.vercel.sh/framework-logos/stencil.svg',
tagline:
'Stencil is a powerful toolchain for building Progressive Web Apps and Design Systems.',
description: 'A Stencil site, created with the Stencil CLI.',
@@ -1400,7 +1400,7 @@ export const frameworks = [
name: 'Nuxt.js',
slug: 'nuxtjs',
demo: 'https://nuxtjs-template.vercel.app',
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/nuxt.svg',
logo: 'https://api-frameworks.vercel.sh/framework-logos/nuxt.svg',
screenshot:
'https://assets.vercel.com/image/upload/v1647366075/front/import/nuxtjs.png',
tagline:
@@ -1460,7 +1460,7 @@ export const frameworks = [
name: 'RedwoodJS',
slug: 'redwoodjs',
demo: 'https://redwood-template.vercel.app',
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/redwoodjs.svg',
logo: 'https://api-frameworks.vercel.sh/framework-logos/redwoodjs.svg',
tagline: 'RedwoodJS is a full-stack framework for the Jamstack.',
description: 'A RedwoodJS app, bootstraped with create-redwood-app.',
website: 'https://redwoodjs.com',
@@ -1497,7 +1497,7 @@ export const frameworks = [
name: 'Hugo',
slug: 'hugo',
demo: 'https://hugo-template.vercel.app',
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/hugo.svg',
logo: 'https://api-frameworks.vercel.sh/framework-logos/hugo.svg',
tagline:
'Hugo is the worlds fastest framework for building websites, written in Go.',
description: 'A Hugo site, created with the Hugo CLI.',
@@ -1550,7 +1550,7 @@ export const frameworks = [
name: 'Jekyll',
slug: 'jekyll',
demo: 'https://jekyll-template.vercel.app',
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/jekyll.svg',
logo: 'https://api-frameworks.vercel.sh/framework-logos/jekyll.svg',
tagline:
'Jekyll makes it super easy to transform your plain text into static websites and blogs.',
description: 'A Jekyll site, created with the Jekyll CLI.',
@@ -1591,7 +1591,7 @@ export const frameworks = [
name: 'Brunch',
slug: 'brunch',
demo: 'https://brunch-template.vercel.app',
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/brunch.svg',
logo: 'https://api-frameworks.vercel.sh/framework-logos/brunch.svg',
tagline:
'Brunch is a fast and simple webapp build tool with seamless incremental compilation for rapid development.',
description: 'A Brunch app, created with the Brunch CLI.',
@@ -1625,7 +1625,7 @@ export const frameworks = [
name: 'Middleman',
slug: 'middleman',
demo: 'https://middleman-template.vercel.app',
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/middleman.svg',
logo: 'https://api-frameworks.vercel.sh/framework-logos/middleman.svg',
tagline:
'Middleman is a static site generator that uses all the shortcuts and tools in modern web development.',
description: 'A Middleman app, created with the Middleman CLI.',
@@ -1660,7 +1660,7 @@ export const frameworks = [
name: 'Zola',
slug: 'zola',
demo: 'https://zola-template.vercel.app',
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/zola.png',
logo: 'https://api-frameworks.vercel.sh/framework-logos/zola.png',
tagline: 'Everything you need to make a static site engine in one binary.',
description: 'A Zola app, created with the "Getting Started" tutorial.',
website: 'https://www.getzola.org',
@@ -1694,7 +1694,7 @@ export const frameworks = [
name: 'Vite',
slug: 'vite',
demo: 'https://vite-vue-template.vercel.app',
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/vite.svg',
logo: 'https://api-frameworks.vercel.sh/framework-logos/vite.svg',
tagline:
'Vite is a new breed of frontend build tool that significantly improves the frontend development experience.',
description: 'A Vue.js app, created with Vite.',
@@ -1732,7 +1732,7 @@ export const frameworks = [
name: 'Parcel',
slug: 'parcel',
demo: 'https://parcel-template.vercel.app',
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/parcel.png',
logo: 'https://api-frameworks.vercel.sh/framework-logos/parcel.png',
tagline:
'Parcel is a zero configuration build tool for the web that scales to projects of any size and complexity.',
description: 'A vanilla web app built with Parcel.',
@@ -1779,16 +1779,22 @@ export const frameworks = [
name: 'Sanity',
slug: 'sanity',
demo: 'https://sanity-studio-template.vercel.app',
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/sanity.svg',
logo: 'https://api-frameworks.vercel.sh/framework-logos/sanity.svg',
tagline: 'The structured content platform.',
description: 'A Sanity Studio',
website: 'https://www.sanity.io',
envPrefix: 'SANITY_STUDIO_',
detectors: {
every: [
some: [
{
path: 'sanity.json',
},
{
path: 'sanity.config.js',
},
{
path: 'sanity.config.ts',
},
],
},
settings: {
@@ -1822,7 +1828,7 @@ export const frameworks = [
name: 'Hydrogen',
slug: 'hydrogen',
demo: 'https://hydrogen-template.vercel.app',
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/hydrogen.svg',
logo: 'https://api-frameworks.vercel.sh/framework-logos/hydrogen.svg',
tagline: 'React framework for headless commerce',
description: 'React framework for headless commerce',
website: 'https://hydrogen.shopify.dev',
@@ -1856,7 +1862,7 @@ export const frameworks = [
{
name: 'Other',
slug: null,
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/other.svg',
logo: 'https://api-frameworks.vercel.sh/framework-logos/other.svg',
description: 'No framework or an unoptimized framework.',
settings: {
installCommand: {

View File

@@ -53,12 +53,12 @@ export interface Framework {
slug: string | null;
/**
* A URL to the logo of the framework
* @example "https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/next.svg"
* @example "https://api-frameworks.vercel.sh/framework-logos/next.svg"
*/
logo: string;
/**
* An additional URL to the logo of the framework optimized for dark mode
* @example "https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/next-dark.svg"
* @example "https://api-frameworks.vercel.sh/framework-logos/next-dark.svg"
*/
darkModeLogo?: string;
/**

View File

@@ -10,6 +10,8 @@ import frameworkList from '../src/frameworks';
// bump timeout for Windows as network can be slower
jest.setTimeout(15 * 1000);
const logoPrefix = 'https://api-frameworks.vercel.sh/framework-logos/';
const SchemaFrameworkDetectionItem = {
type: 'array',
items: [
@@ -172,14 +174,33 @@ describe('frameworks', () => {
expect(result).toBe(true);
});
it('ensure logo', async () => {
it('ensure logo starts with url prefix', async () => {
const invalid = frameworkList
.map(f => f.logo)
.filter(logo => {
return logo && !logo.startsWith(logoPrefix);
});
expect(invalid).toEqual([]);
});
it('ensure darkModeLogo starts with url prefix', async () => {
const invalid = frameworkList
.map(f => f.darkModeLogo)
.filter(darkModeLogo => {
return darkModeLogo && !darkModeLogo.startsWith(logoPrefix);
});
expect(invalid).toEqual([]);
});
it('ensure logo file exists in ./packages/frameworks/logos/', async () => {
const missing = frameworkList
.map(f => f.logo)
.filter(url => {
const prefix =
'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/';
const name = url.replace(prefix, '');
return existsSync(join(__dirname, '..', 'logos', name)) === false;
.filter(logo => {
const filename = logo.slice(logoPrefix.length);
const filepath = join(__dirname, '..', 'logos', filename);
return existsSync(filepath) === false;
});
expect(missing).toEqual([]);

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/fs-detectors",
"version": "2.1.0",
"version": "3.2.0",
"description": "Vercel filesystem detectors",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
@@ -19,7 +19,7 @@
"test-unit": "yarn test"
},
"dependencies": {
"@vercel/frameworks": "1.1.3",
"@vercel/frameworks": "1.1.5",
"@vercel/routing-utils": "2.0.2",
"glob": "8.0.3",
"js-yaml": "4.1.0",

View File

@@ -1,3 +1,5 @@
import { posix as posixPath } from 'path';
export interface Stat {
name: string;
path: string;
@@ -76,12 +78,43 @@ export abstract class DetectorFilesystem {
/**
* Returns a list of Stat objects from the current working directory.
* @param dirPath The path of the directory to read.
* @param options.potentialFiles optional. Array of potential file names (relative to the path). If provided, these will be used to mark the filesystem caches as existing or not existing.
*/
public readdir = async (name: string): Promise<Stat[]> => {
let p = this.readdirCache.get(name);
public readdir = async (
dirPath: string,
options?: { potentialFiles?: string[] }
): Promise<Stat[]> => {
let p = this.readdirCache.get(dirPath);
if (!p) {
p = this._readdir(name);
this.readdirCache.set(name, p);
p = this._readdir(dirPath);
this.readdirCache.set(dirPath, p);
const directoryContent = await p;
const directoryFiles = new Set<string>();
for (const file of directoryContent) {
if (file.type === 'file') {
// we know this file exists, mark it as so on the filesystem
this.fileCache.set(file.path, Promise.resolve(true));
this.pathCache.set(file.path, Promise.resolve(true));
directoryFiles.add(file.name);
}
}
if (options?.potentialFiles) {
// calculate the set of paths that truly do not exist
const filesThatDoNotExist = options.potentialFiles.filter(
path => !directoryFiles.has(path)
);
for (const filePath of filesThatDoNotExist) {
const fullFilePath =
dirPath === '/' ? filePath : posixPath.join(dirPath, filePath);
// we know this file does not exist, mark it as so on the filesystem
this.fileCache.set(fullFilePath, Promise.resolve(false));
this.pathCache.set(fullFilePath, Promise.resolve(false));
}
}
}
return p;
};
@@ -98,10 +131,9 @@ export abstract class DetectorFilesystem {
* @param name the name of the file to write
* @param content The content of the file
*/
public writeFile(name: string, content?: string): void {
if (content)
this.readFileCache.set(name, Promise.resolve(Buffer.from(content)));
public writeFile = async (name: string, content: string): Promise<void> => {
this.readFileCache.set(name, Promise.resolve(Buffer.from(content)));
this.fileCache.set(name, Promise.resolve(true));
this.pathCache.set(name, Promise.resolve(true));
}
};
}

View File

@@ -31,6 +31,28 @@ export const monorepoManagers: Array<
],
},
},
{
name: 'Nx',
slug: 'nx',
detectors: {
every: [
{
path: 'nx.json',
},
],
},
},
{
name: 'Rush',
slug: 'rush',
detectors: {
every: [
{
path: 'rush.json',
},
],
},
},
];
export default monorepoManagers;

View File

@@ -33,6 +33,12 @@ export async function getWorkspacePackagePaths({
case 'pnpm':
results = await getPnpmWorkspacePackagePaths({ fs: workspaceFs });
break;
case 'rush':
// /common/temp is the location that Rush defaults adding the pnpm workspace file
results = await getPnpmWorkspacePackagePaths({
fs: fs.chdir('/common/temp'),
});
break;
default:
throw new Error(`Unknown workspace implementation: ${type}`);
}

View File

@@ -12,7 +12,7 @@ export interface GetWorkspaceOptions {
cwd?: string;
}
export type WorkspaceType = 'yarn' | 'pnpm' | 'npm';
export type WorkspaceType = 'yarn' | 'pnpm' | 'npm' | 'rush';
export type Workspace = {
type: WorkspaceType;

View File

@@ -59,6 +59,18 @@ export const workspaceManagers: Array<
],
},
},
{
name: 'rush',
slug: 'rush',
detectors: {
every: [
{
path: 'rush.json',
matchContent: '"useWorkspaces":\\strue',
},
],
},
},
{
name: 'default',
slug: 'yarn',

View File

@@ -0,0 +1,119 @@
{
"projectType": "application",
"generators": {
"@nrwl/workspace:component": {
"style": "scss"
}
},
"sourceRoot": "apps/products/src",
"prefix": "nx-example",
"targets": {
"build": {
"executor": "@angular-devkit/build-angular:browser",
"options": {
"aot": true,
"outputPath": "dist/apps/products",
"index": "apps/products/src/index.html",
"main": "apps/products/src/main.ts",
"polyfills": "apps/products/src/polyfills.ts",
"tsConfig": "apps/products/tsconfig.app.json",
"assets": [
"apps/products/src/_redirects",
{
"input": "libs/shared/assets/src/assets",
"glob": "**/*",
"output": "assets"
},
{
"input": "libs/shared/assets/src",
"glob": "favicon.ico",
"output": "."
}
],
"styles": [
"libs/shared/styles/src/index.scss",
"libs/shared/header/index.scss",
"node_modules/normalize.css/normalize.css"
],
"scripts": []
},
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "apps/products/src/environments/environment.ts",
"with": "apps/products/src/environments/environment.prod.ts"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"budgets": [
{
"type": "initial",
"maximumWarning": "2mb",
"maximumError": "5mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "6kb"
}
]
}
},
"outputs": ["{options.outputPath}"]
},
"serve": {
"executor": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "products:build"
},
"configurations": {
"production": {
"browserTarget": "products:build:production"
}
}
},
"extract-i18n": {
"executor": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "products:build"
}
},
"lint": {
"executor": "@nrwl/linter:eslint",
"options": {
"lintFilePatterns": [
"apps/products/src/**/*.ts",
"apps/products/src/**/*.html"
]
},
"outputs": ["{options.outputFile}"]
},
"test": {
"executor": "@nrwl/jest:jest",
"options": {
"jestConfig": "apps/products/jest.config.ts",
"passWithNoTests": true
},
"outputs": ["coverage/apps/products"]
},
"deploy": {
"executor": "@nrwl/workspace:run-commands",
"options": {
"commands": [
{
"command": "npx ts-node --project tools/tsconfig.tools.json tools/scripts/deploy --siteName nrwl-nx-examples-products --outputPath dist/apps/products"
}
]
}
}
},
"tags": ["type:app", "scope:products"],
"implicitDependencies": ["shared-assets", "shared-styles"]
}

View File

@@ -0,0 +1,51 @@
{
"implicitDependencies": {
"package.json": {
"dependencies": "*",
"devDependencies": "*"
},
".eslintrc.json": "*"
},
"affected": {
"defaultBase": "master"
},
"npmScope": "nx-example",
"tasksRunnerOptions": {
"default": {
"runner": "@nrwl/nx-cloud",
"options": {
"accessToken": "YmM1MGMwMTUtNzAyYi00ZjM4LWExNGUtZDM2ZjYyNzNiODAxfHJlYWQ=",
"cacheableOperations": ["build", "lint", "test"],
"parallel": 1
}
}
},
"cli": {
"warnings": {
"versionMismatch": false
},
"packageManager": "yarn",
"analytics": false
},
"generators": {
"@nrwl/angular:application": {
"unitTestRunner": "jest",
"e2eTestRunner": "cypress"
},
"@nrwl/angular:library": {
"unitTestRunner": "jest"
},
"@nrwl/angular": {
"convert-tslint-to-eslint": {
"removeTSLintIfNoMoreTSLintTargets": true
}
}
},
"defaultProject": "app",
"$schema": "./node_modules/nx/schemas/nx-schema.json",
"targetDefaults": {
"build": {
"dependsOn": ["^build"]
}
}
}

View File

@@ -0,0 +1,27 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/rush/v5/rush.schema.json",
"rushVersion": "5.76.1",
"pnpmVersion": "6.7.1",
"pnpmOptions": {
"useWorkspaces": true
},
"nodeSupportedVersionRange": ">=12.13.0 <13.0.0 || >=14.15.0 <15.0.0 || >=16.13.0 <17.0.0",
"gitPolicy": {},
"repository": {},
"eventHooks": {
"preRushInstall": [],
"postRushInstall": [],
"preRushBuild": [],
"postRushBuild": []
},
"variants": [],
"projects": []
}

View File

@@ -8,6 +8,8 @@ describe('monorepo-managers', () => {
['28-turborepo-with-yarn-workspaces', 'turbo'],
['31-turborepo-in-package-json', 'turbo'],
['22-pnpm', null],
['39-nx-monorepo', 'nx'],
['40-rush-monorepo', 'rush'],
])('with detectFramework', (fixturePath, frameworkSlug) => {
const testName = frameworkSlug
? `should detect a ${frameworkSlug} workspace for ${fixturePath}`

View File

@@ -135,11 +135,18 @@ describe('DetectorFilesystem', () => {
};
const fs = new VirtualFilesystem(files);
const hasPathSpy = jest.spyOn(fs, '_hasPath');
expect(await fs.readdir('/')).toEqual([
expect(await fs.readdir('/', { potentialFiles: ['config.rb'] })).toEqual([
{ name: 'package.json', path: 'package.json', type: 'file' },
{ name: 'packages', path: 'packages', type: 'dir' },
]);
expect(await fs.hasPath('package.json')).toBe(true);
expect(hasPathSpy).not.toHaveBeenCalled();
expect(await fs.hasPath('config.rb')).toBe(false);
expect(hasPathSpy).not.toHaveBeenCalled();
expect(await fs.hasPath('tsconfig.json')).toBe(false);
expect(hasPathSpy).toHaveBeenCalled();
expect(await fs.readdir('packages')).toEqual([
{ name: 'app1', path: 'packages/app1', type: 'dir' },
@@ -151,24 +158,37 @@ describe('DetectorFilesystem', () => {
{ name: 'app2', path: 'packages/app2', type: 'dir' },
]);
expect(await fs.readdir('packages/app1')).toEqual([
expect(
await fs.readdir('packages/app1', { potentialFiles: ['package.json'] })
).toEqual([
{
name: 'package.json',
path: 'packages/app1/package.json',
type: 'file',
},
]);
hasPathSpy.mock.calls.length = 0;
expect(await fs.hasPath('packages/app1/package.json')).toBe(true);
expect(hasPathSpy).not.toHaveBeenCalled();
});
it('should be able to write files', async () => {
const files = {};
const fs = new VirtualFilesystem(files);
const hasPathSpy = jest.spyOn(fs, '_hasPath');
const isFileSpy = jest.spyOn(fs, '_isFile');
const readFileSpy = jest.spyOn(fs, '_readFile');
fs.writeFile('file.txt', 'Hello World');
await fs.writeFile('file.txt', 'Hello World');
expect(await fs.readFile('file.txt')).toEqual(Buffer.from('Hello World'));
expect(await fs.hasPath('file.txt')).toBe(true);
expect(await fs.isFile('file.txt')).toBe(true);
// We expect that the fs returned values from it's caches instead of calling the underlying functions
expect(hasPathSpy).not.toHaveBeenCalled();
expect(isFileSpy).not.toHaveBeenCalled();
expect(readFileSpy).not.toHaveBeenCalled();
});
it('should be able to change directories', async () => {

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/go",
"version": "2.2.4",
"version": "2.2.5",
"license": "MIT",
"main": "./dist/index",
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/go",
@@ -35,7 +35,7 @@
"@types/jest": "28.1.6",
"@types/node-fetch": "^2.3.0",
"@types/tar": "^4.0.0",
"@vercel/build-utils": "5.4.1",
"@vercel/build-utils": "5.4.2",
"@vercel/ncc": "0.24.0",
"async-retry": "1.3.1",
"execa": "^1.0.0",

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/hydrogen",
"version": "0.0.17",
"version": "0.0.18",
"license": "MIT",
"main": "./dist/index.js",
"homepage": "https://vercel.com/docs",
@@ -21,7 +21,7 @@
"devDependencies": {
"@types/jest": "27.5.1",
"@types/node": "*",
"@vercel/build-utils": "5.4.1",
"@vercel/build-utils": "5.4.2",
"typescript": "4.6.4"
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/next",
"version": "3.1.23",
"version": "3.1.25",
"license": "MIT",
"main": "./dist/index",
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/next-js",
@@ -44,8 +44,8 @@
"@types/semver": "6.0.0",
"@types/text-table": "0.2.1",
"@types/webpack-sources": "3.2.0",
"@vercel/build-utils": "5.4.1",
"@vercel/nft": "0.21.0",
"@vercel/build-utils": "5.4.2",
"@vercel/nft": "0.22.1",
"@vercel/routing-utils": "2.0.2",
"async-sema": "3.0.1",
"buffer-crc32": "0.2.13",

View File

@@ -2636,7 +2636,10 @@ async function getServerlessPages(params: {
for (const [entry, normalizedEntry] of Object.entries(
params.appPathRoutesManifest
)) {
const normalizedPath = `${path.join('.', normalizedEntry)}.js`;
const normalizedPath = `${path.join(
'.',
normalizedEntry === '/' ? '/index' : normalizedEntry
)}.js`;
const globPath = `${path.join('.', entry)}.js`;
if (appPaths[globPath]) {

View File

@@ -2352,7 +2352,22 @@ export async function getMiddlewareBundle({
for (const worker of workerConfigs.values()) {
const edgeFile = worker.edgeFunction.name;
const shortPath = edgeFile.replace(/^pages\//, '');
let shortPath = edgeFile;
// Replacing the folder prefix for the page
//
// For `pages/`, use file base name directly:
// pages/index -> index
// For `app/`, use folder name, handle the root page as index:
// app/route/page -> route
// app/page -> index
// app/index/page -> index/index
if (shortPath.startsWith('pages/')) {
shortPath = shortPath.replace(/^pages\//, '');
} else if (shortPath.startsWith('app/') && shortPath.endsWith('/page')) {
shortPath =
shortPath.replace(/^app\//, '').replace(/(^|\/)page$/, '') || 'index';
}
worker.edgeFunction.name = shortPath;
source.edgeFunctions[shortPath] = worker.edgeFunction;

View File

@@ -0,0 +1,7 @@
export default function Page() {
return <p>edge</p>;
}
export const config = {
runtime: 'experimental-edge',
};

View File

@@ -0,0 +1,7 @@
export default function page() {
return 'index/page';
}
export const config = {
runtime: 'experimental-edge',
};

View File

@@ -0,0 +1,7 @@
export default function page() {
return 'page';
}
export const config = {
runtime: 'experimental-edge',
};

View File

@@ -0,0 +1,9 @@
module.exports = {
experimental: {
appDir: true,
runtime: 'experimental-edge',
serverComponents: true,
legacyBrowsers: false,
browsersListForSwc: true,
},
};

View File

@@ -0,0 +1,7 @@
{
"dependencies": {
"next": "canary",
"react": "experimental",
"react-dom": "experimental"
}
}

View File

@@ -0,0 +1,15 @@
{
"builds": [
{
"src": "package.json",
"use": "@vercel/next"
}
],
"probes": [
{
"path": "/edge",
"status": 200,
"mustContain": "edge"
}
]
}

View File

@@ -0,0 +1,3 @@
export default function Page() {
return <p>index app page</p>;
}

View File

@@ -1,6 +1,6 @@
{
"dependencies": {
"next": "https://files-26yo0dy1b-ijjk-testing.vercel.app",
"next": "canary",
"react": "experimental",
"react-dom": "experimental"
}

View File

@@ -1,9 +0,0 @@
import Link from 'next/link';
export default function Page(props) {
return (
<>
<p>hello from pages/index</p>
<Link href="/dashboard">Dashboard</Link>
</>
);
}

View File

@@ -24,7 +24,7 @@
{
"path": "/",
"status": 200,
"mustContain": "hello from pages/index"
"mustContain": "index app page"
},
{
"path": "/blog/123",

View File

@@ -17,7 +17,6 @@ it('should build with app-dir correctly', async () => {
for (const key of Object.keys(buildResult.output)) {
if (buildResult.output[key].type === 'Lambda') {
lambdas.add(buildResult.output[key]);
console.log('found lambda', key);
}
}
expect(lambdas.size).toBe(1);
@@ -27,6 +26,26 @@ it('should build with app-dir correctly', async () => {
expect(buildResult.output['dashboard/deployments/[id]']).toBeDefined();
});
it('should build with app-dir in edg runtime correctly', async () => {
const { buildResult } = await runBuildLambda(
path.join(__dirname, '../fixtures/00-app-dir-edge')
);
console.log('buildResult', buildResult);
const edgeFunctions = new Set();
for (const key of Object.keys(buildResult.output)) {
if (buildResult.output[key].type === 'EdgeFunction') {
edgeFunctions.add(buildResult.output[key]);
}
}
expect(edgeFunctions.size).toBe(3);
expect(buildResult.output['edge']).toBeDefined();
expect(buildResult.output['index']).toBeDefined();
expect(buildResult.output['index/index']).toBeDefined();
});
it('should show error from basePath with legacy monorepo build', async () => {
let error;

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/node",
"version": "2.5.12",
"version": "2.5.14",
"license": "MIT",
"main": "./dist/index",
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/node-js",
@@ -29,12 +29,12 @@
}
},
"dependencies": {
"@edge-runtime/vm": "1.1.0-beta.23",
"@edge-runtime/vm": "1.1.0-beta.32",
"@types/node": "*",
"@vercel/build-utils": "5.4.1",
"@vercel/build-utils": "5.4.2",
"@vercel/node-bridge": "3.0.0",
"@vercel/static-config": "2.0.3",
"edge-runtime": "1.1.0-beta.23",
"edge-runtime": "1.1.0-beta.32",
"esbuild": "0.14.47",
"exit-hook": "2.2.1",
"node-fetch": "2.6.7",
@@ -53,7 +53,7 @@
"@types/node-fetch": "^2.6.1",
"@types/test-listen": "1.1.0",
"@vercel/ncc": "0.24.0",
"@vercel/nft": "0.22.0",
"@vercel/nft": "0.22.1",
"content-type": "1.0.4",
"cookie": "0.4.0",
"etag": "1.8.1",

View File

@@ -151,7 +151,8 @@ async function serializeRequest(message: IncomingMessage) {
async function compileUserCode(
entrypointPath: string,
entrypointLabel: string
entrypointLabel: string,
isMiddleware: boolean
): Promise<undefined | { userCode: string; wasmAssets: WasmAssets }> {
const { wasmAssets, plugin: edgeWasmPlugin } = createEdgeWasmPlugin();
try {
@@ -176,6 +177,8 @@ async function compileUserCode(
const userCode = `
${compiledFile.text};
const isMiddleware = ${isMiddleware};
addEventListener('fetch', async (event) => {
try {
let serializedRequest = await event.request.text();
@@ -205,7 +208,16 @@ async function compileUserCode(
let response = await edgeHandler(event.request, event);
if (!response) {
throw new Error('Edge Function "${entrypointLabel}" did not return a response.');
if (isMiddleware) {
// allow empty responses to pass through
response = new Response(null, {
headers: {
'x-middleware-next': '1',
},
});
} else {
throw new Error('Edge Function "${entrypointLabel}" did not return a response.');
}
}
return event.respondWith(response);
@@ -280,9 +292,14 @@ async function createEdgeRuntime(params?: {
async function createEdgeEventHandler(
entrypointPath: string,
entrypointLabel: string
entrypointLabel: string,
isMiddleware: boolean
): Promise<(request: IncomingMessage) => Promise<VercelProxyResponse>> {
const userCode = await compileUserCode(entrypointPath, entrypointLabel);
const userCode = await compileUserCode(
entrypointPath,
entrypointLabel,
isMiddleware
);
const server = await createEdgeRuntime(userCode);
return async function (request: IncomingMessage) {
@@ -352,7 +369,11 @@ async function createEventHandler(
// an Edge Function, otherwise needs to be opted-in via
// `export const config = { runtime: 'experimental-edge' }`
if (config.middleware === true || runtime === 'experimental-edge') {
return createEdgeEventHandler(entrypointPath, entrypoint);
return createEdgeEventHandler(
entrypointPath,
entrypoint,
config.middleware || false
);
}
return createServerlessEventHandler(entrypointPath, options);

View File

@@ -1,12 +0,0 @@
import { readFileSync } from 'fs';
import { join } from 'path';
export default function handler(_req, res) {
// This build.js asset should be included but not the dep.js asset
// because this is readFile(), not require(). It also shouldn't transpile
// with babel because it should be considered an asset.
const file = join(process.cwd(), 'assets', 'build.js');
const content = readFileSync(file, 'utf8');
res.setHeader('Content-Type', 'application/javascript');
return res.end(content);
}

View File

@@ -1 +0,0 @@
import dep from './dep.js';

View File

@@ -1,3 +0,0 @@
// This file should not be included because the
// api/index.js is performing a readFile(), not require().
export const dep = 'dep1';

View File

@@ -1,8 +0,0 @@
{
"probes": [
{
"path": "/api",
"mustContain": "import dep from './dep.js';"
}
]
}

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/python",
"version": "3.1.13",
"version": "3.1.14",
"main": "./dist/index.js",
"license": "MIT",
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/python",
@@ -22,7 +22,7 @@
"devDependencies": {
"@types/execa": "^0.9.0",
"@types/jest": "27.4.1",
"@vercel/build-utils": "5.4.1",
"@vercel/build-utils": "5.4.2",
"@vercel/ncc": "0.24.0",
"execa": "^1.0.0",
"typescript": "4.3.4"

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/redwood",
"version": "1.0.21",
"version": "1.0.23",
"main": "./dist/index.js",
"license": "MIT",
"homepage": "https://vercel.com/docs",
@@ -19,7 +19,7 @@
"test-unit": "yarn test test/prepare-cache.test.js"
},
"dependencies": {
"@vercel/nft": "0.22.0",
"@vercel/nft": "0.22.1",
"@vercel/routing-utils": "2.0.2",
"semver": "6.1.1"
},
@@ -27,6 +27,6 @@
"@types/aws-lambda": "8.10.19",
"@types/node": "*",
"@types/semver": "6.0.0",
"@vercel/build-utils": "5.4.1"
"@vercel/build-utils": "5.4.2"
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/remix",
"version": "1.0.22",
"version": "1.0.24",
"license": "MIT",
"main": "./dist/index.js",
"homepage": "https://vercel.com/docs",
@@ -20,12 +20,12 @@
"default-server.js"
],
"dependencies": {
"@vercel/nft": "0.22.0"
"@vercel/nft": "0.22.1"
},
"devDependencies": {
"@types/jest": "27.5.1",
"@types/node": "*",
"@vercel/build-utils": "5.4.1",
"@vercel/build-utils": "5.4.2",
"typescript": "4.6.4"
}
}

View File

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

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/static-build",
"version": "1.0.21",
"version": "1.0.23",
"license": "MIT",
"main": "./dist/index",
"homepage": "https://vercel.com/docs/build-step",
@@ -36,8 +36,8 @@
"@types/ms": "0.7.31",
"@types/node-fetch": "2.5.4",
"@types/promise-timeout": "1.3.0",
"@vercel/build-utils": "5.4.1",
"@vercel/frameworks": "1.1.3",
"@vercel/build-utils": "5.4.2",
"@vercel/frameworks": "1.1.5",
"@vercel/ncc": "0.24.0",
"@vercel/routing-utils": "2.0.2",
"fs-extra": "10.0.0",

View File

@@ -719,10 +719,10 @@
dependencies:
"@jridgewell/trace-mapping" "0.3.9"
"@edge-runtime/format@^1.1.0-beta.23":
version "1.1.0-beta.23"
resolved "https://registry.yarnpkg.com/@edge-runtime/format/-/format-1.1.0-beta.23.tgz#c28fddee0c45a62be63f691a01306c611c99e739"
integrity sha512-TuY7ywLzp2XQQZpM8cX1dzm2QMK2juvtpMVR8K61utL2qvokzJ4gBYLcPSKhH0EWAt4WwgymNVRX0cpdSLAqAg==
"@edge-runtime/format@^1.1.0-beta.32":
version "1.1.0-beta.32"
resolved "https://registry.yarnpkg.com/@edge-runtime/format/-/format-1.1.0-beta.32.tgz#6f0d5a8726cc54ebb2b1dcb86fe25c0ff093731d"
integrity sha512-wpQtbgHJuSF1fvDV6Gxg2L7uNpzhQnRl91DREgOdRfa3S8y9AANjPi1/g3GPBGPiGZoX2Fv+MKV6RgY5/jLfJA==
"@edge-runtime/jest-environment@1.1.0-beta.7":
version "1.1.0-beta.7"
@@ -736,22 +736,22 @@
jest-mock "28.1.1"
jest-util "28.1.1"
"@edge-runtime/primitives@^1.1.0-beta.23":
version "1.1.0-beta.23"
resolved "https://registry.yarnpkg.com/@edge-runtime/primitives/-/primitives-1.1.0-beta.23.tgz#b9b8d83e3dce63286cf80b8d5ece43f32420c4ab"
integrity sha512-0vHcZZwyxjmw/so9irYtA82/+nAlJRs+1WpRYBx7iae1FOGCPM4BIKEmboWmwTuj7c6avz9kIbptokdMUPgV9A==
"@edge-runtime/primitives@^1.1.0-beta.32":
version "1.1.0-beta.33"
resolved "https://registry.yarnpkg.com/@edge-runtime/primitives/-/primitives-1.1.0-beta.33.tgz#9bd0d866addfdc98ec32ff3ca0f6d24f412a5c03"
integrity sha512-mAZw/YRhwkaPVYwSwOTJTMMzZxfuLze6VEepsrVO/4yjnxriOf2GREgLal6OBtTcEEC44q4lqS+OSd0QaSFZEQ==
"@edge-runtime/primitives@^1.1.0-beta.7":
version "1.1.0-beta.7"
resolved "https://registry.yarnpkg.com/@edge-runtime/primitives/-/primitives-1.1.0-beta.7.tgz#0450ee3e5e03a8898ee072c0d0ee01fd2c1ed8f1"
integrity sha512-ZwuSMpmrf2mAj/O7EWxKOXrC03YMkU64N+CgvVFOtJGfhydk4Db/392Zama3BjNYAMOr/oY9L7HxfPutAFesKw==
"@edge-runtime/vm@1.1.0-beta.23", "@edge-runtime/vm@^1.1.0-beta.23":
version "1.1.0-beta.23"
resolved "https://registry.yarnpkg.com/@edge-runtime/vm/-/vm-1.1.0-beta.23.tgz#b55d9add18cb7bb57acf184f6cd7b6edec782a25"
integrity sha512-XBp3rCuX4scJVOo2KconAotL5XGX3zdd8IkfDNr5VVSQ/B6HkiTNuf+EvzSQTpplF+fiyLTpfcP9EbNLibwLTA==
"@edge-runtime/vm@1.1.0-beta.32", "@edge-runtime/vm@^1.1.0-beta.32":
version "1.1.0-beta.32"
resolved "https://registry.yarnpkg.com/@edge-runtime/vm/-/vm-1.1.0-beta.32.tgz#1bc9c77a88343478d50009f30813b9fbf8a0f4ad"
integrity sha512-G0SH80am2XjlK6oFI3RoKlg1SBS5ZAeqakYasfNhJEXqM7g7tsoh5jURMQcNxpLvo48XBTgHgAVEMzhAGgDPZg==
dependencies:
"@edge-runtime/primitives" "^1.1.0-beta.23"
"@edge-runtime/primitives" "^1.1.0-beta.32"
"@edge-runtime/vm@^1.1.0-beta.7":
version "1.1.0-beta.7"
@@ -3212,27 +3212,10 @@
resolved "https://registry.yarnpkg.com/@vercel/ncc/-/ncc-0.24.0.tgz#a2e8783a185caa99b5d8961a57dfc9665de16296"
integrity sha512-crqItMcIwCkvdXY/V3/TzrHJQx6nbIaRqE1cOopJhgGX6izvNov40SmD//nS5flfEvdK54YGjwVVq+zG6crjOg==
"@vercel/nft@0.21.0":
version "0.21.0"
resolved "https://registry.yarnpkg.com/@vercel/nft/-/nft-0.21.0.tgz#e0715b1997cd7021a7c7c48b584ef2295fd4b810"
integrity sha512-hFCAETfI5cG8l5iAiLhMC2bReC5K7SIybzrxGorv+eGspIbIFsVw7Vg85GovXm/LxA08pIDrAlrhR6GN36XB/Q==
dependencies:
"@mapbox/node-pre-gyp" "^1.0.5"
acorn "^8.6.0"
async-sema "^3.1.1"
bindings "^1.4.0"
estree-walker "2.0.2"
glob "^7.1.3"
graceful-fs "^4.2.9"
micromatch "^4.0.2"
node-gyp-build "^4.2.2"
resolve-from "^5.0.0"
rollup-pluginutils "^2.8.2"
"@vercel/nft@0.22.0":
version "0.22.0"
resolved "https://registry.yarnpkg.com/@vercel/nft/-/nft-0.22.0.tgz#586ed4edfd0dabc9bf07525044782198a0b31199"
integrity sha512-hB80/093PPiCefN2gVbqv6J93MH+63Zr7uDCwkiS/U4W07DXkLoftbnkBmZoS0Q84LiTSl9DRVSHU4XYCX+sJA==
"@vercel/nft@0.22.1":
version "0.22.1"
resolved "https://registry.yarnpkg.com/@vercel/nft/-/nft-0.22.1.tgz#0d91d2a21e3a7f0b23ce1550da9870eac4942828"
integrity sha512-lYYZIoxRurqDOSoVIdBicGnpUIpfyaS5qVjdPq+EfI285WqtZK3NK/dyCkiyBul+X2U2OEhRyeMdXPCHGJbohw==
dependencies:
"@mapbox/node-pre-gyp" "^1.0.5"
acorn "^8.6.0"
@@ -5490,13 +5473,13 @@ ecc-jsbn@~0.1.1:
jsbn "~0.1.0"
safer-buffer "^2.1.0"
edge-runtime@1.1.0-beta.23:
version "1.1.0-beta.23"
resolved "https://registry.yarnpkg.com/edge-runtime/-/edge-runtime-1.1.0-beta.23.tgz#fd4d93f021c622e9b188399fa83e6bd5e445cb5e"
integrity sha512-A7dO/Y+4UJnaxFcdz6pepL+0GcvvViWvf201oFQXepgdSxPDKiqxaayCag0eiirQ6OfF+cSTmPD3xrfEoAIjiQ==
edge-runtime@1.1.0-beta.32:
version "1.1.0-beta.32"
resolved "https://registry.yarnpkg.com/edge-runtime/-/edge-runtime-1.1.0-beta.32.tgz#e43fd53c57fdba3c567b3fef50743cba00ff5e49"
integrity sha512-fbqqUF3OKynqtWgExhjyxXX2SwbkWuwmjUYhml3Sv8Y/vkrTxyTKrxS0MoxUy5sGPB3BBEtpopn36cQgwlOpAg==
dependencies:
"@edge-runtime/format" "^1.1.0-beta.23"
"@edge-runtime/vm" "^1.1.0-beta.23"
"@edge-runtime/format" "^1.1.0-beta.32"
"@edge-runtime/vm" "^1.1.0-beta.32"
exit-hook "2.2.1"
http-status "1.5.2"
mri "1.2.0"