Compare commits

..

11 Commits

Author SHA1 Message Date
JJ Kasper
370b0dbed2 Publish Canary
- vercel@23.0.1-canary.2
 - @vercel/node@1.11.1-canary.0
2021-06-06 15:24:50 -05:00
JJ Kasper
cc7a82fb0a [node] Update nft to 0.13.1 (#6333) 2021-06-06 16:22:56 -04:00
Markoz Peña
6eea26c39e [cli] Convert vc alias to TS (#6325)
* refactor: Remove unncessary file

* feat(cli/alias): Migration to TS

* refactor(cli/alias): Add a line break

* refactor(cli/alias): Remove unnecesary code

* feat(cli): Add `Paginationoptions` type to `pagination`

* feat(cli/commands): Rewrite th `alias ls` command to TS

* refactor: Remove unncessary code

* feat: Create helper function for `getSafeAlias`

* refactor: Remove unnecessary code

* feat: Remove parameter generic, "null" for the fetch

* feat(cli/alias): Rewritten in full TS

* feat: Add Partial to opts

* refactor: Remove comment @ts-ignore

* feat: Add Partial to opts

* feat: Only should be return `alias.uid`

* refactor: Remove `Alias` type from of the parameter `id`

* refactor: Remove destructuring from alias object

* refactor: Remove unnecessary code

* feat: Rename `created` property to `createdAt` of number type

* refactor: Move getSafeAlias function in the same file

* refactor: Simplifying code

* refactor: Intentation did not affect diff on git

* Add null back to type

Co-authored-by: Steven <steven@ceriously.com>
2021-06-04 16:43:39 -04:00
Nathan Rajlich
b8bfae7840 [cli] Fix vc logout command when using Team scope (#6322)
Fixes logout command not working when switched to a Team scope:

```
$ vc login
$ vc switch $some_team
$ vc logout
Failed during logout
```
2021-06-04 19:48:03 +00:00
Nathan Rajlich
dc6a0a1cbb [cli] Upgrade token scopes in vc switch command (#6323)
Pass the `Authorization` request header to the verify endpoint so that the current auth token will be upgraded with the new scope.

[ch22273]
2021-06-04 18:33:49 +00:00
Steven
a6807c9d21 Publish Canary
- vercel@23.0.1-canary.1
 - @vercel/python@2.0.4-canary.0
2021-06-01 14:35:09 -04:00
Steven
c628090d08 [cli] Fix vc projects rm race condition (#6306)
The call to `GET /projects/info` is used to check existence but it can cause a race condition if the project was removed before the `DELETE /v2/projects` is called.

Instead, we rely on the response from `DELETE /v2/projects` to determine if the project exists or not.

This will also allow us to remove a legacy API endpoint in the future (see related API PR)
2021-06-01 18:31:20 +00:00
Hydrophobefireman
4e0b291ed1 [python] Remove imports from werkzeug._compat (#6283) 2021-06-01 09:15:06 -04:00
JJ Kasper
ee0bc9b0c8 Publish Canary
- @vercel/build-utils@2.11.1-canary.0
 - vercel@23.0.1-canary.0
 - @vercel/client@10.1.1-canary.0
 - @vercel/frameworks@0.4.1-canary.0
 - @vercel/routing-utils@1.11.2-canary.0
2021-05-26 13:44:39 -05:00
JJ Kasper
e516c1f49f Ensure beforeFiles rewrites come after redirects when continuing (#6289) 2021-05-26 12:50:51 -05:00
JJ Kasper
01f53f36fc [routing-utils] Ensure header key value casing is normalized (#6284)
This ensures we normalize header `key` values in `has` items to be lower-case as the proxy currently only matches against the lower-case variant. Updated superstatic tests to ensure the header key is normalized correctly. 

### Related Issues

[related thread](https://vercel.slack.com/archives/C01N3RWTE5V/p1621937306006400)

### 📋 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

- [ ] This PR has a concise title and thorough description useful to a reviewer
- [ ] Issue from task tracker has a link to this PR
2021-05-25 22:46:28 +00:00
30 changed files with 189 additions and 121 deletions

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/build-utils",
"version": "2.11.0",
"version": "2.11.1-canary.0",
"license": "MIT",
"main": "./dist/index.js",
"types": "./dist/index.d.js",
@@ -29,7 +29,7 @@
"@types/node-fetch": "^2.1.6",
"@types/semver": "6.0.0",
"@types/yazl": "^2.4.1",
"@vercel/frameworks": "0.4.0",
"@vercel/frameworks": "0.4.1-canary.0",
"@vercel/ncc": "0.24.0",
"aggregate-error": "3.0.1",
"async-retry": "1.2.3",

View File

@@ -1,6 +1,6 @@
{
"name": "vercel",
"version": "23.0.0",
"version": "23.0.1-canary.2",
"preferGlobal": true,
"license": "Apache-2.0",
"description": "The command-line interface for Vercel",
@@ -61,10 +61,10 @@
"node": ">= 12"
},
"dependencies": {
"@vercel/build-utils": "2.11.0",
"@vercel/build-utils": "2.11.1-canary.0",
"@vercel/go": "1.2.2",
"@vercel/node": "1.11.0",
"@vercel/python": "2.0.3",
"@vercel/node": "1.11.1-canary.0",
"@vercel/python": "2.0.4-canary.0",
"@vercel/ruby": "1.2.6",
"update-notifier": "4.1.0"
},
@@ -100,7 +100,7 @@
"@types/universal-analytics": "0.4.2",
"@types/which": "1.3.2",
"@types/write-json-file": "2.2.1",
"@vercel/frameworks": "0.4.0",
"@vercel/frameworks": "0.4.1-canary.0",
"@vercel/ncc": "0.24.0",
"@zeit/fun": "0.11.2",
"@zeit/source-map-support": "0.6.2",

View File

@@ -2,10 +2,11 @@ import chalk from 'chalk';
import { handleError } from '../../util/error';
import Client from '../../util/client';
import getArgs from '../../util/get-args';
import getSubcommand from '../../util/get-subcommand';
import logo from '../../util/output/logo';
import { getPkgName } from '../../util/pkg-name.ts';
import { getPkgName } from '../../util/pkg-name';
import ls from './ls';
import rm from './rm';
@@ -36,6 +37,7 @@ const help = () => {
)} Login token
-S, --scope Set a custom scope
-N, --next Show next page of results
${chalk.dim('Examples:')}
${chalk.gray('')} Add a new alias to ${chalk.underline('my-api.vercel.app')}
@@ -64,13 +66,13 @@ const help = () => {
};
const COMMAND_CONFIG = {
default: 'set',
default: ['set'],
ls: ['ls', 'list'],
rm: ['rm', 'remove'],
set: ['set'],
};
export default async function main(client) {
export default async function main(client: Client) {
let argv;
try {

View File

@@ -1,21 +1,26 @@
import chalk from 'chalk';
import ms from 'ms';
import table from 'text-table';
import Now from '../../util';
import Client from '../../util/client';
import getAliases from '../../util/alias/get-aliases';
import getScope from '../../util/get-scope.ts';
import stamp from '../../util/output/stamp.ts';
import strlen from '../../util/strlen.ts';
import getScope from '../../util/get-scope';
import stamp from '../../util/output/stamp';
import strlen from '../../util/strlen';
import getCommandFlags from '../../util/get-command-flags';
import { getCommandName } from '../../util/pkg-name.ts';
import { getCommandName } from '../../util/pkg-name';
export default async function ls(client, opts, args) {
const {
apiUrl,
authConfig: { token },
output,
config: { currentTeam },
} = client;
import { Alias } from '../../types';
interface Options {
'--next'?: number;
}
export default async function ls(
client: Client,
opts: Options,
args: string[]
) {
const { output } = client;
const { '--next': nextTimestamp } = opts;
let contextName = null;
@@ -36,13 +41,6 @@ export default async function ls(client, opts, args) {
return 1;
}
const now = new Now({
apiUrl,
token,
debug: client.output.isDebugEnabled(),
currentTeam,
output,
});
const lsStamp = stamp();
if (args.length > 0) {
@@ -56,8 +54,9 @@ export default async function ls(client, opts, args) {
output.spinner(`Fetching aliases under ${chalk.bold(contextName)}`);
// Get the list of alias
const { aliases, pagination } = await getAliases(
now,
client,
undefined,
nextTimestamp
);
@@ -73,21 +72,20 @@ export default async function ls(client, opts, args) {
);
}
now.close();
return 0;
}
function printAliasTable(aliases) {
function printAliasTable(aliases: Alias[]) {
return `${table(
[
['source', 'url', 'age'].map(h => chalk.gray(h)),
['source', 'url', 'age'].map(header => chalk.gray(header)),
...aliases.map(a => [
// for legacy reasons, we might have situations
// where the deployment was deleted and the alias
// not collected appropriately, and we need to handle it
a.deployment && a.deployment.url ? a.deployment.url : chalk.gray(''),
a.alias,
ms(Date.now() - new Date(a.createdAt)),
ms(Date.now() - a.createdAt),
]),
],
{

View File

@@ -1,23 +1,29 @@
import chalk from 'chalk';
import ms from 'ms';
import table from 'text-table';
import Now from '../../util';
import getScope from '../../util/get-scope.ts';
import Client from '../../util/client';
import getScope from '../../util/get-scope';
import removeAliasById from '../../util/alias/remove-alias-by-id';
import stamp from '../../util/output/stamp.ts';
import strlen from '../../util/strlen.ts';
import stamp from '../../util/output/stamp';
import strlen from '../../util/strlen';
import confirm from '../../util/input/confirm';
import { isValidName } from '../../util/is-valid-name';
import findAliasByAliasOrId from '../../util/alias/find-alias-by-alias-or-id';
import { getCommandName } from '../../util/pkg-name.ts';
export default async function rm(client, opts, args) {
const {
apiUrl,
authConfig: { token },
output,
config: { currentTeam },
} = client;
import { Alias } from '../../types';
import { Output } from '../../util/output';
import { isValidName } from '../../util/is-valid-name';
import { getCommandName } from '../../util/pkg-name';
type Options = {
'--yes': boolean;
};
export default async function rm(
client: Client,
opts: Partial<Options>,
args: string[]
) {
const { output } = client;
let contextName = null;
@@ -32,13 +38,6 @@ export default async function rm(client, opts, args) {
throw err;
}
const now = new Now({
apiUrl,
token,
debug: client.output.isDebugEnabled(),
currentTeam,
output,
});
const [aliasOrId] = args;
if (args.length !== 1) {
@@ -61,7 +60,8 @@ export default async function rm(client, opts, args) {
return 1;
}
const alias = await findAliasByAliasOrId(output, now, aliasOrId);
const alias = await findAliasByAliasOrId(output, client, aliasOrId);
if (!alias) {
output.error(
`Alias not found by "${aliasOrId}" under ${chalk.bold(contextName)}`
@@ -76,7 +76,7 @@ export default async function rm(client, opts, args) {
return 0;
}
await removeAliasById(now, alias.uid);
await removeAliasById(client, alias.uid);
console.log(
`${chalk.cyan('> Success!')} Alias ${chalk.bold(
alias.alias
@@ -85,7 +85,7 @@ export default async function rm(client, opts, args) {
return 0;
}
async function confirmAliasRemove(output, alias) {
async function confirmAliasRemove(output: Output, alias: Alias) {
const srcUrl = alias.deployment
? chalk.underline(alias.deployment.url)
: null;
@@ -94,7 +94,7 @@ async function confirmAliasRemove(output, alias) {
[
...(srcUrl ? [srcUrl] : []),
chalk.underline(alias.alias),
chalk.gray(`${ms(new Date() - new Date(alias.created))} ago`),
chalk.gray(`${ms(Date.now() - alias.createdAt)} ago`),
],
],
{

View File

@@ -28,7 +28,7 @@ type Options = {
export default async function set(
client: Client,
opts: Options,
opts: Partial<Options>,
args: string[]
) {
const { output, localConfig } = client;

View File

@@ -12,7 +12,6 @@ import { getCommandName, getPkgName } from '../util/pkg-name';
import getGlobalPathConfig from '../util/config/global-path';
import { writeToAuthConfigFile, writeToConfigFile } from '../util/config/files';
import Client from '../util/client';
import { LoginParams } from '../util/login/types';
const help = () => {
console.log(`
@@ -46,7 +45,7 @@ const help = () => {
export default async function login(client: Client): Promise<number> {
let argv;
const { apiUrl, output } = client;
const { output } = client;
try {
argv = getArgs(client.argv.slice(2));
@@ -68,18 +67,17 @@ export default async function login(client: Client): Promise<number> {
const input = argv._[1];
let result: number | string = 1;
const params: LoginParams = { output, apiUrl };
if (input) {
// Email or Team slug was provided via command line
if (validateEmail(input)) {
result = await doEmailLogin(params, input);
result = await doEmailLogin(client, input);
} else {
result = await doSsoLogin(params, input);
result = await doSsoLogin(client, input);
}
} else {
// Interactive mode
result = await prompt(params);
result = await prompt(client);
}
// The login function failed, so it returned an exit code

View File

@@ -1,6 +1,5 @@
import chalk from 'chalk';
import logo from '../util/output/logo';
// @ts-ignore
import { handleError } from '../util/error';
import { writeToConfigFile, writeToAuthConfigFile } from '../util/config/files';
import getArgs from '../util/get-args';
@@ -62,6 +61,7 @@ export default async function main(client: Client): Promise<number> {
try {
await client.fetch(`/v3/user/tokens/current`, {
method: 'DELETE',
useCurrentTeam: false,
});
} catch (err) {
if (err.status === 403) {

View File

@@ -187,25 +187,22 @@ async function run({ client, contextName }) {
const name = args[0];
// Check the existence of the project
try {
await client.fetch(`/projects/info/${e(name)}`);
} catch (err) {
if (err.status === 404) {
console.error(error('No such project exists'));
return exit(1);
}
}
const yes = await readConfirmation(name);
if (!yes) {
console.error(error('User abort'));
return exit(0);
}
await client.fetch(`/v2/projects/${name}`, {
method: 'DELETE',
});
try {
await client.fetch(`/v2/projects/${e(name)}`, {
method: 'DELETE',
});
} catch (err) {
if (err.status === 404) {
console.error(error('No such project exists'));
return exit(1);
}
}
const elapsed = ms(new Date() - start);
console.log(
`${chalk.cyan('> Success!')} Project ${chalk.bold(

View File

@@ -16,7 +16,7 @@ export interface JSONObject {
}
export interface AuthConfig {
token: string;
token?: string;
skipWrite?: boolean;
}
@@ -145,7 +145,7 @@ export type Deployment = {
export type Alias = {
uid: string;
alias: string;
created: string;
createdAt: number;
deployment: {
id: string;
url: string;

View File

@@ -1,5 +1,6 @@
import { Output } from '../output';
import { Alias } from '../../types';
import Client from '../client';
export default async function findAliasByAliasOrId(
@@ -11,7 +12,6 @@ export default async function findAliasByAliasOrId(
`/now/aliases/${encodeURIComponent(getSafeAlias(aliasOrId))}`
);
}
function getSafeAlias(alias: string) {
return alias
.replace(/^https:\/\//i, '')

View File

@@ -1,8 +1,9 @@
import { Alias } from '../../types';
import { Alias, PaginationOptions } from '../../types';
import Client from '../client';
type Response = {
aliases: Alias[];
pagination: PaginationOptions;
};
export default async function getAliases(

View File

@@ -2,6 +2,6 @@ import Client from '../client';
export default async function removeAliasById(client: Client, id: string) {
return client.fetch(`/now/aliases/${id}`, {
method: 'DELETE'
method: 'DELETE',
});
}

View File

@@ -23,14 +23,14 @@ export default async function doOauthLogin(
const server = http.createServer();
const address = await listen(server, 0, '127.0.0.1');
const { port } = new URL(address);
url.searchParams.append('mode', 'login');
url.searchParams.append('next', `http://localhost:${port}`);
url.searchParams.set('mode', 'login');
url.searchParams.set('next', `http://localhost:${port}`);
// Append token name param
const hyphens = new RegExp('-', 'g');
const host = hostname().replace(hyphens, ' ').replace('.local', '');
const tokenName = `${getTitleName()} CLI on ${host} via ${provider}`;
url.searchParams.append('tokenName', tokenName);
url.searchParams.set('tokenName', tokenName);
try {
const [query] = await Promise.all([

View File

@@ -4,6 +4,6 @@ import doOauthLogin from './oauth';
export default function doSsoLogin(params: LoginParams, teamIdOrSlug: string) {
const url = new URL('/auth/sso', params.apiUrl);
url.searchParams.append('teamId', teamIdOrSlug);
url.searchParams.set('teamId', teamIdOrSlug);
return doOauthLogin(params, url, 'SAML Single Sign-On');
}

View File

@@ -1,6 +1,8 @@
import { AuthConfig } from '../../types';
import { Output } from '../output';
export interface LoginParams {
authConfig: AuthConfig;
apiUrl: string;
output: Output;
ssoUserId?: string;

View File

@@ -1,24 +1,26 @@
import { URL } from 'url';
import fetch from 'node-fetch';
import fetch, { Headers } from 'node-fetch';
import ua from '../ua';
import { LoginParams } from './types';
export default async function verify(
email: string,
verificationToken: string,
{ apiUrl, ssoUserId }: LoginParams
{ authConfig, apiUrl, ssoUserId }: LoginParams
): Promise<string> {
const url = new URL('/registration/verify', apiUrl);
url.searchParams.append('email', email);
url.searchParams.append('token', verificationToken);
url.searchParams.set('email', email);
url.searchParams.set('token', verificationToken);
if (ssoUserId) {
url.searchParams.append('ssoUserId', ssoUserId);
url.searchParams.set('ssoUserId', ssoUserId);
}
const res = await fetch(url.href, {
headers: { 'User-Agent': ua },
});
const headers = new Headers({ 'User-Agent': ua });
if (authConfig.token) {
headers.set('Authorization', `Bearer ${authConfig.token}`);
}
const res = await fetch(url.href, { headers });
const body = await res.json();
if (!res.ok) {

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/client",
"version": "10.1.0",
"version": "10.1.1-canary.0",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
"homepage": "https://vercel.com",
@@ -40,7 +40,7 @@
]
},
"dependencies": {
"@vercel/build-utils": "2.11.0",
"@vercel/build-utils": "2.11.1-canary.0",
"@zeit/fetch": "5.2.0",
"async-retry": "1.2.3",
"async-sema": "3.0.0",

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/frameworks",
"version": "0.4.0",
"version": "0.4.1-canary.0",
"main": "./dist/frameworks.js",
"types": "./dist/frameworks.d.ts",
"files": [
@@ -20,7 +20,7 @@
"@types/js-yaml": "3.12.1",
"@types/node": "12.0.4",
"@types/node-fetch": "2.5.8",
"@vercel/routing-utils": "1.11.1",
"@vercel/routing-utils": "1.11.2-canary.0",
"ajv": "6.12.2",
"jest": "24.9.0",
"ts-jest": "24.1.0",

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/node",
"version": "1.11.0",
"version": "1.11.1-canary.0",
"license": "MIT",
"main": "./dist/index",
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/node-js",
@@ -33,7 +33,7 @@
"@types/etag": "1.8.0",
"@types/test-listen": "1.1.0",
"@vercel/ncc": "0.24.0",
"@vercel/nft": "0.12.2",
"@vercel/nft": "0.13.1",
"content-type": "1.0.4",
"cookie": "0.4.0",
"etag": "1.8.1",

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/python",
"version": "2.0.3",
"version": "2.0.4-canary.0",
"main": "./dist/index.js",
"license": "MIT",
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/python",

View File

@@ -82,14 +82,27 @@ elif 'app' in __vc_variables:
not inspect.iscoroutinefunction(__vc_module.app.__call__)
):
print('using Web Server Gateway Interface (WSGI)')
from io import BytesIO
from urllib.parse import urlparse
from werkzeug._compat import BytesIO
from werkzeug._compat import string_types
from werkzeug._compat import to_bytes
from werkzeug._compat import wsgi_encoding_dance
from werkzeug.datastructures import Headers
from werkzeug.wrappers import Response
string_types = (str,)
def to_bytes(x, charset=sys.getdefaultencoding(), errors="strict"):
if x is None:
return None
if isinstance(x, (bytes, bytearray, memoryview)):
return bytes(x)
if isinstance(x, str):
return x.encode(charset, errors)
raise TypeError("Expected bytes")
def wsgi_encoding_dance(s, charset="utf-8", errors="replace"):
if isinstance(s, str):
s = s.encode(charset)
return s.decode("latin1", errors)
def vc_handler(event, context):
payload = json.loads(event['body'])

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/routing-utils",
"version": "1.11.1",
"version": "1.11.2-canary.0",
"description": "Vercel routing utilities",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",

View File

@@ -39,7 +39,7 @@ function getCheckAndContinue(
);
} else if (route.check) {
checks.push(route);
} else if (route.continue) {
} else if (route.continue && !route.override) {
continues.push(route);
} else {
others.push(route);

View File

@@ -104,6 +104,9 @@ export const routesSchema = {
continue: {
type: 'boolean',
},
override: {
type: 'boolean',
},
check: {
type: 'boolean',
},

View File

@@ -187,6 +187,10 @@ function collectHasSegments(has?: HasField) {
const hasSegments = new Set<string>();
for (const hasItem of has || []) {
if ('key' in hasItem && hasItem.type === 'header') {
hasItem.key = hasItem.key.toLowerCase();
}
if (!hasItem.value && 'key' in hasItem) {
hasSegments.add(hasItem.key);
}

View File

@@ -27,6 +27,7 @@ export type Source = {
headers?: { [name: string]: string };
methods?: string[];
continue?: boolean;
override?: boolean;
check?: boolean;
important?: boolean;
status?: number;

View File

@@ -419,3 +419,50 @@ test('mergeRoutes ensure `handle: error` comes last', () => {
];
deepStrictEqual(actual, expected);
});
test('mergeRoutes ensure beforeFiles comes after redirects', () => {
const userRoutes = [];
const builds = [
{
use: '@vercel/next',
entrypoint: 'package.json',
routes: [
{
src: '^/home$',
status: 301,
headers: {
Location: '/',
},
},
{
src: '^/hello$',
dest: '/somewhere',
continue: true,
override: true,
},
{
handle: 'filesystem',
},
{
src: '^/404$',
dest: '/404',
status: 404,
check: true,
},
],
},
];
const actual = mergeRoutes({ userRoutes, builds });
const expected = [
{ src: '^/home$', status: 301, headers: { Location: '/' } },
{
src: '^/hello$',
dest: '/somewhere',
continue: true,
override: true,
},
{ handle: 'filesystem' },
{ src: '^/404$', dest: '/404', status: 404, check: true },
];
deepStrictEqual(actual, expected);
});

View File

@@ -247,7 +247,7 @@ test('convertRedirects', () => {
},
{
type: 'header',
key: 'x-pathname',
key: 'X-Pathname',
value: '(?<another>hello|world)',
},
],
@@ -549,7 +549,7 @@ test('convertRewrites', () => {
},
{
type: 'header',
key: 'x-pathname',
key: 'X-Pathname',
value: '(?<another>hello|world)',
},
],
@@ -893,7 +893,7 @@ test('convertHeaders', () => {
},
{
type: 'header',
key: 'x-pathname',
key: 'X-Pathname',
value: '(?<another>hello|world)',
},
],

View File

@@ -2116,13 +2116,13 @@
resolved "https://registry.yarnpkg.com/@vercel/ncc/-/ncc-0.24.0.tgz#a2e8783a185caa99b5d8961a57dfc9665de16296"
integrity sha512-crqItMcIwCkvdXY/V3/TzrHJQx6nbIaRqE1cOopJhgGX6izvNov40SmD//nS5flfEvdK54YGjwVVq+zG6crjOg==
"@vercel/nft@0.12.2":
version "0.12.2"
resolved "https://registry.yarnpkg.com/@vercel/nft/-/nft-0.12.2.tgz#67ea9f231d24639b3783e3e69bef173659972d3b"
integrity sha512-H8n44GboVnJaVVX4+WfuOTAaNLDnUIYH4KpMZcXll7KMNIcg0JTd0IFRsIBe/uvuXisqm6nEANp8Tr3/1dlRQw==
"@vercel/nft@0.13.1":
version "0.13.1"
resolved "https://registry.yarnpkg.com/@vercel/nft/-/nft-0.13.1.tgz#98df07e04620069ba63fff92af490c5842a2f31f"
integrity sha512-7pBTfSkwhhcPAeGVsFml5YX7LCZgtocP+zTAknnRK2u/RsV3GGqOD5yw7CtbgTpfjY8NfXWzwoxF1zOUEVsbww==
dependencies:
"@mapbox/node-pre-gyp" "^1.0.5"
acorn "^8.1.0"
acorn "^8.3.0"
acorn-class-fields "^1.0.0"
acorn-static-class-features "^1.0.0"
bindings "^1.4.0"
@@ -2283,10 +2283,10 @@ acorn@^7.1.1:
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.2.0.tgz#17ea7e40d7c8640ff54a694c889c26f31704effe"
integrity sha512-apwXVmYVpQ34m/i71vrApRrRKCWQnZZF1+npOD0WV5xZFfwWOmKGQ2RWlfdy9vWITsenisM8M0Qeq8agcFHNiQ==
acorn@^8.1.0:
version "8.1.1"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.1.1.tgz#fb0026885b9ac9f48bac1e185e4af472971149ff"
integrity sha512-xYiIVjNuqtKXMxlRMDc6mZUhXehod4a3gbZ1qRlM7icK4EbxUFNLhWoPblCvFtB2Y9CIqHP3CF/rdxLItaQv8g==
acorn@^8.3.0:
version "8.3.0"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.3.0.tgz#1193f9b96c4e8232f00b11a9edff81b2c8b98b88"
integrity sha512-tqPKHZ5CaBJw0Xmy0ZZvLs1qTV+BNFSyvn77ASXkpBNfIRk8ev26fKrD9iLGwGA9zedPao52GSHzq8lyZG0NUw==
agent-base@4, agent-base@^4.1.0, agent-base@^4.3.0:
version "4.3.0"